authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-12-23 17:04:26-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-12-23 17:04:26-05:00
logc00216701c64269a2395e84f3ccff99d6fb89ffc
tree9fa071b9e96f9eadc5069b71634b11fc13b00839
parentc21884e1d64e4193e03be4f3064917a26b34b142
parent45081c1e9cc28757cb563c77553631f7a92b29d8

Merge remote-tracking branch 'origin/master' into llvm8


124 files changed, 6574 insertions(+), 1880 deletions(-)

.builds/freebsd.yml created+22
...@@ -0,0 +1,22 @@
1arch: x86_64
2image: freebsd
3packages:
4 - cmake
5 - ninja
6 - llvm70
7sources:
8 - https://github.com/ziglang/zig.git
9tasks:
10 - build: |
11 cd zig && mkdir build && cd build
12 cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release
13 ninja install
14 - test: |
15 cd zig/build
16 bin/zig test ../test/behavior.zig
17 # TODO enable all tests
18 #bin/zig build --build-file ../build.zig test
19 # TODO integrate with the download page updater and make a
20 # static build available to download for FreeBSD.
21 # This will require setting up a cache of LLVM/Clang built
22 # statically.
CMakeLists.txt+16
...@@ -444,6 +444,7 @@ set(ZIG_STD_FILES...@@ -444,6 +444,7 @@ set(ZIG_STD_FILES
444 "buffer.zig"444 "buffer.zig"
445 "build.zig"445 "build.zig"
446 "c/darwin.zig"446 "c/darwin.zig"
447 "c/freebsd.zig"
447 "c/index.zig"448 "c/index.zig"
448 "c/linux.zig"449 "c/linux.zig"
449 "c/windows.zig"450 "c/windows.zig"
...@@ -490,6 +491,7 @@ set(ZIG_STD_FILES...@@ -490,6 +491,7 @@ set(ZIG_STD_FILES
490 "heap.zig"491 "heap.zig"
491 "index.zig"492 "index.zig"
492 "io.zig"493 "io.zig"
494 "io/seekable_stream.zig"
493 "json.zig"495 "json.zig"
494 "lazy_init.zig"496 "lazy_init.zig"
495 "linked_list.zig"497 "linked_list.zig"
...@@ -582,6 +584,10 @@ set(ZIG_STD_FILES...@@ -582,6 +584,10 @@ set(ZIG_STD_FILES
582 "os/linux/vdso.zig"584 "os/linux/vdso.zig"
583 "os/linux/x86_64.zig"585 "os/linux/x86_64.zig"
584 "os/linux/arm64.zig"586 "os/linux/arm64.zig"
587 "os/freebsd/errno.zig"
588 "os/freebsd/index.zig"
589 "os/freebsd/syscall.zig"
590 "os/freebsd/x86_64.zig"
585 "os/path.zig"591 "os/path.zig"
586 "os/time.zig"592 "os/time.zig"
587 "os/windows/advapi32.zig"593 "os/windows/advapi32.zig"
...@@ -617,6 +623,16 @@ set(ZIG_STD_FILES...@@ -617,6 +623,16 @@ set(ZIG_STD_FILES
617 "special/compiler_rt/fixunstfdi.zig"623 "special/compiler_rt/fixunstfdi.zig"
618 "special/compiler_rt/fixunstfsi.zig"624 "special/compiler_rt/fixunstfsi.zig"
619 "special/compiler_rt/fixunstfti.zig"625 "special/compiler_rt/fixunstfti.zig"
626 "special/compiler_rt/fixint.zig"
627 "special/compiler_rt/fixdfdi.zig"
628 "special/compiler_rt/fixdfsi.zig"
629 "special/compiler_rt/fixdfti.zig"
630 "special/compiler_rt/fixsfdi.zig"
631 "special/compiler_rt/fixsfsi.zig"
632 "special/compiler_rt/fixsfti.zig"
633 "special/compiler_rt/fixtfdi.zig"
634 "special/compiler_rt/fixtfsi.zig"
635 "special/compiler_rt/fixtfti.zig"
620 "special/compiler_rt/floattidf.zig"636 "special/compiler_rt/floattidf.zig"
621 "special/compiler_rt/floattisf.zig"637 "special/compiler_rt/floattisf.zig"
622 "special/compiler_rt/floattitf.zig"638 "special/compiler_rt/floattitf.zig"
README.md+71-30
...@@ -42,33 +42,71 @@ clarity....@@ -42,33 +42,71 @@ clarity.
42 * In addition to creating executables, creating a C library is a primary use42 * In addition to creating executables, creating a C library is a primary use
43 case. You can export an auto-generated .h file.43 case. You can export an auto-generated .h file.
4444
45### Support Table45### Supported Targets
4646
47Freestanding means that you do not directly interact with the OS47#### Tier 1 Support
48or you are writing your own OS.48
4949 * Not only can Zig generate machine code for these targets, but the standard
50Note that if you use libc or other libraries to interact with the OS,50 library cross-platform abstractions have implementations for these targets.
51that counts as "freestanding" for the purposes of this table.51 Thus it is practical to write a pure Zig application with no dependency on
5252 libc.
53| | freestanding | linux | macosx | windows | other |53 * The CI server automatically tests these targets on every commit to master
54|-------------|--------------|---------|---------|---------|---------|54 branch, and updates ziglang.org/download with links to pre-built binaries.
55|i386 | OK | planned | OK | planned | planned |55 * These targets have debug info capabilities and therefore produce stack
56|x86_64 | OK | OK | OK | OK | planned |56 traces on failed assertions.
57|arm | OK | planned | planned | planned | planned |57
58|bpf | OK | planned | N/A | N/A | planned |58#### Tier 2 Support
59|hexagon | OK | planned | N/A | N/A | planned |59
60|mips | OK | planned | N/A | N/A | planned |60 * There may be some standard library implementations, but many abstractions
61|powerpc | OK | planned | N/A | N/A | planned |61 will give an "Unsupported OS" compile error. One can link with libc or other
62|r600 | OK | planned | N/A | N/A | planned |62 libraries to fill in the gaps in the standard library.
63|amdgcn | OK | planned | N/A | N/A | planned |63 * These targets are known to work, but are not automatically tested, so there
64|sparc | OK | planned | N/A | N/A | planned |64 are occasional regressions.
65|s390x | OK | planned | N/A | N/A | planned |65 * Some tests may be disabled for these targets as we work toward Tier 1
66|spir | OK | planned | N/A | N/A | planned |66 support.
67|lanai | OK | planned | N/A | N/A | planned |67
68|wasm32 | planned | N/A | N/A | N/A | N/A |68#### Tier 3 Support
69|wasm64 | planned | N/A | N/A | N/A | N/A |69
70|riscv32 | planned | planned | N/A | N/A | planned |70 * The standard library has little to no knowledge of the existence of this
71|riscv64 | planned | planned | N/A | N/A | planned |71 target.
72 * Because Zig is based on LLVM, it has the capability to build for these
73 targets, and LLVM has the target enabled by default.
74 * These targets are not frequently tested; one will likely need to contribute
75 to Zig in order to build for these targets.
76 * The Zig compiler might need to be updated with a few things such as
77 - what sizes are the C integer types
78 - C ABI calling convention for this target
79 - bootstrap code and default panic handler
80
81#### Tier 4 Support
82
83 * Support for these targets is entirely experimental.
84 * LLVM may have the target as an experimental target, which means that you
85 need to use Zig-provided binaries for the target to be available, or
86 build LLVM from source with special configure flags.
87
88#### Support Table
89
90| | freestanding | linux | macosx | windows | freebsd | other |
91|--------|--------------|--------|--------|---------|---------|--------|
92|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 3 |
93|i386 | Tier 2 | Tier 2 | Tier 2 | Tier 2 | Tier 3 | Tier 3 |
94|arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
95|arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
96|bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
97|hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
98|mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
99|powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
100|r600 | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
101|amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
102|sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
103|s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
104|spir | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
105|lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
106|wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A |
107|wasm64 | Tier 4 | N/A | N/A | N/A | N/A | N/A |
108|riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 |
109|riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 |
72110
73## Community111## Community
74112
...@@ -133,7 +171,8 @@ See https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows...@@ -133,7 +171,8 @@ See https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows
133*Note: Stage 2 compiler is not complete. Beta users of Zig should use the171*Note: Stage 2 compiler is not complete. Beta users of Zig should use the
134Stage 1 compiler for now.*172Stage 1 compiler for now.*
135173
136Dependencies are the same as Stage 1, except now you have a working zig compiler.174Dependencies are the same as Stage 1, except now you can use stage 1 to compile
175Zig code.
137176
138```177```
139bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install178bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install
...@@ -145,11 +184,13 @@ binary....@@ -145,11 +184,13 @@ binary.
145184
146### Stage 3: Rebuild Self-Hosted Zig Using the Self-Hosted Compiler185### Stage 3: Rebuild Self-Hosted Zig Using the Self-Hosted Compiler
147186
148This is the actual compiler binary that we will install to the system.
149
150*Note: Stage 2 compiler is not yet able to build Stage 3. Building Stage 3 is187*Note: Stage 2 compiler is not yet able to build Stage 3. Building Stage 3 is
151not yet supported.*188not yet supported.*
152189
190Once the self-hosted compiler can build itself, this will be the actual
191compiler binary that we will install to the system. Until then, users should
192use stage 1.
193
153#### Debug / Development Build194#### Debug / Development Build
154195
155```196```
build.zig+1-1
...@@ -297,7 +297,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {...@@ -297,7 +297,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
297 );297 );
298298
299 exe.linkSystemLibrary("pthread");299 exe.linkSystemLibrary("pthread");
300 } else if (exe.target.isDarwin()) {300 } else if (exe.target.isDarwin() or exe.target.isFreeBSD()) {
301 if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) {301 if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) {
302 // Compiler is GCC.302 // Compiler is GCC.
303 try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null);303 try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null);
ci/azure/linux_script+3
...@@ -34,6 +34,9 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then...@@ -34,6 +34,9 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then
3434
35 SHASUM=$(sha256sum $ARTIFACTSDIR/$TARBALL | cut '-d ' -f1)35 SHASUM=$(sha256sum $ARTIFACTSDIR/$TARBALL | cut '-d ' -f1)
36 BYTESIZE=$(wc -c < $ARTIFACTSDIR/$TARBALL)36 BYTESIZE=$(wc -c < $ARTIFACTSDIR/$TARBALL)
37 # `set -x` causes these variables to be mangled.
38 # See https://developercommunity.visualstudio.com/content/problem/375679/pipeline-variable-incorrectly-inserts-single-quote.html
39 set +x
37 echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL"40 echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL"
38 echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM"41 echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM"
39 echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE"42 echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE"
ci/azure/macos_script+3
...@@ -98,6 +98,9 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then...@@ -98,6 +98,9 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then
9898
99 SHASUM=$(shasum -a 256 $TARBALL | cut '-d ' -f1)99 SHASUM=$(shasum -a 256 $TARBALL | cut '-d ' -f1)
100 BYTESIZE=$(wc -c < $TARBALL)100 BYTESIZE=$(wc -c < $TARBALL)
101 # `set -x` causes these variables to be mangled.
102 # See https://developercommunity.visualstudio.com/content/problem/375679/pipeline-variable-incorrectly-inserts-single-quote.html
103 set +x
101 echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL"104 echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL"
102 echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM"105 echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM"
103 echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE"106 echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE"
ci/azure/windows_install+1
...@@ -3,6 +3,7 @@...@@ -3,6 +3,7 @@
3set -x3set -x
4set -e4set -e
55
6pacman -Su --needed --noconfirm
6pacman -S --needed --noconfirm wget p7zip python3-pip7pacman -S --needed --noconfirm wget p7zip python3-pip
7pip install s3cmd8pip install s3cmd
8wget -nv "https://ziglang.org/deps/llvm%2bclang-8.0.0-win64-msvc-release.tar.xz"9wget -nv "https://ziglang.org/deps/llvm%2bclang-8.0.0-win64-msvc-release.tar.xz"
ci/azure/windows_upload+3
...@@ -25,6 +25,9 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then...@@ -25,6 +25,9 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then
2525
26 SHASUM=$(sha256sum $TARBALL | cut '-d ' -f1)26 SHASUM=$(sha256sum $TARBALL | cut '-d ' -f1)
27 BYTESIZE=$(wc -c < $TARBALL)27 BYTESIZE=$(wc -c < $TARBALL)
28 # `set -x` causes these variables to be mangled.
29 # See https://developercommunity.visualstudio.com/content/problem/375679/pipeline-variable-incorrectly-inserts-single-quote.html
30 set +x
28 echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL"31 echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL"
29 echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM"32 echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM"
30 echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE"33 echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE"
cmake/Findclang.cmake+2
...@@ -30,6 +30,7 @@ else()...@@ -30,6 +30,7 @@ else()
30 /usr/lib/llvm/8/include30 /usr/lib/llvm/8/include
31 /usr/lib/llvm-8/include31 /usr/lib/llvm-8/include
32 /usr/lib/llvm-8.0/include32 /usr/lib/llvm-8.0/include
33 /usr/local/llvm80/include
33 /mingw64/include)34 /mingw64/include)
3435
35 macro(FIND_AND_ADD_CLANG_LIB _libname_)36 macro(FIND_AND_ADD_CLANG_LIB _libname_)
...@@ -40,6 +41,7 @@ else()...@@ -40,6 +41,7 @@ else()
40 /usr/lib/llvm/8/lib41 /usr/lib/llvm/8/lib
41 /usr/lib/llvm-8/lib42 /usr/lib/llvm-8/lib
42 /usr/lib/llvm-8.0/lib43 /usr/lib/llvm-8.0/lib
44 /usr/local/llvm80/lib
43 /mingw64/lib45 /mingw64/lib
44 /c/msys64/mingw64/lib46 /c/msys64/mingw64/lib
45 c:\\msys64\\mingw64\\lib)47 c:\\msys64\\mingw64\\lib)
cmake/Findlld.cmake+7-1
...@@ -9,9 +9,14 @@...@@ -9,9 +9,14 @@
9find_path(LLD_INCLUDE_DIRS NAMES lld/Common/Driver.h9find_path(LLD_INCLUDE_DIRS NAMES lld/Common/Driver.h
10 PATHS10 PATHS
11 /usr/lib/llvm-8.0/include11 /usr/lib/llvm-8.0/include
12 /usr/local/llvm80/include
12 /mingw64/include)13 /mingw64/include)
1314
14find_library(LLD_LIBRARY NAMES lld-8.0 lld PATHS /usr/lib/llvm-8.0/lib)15find_library(LLD_LIBRARY NAMES lld-8.0 lld80 lld
16 PATHS
17 /usr/lib/llvm-8.0/lib
18 /usr/local/llvm80/lib
19)
15if(EXISTS ${LLD_LIBRARY})20if(EXISTS ${LLD_LIBRARY})
16 set(LLD_LIBRARIES ${LLD_LIBRARY})21 set(LLD_LIBRARIES ${LLD_LIBRARY})
17else()22else()
...@@ -20,6 +25,7 @@ else()...@@ -20,6 +25,7 @@ else()
20 find_library(LLD_${_prettylibname_}_LIB NAMES ${_libname_}25 find_library(LLD_${_prettylibname_}_LIB NAMES ${_libname_}
21 PATHS26 PATHS
22 /usr/lib/llvm-8.0/lib27 /usr/lib/llvm-8.0/lib
28 /usr/local/llvm80/lib
23 /mingw64/lib29 /mingw64/lib
24 /c/msys64/mingw64/lib30 /c/msys64/mingw64/lib
25 c:/msys64/mingw64/lib)31 c:/msys64/mingw64/lib)
cmake/Findllvm.cmake+1-1
...@@ -8,7 +8,7 @@...@@ -8,7 +8,7 @@
8# LLVM_LIBDIRS8# LLVM_LIBDIRS
99
10find_program(LLVM_CONFIG_EXE10find_program(LLVM_CONFIG_EXE
11 NAMES llvm-config-8 llvm-config-8.0 llvm-config11 NAMES llvm-config-8 llvm-config-8.0 llvm-config80 llvm-config
12 PATHS12 PATHS
13 "/mingw64/bin"13 "/mingw64/bin"
14 "/c/msys64/mingw64/bin"14 "/c/msys64/mingw64/bin"
deps/lld/ELF/OutputSections.cpp+1-1
...@@ -95,7 +95,7 @@ void OutputSection::addSection(InputSection *IS) {...@@ -95,7 +95,7 @@ void OutputSection::addSection(InputSection *IS) {
95 Flags = IS->Flags;95 Flags = IS->Flags;
96 } else {96 } else {
97 // Otherwise, check if new type or flags are compatible with existing ones.97 // Otherwise, check if new type or flags are compatible with existing ones.
98 unsigned Mask = SHF_ALLOC | SHF_TLS | SHF_LINK_ORDER;98 unsigned Mask = SHF_TLS | SHF_LINK_ORDER;
99 if ((Flags & Mask) != (IS->Flags & Mask))99 if ((Flags & Mask) != (IS->Flags & Mask))
100 error("incompatible section flags for " + Name + "\n>>> " + toString(IS) +100 error("incompatible section flags for " + Name + "\n>>> " + toString(IS) +
101 ": 0x" + utohexstr(IS->Flags) + "\n>>> output section " + Name +101 ": 0x" + utohexstr(IS->Flags) + "\n>>> output section " + Name +
doc/langref.html.in+166-101
...@@ -8,7 +8,13 @@...@@ -8,7 +8,13 @@
8 body{8 body{
9 background-color:#111;9 background-color:#111;
10 color: #bbb;10 color: #bbb;
11 font-family: sans-serif;11 font-family: system-ui,
12 /* Fallbacks for browsers that don't support system-ui */
13 /* https://caniuse.com/#search=system-ui */
14 -apple-system, /* iOS and macOS */
15 Roboto, /* Android */
16 "Segoe UI", /* Windows */
17 sans-serif;
12 }18 }
13 a {19 a {
14 color: #88f;20 color: #88f;
...@@ -159,7 +165,7 @@ const std = @import("std");...@@ -159,7 +165,7 @@ const std = @import("std");
159165
160pub fn main() !void {166pub fn main() !void {
161 // If this program is run without stdout attached, exit with an error.167 // If this program is run without stdout attached, exit with an error.
162 var stdout_file = try std.io.getStdOut();168 const stdout_file = try std.io.getStdOut();
163 // If this program encounters pipe failure when printing to stdout, exit169 // If this program encounters pipe failure when printing to stdout, exit
164 // with an error.170 // with an error.
165 try stdout_file.write("Hello, world!\n");171 try stdout_file.write("Hello, world!\n");
...@@ -3273,13 +3279,13 @@ const err = (error {FileNotFound}).FileNotFound;...@@ -3273,13 +3279,13 @@ const err = (error {FileNotFound}).FileNotFound;
3273 This becomes useful when using {#link|Inferred Error Sets#}.3279 This becomes useful when using {#link|Inferred Error Sets#}.
3274 </p>3280 </p>
3275 {#header_open|The Global Error Set#}3281 {#header_open|The Global Error Set#}
3276 <p>{#syntax#}error{#endsyntax#} refers to the global error set.3282 <p>{#syntax#}anyerror{#endsyntax#} refers to the global error set.
3277 This is the error set that contains all errors in the entire compilation unit.3283 This is the error set that contains all errors in the entire compilation unit.
3278 It is a superset of all other error sets and a subset of none of them.3284 It is a superset of all other error sets and a subset of none of them.
3279 </p>3285 </p>
3280 <p>3286 <p>
3281 You can implicitly cast any error set to the global one, and you can explicitly3287 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-level3288 cast an error of the global error set to a non-global one. This inserts a language-level
3283 assert to make sure the error value is in fact in the destination error set.3289 assert to make sure the error value is in fact in the destination error set.
3284 </p>3290 </p>
3285 <p>3291 <p>
...@@ -4264,13 +4270,21 @@ fn foo() i32 {...@@ -4264,13 +4270,21 @@ fn foo() i32 {
4264 return 1234;4270 return 1234;
4265}4271}
4266 {#code_end#}4272 {#code_end#}
4267 <p>However, if the expression has type {#syntax#}void{#endsyntax#}:</p>4273 <p>However, if the expression has type {#syntax#}void{#endsyntax#}, there will be no error. Function return values can also be explicitly ignored by assigning them to {#syntax#}_{#endsyntax#}. </p>
4268 {#code_begin|test#}4274 {#code_begin|test#}
4269test "ignoring expression value" {4275test "void is ignored" {
4270 foo();4276 returnsVoid();
4277}
4278
4279test "explicitly ignoring expression value" {
4280 _ = foo();
4271}4281}
42724282
4273fn foo() void {}4283fn returnsVoid() void {}
4284
4285fn foo() i32 {
4286 return 1234;
4287}
4274 {#code_end#}4288 {#code_end#}
4275 {#header_close#}4289 {#header_close#}
42764290
...@@ -5155,6 +5169,34 @@ fn seq(c: u8) void {...@@ -5155,6 +5169,34 @@ fn seq(c: u8) void {
5155 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.5169 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
5156 </p>5170 </p>
5157 {#header_close#}5171 {#header_close#}
5172 {#header_open|@alignCast#}
5173 <pre>{#syntax#}@alignCast(comptime alignment: u29, ptr: var) var{#endsyntax#}</pre>
5174 <p>
5175 {#syntax#}ptr{#endsyntax#} can be {#syntax#}*T{#endsyntax#}, {#syntax#}fn(){#endsyntax#}, {#syntax#}?*T{#endsyntax#},
5176 {#syntax#}?fn(){#endsyntax#}, or {#syntax#}[]T{#endsyntax#}. It returns the same type as {#syntax#}ptr{#endsyntax#}
5177 except with the alignment adjusted to the new value.
5178 </p>
5179 <p>A {#link|pointer alignment safety check|Incorrect Pointer Alignment#} is added
5180 to the generated code to make sure the pointer is aligned as promised.</p>
5181
5182 {#header_close#}
5183 {#header_open|@alignOf#}
5184 <pre>{#syntax#}@alignOf(comptime T: type) comptime_int{#endsyntax#}</pre>
5185 <p>
5186 This function returns the number of bytes that this type should be aligned to
5187 for the current target to match the C ABI. When the child type of a pointer has
5188 this alignment, the alignment can be omitted from the type.
5189 </p>
5190 <pre>{#syntax#}const assert = @import("std").debug.assert;
5191comptime {
5192 assert(*u32 == *align(@alignOf(u32)) u32);
5193}{#endsyntax#}</pre>
5194 <p>
5195 The result is a target-specific compile time constant. It is guaranteed to be
5196 less than or equal to {#link|@sizeOf(T)|@sizeOf#}.
5197 </p>
5198 {#see_also|Alignment#}
5199 {#header_close#}
5158 {#header_open|@ArgType#}5200 {#header_open|@ArgType#}
5159 <pre>{#syntax#}@ArgType(comptime T: type, comptime n: usize) type{#endsyntax#}</pre>5201 <pre>{#syntax#}@ArgType(comptime T: type, comptime n: usize) type{#endsyntax#}</pre>
5160 <p>5202 <p>
...@@ -5227,6 +5269,7 @@ fn seq(c: u8) void {...@@ -5227,6 +5269,7 @@ fn seq(c: u8) void {
5227 Works at compile-time if {#syntax#}value{#endsyntax#} is known at compile time. It's a compile error to bitcast a struct to a scalar type of the same size since structs have undefined layout. However if the struct is packed then it works.5269 Works at compile-time if {#syntax#}value{#endsyntax#} is known at compile time. It's a compile error to bitcast a struct to a scalar type of the same size since structs have undefined layout. However if the struct is packed then it works.
5228 </p>5270 </p>
5229 {#header_close#}5271 {#header_close#}
5272
5230 {#header_open|@bitOffsetOf#}5273 {#header_open|@bitOffsetOf#}
5231 <pre>{#syntax#}@bitOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre>5274 <pre>{#syntax#}@bitOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre>
5232 <p>5275 <p>
...@@ -5239,6 +5282,19 @@ fn seq(c: u8) void {...@@ -5239,6 +5282,19 @@ fn seq(c: u8) void {
5239 </p>5282 </p>
5240 {#see_also|@byteOffsetOf#}5283 {#see_also|@byteOffsetOf#}
5241 {#header_close#}5284 {#header_close#}
5285
5286 {#header_open|@boolToInt#}
5287 <pre>{#syntax#}@boolToInt(value: bool) u1{#endsyntax#}</pre>
5288 <p>
5289 Converts {#syntax#}true{#endsyntax#} to {#syntax#}u1(1){#endsyntax#} and {#syntax#}false{#endsyntax#} to
5290 {#syntax#}u1(0){#endsyntax#}.
5291 </p>
5292 <p>
5293 If the value is known at compile-time, the return type is {#syntax#}comptime_int{#endsyntax#}
5294 instead of {#syntax#}u1{#endsyntax#}.
5295 </p>
5296 {#header_close#}
5297
5242 {#header_open|@breakpoint#}5298 {#header_open|@breakpoint#}
5243 <pre>{#syntax#}@breakpoint(){#endsyntax#}</pre>5299 <pre>{#syntax#}@breakpoint(){#endsyntax#}</pre>
5244 <p>5300 <p>
...@@ -5250,52 +5306,22 @@ fn seq(c: u8) void {...@@ -5250,52 +5306,22 @@ fn seq(c: u8) void {
5250 </p>5306 </p>
52515307
5252 {#header_close#}5308 {#header_close#}
5253 {#header_open|@byteOffsetOf#}
5254 <pre>{#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre>
5255 <p>
5256 Returns the byte offset of a field relative to its containing struct.
5257 </p>
5258 {#see_also|@bitOffsetOf#}
5259 {#header_close#}
5260 {#header_open|@alignCast#}
5261 <pre>{#syntax#}@alignCast(comptime alignment: u29, ptr: var) var{#endsyntax#}</pre>
5262 <p>
5263 {#syntax#}ptr{#endsyntax#} can be {#syntax#}*T{#endsyntax#}, {#syntax#}fn(){#endsyntax#}, {#syntax#}?*T{#endsyntax#},
5264 {#syntax#}?fn(){#endsyntax#}, or {#syntax#}[]T{#endsyntax#}. It returns the same type as {#syntax#}ptr{#endsyntax#}
5265 except with the alignment adjusted to the new value.
5266 </p>
5267 <p>A {#link|pointer alignment safety check|Incorrect Pointer Alignment#} is added
5268 to the generated code to make sure the pointer is aligned as promised.</p>
52695309
5270 {#header_close#}5310 {#header_open|@bswap#}
5271 {#header_open|@alignOf#}5311 <pre>{#syntax#}@bswap(comptime T: type, value: T) T{#endsyntax#}</pre>
5272 <pre>{#syntax#}@alignOf(comptime T: type) comptime_int{#endsyntax#}</pre>5312 <p>{#syntax#}T{#endsyntax#} must be an integer type with bit count evenly divisible by 8.</p>
5273 <p>5313 <p>
5274 This function returns the number of bytes that this type should be aligned to5314 Swaps the byte order of the integer. This converts a big endian integer to a little endian integer,
5275 for the current target to match the C ABI. When the child type of a pointer has5315 and converts a little endian integer to a big endian integer.
5276 this alignment, the alignment can be omitted from the type.
5277 </p>
5278 <pre>{#syntax#}const assert = @import("std").debug.assert;
5279comptime {
5280 assert(*u32 == *align(@alignOf(u32)) u32);
5281}{#endsyntax#}</pre>
5282 <p>
5283 The result is a target-specific compile time constant. It is guaranteed to be
5284 less than or equal to {#link|@sizeOf(T)|@sizeOf#}.
5285 </p>5316 </p>
5286 {#see_also|Alignment#}
5287 {#header_close#}5317 {#header_close#}
52885318
5289 {#header_open|@boolToInt#}5319 {#header_open|@byteOffsetOf#}
5290 <pre>{#syntax#}@boolToInt(value: bool) u1{#endsyntax#}</pre>5320 <pre>{#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre>
5291 <p>
5292 Converts {#syntax#}true{#endsyntax#} to {#syntax#}u1(1){#endsyntax#} and {#syntax#}false{#endsyntax#} to
5293 {#syntax#}u1(0){#endsyntax#}.
5294 </p>
5295 <p>5321 <p>
5296 If the value is known at compile-time, the return type is {#syntax#}comptime_int{#endsyntax#}5322 Returns the byte offset of a field relative to its containing struct.
5297 instead of {#syntax#}u1{#endsyntax#}.
5298 </p>5323 </p>
5324 {#see_also|@bitOffsetOf#}
5299 {#header_close#}5325 {#header_close#}
53005326
5301 {#header_open|@bytesToSlice#}5327 {#header_open|@bytesToSlice#}
...@@ -5364,17 +5390,7 @@ comptime {...@@ -5364,17 +5390,7 @@ comptime {
5364 </p>5390 </p>
5365 {#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#}5391 {#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#}
5366 {#header_close#}5392 {#header_close#}
5367 {#header_open|@cUndef#}5393
5368 <pre>{#syntax#}@cUndef(comptime name: []u8){#endsyntax#}</pre>
5369 <p>
5370 This function can only occur inside {#syntax#}@cImport{#endsyntax#}.
5371 </p>
5372 <p>
5373 This appends <code>#undef $name</code> to the {#syntax#}@cImport{#endsyntax#}
5374 temporary buffer.
5375 </p>
5376 {#see_also|Import from C Header File|@cImport|@cDefine|@cInclude#}
5377 {#header_close#}
5378 {#header_open|@clz#}5394 {#header_open|@clz#}
5379 <pre>{#syntax#}@clz(x: T) U{#endsyntax#}</pre>5395 <pre>{#syntax#}@clz(x: T) U{#endsyntax#}</pre>
5380 <p>5396 <p>
...@@ -5390,6 +5406,7 @@ comptime {...@@ -5390,6 +5406,7 @@ comptime {
5390 </p>5406 </p>
5391 {#see_also|@ctz|@popCount#}5407 {#see_also|@ctz|@popCount#}
5392 {#header_close#}5408 {#header_close#}
5409
5393 {#header_open|@cmpxchgStrong#}5410 {#header_open|@cmpxchgStrong#}
5394 <pre>{#syntax#}@cmpxchgStrong(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}</pre>5411 <pre>{#syntax#}@cmpxchgStrong(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}</pre>
5395 <p>5412 <p>
...@@ -5445,6 +5462,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val...@@ -5445,6 +5462,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
5445 <p>{#syntax#}@typeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>5462 <p>{#syntax#}@typeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
5446 {#see_also|Compile Variables|cmpxchgStrong#}5463 {#see_also|Compile Variables|cmpxchgStrong#}
5447 {#header_close#}5464 {#header_close#}
5465
5448 {#header_open|@compileError#}5466 {#header_open|@compileError#}
5449 <pre>{#syntax#}@compileError(comptime msg: []u8){#endsyntax#}</pre>5467 <pre>{#syntax#}@compileError(comptime msg: []u8){#endsyntax#}</pre>
5450 <p>5468 <p>
...@@ -5457,6 +5475,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val...@@ -5457,6 +5475,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
5457 and {#syntax#}comptime{#endsyntax#} functions.5475 and {#syntax#}comptime{#endsyntax#} functions.
5458 </p>5476 </p>
5459 {#header_close#}5477 {#header_close#}
5478
5460 {#header_open|@compileLog#}5479 {#header_open|@compileLog#}
5461 <pre>{#syntax#}@compileLog(args: ...){#endsyntax#}</pre>5480 <pre>{#syntax#}@compileLog(args: ...){#endsyntax#}</pre>
5462 <p>5481 <p>
...@@ -5511,6 +5530,7 @@ test "main" {...@@ -5511,6 +5530,7 @@ test "main" {
5511}5530}
5512 {#code_end#}5531 {#code_end#}
5513 {#header_close#}5532 {#header_close#}
5533
5514 {#header_open|@ctz#}5534 {#header_open|@ctz#}
5515 <pre>{#syntax#}@ctz(x: T) U{#endsyntax#}</pre>5535 <pre>{#syntax#}@ctz(x: T) U{#endsyntax#}</pre>
5516 <p>5536 <p>
...@@ -5526,6 +5546,19 @@ test "main" {...@@ -5526,6 +5546,19 @@ test "main" {
5526 </p>5546 </p>
5527 {#see_also|@clz|@popCount#}5547 {#see_also|@clz|@popCount#}
5528 {#header_close#}5548 {#header_close#}
5549
5550 {#header_open|@cUndef#}
5551 <pre>{#syntax#}@cUndef(comptime name: []u8){#endsyntax#}</pre>
5552 <p>
5553 This function can only occur inside {#syntax#}@cImport{#endsyntax#}.
5554 </p>
5555 <p>
5556 This appends <code>#undef $name</code> to the {#syntax#}@cImport{#endsyntax#}
5557 temporary buffer.
5558 </p>
5559 {#see_also|Import from C Header File|@cImport|@cDefine|@cInclude#}
5560 {#header_close#}
5561
5529 {#header_open|@divExact#}5562 {#header_open|@divExact#}
5530 <pre>{#syntax#}@divExact(numerator: T, denominator: T) T{#endsyntax#}</pre>5563 <pre>{#syntax#}@divExact(numerator: T, denominator: T) T{#endsyntax#}</pre>
5531 <p>5564 <p>
...@@ -5592,27 +5625,15 @@ test "main" {...@@ -5592,27 +5625,15 @@ test "main" {
5592 {#see_also|@intToEnum#}5625 {#see_also|@intToEnum#}
5593 {#header_close#}5626 {#header_close#}
55945627
5595 {#header_open|@errSetCast#}
5596 <pre>{#syntax#}@errSetCast(comptime T: DestType, value: var) DestType{#endsyntax#}</pre>
5597 <p>
5598 Converts an error value from one error set to another error set. Attempting to convert an error
5599 which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}.
5600 </p>
5601 {#header_close#}
5602
5603 {#header_open|@errorName#}5628 {#header_open|@errorName#}
5604 <pre>{#syntax#}@errorName(err: error) []u8{#endsyntax#}</pre>5629 <pre>{#syntax#}@errorName(err: anyerror) []const u8{#endsyntax#}</pre>
5605 <p>5630 <p>
5606 This function returns the string representation of an error. If an error5631 This function returns the string representation of an error. The string representation
5607 declaration is:5632 of {#syntax#}error.OutOfMem{#endsyntax#} is {#syntax#}"OutOfMem"{#endsyntax#}.
5608 </p>
5609 <pre>{#syntax#}error OutOfMem{#endsyntax#}</pre>
5610 <p>
5611 Then the string representation is {#syntax#}"OutOfMem"{#endsyntax#}.
5612 </p>5633 </p>
5613 <p>5634 <p>
5614 If there are no calls to {#syntax#}@errorName{#endsyntax#} in an entire application,5635 If there are no calls to {#syntax#}@errorName{#endsyntax#} in an entire application,
5615 or all calls have a compile-time known value for {#syntax#}err{#endsyntax#}, then no5636 or all calls have a compile-time known value for {#syntax#}err{#endsyntax#}, then no
5616 error name table will be generated.5637 error name table will be generated.
5617 </p>5638 </p>
5618 {#header_close#}5639 {#header_close#}
...@@ -5627,13 +5648,14 @@ test "main" {...@@ -5627,13 +5648,14 @@ test "main" {
5627 {#header_close#}5648 {#header_close#}
56285649
5629 {#header_open|@errorToInt#}5650 {#header_open|@errorToInt#}
5630 <pre>{#syntax#}@errorToInt(err: var) @IntType(false, @sizeOf(error) * 8){#endsyntax#}</pre>5651 <pre>{#syntax#}@errorToInt(err: var) @IntType(false, @sizeOf(anyerror) * 8){#endsyntax#}</pre>
5631 <p>5652 <p>
5632 Supports the following types:5653 Supports the following types:
5633 </p>5654 </p>
5634 <ul>5655 <ul>
5635 <li>error unions</li>5656 <li>{#link|The Global Error Set#}</li>
5636 <li>{#syntax#}E!void{#endsyntax#}</li>5657 <li>{#link|Error Set Type#}</li>
5658 <li>{#link|Error Union Type#}</li>
5637 </ul>5659 </ul>
5638 <p>5660 <p>
5639 Converts an error to the integer representation of an error.5661 Converts an error to the integer representation of an error.
...@@ -5645,6 +5667,14 @@ test "main" {...@@ -5645,6 +5667,14 @@ test "main" {
5645 {#see_also|@intToError#}5667 {#see_also|@intToError#}
5646 {#header_close#}5668 {#header_close#}
56475669
5670 {#header_open|@errSetCast#}
5671 <pre>{#syntax#}@errSetCast(comptime T: DestType, value: var) DestType{#endsyntax#}</pre>
5672 <p>
5673 Converts an error value from one error set to another error set. Attempting to convert an error
5674 which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}.
5675 </p>
5676 {#header_close#}
5677
5648 {#header_open|@export#}5678 {#header_open|@export#}
5649 <pre>{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8{#endsyntax#}</pre>5679 <pre>{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8{#endsyntax#}</pre>
5650 <p>5680 <p>
...@@ -5713,6 +5743,7 @@ test "main" {...@@ -5713,6 +5743,7 @@ test "main" {
5713 This function is only valid within function scope.5743 This function is only valid within function scope.
5714 </p>5744 </p>
5715 {#header_close#}5745 {#header_close#}
5746
5716 {#header_open|@handle#}5747 {#header_open|@handle#}
5717 <pre>{#syntax#}@handle(){#endsyntax#}</pre>5748 <pre>{#syntax#}@handle(){#endsyntax#}</pre>
5718 <p>5749 <p>
...@@ -5723,6 +5754,7 @@ test "main" {...@@ -5723,6 +5754,7 @@ test "main" {
5723 This function is only valid within an async function scope.5754 This function is only valid within an async function scope.
5724 </p>5755 </p>
5725 {#header_close#}5756 {#header_close#}
5757
5726 {#header_open|@import#}5758 {#header_open|@import#}
5727 <pre>{#syntax#}@import(comptime path: []u8) (namespace){#endsyntax#}</pre>5759 <pre>{#syntax#}@import(comptime path: []u8) (namespace){#endsyntax#}</pre>
5728 <p>5760 <p>
...@@ -5743,6 +5775,7 @@ test "main" {...@@ -5743,6 +5775,7 @@ test "main" {
5743 </ul>5775 </ul>
5744 {#see_also|Compile Variables|@embedFile#}5776 {#see_also|Compile Variables|@embedFile#}
5745 {#header_close#}5777 {#header_close#}
5778
5746 {#header_open|@inlineCall#}5779 {#header_open|@inlineCall#}
5747 <pre>{#syntax#}@inlineCall(function: X, args: ...) Y{#endsyntax#}</pre>5780 <pre>{#syntax#}@inlineCall(function: X, args: ...) Y{#endsyntax#}</pre>
5748 <p>5781 <p>
...@@ -5788,7 +5821,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -5788,7 +5821,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
5788 {#header_open|@intToError#}5821 {#header_open|@intToError#}
5789 <pre>{#syntax#}@intToError(value: @IntType(false, @sizeOf(anyerror) * 8)) anyerror{#endsyntax#}</pre>5822 <pre>{#syntax#}@intToError(value: @IntType(false, @sizeOf(anyerror) * 8)) anyerror{#endsyntax#}</pre>
5790 <p>5823 <p>
5791 Converts from the integer representation of an error into the global error set type.5824 Converts from the integer representation of an error into {#link|The Global Error Set#} type.
5792 </p>5825 </p>
5793 <p>5826 <p>
5794 It is generally recommended to avoid this5827 It is generally recommended to avoid this
...@@ -5822,6 +5855,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -5822,6 +5855,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
5822 bit count for an integer type is {#syntax#}65535{#endsyntax#}.5855 bit count for an integer type is {#syntax#}65535{#endsyntax#}.
5823 </p>5856 </p>
5824 {#header_close#}5857 {#header_close#}
5858
5825 {#header_open|@memberCount#}5859 {#header_open|@memberCount#}
5826 <pre>{#syntax#}@memberCount(comptime T: type) comptime_int{#endsyntax#}</pre>5860 <pre>{#syntax#}@memberCount(comptime T: type) comptime_int{#endsyntax#}</pre>
5827 <p>5861 <p>
...@@ -5848,6 +5882,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -5848,6 +5882,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
5848 <pre>{#syntax#}@memberType(comptime T: type, comptime index: usize) type{#endsyntax#}</pre>5882 <pre>{#syntax#}@memberType(comptime T: type, comptime index: usize) type{#endsyntax#}</pre>
5849 <p>Returns the field type of a struct or union.</p>5883 <p>Returns the field type of a struct or union.</p>
5850 {#header_close#}5884 {#header_close#}
5885
5851 {#header_open|@memcpy#}5886 {#header_open|@memcpy#}
5852 <pre>{#syntax#}@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize){#endsyntax#}</pre>5887 <pre>{#syntax#}@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize){#endsyntax#}</pre>
5853 <p>5888 <p>
...@@ -5866,6 +5901,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -5866,6 +5901,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
5866 <pre>{#syntax#}const mem = @import("std").mem;5901 <pre>{#syntax#}const mem = @import("std").mem;
5867mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>5902mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>
5868 {#header_close#}5903 {#header_close#}
5904
5869 {#header_open|@memset#}5905 {#header_open|@memset#}
5870 <pre>{#syntax#}@memset(dest: [*]u8, c: u8, byte_count: usize){#endsyntax#}</pre>5906 <pre>{#syntax#}@memset(dest: [*]u8, c: u8, byte_count: usize){#endsyntax#}</pre>
5871 <p>5907 <p>
...@@ -5883,6 +5919,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>...@@ -5883,6 +5919,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>
5883 <pre>{#syntax#}const mem = @import("std").mem;5919 <pre>{#syntax#}const mem = @import("std").mem;
5884mem.set(u8, dest, c);{#endsyntax#}</pre>5920mem.set(u8, dest, c);{#endsyntax#}</pre>
5885 {#header_close#}5921 {#header_close#}
5922
5886 {#header_open|@mod#}5923 {#header_open|@mod#}
5887 <pre>{#syntax#}@mod(numerator: T, denominator: T) T{#endsyntax#}</pre>5924 <pre>{#syntax#}@mod(numerator: T, denominator: T) T{#endsyntax#}</pre>
5888 <p>5925 <p>
...@@ -5896,6 +5933,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>...@@ -5896,6 +5933,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>
5896 <p>For a function that returns an error code, see {#syntax#}@import("std").math.mod{#endsyntax#}.</p>5933 <p>For a function that returns an error code, see {#syntax#}@import("std").math.mod{#endsyntax#}.</p>
5897 {#see_also|@rem#}5934 {#see_also|@rem#}
5898 {#header_close#}5935 {#header_close#}
5936
5899 {#header_open|@mulWithOverflow#}5937 {#header_open|@mulWithOverflow#}
5900 <pre>{#syntax#}@mulWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre>5938 <pre>{#syntax#}@mulWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre>
5901 <p>5939 <p>
...@@ -5904,6 +5942,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>...@@ -5904,6 +5942,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>
5904 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.5942 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
5905 </p>5943 </p>
5906 {#header_close#}5944 {#header_close#}
5945
5907 {#header_open|@newStackCall#}5946 {#header_open|@newStackCall#}
5908 <pre>{#syntax#}@newStackCall(new_stack: []u8, function: var, args: ...) var{#endsyntax#}</pre>5947 <pre>{#syntax#}@newStackCall(new_stack: []u8, function: var, args: ...) var{#endsyntax#}</pre>
5909 <p>5948 <p>
...@@ -5940,6 +5979,7 @@ fn targetFunction(x: i32) usize {...@@ -5940,6 +5979,7 @@ fn targetFunction(x: i32) usize {
5940}5979}
5941 {#code_end#}5980 {#code_end#}
5942 {#header_close#}5981 {#header_close#}
5982
5943 {#header_open|@noInlineCall#}5983 {#header_open|@noInlineCall#}
5944 <pre>{#syntax#}@noInlineCall(function: var, args: ...) var{#endsyntax#}</pre>5984 <pre>{#syntax#}@noInlineCall(function: var, args: ...) var{#endsyntax#}</pre>
5945 <p>5985 <p>
...@@ -5962,6 +6002,7 @@ fn add(a: i32, b: i32) i32 {...@@ -5962,6 +6002,7 @@ fn add(a: i32, b: i32) i32 {
5962 </p>6002 </p>
5963 {#see_also|@inlineCall#}6003 {#see_also|@inlineCall#}
5964 {#header_close#}6004 {#header_close#}
6005
5965 {#header_open|@OpaqueType#}6006 {#header_open|@OpaqueType#}
5966 <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>6007 <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>
5967 <p>6008 <p>
...@@ -5985,6 +6026,7 @@ test "call foo" {...@@ -5985,6 +6026,7 @@ test "call foo" {
5985}6026}
5986 {#code_end#}6027 {#code_end#}
5987 {#header_close#}6028 {#header_close#}
6029
5988 {#header_open|@panic#}6030 {#header_open|@panic#}
5989 <pre>{#syntax#}@panic(message: []const u8) noreturn{#endsyntax#}</pre>6031 <pre>{#syntax#}@panic(message: []const u8) noreturn{#endsyntax#}</pre>
5990 <p>6032 <p>
...@@ -6001,6 +6043,7 @@ test "call foo" {...@@ -6001,6 +6043,7 @@ test "call foo" {
6001 </ul>6043 </ul>
6002 {#see_also|Root Source File#}6044 {#see_also|Root Source File#}
6003 {#header_close#}6045 {#header_close#}
6046
6004 {#header_open|@popCount#}6047 {#header_open|@popCount#}
6005 <pre>{#syntax#}@popCount(integer: var) var{#endsyntax#}</pre>6048 <pre>{#syntax#}@popCount(integer: var) var{#endsyntax#}</pre>
6006 <p>Counts the number of bits set in an integer.</p>6049 <p>Counts the number of bits set in an integer.</p>
...@@ -6011,12 +6054,14 @@ test "call foo" {...@@ -6011,12 +6054,14 @@ test "call foo" {
6011 </p>6054 </p>
6012 {#see_also|@ctz|@clz#}6055 {#see_also|@ctz|@clz#}
6013 {#header_close#}6056 {#header_close#}
6057
6014 {#header_open|@ptrCast#}6058 {#header_open|@ptrCast#}
6015 <pre>{#syntax#}@ptrCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre>6059 <pre>{#syntax#}@ptrCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre>
6016 <p>6060 <p>
6017 Converts a pointer of one type to a pointer of another type.6061 Converts a pointer of one type to a pointer of another type.
6018 </p>6062 </p>
6019 {#header_close#}6063 {#header_close#}
6064
6020 {#header_open|@ptrToInt#}6065 {#header_open|@ptrToInt#}
6021 <pre>{#syntax#}@ptrToInt(value: var) usize{#endsyntax#}</pre>6066 <pre>{#syntax#}@ptrToInt(value: var) usize{#endsyntax#}</pre>
6022 <p>6067 <p>
...@@ -6031,6 +6076,7 @@ test "call foo" {...@@ -6031,6 +6076,7 @@ test "call foo" {
6031 <p>To convert the other way, use {#link|@intToPtr#}</p>6076 <p>To convert the other way, use {#link|@intToPtr#}</p>
60326077
6033 {#header_close#}6078 {#header_close#}
6079
6034 {#header_open|@rem#}6080 {#header_open|@rem#}
6035 <pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre>6081 <pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre>
6036 <p>6082 <p>
...@@ -6044,6 +6090,7 @@ test "call foo" {...@@ -6044,6 +6090,7 @@ test "call foo" {
6044 <p>For a function that returns an error code, see {#syntax#}@import("std").math.rem{#endsyntax#}.</p>6090 <p>For a function that returns an error code, see {#syntax#}@import("std").math.rem{#endsyntax#}.</p>
6045 {#see_also|@mod#}6091 {#see_also|@mod#}
6046 {#header_close#}6092 {#header_close#}
6093
6047 {#header_open|@returnAddress#}6094 {#header_open|@returnAddress#}
6048 <pre>{#syntax#}@returnAddress(){#endsyntax#}</pre>6095 <pre>{#syntax#}@returnAddress(){#endsyntax#}</pre>
6049 <p>6096 <p>
...@@ -6064,19 +6111,14 @@ test "call foo" {...@@ -6064,19 +6111,14 @@ test "call foo" {
6064 Ensures that a function will have a stack alignment of at least {#syntax#}alignment{#endsyntax#} bytes.6111 Ensures that a function will have a stack alignment of at least {#syntax#}alignment{#endsyntax#} bytes.
6065 </p>6112 </p>
6066 {#header_close#}6113 {#header_close#}
6114
6067 {#header_open|@setCold#}6115 {#header_open|@setCold#}
6068 <pre>{#syntax#}@setCold(is_cold: bool){#endsyntax#}</pre>6116 <pre>{#syntax#}@setCold(is_cold: bool){#endsyntax#}</pre>
6069 <p>6117 <p>
6070 Tells the optimizer that a function is rarely called.6118 Tells the optimizer that a function is rarely called.
6071 </p>6119 </p>
6072 {#header_close#}6120 {#header_close#}
6073 {#header_open|@setRuntimeSafety#}
6074 <pre>{#syntax#}@setRuntimeSafety(safety_on: bool){#endsyntax#}</pre>
6075 <p>
6076 Sets whether runtime safety checks are on for the scope that contains the function call.
6077 </p>
60786121
6079 {#header_close#}
6080 {#header_open|@setEvalBranchQuota#}6122 {#header_open|@setEvalBranchQuota#}
6081 <pre>{#syntax#}@setEvalBranchQuota(new_quota: usize){#endsyntax#}</pre>6123 <pre>{#syntax#}@setEvalBranchQuota(new_quota: usize){#endsyntax#}</pre>
6082 <p>6124 <p>
...@@ -6111,6 +6153,7 @@ test "foo" {...@@ -6111,6 +6153,7 @@ test "foo" {
61116153
6112 {#see_also|comptime#}6154 {#see_also|comptime#}
6113 {#header_close#}6155 {#header_close#}
6156
6114 {#header_open|@setFloatMode#}6157 {#header_open|@setFloatMode#}
6115 <pre>{#syntax#}@setFloatMode(mode: @import("builtin").FloatMode){#endsyntax#}</pre>6158 <pre>{#syntax#}@setFloatMode(mode: @import("builtin").FloatMode){#endsyntax#}</pre>
6116 <p>6159 <p>
...@@ -6145,6 +6188,7 @@ pub const FloatMode = enum {...@@ -6145,6 +6188,7 @@ pub const FloatMode = enum {
6145 </p>6188 </p>
6146 {#see_also|Floating Point Operations#}6189 {#see_also|Floating Point Operations#}
6147 {#header_close#}6190 {#header_close#}
6191
6148 {#header_open|@setGlobalLinkage#}6192 {#header_open|@setGlobalLinkage#}
6149 <pre>{#syntax#}@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage){#endsyntax#}</pre>6193 <pre>{#syntax#}@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage){#endsyntax#}</pre>
6150 <p>6194 <p>
...@@ -6152,6 +6196,15 @@ pub const FloatMode = enum {...@@ -6152,6 +6196,15 @@ pub const FloatMode = enum {
6152 </p>6196 </p>
6153 {#see_also|Compile Variables#}6197 {#see_also|Compile Variables#}
6154 {#header_close#}6198 {#header_close#}
6199
6200 {#header_open|@setRuntimeSafety#}
6201 <pre>{#syntax#}@setRuntimeSafety(safety_on: bool){#endsyntax#}</pre>
6202 <p>
6203 Sets whether runtime safety checks are on for the scope that contains the function call.
6204 </p>
6205
6206 {#header_close#}
6207
6155 {#header_open|@shlExact#}6208 {#header_open|@shlExact#}
6156 <pre>{#syntax#}@shlExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre>6209 <pre>{#syntax#}@shlExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre>
6157 <p>6210 <p>
...@@ -6164,6 +6217,7 @@ pub const FloatMode = enum {...@@ -6164,6 +6217,7 @@ pub const FloatMode = enum {
6164 </p>6217 </p>
6165 {#see_also|@shrExact|@shlWithOverflow#}6218 {#see_also|@shrExact|@shlWithOverflow#}
6166 {#header_close#}6219 {#header_close#}
6220
6167 {#header_open|@shlWithOverflow#}6221 {#header_open|@shlWithOverflow#}
6168 <pre>{#syntax#}@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: *T) bool{#endsyntax#}</pre>6222 <pre>{#syntax#}@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: *T) bool{#endsyntax#}</pre>
6169 <p>6223 <p>
...@@ -6177,6 +6231,7 @@ pub const FloatMode = enum {...@@ -6177,6 +6231,7 @@ pub const FloatMode = enum {
6177 </p>6231 </p>
6178 {#see_also|@shlExact|@shrExact#}6232 {#see_also|@shlExact|@shrExact#}
6179 {#header_close#}6233 {#header_close#}
6234
6180 {#header_open|@shrExact#}6235 {#header_open|@shrExact#}
6181 <pre>{#syntax#}@shrExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre>6236 <pre>{#syntax#}@shrExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre>
6182 <p>6237 <p>
...@@ -6218,6 +6273,7 @@ pub const FloatMode = enum {...@@ -6218,6 +6273,7 @@ pub const FloatMode = enum {
6218 This is a low-level intrinsic. Most code can use {#syntax#}std.math.sqrt{#endsyntax#} instead.6273 This is a low-level intrinsic. Most code can use {#syntax#}std.math.sqrt{#endsyntax#} instead.
6219 </p>6274 </p>
6220 {#header_close#}6275 {#header_close#}
6276
6221 {#header_open|@subWithOverflow#}6277 {#header_open|@subWithOverflow#}
6222 <pre>{#syntax#}@subWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre>6278 <pre>{#syntax#}@subWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre>
6223 <p>6279 <p>
...@@ -6226,12 +6282,14 @@ pub const FloatMode = enum {...@@ -6226,12 +6282,14 @@ pub const FloatMode = enum {
6226 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.6282 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
6227 </p>6283 </p>
6228 {#header_close#}6284 {#header_close#}
6285
6229 {#header_open|@tagName#}6286 {#header_open|@tagName#}
6230 <pre>{#syntax#}@tagName(value: var) []const u8{#endsyntax#}</pre>6287 <pre>{#syntax#}@tagName(value: var) []const u8{#endsyntax#}</pre>
6231 <p>6288 <p>
6232 Converts an enum value or union value to a slice of bytes representing the name.6289 Converts an enum value or union value to a slice of bytes representing the name.
6233 </p>6290 </p>
6234 {#header_close#}6291 {#header_close#}
6292
6235 {#header_open|@TagType#}6293 {#header_open|@TagType#}
6236 <pre>{#syntax#}@TagType(T: type) type{#endsyntax#}</pre>6294 <pre>{#syntax#}@TagType(T: type) type{#endsyntax#}</pre>
6237 <p>6295 <p>
...@@ -6241,6 +6299,7 @@ pub const FloatMode = enum {...@@ -6241,6 +6299,7 @@ pub const FloatMode = enum {
6241 For a union, returns the enum type that is used to store the tag value.6299 For a union, returns the enum type that is used to store the tag value.
6242 </p>6300 </p>
6243 {#header_close#}6301 {#header_close#}
6302
6244 {#header_open|@This#}6303 {#header_open|@This#}
6245 <pre>{#syntax#}@This() type{#endsyntax#}</pre>6304 <pre>{#syntax#}@This() type{#endsyntax#}</pre>
6246 <p>6305 <p>
...@@ -6276,6 +6335,7 @@ fn List(comptime T: type) type {...@@ -6276,6 +6335,7 @@ fn List(comptime T: type) type {
6276 <a href="https://github.com/ziglang/zig/issues/1047">#1047</a> for details.6335 <a href="https://github.com/ziglang/zig/issues/1047">#1047</a> for details.
6277 </p>6336 </p>
6278 {#header_close#}6337 {#header_close#}
6338
6279 {#header_open|@truncate#}6339 {#header_open|@truncate#}
6280 <pre>{#syntax#}@truncate(comptime T: type, integer) T{#endsyntax#}</pre>6340 <pre>{#syntax#}@truncate(comptime T: type, integer) T{#endsyntax#}</pre>
6281 <p>6341 <p>
...@@ -6300,6 +6360,7 @@ const b: u8 = @truncate(u8, a);...@@ -6300,6 +6360,7 @@ const b: u8 = @truncate(u8, a);
6300 </p>6360 </p>
63016361
6302 {#header_close#}6362 {#header_close#}
6363
6303 {#header_open|@typeId#}6364 {#header_open|@typeId#}
6304 <pre>{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}</pre>6365 <pre>{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}</pre>
6305 <p>6366 <p>
...@@ -6334,6 +6395,7 @@ pub const TypeId = enum {...@@ -6334,6 +6395,7 @@ pub const TypeId = enum {
6334};6395};
6335 {#code_end#}6396 {#code_end#}
6336 {#header_close#}6397 {#header_close#}
6398
6337 {#header_open|@typeInfo#}6399 {#header_open|@typeInfo#}
6338 <pre>{#syntax#}@typeInfo(comptime T: type) @import("builtin").TypeInfo{#endsyntax#}</pre>6400 <pre>{#syntax#}@typeInfo(comptime T: type) @import("builtin").TypeInfo{#endsyntax#}</pre>
6339 <p>6401 <p>
...@@ -6516,6 +6578,7 @@ pub const TypeInfo = union(TypeId) {...@@ -6516,6 +6578,7 @@ pub const TypeInfo = union(TypeId) {
6516};6578};
6517 {#code_end#}6579 {#code_end#}
6518 {#header_close#}6580 {#header_close#}
6581
6519 {#header_open|@typeName#}6582 {#header_open|@typeName#}
6520 <pre>{#syntax#}@typeName(T: type) []u8{#endsyntax#}</pre>6583 <pre>{#syntax#}@typeName(T: type) []u8{#endsyntax#}</pre>
6521 <p>6584 <p>
...@@ -6523,6 +6586,7 @@ pub const TypeInfo = union(TypeId) {...@@ -6523,6 +6586,7 @@ pub const TypeInfo = union(TypeId) {
6523 </p>6586 </p>
65246587
6525 {#header_close#}6588 {#header_close#}
6589
6526 {#header_open|@typeOf#}6590 {#header_open|@typeOf#}
6527 <pre>{#syntax#}@typeOf(expression) type{#endsyntax#}</pre>6591 <pre>{#syntax#}@typeOf(expression) type{#endsyntax#}</pre>
6528 <p>6592 <p>
...@@ -6532,6 +6596,7 @@ pub const TypeInfo = union(TypeId) {...@@ -6532,6 +6596,7 @@ pub const TypeInfo = union(TypeId) {
65326596
6533 {#header_close#}6597 {#header_close#}
6534 {#header_close#}6598 {#header_close#}
6599
6535 {#header_open|Build Mode#}6600 {#header_open|Build Mode#}
6536 <p>6601 <p>
6537 Zig has four build modes:6602 Zig has four build modes:
...@@ -6659,7 +6724,7 @@ fn foo(x: []const u8) u8 {...@@ -6659,7 +6724,7 @@ fn foo(x: []const u8) u8 {
6659 {#header_close#}6724 {#header_close#}
6660 {#header_open|Cast Negative Number to Unsigned Integer#}6725 {#header_open|Cast Negative Number to Unsigned Integer#}
6661 <p>At compile-time:</p>6726 <p>At compile-time:</p>
6662 {#code_begin|test_err|attempt to cast negative value to unsigned integer#}6727 {#code_begin|test_err|cannot cast negative value -1 to unsigned integer type 'u32'#}
6663comptime {6728comptime {
6664 const value: i32 = -1;6729 const value: i32 = -1;
6665 const unsigned = @intCast(u32, value);6730 const unsigned = @intCast(u32, value);
...@@ -6681,7 +6746,7 @@ pub fn main() void {...@@ -6681,7 +6746,7 @@ pub fn main() void {
6681 {#header_close#}6746 {#header_close#}
6682 {#header_open|Cast Truncates Data#}6747 {#header_open|Cast Truncates Data#}
6683 <p>At compile-time:</p>6748 <p>At compile-time:</p>
6684 {#code_begin|test_err|cast from 'u16' to 'u8' truncates bits#}6749 {#code_begin|test_err|integer value 300 cannot be implicitly casted to type 'u8'#}
6685comptime {6750comptime {
6686 const spartan_count: u16 = 300;6751 const spartan_count: u16 = 300;
6687 const byte = @intCast(u8, spartan_count);6752 const byte = @intCast(u8, spartan_count);
...@@ -7830,11 +7895,11 @@ TypeExpr &lt;- PrefixTypeOp* ErrorUnionExpr...@@ -7830,11 +7895,11 @@ TypeExpr &lt;- PrefixTypeOp* ErrorUnionExpr
7830ErrorUnionExpr &lt;- SuffixExpr (EXCLAMATIONMARK TypeExpr)?7895ErrorUnionExpr &lt;- SuffixExpr (EXCLAMATIONMARK TypeExpr)?
78317896
7832SuffixExpr7897SuffixExpr
7833 &lt;- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArgumnets7898 &lt;- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArguments
7834 / PrimaryTypeExpr (SuffixOp / FnCallArgumnets)*7899 / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
78357900
7836PrimaryTypeExpr7901PrimaryTypeExpr
7837 &lt;- BUILTININDENTIFIER FnCallArgumnets7902 &lt;- BUILTINIDENTIFIER FnCallArguments
7838 / CHAR_LITERAL7903 / CHAR_LITERAL
7839 / ContainerDecl7904 / ContainerDecl
7840 / ErrorSetDecl7905 / ErrorSetDecl
...@@ -7884,11 +7949,11 @@ AsmOutput &lt;- COLON AsmOutputList AsmInput?...@@ -7884,11 +7949,11 @@ AsmOutput &lt;- COLON AsmOutputList AsmInput?
78847949
7885AsmOutputItem &lt;- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN7950AsmOutputItem &lt;- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
78867951
7887AsmInput &lt;- COLON AsmInputList AsmCloppers?7952AsmInput &lt;- COLON AsmInputList AsmClobbers?
78887953
7889AsmInputItem &lt;- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN7954AsmInputItem &lt;- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
78907955
7891AsmCloppers &lt;- COLON StringList7956AsmClobbers &lt;- COLON StringList
78927957
7893# *** Helper grammar ***7958# *** Helper grammar ***
7894BreakLabel &lt;- COLON IDENTIFIER7959BreakLabel &lt;- COLON IDENTIFIER
...@@ -8013,7 +8078,7 @@ SuffixOp...@@ -8013,7 +8078,7 @@ SuffixOp
80138078
8014AsyncPrefix &lt;- KEYWORD_async (LARROW PrefixExpr RARROW)?8079AsyncPrefix &lt;- KEYWORD_async (LARROW PrefixExpr RARROW)?
80158080
8016FnCallArgumnets &lt;- LPAREN ExprList RPAREN8081FnCallArguments &lt;- LPAREN ExprList RPAREN
80178082
8018# Ptr specific8083# Ptr specific
8019ArrayTypeStart &lt;- LBRACKET Expr? RBRACKET8084ArrayTypeStart &lt;- LBRACKET Expr? RBRACKET
...@@ -8090,7 +8155,7 @@ STRINGLITERAL...@@ -8090,7 +8155,7 @@ STRINGLITERAL
8090IDENTIFIER8155IDENTIFIER
8091 &lt;- !keyword ("c" !["\\] / [A-Zabd-z_]) [A-Za-z0-9_]* skip8156 &lt;- !keyword ("c" !["\\] / [A-Zabd-z_]) [A-Za-z0-9_]* skip
8092 / "@\"" string_char* "\"" skip8157 / "@\"" string_char* "\"" skip
8093BUILTININDENTIFIER &lt;- "@"[A-Za-z_][A-Za-z0-9_]* skip8158BUILTINIDENTIFIER &lt;- "@"[A-Za-z_][A-Za-z0-9_]* skip
80948159
80958160
8096AMPERSAND &lt;- '&' ![=] skip8161AMPERSAND &lt;- '&' ![=] skip
...@@ -8109,9 +8174,9 @@ DOT2 &lt;- '..' ![.] skip...@@ -8109,9 +8174,9 @@ DOT2 &lt;- '..' ![.] skip
8109DOT3 &lt;- '...' skip8174DOT3 &lt;- '...' skip
8110DOTASTERISK &lt;- '.*' skip8175DOTASTERISK &lt;- '.*' skip
8111DOTQUESTIONMARK &lt;- '.?' skip8176DOTQUESTIONMARK &lt;- '.?' skip
8112EQUAL &lt;- '=' ![>=] skip8177EQUAL &lt;- '=' ![&gt;=] skip
8113EQUALEQUAL &lt;- '==' skip8178EQUALEQUAL &lt;- '==' skip
8114EQUALRARROW &lt;- '=>' skip8179EQUALRARROW &lt;- '=&gt;' skip
8115EXCLAMATIONMARK &lt;- '!' ![=] skip8180EXCLAMATIONMARK &lt;- '!' ![=] skip
8116EXCLAMATIONMARKEQUAL &lt;- '!=' skip8181EXCLAMATIONMARKEQUAL &lt;- '!=' skip
8117LARROW &lt;- '&lt;' ![&lt;=] skip8182LARROW &lt;- '&lt;' ![&lt;=] skip
...@@ -8121,11 +8186,11 @@ LARROWEQUAL &lt;- '&lt;=' skip...@@ -8121,11 +8186,11 @@ LARROWEQUAL &lt;- '&lt;=' skip
8121LBRACE &lt;- '{' skip8186LBRACE &lt;- '{' skip
8122LBRACKET &lt;- '[' skip8187LBRACKET &lt;- '[' skip
8123LPAREN &lt;- '(' skip8188LPAREN &lt;- '(' skip
8124MINUS &lt;- '-' ![%=>] skip8189MINUS &lt;- '-' ![%=&gt;] skip
8125MINUSEQUAL &lt;- '-=' skip8190MINUSEQUAL &lt;- '-=' skip
8126MINUSPERCENT &lt;- '-%' ![=] skip8191MINUSPERCENT &lt;- '-%' ![=] skip
8127MINUSPERCENTEQUAL &lt;- '-%=' skip8192MINUSPERCENTEQUAL &lt;- '-%=' skip
8128MINUSRARROW &lt;- '->' skip8193MINUSRARROW &lt;- '-&gt;' skip
8129PERCENT &lt;- '%' ![=] skip8194PERCENT &lt;- '%' ![=] skip
8130PERCENTEQUAL &lt;- '%=' skip8195PERCENTEQUAL &lt;- '%=' skip
8131PIPE &lt;- '|' ![|=] skip8196PIPE &lt;- '|' ![|=] skip
...@@ -8137,10 +8202,10 @@ PLUSEQUAL &lt;- '+=' skip...@@ -8137,10 +8202,10 @@ PLUSEQUAL &lt;- '+=' skip
8137PLUSPERCENT &lt;- '+%' ![=] skip8202PLUSPERCENT &lt;- '+%' ![=] skip
8138PLUSPERCENTEQUAL &lt;- '+%=' skip8203PLUSPERCENTEQUAL &lt;- '+%=' skip
8139QUESTIONMARK &lt;- '?' skip8204QUESTIONMARK &lt;- '?' skip
8140RARROW &lt;- '>' ![>=] skip8205RARROW &lt;- '&gt;' ![&gt;=] skip
8141RARROW2 &lt;- '>>' ![=] skip8206RARROW2 &lt;- '&gt;&gt;' ![=] skip
8142RARROW2EQUAL &lt;- '>>=' skip8207RARROW2EQUAL &lt;- '&gt;&gt;=' skip
8143RARROWEQUAL &lt;- '>=' skip8208RARROWEQUAL &lt;- '&gt;=' skip
8144RBRACE &lt;- '}' skip8209RBRACE &lt;- '}' skip
8145RBRACKET &lt;- ']' skip8210RBRACKET &lt;- ']' skip
8146RPAREN &lt;- ')' skip8211RPAREN &lt;- ')' skip
example/guess_number/main.zig+5-5
...@@ -15,7 +15,7 @@ pub fn main() !void {...@@ -15,7 +15,7 @@ pub fn main() !void {
15 std.debug.warn("unable to seed random number generator: {}", err);15 std.debug.warn("unable to seed random number generator: {}", err);
16 return err;16 return err;
17 };17 };
18 const seed = std.mem.readInt(seed_bytes, u64, builtin.Endian.Big);18 const seed = std.mem.readIntNative(u64, &seed_bytes);
19 var prng = std.rand.DefaultPrng.init(seed);19 var prng = std.rand.DefaultPrng.init(seed);
2020
21 const answer = prng.random.range(u8, 0, 100) + 1;21 const answer = prng.random.range(u8, 0, 100) + 1;
...@@ -24,15 +24,15 @@ pub fn main() !void {...@@ -24,15 +24,15 @@ pub fn main() !void {
24 try stdout.print("\nGuess a number between 1 and 100: ");24 try stdout.print("\nGuess a number between 1 and 100: ");
25 var line_buf: [20]u8 = undefined;25 var line_buf: [20]u8 = undefined;
2626
27 const line_len = io.readLine(line_buf[0..]) catch |err| switch (err) {27 const line = io.readLineSlice(line_buf[0..]) catch |err| switch (err) {
28 error.InputTooLong => {28 error.OutOfMemory => {
29 try stdout.print("Input too long.\n");29 try stdout.print("Input too long.\n");
30 continue;30 continue;
31 },31 },
32 error.EndOfFile, error.StdInUnavailable => return err,32 else => return err,
33 };33 };
3434
35 const guess = fmt.parseUnsigned(u8, line_buf[0..line_len], 10) catch {35 const guess = fmt.parseUnsigned(u8, line, 10) catch {
36 try stdout.print("Invalid number.\n");36 try stdout.print("Invalid number.\n");
37 continue;37 continue;
38 };38 };
example/hello_world/hello.zig+1-1
...@@ -2,7 +2,7 @@ const std = @import("std");...@@ -2,7 +2,7 @@ const std = @import("std");
22
3pub fn main() !void {3pub fn main() !void {
4 // If this program is run without stdout attached, exit with an error.4 // If this program is run without stdout attached, exit with an error.
5 var stdout_file = try std.io.getStdOut();5 const stdout_file = try std.io.getStdOut();
6 // If this program encounters pipe failure when printing to stdout, exit6 // If this program encounters pipe failure when printing to stdout, exit
7 // with an error.7 // with an error.
8 try stdout_file.write("Hello, world!\n");8 try stdout_file.write("Hello, world!\n");
src-self-hosted/compilation.zig+2-1
...@@ -55,7 +55,7 @@ pub const ZigCompiler = struct {...@@ -55,7 +55,7 @@ pub const ZigCompiler = struct {
5555
56 var seed_bytes: [@sizeOf(u64)]u8 = undefined;56 var seed_bytes: [@sizeOf(u64)]u8 = undefined;
57 try std.os.getRandomBytes(seed_bytes[0..]);57 try std.os.getRandomBytes(seed_bytes[0..]);
58 const seed = std.mem.readInt(seed_bytes, u64, builtin.Endian.Big);58 const seed = mem.readIntNative(u64, &seed_bytes);
5959
60 return ZigCompiler{60 return ZigCompiler{
61 .loop = loop,61 .loop = loop,
...@@ -300,6 +300,7 @@ pub const Compilation = struct {...@@ -300,6 +300,7 @@ pub const Compilation = struct {
300 UserResourceLimitReached,300 UserResourceLimitReached,
301 InvalidUtf8,301 InvalidUtf8,
302 BadPathName,302 BadPathName,
303 DeviceBusy,
303 };304 };
304305
305 pub const Event = union(enum) {306 pub const Event = union(enum) {
src-self-hosted/libc_installation.zig+1-1
...@@ -172,7 +172,7 @@ pub const LibCInstallation = struct {...@@ -172,7 +172,7 @@ pub const LibCInstallation = struct {
172 try group.call(findNativeStaticLibDir, self, loop);172 try group.call(findNativeStaticLibDir, self, loop);
173 try group.call(findNativeDynamicLinker, self, loop);173 try group.call(findNativeDynamicLinker, self, loop);
174 },174 },
175 builtin.Os.macosx => {175 builtin.Os.macosx, builtin.Os.freebsd => {
176 self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include");176 self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include");
177 },177 },
178 else => @compileError("unimplemented: find libc for this OS"),178 else => @compileError("unimplemented: find libc for this OS"),
src-self-hosted/target.zig+155-151
...@@ -311,160 +311,164 @@ pub const Target = union(enum) {...@@ -311,160 +311,164 @@ pub const Target = union(enum) {
311 pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {311 pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {
312 const env = self.getEnviron();312 const env = self.getEnviron();
313 const arch = self.getArch();313 const arch = self.getArch();
314 switch (env) {314 const os = self.getOs();
315 builtin.Environ.android => {315 switch (os) {
316 if (self.is64bit()) {316 builtin.Os.freebsd => {
317 return "/system/bin/linker64";317 return "/libexec/ld-elf.so.1";
318 } else {
319 return "/system/bin/linker";
320 }
321 },318 },
322 builtin.Environ.gnux32 => {319 builtin.Os.linux => {
323 if (arch == builtin.Arch.x86_64) {320 switch (env) {
324 return "/libx32/ld-linux-x32.so.2";321 builtin.Environ.android => {
322 if (self.is64bit()) {
323 return "/system/bin/linker64";
324 } else {
325 return "/system/bin/linker";
326 }
327 },
328 builtin.Environ.gnux32 => {
329 if (arch == builtin.Arch.x86_64) {
330 return "/libx32/ld-linux-x32.so.2";
331 }
332 },
333 builtin.Environ.musl,
334 builtin.Environ.musleabi,
335 builtin.Environ.musleabihf,
336 => {
337 if (arch == builtin.Arch.x86_64) {
338 return "/lib/ld-musl-x86_64.so.1";
339 }
340 },
341 else => {},
325 }342 }
326 },343 switch (arch) {
327 builtin.Environ.musl,344 builtin.Arch.i386,
328 builtin.Environ.musleabi,345 builtin.Arch.sparc,
329 builtin.Environ.musleabihf,346 builtin.Arch.sparcel,
330 => {347 => return "/lib/ld-linux.so.2",
331 if (arch == builtin.Arch.x86_64) {348
332 return "/lib/ld-musl-x86_64.so.1";349 builtin.Arch.aarch64v8_5a,
350 builtin.Arch.aarch64v8_4a,
351 builtin.Arch.aarch64v8_3a,
352 builtin.Arch.aarch64v8_2a,
353 builtin.Arch.aarch64v8_1a,
354 builtin.Arch.aarch64v8,
355 builtin.Arch.aarch64v8r,
356 builtin.Arch.aarch64v8m_baseline,
357 builtin.Arch.aarch64v8m_mainline,
358 => return "/lib/ld-linux-aarch64.so.1",
359
360 builtin.Arch.aarch64_bev8_5a,
361 builtin.Arch.aarch64_bev8_4a,
362 builtin.Arch.aarch64_bev8_3a,
363 builtin.Arch.aarch64_bev8_2a,
364 builtin.Arch.aarch64_bev8_1a,
365 builtin.Arch.aarch64_bev8,
366 builtin.Arch.aarch64_bev8r,
367 builtin.Arch.aarch64_bev8m_baseline,
368 builtin.Arch.aarch64_bev8m_mainline,
369 => return "/lib/ld-linux-aarch64_be.so.1",
370
371 builtin.Arch.armv8_5a,
372 builtin.Arch.armv8_4a,
373 builtin.Arch.armv8_3a,
374 builtin.Arch.armv8_2a,
375 builtin.Arch.armv8_1a,
376 builtin.Arch.armv8,
377 builtin.Arch.armv8r,
378 builtin.Arch.armv8m_baseline,
379 builtin.Arch.armv8m_mainline,
380 builtin.Arch.armv7,
381 builtin.Arch.armv7em,
382 builtin.Arch.armv7m,
383 builtin.Arch.armv7s,
384 builtin.Arch.armv7k,
385 builtin.Arch.armv7ve,
386 builtin.Arch.armv6,
387 builtin.Arch.armv6m,
388 builtin.Arch.armv6k,
389 builtin.Arch.armv6t2,
390 builtin.Arch.armv5,
391 builtin.Arch.armv5te,
392 builtin.Arch.armv4t,
393 builtin.Arch.thumb,
394 builtin.Arch.armebv8_5a,
395 builtin.Arch.armebv8_4a,
396 builtin.Arch.armebv8_3a,
397 builtin.Arch.armebv8_2a,
398 builtin.Arch.armebv8_1a,
399 builtin.Arch.armebv8,
400 builtin.Arch.armebv8r,
401 builtin.Arch.armebv8m_baseline,
402 builtin.Arch.armebv8m_mainline,
403 builtin.Arch.armebv7,
404 builtin.Arch.armebv7em,
405 builtin.Arch.armebv7m,
406 builtin.Arch.armebv7s,
407 builtin.Arch.armebv7k,
408 builtin.Arch.armebv7ve,
409 builtin.Arch.armebv6,
410 builtin.Arch.armebv6m,
411 builtin.Arch.armebv6k,
412 builtin.Arch.armebv6t2,
413 builtin.Arch.armebv5,
414 builtin.Arch.armebv5te,
415 builtin.Arch.armebv4t,
416 builtin.Arch.thumbeb,
417 => return switch (self.getFloatAbi()) {
418 FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3",
419 else => return "/lib/ld-linux.so.3",
420 },
421
422 builtin.Arch.mipsr6,
423 builtin.Arch.mipselr6,
424 builtin.Arch.mips64r6,
425 builtin.Arch.mips64elr6,
426 => return null,
427
428 builtin.Arch.powerpc => return "/lib/ld.so.1",
429 builtin.Arch.powerpc64 => return "/lib64/ld64.so.2",
430 builtin.Arch.powerpc64le => return "/lib64/ld64.so.2",
431 builtin.Arch.s390x => return "/lib64/ld64.so.1",
432 builtin.Arch.sparcv9 => return "/lib64/ld-linux.so.2",
433 builtin.Arch.x86_64 => return "/lib64/ld-linux-x86-64.so.2",
434
435 builtin.Arch.arc,
436 builtin.Arch.avr,
437 builtin.Arch.bpfel,
438 builtin.Arch.bpfeb,
439 builtin.Arch.hexagon,
440 builtin.Arch.msp430,
441 builtin.Arch.nios2,
442 builtin.Arch.r600,
443 builtin.Arch.amdgcn,
444 builtin.Arch.riscv32,
445 builtin.Arch.riscv64,
446 builtin.Arch.tce,
447 builtin.Arch.tcele,
448 builtin.Arch.xcore,
449 builtin.Arch.nvptx,
450 builtin.Arch.nvptx64,
451 builtin.Arch.le32,
452 builtin.Arch.le64,
453 builtin.Arch.amdil,
454 builtin.Arch.amdil64,
455 builtin.Arch.hsail,
456 builtin.Arch.hsail64,
457 builtin.Arch.spir,
458 builtin.Arch.spir64,
459 builtin.Arch.kalimbav3,
460 builtin.Arch.kalimbav4,
461 builtin.Arch.kalimbav5,
462 builtin.Arch.shave,
463 builtin.Arch.lanai,
464 builtin.Arch.wasm32,
465 builtin.Arch.wasm64,
466 builtin.Arch.renderscript32,
467 builtin.Arch.renderscript64,
468 => return null,
333 }469 }
334 },470 },
335 else => {},471 else => return null,
336 }
337 switch (arch) {
338 builtin.Arch.i386,
339 builtin.Arch.sparc,
340 builtin.Arch.sparcel,
341 => return "/lib/ld-linux.so.2",
342
343 builtin.Arch.aarch64v8_5a,
344 builtin.Arch.aarch64v8_4a,
345 builtin.Arch.aarch64v8_3a,
346 builtin.Arch.aarch64v8_2a,
347 builtin.Arch.aarch64v8_1a,
348 builtin.Arch.aarch64v8,
349 builtin.Arch.aarch64v8r,
350 builtin.Arch.aarch64v8m_baseline,
351 builtin.Arch.aarch64v8m_mainline,
352 => return "/lib/ld-linux-aarch64.so.1",
353
354 builtin.Arch.aarch64_bev8_5a,
355 builtin.Arch.aarch64_bev8_4a,
356 builtin.Arch.aarch64_bev8_3a,
357 builtin.Arch.aarch64_bev8_2a,
358 builtin.Arch.aarch64_bev8_1a,
359 builtin.Arch.aarch64_bev8,
360 builtin.Arch.aarch64_bev8r,
361 builtin.Arch.aarch64_bev8m_baseline,
362 builtin.Arch.aarch64_bev8m_mainline,
363 => return "/lib/ld-linux-aarch64_be.so.1",
364
365 builtin.Arch.armv8_5a,
366 builtin.Arch.armv8_4a,
367 builtin.Arch.armv8_3a,
368 builtin.Arch.armv8_2a,
369 builtin.Arch.armv8_1a,
370 builtin.Arch.armv8,
371 builtin.Arch.armv8r,
372 builtin.Arch.armv8m_baseline,
373 builtin.Arch.armv8m_mainline,
374 builtin.Arch.armv7,
375 builtin.Arch.armv7em,
376 builtin.Arch.armv7m,
377 builtin.Arch.armv7s,
378 builtin.Arch.armv7k,
379 builtin.Arch.armv7ve,
380 builtin.Arch.armv6,
381 builtin.Arch.armv6m,
382 builtin.Arch.armv6k,
383 builtin.Arch.armv6t2,
384 builtin.Arch.armv5,
385 builtin.Arch.armv5te,
386 builtin.Arch.armv4t,
387 builtin.Arch.thumb,
388 => return switch (self.getFloatAbi()) {
389 FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3",
390 else => return "/lib/ld-linux.so.3",
391 },
392
393 builtin.Arch.armebv8_5a,
394 builtin.Arch.armebv8_4a,
395 builtin.Arch.armebv8_3a,
396 builtin.Arch.armebv8_2a,
397 builtin.Arch.armebv8_1a,
398 builtin.Arch.armebv8,
399 builtin.Arch.armebv8r,
400 builtin.Arch.armebv8m_baseline,
401 builtin.Arch.armebv8m_mainline,
402 builtin.Arch.armebv7,
403 builtin.Arch.armebv7em,
404 builtin.Arch.armebv7m,
405 builtin.Arch.armebv7s,
406 builtin.Arch.armebv7k,
407 builtin.Arch.armebv7ve,
408 builtin.Arch.armebv6,
409 builtin.Arch.armebv6m,
410 builtin.Arch.armebv6k,
411 builtin.Arch.armebv6t2,
412 builtin.Arch.armebv5,
413 builtin.Arch.armebv5te,
414 builtin.Arch.armebv4t,
415 builtin.Arch.thumbeb,
416 => return switch (self.getFloatAbi()) {
417 FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3",
418 else => return "/lib/ld-linux.so.3",
419 },
420
421 builtin.Arch.mipsr6,
422 builtin.Arch.mipselr6,
423 builtin.Arch.mips64r6,
424 builtin.Arch.mips64elr6,
425 => return null,
426
427 builtin.Arch.powerpc => return "/lib/ld.so.1",
428 builtin.Arch.powerpc64 => return "/lib64/ld64.so.2",
429 builtin.Arch.powerpc64le => return "/lib64/ld64.so.2",
430 builtin.Arch.s390x => return "/lib64/ld64.so.1",
431 builtin.Arch.sparcv9 => return "/lib64/ld-linux.so.2",
432 builtin.Arch.x86_64 => return "/lib64/ld-linux-x86-64.so.2",
433
434 builtin.Arch.arc,
435 builtin.Arch.avr,
436 builtin.Arch.bpfel,
437 builtin.Arch.bpfeb,
438 builtin.Arch.hexagon,
439 builtin.Arch.msp430,
440 builtin.Arch.nios2,
441 builtin.Arch.r600,
442 builtin.Arch.amdgcn,
443 builtin.Arch.riscv32,
444 builtin.Arch.riscv64,
445 builtin.Arch.tce,
446 builtin.Arch.tcele,
447 builtin.Arch.xcore,
448 builtin.Arch.nvptx,
449 builtin.Arch.nvptx64,
450 builtin.Arch.le32,
451 builtin.Arch.le64,
452 builtin.Arch.amdil,
453 builtin.Arch.amdil64,
454 builtin.Arch.hsail,
455 builtin.Arch.hsail64,
456 builtin.Arch.spir,
457 builtin.Arch.spir64,
458 builtin.Arch.kalimbav3,
459 builtin.Arch.kalimbav4,
460 builtin.Arch.kalimbav5,
461 builtin.Arch.shave,
462 builtin.Arch.lanai,
463 builtin.Arch.wasm32,
464 builtin.Arch.wasm64,
465 builtin.Arch.renderscript32,
466 builtin.Arch.renderscript64,
467 => return null,
468 }472 }
469 }473 }
470474
...@@ -513,6 +517,7 @@ pub const Target = union(enum) {...@@ -513,6 +517,7 @@ pub const Target = union(enum) {
513517
514 builtin.Os.linux,518 builtin.Os.linux,
515 builtin.Os.macosx,519 builtin.Os.macosx,
520 builtin.Os.freebsd,
516 builtin.Os.openbsd,521 builtin.Os.openbsd,
517 builtin.Os.zen,522 builtin.Os.zen,
518 => switch (id) {523 => switch (id) {
...@@ -547,7 +552,6 @@ pub const Target = union(enum) {...@@ -547,7 +552,6 @@ pub const Target = union(enum) {
547 builtin.Os.ananas,552 builtin.Os.ananas,
548 builtin.Os.cloudabi,553 builtin.Os.cloudabi,
549 builtin.Os.dragonfly,554 builtin.Os.dragonfly,
550 builtin.Os.freebsd,
551 builtin.Os.fuchsia,555 builtin.Os.fuchsia,
552 builtin.Os.ios,556 builtin.Os.ios,
553 builtin.Os.kfreebsd,557 builtin.Os.kfreebsd,
src/all_types.hpp+13-1
...@@ -605,7 +605,6 @@ enum CastOp {...@@ -605,7 +605,6 @@ enum CastOp {
605 CastOpFloatToInt,605 CastOpFloatToInt,
606 CastOpBoolToInt,606 CastOpBoolToInt,
607 CastOpResizeSlice,607 CastOpResizeSlice,
608 CastOpBytesToSlice,
609 CastOpNumLitToConcrete,608 CastOpNumLitToConcrete,
610 CastOpErrSet,609 CastOpErrSet,
611 CastOpBitCast,610 CastOpBitCast,
...@@ -1415,6 +1414,7 @@ enum BuiltinFnId {...@@ -1415,6 +1414,7 @@ enum BuiltinFnId {
1415 BuiltinFnIdErrorReturnTrace,1414 BuiltinFnIdErrorReturnTrace,
1416 BuiltinFnIdAtomicRmw,1415 BuiltinFnIdAtomicRmw,
1417 BuiltinFnIdAtomicLoad,1416 BuiltinFnIdAtomicLoad,
1417 BuiltinFnIdBswap,
1418};1418};
14191419
1420struct BuiltinFnEntry {1420struct BuiltinFnEntry {
...@@ -1487,6 +1487,7 @@ enum ZigLLVMFnId {...@@ -1487,6 +1487,7 @@ enum ZigLLVMFnId {
1487 ZigLLVMFnIdFloor,1487 ZigLLVMFnIdFloor,
1488 ZigLLVMFnIdCeil,1488 ZigLLVMFnIdCeil,
1489 ZigLLVMFnIdSqrt,1489 ZigLLVMFnIdSqrt,
1490 ZigLLVMFnIdBswap,
1490};1491};
14911492
1492enum AddSubMul {1493enum AddSubMul {
...@@ -1516,6 +1517,9 @@ struct ZigLLVMFnKey {...@@ -1516,6 +1517,9 @@ struct ZigLLVMFnKey {
1516 uint32_t bit_count;1517 uint32_t bit_count;
1517 bool is_signed;1518 bool is_signed;
1518 } overflow_arithmetic;1519 } overflow_arithmetic;
1520 struct {
1521 uint32_t bit_count;
1522 } bswap;
1519 } data;1523 } data;
1520};1524};
15211525
...@@ -2158,6 +2162,7 @@ enum IrInstructionId {...@@ -2158,6 +2162,7 @@ enum IrInstructionId {
2158 IrInstructionIdMergeErrRetTraces,2162 IrInstructionIdMergeErrRetTraces,
2159 IrInstructionIdMarkErrRetTracePtr,2163 IrInstructionIdMarkErrRetTracePtr,
2160 IrInstructionIdSqrt,2164 IrInstructionIdSqrt,
2165 IrInstructionIdBswap,
2161 IrInstructionIdErrSetCast,2166 IrInstructionIdErrSetCast,
2162 IrInstructionIdToBytes,2167 IrInstructionIdToBytes,
2163 IrInstructionIdFromBytes,2168 IrInstructionIdFromBytes,
...@@ -3251,6 +3256,13 @@ struct IrInstructionCheckRuntimeScope {...@@ -3251,6 +3256,13 @@ struct IrInstructionCheckRuntimeScope {
3251 IrInstruction *is_comptime;3256 IrInstruction *is_comptime;
3252};3257};
32533258
3259struct IrInstructionBswap {
3260 IrInstruction base;
3261
3262 IrInstruction *type;
3263 IrInstruction *op;
3264};
3265
3254static const size_t slice_ptr_index = 0;3266static const size_t slice_ptr_index = 0;
3255static const size_t slice_len_index = 1;3267static const size_t slice_len_index = 1;
32563268
src/analyze.cpp+97-61
...@@ -401,7 +401,8 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {...@@ -401,7 +401,8 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {
401}401}
402402
403ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,403ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
404 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset_in_host, uint32_t host_int_bytes)404 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
405 uint32_t bit_offset_in_host, uint32_t host_int_bytes)
405{406{
406 assert(!type_is_invalid(child_type));407 assert(!type_is_invalid(child_type));
407 assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);408 assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
...@@ -1059,7 +1060,7 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {...@@ -1059,7 +1060,7 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
1059 }1060 }
1060 zig_panic("TODO implement C ABI for x86_64 return types. type '%s'\nSee https://github.com/ziglang/zig/issues/1481",1061 zig_panic("TODO implement C ABI for x86_64 return types. type '%s'\nSee https://github.com/ziglang/zig/issues/1481",
1061 buf_ptr(&fn_type_id->return_type->name));1062 buf_ptr(&fn_type_id->return_type->name));
1062 } else if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb) {1063 } else if (target_is_arm(&g->zig_target)) {
1063 return type_size(g, fn_type_id->return_type) > 16;1064 return type_size(g, fn_type_id->return_type) > 16;
1064 }1065 }
1065 zig_panic("TODO implement C ABI for this architecture. See https://github.com/ziglang/zig/issues/1481");1066 zig_panic("TODO implement C ABI for this architecture. See https://github.com/ziglang/zig/issues/1481");
...@@ -1619,13 +1620,16 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc...@@ -1619,13 +1620,16 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
1619 case ZigTypeIdUnion:1620 case ZigTypeIdUnion:
1620 case ZigTypeIdFn:1621 case ZigTypeIdFn:
1621 case ZigTypeIdPromise:1622 case ZigTypeIdPromise:
1622 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))1623 switch (type_requires_comptime(g, type_entry)) {
1623 return g->builtin_types.entry_invalid;1624 case ReqCompTimeNo:
1624 if (type_requires_comptime(type_entry)) {1625 break;
1625 add_node_error(g, param_node->data.param_decl.type,1626 case ReqCompTimeYes:
1626 buf_sprintf("parameter of type '%s' must be declared comptime",1627 add_node_error(g, param_node->data.param_decl.type,
1627 buf_ptr(&type_entry->name)));1628 buf_sprintf("parameter of type '%s' must be declared comptime",
1628 return g->builtin_types.entry_invalid;1629 buf_ptr(&type_entry->name)));
1630 return g->builtin_types.entry_invalid;
1631 case ReqCompTimeInvalid:
1632 return g->builtin_types.entry_invalid;
1629 }1633 }
1630 break;1634 break;
1631 }1635 }
...@@ -1711,10 +1715,13 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc...@@ -1711,10 +1715,13 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
1711 case ZigTypeIdUnion:1715 case ZigTypeIdUnion:
1712 case ZigTypeIdFn:1716 case ZigTypeIdFn:
1713 case ZigTypeIdPromise:1717 case ZigTypeIdPromise:
1714 if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusZeroBitsKnown)))1718 switch (type_requires_comptime(g, fn_type_id.return_type)) {
1715 return g->builtin_types.entry_invalid;1719 case ReqCompTimeInvalid:
1716 if (type_requires_comptime(fn_type_id.return_type)) {1720 return g->builtin_types.entry_invalid;
1717 return get_generic_fn_type(g, &fn_type_id);1721 case ReqCompTimeYes:
1722 return get_generic_fn_type(g, &fn_type_id);
1723 case ReqCompTimeNo:
1724 break;
1718 }1725 }
1719 break;1726 break;
1720 }1727 }
...@@ -2560,8 +2567,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2560,8 +2567,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2560static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {2567static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2561 assert(struct_type->id == ZigTypeIdStruct);2568 assert(struct_type->id == ZigTypeIdStruct);
25622569
2563 Error err;
2564
2565 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)2570 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
2566 return ErrorSemanticAnalyzeFail;2571 return ErrorSemanticAnalyzeFail;
2567 if (struct_type->data.structure.resolve_status >= ResolveStatusZeroBitsKnown)2572 if (struct_type->data.structure.resolve_status >= ResolveStatusZeroBitsKnown)
...@@ -2619,13 +2624,15 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2619,13 +2624,15 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2619 buf_sprintf("enums, not structs, support field assignment"));2624 buf_sprintf("enums, not structs, support field assignment"));
2620 }2625 }
26212626
2622 if ((err = type_resolve(g, field_type, ResolveStatusZeroBitsKnown))) {2627 switch (type_requires_comptime(g, field_type)) {
2623 struct_type->data.structure.resolve_status = ResolveStatusInvalid;2628 case ReqCompTimeYes:
2624 continue;2629 struct_type->data.structure.requires_comptime = true;
2625 }2630 break;
26262631 case ReqCompTimeInvalid:
2627 if (type_requires_comptime(field_type)) {2632 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2628 struct_type->data.structure.requires_comptime = true;2633 continue;
2634 case ReqCompTimeNo:
2635 break;
2629 }2636 }
26302637
2631 if (!type_has_bits(field_type))2638 if (!type_has_bits(field_type))
...@@ -2674,39 +2681,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {...@@ -2674,39 +2681,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
2674 assert(decl_node->type == NodeTypeContainerDecl);2681 assert(decl_node->type == NodeTypeContainerDecl);
2675 assert(struct_type->di_type);2682 assert(struct_type->di_type);
26762683
2684 size_t field_count = struct_type->data.structure.src_field_count;
2677 if (struct_type->data.structure.layout == ContainerLayoutPacked) {2685 if (struct_type->data.structure.layout == ContainerLayoutPacked) {
2678 struct_type->data.structure.abi_alignment = 1;2686 struct_type->data.structure.abi_alignment = 1;
2679 }2687 for (size_t i = 0; i < field_count; i += 1) {
26802688 TypeStructField *field = &struct_type->data.structure.fields[i];
2681 size_t field_count = struct_type->data.structure.src_field_count;2689 if (field->type_entry != nullptr && type_is_invalid(field->type_entry)) {
2682 for (size_t i = 0; i < field_count; i += 1) {2690 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2683 TypeStructField *field = &struct_type->data.structure.fields[i];2691 break;
26842692 }
2685 // If this assertion trips, look up the call stack. Probably something is
2686 // calling type_resolve with ResolveStatusAlignmentKnown when it should only
2687 // be resolving ResolveStatusZeroBitsKnown
2688 assert(field->type_entry != nullptr);
2689
2690 if (type_is_invalid(field->type_entry)) {
2691 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2692 break;
2693 }2693 }
2694 } else for (size_t i = 0; i < field_count; i += 1) {
2695 TypeStructField *field = &struct_type->data.structure.fields[i];
2696 uint32_t this_field_align;
2697
2698 // TODO If we have no type_entry for the field, we've already failed to
2699 // compile the program correctly. This stage1 compiler needs a deeper
2700 // reworking to make this correct, or we can ignore the problem
2701 // and make sure it is fixed in stage2. This workaround is for when
2702 // there is a false positive of a dependency loop, of alignment depending
2703 // on itself. When this false positive happens we assume a pointer-aligned
2704 // field, which is usually fine but could be incorrectly over-aligned or
2705 // even under-aligned. See https://github.com/ziglang/zig/issues/1512
2706 if (field->type_entry == nullptr) {
2707 this_field_align = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0));
2708 } else {
2709 if (type_is_invalid(field->type_entry)) {
2710 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2711 break;
2712 }
26942713
2695 if (!type_has_bits(field->type_entry))2714 if (!type_has_bits(field->type_entry))
2696 continue;2715 continue;
26972716
2698 // alignment of structs is the alignment of the most-aligned field
2699 if (struct_type->data.structure.layout != ContainerLayoutPacked) {
2700 if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {2717 if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {
2701 struct_type->data.structure.resolve_status = ResolveStatusInvalid;2718 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2702 break;2719 break;
2703 }2720 }
27042721
2705 uint32_t this_field_align = get_abi_alignment(g, field->type_entry);2722 this_field_align = get_abi_alignment(g, field->type_entry);
2706 assert(this_field_align != 0);2723 assert(this_field_align != 0);
2707 if (this_field_align > struct_type->data.structure.abi_alignment) {2724 }
2708 struct_type->data.structure.abi_alignment = this_field_align;2725 // alignment of structs is the alignment of the most-aligned field
2709 }2726 if (this_field_align > struct_type->data.structure.abi_alignment) {
2727 struct_type->data.structure.abi_alignment = this_field_align;
2710 }2728 }
2711 }2729 }
27122730
...@@ -2890,11 +2908,17 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2890,11 +2908,17 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2890 }2908 }
2891 union_field->type_entry = field_type;2909 union_field->type_entry = field_type;
28922910
2893 if (type_requires_comptime(field_type)) {2911 switch (type_requires_comptime(g, field_type)) {
2894 union_type->data.unionation.requires_comptime = true;2912 case ReqCompTimeInvalid:
2913 union_type->data.unionation.is_invalid = true;
2914 continue;
2915 case ReqCompTimeYes:
2916 union_type->data.unionation.requires_comptime = true;
2917 break;
2918 case ReqCompTimeNo:
2919 break;
2895 }2920 }
28962921
2897
2898 if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) {2922 if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) {
2899 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value,2923 ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value,
2900 buf_sprintf("non-enum union field assignment"));2924 buf_sprintf("non-enum union field assignment"));
...@@ -4579,7 +4603,10 @@ void find_libc_include_path(CodeGen *g) {...@@ -4579,7 +4603,10 @@ void find_libc_include_path(CodeGen *g) {
4579 fprintf(stderr, "Unable to determine libc include path. --libc-include-dir");4603 fprintf(stderr, "Unable to determine libc include path. --libc-include-dir");
4580 exit(1);4604 exit(1);
4581 }4605 }
4582 } else if (g->zig_target.os == OsLinux || g->zig_target.os == OsMacOSX) {4606 } else if (g->zig_target.os == OsLinux ||
4607 g->zig_target.os == OsMacOSX ||
4608 g->zig_target.os == OsFreeBSD)
4609 {
4583 g->libc_include_dir = get_posix_libc_include_path();4610 g->libc_include_dir = get_posix_libc_include_path();
4584 } else {4611 } else {
4585 fprintf(stderr, "Unable to determine libc include path.\n"4612 fprintf(stderr, "Unable to determine libc include path.\n"
...@@ -4627,6 +4654,8 @@ void find_libc_lib_path(CodeGen *g) {...@@ -4627,6 +4654,8 @@ void find_libc_lib_path(CodeGen *g) {
46274654
4628 } else if (g->zig_target.os == OsLinux) {4655 } else if (g->zig_target.os == OsLinux) {
4629 g->libc_lib_dir = get_linux_libc_lib_path("crt1.o");4656 g->libc_lib_dir = get_linux_libc_lib_path("crt1.o");
4657 } else if (g->zig_target.os == OsFreeBSD) {
4658 g->libc_lib_dir = buf_create_from_str("/usr/lib");
4630 } else {4659 } else {
4631 zig_panic("Unable to determine libc lib path.");4660 zig_panic("Unable to determine libc lib path.");
4632 }4661 }
...@@ -4639,6 +4668,8 @@ void find_libc_lib_path(CodeGen *g) {...@@ -4639,6 +4668,8 @@ void find_libc_lib_path(CodeGen *g) {
4639 return;4668 return;
4640 } else if (g->zig_target.os == OsLinux) {4669 } else if (g->zig_target.os == OsLinux) {
4641 g->libc_static_lib_dir = get_linux_libc_lib_path("crtbegin.o");4670 g->libc_static_lib_dir = get_linux_libc_lib_path("crtbegin.o");
4671 } else if (g->zig_target.os == OsFreeBSD) {
4672 g->libc_static_lib_dir = buf_create_from_str("/usr/lib");
4642 } else {4673 } else {
4643 zig_panic("Unable to determine libc static lib path.");4674 zig_panic("Unable to determine libc static lib path.");
4644 }4675 }
...@@ -5089,7 +5120,10 @@ bool type_has_bits(ZigType *type_entry) {...@@ -5089,7 +5120,10 @@ bool type_has_bits(ZigType *type_entry) {
5089 return !type_entry->zero_bits;5120 return !type_entry->zero_bits;
5090}5121}
50915122
5092bool type_requires_comptime(ZigType *type_entry) {5123ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
5124 Error err;
5125 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
5126 return ReqCompTimeInvalid;
5093 switch (type_entry->id) {5127 switch (type_entry->id) {
5094 case ZigTypeIdInvalid:5128 case ZigTypeIdInvalid:
5095 case ZigTypeIdOpaque:5129 case ZigTypeIdOpaque:
...@@ -5102,27 +5136,25 @@ bool type_requires_comptime(ZigType *type_entry) {...@@ -5102,27 +5136,25 @@ bool type_requires_comptime(ZigType *type_entry) {
5102 case ZigTypeIdNamespace:5136 case ZigTypeIdNamespace:
5103 case ZigTypeIdBoundFn:5137 case ZigTypeIdBoundFn:
5104 case ZigTypeIdArgTuple:5138 case ZigTypeIdArgTuple:
5105 return true;5139 return ReqCompTimeYes;
5106 case ZigTypeIdArray:5140 case ZigTypeIdArray:
5107 return type_requires_comptime(type_entry->data.array.child_type);5141 return type_requires_comptime(g, type_entry->data.array.child_type);
5108 case ZigTypeIdStruct:5142 case ZigTypeIdStruct:
5109 assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));5143 return type_entry->data.structure.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo;
5110 return type_entry->data.structure.requires_comptime;
5111 case ZigTypeIdUnion:5144 case ZigTypeIdUnion:
5112 assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));5145 return type_entry->data.unionation.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo;
5113 return type_entry->data.unionation.requires_comptime;
5114 case ZigTypeIdOptional:5146 case ZigTypeIdOptional:
5115 return type_requires_comptime(type_entry->data.maybe.child_type);5147 return type_requires_comptime(g, type_entry->data.maybe.child_type);
5116 case ZigTypeIdErrorUnion:5148 case ZigTypeIdErrorUnion:
5117 return type_requires_comptime(type_entry->data.error_union.payload_type);5149 return type_requires_comptime(g, type_entry->data.error_union.payload_type);
5118 case ZigTypeIdPointer:5150 case ZigTypeIdPointer:
5119 if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) {5151 if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) {
5120 return false;5152 return ReqCompTimeNo;
5121 } else {5153 } else {
5122 return type_requires_comptime(type_entry->data.pointer.child_type);5154 return type_requires_comptime(g, type_entry->data.pointer.child_type);
5123 }5155 }
5124 case ZigTypeIdFn:5156 case ZigTypeIdFn:
5125 return type_entry->data.fn.is_generic;5157 return type_entry->data.fn.is_generic ? ReqCompTimeYes : ReqCompTimeNo;
5126 case ZigTypeIdEnum:5158 case ZigTypeIdEnum:
5127 case ZigTypeIdErrorSet:5159 case ZigTypeIdErrorSet:
5128 case ZigTypeIdBool:5160 case ZigTypeIdBool:
...@@ -5131,7 +5163,7 @@ bool type_requires_comptime(ZigType *type_entry) {...@@ -5131,7 +5163,7 @@ bool type_requires_comptime(ZigType *type_entry) {
5131 case ZigTypeIdVoid:5163 case ZigTypeIdVoid:
5132 case ZigTypeIdUnreachable:5164 case ZigTypeIdUnreachable:
5133 case ZigTypeIdPromise:5165 case ZigTypeIdPromise:
5134 return false;5166 return ReqCompTimeNo;
5135 }5167 }
5136 zig_unreachable();5168 zig_unreachable();
5137}5169}
...@@ -6090,6 +6122,8 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {...@@ -6090,6 +6122,8 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {
6090 return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089;6122 return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089;
6091 case ZigLLVMFnIdSqrt:6123 case ZigLLVMFnIdSqrt:
6092 return (uint32_t)(x.data.floating.bit_count) * (uint32_t)2225366385;6124 return (uint32_t)(x.data.floating.bit_count) * (uint32_t)2225366385;
6125 case ZigLLVMFnIdBswap:
6126 return (uint32_t)(x.data.bswap.bit_count) * (uint32_t)3661994335;
6093 case ZigLLVMFnIdOverflowArithmetic:6127 case ZigLLVMFnIdOverflowArithmetic:
6094 return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) +6128 return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) +
6095 ((uint32_t)(x.data.overflow_arithmetic.add_sub_mul) * 31640542) +6129 ((uint32_t)(x.data.overflow_arithmetic.add_sub_mul) * 31640542) +
...@@ -6108,6 +6142,8 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {...@@ -6108,6 +6142,8 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
6108 return a.data.clz.bit_count == b.data.clz.bit_count;6142 return a.data.clz.bit_count == b.data.clz.bit_count;
6109 case ZigLLVMFnIdPopCount:6143 case ZigLLVMFnIdPopCount:
6110 return a.data.pop_count.bit_count == b.data.pop_count.bit_count;6144 return a.data.pop_count.bit_count == b.data.pop_count.bit_count;
6145 case ZigLLVMFnIdBswap:
6146 return a.data.bswap.bit_count == b.data.bswap.bit_count;
6111 case ZigLLVMFnIdFloor:6147 case ZigLLVMFnIdFloor:
6112 case ZigLLVMFnIdCeil:6148 case ZigLLVMFnIdCeil:
6113 case ZigLLVMFnIdSqrt:6149 case ZigLLVMFnIdSqrt:
src/analyze.hpp+7-1
...@@ -87,7 +87,6 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node);...@@ -87,7 +87,6 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node);
87ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);87ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);
88void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc);88void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc);
89AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);89AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);
90bool type_requires_comptime(ZigType *type_entry);
91Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry);90Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry);
92Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status);91Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status);
93void complete_enum(CodeGen *g, ZigType *enum_type);92void complete_enum(CodeGen *g, ZigType *enum_type);
...@@ -216,4 +215,11 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);...@@ -216,4 +215,11 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);
216215
217uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field);216uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field);
218217
218enum ReqCompTime {
219 ReqCompTimeInvalid,
220 ReqCompTimeNo,
221 ReqCompTimeYes,
222};
223ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry);
224
219#endif225#endif
src/buffer.hpp+10
...@@ -181,5 +181,15 @@ static inline Slice<uint8_t> buf_to_slice(Buf *buf) {...@@ -181,5 +181,15 @@ static inline Slice<uint8_t> buf_to_slice(Buf *buf) {
181 return Slice<uint8_t>{reinterpret_cast<uint8_t*>(buf_ptr(buf)), buf_len(buf)};181 return Slice<uint8_t>{reinterpret_cast<uint8_t*>(buf_ptr(buf)), buf_len(buf)};
182}182}
183183
184static 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
184194
185#endif195#endif
src/cache_hash.cpp+4-2
...@@ -352,8 +352,9 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {...@@ -352,8 +352,9 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
352 // if the mtime matches we can trust the digest352 // if the mtime matches we can trust the digest
353 OsFile this_file;353 OsFile this_file;
354 if ((err = os_file_open_r(chf->path, &this_file))) {354 if ((err = os_file_open_r(chf->path, &this_file))) {
355 fprintf(stderr, "Unable to open %s\n: %s", buf_ptr(chf->path), err_str(err));
355 os_file_close(ch->manifest_file);356 os_file_close(ch->manifest_file);
356 return err;357 return ErrorCacheUnavailable;
357 }358 }
358 OsTimeStamp actual_mtime;359 OsTimeStamp actual_mtime;
359 if ((err = os_file_mtime(this_file, &actual_mtime))) {360 if ((err = os_file_mtime(this_file, &actual_mtime))) {
...@@ -392,8 +393,9 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {...@@ -392,8 +393,9 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
392 for (; file_i < input_file_count; file_i += 1) {393 for (; file_i < input_file_count; file_i += 1) {
393 CacheHashFile *chf = &ch->files.at(file_i);394 CacheHashFile *chf = &ch->files.at(file_i);
394 if ((err = populate_file_hash(ch, chf, nullptr))) {395 if ((err = populate_file_hash(ch, chf, nullptr))) {
396 fprintf(stderr, "Unable to hash %s: %s\n", buf_ptr(chf->path), err_str(err));
395 os_file_close(ch->manifest_file);397 os_file_close(ch->manifest_file);
396 return err;398 return ErrorCacheUnavailable;
397 }399 }
398 }400 }
399 return ErrorNone;401 return ErrorNone;
src/codegen.cpp+77-34
...@@ -129,6 +129,11 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out...@@ -129,6 +129,11 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
129 Buf *src_dir = buf_alloc();129 Buf *src_dir = buf_alloc();
130 os_path_split(root_src_path, src_dir, src_basename);130 os_path_split(root_src_path, src_dir, src_basename);
131131
132 if (buf_len(src_basename) == 0) {
133 fprintf(stderr, "Invalid root source path: %s\n", buf_ptr(root_src_path));
134 exit(1);
135 }
136
132 g->root_package = new_package(buf_ptr(src_dir), buf_ptr(src_basename));137 g->root_package = new_package(buf_ptr(src_dir), buf_ptr(src_basename));
133 g->std_package = new_package(buf_ptr(g->zig_std_dir), "index.zig");138 g->std_package = new_package(buf_ptr(g->zig_std_dir), "index.zig");
134 g->root_package->package_table.put(buf_create_from_str("std"), g->std_package);139 g->root_package->package_table.put(buf_create_from_str("std"), g->std_package);
...@@ -1645,7 +1650,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z...@@ -1645,7 +1650,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
1645 zig_unreachable();1650 zig_unreachable();
1646 }1651 }
16471652
1648 if (actual_bits >= wanted_bits && actual_type->id == ZigTypeIdInt &&1653 if (actual_type->id == ZigTypeIdInt &&
1649 !wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed &&1654 !wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed &&
1650 want_runtime_safety)1655 want_runtime_safety)
1651 {1656 {
...@@ -2877,32 +2882,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -2877,32 +2882,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
2877 gen_store_untyped(g, new_len, dest_len_ptr, 0, false);2882 gen_store_untyped(g, new_len, dest_len_ptr, 0, false);
28782883
28792884
2880 return cast_instruction->tmp_ptr;
2881 }
2882 case CastOpBytesToSlice:
2883 {
2884 assert(cast_instruction->tmp_ptr);
2885 assert(wanted_type->id == ZigTypeIdStruct);
2886 assert(wanted_type->data.structure.is_slice);
2887 assert(actual_type->id == ZigTypeIdArray);
2888
2889 ZigType *wanted_pointer_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
2890 ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
2891
2892
2893 size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index;
2894 LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
2895 (unsigned)wanted_ptr_index, "");
2896 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, expr_val, wanted_pointer_type->type_ref, "");
2897 gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false);
2898
2899 size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index;
2900 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
2901 (unsigned)wanted_len_index, "");
2902 LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
2903 actual_type->data.array.len / type_size(g, wanted_child_type), false);
2904 gen_store_untyped(g, len_val, len_ptr, 0, false);
2905
2906 return cast_instruction->tmp_ptr;2885 return cast_instruction->tmp_ptr;
2907 }2886 }
2908 case CastOpIntToFloat:2887 case CastOpIntToFloat:
...@@ -3660,6 +3639,13 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru...@@ -3660,6 +3639,13 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru
3660 AsmOutput *asm_output = asm_expr->output_list.at(i);3639 AsmOutput *asm_output = asm_expr->output_list.at(i);
3661 bool is_return = (asm_output->return_type != nullptr);3640 bool is_return = (asm_output->return_type != nullptr);
3662 assert(*buf_ptr(asm_output->constraint) == '=');3641 assert(*buf_ptr(asm_output->constraint) == '=');
3642 // LLVM uses commas internally to separate different constraints,
3643 // alternative constraints are achieved with pipes.
3644 // We still allow the user to use commas in a way that is similar
3645 // to GCC's inline assembly.
3646 // http://llvm.org/docs/LangRef.html#constraint-codes
3647 buf_replace(asm_output->constraint, ',', '|');
3648
3663 if (is_return) {3649 if (is_return) {
3664 buf_appendf(&constraint_buf, "=%s", buf_ptr(asm_output->constraint) + 1);3650 buf_appendf(&constraint_buf, "=%s", buf_ptr(asm_output->constraint) + 1);
3665 } else {3651 } else {
...@@ -3679,14 +3665,30 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru...@@ -3679,14 +3665,30 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru
3679 }3665 }
3680 for (size_t i = 0; i < asm_expr->input_list.length; i += 1, total_index += 1, param_index += 1) {3666 for (size_t i = 0; i < asm_expr->input_list.length; i += 1, total_index += 1, param_index += 1) {
3681 AsmInput *asm_input = asm_expr->input_list.at(i);3667 AsmInput *asm_input = asm_expr->input_list.at(i);
3668 buf_replace(asm_input->constraint, ',', '|');
3682 IrInstruction *ir_input = instruction->input_list[i];3669 IrInstruction *ir_input = instruction->input_list[i];
3683 buf_append_buf(&constraint_buf, asm_input->constraint);3670 buf_append_buf(&constraint_buf, asm_input->constraint);
3684 if (total_index + 1 < total_constraint_count) {3671 if (total_index + 1 < total_constraint_count) {
3685 buf_append_char(&constraint_buf, ',');3672 buf_append_char(&constraint_buf, ',');
3686 }3673 }
36873674
3688 param_types[param_index] = ir_input->value.type->type_ref;3675 ZigType *const type = ir_input->value.type;
3689 param_values[param_index] = ir_llvm_value(g, ir_input);3676 LLVMTypeRef type_ref = type->type_ref;
3677 LLVMValueRef value_ref = ir_llvm_value(g, ir_input);
3678 // Handle integers of non pot bitsize by widening them.
3679 if (type->id == ZigTypeIdInt) {
3680 const size_t bitsize = type->data.integral.bit_count;
3681 if (bitsize < 8 || !is_power_of_2(bitsize)) {
3682 const bool is_signed = type->data.integral.is_signed;
3683 const size_t wider_bitsize = bitsize < 8 ? 8 : round_to_next_power_of_2(bitsize);
3684 ZigType *const wider_type = get_int_type(g, is_signed, wider_bitsize);
3685 type_ref = wider_type->type_ref;
3686 value_ref = gen_widen_or_shorten(g, false, type, wider_type, value_ref);
3687 }
3688 }
3689
3690 param_types[param_index] = type_ref;
3691 param_values[param_index] = value_ref;
3690 }3692 }
3691 for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1, total_index += 1) {3693 for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1, total_index += 1) {
3692 Buf *clobber_buf = asm_expr->clobber_list.at(i);3694 Buf *clobber_buf = asm_expr->clobber_list.at(i);
...@@ -3705,8 +3707,8 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru...@@ -3705,8 +3707,8 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru
3705 LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, (unsigned)input_and_output_count, false);3707 LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, (unsigned)input_and_output_count, false);
37063708
3707 bool is_volatile = asm_expr->is_volatile || (asm_expr->output_list.length == 0);3709 bool is_volatile = asm_expr->is_volatile || (asm_expr->output_list.length == 0);
3708 LLVMValueRef asm_fn = LLVMConstInlineAsm(function_type, buf_ptr(&llvm_template),3710 LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(&llvm_template), buf_len(&llvm_template),
3709 buf_ptr(&constraint_buf), is_volatile, false);3711 buf_ptr(&constraint_buf), buf_len(&constraint_buf), is_volatile, false, LLVMInlineAsmDialectATT);
37103712
3711 return LLVMBuildCall(g->builder, asm_fn, param_values, (unsigned)input_and_output_count, "");3713 return LLVMBuildCall(g->builder, asm_fn, param_values, (unsigned)input_and_output_count, "");
3712}3714}
...@@ -3786,6 +3788,11 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI...@@ -3786,6 +3788,11 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI
3786 n_args = 1;3788 n_args = 1;
3787 key.id = ZigLLVMFnIdPopCount;3789 key.id = ZigLLVMFnIdPopCount;
3788 key.data.pop_count.bit_count = (uint32_t)int_type->data.integral.bit_count;3790 key.data.pop_count.bit_count = (uint32_t)int_type->data.integral.bit_count;
3791 } else if (fn_id == BuiltinFnIdBswap) {
3792 fn_name = "bswap";
3793 n_args = 1;
3794 key.id = ZigLLVMFnIdBswap;
3795 key.data.bswap.bit_count = (uint32_t)int_type->data.integral.bit_count;
3789 } else {3796 } else {
3790 zig_unreachable();3797 zig_unreachable();
3791 }3798 }
...@@ -5070,6 +5077,29 @@ static LLVMValueRef ir_render_sqrt(CodeGen *g, IrExecutable *executable, IrInstr...@@ -5070,6 +5077,29 @@ static LLVMValueRef ir_render_sqrt(CodeGen *g, IrExecutable *executable, IrInstr
5070 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");5077 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
5071}5078}
50725079
5080static 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
5073static void set_debug_location(CodeGen *g, IrInstruction *instruction) {5103static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
5074 AstNode *source_node = instruction->source_node;5104 AstNode *source_node = instruction->source_node;
5075 Scope *scope = instruction->scope;5105 Scope *scope = instruction->scope;
...@@ -5307,6 +5337,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5307,6 +5337,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5307 return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction);5337 return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction);
5308 case IrInstructionIdSqrt:5338 case IrInstructionIdSqrt:
5309 return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction);5339 return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction);
5340 case IrInstructionIdBswap:
5341 return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction);
5310 }5342 }
5311 zig_unreachable();5343 zig_unreachable();
5312}5344}
...@@ -6258,8 +6290,14 @@ static void do_code_gen(CodeGen *g) {...@@ -6258,8 +6290,14 @@ static void do_code_gen(CodeGen *g) {
6258 }6290 }
6259 if (ir_get_var_is_comptime(var))6291 if (ir_get_var_is_comptime(var))
6260 continue;6292 continue;
6261 if (type_requires_comptime(var->value->type))6293 switch (type_requires_comptime(g, var->value->type)) {
6262 continue;6294 case ReqCompTimeInvalid:
6295 zig_unreachable();
6296 case ReqCompTimeYes:
6297 continue;
6298 case ReqCompTimeNo:
6299 break;
6300 }
62636301
6264 if (var->src_arg_index == SIZE_MAX) {6302 if (var->src_arg_index == SIZE_MAX) {
6265 var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);6303 var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);
...@@ -6723,6 +6761,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -6723,6 +6761,7 @@ static void define_builtin_fns(CodeGen *g) {
6723 create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);6761 create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);
6724 create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);6762 create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
6725 create_builtin_fn(g, BuiltinFnIdThis, "This", 0);6763 create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
6764 create_builtin_fn(g, BuiltinFnIdBswap, "bswap", 2);
6726}6765}
67276766
6728static const char *bool_to_str(bool b) {6767static const char *bool_to_str(bool b) {
...@@ -8149,7 +8188,11 @@ void codegen_build_and_link(CodeGen *g) {...@@ -8149,7 +8188,11 @@ void codegen_build_and_link(CodeGen *g) {
8149 os_path_join(stage1_dir, buf_create_from_str("build"), manifest_dir);8188 os_path_join(stage1_dir, buf_create_from_str("build"), manifest_dir);
81508189
8151 if ((err = check_cache(g, manifest_dir, &digest))) {8190 if ((err = check_cache(g, manifest_dir, &digest))) {
8152 fprintf(stderr, "Unable to check cache: %s\n", err_str(err));8191 if (err == ErrorCacheUnavailable) {
8192 // message already printed
8193 } else {
8194 fprintf(stderr, "Unable to check cache: %s\n", err_str(err));
8195 }
8153 exit(1);8196 exit(1);
8154 }8197 }
81558198
src/error.cpp+1
...@@ -33,6 +33,7 @@ const char *err_str(Error err) {...@@ -33,6 +33,7 @@ const char *err_str(Error err) {
33 case ErrorSharingViolation: return "sharing violation";33 case ErrorSharingViolation: return "sharing violation";
34 case ErrorPipeBusy: return "pipe busy";34 case ErrorPipeBusy: return "pipe busy";
35 case ErrorPrimitiveTypeNotFound: return "primitive type not found";35 case ErrorPrimitiveTypeNotFound: return "primitive type not found";
36 case ErrorCacheUnavailable: return "cache unavailable";
36 }37 }
37 return "(invalid error)";38 return "(invalid error)";
38}39}
src/error.hpp+1
...@@ -35,6 +35,7 @@ enum Error {...@@ -35,6 +35,7 @@ enum Error {
35 ErrorSharingViolation,35 ErrorSharingViolation,
36 ErrorPipeBusy,36 ErrorPipeBusy,
37 ErrorPrimitiveTypeNotFound,37 ErrorPrimitiveTypeNotFound,
38 ErrorCacheUnavailable,
38};39};
3940
40const char *err_str(Error err);41const char *err_str(Error err);
src/ir.cpp+601-206
...@@ -34,6 +34,7 @@ struct IrAnalyze {...@@ -34,6 +34,7 @@ struct IrAnalyze {
34 size_t old_bb_index;34 size_t old_bb_index;
35 size_t instruction_index;35 size_t instruction_index;
36 ZigType *explicit_return_type;36 ZigType *explicit_return_type;
37 AstNode *explicit_return_type_source_node;
37 ZigList<IrInstruction *> src_implicit_return_type_list;38 ZigList<IrInstruction *> src_implicit_return_type_list;
38 IrBasicBlock *const_predecessor_bb;39 IrBasicBlock *const_predecessor_bb;
39};40};
...@@ -66,6 +67,8 @@ enum ConstCastResultId {...@@ -66,6 +67,8 @@ enum ConstCastResultId {
66struct ConstCastOnly;67struct ConstCastOnly;
67struct ConstCastArg {68struct ConstCastArg {
68 size_t arg_index;69 size_t arg_index;
70 ZigType *actual_param_type;
71 ZigType *expected_param_type;
69 ConstCastOnly *child;72 ConstCastOnly *child;
70};73};
7174
...@@ -138,6 +141,11 @@ struct ConstCastErrSetMismatch {...@@ -138,6 +141,11 @@ struct ConstCastErrSetMismatch {
138 ZigList<ErrorTableEntry *> missing_errors;141 ZigList<ErrorTableEntry *> missing_errors;
139};142};
140143
144enum UndefAllowed {
145 UndefOk,
146 UndefBad,
147};
148
141static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);149static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
142static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval);150static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval);
143static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);151static IrInstruction *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);
...@@ -151,12 +159,14 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op...@@ -151,12 +159,14 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op
151static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval);159static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval);
152static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);160static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);
153static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);161static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);
154static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);162static Error buf_read_value_bytes(IrAnalyze *ira, AstNode *source_node, uint8_t *buf, ConstExprValue *val);
155static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);163static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);
156static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,164static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
157 ConstExprValue *out_val, ConstExprValue *ptr_val);165 ConstExprValue *out_val, ConstExprValue *ptr_val);
158static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,166static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,
159 ZigType *dest_type, IrInstruction *dest_type_src);167 ZigType *dest_type, IrInstruction *dest_type_src);
168static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
169static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
160170
161static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {171static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
162 assert(get_src_ptr_type(const_val->type) != nullptr);172 assert(get_src_ptr_type(const_val->type) != nullptr);
...@@ -847,6 +857,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) {...@@ -847,6 +857,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) {
847 return IrInstructionIdSqrt;857 return IrInstructionIdSqrt;
848}858}
849859
860static constexpr IrInstructionId ir_instruction_id(IrInstructionBswap *) {
861 return IrInstructionIdBswap;
862}
863
850static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) {864static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) {
851 return IrInstructionIdCheckRuntimeScope;865 return IrInstructionIdCheckRuntimeScope;
852}866}
...@@ -2696,6 +2710,17 @@ static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *sourc...@@ -2696,6 +2710,17 @@ static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *sourc
2696 return &instruction->base;2710 return &instruction->base;
2697}2711}
26982712
2713static 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
2699static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) {2724static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) {
2700 IrInstructionCheckRuntimeScope *instruction = ir_build_instruction<IrInstructionCheckRuntimeScope>(irb, scope, source_node);2725 IrInstructionCheckRuntimeScope *instruction = ir_build_instruction<IrInstructionCheckRuntimeScope>(irb, scope, source_node);
2701 instruction->scope_is_comptime = scope_is_comptime;2726 instruction->scope_is_comptime = scope_is_comptime;
...@@ -4680,6 +4705,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4680,6 +4705,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4680 IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value);4705 IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value);
4681 return ir_lval_wrap(irb, scope, result, lval);4706 return ir_lval_wrap(irb, scope, result, lval);
4682 }4707 }
4708 case BuiltinFnIdBswap:
4709 {
4710 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4711 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4712 if (arg0_value == irb->codegen->invalid_instruction)
4713 return arg0_value;
4714
4715 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4716 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
4717 if (arg1_value == irb->codegen->invalid_instruction)
4718 return arg1_value;
4719
4720 IrInstruction *result = ir_build_bswap(irb, scope, node, arg0_value, arg1_value);
4721 return ir_lval_wrap(irb, scope, result, lval);
4722 }
4683 }4723 }
4684 zig_unreachable();4724 zig_unreachable();
4685}4725}
...@@ -5530,6 +5570,15 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5530,6 +5570,15 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod
5530 return irb->codegen->invalid_instruction;5570 return irb->codegen->invalid_instruction;
5531 }5571 }
5532 }5572 }
5573
5574 const char modifier = *buf_ptr(asm_output->constraint);
5575 if (modifier != '=') {
5576 add_node_error(irb->codegen, node,
5577 buf_sprintf("invalid modifier starting output constraint for '%s': '%c', only '=' is supported."
5578 " Compiler TODO: see https://github.com/ziglang/zig/issues/215",
5579 buf_ptr(asm_output->asm_symbolic_name), modifier));
5580 return irb->codegen->invalid_instruction;
5581 }
5533 }5582 }
5534 for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1) {5583 for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1) {
5535 AsmInput *asm_input = node->data.asm_expr.input_list.at(i);5584 AsmInput *asm_input = node->data.asm_expr.input_list.at(i);
...@@ -7316,15 +7365,31 @@ static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction,...@@ -7316,15 +7365,31 @@ static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction,
7316 return ir_add_error_node(ira, source_instruction->source_node, msg);7365 return ir_add_error_node(ira, source_instruction->source_node, msg);
7317}7366}
73187367
7368// This function takes a comptime ptr and makes the child const value conform to the type
7369// described by the pointer.
7370static 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
7319static ConstExprValue *ir_const_ptr_pointee(IrAnalyze *ira, ConstExprValue *const_val, AstNode *source_node) {7383static ConstExprValue *ir_const_ptr_pointee(IrAnalyze *ira, ConstExprValue *const_val, AstNode *source_node) {
7384 Error err;
7320 ConstExprValue *val = const_ptr_pointee_unchecked(ira->codegen, const_val);7385 ConstExprValue *val = const_ptr_pointee_unchecked(ira->codegen, const_val);
7321 assert(val != nullptr);7386 assert(val != nullptr);
7322 assert(const_val->type->id == ZigTypeIdPointer);7387 assert(const_val->type->id == ZigTypeIdPointer);
7323 ZigType *expected_type = const_val->type->data.pointer.child_type;7388 ZigType *expected_type = const_val->type->data.pointer.child_type;
7324 if (!types_have_same_zig_comptime_repr(val->type, expected_type)) {7389 if (!types_have_same_zig_comptime_repr(val->type, expected_type)) {
7325 ir_add_error_node(ira, source_node,7390 if ((err = eval_comptime_ptr_reinterpret(ira, source_node, const_val)))
7326 buf_sprintf("TODO handle comptime reinterpreted pointer. See https://github.com/ziglang/zig/issues/955"));7391 return nullptr;
7327 return nullptr;7392 return const_ptr_pointee_unchecked(ira->codegen, const_val);
7328 }7393 }
7329 return val;7394 return val;
7330}7395}
...@@ -8063,15 +8128,153 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc...@@ -8063,15 +8128,153 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
8063 return false;8128 return false;
8064 }8129 }
80658130
8066 ConstExprValue *const_val = &instruction->value;8131 ConstExprValue *const_val = ir_resolve_const(ira, instruction, UndefBad);
8067 assert(const_val->special != ConstValSpecialRuntime);8132 assert(const_val != nullptr);
8133
8134 bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt);
8135 bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || const_val->type->id == ZigTypeIdComptimeFloat);
80688136
8069 bool const_val_is_int = (const_val->type->id == ZigTypeIdInt ||
8070 const_val->type->id == ZigTypeIdComptimeInt);
8071 bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat ||
8072 const_val->type->id == ZigTypeIdComptimeFloat);
8073 if (other_type->id == ZigTypeIdFloat) {8137 if (other_type->id == ZigTypeIdFloat) {
8074 return true;8138 if (const_val->type->id == ZigTypeIdComptimeInt || const_val->type->id == ZigTypeIdComptimeFloat) {
8139 return true;
8140 }
8141 if (const_val->type->id == ZigTypeIdInt) {
8142 BigFloat tmp_bf;
8143 bigfloat_init_bigint(&tmp_bf, &const_val->data.x_bigint);
8144 BigFloat orig_bf;
8145 switch (other_type->data.floating.bit_count) {
8146 case 16: {
8147 float16_t tmp = bigfloat_to_f16(&tmp_bf);
8148 bigfloat_init_16(&orig_bf, tmp);
8149 break;
8150 }
8151 case 32: {
8152 float tmp = bigfloat_to_f32(&tmp_bf);
8153 bigfloat_init_32(&orig_bf, tmp);
8154 break;
8155 }
8156 case 64: {
8157 double tmp = bigfloat_to_f64(&tmp_bf);
8158 bigfloat_init_64(&orig_bf, tmp);
8159 break;
8160 }
8161 case 80:
8162 zig_panic("TODO");
8163 case 128: {
8164 float128_t tmp = bigfloat_to_f128(&tmp_bf);
8165 bigfloat_init_128(&orig_bf, tmp);
8166 break;
8167 }
8168 default:
8169 zig_unreachable();
8170 }
8171 BigInt orig_bi;
8172 bigint_init_bigfloat(&orig_bi, &orig_bf);
8173 if (bigint_cmp(&orig_bi, &const_val->data.x_bigint) == CmpEQ) {
8174 return true;
8175 }
8176 Buf *val_buf = buf_alloc();
8177 bigint_append_buf(val_buf, &const_val->data.x_bigint, 10);
8178 ir_add_error(ira, instruction,
8179 buf_sprintf("integer value %s has no representation in type '%s'",
8180 buf_ptr(val_buf),
8181 buf_ptr(&other_type->name)));
8182 return false;
8183 }
8184 if (other_type->data.floating.bit_count >= const_val->type->data.floating.bit_count) {
8185 return true;
8186 }
8187 switch (other_type->data.floating.bit_count) {
8188 case 16:
8189 switch (const_val->type->data.floating.bit_count) {
8190 case 32: {
8191 float16_t tmp = zig_double_to_f16(const_val->data.x_f32);
8192 float orig = zig_f16_to_double(tmp);
8193 if (const_val->data.x_f32 == orig) {
8194 return true;
8195 }
8196 break;
8197 }
8198 case 64: {
8199 float16_t tmp = zig_double_to_f16(const_val->data.x_f64);
8200 double orig = zig_f16_to_double(tmp);
8201 if (const_val->data.x_f64 == orig) {
8202 return true;
8203 }
8204 break;
8205 }
8206 case 80:
8207 zig_panic("TODO");
8208 case 128: {
8209 float16_t tmp = f128M_to_f16(&const_val->data.x_f128);
8210 float128_t orig;
8211 f16_to_f128M(tmp, &orig);
8212 if (f128M_eq(&orig, &const_val->data.x_f128)) {
8213 return true;
8214 }
8215 break;
8216 }
8217 default:
8218 zig_unreachable();
8219 }
8220 break;
8221 case 32:
8222 switch (const_val->type->data.floating.bit_count) {
8223 case 64: {
8224 float tmp = const_val->data.x_f64;
8225 double orig = tmp;
8226 if (const_val->data.x_f64 == orig) {
8227 return true;
8228 }
8229 break;
8230 }
8231 case 80:
8232 zig_panic("TODO");
8233 case 128: {
8234 float32_t tmp = f128M_to_f32(&const_val->data.x_f128);
8235 float128_t orig;
8236 f32_to_f128M(tmp, &orig);
8237 if (f128M_eq(&orig, &const_val->data.x_f128)) {
8238 return true;
8239 }
8240 break;
8241 }
8242 default:
8243 zig_unreachable();
8244 }
8245 break;
8246 case 64:
8247 switch (const_val->type->data.floating.bit_count) {
8248 case 80:
8249 zig_panic("TODO");
8250 case 128: {
8251 float64_t tmp = f128M_to_f64(&const_val->data.x_f128);
8252 float128_t orig;
8253 f64_to_f128M(tmp, &orig);
8254 if (f128M_eq(&orig, &const_val->data.x_f128)) {
8255 return true;
8256 }
8257 break;
8258 }
8259 default:
8260 zig_unreachable();
8261 }
8262 break;
8263 case 80:
8264 assert(const_val->type->data.floating.bit_count == 128);
8265 zig_panic("TODO");
8266 case 128:
8267 return true;
8268 default:
8269 zig_unreachable();
8270 }
8271 Buf *val_buf = buf_alloc();
8272 float_append_buf(val_buf, const_val);
8273 ir_add_error(ira, instruction,
8274 buf_sprintf("cast of value %s to type '%s' loses information",
8275 buf_ptr(val_buf),
8276 buf_ptr(&other_type->name)));
8277 return false;
8075 } else if (other_type->id == ZigTypeIdInt && const_val_is_int) {8278 } else if (other_type->id == ZigTypeIdInt && const_val_is_int) {
8076 if (!other_type->data.integral.is_signed && const_val->data.x_bigint.is_negative) {8279 if (!other_type->data.integral.is_signed && const_val->data.x_bigint.is_negative) {
8077 Buf *val_buf = buf_alloc();8280 Buf *val_buf = buf_alloc();
...@@ -8484,6 +8687,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -8484,6 +8687,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
8484 if (arg_child.id != ConstCastResultIdOk) {8687 if (arg_child.id != ConstCastResultIdOk) {
8485 result.id = ConstCastResultIdFnArg;8688 result.id = ConstCastResultIdFnArg;
8486 result.data.fn_arg.arg_index = i;8689 result.data.fn_arg.arg_index = i;
8690 result.data.fn_arg.actual_param_type = actual_param_info->type;
8691 result.data.fn_arg.expected_param_type = expected_param_info->type;
8487 result.data.fn_arg.child = allocate_nonzero<ConstCastOnly>(1);8692 result.data.fn_arg.child = allocate_nonzero<ConstCastOnly>(1);
8488 *result.data.fn_arg.child = arg_child;8693 *result.data.fn_arg.child = arg_child;
8489 return result;8694 return result;
...@@ -9134,7 +9339,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_...@@ -9134,7 +9339,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
9134 const_val->type = new_type;9339 const_val->type = new_type;
9135 break;9340 break;
9136 case CastOpResizeSlice:9341 case CastOpResizeSlice:
9137 case CastOpBytesToSlice:
9138 // can't do it9342 // can't do it
9139 zig_unreachable();9343 zig_unreachable();
9140 case CastOpIntToFloat:9344 case CastOpIntToFloat:
...@@ -9191,7 +9395,7 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -9191,7 +9395,7 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst
9191 ZigType *wanted_type, CastOp cast_op, bool need_alloca)9395 ZigType *wanted_type, CastOp cast_op, bool need_alloca)
9192{9396{
9193 if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) &&9397 if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) &&
9194 cast_op != CastOpResizeSlice && cast_op != CastOpBytesToSlice)9398 cast_op != CastOpResizeSlice)
9195 {9399 {
9196 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,9400 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
9197 source_instr->source_node, wanted_type);9401 source_instr->source_node, wanted_type);
...@@ -9453,11 +9657,6 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio...@@ -9453,11 +9657,6 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio
9453 return const_instr;9657 return const_instr;
9454}9658}
94559659
9456enum UndefAllowed {
9457 UndefOk,
9458 UndefBad,
9459};
9460
9461static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) {9660static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) {
9462 switch (value->value.special) {9661 switch (value->value.special) {
9463 case ConstValSpecialStatic:9662 case ConstValSpecialStatic:
...@@ -10014,7 +10213,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour...@@ -10014,7 +10213,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
10014 return ira->codegen->invalid_instruction;10213 return ira->codegen->invalid_instruction;
10015 }10214 }
1001610215
10017 assert(actual_type->id == ZigTypeIdInt);10216 assert(actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt);
1001810217
10019 if (instr_is_comptime(target)) {10218 if (instr_is_comptime(target)) {
10020 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);10219 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
...@@ -10334,6 +10533,15 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa...@@ -10334,6 +10533,15 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
10334 }10533 }
10335 break;10534 break;
10336 }10535 }
10536 case ConstCastResultIdFnArg: {
10537 ErrorMsg *msg = add_error_note(ira->codegen, parent_msg, source_node,
10538 buf_sprintf("parameter %" ZIG_PRI_usize ": '%s' cannot cast into '%s'",
10539 cast_result->data.fn_arg.arg_index,
10540 buf_ptr(&cast_result->data.fn_arg.actual_param_type->name),
10541 buf_ptr(&cast_result->data.fn_arg.expected_param_type->name)));
10542 report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg);
10543 break;
10544 }
10337 case ConstCastResultIdFnAlign: // TODO10545 case ConstCastResultIdFnAlign: // TODO
10338 case ConstCastResultIdFnCC: // TODO10546 case ConstCastResultIdFnCC: // TODO
10339 case ConstCastResultIdFnVarArgs: // TODO10547 case ConstCastResultIdFnVarArgs: // TODO
...@@ -10341,7 +10549,6 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa...@@ -10341,7 +10549,6 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
10341 case ConstCastResultIdFnReturnType: // TODO10549 case ConstCastResultIdFnReturnType: // TODO
10342 case ConstCastResultIdFnArgCount: // TODO10550 case ConstCastResultIdFnArgCount: // TODO
10343 case ConstCastResultIdFnGenericArgCount: // TODO10551 case ConstCastResultIdFnGenericArgCount: // TODO
10344 case ConstCastResultIdFnArg: // TODO
10345 case ConstCastResultIdFnArgNoAlias: // TODO10552 case ConstCastResultIdFnArgNoAlias: // TODO
10346 case ConstCastResultIdUnresolvedInferredErrSet: // TODO10553 case ConstCastResultIdUnresolvedInferredErrSet: // TODO
10347 case ConstCastResultIdAsyncAllocatorType: // TODO10554 case ConstCastResultIdAsyncAllocatorType: // TODO
...@@ -10370,6 +10577,121 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10370,6 +10577,121 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10370 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);10577 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
10371 }10578 }
1037210579
10580 // cast from T to ?T
10581 // note that the *T to ?*T case is handled via the "ConstCastOnly" mechanism
10582 if (wanted_type->id == ZigTypeIdOptional) {
10583 ZigType *wanted_child_type = wanted_type->data.maybe.child_type;
10584 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,
10585 false).id == ConstCastResultIdOk)
10586 {
10587 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
10588 } else if (actual_type->id == ZigTypeIdComptimeInt ||
10589 actual_type->id == ZigTypeIdComptimeFloat)
10590 {
10591 if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {
10592 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
10593 } else {
10594 return ira->codegen->invalid_instruction;
10595 }
10596 } else if (
10597 wanted_child_type->id == ZigTypeIdPointer &&
10598 wanted_child_type->data.pointer.ptr_len == PtrLenUnknown &&
10599 actual_type->id == ZigTypeIdPointer &&
10600 actual_type->data.pointer.ptr_len == PtrLenSingle &&
10601 actual_type->data.pointer.child_type->id == ZigTypeIdArray)
10602 {
10603 if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
10604 return ira->codegen->invalid_instruction;
10605 if ((err = type_resolve(ira->codegen, wanted_child_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
10606 return ira->codegen->invalid_instruction;
10607 if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_child_type) &&
10608 types_match_const_cast_only(ira, wanted_child_type->data.pointer.child_type,
10609 actual_type->data.pointer.child_type->data.array.child_type, source_node,
10610 !wanted_child_type->data.pointer.is_const).id == ConstCastResultIdOk)
10611 {
10612 IrInstruction *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value,
10613 wanted_child_type);
10614 if (type_is_invalid(cast1->value.type))
10615 return ira->codegen->invalid_instruction;
10616 return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type);
10617 }
10618 }
10619 }
10620
10621 // T to E!T
10622 if (wanted_type->id == ZigTypeIdErrorUnion) {
10623 if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type,
10624 source_node, false).id == ConstCastResultIdOk)
10625 {
10626 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
10627 } else if (actual_type->id == ZigTypeIdComptimeInt ||
10628 actual_type->id == ZigTypeIdComptimeFloat)
10629 {
10630 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) {
10631 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
10632 } else {
10633 return ira->codegen->invalid_instruction;
10634 }
10635 }
10636 }
10637
10638 // cast from T to E!?T
10639 if (wanted_type->id == ZigTypeIdErrorUnion &&
10640 wanted_type->data.error_union.payload_type->id == ZigTypeIdOptional &&
10641 actual_type->id != ZigTypeIdOptional)
10642 {
10643 ZigType *wanted_child_type = wanted_type->data.error_union.payload_type->data.maybe.child_type;
10644 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node, false).id == ConstCastResultIdOk ||
10645 actual_type->id == ZigTypeIdNull ||
10646 actual_type->id == ZigTypeIdComptimeInt ||
10647 actual_type->id == ZigTypeIdComptimeFloat)
10648 {
10649 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value);
10650 if (type_is_invalid(cast1->value.type))
10651 return ira->codegen->invalid_instruction;
10652
10653 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
10654 if (type_is_invalid(cast2->value.type))
10655 return ira->codegen->invalid_instruction;
10656
10657 return cast2;
10658 }
10659 }
10660
10661
10662 // cast from comptime-known number to another number type
10663 if (instr_is_comptime(value) &&
10664 (actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt ||
10665 actual_type->id == ZigTypeIdFloat || actual_type->id == ZigTypeIdComptimeFloat) &&
10666 (wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt ||
10667 wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat))
10668 {
10669 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {
10670 if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) {
10671 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10672 if (actual_type->id == ZigTypeIdComptimeInt || actual_type->id == ZigTypeIdInt) {
10673 bigint_init_bigint(&result->value.data.x_bigint, &value->value.data.x_bigint);
10674 } else {
10675 float_init_bigint(&result->value.data.x_bigint, &value->value);
10676 }
10677 return result;
10678 } else if (wanted_type->id == ZigTypeIdComptimeFloat || wanted_type->id == ZigTypeIdFloat) {
10679 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10680 if (actual_type->id == ZigTypeIdComptimeInt || actual_type->id == ZigTypeIdInt) {
10681 BigFloat bf;
10682 bigfloat_init_bigint(&bf, &value->value.data.x_bigint);
10683 float_init_bigfloat(&result->value, &bf);
10684 } else {
10685 float_init_float(&result->value, &value->value);
10686 }
10687 return result;
10688 }
10689 zig_unreachable();
10690 } else {
10691 return ira->codegen->invalid_instruction;
10692 }
10693 }
10694
10373 // widening conversion10695 // widening conversion
10374 if (wanted_type->id == ZigTypeIdInt &&10696 if (wanted_type->id == ZigTypeIdInt &&
10375 actual_type->id == ZigTypeIdInt &&10697 actual_type->id == ZigTypeIdInt &&
...@@ -10472,47 +10794,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10472,47 +10794,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10472 }10794 }
1047310795
1047410796
10475 // cast from T to ?T
10476 // note that the *T to ?*T case is handled via the "ConstCastOnly" mechanism
10477 if (wanted_type->id == ZigTypeIdOptional) {
10478 ZigType *wanted_child_type = wanted_type->data.maybe.child_type;
10479 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,
10480 false).id == ConstCastResultIdOk)
10481 {
10482 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
10483 } else if (actual_type->id == ZigTypeIdComptimeInt ||
10484 actual_type->id == ZigTypeIdComptimeFloat)
10485 {
10486 if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {
10487 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
10488 } else {
10489 return ira->codegen->invalid_instruction;
10490 }
10491 } else if (
10492 wanted_child_type->id == ZigTypeIdPointer &&
10493 wanted_child_type->data.pointer.ptr_len == PtrLenUnknown &&
10494 actual_type->id == ZigTypeIdPointer &&
10495 actual_type->data.pointer.ptr_len == PtrLenSingle &&
10496 actual_type->data.pointer.child_type->id == ZigTypeIdArray)
10497 {
10498 if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
10499 return ira->codegen->invalid_instruction;
10500 if ((err = type_resolve(ira->codegen, wanted_child_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
10501 return ira->codegen->invalid_instruction;
10502 if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_child_type) &&
10503 types_match_const_cast_only(ira, wanted_child_type->data.pointer.child_type,
10504 actual_type->data.pointer.child_type->data.array.child_type, source_node,
10505 !wanted_child_type->data.pointer.is_const).id == ConstCastResultIdOk)
10506 {
10507 IrInstruction *cast1 = ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value,
10508 wanted_child_type);
10509 if (type_is_invalid(cast1->value.type))
10510 return ira->codegen->invalid_instruction;
10511 return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type);
10512 }
10513 }
10514 }
10515
10516 // cast from null literal to maybe type10797 // cast from null literal to maybe type
10517 if (wanted_type->id == ZigTypeIdOptional &&10798 if (wanted_type->id == ZigTypeIdOptional &&
10518 actual_type->id == ZigTypeIdNull)10799 actual_type->id == ZigTypeIdNull)
...@@ -10520,23 +10801,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10520,23 +10801,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10520 return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type);10801 return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type);
10521 }10802 }
1052210803
10523 // cast from child type of error type to error type
10524 if (wanted_type->id == ZigTypeIdErrorUnion) {
10525 if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type,
10526 source_node, false).id == ConstCastResultIdOk)
10527 {
10528 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
10529 } else if (actual_type->id == ZigTypeIdComptimeInt ||
10530 actual_type->id == ZigTypeIdComptimeFloat)
10531 {
10532 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) {
10533 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type);
10534 } else {
10535 return ira->codegen->invalid_instruction;
10536 }
10537 }
10538 }
10539
10540 // cast from [N]T to E![]const T10804 // cast from [N]T to E![]const T
10541 if (wanted_type->id == ZigTypeIdErrorUnion &&10805 if (wanted_type->id == ZigTypeIdErrorUnion &&
10542 is_slice(wanted_type->data.error_union.payload_type) &&10806 is_slice(wanted_type->data.error_union.payload_type) &&
...@@ -10568,54 +10832,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10568,54 +10832,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10568 return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type);10832 return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type);
10569 }10833 }
1057010834
10571 // cast from T to E!?T
10572 if (wanted_type->id == ZigTypeIdErrorUnion &&
10573 wanted_type->data.error_union.payload_type->id == ZigTypeIdOptional &&
10574 actual_type->id != ZigTypeIdOptional)
10575 {
10576 ZigType *wanted_child_type = wanted_type->data.error_union.payload_type->data.maybe.child_type;
10577 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node, false).id == ConstCastResultIdOk ||
10578 actual_type->id == ZigTypeIdNull ||
10579 actual_type->id == ZigTypeIdComptimeInt ||
10580 actual_type->id == ZigTypeIdComptimeFloat)
10581 {
10582 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value);
10583 if (type_is_invalid(cast1->value.type))
10584 return ira->codegen->invalid_instruction;
10585
10586 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
10587 if (type_is_invalid(cast2->value.type))
10588 return ira->codegen->invalid_instruction;
10589
10590 return cast2;
10591 }
10592 }
10593
10594 // cast from number literal to another type
10595 if (actual_type->id == ZigTypeIdComptimeFloat ||
10596 actual_type->id == ZigTypeIdComptimeInt)
10597 {
10598 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {
10599 CastOp op;
10600 if ((actual_type->id == ZigTypeIdComptimeFloat &&
10601 wanted_type->id == ZigTypeIdFloat) ||
10602 (actual_type->id == ZigTypeIdComptimeInt &&
10603 wanted_type->id == ZigTypeIdInt))
10604 {
10605 op = CastOpNumLitToConcrete;
10606 } else if (wanted_type->id == ZigTypeIdInt) {
10607 op = CastOpFloatToInt;
10608 } else if (wanted_type->id == ZigTypeIdFloat) {
10609 op = CastOpIntToFloat;
10610 } else {
10611 zig_unreachable();
10612 }
10613 return ir_resolve_cast(ira, source_instr, value, wanted_type, op, false);
10614 } else {
10615 return ira->codegen->invalid_instruction;
10616 }
10617 }
10618
10619 // cast from typed number to integer or float literal.10835 // cast from typed number to integer or float literal.
10620 // works when the number is known at compile time10836 // works when the number is known at compile time
10621 if (instr_is_comptime(value) &&10837 if (instr_is_comptime(value) &&
...@@ -11014,8 +11230,12 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio...@@ -11014,8 +11230,12 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio
11014 return ir_unreach_error(ira);11230 return ir_unreach_error(ira);
1101511231
11016 IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->explicit_return_type);11232 IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->explicit_return_type);
11017 if (type_is_invalid(casted_value->value.type))11233 if (type_is_invalid(casted_value->value.type) && ira->explicit_return_type_source_node != nullptr) {
11234 ErrorMsg *msg = ira->codegen->errors.last();
11235 add_error_note(ira->codegen, msg, ira->explicit_return_type_source_node,
11236 buf_sprintf("return type declared here"));
11018 return ir_unreach_error(ira);11237 return ir_unreach_error(ira);
11238 }
1101911239
11020 if (casted_value->value.special == ConstValSpecialRuntime &&11240 if (casted_value->value.special == ConstValSpecialRuntime &&
11021 casted_value->value.type->id == ZigTypeIdPointer &&11241 casted_value->value.type->id == ZigTypeIdPointer &&
...@@ -11114,7 +11334,6 @@ static bool optional_value_is_null(ConstExprValue *val) {...@@ -11114,7 +11334,6 @@ static bool optional_value_is_null(ConstExprValue *val) {
11114}11334}
1111511335
11116static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {11336static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
11117 Error err;
11118 IrInstruction *op1 = bin_op_instruction->op1->child;11337 IrInstruction *op1 = bin_op_instruction->op1->child;
11119 if (type_is_invalid(op1->value.type))11338 if (type_is_invalid(op1->value.type))
11120 return ira->codegen->invalid_instruction;11339 return ira->codegen->invalid_instruction;
...@@ -11308,10 +11527,19 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11308,10 +11527,19 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11308 if (casted_op2 == ira->codegen->invalid_instruction)11527 if (casted_op2 == ira->codegen->invalid_instruction)
11309 return ira->codegen->invalid_instruction;11528 return ira->codegen->invalid_instruction;
1131011529
11311 if ((err = type_resolve(ira->codegen, resolved_type, ResolveStatusZeroBitsKnown)))11530 bool requires_comptime;
11312 return ira->codegen->invalid_instruction;11531 switch (type_requires_comptime(ira->codegen, resolved_type)) {
11532 case ReqCompTimeYes:
11533 requires_comptime = true;
11534 break;
11535 case ReqCompTimeNo:
11536 requires_comptime = false;
11537 break;
11538 case ReqCompTimeInvalid:
11539 return ira->codegen->invalid_instruction;
11540 }
1131311541
11314 bool one_possible_value = !type_requires_comptime(resolved_type) && !type_has_bits(resolved_type);11542 bool one_possible_value = !requires_comptime && !type_has_bits(resolved_type);
11315 if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {11543 if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {
11316 ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad);11544 ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad);
11317 if (op1_val == nullptr)11545 if (op1_val == nullptr)
...@@ -12244,42 +12472,42 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12244,42 +12472,42 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12244 ZigType *result_type = casted_init_value->value.type;12472 ZigType *result_type = casted_init_value->value.type;
12245 if (type_is_invalid(result_type)) {12473 if (type_is_invalid(result_type)) {
12246 result_type = ira->codegen->builtin_types.entry_invalid;12474 result_type = ira->codegen->builtin_types.entry_invalid;
12247 } else {12475 } else if (result_type->id == ZigTypeIdUnreachable || result_type->id == ZigTypeIdOpaque) {
12248 if ((err = type_resolve(ira->codegen, result_type, ResolveStatusZeroBitsKnown))) {12476 ir_add_error_node(ira, source_node,
12249 result_type = ira->codegen->builtin_types.entry_invalid;12477 buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name)));
12250 }12478 result_type = ira->codegen->builtin_types.entry_invalid;
12251 }12479 }
1225212480
12253 if (!type_is_invalid(result_type)) {12481 switch (type_requires_comptime(ira->codegen, result_type)) {
12254 if (result_type->id == ZigTypeIdUnreachable ||12482 case ReqCompTimeInvalid:
12255 result_type->id == ZigTypeIdOpaque)12483 result_type = ira->codegen->builtin_types.entry_invalid;
12256 {12484 break;
12485 case ReqCompTimeYes: {
12486 var_class_requires_const = true;
12487 if (!var->gen_is_const && !is_comptime_var) {
12257 ir_add_error_node(ira, source_node,12488 ir_add_error_node(ira, source_node,
12258 buf_sprintf("variable of type '%s' not allowed", buf_ptr(&result_type->name)));12489 buf_sprintf("variable of type '%s' must be const or comptime",
12490 buf_ptr(&result_type->name)));
12259 result_type = ira->codegen->builtin_types.entry_invalid;12491 result_type = ira->codegen->builtin_types.entry_invalid;
12260 } else if (type_requires_comptime(result_type)) {12492 }
12493 break;
12494 }
12495 case ReqCompTimeNo:
12496 if (casted_init_value->value.special == ConstValSpecialStatic &&
12497 casted_init_value->value.type->id == ZigTypeIdFn &&
12498 casted_init_value->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
12499 casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways)
12500 {
12261 var_class_requires_const = true;12501 var_class_requires_const = true;
12262 if (!var->gen_is_const && !is_comptime_var) {12502 if (!var->src_is_const && !is_comptime_var) {
12263 ir_add_error_node(ira, source_node,12503 ErrorMsg *msg = ir_add_error_node(ira, source_node,
12264 buf_sprintf("variable of type '%s' must be const or comptime",12504 buf_sprintf("functions marked inline must be stored in const or comptime var"));
12265 buf_ptr(&result_type->name)));12505 AstNode *proto_node = casted_init_value->value.data.x_ptr.data.fn.fn_entry->proto_node;
12506 add_error_note(ira->codegen, msg, proto_node, buf_sprintf("declared here"));
12266 result_type = ira->codegen->builtin_types.entry_invalid;12507 result_type = ira->codegen->builtin_types.entry_invalid;
12267 }12508 }
12268 } else {
12269 if (casted_init_value->value.special == ConstValSpecialStatic &&
12270 casted_init_value->value.type->id == ZigTypeIdFn &&
12271 casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways)
12272 {
12273 var_class_requires_const = true;
12274 if (!var->src_is_const && !is_comptime_var) {
12275 ErrorMsg *msg = ir_add_error_node(ira, source_node,
12276 buf_sprintf("functions marked inline must be stored in const or comptime var"));
12277 AstNode *proto_node = casted_init_value->value.data.x_ptr.data.fn.fn_entry->proto_node;
12278 add_error_note(ira->codegen, msg, proto_node, buf_sprintf("declared here"));
12279 result_type = ira->codegen->builtin_types.entry_invalid;
12280 }
12281 }
12282 }12509 }
12510 break;
12283 }12511 }
1228412512
12285 if (var->value->type != nullptr && !is_comptime_var) {12513 if (var->value->type != nullptr && !is_comptime_var) {
...@@ -12750,10 +12978,15 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod...@@ -12750,10 +12978,15 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
12750 }12978 }
1275112979
12752 if (!comptime_arg) {12980 if (!comptime_arg) {
12753 if (type_requires_comptime(casted_arg->value.type)) {12981 switch (type_requires_comptime(ira->codegen, casted_arg->value.type)) {
12982 case ReqCompTimeYes:
12754 ir_add_error(ira, casted_arg,12983 ir_add_error(ira, casted_arg,
12755 buf_sprintf("parameter of type '%s' requires comptime", buf_ptr(&casted_arg->value.type->name)));12984 buf_sprintf("parameter of type '%s' requires comptime", buf_ptr(&casted_arg->value.type->name)));
12756 return false;12985 return false;
12986 case ReqCompTimeInvalid:
12987 return false;
12988 case ReqCompTimeNo:
12989 break;
12757 }12990 }
1275812991
12759 casted_args[fn_type_id->param_count] = casted_arg;12992 casted_args[fn_type_id->param_count] = casted_arg;
...@@ -13226,12 +13459,15 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13226,12 +13459,15 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13226 inst_fn_type_id.return_type = specified_return_type;13459 inst_fn_type_id.return_type = specified_return_type;
13227 }13460 }
1322813461
13229 if ((err = type_resolve(ira->codegen, specified_return_type, ResolveStatusZeroBitsKnown)))13462 switch (type_requires_comptime(ira->codegen, specified_return_type)) {
13230 return ira->codegen->invalid_instruction;13463 case ReqCompTimeYes:
13231
13232 if (type_requires_comptime(specified_return_type)) {
13233 // Throw out our work and call the function as if it were comptime.13464 // Throw out our work and call the function as if it were comptime.
13234 return ir_analyze_fn_call(ira, call_instruction, fn_entry, fn_type, fn_ref, first_arg_ptr, true, FnInlineAuto);13465 return ir_analyze_fn_call(ira, call_instruction, fn_entry, fn_type, fn_ref, first_arg_ptr,
13466 true, FnInlineAuto);
13467 case ReqCompTimeInvalid:
13468 return ira->codegen->invalid_instruction;
13469 case ReqCompTimeNo:
13470 break;
13235 }13471 }
13236 }13472 }
13237 IrInstruction *async_allocator_inst = nullptr;13473 IrInstruction *async_allocator_inst = nullptr;
...@@ -13485,18 +13721,56 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,...@@ -13485,18 +13721,56 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,
13485 return ErrorNone;13721 return ErrorNone;
13486 }13722 }
1348713723
13488 if (dst_size > src_size) {13724 if (dst_size <= src_size) {
13489 ir_add_error_node(ira, source_node,13725 Buf buf = BUF_INIT;
13490 buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",13726 buf_resize(&buf, src_size);
13491 dst_size, buf_ptr(&pointee->type->name), src_size));13727 buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee);
13492 return ErrorSemanticAnalyzeFail;13728 if ((err = buf_read_value_bytes(ira, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
13729 return err;
13730 return ErrorNone;
13493 }13731 }
1349413732
13495 Buf buf = BUF_INIT;13733 switch (ptr_val->data.x_ptr.special) {
13496 buf_resize(&buf, src_size);13734 case ConstPtrSpecialInvalid:
13497 buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee);13735 zig_unreachable();
13498 buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val);13736 case ConstPtrSpecialRef: {
13499 return ErrorNone;13737 ir_add_error_node(ira, source_node,
13738 buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",
13739 dst_size, buf_ptr(&pointee->type->name), src_size));
13740 return ErrorSemanticAnalyzeFail;
13741 }
13742 case ConstPtrSpecialBaseArray: {
13743 ConstExprValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val;
13744 assert(array_val->type->id == ZigTypeIdArray);
13745 if (array_val->data.x_array.special != ConstArraySpecialNone)
13746 zig_panic("TODO");
13747 size_t elem_size = src_size;
13748 size_t elem_index = ptr_val->data.x_ptr.data.base_array.elem_index;
13749 src_size = elem_size * (array_val->type->data.array.len - elem_index);
13750 if (dst_size > src_size) {
13751 ir_add_error_node(ira, source_node,
13752 buf_sprintf("attempt to read %zu bytes from %s at index %" ZIG_PRI_usize " which is %zu bytes",
13753 dst_size, buf_ptr(&array_val->type->name), elem_index, src_size));
13754 return ErrorSemanticAnalyzeFail;
13755 }
13756 size_t elem_count = (dst_size % elem_size == 0) ? (dst_size / elem_size) : (dst_size / elem_size + 1);
13757 Buf buf = BUF_INIT;
13758 buf_resize(&buf, elem_count * elem_size);
13759 for (size_t i = 0; i < elem_count; i += 1) {
13760 ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[elem_index + i];
13761 buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val);
13762 }
13763 if ((err = buf_read_value_bytes(ira, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
13764 return err;
13765 return ErrorNone;
13766 }
13767 case ConstPtrSpecialBaseStruct:
13768 case ConstPtrSpecialDiscard:
13769 case ConstPtrSpecialHardCodedAddr:
13770 case ConstPtrSpecialFunction:
13771 zig_panic("TODO");
13772 }
13773 zig_unreachable();
13500}13774}
1350113775
13502static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {13776static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
...@@ -14172,11 +14446,16 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -14172,11 +14446,16 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1417214446
14173 } else {14447 } else {
14174 // runtime known element index14448 // runtime known element index
14175 if (type_requires_comptime(return_type)) {14449 switch (type_requires_comptime(ira->codegen, return_type)) {
14450 case ReqCompTimeYes:
14176 ir_add_error(ira, elem_index,14451 ir_add_error(ira, elem_index,
14177 buf_sprintf("values of type '%s' must be comptime known, but index value is runtime known",14452 buf_sprintf("values of type '%s' must be comptime known, but index value is runtime known",
14178 buf_ptr(&return_type->data.pointer.child_type->name)));14453 buf_ptr(&return_type->data.pointer.child_type->name)));
14179 return ira->codegen->invalid_instruction;14454 return ira->codegen->invalid_instruction;
14455 case ReqCompTimeInvalid:
14456 return ira->codegen->invalid_instruction;
14457 case ReqCompTimeNo:
14458 break;
14180 }14459 }
14181 if (ptr_align < abi_align) {14460 if (ptr_align < abi_align) {
14182 if (elem_size >= ptr_align && elem_size % ptr_align == 0) {14461 if (elem_size >= ptr_align && elem_size % ptr_align == 0) {
...@@ -15233,9 +15512,19 @@ static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAs...@@ -15233,9 +15512,19 @@ static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAs
15233 }15512 }
1523415513
15235 for (size_t i = 0; i < asm_expr->input_list.length; i += 1) {15514 for (size_t i = 0; i < asm_expr->input_list.length; i += 1) {
15236 input_list[i] = asm_instruction->input_list[i]->child;15515 IrInstruction *const input_value = asm_instruction->input_list[i]->child;
15237 if (type_is_invalid(input_list[i]->value.type))15516 if (type_is_invalid(input_value->value.type))
15238 return ira->codegen->invalid_instruction;15517 return ira->codegen->invalid_instruction;
15518
15519 if (instr_is_comptime(input_value) &&
15520 (input_value->value.type->id == ZigTypeIdComptimeInt ||
15521 input_value->value.type->id == ZigTypeIdComptimeFloat)) {
15522 ir_add_error_node(ira, input_value->source_node,
15523 buf_sprintf("expected sized integer or sized float, found %s", buf_ptr(&input_value->value.type->name)));
15524 return ira->codegen->invalid_instruction;
15525 }
15526
15527 input_list[i] = input_value;
15239 }15528 }
1524015529
15241 IrInstruction *result = ir_build_asm(&ira->new_irb,15530 IrInstruction *result = ir_build_asm(&ira->new_irb,
...@@ -17850,6 +18139,12 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct...@@ -17850,6 +18139,12 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct
17850 return ira->codegen->invalid_instruction;18139 return ira->codegen->invalid_instruction;
17851 }18140 }
1785218141
18142 if (src_type->data.integral.bit_count == 0) {
18143 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
18144 bigint_init_unsigned(&result->value.data.x_bigint, 0);
18145 return result;
18146 }
18147
17853 if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) {18148 if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) {
17854 const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned";18149 const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned";
17855 ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name)));18150 ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name)));
...@@ -17878,7 +18173,7 @@ static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstruct...@@ -17878,7 +18173,7 @@ static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstruct
17878 if (type_is_invalid(dest_type))18173 if (type_is_invalid(dest_type))
17879 return ira->codegen->invalid_instruction;18174 return ira->codegen->invalid_instruction;
1788018175
17881 if (dest_type->id != ZigTypeIdInt) {18176 if (dest_type->id != ZigTypeIdInt && dest_type->id != ZigTypeIdComptimeInt) {
17882 ir_add_error(ira, instruction->dest_type, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name)));18177 ir_add_error(ira, instruction->dest_type, buf_sprintf("expected integer type, found '%s'", buf_ptr(&dest_type->name)));
17883 return ira->codegen->invalid_instruction;18178 return ira->codegen->invalid_instruction;
17884 }18179 }
...@@ -17887,20 +18182,22 @@ static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstruct...@@ -17887,20 +18182,22 @@ static IrInstruction *ir_analyze_instruction_int_cast(IrAnalyze *ira, IrInstruct
17887 if (type_is_invalid(target->value.type))18182 if (type_is_invalid(target->value.type))
17888 return ira->codegen->invalid_instruction;18183 return ira->codegen->invalid_instruction;
1788918184
17890 if (target->value.type->id == ZigTypeIdComptimeInt) {18185 if (target->value.type->id != ZigTypeIdInt && target->value.type->id != ZigTypeIdComptimeInt) {
17891 if (ir_num_lit_fits_in_other_type(ira, target, dest_type, true)) {
17892 return ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpNumLitToConcrete, false);
17893 } else {
17894 return ira->codegen->invalid_instruction;
17895 }
17896 }
17897
17898 if (target->value.type->id != ZigTypeIdInt) {
17899 ir_add_error(ira, instruction->target, buf_sprintf("expected integer type, found '%s'",18186 ir_add_error(ira, instruction->target, buf_sprintf("expected integer type, found '%s'",
17900 buf_ptr(&target->value.type->name)));18187 buf_ptr(&target->value.type->name)));
17901 return ira->codegen->invalid_instruction;18188 return ira->codegen->invalid_instruction;
17902 }18189 }
1790318190
18191 if (instr_is_comptime(target)) {
18192 return ir_implicit_cast(ira, target, dest_type);
18193 }
18194
18195 if (dest_type->id == ZigTypeIdComptimeInt) {
18196 ir_add_error(ira, instruction->target, buf_sprintf("attempt to cast runtime value to '%s'",
18197 buf_ptr(&dest_type->name)));
18198 return ira->codegen->invalid_instruction;
18199 }
18200
17904 return ir_analyze_widen_or_shorten(ira, &instruction->base, target, dest_type);18201 return ir_analyze_widen_or_shorten(ira, &instruction->base, target, dest_type);
17905}18202}
1790618203
...@@ -19216,7 +19513,6 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,...@@ -19216,7 +19513,6 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
19216}19513}
1921719514
19218static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {19515static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {
19219 Error err;
19220 AstNode *proto_node = instruction->base.source_node;19516 AstNode *proto_node = instruction->base.source_node;
19221 assert(proto_node->type == NodeTypeFnProto);19517 assert(proto_node->type == NodeTypeFnProto);
1922219518
...@@ -19255,11 +19551,8 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct...@@ -19255,11 +19551,8 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct
19255 if (type_is_invalid(param_type_value->value.type))19551 if (type_is_invalid(param_type_value->value.type))
19256 return ira->codegen->invalid_instruction;19552 return ira->codegen->invalid_instruction;
19257 ZigType *param_type = ir_resolve_type(ira, param_type_value);19553 ZigType *param_type = ir_resolve_type(ira, param_type_value);
19258 if (type_is_invalid(param_type))19554 switch (type_requires_comptime(ira->codegen, param_type)) {
19259 return ira->codegen->invalid_instruction;19555 case ReqCompTimeYes:
19260 if ((err = type_resolve(ira->codegen, param_type, ResolveStatusZeroBitsKnown)))
19261 return ira->codegen->invalid_instruction;
19262 if (type_requires_comptime(param_type)) {
19263 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {19556 if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
19264 ir_add_error(ira, param_type_value,19557 ir_add_error(ira, param_type_value,
19265 buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'",19558 buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'",
...@@ -19269,6 +19562,10 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct...@@ -19269,6 +19562,10 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct
19269 param_info->type = param_type;19562 param_info->type = param_type;
19270 fn_type_id.next_param_index += 1;19563 fn_type_id.next_param_index += 1;
19271 return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id));19564 return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id));
19565 case ReqCompTimeInvalid:
19566 return ira->codegen->invalid_instruction;
19567 case ReqCompTimeNo:
19568 break;
19272 }19569 }
19273 if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) {19570 if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) {
19274 ir_add_error(ira, param_type_value,19571 ir_add_error(ira, param_type_value,
...@@ -19711,6 +20008,8 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct...@@ -19711,6 +20008,8 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct
19711}20008}
1971220009
19713static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {20010static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {
20011 if (val->special == ConstValSpecialUndef)
20012 val->special = ConstValSpecialStatic;
19714 assert(val->special == ConstValSpecialStatic);20013 assert(val->special == ConstValSpecialStatic);
19715 switch (val->type->id) {20014 switch (val->type->id) {
19716 case ZigTypeIdInvalid:20015 case ZigTypeIdInvalid:
...@@ -19780,7 +20079,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -19780,7 +20079,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
19780 zig_unreachable();20079 zig_unreachable();
19781}20080}
1978220081
19783static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {20082static Error buf_read_value_bytes(IrAnalyze *ira, AstNode *source_node, uint8_t *buf, ConstExprValue *val) {
20083 Error err;
19784 assert(val->special == ConstValSpecialStatic);20084 assert(val->special == ConstValSpecialStatic);
19785 switch (val->type->id) {20085 switch (val->type->id) {
19786 case ZigTypeIdInvalid:20086 case ZigTypeIdInvalid:
...@@ -19797,30 +20097,60 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -19797,30 +20097,60 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
19797 case ZigTypeIdPromise:20097 case ZigTypeIdPromise:
19798 zig_unreachable();20098 zig_unreachable();
19799 case ZigTypeIdVoid:20099 case ZigTypeIdVoid:
19800 return;20100 return ErrorNone;
19801 case ZigTypeIdBool:20101 case ZigTypeIdBool:
19802 val->data.x_bool = (buf[0] != 0);20102 val->data.x_bool = (buf[0] != 0);
19803 return;20103 return ErrorNone;
19804 case ZigTypeIdInt:20104 case ZigTypeIdInt:
19805 bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,20105 bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,
19806 codegen->is_big_endian, val->type->data.integral.is_signed);20106 ira->codegen->is_big_endian, val->type->data.integral.is_signed);
19807 return;20107 return ErrorNone;
19808 case ZigTypeIdFloat:20108 case ZigTypeIdFloat:
19809 float_read_ieee597(val, buf, codegen->is_big_endian);20109 float_read_ieee597(val, buf, ira->codegen->is_big_endian);
19810 return;20110 return ErrorNone;
19811 case ZigTypeIdPointer:20111 case ZigTypeIdPointer:
19812 {20112 {
19813 val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;20113 val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
19814 BigInt bn;20114 BigInt bn;
19815 bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count,20115 bigint_read_twos_complement(&bn, buf, ira->codegen->builtin_types.entry_usize->data.integral.bit_count,
19816 codegen->is_big_endian, false);20116 ira->codegen->is_big_endian, false);
19817 val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);20117 val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);
19818 return;20118 return ErrorNone;
19819 }20119 }
19820 case ZigTypeIdArray:20120 case ZigTypeIdArray:
19821 zig_panic("TODO buf_read_value_bytes array type");20121 zig_panic("TODO buf_read_value_bytes array type");
19822 case ZigTypeIdStruct:20122 case ZigTypeIdStruct:
19823 zig_panic("TODO buf_read_value_bytes struct type");20123 switch (val->type->data.structure.layout) {
20124 case ContainerLayoutAuto: {
20125 ErrorMsg *msg = ir_add_error_node(ira, source_node,
20126 buf_sprintf("non-extern, non-packed struct '%s' cannot have its bytes reinterpreted",
20127 buf_ptr(&val->type->name)));
20128 add_error_note(ira->codegen, msg, val->type->data.structure.decl_node,
20129 buf_sprintf("declared here"));
20130 return ErrorSemanticAnalyzeFail;
20131 }
20132 case ContainerLayoutExtern: {
20133 size_t src_field_count = val->type->data.structure.src_field_count;
20134 val->data.x_struct.fields = create_const_vals(src_field_count);
20135 for (size_t field_i = 0; field_i < src_field_count; field_i += 1) {
20136 ConstExprValue *field_val = &val->data.x_struct.fields[field_i];
20137 field_val->special = ConstValSpecialStatic;
20138 TypeStructField *type_field = &val->type->data.structure.fields[field_i];
20139 field_val->type = type_field->type_entry;
20140 if (type_field->gen_index == SIZE_MAX)
20141 continue;
20142 size_t offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, val->type->type_ref,
20143 type_field->gen_index);
20144 uint8_t *new_buf = buf + offset;
20145 if ((err = buf_read_value_bytes(ira, source_node, new_buf, field_val)))
20146 return err;
20147 }
20148 return ErrorNone;
20149 }
20150 case ContainerLayoutPacked:
20151 zig_panic("TODO buf_read_value_bytes packed struct");
20152 }
20153 zig_unreachable();
19824 case ZigTypeIdOptional:20154 case ZigTypeIdOptional:
19825 zig_panic("TODO buf_read_value_bytes maybe type");20155 zig_panic("TODO buf_read_value_bytes maybe type");
19826 case ZigTypeIdErrorUnion:20156 case ZigTypeIdErrorUnion:
...@@ -19923,7 +20253,8 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct...@@ -19923,7 +20253,8 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
19923 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);20253 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
19924 uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);20254 uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);
19925 buf_write_value_bytes(ira->codegen, buf, val);20255 buf_write_value_bytes(ira->codegen, buf, val);
19926 buf_read_value_bytes(ira->codegen, buf, &result->value);20256 if ((err = buf_read_value_bytes(ira, instruction->base.source_node, buf, &result->value)))
20257 return ira->codegen->invalid_instruction;
19927 return result;20258 return result;
19928 }20259 }
1992920260
...@@ -20093,6 +20424,9 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct...@@ -20093,6 +20424,9 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
20093 return ira->codegen->invalid_instruction;20424 return ira->codegen->invalid_instruction;
20094 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown)))20425 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown)))
20095 return ira->codegen->invalid_instruction;20426 return ira->codegen->invalid_instruction;
20427 if (!type_has_bits(child_type)) {
20428 align_bytes = 0;
20429 }
20096 } else {20430 } else {
20097 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))20431 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
20098 return ira->codegen->invalid_instruction;20432 return ira->codegen->invalid_instruction;
...@@ -20692,6 +21026,63 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS...@@ -20692,6 +21026,63 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS
20692 return result;21026 return result;
20693}21027}
2069421028
21029static 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
20695static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {21086static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {
20696 Error err;21087 Error err;
20697 IrInstruction *target = instruction->target->child;21088 IrInstruction *target = instruction->target->child;
...@@ -21027,6 +21418,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -21027,6 +21418,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21027 return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);21418 return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);
21028 case IrInstructionIdSqrt:21419 case IrInstructionIdSqrt:
21029 return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction);21420 return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction);
21421 case IrInstructionIdBswap:
21422 return ir_analyze_instruction_bswap(ira, (IrInstructionBswap *)instruction);
21030 case IrInstructionIdIntToErr:21423 case IrInstructionIdIntToErr:
21031 return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);21424 return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);
21032 case IrInstructionIdErrToInt:21425 case IrInstructionIdErrToInt:
...@@ -21063,6 +21456,7 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_...@@ -21063,6 +21456,7 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_
21063 ZigFn *fn_entry = exec_fn_entry(old_exec);21456 ZigFn *fn_entry = exec_fn_entry(old_exec);
21064 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;21457 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
21065 ira->explicit_return_type = is_async ? get_promise_type(codegen, expected_type) : expected_type;21458 ira->explicit_return_type = is_async ? get_promise_type(codegen, expected_type) : expected_type;
21459 ira->explicit_return_type_source_node = expected_type_source_node;
2106621460
21067 ira->old_irb.codegen = codegen;21461 ira->old_irb.codegen = codegen;
21068 ira->old_irb.exec = old_exec;21462 ira->old_irb.exec = old_exec;
...@@ -21247,6 +21641,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21247,6 +21641,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21247 case IrInstructionIdCoroPromise:21641 case IrInstructionIdCoroPromise:
21248 case IrInstructionIdPromiseResultType:21642 case IrInstructionIdPromiseResultType:
21249 case IrInstructionIdSqrt:21643 case IrInstructionIdSqrt:
21644 case IrInstructionIdBswap:
21250 case IrInstructionIdAtomicLoad:21645 case IrInstructionIdAtomicLoad:
21251 case IrInstructionIdIntCast:21646 case IrInstructionIdIntCast:
21252 case IrInstructionIdFloatCast:21647 case IrInstructionIdFloatCast:
src/ir_print.cpp+15
...@@ -1323,6 +1323,18 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) {...@@ -1323,6 +1323,18 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) {
1323 fprintf(irp->f, ")");1323 fprintf(irp->f, ")");
1324}1324}
13251325
1326static 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
1326static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {1338static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1327 ir_print_prefix(irp, instruction);1339 ir_print_prefix(irp, instruction);
1328 switch (instruction->id) {1340 switch (instruction->id) {
...@@ -1736,6 +1748,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1736,6 +1748,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1736 case IrInstructionIdSqrt:1748 case IrInstructionIdSqrt:
1737 ir_print_sqrt(irp, (IrInstructionSqrt *)instruction);1749 ir_print_sqrt(irp, (IrInstructionSqrt *)instruction);
1738 break;1750 break;
1751 case IrInstructionIdBswap:
1752 ir_print_bswap(irp, (IrInstructionBswap *)instruction);
1753 break;
1739 case IrInstructionIdAtomicLoad:1754 case IrInstructionIdAtomicLoad:
1740 ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);1755 ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);
1741 break;1756 break;
src/link.cpp+7
...@@ -150,6 +150,10 @@ static const char *getLDMOption(const ZigTarget *t) {...@@ -150,6 +150,10 @@ static const char *getLDMOption(const ZigTarget *t) {
150 if (t->env_type == ZigLLVM_GNUX32) {150 if (t->env_type == ZigLLVM_GNUX32) {
151 return "elf32_x86_64";151 return "elf32_x86_64";
152 }152 }
153 // Any target elf will use the freebsd osabi if suffixed with "_fbsd".
154 if (t->os == OsFreeBSD) {
155 return "elf_x86_64_fbsd";
156 }
153 return "elf_x86_64";157 return "elf_x86_64";
154 default:158 default:
155 zig_unreachable();159 zig_unreachable();
...@@ -191,6 +195,9 @@ static Buf *try_dynamic_linker_path(const char *ld_name) {...@@ -191,6 +195,9 @@ static Buf *try_dynamic_linker_path(const char *ld_name) {
191}195}
192196
193static Buf *get_dynamic_linker_path(CodeGen *g) {197static Buf *get_dynamic_linker_path(CodeGen *g) {
198 if (g->zig_target.os == OsFreeBSD) {
199 return buf_create_from_str("/libexec/ld-elf.so.1");
200 }
194 if (g->is_native_target && g->zig_target.arch.arch == ZigLLVM_x86_64) {201 if (g->is_native_target && g->zig_target.arch.arch == ZigLLVM_x86_64) {
195 static const char *ld_names[] = {202 static const char *ld_names[] = {
196 "ld-linux-x86-64.so.2",203 "ld-linux-x86-64.so.2",
src/main.cpp+1-8
...@@ -466,16 +466,9 @@ int main(int argc, char **argv) {...@@ -466,16 +466,9 @@ int main(int argc, char **argv) {
466 "\n"466 "\n"
467 "General Options:\n"467 "General Options:\n"
468 " --help Print this help and exit\n"468 " --help Print this help and exit\n"
469 " --build-file [file] Override path to build.zig\n"
470 " --cache-dir [path] Override path to cache directory\n"
471 " --verbose Print commands before executing them\n"469 " --verbose Print commands before executing them\n"
472 " --verbose-tokenize Enable compiler debug output for tokenization\n"
473 " --verbose-ast Enable compiler debug output for parsing into an AST\n"
474 " --verbose-link Enable compiler debug output for linking\n"
475 " --verbose-ir Enable compiler debug output for Zig IR\n"
476 " --verbose-llvm-ir Enable compiler debug output for LLVM IR\n"
477 " --verbose-cimport Enable compiler debug output for C imports\n"
478 " --prefix [path] Override default install prefix\n"470 " --prefix [path] Override default install prefix\n"
471 " --search-prefix [path] Add a path to look for binaries, libraries, headers\n"
479 "\n"472 "\n"
480 "Project-specific options become available when the build file is found.\n"473 "Project-specific options become available when the build file is found.\n"
481 "\n"474 "\n"
src/os.cpp+29-9
...@@ -50,10 +50,13 @@ typedef SSIZE_T ssize_t;...@@ -50,10 +50,13 @@ typedef SSIZE_T ssize_t;
5050
51#endif51#endif
5252
53#if defined(ZIG_OS_LINUX)53#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD)
54#include <link.h>54#include <link.h>
55#endif55#endif
5656
57#if defined(ZIG_OS_FREEBSD)
58#include <sys/sysctl.h>
59#endif
5760
58#if defined(__MACH__)61#if defined(__MACH__)
59#include <mach/clock.h>62#include <mach/clock.h>
...@@ -75,7 +78,9 @@ static clock_serv_t cclock;...@@ -75,7 +78,9 @@ static clock_serv_t cclock;
75#if defined(__APPLE__) && !defined(environ)78#if defined(__APPLE__) && !defined(environ)
76#include <crt_externs.h>79#include <crt_externs.h>
77#define environ (*_NSGetEnviron())80#define environ (*_NSGetEnviron())
78#endif 81#elif defined(ZIG_OS_FREEBSD)
82extern char **environ;
83#endif
7984
80#if defined(ZIG_OS_POSIX)85#if defined(ZIG_OS_POSIX)
81static void populate_termination(Termination *term, int status) {86static void populate_termination(Termination *term, int status) {
...@@ -188,14 +193,20 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename) {...@@ -188,14 +193,20 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename) {
188 size_t len = buf_len(full_path);193 size_t len = buf_len(full_path);
189 if (len != 0) {194 if (len != 0) {
190 size_t last_index = len - 1;195 size_t last_index = len - 1;
191 if (os_is_sep(buf_ptr(full_path)[last_index])) {196 char last_char = buf_ptr(full_path)[last_index];
197 if (os_is_sep(last_char)) {
198 if (last_index == 0) {
199 if (out_dirname) buf_init_from_mem(out_dirname, &last_char, 1);
200 if (out_basename) buf_init_from_str(out_basename, "");
201 return;
202 }
192 last_index -= 1;203 last_index -= 1;
193 }204 }
194 for (size_t i = last_index;;) {205 for (size_t i = last_index;;) {
195 uint8_t c = buf_ptr(full_path)[i];206 uint8_t c = buf_ptr(full_path)[i];
196 if (os_is_sep(c)) {207 if (os_is_sep(c)) {
197 if (out_dirname) {208 if (out_dirname) {
198 buf_init_from_mem(out_dirname, buf_ptr(full_path), i);209 buf_init_from_mem(out_dirname, buf_ptr(full_path), (i == 0) ? 1 : i);
199 }210 }
200 if (out_basename) {211 if (out_basename) {
201 buf_init_from_mem(out_basename, buf_ptr(full_path) + i + 1, buf_len(full_path) - (i + 1));212 buf_init_from_mem(out_basename, buf_ptr(full_path) + i + 1, buf_len(full_path) - (i + 1));
...@@ -1438,6 +1449,15 @@ Error os_self_exe_path(Buf *out_path) {...@@ -1438,6 +1449,15 @@ Error os_self_exe_path(Buf *out_path) {
1438 }1449 }
1439 buf_resize(out_path, amt);1450 buf_resize(out_path, amt);
1440 return ErrorNone;1451 return ErrorNone;
1452#elif defined(ZIG_OS_FREEBSD)
1453 buf_resize(out_path, PATH_MAX);
1454 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
1455 size_t cb = PATH_MAX;
1456 if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) {
1457 return ErrorUnexpected;
1458 }
1459 buf_resize(out_path, cb - 1);
1460 return ErrorNone;
1441#endif1461#endif
1442 return ErrorFileNotFound;1462 return ErrorFileNotFound;
1443}1463}
...@@ -1743,7 +1763,7 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) {...@@ -1743,7 +1763,7 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) {
1743 buf_resize(out_path, 0);1763 buf_resize(out_path, 0);
1744 buf_appendf(out_path, "%s/Library/Application Support/%s", home_dir, appname);1764 buf_appendf(out_path, "%s/Library/Application Support/%s", home_dir, appname);
1745 return ErrorNone;1765 return ErrorNone;
1746#elif defined(ZIG_OS_LINUX)1766#elif defined(ZIG_OS_POSIX)
1747 const char *home_dir = getenv("HOME");1767 const char *home_dir = getenv("HOME");
1748 if (home_dir == nullptr) {1768 if (home_dir == nullptr) {
1749 // TODO use /etc/passwd1769 // TODO use /etc/passwd
...@@ -1756,7 +1776,7 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) {...@@ -1756,7 +1776,7 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) {
1756}1776}
17571777
17581778
1759#if defined(ZIG_OS_LINUX)1779#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD)
1760static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, void *data) {1780static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, void *data) {
1761 ZigList<Buf *> *libs = reinterpret_cast< ZigList<Buf *> *>(data);1781 ZigList<Buf *> *libs = reinterpret_cast< ZigList<Buf *> *>(data);
1762 if (info->dlpi_name[0] == '/') {1782 if (info->dlpi_name[0] == '/') {
...@@ -1767,7 +1787,7 @@ static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size,...@@ -1767,7 +1787,7 @@ static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size,
1767#endif1787#endif
17681788
1769Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {1789Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {
1770#if defined(ZIG_OS_LINUX)1790#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD)
1771 paths.resize(0);1791 paths.resize(0);
1772 dl_iterate_phdr(self_exe_shared_libs_callback, &paths);1792 dl_iterate_phdr(self_exe_shared_libs_callback, &paths);
1773 return ErrorNone;1793 return ErrorNone;
...@@ -1936,7 +1956,7 @@ Error os_file_mtime(OsFile file, OsTimeStamp *mtime) {...@@ -1936,7 +1956,7 @@ Error os_file_mtime(OsFile file, OsTimeStamp *mtime) {
1936 mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime;1956 mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime;
1937 mtime->nsec = 0;1957 mtime->nsec = 0;
1938 return ErrorNone;1958 return ErrorNone;
1939#elif defined(ZIG_OS_LINUX)1959#elif defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD)
1940 struct stat statbuf;1960 struct stat statbuf;
1941 if (fstat(file, &statbuf) == -1)1961 if (fstat(file, &statbuf) == -1)
1942 return ErrorFileSystem;1962 return ErrorFileSystem;
...@@ -1976,7 +1996,7 @@ Error os_file_read(OsFile file, void *ptr, size_t *len) {...@@ -1976,7 +1996,7 @@ Error os_file_read(OsFile file, void *ptr, size_t *len) {
1976 case EFAULT:1996 case EFAULT:
1977 zig_unreachable();1997 zig_unreachable();
1978 case EISDIR:1998 case EISDIR:
1979 zig_unreachable();1999 return ErrorIsDir;
1980 default:2000 default:
1981 return ErrorFileSystem;2001 return ErrorFileSystem;
1982 }2002 }
src/os.hpp+2
...@@ -23,6 +23,8 @@...@@ -23,6 +23,8 @@
23#define ZIG_OS_WINDOWS23#define ZIG_OS_WINDOWS
24#elif defined(__linux__)24#elif defined(__linux__)
25#define ZIG_OS_LINUX25#define ZIG_OS_LINUX
26#elif defined(__FreeBSD__)
27#define ZIG_OS_FREEBSD
26#else28#else
27#define ZIG_OS_UNKNOWN29#define ZIG_OS_UNKNOWN
28#endif30#endif
src/parser.cpp+13-13
...@@ -91,7 +91,7 @@ static Token *ast_parse_break_label(ParseContext *pc);...@@ -91,7 +91,7 @@ static Token *ast_parse_break_label(ParseContext *pc);
91static Token *ast_parse_block_label(ParseContext *pc);91static Token *ast_parse_block_label(ParseContext *pc);
92static AstNode *ast_parse_field_init(ParseContext *pc);92static AstNode *ast_parse_field_init(ParseContext *pc);
93static AstNode *ast_parse_while_continue_expr(ParseContext *pc);93static AstNode *ast_parse_while_continue_expr(ParseContext *pc);
94static AstNode *ast_parse_section(ParseContext *pc);94static AstNode *ast_parse_link_section(ParseContext *pc);
95static Optional<AstNodeFnProto> ast_parse_fn_cc(ParseContext *pc);95static Optional<AstNodeFnProto> ast_parse_fn_cc(ParseContext *pc);
96static AstNode *ast_parse_param_decl(ParseContext *pc);96static AstNode *ast_parse_param_decl(ParseContext *pc);
97static AstNode *ast_parse_param_type(ParseContext *pc);97static AstNode *ast_parse_param_type(ParseContext *pc);
...@@ -775,7 +775,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {...@@ -775,7 +775,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {
775 return nullptr;775 return nullptr;
776}776}
777777
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)
779static AstNode *ast_parse_fn_proto(ParseContext *pc) {779static AstNode *ast_parse_fn_proto(ParseContext *pc) {
780 Token *first = peek_token(pc);780 Token *first = peek_token(pc);
781 AstNodeFnProto fn_cc;781 AstNodeFnProto fn_cc;
...@@ -806,7 +806,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {...@@ -806,7 +806,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {
806 expect_token(pc, TokenIdRParen);806 expect_token(pc, TokenIdRParen);
807807
808 AstNode *align_expr = ast_parse_byte_align(pc);808 AstNode *align_expr = ast_parse_byte_align(pc);
809 AstNode *section_expr = ast_parse_section(pc);809 AstNode *section_expr = ast_parse_link_section(pc);
810 Token *var = eat_token_if(pc, TokenIdKeywordVar);810 Token *var = eat_token_if(pc, TokenIdKeywordVar);
811 Token *exmark = nullptr;811 Token *exmark = nullptr;
812 AstNode *return_type = nullptr;812 AstNode *return_type = nullptr;
...@@ -842,7 +842,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {...@@ -842,7 +842,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {
842 return res;842 return res;
843}843}
844844
845// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? Section? (EQUAL Expr)? SEMICOLON845// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON
846static AstNode *ast_parse_var_decl(ParseContext *pc) {846static AstNode *ast_parse_var_decl(ParseContext *pc) {
847 Token *first = eat_token_if(pc, TokenIdKeywordConst);847 Token *first = eat_token_if(pc, TokenIdKeywordConst);
848 if (first == nullptr)848 if (first == nullptr)
...@@ -856,7 +856,7 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) {...@@ -856,7 +856,7 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) {
856 type_expr = ast_expect(pc, ast_parse_type_expr);856 type_expr = ast_expect(pc, ast_parse_type_expr);
857857
858 AstNode *align_expr = ast_parse_byte_align(pc);858 AstNode *align_expr = ast_parse_byte_align(pc);
859 AstNode *section_expr = ast_parse_section(pc);859 AstNode *section_expr = ast_parse_link_section(pc);
860 AstNode *expr = nullptr;860 AstNode *expr = nullptr;
861 if (eat_token_if(pc, TokenIdEq) != nullptr)861 if (eat_token_if(pc, TokenIdEq) != nullptr)
862 expr = ast_expect(pc, ast_parse_expr);862 expr = ast_expect(pc, ast_parse_expr);
...@@ -1490,8 +1490,8 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) {...@@ -1490,8 +1490,8 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) {
1490}1490}
14911491
1492// SuffixExpr1492// SuffixExpr
1493// <- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArgumnets1493// <- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArguments
1494// / PrimaryTypeExpr (SuffixOp / FnCallArgumnets)*1494// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
1495static AstNode *ast_parse_suffix_expr(ParseContext *pc) {1495static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
1496 AstNode *async_call = ast_parse_async_prefix(pc);1496 AstNode *async_call = ast_parse_async_prefix(pc);
1497 if (async_call != nullptr) {1497 if (async_call != nullptr) {
...@@ -1599,7 +1599,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {...@@ -1599,7 +1599,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
1599}1599}
16001600
1601// PrimaryTypeExpr1601// PrimaryTypeExpr
1602// <- BUILTININDENTIFIER FnCallArgumnets1602// <- BUILTINIDENTIFIER FnCallArguments
1603// / CHAR_LITERAL1603// / CHAR_LITERAL
1604// / ContainerDecl1604// / ContainerDecl
1605// / ErrorSetDecl1605// / ErrorSetDecl
...@@ -1978,7 +1978,7 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {...@@ -1978,7 +1978,7 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {
1978 return res;1978 return res;
1979}1979}
19801980
1981// AsmInput <- COLON AsmInputList AsmCloppers?1981// AsmInput <- COLON AsmInputList AsmClobbers?
1982static AstNode *ast_parse_asm_input(ParseContext *pc) {1982static AstNode *ast_parse_asm_input(ParseContext *pc) {
1983 if (eat_token_if(pc, TokenIdColon) == nullptr)1983 if (eat_token_if(pc, TokenIdColon) == nullptr)
1984 return nullptr;1984 return nullptr;
...@@ -2011,7 +2011,7 @@ static AsmInput *ast_parse_asm_input_item(ParseContext *pc) {...@@ -2011,7 +2011,7 @@ static AsmInput *ast_parse_asm_input_item(ParseContext *pc) {
2011 return res;2011 return res;
2012}2012}
20132013
2014// AsmCloppers <- COLON StringList2014// AsmClobbers <- COLON StringList
2015static AstNode *ast_parse_asm_cloppers(ParseContext *pc) {2015static AstNode *ast_parse_asm_cloppers(ParseContext *pc) {
2016 if (eat_token_if(pc, TokenIdColon) == nullptr)2016 if (eat_token_if(pc, TokenIdColon) == nullptr)
2017 return nullptr;2017 return nullptr;
...@@ -2080,8 +2080,8 @@ static AstNode *ast_parse_while_continue_expr(ParseContext *pc) {...@@ -2080,8 +2080,8 @@ static AstNode *ast_parse_while_continue_expr(ParseContext *pc) {
2080 return expr;2080 return expr;
2081}2081}
20822082
2083// Section <- KEYWORD_section LPAREN Expr RPAREN2083// LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN
2084static AstNode *ast_parse_section(ParseContext *pc) {2084static AstNode *ast_parse_link_section(ParseContext *pc) {
2085 Token *first = eat_token_if(pc, TokenIdKeywordLinkSection);2085 Token *first = eat_token_if(pc, TokenIdKeywordLinkSection);
2086 if (first == nullptr)2086 if (first == nullptr)
2087 return nullptr;2087 return nullptr;
...@@ -2742,7 +2742,7 @@ static AstNode *ast_parse_async_prefix(ParseContext *pc) {...@@ -2742,7 +2742,7 @@ static AstNode *ast_parse_async_prefix(ParseContext *pc) {
2742 return res;2742 return res;
2743}2743}
27442744
2745// FnCallArgumnets <- LPAREN ExprList RPAREN2745// FnCallArguments <- LPAREN ExprList RPAREN
2746static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) {2746static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) {
2747 Token *paren = eat_token_if(pc, TokenIdLParen);2747 Token *paren = eat_token_if(pc, TokenIdLParen);
2748 if (paren == nullptr)2748 if (paren == nullptr)
src/target.cpp+62-1
...@@ -754,6 +754,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {...@@ -754,6 +754,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
754 case OsLinux:754 case OsLinux:
755 case OsMacOSX:755 case OsMacOSX:
756 case OsZen:756 case OsZen:
757 case OsFreeBSD:
757 case OsOpenBSD:758 case OsOpenBSD:
758 switch (id) {759 switch (id) {
759 case CIntTypeShort:760 case CIntTypeShort:
...@@ -790,7 +791,6 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {...@@ -790,7 +791,6 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
790 case OsAnanas:791 case OsAnanas:
791 case OsCloudABI:792 case OsCloudABI:
792 case OsDragonFly:793 case OsDragonFly:
793 case OsFreeBSD:
794 case OsIOS:794 case OsIOS:
795 case OsKFreeBSD:795 case OsKFreeBSD:
796 case OsLv2:796 case OsLv2:
...@@ -1028,3 +1028,64 @@ const char *arch_stack_pointer_register_name(const ArchType *arch) {...@@ -1028,3 +1028,64 @@ const char *arch_stack_pointer_register_name(const ArchType *arch) {
1028 }1028 }
1029 zig_unreachable();1029 zig_unreachable();
1030}1030}
1031
1032bool target_is_arm(const ZigTarget *target) {
1033 switch (target->arch.arch) {
1034 case ZigLLVM_UnknownArch:
1035 zig_unreachable();
1036 case ZigLLVM_aarch64:
1037 case ZigLLVM_arm:
1038 case ZigLLVM_thumb:
1039 case ZigLLVM_aarch64_be:
1040 case ZigLLVM_armeb:
1041 case ZigLLVM_thumbeb:
1042 return true;
1043
1044 case ZigLLVM_x86:
1045 case ZigLLVM_x86_64:
1046 case ZigLLVM_amdgcn:
1047 case ZigLLVM_amdil:
1048 case ZigLLVM_amdil64:
1049 case ZigLLVM_arc:
1050 case ZigLLVM_avr:
1051 case ZigLLVM_bpfeb:
1052 case ZigLLVM_bpfel:
1053 case ZigLLVM_hexagon:
1054 case ZigLLVM_lanai:
1055 case ZigLLVM_hsail:
1056 case ZigLLVM_hsail64:
1057 case ZigLLVM_kalimba:
1058 case ZigLLVM_le32:
1059 case ZigLLVM_le64:
1060 case ZigLLVM_mips:
1061 case ZigLLVM_mips64:
1062 case ZigLLVM_mips64el:
1063 case ZigLLVM_mipsel:
1064 case ZigLLVM_msp430:
1065 case ZigLLVM_nios2:
1066 case ZigLLVM_nvptx:
1067 case ZigLLVM_nvptx64:
1068 case ZigLLVM_ppc64le:
1069 case ZigLLVM_r600:
1070 case ZigLLVM_renderscript32:
1071 case ZigLLVM_renderscript64:
1072 case ZigLLVM_riscv32:
1073 case ZigLLVM_riscv64:
1074 case ZigLLVM_shave:
1075 case ZigLLVM_sparc:
1076 case ZigLLVM_sparcel:
1077 case ZigLLVM_sparcv9:
1078 case ZigLLVM_spir:
1079 case ZigLLVM_spir64:
1080 case ZigLLVM_systemz:
1081 case ZigLLVM_tce:
1082 case ZigLLVM_tcele:
1083 case ZigLLVM_wasm32:
1084 case ZigLLVM_wasm64:
1085 case ZigLLVM_xcore:
1086 case ZigLLVM_ppc:
1087 case ZigLLVM_ppc64:
1088 return false;
1089 }
1090 zig_unreachable();
1091}
src/target.hpp+2
...@@ -122,4 +122,6 @@ Buf *target_dynamic_linker(ZigTarget *target);...@@ -122,4 +122,6 @@ Buf *target_dynamic_linker(ZigTarget *target);
122bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target);122bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target);
123ZigLLVM_OSType get_llvm_os_type(Os os_type);123ZigLLVM_OSType get_llvm_os_type(Os os_type);
124124
125bool target_is_arm(const ZigTarget *target);
126
125#endif127#endif
src/translate_c.cpp+8
...@@ -4784,6 +4784,14 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const...@@ -4784,6 +4784,14 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
47844784
4785 clang_argv.append(target_file);4785 clang_argv.append(target_file);
47864786
4787 if (codegen->verbose_cimport) {
4788 fprintf(stderr, "clang");
4789 for (size_t i = 0; i < clang_argv.length; i += 1) {
4790 fprintf(stderr, " %s", clang_argv.at(i));
4791 }
4792 fprintf(stderr, "\n");
4793 }
4794
4787 // to make the [start...end] argument work4795 // to make the [start...end] argument work
4788 clang_argv.append(nullptr);4796 clang_argv.append(nullptr);
47894797
src/util.hpp+11
...@@ -158,6 +158,17 @@ static inline bool is_power_of_2(uint64_t x) {...@@ -158,6 +158,17 @@ static inline bool is_power_of_2(uint64_t x) {
158 return x != 0 && ((x & (~x + 1)) == x);158 return x != 0 && ((x & (~x + 1)) == x);
159}159}
160160
161static 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
161uint32_t int_hash(int i);172uint32_t int_hash(int i);
162bool int_eq(int a, int b);173bool int_eq(int a, int b);
163uint32_t uint64_hash(uint64_t i);174uint32_t uint64_hash(uint64_t i);
src/zig_llvm.cpp+161-14
...@@ -680,20 +680,6 @@ void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) {...@@ -680,20 +680,6 @@ void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) {
680 llvm::cl::ParseCommandLineOptions(argc, argv);680 llvm::cl::ParseCommandLineOptions(argc, argv);
681}681}
682682
683
684static_assert((Triple::ArchType)ZigLLVM_LastArchType == Triple::LastArchType, "");
685static_assert((Triple::VendorType)ZigLLVM_LastVendorType == Triple::LastVendorType, "");
686static_assert((Triple::OSType)ZigLLVM_LastOSType == Triple::LastOSType, "");
687static_assert((Triple::EnvironmentType)ZigLLVM_LastEnvironmentType == Triple::LastEnvironmentType, "");
688static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v5 == Triple::KalimbaSubArch_v5, "");
689static_assert((Triple::SubArchType)ZigLLVM_MipsSubArch_r6 == Triple::MipsSubArch_r6, "");
690
691static_assert((Triple::ObjectFormatType)ZigLLVM_UnknownObjectFormat == Triple::UnknownObjectFormat, "");
692static_assert((Triple::ObjectFormatType)ZigLLVM_COFF == Triple::COFF, "");
693static_assert((Triple::ObjectFormatType)ZigLLVM_ELF == Triple::ELF, "");
694static_assert((Triple::ObjectFormatType)ZigLLVM_MachO == Triple::MachO, "");
695static_assert((Triple::ObjectFormatType)ZigLLVM_Wasm == Triple::Wasm, "");
696
697const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch) {683const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch) {
698 return (const char*)Triple::getArchTypeName((Triple::ArchType)arch).bytes_begin();684 return (const char*)Triple::getArchTypeName((Triple::ArchType)arch).bytes_begin();
699}685}
...@@ -924,3 +910,164 @@ bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_...@@ -924,3 +910,164 @@ bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_
924 assert(false); // unreachable910 assert(false); // unreachable
925 abort();911 abort();
926}912}
913
914static_assert((Triple::ArchType)ZigLLVM_UnknownArch == Triple::UnknownArch, "");
915static_assert((Triple::ArchType)ZigLLVM_arm == Triple::arm, "");
916static_assert((Triple::ArchType)ZigLLVM_armeb == Triple::armeb, "");
917static_assert((Triple::ArchType)ZigLLVM_aarch64 == Triple::aarch64, "");
918static_assert((Triple::ArchType)ZigLLVM_aarch64_be == Triple::aarch64_be, "");
919static_assert((Triple::ArchType)ZigLLVM_arc == Triple::arc, "");
920static_assert((Triple::ArchType)ZigLLVM_avr == Triple::avr, "");
921static_assert((Triple::ArchType)ZigLLVM_bpfel == Triple::bpfel, "");
922static_assert((Triple::ArchType)ZigLLVM_bpfeb == Triple::bpfeb, "");
923static_assert((Triple::ArchType)ZigLLVM_hexagon == Triple::hexagon, "");
924static_assert((Triple::ArchType)ZigLLVM_mips == Triple::mips, "");
925static_assert((Triple::ArchType)ZigLLVM_mipsel == Triple::mipsel, "");
926static_assert((Triple::ArchType)ZigLLVM_mips64 == Triple::mips64, "");
927static_assert((Triple::ArchType)ZigLLVM_mips64el == Triple::mips64el, "");
928static_assert((Triple::ArchType)ZigLLVM_msp430 == Triple::msp430, "");
929static_assert((Triple::ArchType)ZigLLVM_nios2 == Triple::nios2, "");
930static_assert((Triple::ArchType)ZigLLVM_ppc == Triple::ppc, "");
931static_assert((Triple::ArchType)ZigLLVM_ppc64 == Triple::ppc64, "");
932static_assert((Triple::ArchType)ZigLLVM_ppc64le == Triple::ppc64le, "");
933static_assert((Triple::ArchType)ZigLLVM_r600 == Triple::r600, "");
934static_assert((Triple::ArchType)ZigLLVM_amdgcn == Triple::amdgcn, "");
935static_assert((Triple::ArchType)ZigLLVM_riscv32 == Triple::riscv32, "");
936static_assert((Triple::ArchType)ZigLLVM_riscv64 == Triple::riscv64, "");
937static_assert((Triple::ArchType)ZigLLVM_sparc == Triple::sparc, "");
938static_assert((Triple::ArchType)ZigLLVM_sparcv9 == Triple::sparcv9, "");
939static_assert((Triple::ArchType)ZigLLVM_sparcel == Triple::sparcel, "");
940static_assert((Triple::ArchType)ZigLLVM_systemz == Triple::systemz, "");
941static_assert((Triple::ArchType)ZigLLVM_tce == Triple::tce, "");
942static_assert((Triple::ArchType)ZigLLVM_tcele == Triple::tcele, "");
943static_assert((Triple::ArchType)ZigLLVM_thumb == Triple::thumb, "");
944static_assert((Triple::ArchType)ZigLLVM_thumbeb == Triple::thumbeb, "");
945static_assert((Triple::ArchType)ZigLLVM_x86 == Triple::x86, "");
946static_assert((Triple::ArchType)ZigLLVM_x86_64 == Triple::x86_64, "");
947static_assert((Triple::ArchType)ZigLLVM_xcore == Triple::xcore, "");
948static_assert((Triple::ArchType)ZigLLVM_nvptx == Triple::nvptx, "");
949static_assert((Triple::ArchType)ZigLLVM_nvptx64 == Triple::nvptx64, "");
950static_assert((Triple::ArchType)ZigLLVM_le32 == Triple::le32, "");
951static_assert((Triple::ArchType)ZigLLVM_le64 == Triple::le64, "");
952static_assert((Triple::ArchType)ZigLLVM_amdil == Triple::amdil, "");
953static_assert((Triple::ArchType)ZigLLVM_amdil64 == Triple::amdil64, "");
954static_assert((Triple::ArchType)ZigLLVM_hsail == Triple::hsail, "");
955static_assert((Triple::ArchType)ZigLLVM_hsail64 == Triple::hsail64, "");
956static_assert((Triple::ArchType)ZigLLVM_spir == Triple::spir, "");
957static_assert((Triple::ArchType)ZigLLVM_spir64 == Triple::spir64, "");
958static_assert((Triple::ArchType)ZigLLVM_kalimba == Triple::kalimba, "");
959static_assert((Triple::ArchType)ZigLLVM_shave == Triple::shave, "");
960static_assert((Triple::ArchType)ZigLLVM_lanai == Triple::lanai, "");
961static_assert((Triple::ArchType)ZigLLVM_wasm32 == Triple::wasm32, "");
962static_assert((Triple::ArchType)ZigLLVM_wasm64 == Triple::wasm64, "");
963static_assert((Triple::ArchType)ZigLLVM_renderscript32 == Triple::renderscript32, "");
964static_assert((Triple::ArchType)ZigLLVM_renderscript64 == Triple::renderscript64, "");
965static_assert((Triple::ArchType)ZigLLVM_LastArchType == Triple::LastArchType, "");
966
967static_assert((Triple::SubArchType)ZigLLVM_NoSubArch == Triple::NoSubArch, "");
968static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_4a == Triple::ARMSubArch_v8_4a, "");
969static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_3a == Triple::ARMSubArch_v8_3a, "");
970static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_2a == Triple::ARMSubArch_v8_2a, "");
971static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_1a == Triple::ARMSubArch_v8_1a, "");
972static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8 == Triple::ARMSubArch_v8, "");
973static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8r == Triple::ARMSubArch_v8r, "");
974static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8m_baseline == Triple::ARMSubArch_v8m_baseline, "");
975static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8m_mainline == Triple::ARMSubArch_v8m_mainline, "");
976static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7 == Triple::ARMSubArch_v7, "");
977static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7em == Triple::ARMSubArch_v7em, "");
978static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7m == Triple::ARMSubArch_v7m, "");
979static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7s == Triple::ARMSubArch_v7s, "");
980static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7k == Triple::ARMSubArch_v7k, "");
981static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7ve == Triple::ARMSubArch_v7ve, "");
982static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6 == Triple::ARMSubArch_v6, "");
983static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6m == Triple::ARMSubArch_v6m, "");
984static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6k == Triple::ARMSubArch_v6k, "");
985static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6t2 == Triple::ARMSubArch_v6t2, "");
986static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v5 == Triple::ARMSubArch_v5, "");
987static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v5te == Triple::ARMSubArch_v5te, "");
988static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v4t == Triple::ARMSubArch_v4t, "");
989static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v3 == Triple::KalimbaSubArch_v3, "");
990static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v4 == Triple::KalimbaSubArch_v4, "");
991static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v5 == Triple::KalimbaSubArch_v5, "");
992static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v5 == Triple::KalimbaSubArch_v5, "");
993static_assert((Triple::SubArchType)ZigLLVM_MipsSubArch_r6 == Triple::MipsSubArch_r6, "");
994
995static_assert((Triple::VendorType)ZigLLVM_UnknownVendor == Triple::UnknownVendor, "");
996static_assert((Triple::VendorType)ZigLLVM_Apple == Triple::Apple, "");
997static_assert((Triple::VendorType)ZigLLVM_PC == Triple::PC, "");
998static_assert((Triple::VendorType)ZigLLVM_SCEI == Triple::SCEI, "");
999static_assert((Triple::VendorType)ZigLLVM_BGP == Triple::BGP, "");
1000static_assert((Triple::VendorType)ZigLLVM_BGQ == Triple::BGQ, "");
1001static_assert((Triple::VendorType)ZigLLVM_Freescale == Triple::Freescale, "");
1002static_assert((Triple::VendorType)ZigLLVM_IBM == Triple::IBM, "");
1003static_assert((Triple::VendorType)ZigLLVM_ImaginationTechnologies == Triple::ImaginationTechnologies, "");
1004static_assert((Triple::VendorType)ZigLLVM_MipsTechnologies == Triple::MipsTechnologies, "");
1005static_assert((Triple::VendorType)ZigLLVM_NVIDIA == Triple::NVIDIA, "");
1006static_assert((Triple::VendorType)ZigLLVM_CSR == Triple::CSR, "");
1007static_assert((Triple::VendorType)ZigLLVM_Myriad == Triple::Myriad, "");
1008static_assert((Triple::VendorType)ZigLLVM_AMD == Triple::AMD, "");
1009static_assert((Triple::VendorType)ZigLLVM_Mesa == Triple::Mesa, "");
1010static_assert((Triple::VendorType)ZigLLVM_SUSE == Triple::SUSE, "");
1011static_assert((Triple::VendorType)ZigLLVM_OpenEmbedded == Triple::OpenEmbedded, "");
1012static_assert((Triple::VendorType)ZigLLVM_LastVendorType == Triple::LastVendorType, "");
1013
1014static_assert((Triple::OSType)ZigLLVM_UnknownOS == Triple::UnknownOS, "");
1015static_assert((Triple::OSType)ZigLLVM_Ananas == Triple::Ananas, "");
1016static_assert((Triple::OSType)ZigLLVM_CloudABI == Triple::CloudABI, "");
1017static_assert((Triple::OSType)ZigLLVM_Darwin == Triple::Darwin, "");
1018static_assert((Triple::OSType)ZigLLVM_DragonFly == Triple::DragonFly, "");
1019static_assert((Triple::OSType)ZigLLVM_FreeBSD == Triple::FreeBSD, "");
1020static_assert((Triple::OSType)ZigLLVM_Fuchsia == Triple::Fuchsia, "");
1021static_assert((Triple::OSType)ZigLLVM_IOS == Triple::IOS, "");
1022static_assert((Triple::OSType)ZigLLVM_KFreeBSD == Triple::KFreeBSD, "");
1023static_assert((Triple::OSType)ZigLLVM_Linux == Triple::Linux, "");
1024static_assert((Triple::OSType)ZigLLVM_Lv2 == Triple::Lv2, "");
1025static_assert((Triple::OSType)ZigLLVM_MacOSX == Triple::MacOSX, "");
1026static_assert((Triple::OSType)ZigLLVM_NetBSD == Triple::NetBSD, "");
1027static_assert((Triple::OSType)ZigLLVM_OpenBSD == Triple::OpenBSD, "");
1028static_assert((Triple::OSType)ZigLLVM_Solaris == Triple::Solaris, "");
1029static_assert((Triple::OSType)ZigLLVM_Win32 == Triple::Win32, "");
1030static_assert((Triple::OSType)ZigLLVM_Haiku == Triple::Haiku, "");
1031static_assert((Triple::OSType)ZigLLVM_Minix == Triple::Minix, "");
1032static_assert((Triple::OSType)ZigLLVM_RTEMS == Triple::RTEMS, "");
1033static_assert((Triple::OSType)ZigLLVM_NaCl == Triple::NaCl, "");
1034static_assert((Triple::OSType)ZigLLVM_CNK == Triple::CNK, "");
1035static_assert((Triple::OSType)ZigLLVM_AIX == Triple::AIX, "");
1036static_assert((Triple::OSType)ZigLLVM_CUDA == Triple::CUDA, "");
1037static_assert((Triple::OSType)ZigLLVM_NVCL == Triple::NVCL, "");
1038static_assert((Triple::OSType)ZigLLVM_AMDHSA == Triple::AMDHSA, "");
1039static_assert((Triple::OSType)ZigLLVM_PS4 == Triple::PS4, "");
1040static_assert((Triple::OSType)ZigLLVM_ELFIAMCU == Triple::ELFIAMCU, "");
1041static_assert((Triple::OSType)ZigLLVM_TvOS == Triple::TvOS, "");
1042static_assert((Triple::OSType)ZigLLVM_WatchOS == Triple::WatchOS, "");
1043static_assert((Triple::OSType)ZigLLVM_Mesa3D == Triple::Mesa3D, "");
1044static_assert((Triple::OSType)ZigLLVM_Contiki == Triple::Contiki, "");
1045static_assert((Triple::OSType)ZigLLVM_AMDPAL == Triple::AMDPAL, "");
1046static_assert((Triple::OSType)ZigLLVM_LastOSType == Triple::LastOSType, "");
1047
1048static_assert((Triple::EnvironmentType)ZigLLVM_UnknownEnvironment == Triple::UnknownEnvironment, "");
1049static_assert((Triple::EnvironmentType)ZigLLVM_GNU == Triple::GNU, "");
1050static_assert((Triple::EnvironmentType)ZigLLVM_GNUABIN32 == Triple::GNUABIN32, "");
1051static_assert((Triple::EnvironmentType)ZigLLVM_GNUABI64 == Triple::GNUABI64, "");
1052static_assert((Triple::EnvironmentType)ZigLLVM_GNUEABI == Triple::GNUEABI, "");
1053static_assert((Triple::EnvironmentType)ZigLLVM_GNUEABIHF == Triple::GNUEABIHF, "");
1054static_assert((Triple::EnvironmentType)ZigLLVM_GNUX32 == Triple::GNUX32, "");
1055static_assert((Triple::EnvironmentType)ZigLLVM_CODE16 == Triple::CODE16, "");
1056static_assert((Triple::EnvironmentType)ZigLLVM_EABI == Triple::EABI, "");
1057static_assert((Triple::EnvironmentType)ZigLLVM_EABIHF == Triple::EABIHF, "");
1058static_assert((Triple::EnvironmentType)ZigLLVM_Android == Triple::Android, "");
1059static_assert((Triple::EnvironmentType)ZigLLVM_Musl == Triple::Musl, "");
1060static_assert((Triple::EnvironmentType)ZigLLVM_MuslEABI == Triple::MuslEABI, "");
1061static_assert((Triple::EnvironmentType)ZigLLVM_MuslEABIHF == Triple::MuslEABIHF, "");
1062static_assert((Triple::EnvironmentType)ZigLLVM_MSVC == Triple::MSVC, "");
1063static_assert((Triple::EnvironmentType)ZigLLVM_Itanium == Triple::Itanium, "");
1064static_assert((Triple::EnvironmentType)ZigLLVM_Cygnus == Triple::Cygnus, "");
1065static_assert((Triple::EnvironmentType)ZigLLVM_CoreCLR == Triple::CoreCLR, "");
1066static_assert((Triple::EnvironmentType)ZigLLVM_Simulator == Triple::Simulator, "");
1067static_assert((Triple::EnvironmentType)ZigLLVM_LastEnvironmentType == Triple::LastEnvironmentType, "");
1068
1069static_assert((Triple::ObjectFormatType)ZigLLVM_UnknownObjectFormat == Triple::UnknownObjectFormat, "");
1070static_assert((Triple::ObjectFormatType)ZigLLVM_COFF == Triple::COFF, "");
1071static_assert((Triple::ObjectFormatType)ZigLLVM_ELF == Triple::ELF, "");
1072static_assert((Triple::ObjectFormatType)ZigLLVM_MachO == Triple::MachO, "");
1073static_assert((Triple::ObjectFormatType)ZigLLVM_Wasm == Triple::Wasm, "");
std/array_list.zig+11
...@@ -398,3 +398,14 @@ test "std.ArrayList.insertSlice" {...@@ -398,3 +398,14 @@ test "std.ArrayList.insertSlice" {
398 assert(list.len == 6);398 assert(list.len == 6);
399 assert(list.items[0] == 1);399 assert(list.items[0] == 1);
400}400}
401
402const Item = struct {
403 integer: i32,
404 sub_items: ArrayList(Item),
405};
406
407test "std.ArrayList: ArrayList(T) of struct T" {
408 var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(debug.global_allocator) };
409 try root.sub_items.append( Item{ .integer = 42, .sub_items = ArrayList(Item).init(debug.global_allocator) } );
410 assert(root.sub_items.items[0].integer == 42);
411}
std/atomic/int.zig+4
...@@ -26,6 +26,10 @@ pub fn Int(comptime T: type) type {...@@ -26,6 +26,10 @@ pub fn Int(comptime T: type) type {
26 return @atomicLoad(T, &self.unprotected_value, AtomicOrder.SeqCst);26 return @atomicLoad(T, &self.unprotected_value, AtomicOrder.SeqCst);
27 }27 }
2828
29 pub fn set(self: *Self, new_value: T) void {
30 _ = self.xchg(new_value);
31 }
32
29 pub fn xchg(self: *Self, new_value: T) T {33 pub fn xchg(self: *Self, new_value: T) T {
30 return @atomicRmw(T, &self.unprotected_value, builtin.AtomicRmwOp.Xchg, new_value, AtomicOrder.SeqCst);34 return @atomicRmw(T, &self.unprotected_value, builtin.AtomicRmwOp.Xchg, new_value, AtomicOrder.SeqCst);
31 }35 }
std/buf_map.zig+27-9
...@@ -16,7 +16,7 @@ pub const BufMap = struct {...@@ -16,7 +16,7 @@ pub const BufMap = struct {
16 return self;16 return self;
17 }17 }
1818
19 pub fn deinit(self: *const BufMap) void {19 pub fn deinit(self: *BufMap) void {
20 var it = self.hash_map.iterator();20 var it = self.hash_map.iterator();
21 while (true) {21 while (true) {
22 const entry = it.next() orelse break;22 const entry = it.next() orelse break;
...@@ -27,16 +27,34 @@ pub const BufMap = struct {...@@ -27,16 +27,34 @@ pub const BufMap = struct {
27 self.hash_map.deinit();27 self.hash_map.deinit();
28 }28 }
2929
30 /// Same as `set` but the key and value become owned by the BufMap rather
31 /// than being copied.
32 /// If `setMove` fails, the ownership of key and value does not transfer.
33 pub fn setMove(self: *BufMap, key: []u8, value: []u8) !void {
34 const get_or_put = try self.hash_map.getOrPut(key);
35 if (get_or_put.found_existing) {
36 self.free(get_or_put.kv.key);
37 get_or_put.kv.key = key;
38 }
39 get_or_put.kv.value = value;
40 }
41
42 /// `key` and `value` are copied into the BufMap.
30 pub fn set(self: *BufMap, key: []const u8, value: []const u8) !void {43 pub fn set(self: *BufMap, key: []const u8, value: []const u8) !void {
31 self.delete(key);
32 const key_copy = try self.copy(key);
33 errdefer self.free(key_copy);
34 const value_copy = try self.copy(value);44 const value_copy = try self.copy(value);
35 errdefer self.free(value_copy);45 errdefer self.free(value_copy);
36 _ = try self.hash_map.put(key_copy, value_copy);46 // Avoid copying key if it already exists
47 const get_or_put = try self.hash_map.getOrPut(key);
48 if (!get_or_put.found_existing) {
49 get_or_put.kv.key = self.copy(key) catch |err| {
50 _ = self.hash_map.remove(key);
51 return err;
52 };
53 }
54 get_or_put.kv.value = value_copy;
37 }55 }
3856
39 pub fn get(self: *const BufMap, key: []const u8) ?[]const u8 {57 pub fn get(self: BufMap, key: []const u8) ?[]const u8 {
40 const entry = self.hash_map.get(key) orelse return null;58 const entry = self.hash_map.get(key) orelse return null;
41 return entry.value;59 return entry.value;
42 }60 }
...@@ -47,7 +65,7 @@ pub const BufMap = struct {...@@ -47,7 +65,7 @@ pub const BufMap = struct {
47 self.free(entry.value);65 self.free(entry.value);
48 }66 }
4967
50 pub fn count(self: *const BufMap) usize {68 pub fn count(self: BufMap) usize {
51 return self.hash_map.count();69 return self.hash_map.count();
52 }70 }
5371
...@@ -55,11 +73,11 @@ pub const BufMap = struct {...@@ -55,11 +73,11 @@ pub const BufMap = struct {
55 return self.hash_map.iterator();73 return self.hash_map.iterator();
56 }74 }
5775
58 fn free(self: *const BufMap, value: []const u8) void {76 fn free(self: BufMap, value: []const u8) void {
59 self.hash_map.allocator.free(value);77 self.hash_map.allocator.free(value);
60 }78 }
6179
62 fn copy(self: *const BufMap, value: []const u8) ![]const u8 {80 fn copy(self: BufMap, value: []const u8) ![]u8 {
63 return mem.dupe(self.hash_map.allocator, u8, value);81 return mem.dupe(self.hash_map.allocator, u8, value);
64 }82 }
65};83};
std/build.zig+38-8
...@@ -150,7 +150,11 @@ pub const Builder = struct {...@@ -150,7 +150,11 @@ pub const Builder = struct {
150 }150 }
151151
152 pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {152 pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
153 return LibExeObjStep.createExecutable(self, name, root_src);153 return LibExeObjStep.createExecutable(self, name, root_src, false);
154 }
155
156 pub fn addStaticExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
157 return LibExeObjStep.createExecutable(self, name, root_src, true);
154 }158 }
155159
156 pub fn addObject(self: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep {160 pub fn addObject(self: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep {
...@@ -795,11 +799,23 @@ pub const Target = union(enum) {...@@ -795,11 +799,23 @@ pub const Target = union(enum) {
795 };799 };
796 }800 }
797801
802 pub fn isFreeBSD(self: *const Target) bool {
803 return switch (self.getOs()) {
804 builtin.Os.freebsd => true,
805 else => false,
806 };
807 }
808
798 pub fn wantSharedLibSymLinks(self: *const Target) bool {809 pub fn wantSharedLibSymLinks(self: *const Target) bool {
799 return !self.isWindows();810 return !self.isWindows();
800 }811 }
801};812};
802813
814const Pkg = struct {
815 name: []const u8,
816 path: []const u8,
817};
818
803pub const LibExeObjStep = struct {819pub const LibExeObjStep = struct {
804 step: Step,820 step: Step,
805 builder: *Builder,821 builder: *Builder,
...@@ -842,11 +858,6 @@ pub const LibExeObjStep = struct {...@@ -842,11 +858,6 @@ pub const LibExeObjStep = struct {
842 source_files: ArrayList([]const u8),858 source_files: ArrayList([]const u8),
843 object_src: []const u8,859 object_src: []const u8,
844860
845 const Pkg = struct {
846 name: []const u8,
847 path: []const u8,
848 };
849
850 const Kind = enum {861 const Kind = enum {
851 Exe,862 Exe,
852 Lib,863 Lib,
...@@ -884,8 +895,8 @@ pub const LibExeObjStep = struct {...@@ -884,8 +895,8 @@ pub const LibExeObjStep = struct {
884 return self;895 return self;
885 }896 }
886897
887 pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {898 pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8, static: bool) *LibExeObjStep {
888 const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0))) catch unreachable;899 const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Exe, static, builder.version(0, 0, 0))) catch unreachable;
889 return self;900 return self;
890 }901 }
891902
...@@ -1263,6 +1274,9 @@ pub const LibExeObjStep = struct {...@@ -1263,6 +1274,9 @@ pub const LibExeObjStep = struct {
1263 zig_args.append("--ver-patch") catch unreachable;1274 zig_args.append("--ver-patch") catch unreachable;
1264 zig_args.append(builder.fmt("{}", self.version.patch)) catch unreachable;1275 zig_args.append(builder.fmt("{}", self.version.patch)) catch unreachable;
1265 }1276 }
1277 if (self.kind == Kind.Exe and self.static) {
1278 zig_args.append("--static") catch unreachable;
1279 }
12661280
1267 switch (self.target) {1281 switch (self.target) {
1268 Target.Native => {},1282 Target.Native => {},
...@@ -1653,6 +1667,7 @@ pub const TestStep = struct {...@@ -1653,6 +1667,7 @@ pub const TestStep = struct {
1653 exec_cmd_args: ?[]const ?[]const u8,1667 exec_cmd_args: ?[]const ?[]const u8,
1654 include_dirs: ArrayList([]const u8),1668 include_dirs: ArrayList([]const u8),
1655 lib_paths: ArrayList([]const u8),1669 lib_paths: ArrayList([]const u8),
1670 packages: ArrayList(Pkg),
1656 object_files: ArrayList([]const u8),1671 object_files: ArrayList([]const u8),
1657 no_rosegment: bool,1672 no_rosegment: bool,
1658 output_path: ?[]const u8,1673 output_path: ?[]const u8,
...@@ -1673,6 +1688,7 @@ pub const TestStep = struct {...@@ -1673,6 +1688,7 @@ pub const TestStep = struct {
1673 .exec_cmd_args = null,1688 .exec_cmd_args = null,
1674 .include_dirs = ArrayList([]const u8).init(builder.allocator),1689 .include_dirs = ArrayList([]const u8).init(builder.allocator),
1675 .lib_paths = ArrayList([]const u8).init(builder.allocator),1690 .lib_paths = ArrayList([]const u8).init(builder.allocator),
1691 .packages = ArrayList(Pkg).init(builder.allocator),
1676 .object_files = ArrayList([]const u8).init(builder.allocator),1692 .object_files = ArrayList([]const u8).init(builder.allocator),
1677 .no_rosegment = false,1693 .no_rosegment = false,
1678 .output_path = null,1694 .output_path = null,
...@@ -1688,6 +1704,13 @@ pub const TestStep = struct {...@@ -1688,6 +1704,13 @@ pub const TestStep = struct {
1688 self.lib_paths.append(path) catch unreachable;1704 self.lib_paths.append(path) catch unreachable;
1689 }1705 }
16901706
1707 pub fn addPackagePath(self: *TestStep, name: []const u8, pkg_index_path: []const u8) void {
1708 self.packages.append(Pkg{
1709 .name = name,
1710 .path = pkg_index_path,
1711 }) catch unreachable;
1712 }
1713
1691 pub fn setVerbose(self: *TestStep, value: bool) void {1714 pub fn setVerbose(self: *TestStep, value: bool) void {
1692 self.verbose = value;1715 self.verbose = value;
1693 }1716 }
...@@ -1864,6 +1887,13 @@ pub const TestStep = struct {...@@ -1864,6 +1887,13 @@ pub const TestStep = struct {
1864 try zig_args.append(lib_path);1887 try zig_args.append(lib_path);
1865 }1888 }
18661889
1890 for (self.packages.toSliceConst()) |pkg| {
1891 zig_args.append("--pkg-begin") catch unreachable;
1892 zig_args.append(pkg.name) catch unreachable;
1893 zig_args.append(builder.pathFromRoot(pkg.path)) catch unreachable;
1894 zig_args.append("--pkg-end") catch unreachable;
1895 }
1896
1867 if (self.no_rosegment) {1897 if (self.no_rosegment) {
1868 try zig_args.append("--no-rosegment");1898 try zig_args.append("--no-rosegment");
1869 }1899 }
std/c/freebsd.zig created+33
...@@ -0,0 +1,33 @@
1const timespec = @import("../os/freebsd/index.zig").timespec;
2
3extern "c" fn __error() *c_int;
4pub const _errno = __error;
5
6pub extern "c" fn kqueue() c_int;
7pub 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;
15pub extern "c" fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
16pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
17pub 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.
20pub 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
30pub const pthread_attr_t = extern struct {
31 __size: [56]u8,
32 __align: c_long,
33};
std/c/index.zig+1
...@@ -5,6 +5,7 @@ pub use switch (builtin.os) {...@@ -5,6 +5,7 @@ pub use switch (builtin.os) {
5 Os.linux => @import("linux.zig"),5 Os.linux => @import("linux.zig"),
6 Os.windows => @import("windows.zig"),6 Os.windows => @import("windows.zig"),
7 Os.macosx, Os.ios => @import("darwin.zig"),7 Os.macosx, Os.ios => @import("darwin.zig"),
8 Os.freebsd => @import("freebsd.zig"),
8 else => empty_import,9 else => empty_import,
9};10};
10const empty_import = @import("../empty.zig");11const empty_import = @import("../empty.zig");
std/coff.zig+22-22
...@@ -51,7 +51,7 @@ pub const Coff = struct {...@@ -51,7 +51,7 @@ pub const Coff = struct {
5151
52 // Seek to PE File Header (coff header)52 // Seek to PE File Header (coff header)
53 try self.in_file.seekTo(pe_pointer_offset);53 try self.in_file.seekTo(pe_pointer_offset);
54 const pe_magic_offset = try in.readIntLe(u32);54 const pe_magic_offset = try in.readIntLittle(u32);
55 try self.in_file.seekTo(pe_magic_offset);55 try self.in_file.seekTo(pe_magic_offset);
5656
57 var pe_header_magic: [4]u8 = undefined;57 var pe_header_magic: [4]u8 = undefined;
...@@ -60,13 +60,13 @@ pub const Coff = struct {...@@ -60,13 +60,13 @@ pub const Coff = struct {
60 return error.InvalidPEHeader;60 return error.InvalidPEHeader;
6161
62 self.coff_header = CoffHeader{62 self.coff_header = CoffHeader{
63 .machine = try in.readIntLe(u16),63 .machine = try in.readIntLittle(u16),
64 .number_of_sections = try in.readIntLe(u16),64 .number_of_sections = try in.readIntLittle(u16),
65 .timedate_stamp = try in.readIntLe(u32),65 .timedate_stamp = try in.readIntLittle(u32),
66 .pointer_to_symbol_table = try in.readIntLe(u32),66 .pointer_to_symbol_table = try in.readIntLittle(u32),
67 .number_of_symbols = try in.readIntLe(u32),67 .number_of_symbols = try in.readIntLittle(u32),
68 .size_of_optional_header = try in.readIntLe(u16),68 .size_of_optional_header = try in.readIntLittle(u16),
69 .characteristics = try in.readIntLe(u16),69 .characteristics = try in.readIntLittle(u16),
70 };70 };
7171
72 switch (self.coff_header.machine) {72 switch (self.coff_header.machine) {
...@@ -79,7 +79,7 @@ pub const Coff = struct {...@@ -79,7 +79,7 @@ pub const Coff = struct {
7979
80 fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void {80 fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void {
81 const in = &file_stream.stream;81 const in = &file_stream.stream;
82 self.pe_header.magic = try in.readIntLe(u16);82 self.pe_header.magic = try in.readIntLittle(u16);
83 // For now we're only interested in finding the reference to the .pdb,83 // For now we're only interested in finding the reference to the .pdb,
84 // so we'll skip most of this header, which size is different in 3284 // so we'll skip most of this header, which size is different in 32
85 // 64 bits by the way.85 // 64 bits by the way.
...@@ -93,14 +93,14 @@ pub const Coff = struct {...@@ -93,14 +93,14 @@ pub const Coff = struct {
9393
94 try self.in_file.seekForward(skip_size);94 try self.in_file.seekForward(skip_size);
9595
96 const number_of_rva_and_sizes = try in.readIntLe(u32);96 const number_of_rva_and_sizes = try in.readIntLittle(u32);
97 if (number_of_rva_and_sizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES)97 if (number_of_rva_and_sizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
98 return error.InvalidPEHeader;98 return error.InvalidPEHeader;
9999
100 for (self.pe_header.data_directory) |*data_dir| {100 for (self.pe_header.data_directory) |*data_dir| {
101 data_dir.* = OptionalHeader.DataDirectory{101 data_dir.* = OptionalHeader.DataDirectory{
102 .virtual_address = try in.readIntLe(u32),102 .virtual_address = try in.readIntLittle(u32),
103 .size = try in.readIntLe(u32),103 .size = try in.readIntLittle(u32),
104 };104 };
105 }105 }
106 }106 }
...@@ -124,7 +124,7 @@ pub const Coff = struct {...@@ -124,7 +124,7 @@ pub const Coff = struct {
124 if (!mem.eql(u8, cv_signature, "RSDS"))124 if (!mem.eql(u8, cv_signature, "RSDS"))
125 return error.InvalidPEMagic;125 return error.InvalidPEMagic;
126 try in.readNoEof(self.guid[0..]);126 try in.readNoEof(self.guid[0..]);
127 self.age = try in.readIntLe(u32);127 self.age = try in.readIntLittle(u32);
128128
129 // Finally read the null-terminated string.129 // Finally read the null-terminated string.
130 var byte = try in.readByte();130 var byte = try in.readByte();
...@@ -157,15 +157,15 @@ pub const Coff = struct {...@@ -157,15 +157,15 @@ pub const Coff = struct {
157 try self.sections.append(Section{157 try self.sections.append(Section{
158 .header = SectionHeader{158 .header = SectionHeader{
159 .name = name,159 .name = name,
160 .misc = SectionHeader.Misc{ .physical_address = try in.readIntLe(u32) },160 .misc = SectionHeader.Misc{ .physical_address = try in.readIntLittle(u32) },
161 .virtual_address = try in.readIntLe(u32),161 .virtual_address = try in.readIntLittle(u32),
162 .size_of_raw_data = try in.readIntLe(u32),162 .size_of_raw_data = try in.readIntLittle(u32),
163 .pointer_to_raw_data = try in.readIntLe(u32),163 .pointer_to_raw_data = try in.readIntLittle(u32),
164 .pointer_to_relocations = try in.readIntLe(u32),164 .pointer_to_relocations = try in.readIntLittle(u32),
165 .pointer_to_line_numbers = try in.readIntLe(u32),165 .pointer_to_line_numbers = try in.readIntLittle(u32),
166 .number_of_relocations = try in.readIntLe(u16),166 .number_of_relocations = try in.readIntLittle(u16),
167 .number_of_line_numbers = try in.readIntLe(u16),167 .number_of_line_numbers = try in.readIntLittle(u16),
168 .characteristics = try in.readIntLe(u32),168 .characteristics = try in.readIntLittle(u32),
169 },169 },
170 });170 });
171 }171 }
std/crypto/blake2.zig+7-4
...@@ -123,7 +123,8 @@ fn Blake2s(comptime out_len: usize) type {...@@ -123,7 +123,8 @@ fn Blake2s(comptime out_len: usize) type {
123 const rr = d.h[0 .. out_len / 32];123 const rr = d.h[0 .. out_len / 32];
124124
125 for (rr) |s, j| {125 for (rr) |s, j| {
126 mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Little);126 // TODO https://github.com/ziglang/zig/issues/863
127 mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s);
127 }128 }
128 }129 }
129130
...@@ -134,7 +135,8 @@ fn Blake2s(comptime out_len: usize) type {...@@ -134,7 +135,8 @@ fn Blake2s(comptime out_len: usize) type {
134 var v: [16]u32 = undefined;135 var v: [16]u32 = undefined;
135136
136 for (m) |*r, i| {137 for (m) |*r, i| {
137 r.* = mem.readIntLE(u32, b[4 * i .. 4 * i + 4]);138 // TODO https://github.com/ziglang/zig/issues/863
139 r.* = mem.readIntSliceLittle(u32, b[4 * i .. 4 * i + 4]);
138 }140 }
139141
140 var k: usize = 0;142 var k: usize = 0;
...@@ -356,7 +358,8 @@ fn Blake2b(comptime out_len: usize) type {...@@ -356,7 +358,8 @@ fn Blake2b(comptime out_len: usize) type {
356 const rr = d.h[0 .. out_len / 64];358 const rr = d.h[0 .. out_len / 64];
357359
358 for (rr) |s, j| {360 for (rr) |s, j| {
359 mem.writeInt(out[8 * j .. 8 * j + 8], s, builtin.Endian.Little);361 // TODO https://github.com/ziglang/zig/issues/863
362 mem.writeIntSliceLittle(u64, out[8 * j .. 8 * j + 8], s);
360 }363 }
361 }364 }
362365
...@@ -367,7 +370,7 @@ fn Blake2b(comptime out_len: usize) type {...@@ -367,7 +370,7 @@ fn Blake2b(comptime out_len: usize) type {
367 var v: [16]u64 = undefined;370 var v: [16]u64 = undefined;
368371
369 for (m) |*r, i| {372 for (m) |*r, i| {
370 r.* = mem.readIntLE(u64, b[8 * i .. 8 * i + 8]);373 r.* = mem.readIntSliceLittle(u64, b[8 * i .. 8 * i + 8]);
371 }374 }
372375
373 var k: usize = 0;376 var k: usize = 0;
std/crypto/chacha20.zig+27-26
...@@ -59,7 +59,8 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void {...@@ -59,7 +59,8 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void {
59 }59 }
6060
61 for (x) |_, i| {61 for (x) |_, i| {
62 mem.writeInt(out[4 * i .. 4 * i + 4], x[i] +% input[i], builtin.Endian.Little);62 // TODO https://github.com/ziglang/zig/issues/863
63 mem.writeIntSliceLittle(u32, out[4 * i .. 4 * i + 4], x[i] +% input[i]);
63 }64 }
64}65}
6566
...@@ -70,10 +71,10 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo...@@ -70,10 +71,10 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo
7071
71 const c = "expand 32-byte k";72 const c = "expand 32-byte k";
72 const constant_le = []u32{73 const constant_le = []u32{
73 mem.readIntLE(u32, c[0..4]),74 mem.readIntSliceLittle(u32, c[0..4]),
74 mem.readIntLE(u32, c[4..8]),75 mem.readIntSliceLittle(u32, c[4..8]),
75 mem.readIntLE(u32, c[8..12]),76 mem.readIntSliceLittle(u32, c[8..12]),
76 mem.readIntLE(u32, c[12..16]),77 mem.readIntSliceLittle(u32, c[12..16]),
77 };78 };
7879
79 mem.copy(u32, ctx[0..], constant_le[0..4]);80 mem.copy(u32, ctx[0..], constant_le[0..4]);
...@@ -117,19 +118,19 @@ pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce:...@@ -117,19 +118,19 @@ pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce:
117 var k: [8]u32 = undefined;118 var k: [8]u32 = undefined;
118 var c: [4]u32 = undefined;119 var c: [4]u32 = undefined;
119120
120 k[0] = mem.readIntLE(u32, key[0..4]);121 k[0] = mem.readIntSliceLittle(u32, key[0..4]);
121 k[1] = mem.readIntLE(u32, key[4..8]);122 k[1] = mem.readIntSliceLittle(u32, key[4..8]);
122 k[2] = mem.readIntLE(u32, key[8..12]);123 k[2] = mem.readIntSliceLittle(u32, key[8..12]);
123 k[3] = mem.readIntLE(u32, key[12..16]);124 k[3] = mem.readIntSliceLittle(u32, key[12..16]);
124 k[4] = mem.readIntLE(u32, key[16..20]);125 k[4] = mem.readIntSliceLittle(u32, key[16..20]);
125 k[5] = mem.readIntLE(u32, key[20..24]);126 k[5] = mem.readIntSliceLittle(u32, key[20..24]);
126 k[6] = mem.readIntLE(u32, key[24..28]);127 k[6] = mem.readIntSliceLittle(u32, key[24..28]);
127 k[7] = mem.readIntLE(u32, key[28..32]);128 k[7] = mem.readIntSliceLittle(u32, key[28..32]);
128129
129 c[0] = counter;130 c[0] = counter;
130 c[1] = mem.readIntLE(u32, nonce[0..4]);131 c[1] = mem.readIntSliceLittle(u32, nonce[0..4]);
131 c[2] = mem.readIntLE(u32, nonce[4..8]);132 c[2] = mem.readIntSliceLittle(u32, nonce[4..8]);
132 c[3] = mem.readIntLE(u32, nonce[8..12]);133 c[3] = mem.readIntSliceLittle(u32, nonce[8..12]);
133 chaCha20_internal(out, in, k, c);134 chaCha20_internal(out, in, k, c);
134}135}
135136
...@@ -144,19 +145,19 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]...@@ -144,19 +145,19 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]
144 var k: [8]u32 = undefined;145 var k: [8]u32 = undefined;
145 var c: [4]u32 = undefined;146 var c: [4]u32 = undefined;
146147
147 k[0] = mem.readIntLE(u32, key[0..4]);148 k[0] = mem.readIntSliceLittle(u32, key[0..4]);
148 k[1] = mem.readIntLE(u32, key[4..8]);149 k[1] = mem.readIntSliceLittle(u32, key[4..8]);
149 k[2] = mem.readIntLE(u32, key[8..12]);150 k[2] = mem.readIntSliceLittle(u32, key[8..12]);
150 k[3] = mem.readIntLE(u32, key[12..16]);151 k[3] = mem.readIntSliceLittle(u32, key[12..16]);
151 k[4] = mem.readIntLE(u32, key[16..20]);152 k[4] = mem.readIntSliceLittle(u32, key[16..20]);
152 k[5] = mem.readIntLE(u32, key[20..24]);153 k[5] = mem.readIntSliceLittle(u32, key[20..24]);
153 k[6] = mem.readIntLE(u32, key[24..28]);154 k[6] = mem.readIntSliceLittle(u32, key[24..28]);
154 k[7] = mem.readIntLE(u32, key[28..32]);155 k[7] = mem.readIntSliceLittle(u32, key[28..32]);
155156
156 c[0] = @truncate(u32, counter);157 c[0] = @truncate(u32, counter);
157 c[1] = @truncate(u32, counter >> 32);158 c[1] = @truncate(u32, counter >> 32);
158 c[2] = mem.readIntLE(u32, nonce[0..4]);159 c[2] = mem.readIntSliceLittle(u32, nonce[0..4]);
159 c[3] = mem.readIntLE(u32, nonce[4..8]);160 c[3] = mem.readIntSliceLittle(u32, nonce[4..8]);
160161
161 const block_size = (1 << 6);162 const block_size = (1 << 6);
162 const big_block = (block_size << 32);163 const big_block = (block_size << 32);
std/crypto/md5.zig+2-1
...@@ -112,7 +112,8 @@ pub const Md5 = struct {...@@ -112,7 +112,8 @@ pub const Md5 = struct {
112 d.round(d.buf[0..]);112 d.round(d.buf[0..]);
113113
114 for (d.s) |s, j| {114 for (d.s) |s, j| {
115 mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Little);115 // TODO https://github.com/ziglang/zig/issues/863
116 mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s);
116 }117 }
117 }118 }
118119
std/crypto/poly1305.zig+14-13
...@@ -6,8 +6,8 @@ const std = @import("../index.zig");...@@ -6,8 +6,8 @@ const std = @import("../index.zig");
6const builtin = @import("builtin");6const builtin = @import("builtin");
77
8const Endian = builtin.Endian;8const Endian = builtin.Endian;
9const readInt = std.mem.readInt;9const readIntSliceLittle = std.mem.readIntSliceLittle;
10const writeInt = std.mem.writeInt;10const writeIntSliceLittle = std.mem.writeIntSliceLittle;
1111
12pub const Poly1305 = struct {12pub const Poly1305 = struct {
13 const Self = @This();13 const Self = @This();
...@@ -59,19 +59,19 @@ pub const Poly1305 = struct {...@@ -59,19 +59,19 @@ pub const Poly1305 = struct {
59 {59 {
60 var i: usize = 0;60 var i: usize = 0;
61 while (i < 1) : (i += 1) {61 while (i < 1) : (i += 1) {
62 ctx.r[0] = readInt(key[0..4], u32, Endian.Little) & 0x0fffffff;62 ctx.r[0] = readIntSliceLittle(u32, key[0..4]) & 0x0fffffff;
63 }63 }
64 }64 }
65 {65 {
66 var i: usize = 1;66 var i: usize = 1;
67 while (i < 4) : (i += 1) {67 while (i < 4) : (i += 1) {
68 ctx.r[i] = readInt(key[i * 4 .. i * 4 + 4], u32, Endian.Little) & 0x0ffffffc;68 ctx.r[i] = readIntSliceLittle(u32, key[i * 4 .. i * 4 + 4]) & 0x0ffffffc;
69 }69 }
70 }70 }
71 {71 {
72 var i: usize = 0;72 var i: usize = 0;
73 while (i < 4) : (i += 1) {73 while (i < 4) : (i += 1) {
74 ctx.pad[i] = readInt(key[i * 4 + 16 .. i * 4 + 16 + 4], u32, Endian.Little);74 ctx.pad[i] = readIntSliceLittle(u32, key[i * 4 + 16 .. i * 4 + 16 + 4]);
75 }75 }
76 }76 }
7777
...@@ -168,10 +168,10 @@ pub const Poly1305 = struct {...@@ -168,10 +168,10 @@ pub const Poly1305 = struct {
168 const nb_blocks = nmsg.len >> 4;168 const nb_blocks = nmsg.len >> 4;
169 var i: usize = 0;169 var i: usize = 0;
170 while (i < nb_blocks) : (i += 1) {170 while (i < nb_blocks) : (i += 1) {
171 ctx.c[0] = readInt(nmsg[0..4], u32, Endian.Little);171 ctx.c[0] = readIntSliceLittle(u32, nmsg[0..4]);
172 ctx.c[1] = readInt(nmsg[4..8], u32, Endian.Little);172 ctx.c[1] = readIntSliceLittle(u32, nmsg[4..8]);
173 ctx.c[2] = readInt(nmsg[8..12], u32, Endian.Little);173 ctx.c[2] = readIntSliceLittle(u32, nmsg[8..12]);
174 ctx.c[3] = readInt(nmsg[12..16], u32, Endian.Little);174 ctx.c[3] = readIntSliceLittle(u32, nmsg[12..16]);
175 polyBlock(ctx);175 polyBlock(ctx);
176 nmsg = nmsg[16..];176 nmsg = nmsg[16..];
177 }177 }
...@@ -210,10 +210,11 @@ pub const Poly1305 = struct {...@@ -210,10 +210,11 @@ pub const Poly1305 = struct {
210 const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000210 const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000
211 const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000211 const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000
212212
213 writeInt(out[0..], @truncate(u32, uu0), Endian.Little);213 // TODO https://github.com/ziglang/zig/issues/863
214 writeInt(out[4..], @truncate(u32, uu1), Endian.Little);214 writeIntSliceLittle(u32, out[0..], @truncate(u32, uu0));
215 writeInt(out[8..], @truncate(u32, uu2), Endian.Little);215 writeIntSliceLittle(u32, out[4..], @truncate(u32, uu1));
216 writeInt(out[12..], @truncate(u32, uu3), Endian.Little);216 writeIntSliceLittle(u32, out[8..], @truncate(u32, uu2));
217 writeIntSliceLittle(u32, out[12..], @truncate(u32, uu3));
217218
218 ctx.secureZero();219 ctx.secureZero();
219 }220 }
std/crypto/sha1.zig+2-1
...@@ -109,7 +109,8 @@ pub const Sha1 = struct {...@@ -109,7 +109,8 @@ pub const Sha1 = struct {
109 d.round(d.buf[0..]);109 d.round(d.buf[0..]);
110110
111 for (d.s) |s, j| {111 for (d.s) |s, j| {
112 mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Big);112 // TODO https://github.com/ziglang/zig/issues/863
113 mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s);
113 }114 }
114 }115 }
115116
std/crypto/sha2.zig+4-2
...@@ -167,7 +167,8 @@ fn Sha2_32(comptime params: Sha2Params32) type {...@@ -167,7 +167,8 @@ fn Sha2_32(comptime params: Sha2Params32) type {
167 const rr = d.s[0 .. params.out_len / 32];167 const rr = d.s[0 .. params.out_len / 32];
168168
169 for (rr) |s, j| {169 for (rr) |s, j| {
170 mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Big);170 // TODO https://github.com/ziglang/zig/issues/863
171 mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s);
171 }172 }
172 }173 }
173174
...@@ -508,7 +509,8 @@ fn Sha2_64(comptime params: Sha2Params64) type {...@@ -508,7 +509,8 @@ fn Sha2_64(comptime params: Sha2Params64) type {
508 const rr = d.s[0 .. params.out_len / 64];509 const rr = d.s[0 .. params.out_len / 64];
509510
510 for (rr) |s, j| {511 for (rr) |s, j| {
511 mem.writeInt(out[8 * j .. 8 * j + 8], s, builtin.Endian.Big);512 // TODO https://github.com/ziglang/zig/issues/863
513 mem.writeIntSliceBig(u64, out[8 * j .. 8 * j + 8], s);
512 }514 }
513 }515 }
514516
std/crypto/sha3.zig+3-2
...@@ -120,7 +120,7 @@ fn keccak_f(comptime F: usize, d: []u8) void {...@@ -120,7 +120,7 @@ fn keccak_f(comptime F: usize, d: []u8) void {
120 var c = []const u64{0} ** 5;120 var c = []const u64{0} ** 5;
121121
122 for (s) |*r, i| {122 for (s) |*r, i| {
123 r.* = mem.readIntLE(u64, d[8 * i .. 8 * i + 8]);123 r.* = mem.readIntSliceLittle(u64, d[8 * i .. 8 * i + 8]);
124 }124 }
125125
126 comptime var x: usize = 0;126 comptime var x: usize = 0;
...@@ -167,7 +167,8 @@ fn keccak_f(comptime F: usize, d: []u8) void {...@@ -167,7 +167,8 @@ fn keccak_f(comptime F: usize, d: []u8) void {
167 }167 }
168168
169 for (s) |r, i| {169 for (s) |r, i| {
170 mem.writeInt(d[8 * i .. 8 * i + 8], r, builtin.Endian.Little);170 // TODO https://github.com/ziglang/zig/issues/863
171 mem.writeIntSliceLittle(u64, d[8 * i .. 8 * i + 8], r);
171 }172 }
172}173}
173174
std/crypto/x25519.zig+21-20
...@@ -7,8 +7,8 @@ const builtin = @import("builtin");...@@ -7,8 +7,8 @@ const builtin = @import("builtin");
7const fmt = std.fmt;7const fmt = std.fmt;
88
9const Endian = builtin.Endian;9const Endian = builtin.Endian;
10const readInt = std.mem.readInt;10const readIntSliceLittle = std.mem.readIntSliceLittle;
11const writeInt = std.mem.writeInt;11const writeIntSliceLittle = std.mem.writeIntSliceLittle;
1212
13// Based on Supercop's ref10 implementation.13// Based on Supercop's ref10 implementation.
14pub const X25519 = struct {14pub const X25519 = struct {
...@@ -255,16 +255,16 @@ const Fe = struct {...@@ -255,16 +255,16 @@ const Fe = struct {
255255
256 var t: [10]i64 = undefined;256 var t: [10]i64 = undefined;
257257
258 t[0] = readInt(s[0..4], u32, Endian.Little);258 t[0] = readIntSliceLittle(u32, s[0..4]);
259 t[1] = readInt(s[4..7], u32, Endian.Little) << 6;259 t[1] = u32(readIntSliceLittle(u24, s[4..7])) << 6;
260 t[2] = readInt(s[7..10], u32, Endian.Little) << 5;260 t[2] = u32(readIntSliceLittle(u24, s[7..10])) << 5;
261 t[3] = readInt(s[10..13], u32, Endian.Little) << 3;261 t[3] = u32(readIntSliceLittle(u24, s[10..13])) << 3;
262 t[4] = readInt(s[13..16], u32, Endian.Little) << 2;262 t[4] = u32(readIntSliceLittle(u24, s[13..16])) << 2;
263 t[5] = readInt(s[16..20], u32, Endian.Little);263 t[5] = readIntSliceLittle(u32, s[16..20]);
264 t[6] = readInt(s[20..23], u32, Endian.Little) << 7;264 t[6] = u32(readIntSliceLittle(u24, s[20..23])) << 7;
265 t[7] = readInt(s[23..26], u32, Endian.Little) << 5;265 t[7] = u32(readIntSliceLittle(u24, s[23..26])) << 5;
266 t[8] = readInt(s[26..29], u32, Endian.Little) << 4;266 t[8] = u32(readIntSliceLittle(u24, s[26..29])) << 4;
267 t[9] = (readInt(s[29..32], u32, Endian.Little) & 0x7fffff) << 2;267 t[9] = (u32(readIntSliceLittle(u24, s[29..32])) & 0x7fffff) << 2;
268268
269 carry1(h, t[0..]);269 carry1(h, t[0..]);
270 }270 }
...@@ -544,14 +544,15 @@ const Fe = struct {...@@ -544,14 +544,15 @@ const Fe = struct {
544 ut[i] = @bitCast(u32, @intCast(i32, t[i]));544 ut[i] = @bitCast(u32, @intCast(i32, t[i]));
545 }545 }
546546
547 writeInt(s[0..], (ut[0] >> 0) | (ut[1] << 26), Endian.Little);547 // TODO https://github.com/ziglang/zig/issues/863
548 writeInt(s[4..], (ut[1] >> 6) | (ut[2] << 19), Endian.Little);548 writeIntSliceLittle(u32, s[0..4], (ut[0] >> 0) | (ut[1] << 26));
549 writeInt(s[8..], (ut[2] >> 13) | (ut[3] << 13), Endian.Little);549 writeIntSliceLittle(u32, s[4..8], (ut[1] >> 6) | (ut[2] << 19));
550 writeInt(s[12..], (ut[3] >> 19) | (ut[4] << 6), Endian.Little);550 writeIntSliceLittle(u32, s[8..12], (ut[2] >> 13) | (ut[3] << 13));
551 writeInt(s[16..], (ut[5] >> 0) | (ut[6] << 25), Endian.Little);551 writeIntSliceLittle(u32, s[12..16], (ut[3] >> 19) | (ut[4] << 6));
552 writeInt(s[20..], (ut[6] >> 7) | (ut[7] << 19), Endian.Little);552 writeIntSliceLittle(u32, s[16..20], (ut[5] >> 0) | (ut[6] << 25));
553 writeInt(s[24..], (ut[7] >> 13) | (ut[8] << 12), Endian.Little);553 writeIntSliceLittle(u32, s[20..24], (ut[6] >> 7) | (ut[7] << 19));
554 writeInt(s[28..], (ut[8] >> 20) | (ut[9] << 6), Endian.Little);554 writeIntSliceLittle(u32, s[24..28], (ut[7] >> 13) | (ut[8] << 12));
555 writeIntSliceLittle(u32, s[28..], (ut[8] >> 20) | (ut[9] << 6));
555556
556 std.mem.secureZero(i64, t[0..]);557 std.mem.secureZero(i64, t[0..]);
557 }558 }
std/debug/index.zig+261-238
...@@ -198,49 +198,44 @@ pub fn writeStackTrace(stack_trace: *const builtin.StackTrace, out_stream: var,...@@ -198,49 +198,44 @@ pub fn writeStackTrace(stack_trace: *const builtin.StackTrace, out_stream: var,
198 }198 }
199}199}
200200
201pub inline fn getReturnAddress(frame_count: usize) usize {201pub const StackIterator = struct {
202 var fp = @ptrToInt(@frameAddress());202 first_addr: ?usize,
203 var i: usize = 0;203 fp: usize,
204 while (fp != 0 and i < frame_count) {204
205 fp = @intToPtr(*const usize, fp).*;205 pub fn init(first_addr: ?usize) StackIterator {
206 i += 1;206 return StackIterator{
207 .first_addr = first_addr,
208 .fp = @ptrToInt(@frameAddress()),
209 };
207 }210 }
208 return @intToPtr(*const usize, fp + @sizeOf(usize)).*;211
209}212 fn next(self: *StackIterator) ?usize {
213 if (self.fp == 0) return null;
214 self.fp = @intToPtr(*const usize, self.fp).*;
215 if (self.fp == 0) return null;
216
217 if (self.first_addr) |addr| {
218 while (self.fp != 0) : (self.fp = @intToPtr(*const usize, self.fp).*) {
219 const return_address = @intToPtr(*const usize, self.fp + @sizeOf(usize)).*;
220 if (addr == return_address) {
221 self.first_addr = null;
222 return return_address;
223 }
224 }
225 }
226
227 const return_address = @intToPtr(*const usize, self.fp + @sizeOf(usize)).*;
228 return return_address;
229 }
230};
210231
211pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void {232pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void {
212 switch (builtin.os) {233 switch (builtin.os) {
213 builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr),234 builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr),
214 else => {},235 else => {},
215 }236 }
216 const AddressState = union(enum) {237 var it = StackIterator.init(start_addr);
217 NotLookingForStartAddress,238 while (it.next()) |return_address| {
218 LookingForStartAddress: usize,
219 };
220 // TODO: I want to express like this:
221 //var addr_state = if (start_addr) |addr| AddressState { .LookingForStartAddress = addr }
222 // else AddressState.NotLookingForStartAddress;
223 var addr_state: AddressState = undefined;
224 if (start_addr) |addr| {
225 addr_state = AddressState{ .LookingForStartAddress = addr };
226 } else {
227 addr_state = AddressState.NotLookingForStartAddress;
228 }
229
230 var fp = @ptrToInt(@frameAddress());
231 while (fp != 0) : (fp = @intToPtr(*const usize, fp).*) {
232 const return_address = @intToPtr(*const usize, fp + @sizeOf(usize)).*;
233
234 switch (addr_state) {
235 AddressState.NotLookingForStartAddress => {},
236 AddressState.LookingForStartAddress => |addr| {
237 if (return_address == addr) {
238 addr_state = AddressState.NotLookingForStartAddress;
239 } else {
240 continue;
241 }
242 },
243 }
244 try printSourceAtAddress(debug_info, out_stream, return_address, tty_color);239 try printSourceAtAddress(debug_info, out_stream, return_address, tty_color);
245 }240 }
246}241}
...@@ -282,8 +277,9 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres...@@ -282,8 +277,9 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
282277
283 var coff_section: *coff.Section = undefined;278 var coff_section: *coff.Section = undefined;
284 const mod_index = for (di.sect_contribs) |sect_contrib| {279 const mod_index = for (di.sect_contribs) |sect_contrib| {
285 if (sect_contrib.Section >= di.coff.sections.len) continue;280 if (sect_contrib.Section > di.coff.sections.len) continue;
286 coff_section = &di.coff.sections.toSlice()[sect_contrib.Section];281 // Remember that SectionContribEntry.Section is 1-based.
282 coff_section = &di.coff.sections.toSlice()[sect_contrib.Section - 1];
287283
288 const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset;284 const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset;
289 const vaddr_end = vaddr_start + sect_contrib.Size;285 const vaddr_end = vaddr_start + sect_contrib.Size;
...@@ -413,7 +409,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres...@@ -413,7 +409,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
413409
414 if (opt_line_info) |line_info| {410 if (opt_line_info) |line_info| {
415 try out_stream.print("\n");411 try out_stream.print("\n");
416 if (printLineFromFile(out_stream, line_info)) {412 if (printLineFromFileAnyOs(out_stream, line_info)) {
417 if (line_info.column == 0) {413 if (line_info.column == 0) {
418 try out_stream.write("\n");414 try out_stream.write("\n");
419 } else {415 } else {
...@@ -527,7 +523,7 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void {...@@ -527,7 +523,7 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void {
527523
528 const modi = di.pdb.getStreamById(mod.mod_info.ModuleSymStream) orelse return error.MissingDebugInfo;524 const modi = di.pdb.getStreamById(mod.mod_info.ModuleSymStream) orelse return error.MissingDebugInfo;
529525
530 const signature = try modi.stream.readIntLe(u32);526 const signature = try modi.stream.readIntLittle(u32);
531 if (signature != 4)527 if (signature != 4)
532 return error.InvalidDebugInfo;528 return error.InvalidDebugInfo;
533529
...@@ -597,7 +593,15 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt...@@ -597,7 +593,15 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
597 } else "???";593 } else "???";
598 if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| {594 if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| {
599 defer line_info.deinit();595 defer line_info.deinit();
600 try printLineInfo(di, out_stream, line_info, address, symbol_name, compile_unit_name, tty_color);596 try printLineInfo(
597 out_stream,
598 line_info,
599 address,
600 symbol_name,
601 compile_unit_name,
602 tty_color,
603 printLineFromFileAnyOs,
604 );
601 } else |err| switch (err) {605 } else |err| switch (err) {
602 error.MissingDebugInfo, error.InvalidDebugInfo => {606 error.MissingDebugInfo, error.InvalidDebugInfo => {
603 if (tty_color) {607 if (tty_color) {
...@@ -610,7 +614,15 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt...@@ -610,7 +614,15 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
610 }614 }
611}615}
612616
613pub 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
619pub fn printSourceAtAddressDwarf(
620 debug_info: *DwarfInfo,
621 out_stream: var,
622 address: usize,
623 tty_color: bool,
624 comptime printLineFromFile: var,
625) !void {
614 const compile_unit = findCompileUnit(debug_info, address) catch {626 const compile_unit = findCompileUnit(debug_info, address) catch {
615 if (tty_color) {627 if (tty_color) {
616 try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? (???)" ++ RESET ++ "\n\n\n", address);628 try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? (???)" ++ RESET ++ "\n\n\n", address);
...@@ -620,10 +632,18 @@ pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, addres...@@ -620,10 +632,18 @@ pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, addres
620 return;632 return;
621 };633 };
622 const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name);634 const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name);
623 if (getLineNumberInfoLinux(debug_info, compile_unit, address - 1)) |line_info| {635 if (getLineNumberInfoDwarf(debug_info, compile_unit.*, address - 1)) |line_info| {
624 defer line_info.deinit();636 defer line_info.deinit();
625 const symbol_name = "???";637 const symbol_name = "???";
626 try printLineInfo(debug_info, out_stream, line_info, address, symbol_name, compile_unit_name, tty_color);638 try printLineInfo(
639 out_stream,
640 line_info,
641 address,
642 symbol_name,
643 compile_unit_name,
644 tty_color,
645 printLineFromFile,
646 );
627 } else |err| switch (err) {647 } else |err| switch (err) {
628 error.MissingDebugInfo, error.InvalidDebugInfo => {648 error.MissingDebugInfo, error.InvalidDebugInfo => {
629 if (tty_color) {649 if (tty_color) {
...@@ -636,14 +656,18 @@ pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, addres...@@ -636,14 +656,18 @@ pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, addres
636 }656 }
637}657}
638658
659pub 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
639fn printLineInfo(663fn printLineInfo(
640 debug_info: *DebugInfo,
641 out_stream: var,664 out_stream: var,
642 line_info: LineInfo,665 line_info: LineInfo,
643 address: usize,666 address: usize,
644 symbol_name: []const u8,667 symbol_name: []const u8,
645 compile_unit_name: []const u8,668 compile_unit_name: []const u8,
646 tty_color: bool,669 tty_color: bool,
670 comptime printLineFromFile: var,
647) !void {671) !void {
648 if (tty_color) {672 if (tty_color) {
649 try out_stream.print(673 try out_stream.print(
...@@ -733,9 +757,9 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {...@@ -733,9 +757,9 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
733 try di.pdb.openFile(di.coff, path);757 try di.pdb.openFile(di.coff, path);
734758
735 var pdb_stream = di.pdb.getStream(pdb.StreamType.Pdb) orelse return error.InvalidDebugInfo;759 var pdb_stream = di.pdb.getStream(pdb.StreamType.Pdb) orelse return error.InvalidDebugInfo;
736 const version = try pdb_stream.stream.readIntLe(u32);760 const version = try pdb_stream.stream.readIntLittle(u32);
737 const signature = try pdb_stream.stream.readIntLe(u32);761 const signature = try pdb_stream.stream.readIntLittle(u32);
738 const age = try pdb_stream.stream.readIntLe(u32);762 const age = try pdb_stream.stream.readIntLittle(u32);
739 var guid: [16]u8 = undefined;763 var guid: [16]u8 = undefined;
740 try pdb_stream.stream.readNoEof(guid[0..]);764 try pdb_stream.stream.readNoEof(guid[0..]);
741 if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age)765 if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age)
...@@ -743,7 +767,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {...@@ -743,7 +767,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
743 // We validated the executable and pdb match.767 // We validated the executable and pdb match.
744768
745 const string_table_index = str_tab_index: {769 const string_table_index = str_tab_index: {
746 const name_bytes_len = try pdb_stream.stream.readIntLe(u32);770 const name_bytes_len = try pdb_stream.stream.readIntLittle(u32);
747 const name_bytes = try allocator.alloc(u8, name_bytes_len);771 const name_bytes = try allocator.alloc(u8, name_bytes_len);
748 try pdb_stream.stream.readNoEof(name_bytes);772 try pdb_stream.stream.readNoEof(name_bytes);
749773
...@@ -773,8 +797,8 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {...@@ -773,8 +797,8 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
773 };797 };
774 const bucket_list = try allocator.alloc(Bucket, present.len);798 const bucket_list = try allocator.alloc(Bucket, present.len);
775 for (present) |_| {799 for (present) |_| {
776 const name_offset = try pdb_stream.stream.readIntLe(u32);800 const name_offset = try pdb_stream.stream.readIntLittle(u32);
777 const name_index = try pdb_stream.stream.readIntLe(u32);801 const name_index = try pdb_stream.stream.readIntLittle(u32);
778 const name = mem.toSlice(u8, name_bytes.ptr + name_offset);802 const name = mem.toSlice(u8, name_bytes.ptr + name_offset);
779 if (mem.eql(u8, name, "/names")) {803 if (mem.eql(u8, name, "/names")) {
780 break :str_tab_index name_index;804 break :str_tab_index name_index;
...@@ -835,7 +859,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {...@@ -835,7 +859,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
835 var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator);859 var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator);
836 var sect_cont_offset: usize = 0;860 var sect_cont_offset: usize = 0;
837 if (section_contrib_size != 0) {861 if (section_contrib_size != 0) {
838 const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLe(u32));862 const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLittle(u32));
839 if (ver != pdb.SectionContrSubstreamVersion.Ver60)863 if (ver != pdb.SectionContrSubstreamVersion.Ver60)
840 return error.InvalidDebugInfo;864 return error.InvalidDebugInfo;
841 sect_cont_offset += @sizeOf(u32);865 sect_cont_offset += @sizeOf(u32);
...@@ -855,11 +879,11 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {...@@ -855,11 +879,11 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
855}879}
856880
857fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {881fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {
858 const num_words = try stream.readIntLe(u32);882 const num_words = try stream.readIntLittle(u32);
859 var word_i: usize = 0;883 var word_i: usize = 0;
860 var list = ArrayList(usize).init(allocator);884 var list = ArrayList(usize).init(allocator);
861 while (word_i != num_words) : (word_i += 1) {885 while (word_i != num_words) : (word_i += 1) {
862 const word = try stream.readIntLe(u32);886 const word = try stream.readIntLittle(u32);
863 var bit_i: u5 = 0;887 var bit_i: u5 = 0;
864 while (true) : (bit_i += 1) {888 while (true) : (bit_i += 1) {
865 if (word & (u32(1) << bit_i) != 0) {889 if (word & (u32(1) << bit_i) != 0) {
...@@ -871,55 +895,68 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {...@@ -871,55 +895,68 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {
871 return list.toOwnedSlice();895 return list.toOwnedSlice();
872}896}
873897
874fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo {898fn findDwarfSectionFromElf(elf_file: *elf.Elf, name: []const u8) !?DwarfInfo.Section {
875 var di = DebugInfo{899 const elf_header = (try elf_file.findSection(name)) orelse return null;
876 .self_exe_file = undefined,900 return DwarfInfo.Section{
877 .elf = undefined,901 .offset = elf_header.offset,
878 .debug_info = undefined,902 .size = elf_header.size,
879 .debug_abbrev = undefined,
880 .debug_str = undefined,
881 .debug_line = undefined,
882 .debug_ranges = null,
883 .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator),
884 .compile_unit_list = ArrayList(CompileUnit).init(allocator),
885 };903 };
886 di.self_exe_file = try os.openSelfExe();
887 errdefer di.self_exe_file.close();
888
889 try di.elf.openFile(allocator, di.self_exe_file);
890 errdefer di.elf.close();
891
892 di.debug_info = (try di.elf.findSection(".debug_info")) orelse return error.MissingDebugInfo;
893 di.debug_abbrev = (try di.elf.findSection(".debug_abbrev")) orelse return error.MissingDebugInfo;
894 di.debug_str = (try di.elf.findSection(".debug_str")) orelse return error.MissingDebugInfo;
895 di.debug_line = (try di.elf.findSection(".debug_line")) orelse return error.MissingDebugInfo;
896 di.debug_ranges = (try di.elf.findSection(".debug_ranges"));
897 try scanAllCompileUnits(&di);
898 return di;
899}904}
900905
901pub fn findElfSection(elf: *Elf, name: []const u8) ?*elf.Shdr {906/// Initialize DWARF info. The caller has the responsibility to initialize most
902 var file_stream = elf.in_file.inStream();907/// the DwarfInfo fields before calling. These fields can be left undefined:
903 const in = &file_stream.stream;908/// * abbrev_table_list
904909/// * compile_unit_list
905 section_loop: for (elf.section_headers) |*elf_section| {910pub fn openDwarfDebugInfo(di: *DwarfInfo, allocator: *mem.Allocator) !void {
906 if (elf_section.sh_type == SHT_NULL) continue;911 di.abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator);
907912 di.compile_unit_list = ArrayList(CompileUnit).init(allocator);
908 const name_offset = elf.string_section.offset + elf_section.name;913 try scanAllCompileUnits(di);
909 try elf.in_file.seekTo(name_offset);914}
910
911 for (name) |expected_c| {
912 const target_c = try in.readByte();
913 if (target_c == 0 or expected_c != target_c) continue :section_loop;
914 }
915915
916 {916pub fn openElfDebugInfo(
917 const null_byte = try in.readByte();917 allocator: *mem.Allocator,
918 if (null_byte == 0) return elf_section;918 elf_seekable_stream: *DwarfSeekableStream,
919 }919 elf_in_stream: *DwarfInStream,
920 }920) !DwarfInfo {
921 var efile: elf.Elf = undefined;
922 try efile.openStream(allocator, elf_seekable_stream, elf_in_stream);
923 errdefer efile.close();
924
925 var di = DwarfInfo{
926 .dwarf_seekable_stream = elf_seekable_stream,
927 .dwarf_in_stream = elf_in_stream,
928 .endian = efile.endian,
929 .debug_info = (try findDwarfSectionFromElf(&efile, ".debug_info")) orelse return error.MissingDebugInfo,
930 .debug_abbrev = (try findDwarfSectionFromElf(&efile, ".debug_abbrev")) orelse return error.MissingDebugInfo,
931 .debug_str = (try findDwarfSectionFromElf(&efile, ".debug_str")) orelse return error.MissingDebugInfo,
932 .debug_line = (try findDwarfSectionFromElf(&efile, ".debug_line")) orelse return error.MissingDebugInfo,
933 .debug_ranges = (try findDwarfSectionFromElf(&efile, ".debug_ranges")),
934 .abbrev_table_list = undefined,
935 .compile_unit_list = undefined,
936 };
937 try openDwarfDebugInfo(&di, allocator);
938 return di;
939}
921940
922 return null;941fn 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}
924961
925fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {962fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
...@@ -999,7 +1036,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {...@@ -999,7 +1036,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
999 };1036 };
1000}1037}
10011038
1002fn printLineFromFile(out_stream: var, line_info: LineInfo) !void {1039fn printLineFromFileAnyOs(out_stream: var, line_info: LineInfo) !void {
1003 var f = try os.File.openRead(line_info.file_name);1040 var f = try os.File.openRead(line_info.file_name);
1004 defer f.close();1041 defer f.close();
1005 // TODO fstat and make sure that the file has the correct size1042 // TODO fstat and make sure that the file has the correct size
...@@ -1052,6 +1089,35 @@ const MachOFile = struct {...@@ -1052,6 +1089,35 @@ const MachOFile = struct {
1052 sect_debug_line: ?*const macho.section_64,1089 sect_debug_line: ?*const macho.section_64,
1053};1090};
10541091
1092pub const DwarfSeekableStream = io.SeekableStream(anyerror, anyerror);
1093pub const DwarfInStream = io.InStream(anyerror);
1094
1095pub 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
1055pub const DebugInfo = switch (builtin.os) {1121pub const DebugInfo = switch (builtin.os) {
1056 builtin.Os.macosx => struct {1122 builtin.Os.macosx => struct {
1057 symbols: []const MachoSymbol,1123 symbols: []const MachoSymbol,
...@@ -1075,32 +1141,8 @@ pub const DebugInfo = switch (builtin.os) {...@@ -1075,32 +1141,8 @@ pub const DebugInfo = switch (builtin.os) {
1075 sect_contribs: []pdb.SectionContribEntry,1141 sect_contribs: []pdb.SectionContribEntry,
1076 modules: []Module,1142 modules: []Module,
1077 },1143 },
1078 builtin.Os.linux => struct {1144 builtin.Os.linux => DwarfInfo,
1079 self_exe_file: os.File,1145 builtin.Os.freebsd => struct {},
1080 elf: elf.Elf,
1081 debug_info: *elf.SectionHeader,
1082 debug_abbrev: *elf.SectionHeader,
1083 debug_str: *elf.SectionHeader,
1084 debug_line: *elf.SectionHeader,
1085 debug_ranges: ?*elf.SectionHeader,
1086 abbrev_table_list: ArrayList(AbbrevTableHeader),
1087 compile_unit_list: ArrayList(CompileUnit),
1088
1089 pub fn allocator(self: DebugInfo) *mem.Allocator {
1090 return self.abbrev_table_list.allocator;
1091 }
1092
1093 pub fn readString(self: *DebugInfo) ![]u8 {
1094 var in_file_stream = self.self_exe_file.inStream();
1095 const in_stream = &in_file_stream.stream;
1096 return readStringRaw(self.allocator(), in_stream);
1097 }
1098
1099 pub fn close(self: *DebugInfo) void {
1100 self.self_exe_file.close();
1101 self.elf.close();
1102 }
1103 },
1104 else => @compileError("Unsupported OS"),1146 else => @compileError("Unsupported OS"),
1105};1147};
11061148
...@@ -1158,7 +1200,7 @@ const Constant = struct {...@@ -1158,7 +1200,7 @@ const Constant = struct {
1158 fn asUnsignedLe(self: *const Constant) !u64 {1200 fn asUnsignedLe(self: *const Constant) !u64 {
1159 if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo;1201 if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo;
1160 if (self.signed) return error.InvalidDebugInfo;1202 if (self.signed) return error.InvalidDebugInfo;
1161 return mem.readInt(self.payload, u64, builtin.Endian.Little);1203 return mem.readVarInt(u64, self.payload, builtin.Endian.Little);
1162 }1204 }
1163};1205};
11641206
...@@ -1204,11 +1246,11 @@ const Die = struct {...@@ -1204,11 +1246,11 @@ const Die = struct {
1204 };1246 };
1205 }1247 }
12061248
1207 fn getAttrString(self: *const Die, st: *DebugInfo, id: u64) ![]u8 {1249 fn getAttrString(self: *const Die, di: *DwarfInfo, id: u64) ![]u8 {
1208 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;1250 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
1209 return switch (form_value.*) {1251 return switch (form_value.*) {
1210 FormValue.String => |value| value,1252 FormValue.String => |value| value,
1211 FormValue.StrPtr => |offset| getString(st, offset),1253 FormValue.StrPtr => |offset| getString(di, offset),
1212 else => error.InvalidDebugInfo,1254 else => error.InvalidDebugInfo,
1213 };1255 };
1214 }1256 }
...@@ -1221,14 +1263,15 @@ const FileEntry = struct {...@@ -1221,14 +1263,15 @@ const FileEntry = struct {
1221 len_bytes: usize,1263 len_bytes: usize,
1222};1264};
12231265
1224const LineInfo = struct {1266pub const LineInfo = struct {
1225 line: usize,1267 line: usize,
1226 column: usize,1268 column: usize,
1227 file_name: []u8,1269 file_name: []const u8,
1228 allocator: *mem.Allocator,1270 allocator: ?*mem.Allocator,
12291271
1230 fn deinit(self: *const LineInfo) void {1272 fn deinit(self: LineInfo) void {
1231 self.allocator.free(self.file_name);1273 const allocator = self.allocator orelse return;
1274 allocator.free(self.file_name);
1232 }1275 }
1233};1276};
12341277
...@@ -1319,10 +1362,10 @@ fn readStringRaw(allocator: *mem.Allocator, in_stream: var) ![]u8 {...@@ -1319,10 +1362,10 @@ fn readStringRaw(allocator: *mem.Allocator, in_stream: var) ![]u8 {
1319 return buf.toSlice();1362 return buf.toSlice();
1320}1363}
13211364
1322fn getString(st: *DebugInfo, offset: u64) ![]u8 {1365fn getString(di: *DwarfInfo, offset: u64) ![]u8 {
1323 const pos = st.debug_str.offset + offset;1366 const pos = di.debug_str.offset + offset;
1324 try st.self_exe_file.seekTo(pos);1367 try di.dwarf_seekable_stream.seekTo(pos);
1325 return st.readString();1368 return di.readString();
1326}1369}
13271370
1328fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8 {1371fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8 {
...@@ -1338,7 +1381,7 @@ fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize...@@ -1338,7 +1381,7 @@ fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize
1338}1381}
13391382
1340fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {1383fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
1341 const block_len = try in_stream.readVarInt(builtin.Endian.Little, usize, size);1384 const block_len = try in_stream.readVarInt(usize, builtin.Endian.Little, size);
1342 return parseFormValueBlockLen(allocator, in_stream, block_len);1385 return parseFormValueBlockLen(allocator, in_stream, block_len);
1343}1386}
13441387
...@@ -1352,11 +1395,11 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo...@@ -1352,11 +1395,11 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo
1352}1395}
13531396
1354fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {1397fn 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}
13571400
1358fn parseFormValueTargetAddrSize(in_stream: var) !u64 {1401fn 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}
13611404
1362fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {1405fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
...@@ -1365,18 +1408,11 @@ fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize)...@@ -1365,18 +1408,11 @@ fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize)
1365}1408}
13661409
1367fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue {1410fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue {
1368 const block_len = try in_stream.readIntLe(T);1411 const block_len = try in_stream.readIntLittle(T);
1369 return parseFormValueRefLen(allocator, in_stream, block_len);1412 return parseFormValueRefLen(allocator, in_stream, block_len);
1370}1413}
13711414
1372const ParseFormValueError = error{1415fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue {
1373 EndOfStream,
1374 InvalidDebugInfo,
1375 EndOfFile,
1376 OutOfMemory,
1377} || std.os.File.ReadError;
1378
1379fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) ParseFormValueError!FormValue {
1380 return switch (form_id) {1416 return switch (form_id) {
1381 DW.FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) },1417 DW.FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) },
1382 DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1),1418 DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1),
...@@ -1414,7 +1450,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64...@@ -1414,7 +1450,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
1414 },1450 },
14151451
1416 DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },1452 DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
1417 DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLe(u64) },1453 DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLittle(u64) },
14181454
1419 DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },1455 DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },
1420 DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },1456 DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
...@@ -1426,25 +1462,22 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64...@@ -1426,25 +1462,22 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
1426 };1462 };
1427}1463}
14281464
1429fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable {1465fn parseAbbrevTable(di: *DwarfInfo) !AbbrevTable {
1430 const in_file = st.self_exe_file;1466 var result = AbbrevTable.init(di.allocator());
1431 var in_file_stream = in_file.inStream();
1432 const in_stream = &in_file_stream.stream;
1433 var result = AbbrevTable.init(st.allocator());
1434 while (true) {1467 while (true) {
1435 const abbrev_code = try readULeb128(in_stream);1468 const abbrev_code = try readULeb128(di.dwarf_in_stream);
1436 if (abbrev_code == 0) return result;1469 if (abbrev_code == 0) return result;
1437 try result.append(AbbrevTableEntry{1470 try result.append(AbbrevTableEntry{
1438 .abbrev_code = abbrev_code,1471 .abbrev_code = abbrev_code,
1439 .tag_id = try readULeb128(in_stream),1472 .tag_id = try readULeb128(di.dwarf_in_stream),
1440 .has_children = (try in_stream.readByte()) == DW.CHILDREN_yes,1473 .has_children = (try di.dwarf_in_stream.readByte()) == DW.CHILDREN_yes,
1441 .attrs = ArrayList(AbbrevAttr).init(st.allocator()),1474 .attrs = ArrayList(AbbrevAttr).init(di.allocator()),
1442 });1475 });
1443 const attrs = &result.items[result.len - 1].attrs;1476 const attrs = &result.items[result.len - 1].attrs;
14441477
1445 while (true) {1478 while (true) {
1446 const attr_id = try readULeb128(in_stream);1479 const attr_id = try readULeb128(di.dwarf_in_stream);
1447 const form_id = try readULeb128(in_stream);1480 const form_id = try readULeb128(di.dwarf_in_stream);
1448 if (attr_id == 0 and form_id == 0) break;1481 if (attr_id == 0 and form_id == 0) break;
1449 try attrs.append(AbbrevAttr{1482 try attrs.append(AbbrevAttr{
1450 .attr_id = attr_id,1483 .attr_id = attr_id,
...@@ -1456,18 +1489,18 @@ fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable {...@@ -1456,18 +1489,18 @@ fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable {
14561489
1457/// Gets an already existing AbbrevTable given the abbrev_offset, or if not found,1490/// Gets an already existing AbbrevTable given the abbrev_offset, or if not found,
1458/// seeks in the stream and parses it.1491/// seeks in the stream and parses it.
1459fn getAbbrevTable(st: *DebugInfo, abbrev_offset: u64) !*const AbbrevTable {1492fn getAbbrevTable(di: *DwarfInfo, abbrev_offset: u64) !*const AbbrevTable {
1460 for (st.abbrev_table_list.toSlice()) |*header| {1493 for (di.abbrev_table_list.toSlice()) |*header| {
1461 if (header.offset == abbrev_offset) {1494 if (header.offset == abbrev_offset) {
1462 return &header.table;1495 return &header.table;
1463 }1496 }
1464 }1497 }
1465 try st.self_exe_file.seekTo(st.debug_abbrev.offset + abbrev_offset);1498 try di.dwarf_seekable_stream.seekTo(di.debug_abbrev.offset + abbrev_offset);
1466 try st.abbrev_table_list.append(AbbrevTableHeader{1499 try di.abbrev_table_list.append(AbbrevTableHeader{
1467 .offset = abbrev_offset,1500 .offset = abbrev_offset,
1468 .table = try parseAbbrevTable(st),1501 .table = try parseAbbrevTable(di),
1469 });1502 });
1470 return &st.abbrev_table_list.items[st.abbrev_table_list.len - 1].table;1503 return &di.abbrev_table_list.items[di.abbrev_table_list.len - 1].table;
1471}1504}
14721505
1473fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*const AbbrevTableEntry {1506fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*const AbbrevTableEntry {
...@@ -1477,23 +1510,20 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con...@@ -1477,23 +1510,20 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con
1477 return null;1510 return null;
1478}1511}
14791512
1480fn parseDie(st: *DebugInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die {1513fn parseDie(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die {
1481 const in_file = st.self_exe_file;1514 const abbrev_code = try readULeb128(di.dwarf_in_stream);
1482 var in_file_stream = in_file.inStream();
1483 const in_stream = &in_file_stream.stream;
1484 const abbrev_code = try readULeb128(in_stream);
1485 const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;1515 const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;
14861516
1487 var result = Die{1517 var result = Die{
1488 .tag_id = table_entry.tag_id,1518 .tag_id = table_entry.tag_id,
1489 .has_children = table_entry.has_children,1519 .has_children = table_entry.has_children,
1490 .attrs = ArrayList(Die.Attr).init(st.allocator()),1520 .attrs = ArrayList(Die.Attr).init(di.allocator()),
1491 };1521 };
1492 try result.attrs.resize(table_entry.attrs.len);1522 try result.attrs.resize(table_entry.attrs.len);
1493 for (table_entry.attrs.toSliceConst()) |attr, i| {1523 for (table_entry.attrs.toSliceConst()) |attr, i| {
1494 result.attrs.items[i] = Die.Attr{1524 result.attrs.items[i] = Die.Attr{
1495 .id = attr.attr_id,1525 .id = attr.attr_id,
1496 .value = try parseFormValue(st.allocator(), in_stream, attr.form_id, is_64),1526 .value = try parseFormValue(di.allocator(), di.dwarf_in_stream, attr.form_id, is_64),
1497 };1527 };
1498 }1528 }
1499 return result;1529 return result;
...@@ -1697,22 +1727,18 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u...@@ -1697,22 +1727,18 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
1697 return error.MissingDebugInfo;1727 return error.MissingDebugInfo;
1698}1728}
16991729
1700fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, target_address: usize) !LineInfo {1730fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo {
1701 const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir);1731 const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir);
17021732
1703 const in_file = di.self_exe_file;
1704 const debug_line_end = di.debug_line.offset + di.debug_line.size;1733 const debug_line_end = di.debug_line.offset + di.debug_line.size;
1705 var this_offset = di.debug_line.offset;1734 var this_offset = di.debug_line.offset;
1706 var this_index: usize = 0;1735 var this_index: usize = 0;
17071736
1708 var in_file_stream = in_file.inStream();
1709 const in_stream = &in_file_stream.stream;
1710
1711 while (this_offset < debug_line_end) : (this_index += 1) {1737 while (this_offset < debug_line_end) : (this_index += 1) {
1712 try in_file.seekTo(this_offset);1738 try di.dwarf_seekable_stream.seekTo(this_offset);
17131739
1714 var is_64: bool = undefined;1740 var is_64: bool = undefined;
1715 const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64);1741 const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64);
1716 if (unit_length == 0) return error.MissingDebugInfo;1742 if (unit_length == 0) return error.MissingDebugInfo;
1717 const next_offset = unit_length + (if (is_64) usize(12) else usize(4));1743 const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
17181744
...@@ -1721,35 +1747,35 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ...@@ -1721,35 +1747,35 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
1721 continue;1747 continue;
1722 }1748 }
17231749
1724 const version = try in_stream.readInt(di.elf.endian, u16);1750 const version = try di.dwarf_in_stream.readInt(u16, di.endian);
1725 // TODO support 3 and 51751 // TODO support 3 and 5
1726 if (version != 2 and version != 4) return error.InvalidDebugInfo;1752 if (version != 2 and version != 4) return error.InvalidDebugInfo;
17271753
1728 const prologue_length = if (is_64) try in_stream.readInt(di.elf.endian, u64) else try in_stream.readInt(di.elf.endian, u32);1754 const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian);
1729 const prog_start_offset = (try in_file.getPos()) + prologue_length;1755 const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length;
17301756
1731 const minimum_instruction_length = try in_stream.readByte();1757 const minimum_instruction_length = try di.dwarf_in_stream.readByte();
1732 if (minimum_instruction_length == 0) return error.InvalidDebugInfo;1758 if (minimum_instruction_length == 0) return error.InvalidDebugInfo;
17331759
1734 if (version >= 4) {1760 if (version >= 4) {
1735 // maximum_operations_per_instruction1761 // maximum_operations_per_instruction
1736 _ = try in_stream.readByte();1762 _ = try di.dwarf_in_stream.readByte();
1737 }1763 }
17381764
1739 const default_is_stmt = (try in_stream.readByte()) != 0;1765 const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0;
1740 const line_base = try in_stream.readByteSigned();1766 const line_base = try di.dwarf_in_stream.readByteSigned();
17411767
1742 const line_range = try in_stream.readByte();1768 const line_range = try di.dwarf_in_stream.readByte();
1743 if (line_range == 0) return error.InvalidDebugInfo;1769 if (line_range == 0) return error.InvalidDebugInfo;
17441770
1745 const opcode_base = try in_stream.readByte();1771 const opcode_base = try di.dwarf_in_stream.readByte();
17461772
1747 const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1);1773 const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1);
17481774
1749 {1775 {
1750 var i: usize = 0;1776 var i: usize = 0;
1751 while (i < opcode_base - 1) : (i += 1) {1777 while (i < opcode_base - 1) : (i += 1) {
1752 standard_opcode_lengths[i] = try in_stream.readByte();1778 standard_opcode_lengths[i] = try di.dwarf_in_stream.readByte();
1753 }1779 }
1754 }1780 }
17551781
...@@ -1767,9 +1793,9 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ...@@ -1767,9 +1793,9 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
1767 while (true) {1793 while (true) {
1768 const file_name = try di.readString();1794 const file_name = try di.readString();
1769 if (file_name.len == 0) break;1795 if (file_name.len == 0) break;
1770 const dir_index = try readULeb128(in_stream);1796 const dir_index = try readULeb128(di.dwarf_in_stream);
1771 const mtime = try readULeb128(in_stream);1797 const mtime = try readULeb128(di.dwarf_in_stream);
1772 const len_bytes = try readULeb128(in_stream);1798 const len_bytes = try readULeb128(di.dwarf_in_stream);
1773 try file_entries.append(FileEntry{1799 try file_entries.append(FileEntry{
1774 .file_name = file_name,1800 .file_name = file_name,
1775 .dir_index = dir_index,1801 .dir_index = dir_index,
...@@ -1778,15 +1804,15 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ...@@ -1778,15 +1804,15 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
1778 });1804 });
1779 }1805 }
17801806
1781 try in_file.seekTo(prog_start_offset);1807 try di.dwarf_seekable_stream.seekTo(prog_start_offset);
17821808
1783 while (true) {1809 while (true) {
1784 const opcode = try in_stream.readByte();1810 const opcode = try di.dwarf_in_stream.readByte();
17851811
1786 if (opcode == DW.LNS_extended_op) {1812 if (opcode == DW.LNS_extended_op) {
1787 const op_size = try readULeb128(in_stream);1813 const op_size = try readULeb128(di.dwarf_in_stream);
1788 if (op_size < 1) return error.InvalidDebugInfo;1814 if (op_size < 1) return error.InvalidDebugInfo;
1789 var sub_op = try in_stream.readByte();1815 var sub_op = try di.dwarf_in_stream.readByte();
1790 switch (sub_op) {1816 switch (sub_op) {
1791 DW.LNE_end_sequence => {1817 DW.LNE_end_sequence => {
1792 prog.end_sequence = true;1818 prog.end_sequence = true;
...@@ -1794,14 +1820,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ...@@ -1794,14 +1820,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
1794 return error.MissingDebugInfo;1820 return error.MissingDebugInfo;
1795 },1821 },
1796 DW.LNE_set_address => {1822 DW.LNE_set_address => {
1797 const addr = try in_stream.readInt(di.elf.endian, usize);1823 const addr = try di.dwarf_in_stream.readInt(usize, di.endian);
1798 prog.address = addr;1824 prog.address = addr;
1799 },1825 },
1800 DW.LNE_define_file => {1826 DW.LNE_define_file => {
1801 const file_name = try di.readString();1827 const file_name = try di.readString();
1802 const dir_index = try readULeb128(in_stream);1828 const dir_index = try readULeb128(di.dwarf_in_stream);
1803 const mtime = try readULeb128(in_stream);1829 const mtime = try readULeb128(di.dwarf_in_stream);
1804 const len_bytes = try readULeb128(in_stream);1830 const len_bytes = try readULeb128(di.dwarf_in_stream);
1805 try file_entries.append(FileEntry{1831 try file_entries.append(FileEntry{
1806 .file_name = file_name,1832 .file_name = file_name,
1807 .dir_index = dir_index,1833 .dir_index = dir_index,
...@@ -1811,7 +1837,7 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ...@@ -1811,7 +1837,7 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
1811 },1837 },
1812 else => {1838 else => {
1813 const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo;1839 const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo;
1814 try in_file.seekForward(fwd_amt);1840 try di.dwarf_seekable_stream.seekForward(fwd_amt);
1815 },1841 },
1816 }1842 }
1817 } else if (opcode >= opcode_base) {1843 } else if (opcode >= opcode_base) {
...@@ -1830,19 +1856,19 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ...@@ -1830,19 +1856,19 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
1830 prog.basic_block = false;1856 prog.basic_block = false;
1831 },1857 },
1832 DW.LNS_advance_pc => {1858 DW.LNS_advance_pc => {
1833 const arg = try readULeb128(in_stream);1859 const arg = try readULeb128(di.dwarf_in_stream);
1834 prog.address += arg * minimum_instruction_length;1860 prog.address += arg * minimum_instruction_length;
1835 },1861 },
1836 DW.LNS_advance_line => {1862 DW.LNS_advance_line => {
1837 const arg = try readILeb128(in_stream);1863 const arg = try readILeb128(di.dwarf_in_stream);
1838 prog.line += arg;1864 prog.line += arg;
1839 },1865 },
1840 DW.LNS_set_file => {1866 DW.LNS_set_file => {
1841 const arg = try readULeb128(in_stream);1867 const arg = try readULeb128(di.dwarf_in_stream);
1842 prog.file = arg;1868 prog.file = arg;
1843 },1869 },
1844 DW.LNS_set_column => {1870 DW.LNS_set_column => {
1845 const arg = try readULeb128(in_stream);1871 const arg = try readULeb128(di.dwarf_in_stream);
1846 prog.column = arg;1872 prog.column = arg;
1847 },1873 },
1848 DW.LNS_negate_stmt => {1874 DW.LNS_negate_stmt => {
...@@ -1856,14 +1882,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ...@@ -1856,14 +1882,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
1856 prog.address += inc_addr;1882 prog.address += inc_addr;
1857 },1883 },
1858 DW.LNS_fixed_advance_pc => {1884 DW.LNS_fixed_advance_pc => {
1859 const arg = try in_stream.readInt(di.elf.endian, u16);1885 const arg = try di.dwarf_in_stream.readInt(u16, di.endian);
1860 prog.address += arg;1886 prog.address += arg;
1861 },1887 },
1862 DW.LNS_set_prologue_end => {},1888 DW.LNS_set_prologue_end => {},
1863 else => {1889 else => {
1864 if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo;1890 if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo;
1865 const len_bytes = standard_opcode_lengths[opcode - 1];1891 const len_bytes = standard_opcode_lengths[opcode - 1];
1866 try in_file.seekForward(len_bytes);1892 try di.dwarf_seekable_stream.seekForward(len_bytes);
1867 },1893 },
1868 }1894 }
1869 }1895 }
...@@ -1875,36 +1901,33 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ...@@ -1875,36 +1901,33 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
1875 return error.MissingDebugInfo;1901 return error.MissingDebugInfo;
1876}1902}
18771903
1878fn scanAllCompileUnits(st: *DebugInfo) !void {1904fn scanAllCompileUnits(di: *DwarfInfo) !void {
1879 const debug_info_end = st.debug_info.offset + st.debug_info.size;1905 const debug_info_end = di.debug_info.offset + di.debug_info.size;
1880 var this_unit_offset = st.debug_info.offset;1906 var this_unit_offset = di.debug_info.offset;
1881 var cu_index: usize = 0;1907 var cu_index: usize = 0;
18821908
1883 var in_file_stream = st.self_exe_file.inStream();
1884 const in_stream = &in_file_stream.stream;
1885
1886 while (this_unit_offset < debug_info_end) {1909 while (this_unit_offset < debug_info_end) {
1887 try st.self_exe_file.seekTo(this_unit_offset);1910 try di.dwarf_seekable_stream.seekTo(this_unit_offset);
18881911
1889 var is_64: bool = undefined;1912 var is_64: bool = undefined;
1890 const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64);1913 const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64);
1891 if (unit_length == 0) return;1914 if (unit_length == 0) return;
1892 const next_offset = unit_length + (if (is_64) usize(12) else usize(4));1915 const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
18931916
1894 const version = try in_stream.readInt(st.elf.endian, u16);1917 const version = try di.dwarf_in_stream.readInt(u16, di.endian);
1895 if (version < 2 or version > 5) return error.InvalidDebugInfo;1918 if (version < 2 or version > 5) return error.InvalidDebugInfo;
18961919
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);
18981921
1899 const address_size = try in_stream.readByte();1922 const address_size = try di.dwarf_in_stream.readByte();
1900 if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;1923 if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
19011924
1902 const compile_unit_pos = try st.self_exe_file.getPos();1925 const compile_unit_pos = try di.dwarf_seekable_stream.getPos();
1903 const abbrev_table = try getAbbrevTable(st, debug_abbrev_offset);1926 const abbrev_table = try getAbbrevTable(di, debug_abbrev_offset);
19041927
1905 try st.self_exe_file.seekTo(compile_unit_pos);1928 try di.dwarf_seekable_stream.seekTo(compile_unit_pos);
19061929
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));
19081931
1909 if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo;1932 if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo;
19101933
...@@ -1932,7 +1955,7 @@ fn scanAllCompileUnits(st: *DebugInfo) !void {...@@ -1932,7 +1955,7 @@ fn scanAllCompileUnits(st: *DebugInfo) !void {
1932 }1955 }
1933 };1956 };
19341957
1935 try st.compile_unit_list.append(CompileUnit{1958 try di.compile_unit_list.append(CompileUnit{
1936 .version = version,1959 .version = version,
1937 .is_64 = is_64,1960 .is_64 = is_64,
1938 .pc_range = pc_range,1961 .pc_range = pc_range,
...@@ -1945,20 +1968,18 @@ fn scanAllCompileUnits(st: *DebugInfo) !void {...@@ -1945,20 +1968,18 @@ fn scanAllCompileUnits(st: *DebugInfo) !void {
1945 }1968 }
1946}1969}
19471970
1948fn findCompileUnit(st: *DebugInfo, target_address: u64) !*const CompileUnit {1971fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit {
1949 var in_file_stream = st.self_exe_file.inStream();1972 for (di.compile_unit_list.toSlice()) |*compile_unit| {
1950 const in_stream = &in_file_stream.stream;
1951 for (st.compile_unit_list.toSlice()) |*compile_unit| {
1952 if (compile_unit.pc_range) |range| {1973 if (compile_unit.pc_range) |range| {
1953 if (target_address >= range.start and target_address < range.end) return compile_unit;1974 if (target_address >= range.start and target_address < range.end) return compile_unit;
1954 }1975 }
1955 if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| {1976 if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| {
1956 var base_address: usize = 0;1977 var base_address: usize = 0;
1957 if (st.debug_ranges) |debug_ranges| {1978 if (di.debug_ranges) |debug_ranges| {
1958 try st.self_exe_file.seekTo(debug_ranges.offset + ranges_offset);1979 try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset);
1959 while (true) {1980 while (true) {
1960 const begin_addr = try in_stream.readIntLe(usize);1981 const begin_addr = try di.dwarf_in_stream.readIntLittle(usize);
1961 const end_addr = try in_stream.readIntLe(usize);1982 const end_addr = try di.dwarf_in_stream.readIntLittle(usize);
1962 if (begin_addr == 0 and end_addr == 0) {1983 if (begin_addr == 0 and end_addr == 0) {
1963 break;1984 break;
1964 }1985 }
...@@ -1980,7 +2001,8 @@ fn findCompileUnit(st: *DebugInfo, target_address: u64) !*const CompileUnit {...@@ -1980,7 +2001,8 @@ fn findCompileUnit(st: *DebugInfo, target_address: u64) !*const CompileUnit {
1980}2001}
19812002
1982fn readIntMem(ptr: *[*]const u8, comptime T: type, endian: builtin.Endian) T {2003fn readIntMem(ptr: *[*]const u8, comptime T: type, endian: builtin.Endian) T {
1983 const result = mem.readInt(ptr.*[0..@sizeOf(T)], T, endian);2004 // TODO https://github.com/ziglang/zig/issues/863
2005 const result = mem.readIntSlice(T, ptr.*[0..@sizeOf(T)], endian);
1984 ptr.* += @sizeOf(T);2006 ptr.* += @sizeOf(T);
1985 return result;2007 return result;
1986}2008}
...@@ -1996,11 +2018,12 @@ fn readByteSignedMem(ptr: *[*]const u8) i8 {...@@ -1996,11 +2018,12 @@ fn readByteSignedMem(ptr: *[*]const u8) i8 {
1996}2018}
19972019
1998fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 {2020fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 {
1999 const first_32_bits = mem.readIntLE(u32, ptr.*[0..4]);2021 // TODO this code can be improved with https://github.com/ziglang/zig/issues/863
2022 const first_32_bits = mem.readIntSliceLittle(u32, ptr.*[0..4]);
2000 is_64.* = (first_32_bits == 0xffffffff);2023 is_64.* = (first_32_bits == 0xffffffff);
2001 if (is_64.*) {2024 if (is_64.*) {
2002 ptr.* += 4;2025 ptr.* += 4;
2003 const result = mem.readIntLE(u64, ptr.*[0..8]);2026 const result = mem.readIntSliceLittle(u64, ptr.*[0..8]);
2004 ptr.* += 8;2027 ptr.* += 8;
2005 return result;2028 return result;
2006 } else {2029 } else {
...@@ -2063,10 +2086,10 @@ fn readILeb128Mem(ptr: *[*]const u8) !i64 {...@@ -2063,10 +2086,10 @@ fn readILeb128Mem(ptr: *[*]const u8) !i64 {
2063}2086}
20642087
2065fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 {2088fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 {
2066 const first_32_bits = try in_stream.readIntLe(u32);2089 const first_32_bits = try in_stream.readIntLittle(u32);
2067 is_64.* = (first_32_bits == 0xffffffff);2090 is_64.* = (first_32_bits == 0xffffffff);
2068 if (is_64.*) {2091 if (is_64.*) {
2069 return in_stream.readIntLe(u64);2092 return in_stream.readIntLittle(u64);
2070 } else {2093 } else {
2071 if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo;2094 if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo;
2072 return u64(first_32_bits);2095 return u64(first_32_bits);
std/dynamic_library.zig+1-3
...@@ -19,7 +19,6 @@ pub const DynLib = switch (builtin.os) {...@@ -19,7 +19,6 @@ pub const DynLib = switch (builtin.os) {
19};19};
2020
21pub const LinuxDynLib = struct {21pub const LinuxDynLib = struct {
22 allocator: *mem.Allocator,
23 elf_lib: ElfLib,22 elf_lib: ElfLib,
24 fd: i32,23 fd: i32,
25 map_addr: usize,24 map_addr: usize,
...@@ -27,7 +26,7 @@ pub const LinuxDynLib = struct {...@@ -27,7 +26,7 @@ pub const LinuxDynLib = struct {
2726
28 /// Trusts the file27 /// Trusts the file
29 pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib {28 pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib {
30 const fd = try std.os.posixOpen(allocator, path, 0, linux.O_RDONLY | linux.O_CLOEXEC);29 const fd = try std.os.posixOpen(path, 0, linux.O_RDONLY | linux.O_CLOEXEC);
31 errdefer std.os.close(fd);30 errdefer std.os.close(fd);
3231
33 const size = @intCast(usize, (try std.os.posixFStat(fd)).size);32 const size = @intCast(usize, (try std.os.posixFStat(fd)).size);
...@@ -45,7 +44,6 @@ pub const LinuxDynLib = struct {...@@ -45,7 +44,6 @@ pub const LinuxDynLib = struct {
45 const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size];44 const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size];
4645
47 return DynLib{46 return DynLib{
48 .allocator = allocator,
49 .elf_lib = try ElfLib.init(bytes),47 .elf_lib = try ElfLib.init(bytes),
50 .fd = fd,48 .fd = fd,
51 .map_addr = addr,49 .map_addr = addr,
std/elf.zig+59-56
...@@ -353,7 +353,8 @@ pub const SectionHeader = struct {...@@ -353,7 +353,8 @@ pub const SectionHeader = struct {
353};353};
354354
355pub const Elf = struct {355pub const Elf = struct {
356 in_file: os.File,356 seekable_stream: *io.SeekableStream(anyerror, anyerror),
357 in_stream: *io.InStream(anyerror),
357 auto_close_stream: bool,358 auto_close_stream: bool,
358 is_64: bool,359 is_64: bool,
359 endian: builtin.Endian,360 endian: builtin.Endian,
...@@ -370,19 +371,24 @@ pub const Elf = struct {...@@ -370,19 +371,24 @@ pub const Elf = struct {
370371
371 /// Call close when done.372 /// Call close when done.
372 pub fn openPath(elf: *Elf, allocator: *mem.Allocator, path: []const u8) !void {373 pub fn openPath(elf: *Elf, allocator: *mem.Allocator, path: []const u8) !void {
373 try elf.prealloc_file.open(path);374 @compileError("TODO implement");
374 try elf.openFile(allocator, *elf.prealloc_file);
375 elf.auto_close_stream = true;
376 }375 }
377376
378 /// Call close when done.377 /// Call close when done.
379 pub fn openFile(elf: *Elf, allocator: *mem.Allocator, file: os.File) !void {378 pub fn openFile(elf: *Elf, allocator: *mem.Allocator, file: os.File) !void {
380 elf.allocator = allocator;379 @compileError("TODO implement");
381 elf.in_file = file;380 }
382 elf.auto_close_stream = false;
383381
384 var file_stream = elf.in_file.inStream();382 pub fn openStream(
385 const in = &file_stream.stream;383 elf: *Elf,
384 allocator: *mem.Allocator,
385 seekable_stream: *io.SeekableStream(anyerror, anyerror),
386 in: *io.InStream(anyerror),
387 ) !void {
388 elf.auto_close_stream = false;
389 elf.allocator = allocator;
390 elf.seekable_stream = seekable_stream;
391 elf.in_stream = in;
386392
387 var magic: [4]u8 = undefined;393 var magic: [4]u8 = undefined;
388 try in.readNoEof(magic[0..]);394 try in.readNoEof(magic[0..]);
...@@ -404,9 +410,9 @@ pub const Elf = struct {...@@ -404,9 +410,9 @@ pub const Elf = struct {
404 if (version_byte != 1) return error.InvalidFormat;410 if (version_byte != 1) return error.InvalidFormat;
405411
406 // skip over padding412 // skip over padding
407 try elf.in_file.seekForward(9);413 try seekable_stream.seekForward(9);
408414
409 elf.file_type = switch (try in.readInt(elf.endian, u16)) {415 elf.file_type = switch (try in.readInt(u16, elf.endian)) {
410 1 => FileType.Relocatable,416 1 => FileType.Relocatable,
411 2 => FileType.Executable,417 2 => FileType.Executable,
412 3 => FileType.Shared,418 3 => FileType.Shared,
...@@ -414,7 +420,7 @@ pub const Elf = struct {...@@ -414,7 +420,7 @@ pub const Elf = struct {
414 else => return error.InvalidFormat,420 else => return error.InvalidFormat,
415 };421 };
416422
417 elf.arch = switch (try in.readInt(elf.endian, u16)) {423 elf.arch = switch (try in.readInt(u16, elf.endian)) {
418 0x02 => Arch.Sparc,424 0x02 => Arch.Sparc,
419 0x03 => Arch.x86,425 0x03 => Arch.x86,
420 0x08 => Arch.Mips,426 0x08 => Arch.Mips,
...@@ -427,32 +433,32 @@ pub const Elf = struct {...@@ -427,32 +433,32 @@ pub const Elf = struct {
427 else => return error.InvalidFormat,433 else => return error.InvalidFormat,
428 };434 };
429435
430 const elf_version = try in.readInt(elf.endian, u32);436 const elf_version = try in.readInt(u32, elf.endian);
431 if (elf_version != 1) return error.InvalidFormat;437 if (elf_version != 1) return error.InvalidFormat;
432438
433 if (elf.is_64) {439 if (elf.is_64) {
434 elf.entry_addr = try in.readInt(elf.endian, u64);440 elf.entry_addr = try in.readInt(u64, elf.endian);
435 elf.program_header_offset = try in.readInt(elf.endian, u64);441 elf.program_header_offset = try in.readInt(u64, elf.endian);
436 elf.section_header_offset = try in.readInt(elf.endian, u64);442 elf.section_header_offset = try in.readInt(u64, elf.endian);
437 } else {443 } else {
438 elf.entry_addr = u64(try in.readInt(elf.endian, u32));444 elf.entry_addr = u64(try in.readInt(u32, elf.endian));
439 elf.program_header_offset = u64(try in.readInt(elf.endian, u32));445 elf.program_header_offset = u64(try in.readInt(u32, elf.endian));
440 elf.section_header_offset = u64(try in.readInt(elf.endian, u32));446 elf.section_header_offset = u64(try in.readInt(u32, elf.endian));
441 }447 }
442448
443 // skip over flags449 // skip over flags
444 try elf.in_file.seekForward(4);450 try seekable_stream.seekForward(4);
445451
446 const header_size = try in.readInt(elf.endian, u16);452 const header_size = try in.readInt(u16, elf.endian);
447 if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) {453 if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) {
448 return error.InvalidFormat;454 return error.InvalidFormat;
449 }455 }
450456
451 const ph_entry_size = try in.readInt(elf.endian, u16);457 const ph_entry_size = try in.readInt(u16, elf.endian);
452 const ph_entry_count = try in.readInt(elf.endian, u16);458 const ph_entry_count = try in.readInt(u16, elf.endian);
453 const sh_entry_size = try in.readInt(elf.endian, u16);459 const sh_entry_size = try in.readInt(u16, elf.endian);
454 const sh_entry_count = try in.readInt(elf.endian, u16);460 const sh_entry_count = try in.readInt(u16, elf.endian);
455 elf.string_section_index = u64(try in.readInt(elf.endian, u16));461 elf.string_section_index = u64(try in.readInt(u16, elf.endian));
456462
457 if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat;463 if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat;
458464
...@@ -461,12 +467,12 @@ pub const Elf = struct {...@@ -461,12 +467,12 @@ pub const Elf = struct {
461 const ph_byte_count = u64(ph_entry_size) * u64(ph_entry_count);467 const ph_byte_count = u64(ph_entry_size) * u64(ph_entry_count);
462 const end_ph = try math.add(u64, elf.program_header_offset, ph_byte_count);468 const end_ph = try math.add(u64, elf.program_header_offset, ph_byte_count);
463469
464 const stream_end = try elf.in_file.getEndPos();470 const stream_end = try seekable_stream.getEndPos();
465 if (stream_end < end_sh or stream_end < end_ph) {471 if (stream_end < end_sh or stream_end < end_ph) {
466 return error.InvalidFormat;472 return error.InvalidFormat;
467 }473 }
468474
469 try elf.in_file.seekTo(elf.section_header_offset);475 try seekable_stream.seekTo(elf.section_header_offset);
470476
471 elf.section_headers = try elf.allocator.alloc(SectionHeader, sh_entry_count);477 elf.section_headers = try elf.allocator.alloc(SectionHeader, sh_entry_count);
472 errdefer elf.allocator.free(elf.section_headers);478 errdefer elf.allocator.free(elf.section_headers);
...@@ -475,32 +481,32 @@ pub const Elf = struct {...@@ -475,32 +481,32 @@ pub const Elf = struct {
475 if (sh_entry_size != 64) return error.InvalidFormat;481 if (sh_entry_size != 64) return error.InvalidFormat;
476482
477 for (elf.section_headers) |*elf_section| {483 for (elf.section_headers) |*elf_section| {
478 elf_section.name = try in.readInt(elf.endian, u32);484 elf_section.name = try in.readInt(u32, elf.endian);
479 elf_section.sh_type = try in.readInt(elf.endian, u32);485 elf_section.sh_type = try in.readInt(u32, elf.endian);
480 elf_section.flags = try in.readInt(elf.endian, u64);486 elf_section.flags = try in.readInt(u64, elf.endian);
481 elf_section.addr = try in.readInt(elf.endian, u64);487 elf_section.addr = try in.readInt(u64, elf.endian);
482 elf_section.offset = try in.readInt(elf.endian, u64);488 elf_section.offset = try in.readInt(u64, elf.endian);
483 elf_section.size = try in.readInt(elf.endian, u64);489 elf_section.size = try in.readInt(u64, elf.endian);
484 elf_section.link = try in.readInt(elf.endian, u32);490 elf_section.link = try in.readInt(u32, elf.endian);
485 elf_section.info = try in.readInt(elf.endian, u32);491 elf_section.info = try in.readInt(u32, elf.endian);
486 elf_section.addr_align = try in.readInt(elf.endian, u64);492 elf_section.addr_align = try in.readInt(u64, elf.endian);
487 elf_section.ent_size = try in.readInt(elf.endian, u64);493 elf_section.ent_size = try in.readInt(u64, elf.endian);
488 }494 }
489 } else {495 } else {
490 if (sh_entry_size != 40) return error.InvalidFormat;496 if (sh_entry_size != 40) return error.InvalidFormat;
491497
492 for (elf.section_headers) |*elf_section| {498 for (elf.section_headers) |*elf_section| {
493 // TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ?499 // TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ?
494 elf_section.name = try in.readInt(elf.endian, u32);500 elf_section.name = try in.readInt(u32, elf.endian);
495 elf_section.sh_type = try in.readInt(elf.endian, u32);501 elf_section.sh_type = try in.readInt(u32, elf.endian);
496 elf_section.flags = u64(try in.readInt(elf.endian, u32));502 elf_section.flags = u64(try in.readInt(u32, elf.endian));
497 elf_section.addr = u64(try in.readInt(elf.endian, u32));503 elf_section.addr = u64(try in.readInt(u32, elf.endian));
498 elf_section.offset = u64(try in.readInt(elf.endian, u32));504 elf_section.offset = u64(try in.readInt(u32, elf.endian));
499 elf_section.size = u64(try in.readInt(elf.endian, u32));505 elf_section.size = u64(try in.readInt(u32, elf.endian));
500 elf_section.link = try in.readInt(elf.endian, u32);506 elf_section.link = try in.readInt(u32, elf.endian);
501 elf_section.info = try in.readInt(elf.endian, u32);507 elf_section.info = try in.readInt(u32, elf.endian);
502 elf_section.addr_align = u64(try in.readInt(elf.endian, u32));508 elf_section.addr_align = u64(try in.readInt(u32, elf.endian));
503 elf_section.ent_size = u64(try in.readInt(elf.endian, u32));509 elf_section.ent_size = u64(try in.readInt(u32, elf.endian));
504 }510 }
505 }511 }
506512
...@@ -521,26 +527,23 @@ pub const Elf = struct {...@@ -521,26 +527,23 @@ pub const Elf = struct {
521 pub fn close(elf: *Elf) void {527 pub fn close(elf: *Elf) void {
522 elf.allocator.free(elf.section_headers);528 elf.allocator.free(elf.section_headers);
523529
524 if (elf.auto_close_stream) elf.in_file.close();530 if (elf.auto_close_stream) elf.prealloc_file.close();
525 }531 }
526532
527 pub fn findSection(elf: *Elf, name: []const u8) !?*SectionHeader {533 pub fn findSection(elf: *Elf, name: []const u8) !?*SectionHeader {
528 var file_stream = elf.in_file.inStream();
529 const in = &file_stream.stream;
530
531 section_loop: for (elf.section_headers) |*elf_section| {534 section_loop: for (elf.section_headers) |*elf_section| {
532 if (elf_section.sh_type == SHT_NULL) continue;535 if (elf_section.sh_type == SHT_NULL) continue;
533536
534 const name_offset = elf.string_section.offset + elf_section.name;537 const name_offset = elf.string_section.offset + elf_section.name;
535 try elf.in_file.seekTo(name_offset);538 try elf.seekable_stream.seekTo(name_offset);
536539
537 for (name) |expected_c| {540 for (name) |expected_c| {
538 const target_c = try in.readByte();541 const target_c = try elf.in_stream.readByte();
539 if (target_c == 0 or expected_c != target_c) continue :section_loop;542 if (target_c == 0 or expected_c != target_c) continue :section_loop;
540 }543 }
541544
542 {545 {
543 const null_byte = try in.readByte();546 const null_byte = try elf.in_stream.readByte();
544 if (null_byte == 0) return elf_section;547 if (null_byte == 0) return elf_section;
545 }548 }
546 }549 }
...@@ -549,7 +552,7 @@ pub const Elf = struct {...@@ -549,7 +552,7 @@ pub const Elf = struct {
549 }552 }
550553
551 pub fn seekToSection(elf: *Elf, elf_section: *SectionHeader) !void {554 pub fn seekToSection(elf: *Elf, elf_section: *SectionHeader) !void {
552 try elf.in_file.seekTo(elf_section.offset);555 try elf.seekable_stream.seekTo(elf_section.offset);
553 }556 }
554};557};
555558
std/event/fs.zig+21-10
...@@ -83,6 +83,7 @@ pub async fn pwritev(loop: *Loop, fd: os.FileHandle, data: []const []const u8, o...@@ -83,6 +83,7 @@ pub async fn pwritev(loop: *Loop, fd: os.FileHandle, data: []const []const u8, o
83 switch (builtin.os) {83 switch (builtin.os) {
84 builtin.Os.macosx,84 builtin.Os.macosx,
85 builtin.Os.linux,85 builtin.Os.linux,
86 builtin.Os.freebsd,
86 => {87 => {
87 const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);88 const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);
88 defer loop.allocator.free(iovecs);89 defer loop.allocator.free(iovecs);
...@@ -219,6 +220,7 @@ pub async fn preadv(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset:...@@ -219,6 +220,7 @@ pub async fn preadv(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset:
219 switch (builtin.os) {220 switch (builtin.os) {
220 builtin.Os.macosx,221 builtin.Os.macosx,
221 builtin.Os.linux,222 builtin.Os.linux,
223 builtin.Os.freebsd,
222 => {224 => {
223 const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);225 const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);
224 defer loop.allocator.free(iovecs);226 defer loop.allocator.free(iovecs);
...@@ -399,7 +401,7 @@ pub async fn openPosix(...@@ -399,7 +401,7 @@ pub async fn openPosix(
399401
400pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!os.FileHandle {402pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!os.FileHandle {
401 switch (builtin.os) {403 switch (builtin.os) {
402 builtin.Os.macosx, builtin.Os.linux => {404 builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd => {
403 const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC;405 const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC;
404 return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);406 return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);
405 },407 },
...@@ -427,6 +429,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os...@@ -427,6 +429,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os
427 switch (builtin.os) {429 switch (builtin.os) {
428 builtin.Os.macosx,430 builtin.Os.macosx,
429 builtin.Os.linux,431 builtin.Os.linux,
432 builtin.Os.freebsd,
430 => {433 => {
431 const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC;434 const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC;
432 return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);435 return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);
...@@ -449,7 +452,7 @@ pub async fn openReadWrite(...@@ -449,7 +452,7 @@ pub async fn openReadWrite(
449 mode: os.File.Mode,452 mode: os.File.Mode,
450) os.File.OpenError!os.FileHandle {453) os.File.OpenError!os.FileHandle {
451 switch (builtin.os) {454 switch (builtin.os) {
452 builtin.Os.macosx, builtin.Os.linux => {455 builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd => {
453 const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC;456 const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC;
454 return await (async openPosix(loop, path, flags, mode) catch unreachable);457 return await (async openPosix(loop, path, flags, mode) catch unreachable);
455 },458 },
...@@ -477,7 +480,7 @@ pub const CloseOperation = struct {...@@ -477,7 +480,7 @@ pub const CloseOperation = struct {
477 os_data: OsData,480 os_data: OsData,
478481
479 const OsData = switch (builtin.os) {482 const OsData = switch (builtin.os) {
480 builtin.Os.linux, builtin.Os.macosx => OsDataPosix,483 builtin.Os.linux, builtin.Os.macosx, builtin.Os.freebsd => OsDataPosix,
481484
482 builtin.Os.windows => struct {485 builtin.Os.windows => struct {
483 handle: ?os.FileHandle,486 handle: ?os.FileHandle,
...@@ -496,7 +499,7 @@ pub const CloseOperation = struct {...@@ -496,7 +499,7 @@ pub const CloseOperation = struct {
496 self.* = CloseOperation{499 self.* = CloseOperation{
497 .loop = loop,500 .loop = loop,
498 .os_data = switch (builtin.os) {501 .os_data = switch (builtin.os) {
499 builtin.Os.linux, builtin.Os.macosx => initOsDataPosix(self),502 builtin.Os.linux, builtin.Os.macosx, builtin.Os.freebsd => initOsDataPosix(self),
500 builtin.Os.windows => OsData{ .handle = null },503 builtin.Os.windows => OsData{ .handle = null },
501 else => @compileError("Unsupported OS"),504 else => @compileError("Unsupported OS"),
502 },505 },
...@@ -525,6 +528,7 @@ pub const CloseOperation = struct {...@@ -525,6 +528,7 @@ pub const CloseOperation = struct {
525 switch (builtin.os) {528 switch (builtin.os) {
526 builtin.Os.linux,529 builtin.Os.linux,
527 builtin.Os.macosx,530 builtin.Os.macosx,
531 builtin.Os.freebsd,
528 => {532 => {
529 if (self.os_data.have_fd) {533 if (self.os_data.have_fd) {
530 self.loop.posixFsRequest(&self.os_data.close_req_node);534 self.loop.posixFsRequest(&self.os_data.close_req_node);
...@@ -546,6 +550,7 @@ pub const CloseOperation = struct {...@@ -546,6 +550,7 @@ pub const CloseOperation = struct {
546 switch (builtin.os) {550 switch (builtin.os) {
547 builtin.Os.linux,551 builtin.Os.linux,
548 builtin.Os.macosx,552 builtin.Os.macosx,
553 builtin.Os.freebsd,
549 => {554 => {
550 self.os_data.close_req_node.data.msg.Close.fd = handle;555 self.os_data.close_req_node.data.msg.Close.fd = handle;
551 self.os_data.have_fd = true;556 self.os_data.have_fd = true;
...@@ -562,6 +567,7 @@ pub const CloseOperation = struct {...@@ -562,6 +567,7 @@ pub const CloseOperation = struct {
562 switch (builtin.os) {567 switch (builtin.os) {
563 builtin.Os.linux,568 builtin.Os.linux,
564 builtin.Os.macosx,569 builtin.Os.macosx,
570 builtin.Os.freebsd,
565 => {571 => {
566 self.os_data.have_fd = false;572 self.os_data.have_fd = false;
567 },573 },
...@@ -576,6 +582,7 @@ pub const CloseOperation = struct {...@@ -576,6 +582,7 @@ pub const CloseOperation = struct {
576 switch (builtin.os) {582 switch (builtin.os) {
577 builtin.Os.linux,583 builtin.Os.linux,
578 builtin.Os.macosx,584 builtin.Os.macosx,
585 builtin.Os.freebsd,
579 => {586 => {
580 assert(self.os_data.have_fd);587 assert(self.os_data.have_fd);
581 return self.os_data.close_req_node.data.msg.Close.fd;588 return self.os_data.close_req_node.data.msg.Close.fd;
...@@ -599,6 +606,7 @@ pub async fn writeFileMode(loop: *Loop, path: []const u8, contents: []const u8,...@@ -599,6 +606,7 @@ pub async fn writeFileMode(loop: *Loop, path: []const u8, contents: []const u8,
599 switch (builtin.os) {606 switch (builtin.os) {
600 builtin.Os.linux,607 builtin.Os.linux,
601 builtin.Os.macosx,608 builtin.Os.macosx,
609 builtin.Os.freebsd,
602 => return await (async writeFileModeThread(loop, path, contents, mode) catch unreachable),610 => return await (async writeFileModeThread(loop, path, contents, mode) catch unreachable),
603 builtin.Os.windows => return await (async writeFileWindows(loop, path, contents) catch unreachable),611 builtin.Os.windows => return await (async writeFileWindows(loop, path, contents) catch unreachable),
604 else => @compileError("Unsupported OS"),612 else => @compileError("Unsupported OS"),
...@@ -704,7 +712,7 @@ pub fn Watch(comptime V: type) type {...@@ -704,7 +712,7 @@ pub fn Watch(comptime V: type) type {
704 os_data: OsData,712 os_data: OsData,
705713
706 const OsData = switch (builtin.os) {714 const OsData = switch (builtin.os) {
707 builtin.Os.macosx => struct {715 builtin.Os.macosx, builtin.Os.freebsd => struct {
708 file_table: FileTable,716 file_table: FileTable,
709 table_lock: event.Lock,717 table_lock: event.Lock,
710718
...@@ -793,7 +801,7 @@ pub fn Watch(comptime V: type) type {...@@ -793,7 +801,7 @@ pub fn Watch(comptime V: type) type {
793 return self;801 return self;
794 },802 },
795803
796 builtin.Os.macosx => {804 builtin.Os.macosx, builtin.Os.freebsd => {
797 const self = try loop.allocator.createOne(Self);805 const self = try loop.allocator.createOne(Self);
798 errdefer loop.allocator.destroy(self);806 errdefer loop.allocator.destroy(self);
799807
...@@ -813,7 +821,7 @@ pub fn Watch(comptime V: type) type {...@@ -813,7 +821,7 @@ pub fn Watch(comptime V: type) type {
813 /// All addFile calls and removeFile calls must have completed.821 /// All addFile calls and removeFile calls must have completed.
814 pub fn destroy(self: *Self) void {822 pub fn destroy(self: *Self) void {
815 switch (builtin.os) {823 switch (builtin.os) {
816 builtin.Os.macosx => {824 builtin.Os.macosx, builtin.Os.freebsd => {
817 // TODO we need to cancel the coroutines before destroying the lock825 // TODO we need to cancel the coroutines before destroying the lock
818 self.os_data.table_lock.deinit();826 self.os_data.table_lock.deinit();
819 var it = self.os_data.file_table.iterator();827 var it = self.os_data.file_table.iterator();
...@@ -855,14 +863,14 @@ pub fn Watch(comptime V: type) type {...@@ -855,14 +863,14 @@ pub fn Watch(comptime V: type) type {
855863
856 pub async fn addFile(self: *Self, file_path: []const u8, value: V) !?V {864 pub async fn addFile(self: *Self, file_path: []const u8, value: V) !?V {
857 switch (builtin.os) {865 switch (builtin.os) {
858 builtin.Os.macosx => return await (async addFileMacosx(self, file_path, value) catch unreachable),866 builtin.Os.macosx, builtin.Os.freebsd => return await (async addFileKEvent(self, file_path, value) catch unreachable),
859 builtin.Os.linux => return await (async addFileLinux(self, file_path, value) catch unreachable),867 builtin.Os.linux => return await (async addFileLinux(self, file_path, value) catch unreachable),
860 builtin.Os.windows => return await (async addFileWindows(self, file_path, value) catch unreachable),868 builtin.Os.windows => return await (async addFileWindows(self, file_path, value) catch unreachable),
861 else => @compileError("Unsupported OS"),869 else => @compileError("Unsupported OS"),
862 }870 }
863 }871 }
864872
865 async fn addFileMacosx(self: *Self, file_path: []const u8, value: V) !?V {873 async fn addFileKEvent(self: *Self, file_path: []const u8, value: V) !?V {
866 const resolved_path = try os.path.resolve(self.channel.loop.allocator, file_path);874 const resolved_path = try os.path.resolve(self.channel.loop.allocator, file_path);
867 var resolved_path_consumed = false;875 var resolved_path_consumed = false;
868 defer if (!resolved_path_consumed) self.channel.loop.allocator.free(resolved_path);876 defer if (!resolved_path_consumed) self.channel.loop.allocator.free(resolved_path);
...@@ -871,7 +879,10 @@ pub fn Watch(comptime V: type) type {...@@ -871,7 +879,10 @@ pub fn Watch(comptime V: type) type {
871 var close_op_consumed = false;879 var close_op_consumed = false;
872 defer if (!close_op_consumed) close_op.finish();880 defer if (!close_op_consumed) close_op.finish();
873881
874 const flags = posix.O_SYMLINK | posix.O_EVTONLY;882 const flags = switch (builtin.os) {
883 builtin.Os.macosx => posix.O_SYMLINK | posix.O_EVTONLY,
884 else => 0,
885 };
875 const mode = 0;886 const mode = 0;
876 const fd = try await (async openPosix(self.channel.loop, resolved_path, flags, mode) catch unreachable);887 const fd = try await (async openPosix(self.channel.loop, resolved_path, flags, mode) catch unreachable);
877 close_op.setHandle(fd);888 close_op.setHandle(fd);
std/event/io.zig+9-5
...@@ -39,18 +39,22 @@ pub fn InStream(comptime ReadError: type) type {...@@ -39,18 +39,22 @@ pub fn InStream(comptime ReadError: type) type {
39 if (amt_read < buf.len) return error.EndOfStream;39 if (amt_read < buf.len) return error.EndOfStream;
40 }40 }
4141
42 pub async fn readIntLe(self: *Self, comptime T: type) !T {42 pub async fn readIntLittle(self: *Self, comptime T: type) !T {
43 return await (async self.readInt(builtin.Endian.Little, T) catch unreachable);43 var bytes: [@sizeOf(T)]u8 = undefined;
44 try await (async self.readNoEof(bytes[0..]) catch unreachable);
45 return mem.readIntLittle(T, &bytes);
44 }46 }
4547
46 pub async fn readIntBe(self: *Self, comptime T: type) !T {48 pub async fn readIntBe(self: *Self, comptime T: type) !T {
47 return await (async self.readInt(builtin.Endian.Big, T) catch unreachable);49 var bytes: [@sizeOf(T)]u8 = undefined;
50 try await (async self.readNoEof(bytes[0..]) catch unreachable);
51 return mem.readIntBig(T, &bytes);
48 }52 }
4953
50 pub async fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T {54 pub async fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
51 var bytes: [@sizeOf(T)]u8 = undefined;55 var bytes: [@sizeOf(T)]u8 = undefined;
52 try await (async self.readNoEof(bytes[0..]) catch unreachable);56 try await (async self.readNoEof(bytes[0..]) catch unreachable);
53 return mem.readInt(bytes, T, endian);57 return mem.readInt(T, &bytes, endian);
54 }58 }
5559
56 pub async fn readStruct(self: *Self, comptime T: type) !T {60 pub async fn readStruct(self: *Self, comptime T: type) !T {
std/event/loop.zig+14-13
...@@ -49,7 +49,7 @@ pub const Loop = struct {...@@ -49,7 +49,7 @@ pub const Loop = struct {
49 };49 };
5050
51 pub const EventFd = switch (builtin.os) {51 pub const EventFd = switch (builtin.os) {
52 builtin.Os.macosx => MacOsEventFd,52 builtin.Os.macosx, builtin.Os.freebsd => KEventFd,
53 builtin.Os.linux => struct {53 builtin.Os.linux => struct {
54 base: ResumeNode,54 base: ResumeNode,
55 epoll_op: u32,55 epoll_op: u32,
...@@ -62,13 +62,13 @@ pub const Loop = struct {...@@ -62,13 +62,13 @@ pub const Loop = struct {
62 else => @compileError("unsupported OS"),62 else => @compileError("unsupported OS"),
63 };63 };
6464
65 const MacOsEventFd = struct {65 const KEventFd = struct {
66 base: ResumeNode,66 base: ResumeNode,
67 kevent: posix.Kevent,67 kevent: posix.Kevent,
68 };68 };
6969
70 pub const Basic = switch (builtin.os) {70 pub const Basic = switch (builtin.os) {
71 builtin.Os.macosx => MacOsBasic,71 builtin.Os.macosx, builtin.Os.freebsd => KEventBasic,
72 builtin.Os.linux => struct {72 builtin.Os.linux => struct {
73 base: ResumeNode,73 base: ResumeNode,
74 },74 },
...@@ -78,7 +78,7 @@ pub const Loop = struct {...@@ -78,7 +78,7 @@ pub const Loop = struct {
78 else => @compileError("unsupported OS"),78 else => @compileError("unsupported OS"),
79 };79 };
8080
81 const MacOsBasic = struct {81 const KEventBasic = struct {
82 base: ResumeNode,82 base: ResumeNode,
83 kev: posix.Kevent,83 kev: posix.Kevent,
84 };84 };
...@@ -214,7 +214,7 @@ pub const Loop = struct {...@@ -214,7 +214,7 @@ pub const Loop = struct {
214 self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun);214 self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun);
215 }215 }
216 },216 },
217 builtin.Os.macosx => {217 builtin.Os.macosx, builtin.Os.freebsd => {
218 self.os_data.kqfd = try os.bsdKQueue();218 self.os_data.kqfd = try os.bsdKQueue();
219 errdefer os.close(self.os_data.kqfd);219 errdefer os.close(self.os_data.kqfd);
220220
...@@ -369,7 +369,7 @@ pub const Loop = struct {...@@ -369,7 +369,7 @@ pub const Loop = struct {
369 os.close(self.os_data.epollfd);369 os.close(self.os_data.epollfd);
370 self.allocator.free(self.eventfd_resume_nodes);370 self.allocator.free(self.eventfd_resume_nodes);
371 },371 },
372 builtin.Os.macosx => {372 builtin.Os.macosx, builtin.Os.freebsd => {
373 os.close(self.os_data.kqfd);373 os.close(self.os_data.kqfd);
374 os.close(self.os_data.fs_kqfd);374 os.close(self.os_data.fs_kqfd);
375 },375 },
...@@ -484,7 +484,7 @@ pub const Loop = struct {...@@ -484,7 +484,7 @@ pub const Loop = struct {
484 const eventfd_node = &resume_stack_node.data;484 const eventfd_node = &resume_stack_node.data;
485 eventfd_node.base.handle = next_tick_node.data;485 eventfd_node.base.handle = next_tick_node.data;
486 switch (builtin.os) {486 switch (builtin.os) {
487 builtin.Os.macosx => {487 builtin.Os.macosx, builtin.Os.freebsd => {
488 const kevent_array = (*[1]posix.Kevent)(&eventfd_node.kevent);488 const kevent_array = (*[1]posix.Kevent)(&eventfd_node.kevent);
489 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];489 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
490 _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch {490 _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch {
...@@ -546,6 +546,7 @@ pub const Loop = struct {...@@ -546,6 +546,7 @@ pub const Loop = struct {
546 switch (builtin.os) {546 switch (builtin.os) {
547 builtin.Os.linux,547 builtin.Os.linux,
548 builtin.Os.macosx,548 builtin.Os.macosx,
549 builtin.Os.freebsd,
549 => self.os_data.fs_thread.wait(),550 => self.os_data.fs_thread.wait(),
550 else => {},551 else => {},
551 }552 }
...@@ -610,7 +611,7 @@ pub const Loop = struct {...@@ -610,7 +611,7 @@ pub const Loop = struct {
610 os.posixWrite(self.os_data.final_eventfd, wakeup_bytes) catch unreachable;611 os.posixWrite(self.os_data.final_eventfd, wakeup_bytes) catch unreachable;
611 return;612 return;
612 },613 },
613 builtin.Os.macosx => {614 builtin.Os.macosx, builtin.Os.freebsd => {
614 self.posixFsRequest(&self.os_data.fs_end_request);615 self.posixFsRequest(&self.os_data.fs_end_request);
615 const final_kevent = (*[1]posix.Kevent)(&self.os_data.final_kevent);616 const final_kevent = (*[1]posix.Kevent)(&self.os_data.final_kevent);
616 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];617 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
...@@ -668,7 +669,7 @@ pub const Loop = struct {...@@ -668,7 +669,7 @@ pub const Loop = struct {
668 }669 }
669 }670 }
670 },671 },
671 builtin.Os.macosx => {672 builtin.Os.macosx, builtin.Os.freebsd => {
672 var eventlist: [1]posix.Kevent = undefined;673 var eventlist: [1]posix.Kevent = undefined;
673 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];674 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
674 const count = os.bsdKEvent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable;675 const count = os.bsdKEvent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable;
...@@ -731,7 +732,7 @@ pub const Loop = struct {...@@ -731,7 +732,7 @@ pub const Loop = struct {
731 self.beginOneEvent(); // finished in posixFsRun after processing the msg732 self.beginOneEvent(); // finished in posixFsRun after processing the msg
732 self.os_data.fs_queue.put(request_node);733 self.os_data.fs_queue.put(request_node);
733 switch (builtin.os) {734 switch (builtin.os) {
734 builtin.Os.macosx => {735 builtin.Os.macosx, builtin.Os.freebsd => {
735 const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wake);736 const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wake);
736 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];737 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
737 _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable;738 _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable;
...@@ -801,7 +802,7 @@ pub const Loop = struct {...@@ -801,7 +802,7 @@ pub const Loop = struct {
801 else => unreachable,802 else => unreachable,
802 }803 }
803 },804 },
804 builtin.Os.macosx => {805 builtin.Os.macosx, builtin.Os.freebsd => {
805 const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wait);806 const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wait);
806 var out_kevs: [1]posix.Kevent = undefined;807 var out_kevs: [1]posix.Kevent = undefined;
807 _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable;808 _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable;
...@@ -813,7 +814,7 @@ pub const Loop = struct {...@@ -813,7 +814,7 @@ pub const Loop = struct {
813814
814 const OsData = switch (builtin.os) {815 const OsData = switch (builtin.os) {
815 builtin.Os.linux => LinuxOsData,816 builtin.Os.linux => LinuxOsData,
816 builtin.Os.macosx => MacOsData,817 builtin.Os.macosx, builtin.Os.freebsd => KEventData,
817 builtin.Os.windows => struct {818 builtin.Os.windows => struct {
818 io_port: windows.HANDLE,819 io_port: windows.HANDLE,
819 extra_thread_count: usize,820 extra_thread_count: usize,
...@@ -821,7 +822,7 @@ pub const Loop = struct {...@@ -821,7 +822,7 @@ pub const Loop = struct {
821 else => struct {},822 else => struct {},
822 };823 };
823824
824 const MacOsData = struct {825 const KEventData = struct {
825 kqfd: i32,826 kqfd: i32,
826 final_kevent: posix.Kevent,827 final_kevent: posix.Kevent,
827 fs_kevent_wake: posix.Kevent,828 fs_kevent_wake: posix.Kevent,
std/fmt/index.zig+72-8
...@@ -2,6 +2,7 @@ const std = @import("../index.zig");...@@ -2,6 +2,7 @@ const std = @import("../index.zig");
2const math = std.math;2const math = std.math;
3const debug = std.debug;3const debug = std.debug;
4const assert = debug.assert;4const assert = debug.assert;
5const assertError = debug.assertError;
5const mem = std.mem;6const mem = std.mem;
6const builtin = @import("builtin");7const builtin = @import("builtin");
7const errol = @import("errol/index.zig");8const errol = @import("errol/index.zig");
...@@ -116,7 +117,7 @@ pub fn formatType(...@@ -116,7 +117,7 @@ pub fn formatType(
116 return output(context, @errorName(value));117 return output(context, @errorName(value));
117 }118 }
118 switch (@typeInfo(T)) {119 switch (@typeInfo(T)) {
119 builtin.TypeId.Int, builtin.TypeId.Float => {120 builtin.TypeId.ComptimeInt, builtin.TypeId.Int, builtin.TypeId.Float => {
120 return formatValue(value, fmt, context, Errors, output);121 return formatValue(value, fmt, context, Errors, output);
121 },122 },
122 builtin.TypeId.Void => {123 builtin.TypeId.Void => {
...@@ -242,6 +243,9 @@ pub fn formatType(...@@ -242,6 +243,9 @@ pub fn formatType(
242 }243 }
243 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));244 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));
244 },245 },
246 builtin.TypeId.Fn => {
247 return format(context, Errors, output, "{}@{x}", @typeName(T), @ptrToInt(value));
248 },
245 else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),249 else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
246 }250 }
247}251}
...@@ -267,11 +271,15 @@ fn formatValue(...@@ -267,11 +271,15 @@ fn formatValue(
267 }271 }
268 }272 }
269273
270 comptime var T = @typeOf(value);274 const T = @typeOf(value);
271 switch (@typeId(T)) {275 switch (@typeId(T)) {
272 builtin.TypeId.Float => return formatFloatValue(value, fmt, context, Errors, output),276 builtin.TypeId.Float => return formatFloatValue(value, fmt, context, Errors, output),
273 builtin.TypeId.Int => return formatIntValue(value, fmt, context, Errors, output),277 builtin.TypeId.Int => return formatIntValue(value, fmt, context, Errors, output),
274 else => unreachable,278 builtin.TypeId.ComptimeInt => {
279 const Int = math.IntFittingRange(value, value);
280 return formatIntValue(Int(value), fmt, context, Errors, output);
281 },
282 else => comptime unreachable,
275 }283 }
276}284}
277285
...@@ -288,9 +296,10 @@ pub fn formatIntValue(...@@ -288,9 +296,10 @@ pub fn formatIntValue(
288 if (fmt.len > 0) {296 if (fmt.len > 0) {
289 switch (fmt[0]) {297 switch (fmt[0]) {
290 'c' => {298 'c' => {
291 if (@typeOf(value) == u8) {299 if (@typeOf(value).bit_count <= 8) {
292 if (fmt.len > 1) @compileError("Unknown format character: " ++ []u8{fmt[1]});300 if (fmt.len > 1)
293 return formatAsciiChar(value, context, Errors, output);301 @compileError("Unknown format character: " ++ []u8{fmt[1]});
302 return formatAsciiChar(u8(value), context, Errors, output);
294 }303 }
295 },304 },
296 'b' => {305 'b' => {
...@@ -811,13 +820,41 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned...@@ -811,13 +820,41 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned
811820
812 for (buf) |c| {821 for (buf) |c| {
813 const digit = try charToDigit(c, radix);822 const digit = try charToDigit(c, radix);
814 x = try math.mul(T, x, radix);823
815 x = try math.add(T, x, digit);824 if (x != 0) x = try math.mul(T, x, try math.cast(T, radix));
825 x = try math.add(T, x, try math.cast(T, digit));
816 }826 }
817827
818 return x;828 return x;
819}829}
820830
831test "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
821pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {858pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
822 const value = switch (c) {859 const value = switch (c) {
823 '0'...'9' => c - '0',860 '0'...'9' => c - '0',
...@@ -935,6 +972,25 @@ test "fmt.format" {...@@ -935,6 +972,25 @@ test "fmt.format" {
935 const value: u8 = 0b1100;972 const value: u8 = 0b1100;
936 try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", value);973 try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", value);
937 }974 }
975 {
976 var buf1: [32]u8 = undefined;
977 var context = BufPrintContext{ .remaining = buf1[0..] };
978 try formatType(1234, "", &context, error{BufferTooSmall}, bufPrintWrite);
979 var res = buf1[0 .. buf1.len - context.remaining.len];
980 assert(mem.eql(u8, res, "1234"));
981
982 context = BufPrintContext{ .remaining = buf1[0..] };
983 try formatType('a', "c", &context, error{BufferTooSmall}, bufPrintWrite);
984 res = buf1[0 .. buf1.len - context.remaining.len];
985 debug.warn("{}\n", res);
986 assert(mem.eql(u8, res, "a"));
987
988 context = BufPrintContext{ .remaining = buf1[0..] };
989 try formatType(0b1100, "b", &context, error{BufferTooSmall}, bufPrintWrite);
990 res = buf1[0 .. buf1.len - context.remaining.len];
991 debug.warn("{}\n", res);
992 assert(mem.eql(u8, res, "1100"));
993 }
938 {994 {
939 const value: [3]u8 = "abc";995 const value: [3]u8 = "abc";
940 try testFmt("array: abc\n", "array: {}\n", value);996 try testFmt("array: abc\n", "array: {}\n", value);
...@@ -956,6 +1012,14 @@ test "fmt.format" {...@@ -956,6 +1012,14 @@ test "fmt.format" {
956 try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", value);1012 try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", value);
957 try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", value);1013 try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", value);
958 }1014 }
1015 {
1016 const value = @intToPtr(fn () void, 0xdeadbeef);
1017 try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value);
1018 }
1019 {
1020 const value = @intToPtr(fn () void, 0xdeadbeef);
1021 try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value);
1022 }
959 try testFmt("buf: Test \n", "buf: {s5}\n", "Test");1023 try testFmt("buf: Test \n", "buf: {s5}\n", "Test");
960 try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test");1024 try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test");
961 try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C");1025 try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C");
std/hash/siphash.zig+7-7
...@@ -42,8 +42,8 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)...@@ -42,8 +42,8 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
42 pub fn init(key: []const u8) Self {42 pub fn init(key: []const u8) Self {
43 debug.assert(key.len >= 16);43 debug.assert(key.len >= 16);
4444
45 const k0 = mem.readInt(key[0..8], u64, Endian.Little);45 const k0 = mem.readIntSliceLittle(u64, key[0..8]);
46 const k1 = mem.readInt(key[8..16], u64, Endian.Little);46 const k1 = mem.readIntSliceLittle(u64, key[8..16]);
4747
48 var d = Self{48 var d = Self{
49 .v0 = k0 ^ 0x736f6d6570736575,49 .v0 = k0 ^ 0x736f6d6570736575,
...@@ -121,7 +121,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)...@@ -121,7 +121,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
121 fn round(d: *Self, b: []const u8) void {121 fn round(d: *Self, b: []const u8) void {
122 debug.assert(b.len == 8);122 debug.assert(b.len == 8);
123123
124 const m = mem.readInt(b[0..], u64, Endian.Little);124 const m = mem.readIntSliceLittle(u64, b[0..]);
125 d.v3 ^= m;125 d.v3 ^= m;
126126
127 comptime var i: usize = 0;127 comptime var i: usize = 0;
...@@ -162,7 +162,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)...@@ -162,7 +162,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
162const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";162const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";
163163
164test "siphash64-2-4 sanity" {164test "siphash64-2-4 sanity" {
165 const vectors = [][]const u8{165 const vectors = [][8]u8{
166 "\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // ""166 "\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // ""
167 "\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00"167 "\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00"
168 "\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc168 "\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc
...@@ -235,13 +235,13 @@ test "siphash64-2-4 sanity" {...@@ -235,13 +235,13 @@ test "siphash64-2-4 sanity" {
235 for (vectors) |vector, i| {235 for (vectors) |vector, i| {
236 buffer[i] = @intCast(u8, i);236 buffer[i] = @intCast(u8, i);
237237
238 const expected = mem.readInt(vector, u64, Endian.Little);238 const expected = mem.readIntLittle(u64, &vector);
239 debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);239 debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
240 }240 }
241}241}
242242
243test "siphash128-2-4 sanity" {243test "siphash128-2-4 sanity" {
244 const vectors = [][]const u8{244 const vectors = [][16]u8{
245 "\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93",245 "\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93",
246 "\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45",246 "\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45",
247 "\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4",247 "\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4",
...@@ -314,7 +314,7 @@ test "siphash128-2-4 sanity" {...@@ -314,7 +314,7 @@ test "siphash128-2-4 sanity" {
314 for (vectors) |vector, i| {314 for (vectors) |vector, i| {
315 buffer[i] = @intCast(u8, i);315 buffer[i] = @intCast(u8, i);
316316
317 const expected = mem.readInt(vector, u128, Endian.Little);317 const expected = mem.readIntLittle(u128, &vector);
318 debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);318 debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
319 }319 }
320}320}
std/hash_map.zig+14
...@@ -126,6 +126,14 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3...@@ -126,6 +126,14 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
126 };126 };
127 }127 }
128128
129 pub fn getOrPutValue(self: *Self, key: K, value: V) !*KV {
130 const res = try self.getOrPut(key);
131 if (!res.found_existing)
132 res.kv.value = value;
133
134 return res.kv;
135 }
136
129 fn ensureCapacity(self: *Self) !void {137 fn ensureCapacity(self: *Self) !void {
130 if (self.entries.len == 0) {138 if (self.entries.len == 0) {
131 return self.initCapacity(16);139 return self.initCapacity(16);
...@@ -354,6 +362,12 @@ test "basic hash map usage" {...@@ -354,6 +362,12 @@ test "basic hash map usage" {
354 gop2.kv.value = 42;362 gop2.kv.value = 42;
355 assert(map.get(99).?.value == 42);363 assert(map.get(99).?.value == 42);
356364
365 const gop3 = try map.getOrPutValue(5, 5);
366 assert(gop3.value == 77);
367
368 const gop4 = try map.getOrPutValue(100, 41);
369 assert(gop4.value == 41);
370
357 assert(map.contains(2));371 assert(map.contains(2));
358 assert(map.get(2).?.value == 22);372 assert(map.get(2).?.value == 22);
359 _ = map.remove(2);373 _ = map.remove(2);
std/heap.zig+4-4
...@@ -66,11 +66,11 @@ pub const DirectAllocator = struct {...@@ -66,11 +66,11 @@ pub const DirectAllocator = struct {
66 }66 }
67 }67 }
6868
69 fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 {69 fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 {
70 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);70 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
7171
72 switch (builtin.os) {72 switch (builtin.os) {
73 Os.linux, Os.macosx, Os.ios => {73 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
74 const p = os.posix;74 const p = os.posix;
75 const alloc_size = if (alignment <= os.page_size) n else n + alignment;75 const alloc_size = if (alignment <= os.page_size) n else n + alignment;
76 const addr = p.mmap(null, alloc_size, p.PROT_READ | p.PROT_WRITE, p.MAP_PRIVATE | p.MAP_ANONYMOUS, -1, 0);76 const addr = p.mmap(null, alloc_size, p.PROT_READ | p.PROT_WRITE, p.MAP_PRIVATE | p.MAP_ANONYMOUS, -1, 0);
...@@ -121,7 +121,7 @@ pub const DirectAllocator = struct {...@@ -121,7 +121,7 @@ pub const DirectAllocator = struct {
121 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);121 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
122122
123 switch (builtin.os) {123 switch (builtin.os) {
124 Os.linux, Os.macosx, Os.ios => {124 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
125 if (new_size <= old_mem.len) {125 if (new_size <= old_mem.len) {
126 const base_addr = @ptrToInt(old_mem.ptr);126 const base_addr = @ptrToInt(old_mem.ptr);
127 const old_addr_end = base_addr + old_mem.len;127 const old_addr_end = base_addr + old_mem.len;
...@@ -166,7 +166,7 @@ pub const DirectAllocator = struct {...@@ -166,7 +166,7 @@ pub const DirectAllocator = struct {
166 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);166 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
167167
168 switch (builtin.os) {168 switch (builtin.os) {
169 Os.linux, Os.macosx, Os.ios => {169 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
170 _ = os.posix.munmap(@ptrToInt(bytes.ptr), bytes.len);170 _ = os.posix.munmap(@ptrToInt(bytes.ptr), bytes.len);
171 },171 },
172 Os.windows => {172 Os.windows => {
std/index.zig+2-1
...@@ -57,7 +57,8 @@ test "std" {...@@ -57,7 +57,8 @@ test "std" {
57 _ = @import("mutex.zig");57 _ = @import("mutex.zig");
58 _ = @import("segmented_list.zig");58 _ = @import("segmented_list.zig");
59 _ = @import("spinlock.zig");59 _ = @import("spinlock.zig");
6060
61 _ = @import("dynamic_library.zig");
61 _ = @import("base64.zig");62 _ = @import("base64.zig");
62 _ = @import("build.zig");63 _ = @import("build.zig");
63 _ = @import("c/index.zig");64 _ = @import("c/index.zig");
std/io.zig+104-37
...@@ -32,6 +32,8 @@ pub fn getStdIn() GetStdIoErrs!File {...@@ -32,6 +32,8 @@ pub fn getStdIn() GetStdIoErrs!File {
32 return File.openHandle(handle);32 return File.openHandle(handle);
33}33}
3434
35pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;
36
35pub fn InStream(comptime ReadError: type) type {37pub fn InStream(comptime ReadError: type) type {
36 return struct {38 return struct {
37 const Self = @This();39 const Self = @This();
...@@ -150,35 +152,43 @@ pub fn InStream(comptime ReadError: type) type {...@@ -150,35 +152,43 @@ pub fn InStream(comptime ReadError: type) type {
150 }152 }
151153
152 /// Reads a native-endian integer154 /// Reads a native-endian integer
153 pub fn readIntNe(self: *Self, comptime T: type) !T {155 pub fn readIntNative(self: *Self, comptime T: type) !T {
154 return self.readInt(builtin.endian, T);156 var bytes: [@sizeOf(T)]u8 = undefined;
157 try self.readNoEof(bytes[0..]);
158 return mem.readIntNative(T, &bytes);
159 }
160
161 /// Reads a foreign-endian integer
162 pub fn readIntForeign(self: *Self, comptime T: type) !T {
163 var bytes: [@sizeOf(T)]u8 = undefined;
164 try self.readNoEof(bytes[0..]);
165 return mem.readIntForeign(T, &bytes);
155 }166 }
156167
157 pub fn readIntLe(self: *Self, comptime T: type) !T {168 pub fn readIntLittle(self: *Self, comptime T: type) !T {
158 var bytes: [@sizeOf(T)]u8 = undefined;169 var bytes: [@sizeOf(T)]u8 = undefined;
159 try self.readNoEof(bytes[0..]);170 try self.readNoEof(bytes[0..]);
160 return mem.readIntLE(T, bytes);171 return mem.readIntLittle(T, &bytes);
161 }172 }
162173
163 pub fn readIntBe(self: *Self, comptime T: type) !T {174 pub fn readIntBig(self: *Self, comptime T: type) !T {
164 var bytes: [@sizeOf(T)]u8 = undefined;175 var bytes: [@sizeOf(T)]u8 = undefined;
165 try self.readNoEof(bytes[0..]);176 try self.readNoEof(bytes[0..]);
166 return mem.readIntBE(T, bytes);177 return mem.readIntBig(T, &bytes);
167 }178 }
168179
169 pub fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T {180 pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
170 var bytes: [@sizeOf(T)]u8 = undefined;181 var bytes: [@sizeOf(T)]u8 = undefined;
171 try self.readNoEof(bytes[0..]);182 try self.readNoEof(bytes[0..]);
172 return mem.readInt(bytes, T, endian);183 return mem.readInt(T, &bytes, endian);
173 }184 }
174185
175 pub fn readVarInt(self: *Self, endian: builtin.Endian, comptime T: type, size: usize) !T {186 pub fn readVarInt(self: *Self, comptime ReturnType: type, endian: builtin.Endian, size: usize) !ReturnType {
176 assert(size <= @sizeOf(T));187 assert(size <= @sizeOf(ReturnType));
177 assert(size <= 8);188 var bytes_buf: [@sizeOf(ReturnType)]u8 = undefined;
178 var input_buf: [8]u8 = undefined;189 const bytes = bytes_buf[0..size];
179 const input_slice = input_buf[0..size];190 try self.readNoEof(bytes);
180 try self.readNoEof(input_slice);191 return mem.readVarInt(ReturnType, bytes, endian);
181 return mem.readInt(input_slice, T, endian);
182 }192 }
183193
184 pub fn skipBytes(self: *Self, num_bytes: usize) !void {194 pub fn skipBytes(self: *Self, num_bytes: usize) !void {
...@@ -227,25 +237,34 @@ pub fn OutStream(comptime WriteError: type) type {...@@ -227,25 +237,34 @@ pub fn OutStream(comptime WriteError: type) type {
227 }237 }
228238
229 /// Write a native-endian integer.239 /// Write a native-endian integer.
230 pub fn writeIntNe(self: *Self, comptime T: type, value: T) Error!void {240 pub fn writeIntNative(self: *Self, comptime T: type, value: T) Error!void {
231 return self.writeInt(builtin.endian, T, value);241 var bytes: [@sizeOf(T)]u8 = undefined;
242 mem.writeIntNative(T, &bytes, value);
243 return self.writeFn(self, bytes);
244 }
245
246 /// Write a foreign-endian integer.
247 pub fn writeIntForeign(self: *Self, comptime T: type, value: T) Error!void {
248 var bytes: [@sizeOf(T)]u8 = undefined;
249 mem.writeIntForeign(T, &bytes, value);
250 return self.writeFn(self, bytes);
232 }251 }
233252
234 pub fn writeIntLe(self: *Self, comptime T: type, value: T) Error!void {253 pub fn writeIntLittle(self: *Self, comptime T: type, value: T) Error!void {
235 var bytes: [@sizeOf(T)]u8 = undefined;254 var bytes: [@sizeOf(T)]u8 = undefined;
236 mem.writeIntLE(T, &bytes, value);255 mem.writeIntLittle(T, &bytes, value);
237 return self.writeFn(self, bytes);256 return self.writeFn(self, bytes);
238 }257 }
239258
240 pub fn writeIntBe(self: *Self, comptime T: type, value: T) Error!void {259 pub fn writeIntBig(self: *Self, comptime T: type, value: T) Error!void {
241 var bytes: [@sizeOf(T)]u8 = undefined;260 var bytes: [@sizeOf(T)]u8 = undefined;
242 mem.writeIntBE(T, &bytes, value);261 mem.writeIntBig(T, &bytes, value);
243 return self.writeFn(self, bytes);262 return self.writeFn(self, bytes);
244 }263 }
245264
246 pub fn writeInt(self: *Self, endian: builtin.Endian, comptime T: type, value: T) Error!void {265 pub fn writeInt(self: *Self, comptime T: type, value: T, endian: builtin.Endian) Error!void {
247 var bytes: [@sizeOf(T)]u8 = undefined;266 var bytes: [@sizeOf(T)]u8 = undefined;
248 mem.writeInt(bytes[0..], value, endian);267 mem.writeInt(T, &bytes, value, endian);
249 return self.writeFn(self, bytes);268 return self.writeFn(self, bytes);
250 }269 }
251 };270 };
...@@ -683,25 +702,73 @@ test "import io tests" {...@@ -683,25 +702,73 @@ test "import io tests" {
683 }702 }
684}703}
685704
686pub fn readLine(buf: []u8) !usize {705pub fn readLine(buf: *std.Buffer) ![]u8 {
687 var stdin = getStdIn() catch return error.StdInUnavailable;706 var stdin = try getStdIn();
688 var adapter = stdin.inStream();707 var stdin_stream = stdin.inStream();
689 var stream = &adapter.stream;708 return readLineFrom(&stdin_stream.stream, buf);
690 var index: usize = 0;709}
710
711/// Reads all characters until the next newline into buf, and returns
712/// a slice of the characters read (excluding the newline character(s)).
713pub fn readLineFrom(stream: var, buf: *std.Buffer) ![]u8 {
714 const start = buf.len();
691 while (true) {715 while (true) {
692 const byte = stream.readByte() catch return error.EndOfFile;716 const byte = try stream.readByte();
693 switch (byte) {717 switch (byte) {
694 '\r' => {718 '\r' => {
695 // trash the following \n719 // trash the following \n
696 _ = stream.readByte() catch return error.EndOfFile;720 _ = try stream.readByte();
697 return index;721 return buf.toSlice()[start..];
698 },
699 '\n' => return index,
700 else => {
701 if (index == buf.len) return error.InputTooLong;
702 buf[index] = byte;
703 index += 1;
704 },722 },
723 '\n' => return buf.toSlice()[start..],
724 else => try buf.appendByte(byte),
705 }725 }
706 }726 }
707}727}
728
729test "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
747pub 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)).
755pub 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
763test "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 @@
1const std = @import("../index.zig");
2const InStream = std.io.InStream;
3
4pub fn SeekableStream(comptime SeekErrorType: type, comptime GetSeekPosErrorType: type) type {
5 return struct {
6 const Self = @This();
7 pub const SeekError = SeekErrorType;
8 pub const GetSeekPosError = GetSeekPosErrorType;
9
10 seekToFn: fn (self: *Self, pos: usize) SeekError!void,
11 seekForwardFn: fn (self: *Self, pos: isize) SeekError!void,
12
13 getPosFn: fn (self: *Self) GetSeekPosError!usize,
14 getEndPosFn: fn (self: *Self) GetSeekPosError!usize,
15
16 pub fn seekTo(self: *Self, pos: usize) SeekError!void {
17 return self.seekToFn(self, pos);
18 }
19
20 pub fn seekForward(self: *Self, amt: isize) SeekError!void {
21 return self.seekForwardFn(self, amt);
22 }
23
24 pub fn getEndPos(self: *Self) GetSeekPosError!usize {
25 return self.getEndPosFn(self);
26 }
27
28 pub fn getPos(self: *Self) GetSeekPosError!usize {
29 return self.getPosFn(self);
30 }
31 };
32}
std/json.zig+17-10
...@@ -910,7 +910,7 @@ fn checkNext(p: *TokenStream, id: Token.Id) void {...@@ -910,7 +910,7 @@ fn checkNext(p: *TokenStream, id: Token.Id) void {
910 debug.assert(token.id == id);910 debug.assert(token.id == id);
911}911}
912912
913test "token" {913test "json.token" {
914 const s =914 const s =
915 \\{915 \\{
916 \\ "Image": {916 \\ "Image": {
...@@ -980,7 +980,7 @@ pub fn validate(s: []const u8) bool {...@@ -980,7 +980,7 @@ pub fn validate(s: []const u8) bool {
980 return p.complete;980 return p.complete;
981}981}
982982
983test "json validate" {983test "json.validate" {
984 debug.assert(validate("{}"));984 debug.assert(validate("{}"));
985}985}
986986
...@@ -1188,7 +1188,7 @@ pub const Parser = struct {...@@ -1188,7 +1188,7 @@ pub const Parser = struct {
1188 }1188 }
11891189
1190 var value = p.stack.pop();1190 var value = p.stack.pop();
1191 try p.pushToParent(value);1191 try p.pushToParent(&value);
1192 },1192 },
1193 Token.Id.String => {1193 Token.Id.String => {
1194 try p.stack.append(try p.parseString(allocator, token, input, i));1194 try p.stack.append(try p.parseString(allocator, token, input, i));
...@@ -1251,7 +1251,7 @@ pub const Parser = struct {...@@ -1251,7 +1251,7 @@ pub const Parser = struct {
1251 }1251 }
12521252
1253 var value = p.stack.pop();1253 var value = p.stack.pop();
1254 try p.pushToParent(value);1254 try p.pushToParent(&value);
1255 },1255 },
1256 Token.Id.ObjectBegin => {1256 Token.Id.ObjectBegin => {
1257 try p.stack.append(Value{ .Object = ObjectMap.init(allocator) });1257 try p.stack.append(Value{ .Object = ObjectMap.init(allocator) });
...@@ -1312,19 +1312,19 @@ pub const Parser = struct {...@@ -1312,19 +1312,19 @@ pub const Parser = struct {
1312 }1312 }
1313 }1313 }
13141314
1315 fn pushToParent(p: *Parser, value: Value) !void {1315 fn pushToParent(p: *Parser, value: *const Value) !void {
1316 switch (p.stack.at(p.stack.len - 1)) {1316 switch (p.stack.toSlice()[p.stack.len - 1]) {
1317 // Object Parent -> [ ..., object, <key>, value ]1317 // Object Parent -> [ ..., object, <key>, value ]
1318 Value.String => |key| {1318 Value.String => |key| {
1319 _ = p.stack.pop();1319 _ = p.stack.pop();
13201320
1321 var object = &p.stack.items[p.stack.len - 1].Object;1321 var object = &p.stack.items[p.stack.len - 1].Object;
1322 _ = try object.put(key, value);1322 _ = try object.put(key, value.*);
1323 p.state = State.ObjectKey;1323 p.state = State.ObjectKey;
1324 },1324 },
1325 // Array Parent -> [ ..., <array>, value ]1325 // Array Parent -> [ ..., <array>, value ]
1326 Value.Array => |*array| {1326 Value.Array => |*array| {
1327 try array.append(value);1327 try array.append(value.*);
1328 p.state = State.ArrayValue;1328 p.state = State.ArrayValue;
1329 },1329 },
1330 else => {1330 else => {
...@@ -1348,7 +1348,7 @@ pub const Parser = struct {...@@ -1348,7 +1348,7 @@ pub const Parser = struct {
1348 }1348 }
1349};1349};
13501350
1351test "json parser dynamic" {1351test "json.parser.dynamic" {
1352 var p = Parser.init(debug.global_allocator, false);1352 var p = Parser.init(debug.global_allocator, false);
1353 defer p.deinit();1353 defer p.deinit();
13541354
...@@ -1364,7 +1364,8 @@ test "json parser dynamic" {...@@ -1364,7 +1364,8 @@ test "json parser dynamic" {
1364 \\ "Width": 1001364 \\ "Width": 100
1365 \\ },1365 \\ },
1366 \\ "Animated" : false,1366 \\ "Animated" : false,
1367 \\ "IDs": [116, 943, 234, 38793]1367 \\ "IDs": [116, 943, 234, 38793],
1368 \\ "ArrayOfObject": [{"n": "m"}]
1368 \\ }1369 \\ }
1369 \\}1370 \\}
1370 ;1371 ;
...@@ -1387,4 +1388,10 @@ test "json parser dynamic" {...@@ -1387,4 +1388,10 @@ test "json parser dynamic" {
13871388
1388 const animated = image.Object.get("Animated").?.value;1389 const animated = image.Object.get("Animated").?.value;
1389 debug.assert(animated.Bool == false);1390 debug.assert(animated.Bool == false);
1391
1392 const array_of_object = image.Object.get("ArrayOfObject").?.value;
1393 debug.assert(array_of_object.Array.len == 1);
1394
1395 const obj0 = array_of_object.Array.at(0).Object.get("n").?.value;
1396 debug.assert(mem.eql(u8, obj0.String, "m"));
1390}1397}
std/json_test.zig+319-319
...@@ -21,7 +21,7 @@ fn any(comptime s: []const u8) void {...@@ -21,7 +21,7 @@ fn any(comptime s: []const u8) void {
21//21//
22// Additional tests not part of test JSONTestSuite.22// Additional tests not part of test JSONTestSuite.
2323
24test "y_trailing_comma_after_empty" {24test "json.test.y_trailing_comma_after_empty" {
25 ok(25 ok(
26 \\{"1":[],"2":{},"3":"4"}26 \\{"1":[],"2":{},"3":"4"}
27 );27 );
...@@ -29,252 +29,252 @@ test "y_trailing_comma_after_empty" {...@@ -29,252 +29,252 @@ test "y_trailing_comma_after_empty" {
2929
30////////////////////////////////////////////////////////////////////////////////////////////////////30////////////////////////////////////////////////////////////////////////////////////////////////////
3131
32test "y_array_arraysWithSpaces" {32test "json.test.y_array_arraysWithSpaces" {
33 ok(33 ok(
34 \\[[] ]34 \\[[] ]
35 );35 );
36}36}
3737
38test "y_array_empty" {38test "json.test.y_array_empty" {
39 ok(39 ok(
40 \\[]40 \\[]
41 );41 );
42}42}
4343
44test "y_array_empty-string" {44test "json.test.y_array_empty-string" {
45 ok(45 ok(
46 \\[""]46 \\[""]
47 );47 );
48}48}
4949
50test "y_array_ending_with_newline" {50test "json.test.y_array_ending_with_newline" {
51 ok(51 ok(
52 \\["a"]52 \\["a"]
53 );53 );
54}54}
5555
56test "y_array_false" {56test "json.test.y_array_false" {
57 ok(57 ok(
58 \\[false]58 \\[false]
59 );59 );
60}60}
6161
62test "y_array_heterogeneous" {62test "json.test.y_array_heterogeneous" {
63 ok(63 ok(
64 \\[null, 1, "1", {}]64 \\[null, 1, "1", {}]
65 );65 );
66}66}
6767
68test "y_array_null" {68test "json.test.y_array_null" {
69 ok(69 ok(
70 \\[null]70 \\[null]
71 );71 );
72}72}
7373
74test "y_array_with_1_and_newline" {74test "json.test.y_array_with_1_and_newline" {
75 ok(75 ok(
76 \\[176 \\[1
77 \\]77 \\]
78 );78 );
79}79}
8080
81test "y_array_with_leading_space" {81test "json.test.y_array_with_leading_space" {
82 ok(82 ok(
83 \\ [1]83 \\ [1]
84 );84 );
85}85}
8686
87test "y_array_with_several_null" {87test "json.test.y_array_with_several_null" {
88 ok(88 ok(
89 \\[1,null,null,null,2]89 \\[1,null,null,null,2]
90 );90 );
91}91}
9292
93test "y_array_with_trailing_space" {93test "json.test.y_array_with_trailing_space" {
94 ok("[2] ");94 ok("[2] ");
95}95}
9696
97test "y_number_0e+1" {97test "json.test.y_number_0e+1" {
98 ok(98 ok(
99 \\[0e+1]99 \\[0e+1]
100 );100 );
101}101}
102102
103test "y_number_0e1" {103test "json.test.y_number_0e1" {
104 ok(104 ok(
105 \\[0e1]105 \\[0e1]
106 );106 );
107}107}
108108
109test "y_number_after_space" {109test "json.test.y_number_after_space" {
110 ok(110 ok(
111 \\[ 4]111 \\[ 4]
112 );112 );
113}113}
114114
115test "y_number_double_close_to_zero" {115test "json.test.y_number_double_close_to_zero" {
116 ok(116 ok(
117 \\[-0.000000000000000000000000000000000000000000000000000000000000000000000000000001]117 \\[-0.000000000000000000000000000000000000000000000000000000000000000000000000000001]
118 );118 );
119}119}
120120
121test "y_number_int_with_exp" {121test "json.test.y_number_int_with_exp" {
122 ok(122 ok(
123 \\[20e1]123 \\[20e1]
124 );124 );
125}125}
126126
127test "y_number" {127test "json.test.y_number" {
128 ok(128 ok(
129 \\[123e65]129 \\[123e65]
130 );130 );
131}131}
132132
133test "y_number_minus_zero" {133test "json.test.y_number_minus_zero" {
134 ok(134 ok(
135 \\[-0]135 \\[-0]
136 );136 );
137}137}
138138
139test "y_number_negative_int" {139test "json.test.y_number_negative_int" {
140 ok(140 ok(
141 \\[-123]141 \\[-123]
142 );142 );
143}143}
144144
145test "y_number_negative_one" {145test "json.test.y_number_negative_one" {
146 ok(146 ok(
147 \\[-1]147 \\[-1]
148 );148 );
149}149}
150150
151test "y_number_negative_zero" {151test "json.test.y_number_negative_zero" {
152 ok(152 ok(
153 \\[-0]153 \\[-0]
154 );154 );
155}155}
156156
157test "y_number_real_capital_e" {157test "json.test.y_number_real_capital_e" {
158 ok(158 ok(
159 \\[1E22]159 \\[1E22]
160 );160 );
161}161}
162162
163test "y_number_real_capital_e_neg_exp" {163test "json.test.y_number_real_capital_e_neg_exp" {
164 ok(164 ok(
165 \\[1E-2]165 \\[1E-2]
166 );166 );
167}167}
168168
169test "y_number_real_capital_e_pos_exp" {169test "json.test.y_number_real_capital_e_pos_exp" {
170 ok(170 ok(
171 \\[1E+2]171 \\[1E+2]
172 );172 );
173}173}
174174
175test "y_number_real_exponent" {175test "json.test.y_number_real_exponent" {
176 ok(176 ok(
177 \\[123e45]177 \\[123e45]
178 );178 );
179}179}
180180
181test "y_number_real_fraction_exponent" {181test "json.test.y_number_real_fraction_exponent" {
182 ok(182 ok(
183 \\[123.456e78]183 \\[123.456e78]
184 );184 );
185}185}
186186
187test "y_number_real_neg_exp" {187test "json.test.y_number_real_neg_exp" {
188 ok(188 ok(
189 \\[1e-2]189 \\[1e-2]
190 );190 );
191}191}
192192
193test "y_number_real_pos_exponent" {193test "json.test.y_number_real_pos_exponent" {
194 ok(194 ok(
195 \\[1e+2]195 \\[1e+2]
196 );196 );
197}197}
198198
199test "y_number_simple_int" {199test "json.test.y_number_simple_int" {
200 ok(200 ok(
201 \\[123]201 \\[123]
202 );202 );
203}203}
204204
205test "y_number_simple_real" {205test "json.test.y_number_simple_real" {
206 ok(206 ok(
207 \\[123.456789]207 \\[123.456789]
208 );208 );
209}209}
210210
211test "y_object_basic" {211test "json.test.y_object_basic" {
212 ok(212 ok(
213 \\{"asd":"sdf"}213 \\{"asd":"sdf"}
214 );214 );
215}215}
216216
217test "y_object_duplicated_key_and_value" {217test "json.test.y_object_duplicated_key_and_value" {
218 ok(218 ok(
219 \\{"a":"b","a":"b"}219 \\{"a":"b","a":"b"}
220 );220 );
221}221}
222222
223test "y_object_duplicated_key" {223test "json.test.y_object_duplicated_key" {
224 ok(224 ok(
225 \\{"a":"b","a":"c"}225 \\{"a":"b","a":"c"}
226 );226 );
227}227}
228228
229test "y_object_empty" {229test "json.test.y_object_empty" {
230 ok(230 ok(
231 \\{}231 \\{}
232 );232 );
233}233}
234234
235test "y_object_empty_key" {235test "json.test.y_object_empty_key" {
236 ok(236 ok(
237 \\{"":0}237 \\{"":0}
238 );238 );
239}239}
240240
241test "y_object_escaped_null_in_key" {241test "json.test.y_object_escaped_null_in_key" {
242 ok(242 ok(
243 \\{"foo\u0000bar": 42}243 \\{"foo\u0000bar": 42}
244 );244 );
245}245}
246246
247test "y_object_extreme_numbers" {247test "json.test.y_object_extreme_numbers" {
248 ok(248 ok(
249 \\{ "min": -1.0e+28, "max": 1.0e+28 }249 \\{ "min": -1.0e+28, "max": 1.0e+28 }
250 );250 );
251}251}
252252
253test "y_object" {253test "json.test.y_object" {
254 ok(254 ok(
255 \\{"asd":"sdf", "dfg":"fgh"}255 \\{"asd":"sdf", "dfg":"fgh"}
256 );256 );
257}257}
258258
259test "y_object_long_strings" {259test "json.test.y_object_long_strings" {
260 ok(260 ok(
261 \\{"x":[{"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}], "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}261 \\{"x":[{"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}], "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
262 );262 );
263}263}
264264
265test "y_object_simple" {265test "json.test.y_object_simple" {
266 ok(266 ok(
267 \\{"a":[]}267 \\{"a":[]}
268 );268 );
269}269}
270270
271test "y_object_string_unicode" {271test "json.test.y_object_string_unicode" {
272 ok(272 ok(
273 \\{"title":"\u041f\u043e\u043b\u0442\u043e\u0440\u0430 \u0417\u0435\u043c\u043b\u0435\u043a\u043e\u043f\u0430" }273 \\{"title":"\u041f\u043e\u043b\u0442\u043e\u0440\u0430 \u0417\u0435\u043c\u043b\u0435\u043a\u043e\u043f\u0430" }
274 );274 );
275}275}
276276
277test "y_object_with_newlines" {277test "json.test.y_object_with_newlines" {
278 ok(278 ok(
279 \\{279 \\{
280 \\"a": "b"280 \\"a": "b"
...@@ -282,419 +282,419 @@ test "y_object_with_newlines" {...@@ -282,419 +282,419 @@ test "y_object_with_newlines" {
282 );282 );
283}283}
284284
285test "y_string_1_2_3_bytes_UTF-8_sequences" {285test "json.test.y_string_1_2_3_bytes_UTF-8_sequences" {
286 ok(286 ok(
287 \\["\u0060\u012a\u12AB"]287 \\["\u0060\u012a\u12AB"]
288 );288 );
289}289}
290290
291test "y_string_accepted_surrogate_pair" {291test "json.test.y_string_accepted_surrogate_pair" {
292 ok(292 ok(
293 \\["\uD801\udc37"]293 \\["\uD801\udc37"]
294 );294 );
295}295}
296296
297test "y_string_accepted_surrogate_pairs" {297test "json.test.y_string_accepted_surrogate_pairs" {
298 ok(298 ok(
299 \\["\ud83d\ude39\ud83d\udc8d"]299 \\["\ud83d\ude39\ud83d\udc8d"]
300 );300 );
301}301}
302302
303test "y_string_allowed_escapes" {303test "json.test.y_string_allowed_escapes" {
304 ok(304 ok(
305 \\["\"\\\/\b\f\n\r\t"]305 \\["\"\\\/\b\f\n\r\t"]
306 );306 );
307}307}
308308
309test "y_string_backslash_and_u_escaped_zero" {309test "json.test.y_string_backslash_and_u_escaped_zero" {
310 ok(310 ok(
311 \\["\\u0000"]311 \\["\\u0000"]
312 );312 );
313}313}
314314
315test "y_string_backslash_doublequotes" {315test "json.test.y_string_backslash_doublequotes" {
316 ok(316 ok(
317 \\["\""]317 \\["\""]
318 );318 );
319}319}
320320
321test "y_string_comments" {321test "json.test.y_string_comments" {
322 ok(322 ok(
323 \\["a/*b*/c/*d//e"]323 \\["a/*b*/c/*d//e"]
324 );324 );
325}325}
326326
327test "y_string_double_escape_a" {327test "json.test.y_string_double_escape_a" {
328 ok(328 ok(
329 \\["\\a"]329 \\["\\a"]
330 );330 );
331}331}
332332
333test "y_string_double_escape_n" {333test "json.test.y_string_double_escape_n" {
334 ok(334 ok(
335 \\["\\n"]335 \\["\\n"]
336 );336 );
337}337}
338338
339test "y_string_escaped_control_character" {339test "json.test.y_string_escaped_control_character" {
340 ok(340 ok(
341 \\["\u0012"]341 \\["\u0012"]
342 );342 );
343}343}
344344
345test "y_string_escaped_noncharacter" {345test "json.test.y_string_escaped_noncharacter" {
346 ok(346 ok(
347 \\["\uFFFF"]347 \\["\uFFFF"]
348 );348 );
349}349}
350350
351test "y_string_in_array" {351test "json.test.y_string_in_array" {
352 ok(352 ok(
353 \\["asd"]353 \\["asd"]
354 );354 );
355}355}
356356
357test "y_string_in_array_with_leading_space" {357test "json.test.y_string_in_array_with_leading_space" {
358 ok(358 ok(
359 \\[ "asd"]359 \\[ "asd"]
360 );360 );
361}361}
362362
363test "y_string_last_surrogates_1_and_2" {363test "json.test.y_string_last_surrogates_1_and_2" {
364 ok(364 ok(
365 \\["\uDBFF\uDFFF"]365 \\["\uDBFF\uDFFF"]
366 );366 );
367}367}
368368
369test "y_string_nbsp_uescaped" {369test "json.test.y_string_nbsp_uescaped" {
370 ok(370 ok(
371 \\["new\u00A0line"]371 \\["new\u00A0line"]
372 );372 );
373}373}
374374
375test "y_string_nonCharacterInUTF-8_U+10FFFF" {375test "json.test.y_string_nonCharacterInUTF-8_U+10FFFF" {
376 ok(376 ok(
377 \\["􏿿"]377 \\["􏿿"]
378 );378 );
379}379}
380380
381test "y_string_nonCharacterInUTF-8_U+FFFF" {381test "json.test.y_string_nonCharacterInUTF-8_U+FFFF" {
382 ok(382 ok(
383 \\["￿"]383 \\["￿"]
384 );384 );
385}385}
386386
387test "y_string_null_escape" {387test "json.test.y_string_null_escape" {
388 ok(388 ok(
389 \\["\u0000"]389 \\["\u0000"]
390 );390 );
391}391}
392392
393test "y_string_one-byte-utf-8" {393test "json.test.y_string_one-byte-utf-8" {
394 ok(394 ok(
395 \\["\u002c"]395 \\["\u002c"]
396 );396 );
397}397}
398398
399test "y_string_pi" {399test "json.test.y_string_pi" {
400 ok(400 ok(
401 \\["π"]401 \\["π"]
402 );402 );
403}403}
404404
405test "y_string_reservedCharacterInUTF-8_U+1BFFF" {405test "json.test.y_string_reservedCharacterInUTF-8_U+1BFFF" {
406 ok(406 ok(
407 \\["𛿿"]407 \\["𛿿"]
408 );408 );
409}409}
410410
411test "y_string_simple_ascii" {411test "json.test.y_string_simple_ascii" {
412 ok(412 ok(
413 \\["asd "]413 \\["asd "]
414 );414 );
415}415}
416416
417test "y_string_space" {417test "json.test.y_string_space" {
418 ok(418 ok(
419 \\" "419 \\" "
420 );420 );
421}421}
422422
423test "y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF" {423test "json.test.y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF" {
424 ok(424 ok(
425 \\["\uD834\uDd1e"]425 \\["\uD834\uDd1e"]
426 );426 );
427}427}
428428
429test "y_string_three-byte-utf-8" {429test "json.test.y_string_three-byte-utf-8" {
430 ok(430 ok(
431 \\["\u0821"]431 \\["\u0821"]
432 );432 );
433}433}
434434
435test "y_string_two-byte-utf-8" {435test "json.test.y_string_two-byte-utf-8" {
436 ok(436 ok(
437 \\["\u0123"]437 \\["\u0123"]
438 );438 );
439}439}
440440
441test "y_string_u+2028_line_sep" {441test "json.test.y_string_u+2028_line_sep" {
442 ok("[\"\xe2\x80\xa8\"]");442 ok("[\"\xe2\x80\xa8\"]");
443}443}
444444
445test "y_string_u+2029_par_sep" {445test "json.test.y_string_u+2029_par_sep" {
446 ok("[\"\xe2\x80\xa9\"]");446 ok("[\"\xe2\x80\xa9\"]");
447}447}
448448
449test "y_string_uescaped_newline" {449test "json.test.y_string_uescaped_newline" {
450 ok(450 ok(
451 \\["new\u000Aline"]451 \\["new\u000Aline"]
452 );452 );
453}453}
454454
455test "y_string_uEscape" {455test "json.test.y_string_uEscape" {
456 ok(456 ok(
457 \\["\u0061\u30af\u30EA\u30b9"]457 \\["\u0061\u30af\u30EA\u30b9"]
458 );458 );
459}459}
460460
461test "y_string_unescaped_char_delete" {461test "json.test.y_string_unescaped_char_delete" {
462 ok("[\"\x7f\"]");462 ok("[\"\x7f\"]");
463}463}
464464
465test "y_string_unicode_2" {465test "json.test.y_string_unicode_2" {
466 ok(466 ok(
467 \\["⍂㈴⍂"]467 \\["⍂㈴⍂"]
468 );468 );
469}469}
470470
471test "y_string_unicodeEscapedBackslash" {471test "json.test.y_string_unicodeEscapedBackslash" {
472 ok(472 ok(
473 \\["\u005C"]473 \\["\u005C"]
474 );474 );
475}475}
476476
477test "y_string_unicode_escaped_double_quote" {477test "json.test.y_string_unicode_escaped_double_quote" {
478 ok(478 ok(
479 \\["\u0022"]479 \\["\u0022"]
480 );480 );
481}481}
482482
483test "y_string_unicode" {483test "json.test.y_string_unicode" {
484 ok(484 ok(
485 \\["\uA66D"]485 \\["\uA66D"]
486 );486 );
487}487}
488488
489test "y_string_unicode_U+10FFFE_nonchar" {489test "json.test.y_string_unicode_U+10FFFE_nonchar" {
490 ok(490 ok(
491 \\["\uDBFF\uDFFE"]491 \\["\uDBFF\uDFFE"]
492 );492 );
493}493}
494494
495test "y_string_unicode_U+1FFFE_nonchar" {495test "json.test.y_string_unicode_U+1FFFE_nonchar" {
496 ok(496 ok(
497 \\["\uD83F\uDFFE"]497 \\["\uD83F\uDFFE"]
498 );498 );
499}499}
500500
501test "y_string_unicode_U+200B_ZERO_WIDTH_SPACE" {501test "json.test.y_string_unicode_U+200B_ZERO_WIDTH_SPACE" {
502 ok(502 ok(
503 \\["\u200B"]503 \\["\u200B"]
504 );504 );
505}505}
506506
507test "y_string_unicode_U+2064_invisible_plus" {507test "json.test.y_string_unicode_U+2064_invisible_plus" {
508 ok(508 ok(
509 \\["\u2064"]509 \\["\u2064"]
510 );510 );
511}511}
512512
513test "y_string_unicode_U+FDD0_nonchar" {513test "json.test.y_string_unicode_U+FDD0_nonchar" {
514 ok(514 ok(
515 \\["\uFDD0"]515 \\["\uFDD0"]
516 );516 );
517}517}
518518
519test "y_string_unicode_U+FFFE_nonchar" {519test "json.test.y_string_unicode_U+FFFE_nonchar" {
520 ok(520 ok(
521 \\["\uFFFE"]521 \\["\uFFFE"]
522 );522 );
523}523}
524524
525test "y_string_utf8" {525test "json.test.y_string_utf8" {
526 ok(526 ok(
527 \\["€𝄞"]527 \\["€𝄞"]
528 );528 );
529}529}
530530
531test "y_string_with_del_character" {531test "json.test.y_string_with_del_character" {
532 ok("[\"a\x7fa\"]");532 ok("[\"a\x7fa\"]");
533}533}
534534
535test "y_structure_lonely_false" {535test "json.test.y_structure_lonely_false" {
536 ok(536 ok(
537 \\false537 \\false
538 );538 );
539}539}
540540
541test "y_structure_lonely_int" {541test "json.test.y_structure_lonely_int" {
542 ok(542 ok(
543 \\42543 \\42
544 );544 );
545}545}
546546
547test "y_structure_lonely_negative_real" {547test "json.test.y_structure_lonely_negative_real" {
548 ok(548 ok(
549 \\-0.1549 \\-0.1
550 );550 );
551}551}
552552
553test "y_structure_lonely_null" {553test "json.test.y_structure_lonely_null" {
554 ok(554 ok(
555 \\null555 \\null
556 );556 );
557}557}
558558
559test "y_structure_lonely_string" {559test "json.test.y_structure_lonely_string" {
560 ok(560 ok(
561 \\"asd"561 \\"asd"
562 );562 );
563}563}
564564
565test "y_structure_lonely_true" {565test "json.test.y_structure_lonely_true" {
566 ok(566 ok(
567 \\true567 \\true
568 );568 );
569}569}
570570
571test "y_structure_string_empty" {571test "json.test.y_structure_string_empty" {
572 ok(572 ok(
573 \\""573 \\""
574 );574 );
575}575}
576576
577test "y_structure_trailing_newline" {577test "json.test.y_structure_trailing_newline" {
578 ok(578 ok(
579 \\["a"]579 \\["a"]
580 );580 );
581}581}
582582
583test "y_structure_true_in_array" {583test "json.test.y_structure_true_in_array" {
584 ok(584 ok(
585 \\[true]585 \\[true]
586 );586 );
587}587}
588588
589test "y_structure_whitespace_array" {589test "json.test.y_structure_whitespace_array" {
590 ok(" [] ");590 ok(" [] ");
591}591}
592592
593////////////////////////////////////////////////////////////////////////////////////////////////////593////////////////////////////////////////////////////////////////////////////////////////////////////
594594
595test "n_array_1_true_without_comma" {595test "json.test.n_array_1_true_without_comma" {
596 err(596 err(
597 \\[1 true]597 \\[1 true]
598 );598 );
599}599}
600600
601test "n_array_a_invalid_utf8" {601test "json.test.n_array_a_invalid_utf8" {
602 err(602 err(
603 \\[aå]603 \\[aå]
604 );604 );
605}605}
606606
607test "n_array_colon_instead_of_comma" {607test "json.test.n_array_colon_instead_of_comma" {
608 err(608 err(
609 \\["": 1]609 \\["": 1]
610 );610 );
611}611}
612612
613test "n_array_comma_after_close" {613test "json.test.n_array_comma_after_close" {
614 //err(614 //err(
615 // \\[""],615 // \\[""],
616 //);616 //);
617}617}
618618
619test "n_array_comma_and_number" {619test "json.test.n_array_comma_and_number" {
620 err(620 err(
621 \\[,1]621 \\[,1]
622 );622 );
623}623}
624624
625test "n_array_double_comma" {625test "json.test.n_array_double_comma" {
626 err(626 err(
627 \\[1,,2]627 \\[1,,2]
628 );628 );
629}629}
630630
631test "n_array_double_extra_comma" {631test "json.test.n_array_double_extra_comma" {
632 err(632 err(
633 \\["x",,]633 \\["x",,]
634 );634 );
635}635}
636636
637test "n_array_extra_close" {637test "json.test.n_array_extra_close" {
638 err(638 err(
639 \\["x"]]639 \\["x"]]
640 );640 );
641}641}
642642
643test "n_array_extra_comma" {643test "json.test.n_array_extra_comma" {
644 //err(644 //err(
645 // \\["",]645 // \\["",]
646 //);646 //);
647}647}
648648
649test "n_array_incomplete_invalid_value" {649test "json.test.n_array_incomplete_invalid_value" {
650 err(650 err(
651 \\[x651 \\[x
652 );652 );
653}653}
654654
655test "n_array_incomplete" {655test "json.test.n_array_incomplete" {
656 err(656 err(
657 \\["x"657 \\["x"
658 );658 );
659}659}
660660
661test "n_array_inner_array_no_comma" {661test "json.test.n_array_inner_array_no_comma" {
662 err(662 err(
663 \\[3[4]]663 \\[3[4]]
664 );664 );
665}665}
666666
667test "n_array_invalid_utf8" {667test "json.test.n_array_invalid_utf8" {
668 err(668 err(
669 \\[ÿ]669 \\[ÿ]
670 );670 );
671}671}
672672
673test "n_array_items_separated_by_semicolon" {673test "json.test.n_array_items_separated_by_semicolon" {
674 err(674 err(
675 \\[1:2]675 \\[1:2]
676 );676 );
677}677}
678678
679test "n_array_just_comma" {679test "json.test.n_array_just_comma" {
680 err(680 err(
681 \\[,]681 \\[,]
682 );682 );
683}683}
684684
685test "n_array_just_minus" {685test "json.test.n_array_just_minus" {
686 err(686 err(
687 \\[-]687 \\[-]
688 );688 );
689}689}
690690
691test "n_array_missing_value" {691test "json.test.n_array_missing_value" {
692 err(692 err(
693 \\[ , ""]693 \\[ , ""]
694 );694 );
695}695}
696696
697test "n_array_newlines_unclosed" {697test "json.test.n_array_newlines_unclosed" {
698 err(698 err(
699 \\["a",699 \\["a",
700 \\4700 \\4
...@@ -702,41 +702,41 @@ test "n_array_newlines_unclosed" {...@@ -702,41 +702,41 @@ test "n_array_newlines_unclosed" {
702 );702 );
703}703}
704704
705test "n_array_number_and_comma" {705test "json.test.n_array_number_and_comma" {
706 err(706 err(
707 \\[1,]707 \\[1,]
708 );708 );
709}709}
710710
711test "n_array_number_and_several_commas" {711test "json.test.n_array_number_and_several_commas" {
712 err(712 err(
713 \\[1,,]713 \\[1,,]
714 );714 );
715}715}
716716
717test "n_array_spaces_vertical_tab_formfeed" {717test "json.test.n_array_spaces_vertical_tab_formfeed" {
718 err("[\"\x0aa\"\\f]");718 err("[\"\x0aa\"\\f]");
719}719}
720720
721test "n_array_star_inside" {721test "json.test.n_array_star_inside" {
722 err(722 err(
723 \\[*]723 \\[*]
724 );724 );
725}725}
726726
727test "n_array_unclosed" {727test "json.test.n_array_unclosed" {
728 err(728 err(
729 \\[""729 \\[""
730 );730 );
731}731}
732732
733test "n_array_unclosed_trailing_comma" {733test "json.test.n_array_unclosed_trailing_comma" {
734 err(734 err(
735 \\[1,735 \\[1,
736 );736 );
737}737}
738738
739test "n_array_unclosed_with_new_lines" {739test "json.test.n_array_unclosed_with_new_lines" {
740 err(740 err(
741 \\[1,741 \\[1,
742 \\1742 \\1
...@@ -744,956 +744,956 @@ test "n_array_unclosed_with_new_lines" {...@@ -744,956 +744,956 @@ test "n_array_unclosed_with_new_lines" {
744 );744 );
745}745}
746746
747test "n_array_unclosed_with_object_inside" {747test "json.test.n_array_unclosed_with_object_inside" {
748 err(748 err(
749 \\[{}749 \\[{}
750 );750 );
751}751}
752752
753test "n_incomplete_false" {753test "json.test.n_incomplete_false" {
754 err(754 err(
755 \\[fals]755 \\[fals]
756 );756 );
757}757}
758758
759test "n_incomplete_null" {759test "json.test.n_incomplete_null" {
760 err(760 err(
761 \\[nul]761 \\[nul]
762 );762 );
763}763}
764764
765test "n_incomplete_true" {765test "json.test.n_incomplete_true" {
766 err(766 err(
767 \\[tru]767 \\[tru]
768 );768 );
769}769}
770770
771test "n_multidigit_number_then_00" {771test "json.test.n_multidigit_number_then_00" {
772 err("123\x00");772 err("123\x00");
773}773}
774774
775test "n_number_0.1.2" {775test "json.test.n_number_0.1.2" {
776 err(776 err(
777 \\[0.1.2]777 \\[0.1.2]
778 );778 );
779}779}
780780
781test "n_number_-01" {781test "json.test.n_number_-01" {
782 err(782 err(
783 \\[-01]783 \\[-01]
784 );784 );
785}785}
786786
787test "n_number_0.3e" {787test "json.test.n_number_0.3e" {
788 err(788 err(
789 \\[0.3e]789 \\[0.3e]
790 );790 );
791}791}
792792
793test "n_number_0.3e+" {793test "json.test.n_number_0.3e+" {
794 err(794 err(
795 \\[0.3e+]795 \\[0.3e+]
796 );796 );
797}797}
798798
799test "n_number_0_capital_E" {799test "json.test.n_number_0_capital_E" {
800 err(800 err(
801 \\[0E]801 \\[0E]
802 );802 );
803}803}
804804
805test "n_number_0_capital_E+" {805test "json.test.n_number_0_capital_E+" {
806 err(806 err(
807 \\[0E+]807 \\[0E+]
808 );808 );
809}809}
810810
811test "n_number_0.e1" {811test "json.test.n_number_0.e1" {
812 err(812 err(
813 \\[0.e1]813 \\[0.e1]
814 );814 );
815}815}
816816
817test "n_number_0e" {817test "json.test.n_number_0e" {
818 err(818 err(
819 \\[0e]819 \\[0e]
820 );820 );
821}821}
822822
823test "n_number_0e+" {823test "json.test.n_number_0e+" {
824 err(824 err(
825 \\[0e+]825 \\[0e+]
826 );826 );
827}827}
828828
829test "n_number_1_000" {829test "json.test.n_number_1_000" {
830 err(830 err(
831 \\[1 000.0]831 \\[1 000.0]
832 );832 );
833}833}
834834
835test "n_number_1.0e-" {835test "json.test.n_number_1.0e-" {
836 err(836 err(
837 \\[1.0e-]837 \\[1.0e-]
838 );838 );
839}839}
840840
841test "n_number_1.0e" {841test "json.test.n_number_1.0e" {
842 err(842 err(
843 \\[1.0e]843 \\[1.0e]
844 );844 );
845}845}
846846
847test "n_number_1.0e+" {847test "json.test.n_number_1.0e+" {
848 err(848 err(
849 \\[1.0e+]849 \\[1.0e+]
850 );850 );
851}851}
852852
853test "n_number_-1.0." {853test "json.test.n_number_-1.0." {
854 err(854 err(
855 \\[-1.0.]855 \\[-1.0.]
856 );856 );
857}857}
858858
859test "n_number_1eE2" {859test "json.test.n_number_1eE2" {
860 err(860 err(
861 \\[1eE2]861 \\[1eE2]
862 );862 );
863}863}
864864
865test "n_number_.-1" {865test "json.test.n_number_.-1" {
866 err(866 err(
867 \\[.-1]867 \\[.-1]
868 );868 );
869}869}
870870
871test "n_number_+1" {871test "json.test.n_number_+1" {
872 err(872 err(
873 \\[+1]873 \\[+1]
874 );874 );
875}875}
876876
877test "n_number_.2e-3" {877test "json.test.n_number_.2e-3" {
878 err(878 err(
879 \\[.2e-3]879 \\[.2e-3]
880 );880 );
881}881}
882882
883test "n_number_2.e-3" {883test "json.test.n_number_2.e-3" {
884 err(884 err(
885 \\[2.e-3]885 \\[2.e-3]
886 );886 );
887}887}
888888
889test "n_number_2.e+3" {889test "json.test.n_number_2.e+3" {
890 err(890 err(
891 \\[2.e+3]891 \\[2.e+3]
892 );892 );
893}893}
894894
895test "n_number_2.e3" {895test "json.test.n_number_2.e3" {
896 err(896 err(
897 \\[2.e3]897 \\[2.e3]
898 );898 );
899}899}
900900
901test "n_number_-2." {901test "json.test.n_number_-2." {
902 err(902 err(
903 \\[-2.]903 \\[-2.]
904 );904 );
905}905}
906906
907test "n_number_9.e+" {907test "json.test.n_number_9.e+" {
908 err(908 err(
909 \\[9.e+]909 \\[9.e+]
910 );910 );
911}911}
912912
913test "n_number_expression" {913test "json.test.n_number_expression" {
914 err(914 err(
915 \\[1+2]915 \\[1+2]
916 );916 );
917}917}
918918
919test "n_number_hex_1_digit" {919test "json.test.n_number_hex_1_digit" {
920 err(920 err(
921 \\[0x1]921 \\[0x1]
922 );922 );
923}923}
924924
925test "n_number_hex_2_digits" {925test "json.test.n_number_hex_2_digits" {
926 err(926 err(
927 \\[0x42]927 \\[0x42]
928 );928 );
929}929}
930930
931test "n_number_infinity" {931test "json.test.n_number_infinity" {
932 err(932 err(
933 \\[Infinity]933 \\[Infinity]
934 );934 );
935}935}
936936
937test "n_number_+Inf" {937test "json.test.n_number_+Inf" {
938 err(938 err(
939 \\[+Inf]939 \\[+Inf]
940 );940 );
941}941}
942942
943test "n_number_Inf" {943test "json.test.n_number_Inf" {
944 err(944 err(
945 \\[Inf]945 \\[Inf]
946 );946 );
947}947}
948948
949test "n_number_invalid+-" {949test "json.test.n_number_invalid+-" {
950 err(950 err(
951 \\[0e+-1]951 \\[0e+-1]
952 );952 );
953}953}
954954
955test "n_number_invalid-negative-real" {955test "json.test.n_number_invalid-negative-real" {
956 err(956 err(
957 \\[-123.123foo]957 \\[-123.123foo]
958 );958 );
959}959}
960960
961test "n_number_invalid-utf-8-in-bigger-int" {961test "json.test.n_number_invalid-utf-8-in-bigger-int" {
962 err(962 err(
963 \\[123å]963 \\[123å]
964 );964 );
965}965}
966966
967test "n_number_invalid-utf-8-in-exponent" {967test "json.test.n_number_invalid-utf-8-in-exponent" {
968 err(968 err(
969 \\[1e1å]969 \\[1e1å]
970 );970 );
971}971}
972972
973test "n_number_invalid-utf-8-in-int" {973test "json.test.n_number_invalid-utf-8-in-int" {
974 err(974 err(
975 \\[0å]975 \\[0å]
976 );976 );
977}977}
978978
979test "n_number_++" {979test "json.test.n_number_++" {
980 err(980 err(
981 \\[++1234]981 \\[++1234]
982 );982 );
983}983}
984984
985test "n_number_minus_infinity" {985test "json.test.n_number_minus_infinity" {
986 err(986 err(
987 \\[-Infinity]987 \\[-Infinity]
988 );988 );
989}989}
990990
991test "n_number_minus_sign_with_trailing_garbage" {991test "json.test.n_number_minus_sign_with_trailing_garbage" {
992 err(992 err(
993 \\[-foo]993 \\[-foo]
994 );994 );
995}995}
996996
997test "n_number_minus_space_1" {997test "json.test.n_number_minus_space_1" {
998 err(998 err(
999 \\[- 1]999 \\[- 1]
1000 );1000 );
1001}1001}
10021002
1003test "n_number_-NaN" {1003test "json.test.n_number_-NaN" {
1004 err(1004 err(
1005 \\[-NaN]1005 \\[-NaN]
1006 );1006 );
1007}1007}
10081008
1009test "n_number_NaN" {1009test "json.test.n_number_NaN" {
1010 err(1010 err(
1011 \\[NaN]1011 \\[NaN]
1012 );1012 );
1013}1013}
10141014
1015test "n_number_neg_int_starting_with_zero" {1015test "json.test.n_number_neg_int_starting_with_zero" {
1016 err(1016 err(
1017 \\[-012]1017 \\[-012]
1018 );1018 );
1019}1019}
10201020
1021test "n_number_neg_real_without_int_part" {1021test "json.test.n_number_neg_real_without_int_part" {
1022 err(1022 err(
1023 \\[-.123]1023 \\[-.123]
1024 );1024 );
1025}1025}
10261026
1027test "n_number_neg_with_garbage_at_end" {1027test "json.test.n_number_neg_with_garbage_at_end" {
1028 err(1028 err(
1029 \\[-1x]1029 \\[-1x]
1030 );1030 );
1031}1031}
10321032
1033test "n_number_real_garbage_after_e" {1033test "json.test.n_number_real_garbage_after_e" {
1034 err(1034 err(
1035 \\[1ea]1035 \\[1ea]
1036 );1036 );
1037}1037}
10381038
1039test "n_number_real_with_invalid_utf8_after_e" {1039test "json.test.n_number_real_with_invalid_utf8_after_e" {
1040 err(1040 err(
1041 \\[1eå]1041 \\[1eå]
1042 );1042 );
1043}1043}
10441044
1045test "n_number_real_without_fractional_part" {1045test "json.test.n_number_real_without_fractional_part" {
1046 err(1046 err(
1047 \\[1.]1047 \\[1.]
1048 );1048 );
1049}1049}
10501050
1051test "n_number_starting_with_dot" {1051test "json.test.n_number_starting_with_dot" {
1052 err(1052 err(
1053 \\[.123]1053 \\[.123]
1054 );1054 );
1055}1055}
10561056
1057test "n_number_U+FF11_fullwidth_digit_one" {1057test "json.test.n_number_U+FF11_fullwidth_digit_one" {
1058 err(1058 err(
1059 \\[1]1059 \\[1]
1060 );1060 );
1061}1061}
10621062
1063test "n_number_with_alpha_char" {1063test "json.test.n_number_with_alpha_char" {
1064 err(1064 err(
1065 \\[1.8011670033376514H-308]1065 \\[1.8011670033376514H-308]
1066 );1066 );
1067}1067}
10681068
1069test "n_number_with_alpha" {1069test "json.test.n_number_with_alpha" {
1070 err(1070 err(
1071 \\[1.2a-3]1071 \\[1.2a-3]
1072 );1072 );
1073}1073}
10741074
1075test "n_number_with_leading_zero" {1075test "json.test.n_number_with_leading_zero" {
1076 err(1076 err(
1077 \\[012]1077 \\[012]
1078 );1078 );
1079}1079}
10801080
1081test "n_object_bad_value" {1081test "json.test.n_object_bad_value" {
1082 err(1082 err(
1083 \\["x", truth]1083 \\["x", truth]
1084 );1084 );
1085}1085}
10861086
1087test "n_object_bracket_key" {1087test "json.test.n_object_bracket_key" {
1088 err(1088 err(
1089 \\{[: "x"}1089 \\{[: "x"}
1090 );1090 );
1091}1091}
10921092
1093test "n_object_comma_instead_of_colon" {1093test "json.test.n_object_comma_instead_of_colon" {
1094 err(1094 err(
1095 \\{"x", null}1095 \\{"x", null}
1096 );1096 );
1097}1097}
10981098
1099test "n_object_double_colon" {1099test "json.test.n_object_double_colon" {
1100 err(1100 err(
1101 \\{"x"::"b"}1101 \\{"x"::"b"}
1102 );1102 );
1103}1103}
11041104
1105test "n_object_emoji" {1105test "json.test.n_object_emoji" {
1106 err(1106 err(
1107 \\{🇨🇭}1107 \\{🇨🇭}
1108 );1108 );
1109}1109}
11101110
1111test "n_object_garbage_at_end" {1111test "json.test.n_object_garbage_at_end" {
1112 err(1112 err(
1113 \\{"a":"a" 123}1113 \\{"a":"a" 123}
1114 );1114 );
1115}1115}
11161116
1117test "n_object_key_with_single_quotes" {1117test "json.test.n_object_key_with_single_quotes" {
1118 err(1118 err(
1119 \\{key: 'value'}1119 \\{key: 'value'}
1120 );1120 );
1121}1121}
11221122
1123test "n_object_lone_continuation_byte_in_key_and_trailing_comma" {1123test "json.test.n_object_lone_continuation_byte_in_key_and_trailing_comma" {
1124 err(1124 err(
1125 \\{"¹":"0",}1125 \\{"¹":"0",}
1126 );1126 );
1127}1127}
11281128
1129test "n_object_missing_colon" {1129test "json.test.n_object_missing_colon" {
1130 err(1130 err(
1131 \\{"a" b}1131 \\{"a" b}
1132 );1132 );
1133}1133}
11341134
1135test "n_object_missing_key" {1135test "json.test.n_object_missing_key" {
1136 err(1136 err(
1137 \\{:"b"}1137 \\{:"b"}
1138 );1138 );
1139}1139}
11401140
1141test "n_object_missing_semicolon" {1141test "json.test.n_object_missing_semicolon" {
1142 err(1142 err(
1143 \\{"a" "b"}1143 \\{"a" "b"}
1144 );1144 );
1145}1145}
11461146
1147test "n_object_missing_value" {1147test "json.test.n_object_missing_value" {
1148 err(1148 err(
1149 \\{"a":1149 \\{"a":
1150 );1150 );
1151}1151}
11521152
1153test "n_object_no-colon" {1153test "json.test.n_object_no-colon" {
1154 err(1154 err(
1155 \\{"a"1155 \\{"a"
1156 );1156 );
1157}1157}
11581158
1159test "n_object_non_string_key_but_huge_number_instead" {1159test "json.test.n_object_non_string_key_but_huge_number_instead" {
1160 err(1160 err(
1161 \\{9999E9999:1}1161 \\{9999E9999:1}
1162 );1162 );
1163}1163}
11641164
1165test "n_object_non_string_key" {1165test "json.test.n_object_non_string_key" {
1166 err(1166 err(
1167 \\{1:1}1167 \\{1:1}
1168 );1168 );
1169}1169}
11701170
1171test "n_object_repeated_null_null" {1171test "json.test.n_object_repeated_null_null" {
1172 err(1172 err(
1173 \\{null:null,null:null}1173 \\{null:null,null:null}
1174 );1174 );
1175}1175}
11761176
1177test "n_object_several_trailing_commas" {1177test "json.test.n_object_several_trailing_commas" {
1178 err(1178 err(
1179 \\{"id":0,,,,,}1179 \\{"id":0,,,,,}
1180 );1180 );
1181}1181}
11821182
1183test "n_object_single_quote" {1183test "json.test.n_object_single_quote" {
1184 err(1184 err(
1185 \\{'a':0}1185 \\{'a':0}
1186 );1186 );
1187}1187}
11881188
1189test "n_object_trailing_comma" {1189test "json.test.n_object_trailing_comma" {
1190 err(1190 err(
1191 \\{"id":0,}1191 \\{"id":0,}
1192 );1192 );
1193}1193}
11941194
1195test "n_object_trailing_comment" {1195test "json.test.n_object_trailing_comment" {
1196 err(1196 err(
1197 \\{"a":"b"}/**/1197 \\{"a":"b"}/**/
1198 );1198 );
1199}1199}
12001200
1201test "n_object_trailing_comment_open" {1201test "json.test.n_object_trailing_comment_open" {
1202 err(1202 err(
1203 \\{"a":"b"}/**//1203 \\{"a":"b"}/**//
1204 );1204 );
1205}1205}
12061206
1207test "n_object_trailing_comment_slash_open_incomplete" {1207test "json.test.n_object_trailing_comment_slash_open_incomplete" {
1208 err(1208 err(
1209 \\{"a":"b"}/1209 \\{"a":"b"}/
1210 );1210 );
1211}1211}
12121212
1213test "n_object_trailing_comment_slash_open" {1213test "json.test.n_object_trailing_comment_slash_open" {
1214 err(1214 err(
1215 \\{"a":"b"}//1215 \\{"a":"b"}//
1216 );1216 );
1217}1217}
12181218
1219test "n_object_two_commas_in_a_row" {1219test "json.test.n_object_two_commas_in_a_row" {
1220 err(1220 err(
1221 \\{"a":"b",,"c":"d"}1221 \\{"a":"b",,"c":"d"}
1222 );1222 );
1223}1223}
12241224
1225test "n_object_unquoted_key" {1225test "json.test.n_object_unquoted_key" {
1226 err(1226 err(
1227 \\{a: "b"}1227 \\{a: "b"}
1228 );1228 );
1229}1229}
12301230
1231test "n_object_unterminated-value" {1231test "json.test.n_object_unterminated-value" {
1232 err(1232 err(
1233 \\{"a":"a1233 \\{"a":"a
1234 );1234 );
1235}1235}
12361236
1237test "n_object_with_single_string" {1237test "json.test.n_object_with_single_string" {
1238 err(1238 err(
1239 \\{ "foo" : "bar", "a" }1239 \\{ "foo" : "bar", "a" }
1240 );1240 );
1241}1241}
12421242
1243test "n_object_with_trailing_garbage" {1243test "json.test.n_object_with_trailing_garbage" {
1244 err(1244 err(
1245 \\{"a":"b"}#1245 \\{"a":"b"}#
1246 );1246 );
1247}1247}
12481248
1249test "n_single_space" {1249test "json.test.n_single_space" {
1250 err(" ");1250 err(" ");
1251}1251}
12521252
1253test "n_string_1_surrogate_then_escape" {1253test "json.test.n_string_1_surrogate_then_escape" {
1254 err(1254 err(
1255 \\["\uD800\"]1255 \\["\uD800\"]
1256 );1256 );
1257}1257}
12581258
1259test "n_string_1_surrogate_then_escape_u1" {1259test "json.test.n_string_1_surrogate_then_escape_u1" {
1260 err(1260 err(
1261 \\["\uD800\u1"]1261 \\["\uD800\u1"]
1262 );1262 );
1263}1263}
12641264
1265test "n_string_1_surrogate_then_escape_u1x" {1265test "json.test.n_string_1_surrogate_then_escape_u1x" {
1266 err(1266 err(
1267 \\["\uD800\u1x"]1267 \\["\uD800\u1x"]
1268 );1268 );
1269}1269}
12701270
1271test "n_string_1_surrogate_then_escape_u" {1271test "json.test.n_string_1_surrogate_then_escape_u" {
1272 err(1272 err(
1273 \\["\uD800\u"]1273 \\["\uD800\u"]
1274 );1274 );
1275}1275}
12761276
1277test "n_string_accentuated_char_no_quotes" {1277test "json.test.n_string_accentuated_char_no_quotes" {
1278 err(1278 err(
1279 \\[é]1279 \\[é]
1280 );1280 );
1281}1281}
12821282
1283test "n_string_backslash_00" {1283test "json.test.n_string_backslash_00" {
1284 err("[\"\x00\"]");1284 err("[\"\x00\"]");
1285}1285}
12861286
1287test "n_string_escaped_backslash_bad" {1287test "json.test.n_string_escaped_backslash_bad" {
1288 err(1288 err(
1289 \\["\\\"]1289 \\["\\\"]
1290 );1290 );
1291}1291}
12921292
1293test "n_string_escaped_ctrl_char_tab" {1293test "json.test.n_string_escaped_ctrl_char_tab" {
1294 err("\x5b\x22\x5c\x09\x22\x5d");1294 err("\x5b\x22\x5c\x09\x22\x5d");
1295}1295}
12961296
1297test "n_string_escaped_emoji" {1297test "json.test.n_string_escaped_emoji" {
1298 err("[\"\x5c\xc3\xb0\xc2\x9f\xc2\x8c\xc2\x80\"]");1298 err("[\"\x5c\xc3\xb0\xc2\x9f\xc2\x8c\xc2\x80\"]");
1299}1299}
13001300
1301test "n_string_escape_x" {1301test "json.test.n_string_escape_x" {
1302 err(1302 err(
1303 \\["\x00"]1303 \\["\x00"]
1304 );1304 );
1305}1305}
13061306
1307test "n_string_incomplete_escaped_character" {1307test "json.test.n_string_incomplete_escaped_character" {
1308 err(1308 err(
1309 \\["\u00A"]1309 \\["\u00A"]
1310 );1310 );
1311}1311}
13121312
1313test "n_string_incomplete_escape" {1313test "json.test.n_string_incomplete_escape" {
1314 err(1314 err(
1315 \\["\"]1315 \\["\"]
1316 );1316 );
1317}1317}
13181318
1319test "n_string_incomplete_surrogate_escape_invalid" {1319test "json.test.n_string_incomplete_surrogate_escape_invalid" {
1320 err(1320 err(
1321 \\["\uD800\uD800\x"]1321 \\["\uD800\uD800\x"]
1322 );1322 );
1323}1323}
13241324
1325test "n_string_incomplete_surrogate" {1325test "json.test.n_string_incomplete_surrogate" {
1326 err(1326 err(
1327 \\["\uD834\uDd"]1327 \\["\uD834\uDd"]
1328 );1328 );
1329}1329}
13301330
1331test "n_string_invalid_backslash_esc" {1331test "json.test.n_string_invalid_backslash_esc" {
1332 err(1332 err(
1333 \\["\a"]1333 \\["\a"]
1334 );1334 );
1335}1335}
13361336
1337test "n_string_invalid_unicode_escape" {1337test "json.test.n_string_invalid_unicode_escape" {
1338 err(1338 err(
1339 \\["\uqqqq"]1339 \\["\uqqqq"]
1340 );1340 );
1341}1341}
13421342
1343test "n_string_invalid_utf8_after_escape" {1343test "json.test.n_string_invalid_utf8_after_escape" {
1344 err("[\"\\\x75\xc3\xa5\"]");1344 err("[\"\\\x75\xc3\xa5\"]");
1345}1345}
13461346
1347test "n_string_invalid-utf-8-in-escape" {1347test "json.test.n_string_invalid-utf-8-in-escape" {
1348 err(1348 err(
1349 \\["\uå"]1349 \\["\uå"]
1350 );1350 );
1351}1351}
13521352
1353test "n_string_leading_uescaped_thinspace" {1353test "json.test.n_string_leading_uescaped_thinspace" {
1354 err(1354 err(
1355 \\[\u0020"asd"]1355 \\[\u0020"asd"]
1356 );1356 );
1357}1357}
13581358
1359test "n_string_no_quotes_with_bad_escape" {1359test "json.test.n_string_no_quotes_with_bad_escape" {
1360 err(1360 err(
1361 \\[\n]1361 \\[\n]
1362 );1362 );
1363}1363}
13641364
1365test "n_string_single_doublequote" {1365test "json.test.n_string_single_doublequote" {
1366 err(1366 err(
1367 \\"1367 \\"
1368 );1368 );
1369}1369}
13701370
1371test "n_string_single_quote" {1371test "json.test.n_string_single_quote" {
1372 err(1372 err(
1373 \\['single quote']1373 \\['single quote']
1374 );1374 );
1375}1375}
13761376
1377test "n_string_single_string_no_double_quotes" {1377test "json.test.n_string_single_string_no_double_quotes" {
1378 err(1378 err(
1379 \\abc1379 \\abc
1380 );1380 );
1381}1381}
13821382
1383test "n_string_start_escape_unclosed" {1383test "json.test.n_string_start_escape_unclosed" {
1384 err(1384 err(
1385 \\["\1385 \\["\
1386 );1386 );
1387}1387}
13881388
1389test "n_string_unescaped_crtl_char" {1389test "json.test.n_string_unescaped_crtl_char" {
1390 err("[\"a\x00a\"]");1390 err("[\"a\x00a\"]");
1391}1391}
13921392
1393test "n_string_unescaped_newline" {1393test "json.test.n_string_unescaped_newline" {
1394 err(1394 err(
1395 \\["new1395 \\["new
1396 \\line"]1396 \\line"]
1397 );1397 );
1398}1398}
13991399
1400test "n_string_unescaped_tab" {1400test "json.test.n_string_unescaped_tab" {
1401 err("[\"\t\"]");1401 err("[\"\t\"]");
1402}1402}
14031403
1404test "n_string_unicode_CapitalU" {1404test "json.test.n_string_unicode_CapitalU" {
1405 err(1405 err(
1406 \\"\UA66D"1406 \\"\UA66D"
1407 );1407 );
1408}1408}
14091409
1410test "n_string_with_trailing_garbage" {1410test "json.test.n_string_with_trailing_garbage" {
1411 err(1411 err(
1412 \\""x1412 \\""x
1413 );1413 );
1414}1414}
14151415
1416test "n_structure_100000_opening_arrays" {1416test "json.test.n_structure_100000_opening_arrays" {
1417 err("[" ** 100000);1417 err("[" ** 100000);
1418}1418}
14191419
1420test "n_structure_angle_bracket_." {1420test "json.test.n_structure_angle_bracket_." {
1421 err(1421 err(
1422 \\<.>1422 \\<.>
1423 );1423 );
1424}1424}
14251425
1426test "n_structure_angle_bracket_null" {1426test "json.test.n_structure_angle_bracket_null" {
1427 err(1427 err(
1428 \\[<null>]1428 \\[<null>]
1429 );1429 );
1430}1430}
14311431
1432test "n_structure_array_trailing_garbage" {1432test "json.test.n_structure_array_trailing_garbage" {
1433 err(1433 err(
1434 \\[1]x1434 \\[1]x
1435 );1435 );
1436}1436}
14371437
1438test "n_structure_array_with_extra_array_close" {1438test "json.test.n_structure_array_with_extra_array_close" {
1439 err(1439 err(
1440 \\[1]]1440 \\[1]]
1441 );1441 );
1442}1442}
14431443
1444test "n_structure_array_with_unclosed_string" {1444test "json.test.n_structure_array_with_unclosed_string" {
1445 err(1445 err(
1446 \\["asd]1446 \\["asd]
1447 );1447 );
1448}1448}
14491449
1450test "n_structure_ascii-unicode-identifier" {1450test "json.test.n_structure_ascii-unicode-identifier" {
1451 err(1451 err(
1452 \\aå1452 \\aå
1453 );1453 );
1454}1454}
14551455
1456test "n_structure_capitalized_True" {1456test "json.test.n_structure_capitalized_True" {
1457 err(1457 err(
1458 \\[True]1458 \\[True]
1459 );1459 );
1460}1460}
14611461
1462test "n_structure_close_unopened_array" {1462test "json.test.n_structure_close_unopened_array" {
1463 err(1463 err(
1464 \\1]1464 \\1]
1465 );1465 );
1466}1466}
14671467
1468test "n_structure_comma_instead_of_closing_brace" {1468test "json.test.n_structure_comma_instead_of_closing_brace" {
1469 err(1469 err(
1470 \\{"x": true,1470 \\{"x": true,
1471 );1471 );
1472}1472}
14731473
1474test "n_structure_double_array" {1474test "json.test.n_structure_double_array" {
1475 err(1475 err(
1476 \\[][]1476 \\[][]
1477 );1477 );
1478}1478}
14791479
1480test "n_structure_end_array" {1480test "json.test.n_structure_end_array" {
1481 err(1481 err(
1482 \\]1482 \\]
1483 );1483 );
1484}1484}
14851485
1486test "n_structure_incomplete_UTF8_BOM" {1486test "json.test.n_structure_incomplete_UTF8_BOM" {
1487 err(1487 err(
1488 \\ï»{}1488 \\ï»{}
1489 );1489 );
1490}1490}
14911491
1492test "n_structure_lone-invalid-utf-8" {1492test "json.test.n_structure_lone-invalid-utf-8" {
1493 err(1493 err(
1494 \\å1494 \\å
1495 );1495 );
1496}1496}
14971497
1498test "n_structure_lone-open-bracket" {1498test "json.test.n_structure_lone-open-bracket" {
1499 err(1499 err(
1500 \\[1500 \\[
1501 );1501 );
1502}1502}
15031503
1504test "n_structure_no_data" {1504test "json.test.n_structure_no_data" {
1505 err(1505 err(
1506 \\1506 \\
1507 );1507 );
1508}1508}
15091509
1510test "n_structure_null-byte-outside-string" {1510test "json.test.n_structure_null-byte-outside-string" {
1511 err("[\x00]");1511 err("[\x00]");
1512}1512}
15131513
1514test "n_structure_number_with_trailing_garbage" {1514test "json.test.n_structure_number_with_trailing_garbage" {
1515 err(1515 err(
1516 \\2@1516 \\2@
1517 );1517 );
1518}1518}
15191519
1520test "n_structure_object_followed_by_closing_object" {1520test "json.test.n_structure_object_followed_by_closing_object" {
1521 err(1521 err(
1522 \\{}}1522 \\{}}
1523 );1523 );
1524}1524}
15251525
1526test "n_structure_object_unclosed_no_value" {1526test "json.test.n_structure_object_unclosed_no_value" {
1527 err(1527 err(
1528 \\{"":1528 \\{"":
1529 );1529 );
1530}1530}
15311531
1532test "n_structure_object_with_comment" {1532test "json.test.n_structure_object_with_comment" {
1533 err(1533 err(
1534 \\{"a":/*comment*/"b"}1534 \\{"a":/*comment*/"b"}
1535 );1535 );
1536}1536}
15371537
1538test "n_structure_object_with_trailing_garbage" {1538test "json.test.n_structure_object_with_trailing_garbage" {
1539 err(1539 err(
1540 \\{"a": true} "x"1540 \\{"a": true} "x"
1541 );1541 );
1542}1542}
15431543
1544test "n_structure_open_array_apostrophe" {1544test "json.test.n_structure_open_array_apostrophe" {
1545 err(1545 err(
1546 \\['1546 \\['
1547 );1547 );
1548}1548}
15491549
1550test "n_structure_open_array_comma" {1550test "json.test.n_structure_open_array_comma" {
1551 err(1551 err(
1552 \\[,1552 \\[,
1553 );1553 );
1554}1554}
15551555
1556test "n_structure_open_array_object" {1556test "json.test.n_structure_open_array_object" {
1557 err("[{\"\":" ** 50000);1557 err("[{\"\":" ** 50000);
1558}1558}
15591559
1560test "n_structure_open_array_open_object" {1560test "json.test.n_structure_open_array_open_object" {
1561 err(1561 err(
1562 \\[{1562 \\[{
1563 );1563 );
1564}1564}
15651565
1566test "n_structure_open_array_open_string" {1566test "json.test.n_structure_open_array_open_string" {
1567 err(1567 err(
1568 \\["a1568 \\["a
1569 );1569 );
1570}1570}
15711571
1572test "n_structure_open_array_string" {1572test "json.test.n_structure_open_array_string" {
1573 err(1573 err(
1574 \\["a"1574 \\["a"
1575 );1575 );
1576}1576}
15771577
1578test "n_structure_open_object_close_array" {1578test "json.test.n_structure_open_object_close_array" {
1579 err(1579 err(
1580 \\{]1580 \\{]
1581 );1581 );
1582}1582}
15831583
1584test "n_structure_open_object_comma" {1584test "json.test.n_structure_open_object_comma" {
1585 err(1585 err(
1586 \\{,1586 \\{,
1587 );1587 );
1588}1588}
15891589
1590test "n_structure_open_object" {1590test "json.test.n_structure_open_object" {
1591 err(1591 err(
1592 \\{1592 \\{
1593 );1593 );
1594}1594}
15951595
1596test "n_structure_open_object_open_array" {1596test "json.test.n_structure_open_object_open_array" {
1597 err(1597 err(
1598 \\{[1598 \\{[
1599 );1599 );
1600}1600}
16011601
1602test "n_structure_open_object_open_string" {1602test "json.test.n_structure_open_object_open_string" {
1603 err(1603 err(
1604 \\{"a1604 \\{"a
1605 );1605 );
1606}1606}
16071607
1608test "n_structure_open_object_string_with_apostrophes" {1608test "json.test.n_structure_open_object_string_with_apostrophes" {
1609 err(1609 err(
1610 \\{'a'1610 \\{'a'
1611 );1611 );
1612}1612}
16131613
1614test "n_structure_open_open" {1614test "json.test.n_structure_open_open" {
1615 err(1615 err(
1616 \\["\{["\{["\{["\{1616 \\["\{["\{["\{["\{
1617 );1617 );
1618}1618}
16191619
1620test "n_structure_single_eacute" {1620test "json.test.n_structure_single_eacute" {
1621 err(1621 err(
1622 \\é1622 \\é
1623 );1623 );
1624}1624}
16251625
1626test "n_structure_single_star" {1626test "json.test.n_structure_single_star" {
1627 err(1627 err(
1628 \\*1628 \\*
1629 );1629 );
1630}1630}
16311631
1632test "n_structure_trailing_#" {1632test "json.test.n_structure_trailing_#" {
1633 err(1633 err(
1634 \\{"a":"b"}#{}1634 \\{"a":"b"}#{}
1635 );1635 );
1636}1636}
16371637
1638test "n_structure_U+2060_word_joined" {1638test "json.test.n_structure_U+2060_word_joined" {
1639 err(1639 err(
1640 \\[⁠]1640 \\[⁠]
1641 );1641 );
1642}1642}
16431643
1644test "n_structure_uescaped_LF_before_string" {1644test "json.test.n_structure_uescaped_LF_before_string" {
1645 err(1645 err(
1646 \\[\u000A""]1646 \\[\u000A""]
1647 );1647 );
1648}1648}
16491649
1650test "n_structure_unclosed_array" {1650test "json.test.n_structure_unclosed_array" {
1651 err(1651 err(
1652 \\[11652 \\[1
1653 );1653 );
1654}1654}
16551655
1656test "n_structure_unclosed_array_partial_null" {1656test "json.test.n_structure_unclosed_array_partial_null" {
1657 err(1657 err(
1658 \\[ false, nul1658 \\[ false, nul
1659 );1659 );
1660}1660}
16611661
1662test "n_structure_unclosed_array_unfinished_false" {1662test "json.test.n_structure_unclosed_array_unfinished_false" {
1663 err(1663 err(
1664 \\[ true, fals1664 \\[ true, fals
1665 );1665 );
1666}1666}
16671667
1668test "n_structure_unclosed_array_unfinished_true" {1668test "json.test.n_structure_unclosed_array_unfinished_true" {
1669 err(1669 err(
1670 \\[ false, tru1670 \\[ false, tru
1671 );1671 );
1672}1672}
16731673
1674test "n_structure_unclosed_object" {1674test "json.test.n_structure_unclosed_object" {
1675 err(1675 err(
1676 \\{"asd":"asd"1676 \\{"asd":"asd"
1677 );1677 );
1678}1678}
16791679
1680test "n_structure_unicode-identifier" {1680test "json.test.n_structure_unicode-identifier" {
1681 err(1681 err(
1682 \\Ã¥1682 \\Ã¥
1683 );1683 );
1684}1684}
16851685
1686test "n_structure_UTF8_BOM_no_data" {1686test "json.test.n_structure_UTF8_BOM_no_data" {
1687 err(1687 err(
1688 \\1688 \\
1689 );1689 );
1690}1690}
16911691
1692test "n_structure_whitespace_formfeed" {1692test "json.test.n_structure_whitespace_formfeed" {
1693 err("[\x0c]");1693 err("[\x0c]");
1694}1694}
16951695
1696test "n_structure_whitespace_U+2060_word_joiner" {1696test "json.test.n_structure_whitespace_U+2060_word_joiner" {
1697 err(1697 err(
1698 \\[⁠]1698 \\[⁠]
1699 );1699 );
...@@ -1701,203 +1701,203 @@ test "n_structure_whitespace_U+2060_word_joiner" {...@@ -1701,203 +1701,203 @@ test "n_structure_whitespace_U+2060_word_joiner" {
17011701
1702////////////////////////////////////////////////////////////////////////////////////////////////////1702////////////////////////////////////////////////////////////////////////////////////////////////////
17031703
1704test "i_number_double_huge_neg_exp" {1704test "json.test.i_number_double_huge_neg_exp" {
1705 any(1705 any(
1706 \\[123.456e-789]1706 \\[123.456e-789]
1707 );1707 );
1708}1708}
17091709
1710test "i_number_huge_exp" {1710test "json.test.i_number_huge_exp" {
1711 any(1711 any(
1712 \\[0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006]1712 \\[0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006]
1713 );1713 );
1714}1714}
17151715
1716test "i_number_neg_int_huge_exp" {1716test "json.test.i_number_neg_int_huge_exp" {
1717 any(1717 any(
1718 \\[-1e+9999]1718 \\[-1e+9999]
1719 );1719 );
1720}1720}
17211721
1722test "i_number_pos_double_huge_exp" {1722test "json.test.i_number_pos_double_huge_exp" {
1723 any(1723 any(
1724 \\[1.5e+9999]1724 \\[1.5e+9999]
1725 );1725 );
1726}1726}
17271727
1728test "i_number_real_neg_overflow" {1728test "json.test.i_number_real_neg_overflow" {
1729 any(1729 any(
1730 \\[-123123e100000]1730 \\[-123123e100000]
1731 );1731 );
1732}1732}
17331733
1734test "i_number_real_pos_overflow" {1734test "json.test.i_number_real_pos_overflow" {
1735 any(1735 any(
1736 \\[123123e100000]1736 \\[123123e100000]
1737 );1737 );
1738}1738}
17391739
1740test "i_number_real_underflow" {1740test "json.test.i_number_real_underflow" {
1741 any(1741 any(
1742 \\[123e-10000000]1742 \\[123e-10000000]
1743 );1743 );
1744}1744}
17451745
1746test "i_number_too_big_neg_int" {1746test "json.test.i_number_too_big_neg_int" {
1747 any(1747 any(
1748 \\[-123123123123123123123123123123]1748 \\[-123123123123123123123123123123]
1749 );1749 );
1750}1750}
17511751
1752test "i_number_too_big_pos_int" {1752test "json.test.i_number_too_big_pos_int" {
1753 any(1753 any(
1754 \\[100000000000000000000]1754 \\[100000000000000000000]
1755 );1755 );
1756}1756}
17571757
1758test "i_number_very_big_negative_int" {1758test "json.test.i_number_very_big_negative_int" {
1759 any(1759 any(
1760 \\[-237462374673276894279832749832423479823246327846]1760 \\[-237462374673276894279832749832423479823246327846]
1761 );1761 );
1762}1762}
17631763
1764test "i_object_key_lone_2nd_surrogate" {1764test "json.test.i_object_key_lone_2nd_surrogate" {
1765 any(1765 any(
1766 \\{"\uDFAA":0}1766 \\{"\uDFAA":0}
1767 );1767 );
1768}1768}
17691769
1770test "i_string_1st_surrogate_but_2nd_missing" {1770test "json.test.i_string_1st_surrogate_but_2nd_missing" {
1771 any(1771 any(
1772 \\["\uDADA"]1772 \\["\uDADA"]
1773 );1773 );
1774}1774}
17751775
1776test "i_string_1st_valid_surrogate_2nd_invalid" {1776test "json.test.i_string_1st_valid_surrogate_2nd_invalid" {
1777 any(1777 any(
1778 \\["\uD888\u1234"]1778 \\["\uD888\u1234"]
1779 );1779 );
1780}1780}
17811781
1782test "i_string_incomplete_surrogate_and_escape_valid" {1782test "json.test.i_string_incomplete_surrogate_and_escape_valid" {
1783 any(1783 any(
1784 \\["\uD800\n"]1784 \\["\uD800\n"]
1785 );1785 );
1786}1786}
17871787
1788test "i_string_incomplete_surrogate_pair" {1788test "json.test.i_string_incomplete_surrogate_pair" {
1789 any(1789 any(
1790 \\["\uDd1ea"]1790 \\["\uDd1ea"]
1791 );1791 );
1792}1792}
17931793
1794test "i_string_incomplete_surrogates_escape_valid" {1794test "json.test.i_string_incomplete_surrogates_escape_valid" {
1795 any(1795 any(
1796 \\["\uD800\uD800\n"]1796 \\["\uD800\uD800\n"]
1797 );1797 );
1798}1798}
17991799
1800test "i_string_invalid_lonely_surrogate" {1800test "json.test.i_string_invalid_lonely_surrogate" {
1801 any(1801 any(
1802 \\["\ud800"]1802 \\["\ud800"]
1803 );1803 );
1804}1804}
18051805
1806test "i_string_invalid_surrogate" {1806test "json.test.i_string_invalid_surrogate" {
1807 any(1807 any(
1808 \\["\ud800abc"]1808 \\["\ud800abc"]
1809 );1809 );
1810}1810}
18111811
1812test "i_string_invalid_utf-8" {1812test "json.test.i_string_invalid_utf-8" {
1813 any(1813 any(
1814 \\["ÿ"]1814 \\["ÿ"]
1815 );1815 );
1816}1816}
18171817
1818test "i_string_inverted_surrogates_U+1D11E" {1818test "json.test.i_string_inverted_surrogates_U+1D11E" {
1819 any(1819 any(
1820 \\["\uDd1e\uD834"]1820 \\["\uDd1e\uD834"]
1821 );1821 );
1822}1822}
18231823
1824test "i_string_iso_latin_1" {1824test "json.test.i_string_iso_latin_1" {
1825 any(1825 any(
1826 \\["é"]1826 \\["é"]
1827 );1827 );
1828}1828}
18291829
1830test "i_string_lone_second_surrogate" {1830test "json.test.i_string_lone_second_surrogate" {
1831 any(1831 any(
1832 \\["\uDFAA"]1832 \\["\uDFAA"]
1833 );1833 );
1834}1834}
18351835
1836test "i_string_lone_utf8_continuation_byte" {1836test "json.test.i_string_lone_utf8_continuation_byte" {
1837 any(1837 any(
1838 \\[""]1838 \\[""]
1839 );1839 );
1840}1840}
18411841
1842test "i_string_not_in_unicode_range" {1842test "json.test.i_string_not_in_unicode_range" {
1843 any(1843 any(
1844 \\["ô¿¿¿"]1844 \\["ô¿¿¿"]
1845 );1845 );
1846}1846}
18471847
1848test "i_string_overlong_sequence_2_bytes" {1848test "json.test.i_string_overlong_sequence_2_bytes" {
1849 any(1849 any(
1850 \\["À¯"]1850 \\["À¯"]
1851 );1851 );
1852}1852}
18531853
1854test "i_string_overlong_sequence_6_bytes" {1854test "json.test.i_string_overlong_sequence_6_bytes" {
1855 any(1855 any(
1856 \\["üƒ¿¿¿¿"]1856 \\["üƒ¿¿¿¿"]
1857 );1857 );
1858}1858}
18591859
1860test "i_string_overlong_sequence_6_bytes_null" {1860test "json.test.i_string_overlong_sequence_6_bytes_null" {
1861 any(1861 any(
1862 \\["ü€€€€€"]1862 \\["ü€€€€€"]
1863 );1863 );
1864}1864}
18651865
1866test "i_string_truncated-utf-8" {1866test "json.test.i_string_truncated-utf-8" {
1867 any(1867 any(
1868 \\["àÿ"]1868 \\["àÿ"]
1869 );1869 );
1870}1870}
18711871
1872test "i_string_utf16BE_no_BOM" {1872test "json.test.i_string_utf16BE_no_BOM" {
1873 any("\x00\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d");1873 any("\x00\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d");
1874}1874}
18751875
1876test "i_string_utf16LE_no_BOM" {1876test "json.test.i_string_utf16LE_no_BOM" {
1877 any("\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00");1877 any("\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00");
1878}1878}
18791879
1880test "i_string_UTF-16LE_with_BOM" {1880test "json.test.i_string_UTF-16LE_with_BOM" {
1881 any("\xc3\xbf\xc3\xbe\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00");1881 any("\xc3\xbf\xc3\xbe\x5b\x00\x22\x00\xc3\xa9\x00\x22\x00\x5d\x00");
1882}1882}
18831883
1884test "i_string_UTF-8_invalid_sequence" {1884test "json.test.i_string_UTF-8_invalid_sequence" {
1885 any(1885 any(
1886 \\["日шú"]1886 \\["日шú"]
1887 );1887 );
1888}1888}
18891889
1890test "i_string_UTF8_surrogate_U+D800" {1890test "json.test.i_string_UTF8_surrogate_U+D800" {
1891 any(1891 any(
1892 \\["í €"]1892 \\["í €"]
1893 );1893 );
1894}1894}
18951895
1896test "i_structure_500_nested_arrays" {1896test "json.test.i_structure_500_nested_arrays" {
1897 any(("[" ** 500) ++ ("]" ** 500));1897 any(("[" ** 500) ++ ("]" ** 500));
1898}1898}
18991899
1900test "i_structure_UTF-8_BOM_empty_object" {1900test "json.test.i_structure_UTF-8_BOM_empty_object" {
1901 any(1901 any(
1902 \\{}1902 \\{}
1903 );1903 );
std/linked_list.zig+96
...@@ -82,6 +82,28 @@ pub fn LinkedList(comptime T: type) type {...@@ -82,6 +82,28 @@ pub fn LinkedList(comptime T: type) type {
82 list.len += 1;82 list.len += 1;
83 }83 }
8484
85 /// Concatenate list2 onto the end of list1, removing all entries from the former.
86 ///
87 /// Arguments:
88 /// list1: the list to concatenate onto
89 /// list2: the list to be concatenated
90 pub fn concatByMoving(list1: *Self, list2: *Self) void {
91 const l2_first = list2.first orelse return;
92 if (list1.last) |l1_last| {
93 l1_last.next = list2.first;
94 l2_first.prev = list1.last;
95 list1.len += list2.len;
96 } else {
97 // list1 was empty
98 list1.first = list2.first;
99 list1.len = list2.len;
100 }
101 list1.last = list2.last;
102 list2.first = null;
103 list2.last = null;
104 list2.len = 0;
105 }
106
85 /// Insert a new node at the end of the list.107 /// Insert a new node at the end of the list.
86 ///108 ///
87 /// Arguments:109 /// Arguments:
...@@ -247,3 +269,77 @@ test "basic linked list test" {...@@ -247,3 +269,77 @@ test "basic linked list test" {
247 assert(list.last.?.data == 4);269 assert(list.last.?.data == 4);
248 assert(list.len == 2);270 assert(list.len == 2);
249}271}
272
273test "linked list concatenation" {
274 const allocator = debug.global_allocator;
275 var list1 = LinkedList(u32).init();
276 var list2 = LinkedList(u32).init();
277
278 var one = try list1.createNode(1, allocator);
279 defer list1.destroyNode(one, allocator);
280 var two = try list1.createNode(2, allocator);
281 defer list1.destroyNode(two, allocator);
282 var three = try list1.createNode(3, allocator);
283 defer list1.destroyNode(three, allocator);
284 var four = try list1.createNode(4, allocator);
285 defer list1.destroyNode(four, allocator);
286 var five = try list1.createNode(5, allocator);
287 defer list1.destroyNode(five, allocator);
288
289 list1.append(one);
290 list1.append(two);
291 list2.append(three);
292 list2.append(four);
293 list2.append(five);
294
295 list1.concatByMoving(&list2);
296
297 assert(list1.last == five);
298 assert(list1.len == 5);
299 assert(list2.first == null);
300 assert(list2.last == null);
301 assert(list2.len == 0);
302
303 // Traverse forwards.
304 {
305 var it = list1.first;
306 var index: u32 = 1;
307 while (it) |node| : (it = node.next) {
308 assert(node.data == index);
309 index += 1;
310 }
311 }
312
313 // Traverse backwards.
314 {
315 var it = list1.last;
316 var index: u32 = 1;
317 while (it) |node| : (it = node.prev) {
318 assert(node.data == (6 - index));
319 index += 1;
320 }
321 }
322
323 // Swap them back, this verifies that concating to an empty list works.
324 list2.concatByMoving(&list1);
325
326 // Traverse forwards.
327 {
328 var it = list2.first;
329 var index: u32 = 1;
330 while (it) |node| : (it = node.next) {
331 assert(node.data == index);
332 index += 1;
333 }
334 }
335
336 // Traverse backwards.
337 {
338 var it = list2.last;
339 var index: u32 = 1;
340 while (it) |node| : (it = node.prev) {
341 assert(node.data == (6 - index));
342 index += 1;
343 }
344 }
345}
std/math/index.zig+70
...@@ -6,6 +6,13 @@ const assert = std.debug.assert;...@@ -6,6 +6,13 @@ const assert = std.debug.assert;
6pub const e = 2.71828182845904523536028747135266249775724709369995;6pub const e = 2.71828182845904523536028747135266249775724709369995;
7pub const pi = 3.14159265358979323846264338327950288419716939937510;7pub const pi = 3.14159265358979323846264338327950288419716939937510;
88
9// From a small c++ [program using boost float128](https://github.com/winksaville/cpp_boost_float128)
10pub const f128_true_min = @bitCast(f128, u128(0x00000000000000000000000000000001));
11pub const f128_min = @bitCast(f128, u128(0x00010000000000000000000000000000));
12pub const f128_max = @bitCast(f128, u128(0x7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFF));
13pub const f128_epsilon = @bitCast(f128, u128(0x3F8F0000000000000000000000000000));
14pub const f128_toint = 1.0 / f128_epsilon;
15
9// float.h details16// float.h details
10pub const f64_true_min = 4.94065645841246544177e-324;17pub const f64_true_min = 4.94065645841246544177e-324;
11pub const f64_min = 2.2250738585072014e-308;18pub const f64_min = 2.2250738585072014e-308;
...@@ -365,6 +372,69 @@ pub fn Log2Int(comptime T: type) type {...@@ -365,6 +372,69 @@ pub fn Log2Int(comptime T: type) type {
365 return @IntType(false, count);372 return @IntType(false, count);
366}373}
367374
375pub 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
391test "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
368test "math overflow functions" {438test "math overflow functions" {
369 testOverflow();439 testOverflow();
370 comptime testOverflow();440 comptime testOverflow();
std/mem.zig+277-148
...@@ -410,12 +410,8 @@ test "mem.indexOf" {...@@ -410,12 +410,8 @@ test "mem.indexOf" {
410/// Reads an integer from memory with size equal to bytes.len.410/// Reads an integer from memory with size equal to bytes.len.
411/// T specifies the return type, which must be large enough to store411/// T specifies the return type, which must be large enough to store
412/// the result.412/// the result.
413/// See also ::readIntBE or ::readIntLE.413pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: builtin.Endian) ReturnType {
414pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T {414 var result: ReturnType = 0;
415 if (T.bit_count == 8) {
416 return bytes[0];
417 }
418 var result: T = 0;
419 switch (endian) {415 switch (endian) {
420 builtin.Endian.Big => {416 builtin.Endian.Big => {
421 for (bytes) |b| {417 for (bytes) |b| {
...@@ -423,172 +419,270 @@ pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T {...@@ -423,172 +419,270 @@ pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T {
423 }419 }
424 },420 },
425 builtin.Endian.Little => {421 builtin.Endian.Little => {
426 const ShiftType = math.Log2Int(T);422 const ShiftType = math.Log2Int(ReturnType);
427 for (bytes) |b, index| {423 for (bytes) |b, index| {
428 result = result | (T(b) << @intCast(ShiftType, index * 8));424 result = result | (ReturnType(b) << @intCast(ShiftType, index * 8));
429 }425 }
430 },426 },
431 }427 }
432 return result;428 return result;
433}429}
434430
435/// Reads a big-endian int of type T from bytes.431/// Reads an integer from memory with bit count specified by T.
436/// bytes.len must be exactly @sizeOf(T).432/// The bit count of T must be evenly divisible by 8.
437pub fn readIntBE(comptime T: type, bytes: []const u8) T {433/// This function cannot fail and cannot cause undefined behavior.
438 if (T.is_signed) {434/// Assumes the endianness of memory is native. This means the function can
439 return @bitCast(T, readIntBE(@IntType(false, T.bit_count), bytes));435/// simply pointer cast memory.
440 }436pub fn readIntNative(comptime T: type, bytes: *const [@sizeOf(T)]u8) T {
441 assert(bytes.len == @sizeOf(T));437 comptime assert(T.bit_count % 8 == 0);
442 if (T == u8) return bytes[0];438 return @ptrCast(*align(1) const T, bytes).*;
443 var result: T = 0;439}
444 {440
445 comptime var i = 0;441/// Reads an integer from memory with bit count specified by T.
446 inline while (i < @sizeOf(T)) : (i += 1) {442/// The bit count of T must be evenly divisible by 8.
447 result = (result << 8) | T(bytes[i]);443/// This function cannot fail and cannot cause undefined behavior.
448 }444/// Assumes the endianness of memory is foreign, so it must byte-swap.
445pub fn readIntForeign(comptime T: type, bytes: *const [@sizeOf(T)]u8) T {
446 return @bswap(T, readIntNative(T, bytes));
447}
448
449pub const readIntLittle = switch (builtin.endian) {
450 builtin.Endian.Little => readIntNative,
451 builtin.Endian.Big => readIntForeign,
452};
453
454pub 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.
465pub 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.
477pub fn readIntSliceForeign(comptime T: type, bytes: []const u8) T {
478 return @bswap(T, readIntSliceNative(T, bytes));
479}
480
481pub const readIntSliceLittle = switch (builtin.endian) {
482 builtin.Endian.Little => readIntSliceNative,
483 builtin.Endian.Big => readIntSliceForeign,
484};
485
486pub 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.
494pub 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}
452501
453/// Reads a little-endian int of type T from bytes.502/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0
454/// bytes.len must be exactly @sizeOf(T).503/// and ignores extra bytes.
455pub fn readIntLE(comptime T: type, bytes: []const u8) T {504/// Note that @sizeOf(u24) is 3.
456 if (T.is_signed) {505/// The bit count of T must be evenly divisible by 8.
457 return @bitCast(T, readIntLE(@IntType(false, T.bit_count), bytes));506pub 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
513test "comptime read/write int" {
514 comptime {
515 var bytes: [2]u8 = undefined;
516 std.mem.writeIntLittle(u16, &bytes, 0x1234);
517 const result = std.mem.readIntBig(u16, &bytes);
518 std.debug.assert(result == 0x3412);
458 }519 }
459 assert(bytes.len == @sizeOf(T));520 comptime {
460 if (T == u8) return bytes[0];521 var bytes: [2]u8 = undefined;
461 var result: T = 0;522 std.mem.writeIntBig(u16, &bytes, 0x1234);
462 {523 const result = std.mem.readIntLittle(u16, &bytes);
463 comptime var i = 0;524 std.debug.assert(result == 0x3412);
464 inline while (i < @sizeOf(T)) : (i += 1) {
465 result |= T(bytes[i]) << i * 8;
466 }
467 }525 }
468 return result;
469}526}
470527
471test "readIntBE/LE" {528test "readIntBig and readIntLittle" {
472 assert(readIntBE(u0, []u8{}) == 0x0);529 assert(readIntSliceBig(u0, []u8{}) == 0x0);
473 assert(readIntLE(u0, []u8{}) == 0x0);530 assert(readIntSliceLittle(u0, []u8{}) == 0x0);
474531
475 assert(readIntBE(u8, []u8{0x32}) == 0x32);532 assert(readIntSliceBig(u8, []u8{0x32}) == 0x32);
476 assert(readIntLE(u8, []u8{0x12}) == 0x12);533 assert(readIntSliceLittle(u8, []u8{0x12}) == 0x12);
477534
478 assert(readIntBE(u16, []u8{0x12, 0x34}) == 0x1234);535 assert(readIntSliceBig(u16, []u8{ 0x12, 0x34 }) == 0x1234);
479 assert(readIntLE(u16, []u8{0x12, 0x34}) == 0x3412);536 assert(readIntSliceLittle(u16, []u8{ 0x12, 0x34 }) == 0x3412);
480537
481 assert(readIntBE(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024);538 assert(readIntSliceBig(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024);
482 assert(readIntLE(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec);539 assert(readIntSliceLittle(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec);
483540
484 assert(readIntBE(i8, []u8{0xff}) == -1);541 assert(readIntSliceBig(i8, []u8{0xff}) == -1);
485 assert(readIntLE(i8, []u8{0xfe}) == -2);542 assert(readIntSliceLittle(i8, []u8{0xfe}) == -2);
486543
487 assert(readIntBE(i16, []u8{0xff, 0xfd}) == -3);544 assert(readIntSliceBig(i16, []u8{ 0xff, 0xfd }) == -3);
488 assert(readIntLE(i16, []u8{0xfc, 0xff}) == -4);545 assert(readIntSliceLittle(i16, []u8{ 0xfc, 0xff }) == -4);
489}546}
490547
491/// Writes an integer to memory with size equal to bytes.len. Pads with zeroes548/// Writes an integer to memory, storing it in twos-complement.
492/// to fill the entire buffer provided.549/// This function always succeeds, has defined behavior for all inputs, and
493/// value must be an integer.550/// accepts any integer bit width.
494pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void {551/// This function stores in native endian, which means it is implemented as a simple
495 const uint = @IntType(false, @typeOf(value).bit_count);552/// memory store.
496 var bits = @truncate(uint, value);553pub fn writeIntNative(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
497 switch (endian) {554 @ptrCast(*align(1) T, buf).* = value;
498 builtin.Endian.Big => {555}
499 var index: usize = buf.len;
500 while (index != 0) {
501 index -= 1;
502556
503 buf[index] = @truncate(u8, bits);557/// Writes an integer to memory, storing it in twos-complement.
504 bits >>= 8;558/// This function always succeeds, has defined behavior for all inputs, but
505 }559/// the integer bit width must be divisible by 8.
506 },560/// This function stores in foreign endian, which means it does a @bswap first.
507 builtin.Endian.Little => {561pub fn writeIntForeign(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
508 for (buf) |*b| {562 writeIntNative(T, buf, @bswap(T, value));
509 b.* = @truncate(u8, bits);563}
510 bits >>= 8;564
511 }565pub const writeIntLittle = switch (builtin.endian) {
512 },566 builtin.Endian.Little => writeIntNative,
567 builtin.Endian.Big => writeIntForeign,
568};
569
570pub 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.
578pub 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}
516586
517pub fn writeIntBE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {587/// Writes a twos-complement little-endian integer to memory.
518 assert(T.bit_count % 8 == 0);588/// Asserts that buf.len >= @sizeOf(T). Note that @sizeOf(u24) is 3.
589/// The bit count of T must be divisible by 8.
590/// Any extra bytes in buffer after writing the integer are set to zero. To
591/// avoid the branch to check for extra buffer bytes, use writeIntLittle
592/// instead.
593pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {
594 comptime assert(@sizeOf(u24) == 3);
595 comptime assert(T.bit_count % 8 == 0);
596 assert(buffer.len >= @sizeOf(T));
597
598 // TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough
519 const uint = @IntType(false, T.bit_count);599 const uint = @IntType(false, T.bit_count);
520 if (uint == u0) {600 var bits = @truncate(uint, value);
521 return;601 for (buffer) |*b| {
522 }602 b.* = @truncate(u8, bits);
523 var bits = @bitCast(uint, value);603 bits >>= 8;
524 if (uint == u8) {
525 buf[0] = bits;
526 return;
527 }604 }
528 var index: usize = buf.len;605}
606
607/// Writes a twos-complement big-endian integer to memory.
608/// Asserts that buffer.len >= @sizeOf(T). Note that @sizeOf(u24) is 3.
609/// The bit count of T must be divisible by 8.
610/// Any extra bytes in buffer before writing the integer are set to zero. To
611/// avoid the branch to check for extra buffer bytes, use writeIntBig instead.
612pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void {
613 comptime assert(@sizeOf(u24) == 3);
614 comptime assert(T.bit_count % 8 == 0);
615 assert(buffer.len >= @sizeOf(T));
616
617 // TODO I want to call writeIntBig here but comptime eval facilities aren't good enough
618 const uint = @IntType(false, T.bit_count);
619 var bits = @truncate(uint, value);
620 var index: usize = buffer.len;
529 while (index != 0) {621 while (index != 0) {
530 index -= 1;622 index -= 1;
531623 buffer[index] = @truncate(u8, bits);
532 buf[index] = @truncate(u8, bits);
533 bits >>= 8;624 bits >>= 8;
534 }625 }
535 assert(bits == 0);
536}626}
537627
538pub fn writeIntLE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {628pub const writeIntSliceNative = switch (builtin.endian) {
539 assert(T.bit_count % 8 == 0);629 builtin.Endian.Little => writeIntSliceLittle,
540 const uint = @IntType(false, T.bit_count);630 builtin.Endian.Big => writeIntSliceBig,
541 if (uint == u0) {631};
542 return;632
543 }633pub const writeIntSliceForeign = switch (builtin.endian) {
544 var bits = @bitCast(uint, value);634 builtin.Endian.Little => writeIntSliceBig,
545 if (uint == u8) {635 builtin.Endian.Big => writeIntSliceLittle,
546 buf[0] = bits;636};
547 return;637
548 }638/// Writes a twos-complement integer to memory, with the specified endianness.
549 // FIXME: this should just be for (buf).639/// Asserts that buf.len >= @sizeOf(T). Note that @sizeOf(u24) is 3.
550 // See https://github.com/ziglang/zig/issues/1663640/// The bit count of T must be evenly divisible by 8.
551 for (buf.*) |*b| {641/// Any extra bytes in buffer not part of the integer are set to zero, with
552 b.* = @truncate(u8, bits);642/// respect to endianness. To avoid the branch to check for extra buffer bytes,
553 bits >>= 8;643/// use writeInt instead.
644pub 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}
557651
558test "writeIntBE/LE" {652test "writeIntBig and writeIntLittle" {
559 var buf0: [0]u8 = undefined;653 var buf0: [0]u8 = undefined;
560 var buf1: [1]u8 = undefined;654 var buf1: [1]u8 = undefined;
561 var buf2: [2]u8 = undefined;655 var buf2: [2]u8 = undefined;
562 var buf9: [9]u8 = undefined;656 var buf9: [9]u8 = undefined;
563657
564 writeIntBE(u0, &buf0, 0x0);658 writeIntBig(u0, &buf0, 0x0);
565 assert(eql_slice_u8(buf0[0..], []u8{}));659 assert(eql_slice_u8(buf0[0..], []u8{}));
566 writeIntLE(u0, &buf0, 0x0);660 writeIntLittle(u0, &buf0, 0x0);
567 assert(eql_slice_u8(buf0[0..], []u8{}));661 assert(eql_slice_u8(buf0[0..], []u8{}));
568662
569 writeIntBE(u8, &buf1, 0x12);663 writeIntBig(u8, &buf1, 0x12);
570 assert(eql_slice_u8(buf1[0..], []u8{0x12}));664 assert(eql_slice_u8(buf1[0..], []u8{0x12}));
571 writeIntLE(u8, &buf1, 0x34);665 writeIntLittle(u8, &buf1, 0x34);
572 assert(eql_slice_u8(buf1[0..], []u8{0x34}));666 assert(eql_slice_u8(buf1[0..], []u8{0x34}));
573667
574 writeIntBE(u16, &buf2, 0x1234);668 writeIntBig(u16, &buf2, 0x1234);
575 assert(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 }));669 assert(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 }));
576 writeIntLE(u16, &buf2, 0x5678);670 writeIntLittle(u16, &buf2, 0x5678);
577 assert(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 }));671 assert(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 }));
578672
579 writeIntBE(u72, &buf9, 0x123456789abcdef024);673 writeIntBig(u72, &buf9, 0x123456789abcdef024);
580 assert(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }));674 assert(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }));
581 writeIntLE(u72, &buf9, 0xfedcba9876543210ec);675 writeIntLittle(u72, &buf9, 0xfedcba9876543210ec);
582 assert(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }));676 assert(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }));
583677
584 writeIntBE(i8, &buf1, -1);678 writeIntBig(i8, &buf1, -1);
585 assert(eql_slice_u8(buf1[0..], []u8{0xff}));679 assert(eql_slice_u8(buf1[0..], []u8{0xff}));
586 writeIntLE(i8, &buf1, -2);680 writeIntLittle(i8, &buf1, -2);
587 assert(eql_slice_u8(buf1[0..], []u8{0xfe}));681 assert(eql_slice_u8(buf1[0..], []u8{0xfe}));
588682
589 writeIntBE(i16, &buf2, -3);683 writeIntBig(i16, &buf2, -3);
590 assert(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd }));684 assert(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd }));
591 writeIntLE(i16, &buf2, -4);685 writeIntLittle(i16, &buf2, -4);
592 assert(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff }));686 assert(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff }));
593}687}
594688
...@@ -737,12 +831,12 @@ fn testReadIntImpl() void {...@@ -737,12 +831,12 @@ fn testReadIntImpl() void {
737 0x56,831 0x56,
738 0x78,832 0x78,
739 };833 };
740 assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678);834 assert(readInt(u32, &bytes, builtin.Endian.Big) == 0x12345678);
741 assert(readIntBE(u32, bytes) == 0x12345678);835 assert(readIntBig(u32, &bytes) == 0x12345678);
742 assert(readIntBE(i32, bytes) == 0x12345678);836 assert(readIntBig(i32, &bytes) == 0x12345678);
743 assert(readInt(bytes, u32, builtin.Endian.Little) == 0x78563412);837 assert(readInt(u32, &bytes, builtin.Endian.Little) == 0x78563412);
744 assert(readIntLE(u32, bytes) == 0x78563412);838 assert(readIntLittle(u32, &bytes) == 0x78563412);
745 assert(readIntLE(i32, bytes) == 0x78563412);839 assert(readIntLittle(i32, &bytes) == 0x78563412);
746 }840 }
747 {841 {
748 const buf = []u8{842 const buf = []u8{
...@@ -751,7 +845,7 @@ fn testReadIntImpl() void {...@@ -751,7 +845,7 @@ fn testReadIntImpl() void {
751 0x12,845 0x12,
752 0x34,846 0x34,
753 };847 };
754 const answer = readInt(buf, u64, builtin.Endian.Big);848 const answer = readInt(u32, &buf, builtin.Endian.Big);
755 assert(answer == 0x00001234);849 assert(answer == 0x00001234);
756 }850 }
757 {851 {
...@@ -761,7 +855,7 @@ fn testReadIntImpl() void {...@@ -761,7 +855,7 @@ fn testReadIntImpl() void {
761 0x00,855 0x00,
762 0x00,856 0x00,
763 };857 };
764 const answer = readInt(buf, u64, builtin.Endian.Little);858 const answer = readInt(u32, &buf, builtin.Endian.Little);
765 assert(answer == 0x00003412);859 assert(answer == 0x00003412);
766 }860 }
767 {861 {
...@@ -769,21 +863,33 @@ fn testReadIntImpl() void {...@@ -769,21 +863,33 @@ fn testReadIntImpl() void {
769 0xff,863 0xff,
770 0xfe,864 0xfe,
771 };865 };
772 assert(readIntBE(u16, bytes) == 0xfffe);866 assert(readIntBig(u16, &bytes) == 0xfffe);
773 assert(readIntBE(i16, bytes) == -0x0002);867 assert(readIntBig(i16, &bytes) == -0x0002);
774 assert(readIntLE(u16, bytes) == 0xfeff);868 assert(readIntLittle(u16, &bytes) == 0xfeff);
775 assert(readIntLE(i16, bytes) == -0x0101);869 assert(readIntLittle(i16, &bytes) == -0x0101);
776 }870 }
777}871}
778872
779test "testWriteInt" {873test "std.mem.writeIntSlice" {
780 testWriteIntImpl();874 testWriteIntImpl();
781 comptime testWriteIntImpl();875 comptime testWriteIntImpl();
782}876}
783fn testWriteIntImpl() void {877fn testWriteIntImpl() void {
784 var bytes: [8]u8 = undefined;878 var bytes: [8]u8 = undefined;
785879
786 writeInt(bytes[0..], u64(0x12345678CAFEBABE), builtin.Endian.Big);880 writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Big);
881 assert(eql(u8, bytes, []u8{
882 0x00, 0x00, 0x00, 0x00,
883 0x00, 0x00, 0x00, 0x00,
884 }));
885
886 writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Little);
887 assert(eql(u8, bytes, []u8{
888 0x00, 0x00, 0x00, 0x00,
889 0x00, 0x00, 0x00, 0x00,
890 }));
891
892 writeIntSlice(u64, bytes[0..], 0x12345678CAFEBABE, builtin.Endian.Big);
787 assert(eql(u8, bytes, []u8{893 assert(eql(u8, bytes, []u8{
788 0x12,894 0x12,
789 0x34,895 0x34,
...@@ -795,7 +901,7 @@ fn testWriteIntImpl() void {...@@ -795,7 +901,7 @@ fn testWriteIntImpl() void {
795 0xBE,901 0xBE,
796 }));902 }));
797903
798 writeInt(bytes[0..], u64(0xBEBAFECA78563412), builtin.Endian.Little);904 writeIntSlice(u64, bytes[0..], 0xBEBAFECA78563412, builtin.Endian.Little);
799 assert(eql(u8, bytes, []u8{905 assert(eql(u8, bytes, []u8{
800 0x12,906 0x12,
801 0x34,907 0x34,
...@@ -807,7 +913,7 @@ fn testWriteIntImpl() void {...@@ -807,7 +913,7 @@ fn testWriteIntImpl() void {
807 0xBE,913 0xBE,
808 }));914 }));
809915
810 writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big);916 writeIntSlice(u32, bytes[0..], 0x12345678, builtin.Endian.Big);
811 assert(eql(u8, bytes, []u8{917 assert(eql(u8, bytes, []u8{
812 0x00,918 0x00,
813 0x00,919 0x00,
...@@ -819,7 +925,7 @@ fn testWriteIntImpl() void {...@@ -819,7 +925,7 @@ fn testWriteIntImpl() void {
819 0x78,925 0x78,
820 }));926 }));
821927
822 writeInt(bytes[0..], u32(0x78563412), builtin.Endian.Little);928 writeIntSlice(u32, bytes[0..], 0x78563412, builtin.Endian.Little);
823 assert(eql(u8, bytes, []u8{929 assert(eql(u8, bytes, []u8{
824 0x12,930 0x12,
825 0x34,931 0x34,
...@@ -831,7 +937,7 @@ fn testWriteIntImpl() void {...@@ -831,7 +937,7 @@ fn testWriteIntImpl() void {
831 0x00,937 0x00,
832 }));938 }));
833939
834 writeInt(bytes[0..], u16(0x1234), builtin.Endian.Big);940 writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Big);
835 assert(eql(u8, bytes, []u8{941 assert(eql(u8, bytes, []u8{
836 0x00,942 0x00,
837 0x00,943 0x00,
...@@ -843,7 +949,7 @@ fn testWriteIntImpl() void {...@@ -843,7 +949,7 @@ fn testWriteIntImpl() void {
843 0x34,949 0x34,
844 }));950 }));
845951
846 writeInt(bytes[0..], u16(0x1234), builtin.Endian.Little);952 writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Little);
847 assert(eql(u8, bytes, []u8{953 assert(eql(u8, bytes, []u8{
848 0x34,954 0x34,
849 0x12,955 0x12,
...@@ -941,29 +1047,52 @@ test "std.mem.rotate" {...@@ -941,29 +1047,52 @@ test "std.mem.rotate" {
941 }));1047 }));
942}1048}
9431049
944// TODO: When https://github.com/ziglang/zig/issues/649 is solved these can be done by1050/// Converts a little-endian integer to host endianness.
945// endian-casting the pointer and then dereferencing1051pub 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}
9461057
947pub fn endianSwapIfLe(comptime T: type, x: T) T {1058/// Converts a big-endian integer to host endianness.
948 return endianSwapIf(builtin.Endian.Little, T, x);1059pub 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}
9501065
951pub fn endianSwapIfBe(comptime T: type, x: T) T {1066/// Converts an integer from specified endianness to host endianness.
952 return endianSwapIf(builtin.Endian.Big, T, x);1067pub 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}
9541073
955pub fn endianSwapIf(endian: builtin.Endian, comptime T: type, x: T) T {1074/// Converts an integer which has host endianness to the desired endianness.
956 return if (builtin.endian == endian) endianSwap(T, x) else x;1075pub 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}
9581081
959pub fn endianSwap(comptime T: type, x: T) T {1082/// Converts an integer which has host endianness to little endian.
960 var buf: [@sizeOf(T)]u8 = undefined;1083pub fn nativeToLittle(comptime T: type, x: T) T {
961 mem.writeInt(buf[0..], x, builtin.Endian.Little);1084 return switch (builtin.endian) {
962 return mem.readInt(buf, T, builtin.Endian.Big);1085 builtin.Endian.Little => x,
1086 builtin.Endian.Big => @bswap(T, x),
1087 };
963}1088}
9641089
965test "std.mem.endianSwap" {1090/// Converts an integer which has host endianness to big endian.
966 assert(endianSwap(u32, 0xDEADBEEF) == 0xEFBEADDE);1091pub 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}
9681097
969fn AsBytesReturnType(comptime P: type) type {1098fn AsBytesReturnType(comptime P: type) type {
std/meta/index.zig+48
...@@ -76,6 +76,25 @@ test "std.meta.tagName" {...@@ -76,6 +76,25 @@ test "std.meta.tagName" {
76 debug.assert(mem.eql(u8, tagName(u2b), "D"));76 debug.assert(mem.eql(u8, tagName(u2b), "D"));
77}77}
7878
79pub 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
88test "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
79pub fn bitCount(comptime T: type) u32 {98pub fn bitCount(comptime T: type) u32 {
80 return switch (@typeInfo(T)) {99 return switch (@typeInfo(T)) {
81 TypeId.Int => |info| info.bits,100 TypeId.Int => |info| info.bits,
...@@ -483,3 +502,32 @@ test "std.meta.eql" {...@@ -483,3 +502,32 @@ test "std.meta.eql" {
483 debug.assert(eql(EU.tst(false), EU.tst(false)));502 debug.assert(eql(EU.tst(false), EU.tst(false)));
484 debug.assert(!eql(EU.tst(false), EU.tst(true)));503 debug.assert(!eql(EU.tst(false), EU.tst(true)));
485}504}
505
506test "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
522pub const IntToEnumError = error{InvalidEnumTag};
523
524pub fn intToEnum(comptime Tag: type, tag_int: var) IntToEnumError!Tag {
525 comptime var i = 0;
526 inline while (i != @memberCount(Tag)) : (i += 1) {
527 const this_tag_value = @field(Tag, @memberName(Tag, i));
528 if (tag_int == @enumToInt(this_tag_value)) {
529 return this_tag_value;
530 }
531 }
532 return error.InvalidEnumTag;
533}
std/net.zig+6-6
...@@ -23,7 +23,7 @@ pub const Address = struct {...@@ -23,7 +23,7 @@ pub const Address = struct {
23 .os_addr = posix.sockaddr{23 .os_addr = posix.sockaddr{
24 .in = posix.sockaddr_in{24 .in = posix.sockaddr_in{
25 .family = posix.AF_INET,25 .family = posix.AF_INET,
26 .port = std.mem.endianSwapIfLe(u16, _port),26 .port = mem.nativeToBig(u16, _port),
27 .addr = ip4,27 .addr = ip4,
28 .zero = []u8{0} ** 8,28 .zero = []u8{0} ** 8,
29 },29 },
...@@ -37,7 +37,7 @@ pub const Address = struct {...@@ -37,7 +37,7 @@ pub const Address = struct {
37 .os_addr = posix.sockaddr{37 .os_addr = posix.sockaddr{
38 .in6 = posix.sockaddr_in6{38 .in6 = posix.sockaddr_in6{
39 .family = posix.AF_INET6,39 .family = posix.AF_INET6,
40 .port = std.mem.endianSwapIfLe(u16, _port),40 .port = mem.nativeToBig(u16, _port),
41 .flowinfo = 0,41 .flowinfo = 0,
42 .addr = ip6.addr,42 .addr = ip6.addr,
43 .scope_id = ip6.scope_id,43 .scope_id = ip6.scope_id,
...@@ -47,7 +47,7 @@ pub const Address = struct {...@@ -47,7 +47,7 @@ pub const Address = struct {
47 }47 }
4848
49 pub fn port(self: Address) u16 {49 pub fn port(self: Address) u16 {
50 return std.mem.endianSwapIfLe(u16, self.os_addr.in.port);50 return mem.bigToNative(u16, self.os_addr.in.port);
51 }51 }
5252
53 pub fn initPosix(addr: posix.sockaddr) Address {53 pub fn initPosix(addr: posix.sockaddr) Address {
...@@ -57,12 +57,12 @@ pub const Address = struct {...@@ -57,12 +57,12 @@ pub const Address = struct {
57 pub fn format(self: *const Address, out_stream: var) !void {57 pub fn format(self: *const Address, out_stream: var) !void {
58 switch (self.os_addr.in.family) {58 switch (self.os_addr.in.family) {
59 posix.AF_INET => {59 posix.AF_INET => {
60 const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in.port);60 const native_endian_port = mem.bigToNative(u16, self.os_addr.in.port);
61 const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]);61 const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]);
62 try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port);62 try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port);
63 },63 },
64 posix.AF_INET6 => {64 posix.AF_INET6 => {
65 const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in6.port);65 const native_endian_port = mem.bigToNative(u16, self.os_addr.in6.port);
66 try out_stream.print("[TODO render ip6 address]:{}", native_endian_port);66 try out_stream.print("[TODO render ip6 address]:{}", native_endian_port);
67 },67 },
68 else => try out_stream.write("(unrecognized address family)"),68 else => try out_stream.write("(unrecognized address family)"),
...@@ -193,7 +193,7 @@ pub fn parseIp6(buf: []const u8) !Ip6Addr {...@@ -193,7 +193,7 @@ pub fn parseIp6(buf: []const u8) !Ip6Addr {
193}193}
194194
195test "std.net.parseIp4" {195test "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));
197197
198 testParseIp4Fail("256.0.0.1", error.Overflow);198 testParseIp4Fail("256.0.0.1", error.Overflow);
199 testParseIp4Fail("x.0.0.1", error.InvalidCharacter);199 testParseIp4Fail("x.0.0.1", error.InvalidCharacter);
std/os/child_process.zig+15-2
...@@ -390,6 +390,19 @@ pub const ChildProcess = struct {...@@ -390,6 +390,19 @@ pub const ChildProcess = struct {
390 setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);390 setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
391 setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);391 setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
392392
393 if (self.stdin_behavior == StdIo.Pipe) {
394 os.close(stdin_pipe[0]);
395 os.close(stdin_pipe[1]);
396 }
397 if (self.stdout_behavior == StdIo.Pipe) {
398 os.close(stdout_pipe[0]);
399 os.close(stdout_pipe[1]);
400 }
401 if (self.stderr_behavior == StdIo.Pipe) {
402 os.close(stderr_pipe[0]);
403 os.close(stderr_pipe[1]);
404 }
405
393 if (self.cwd) |cwd| {406 if (self.cwd) |cwd| {
394 os.changeCurDir(self.allocator, cwd) catch |err| forkChildErrReport(err_pipe[1], err);407 os.changeCurDir(self.allocator, cwd) catch |err| forkChildErrReport(err_pipe[1], err);
395 }408 }
...@@ -794,10 +807,10 @@ const ErrInt = @IntType(false, @sizeOf(anyerror) * 8);...@@ -794,10 +807,10 @@ const ErrInt = @IntType(false, @sizeOf(anyerror) * 8);
794807
795fn writeIntFd(fd: i32, value: ErrInt) !void {808fn writeIntFd(fd: i32, value: ErrInt) !void {
796 const stream = &os.File.openHandle(fd).outStream().stream;809 const stream = &os.File.openHandle(fd).outStream().stream;
797 stream.writeIntNe(ErrInt, value) catch return error.SystemResources;810 stream.writeIntNative(ErrInt, value) catch return error.SystemResources;
798}811}
799812
800fn readIntFd(fd: i32) !ErrInt {813fn readIntFd(fd: i32) !ErrInt {
801 const stream = &os.File.openHandle(fd).inStream().stream;814 const stream = &os.File.openHandle(fd).inStream().stream;
802 return stream.readIntNe(ErrInt) catch return error.SystemResources;815 return stream.readIntNative(ErrInt) catch return error.SystemResources;
803}816}
std/os/file.zig+62-8
...@@ -228,9 +228,16 @@ pub const File = struct {...@@ -228,9 +228,16 @@ pub const File = struct {
228 return os.isTty(self.handle);228 return os.isTty(self.handle);
229 }229 }
230230
231 pub fn seekForward(self: File, amount: isize) !void {231 pub const SeekError = error{
232 /// TODO make this error impossible to get
233 Overflow,
234 Unseekable,
235 Unexpected,
236 };
237
238 pub fn seekForward(self: File, amount: isize) SeekError!void {
232 switch (builtin.os) {239 switch (builtin.os) {
233 Os.linux, Os.macosx, Os.ios => {240 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
234 const result = posix.lseek(self.handle, amount, posix.SEEK_CUR);241 const result = posix.lseek(self.handle, amount, posix.SEEK_CUR);
235 const err = posix.getErrno(result);242 const err = posix.getErrno(result);
236 if (err > 0) {243 if (err > 0) {
...@@ -259,9 +266,9 @@ pub const File = struct {...@@ -259,9 +266,9 @@ pub const File = struct {
259 }266 }
260 }267 }
261268
262 pub fn seekTo(self: File, pos: usize) !void {269 pub fn seekTo(self: File, pos: usize) SeekError!void {
263 switch (builtin.os) {270 switch (builtin.os) {
264 Os.linux, Os.macosx, Os.ios => {271 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
265 const ipos = try math.cast(isize, pos);272 const ipos = try math.cast(isize, pos);
266 const result = posix.lseek(self.handle, ipos, posix.SEEK_SET);273 const result = posix.lseek(self.handle, ipos, posix.SEEK_SET);
267 const err = posix.getErrno(result);274 const err = posix.getErrno(result);
...@@ -293,9 +300,16 @@ pub const File = struct {...@@ -293,9 +300,16 @@ pub const File = struct {
293 }300 }
294 }301 }
295302
296 pub fn getPos(self: File) !usize {303 pub const GetSeekPosError = error{
304 Overflow,
305 SystemResources,
306 Unseekable,
307 Unexpected,
308 };
309
310 pub fn getPos(self: File) GetSeekPosError!usize {
297 switch (builtin.os) {311 switch (builtin.os) {
298 Os.linux, Os.macosx, Os.ios => {312 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
299 const result = posix.lseek(self.handle, 0, posix.SEEK_CUR);313 const result = posix.lseek(self.handle, 0, posix.SEEK_CUR);
300 const err = posix.getErrno(result);314 const err = posix.getErrno(result);
301 if (err > 0) {315 if (err > 0) {
...@@ -323,13 +337,13 @@ pub const File = struct {...@@ -323,13 +337,13 @@ pub const File = struct {
323 }337 }
324338
325 assert(pos >= 0);339 assert(pos >= 0);
326 return math.cast(usize, pos) catch error.FilePosLargerThanPointerRange;340 return math.cast(usize, pos);
327 },341 },
328 else => @compileError("unsupported OS"),342 else => @compileError("unsupported OS"),
329 }343 }
330 }344 }
331345
332 pub fn getEndPos(self: File) !usize {346 pub fn getEndPos(self: File) GetSeekPosError!usize {
333 if (is_posix) {347 if (is_posix) {
334 const stat = try os.posixFStat(self.handle);348 const stat = try os.posixFStat(self.handle);
335 return @intCast(usize, stat.size);349 return @intCast(usize, stat.size);
...@@ -431,6 +445,18 @@ pub const File = struct {...@@ -431,6 +445,18 @@ pub const File = struct {
431 };445 };
432 }446 }
433447
448 pub fn seekableStream(file: File) SeekableStream {
449 return SeekableStream{
450 .file = file,
451 .stream = SeekableStream.Stream{
452 .seekToFn = SeekableStream.seekToFn,
453 .seekForwardFn = SeekableStream.seekForwardFn,
454 .getPosFn = SeekableStream.getPosFn,
455 .getEndPosFn = SeekableStream.getEndPosFn,
456 },
457 };
458 }
459
434 /// Implementation of io.InStream trait for File460 /// Implementation of io.InStream trait for File
435 pub const InStream = struct {461 pub const InStream = struct {
436 file: File,462 file: File,
...@@ -458,4 +484,32 @@ pub const File = struct {...@@ -458,4 +484,32 @@ pub const File = struct {
458 return self.file.write(bytes);484 return self.file.write(bytes);
459 }485 }
460 };486 };
487
488 /// Implementation of io.SeekableStream trait for File
489 pub const SeekableStream = struct {
490 file: File,
491 stream: Stream,
492
493 pub const Stream = io.SeekableStream(SeekError, GetSeekPosError);
494
495 pub fn seekToFn(seekable_stream: *Stream, pos: usize) SeekError!void {
496 const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
497 return self.file.seekTo(pos);
498 }
499
500 pub fn seekForwardFn(seekable_stream: *Stream, amt: isize) SeekError!void {
501 const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
502 return self.file.seekForward(amt);
503 }
504
505 pub fn getEndPosFn(seekable_stream: *Stream) GetSeekPosError!usize {
506 const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
507 return self.file.getEndPos();
508 }
509
510 pub fn getPosFn(seekable_stream: *Stream) GetSeekPosError!usize {
511 const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
512 return self.file.getPos();
513 }
514 };
461};515};
std/os/freebsd/errno.zig created+121
...@@ -0,0 +1,121 @@
1pub const EPERM = 1; // Operation not permitted
2pub const ENOENT = 2; // No such file or directory
3pub const ESRCH = 3; // No such process
4pub const EINTR = 4; // Interrupted system call
5pub const EIO = 5; // Input/output error
6pub const ENXIO = 6; // Device not configured
7pub const E2BIG = 7; // Argument list too long
8pub const ENOEXEC = 8; // Exec format error
9pub const EBADF = 9; // Bad file descriptor
10pub const ECHILD = 10; // No child processes
11pub const EDEADLK = 11; // Resource deadlock avoided
12// 11 was EAGAIN
13pub const ENOMEM = 12; // Cannot allocate memory
14pub const EACCES = 13; // Permission denied
15pub const EFAULT = 14; // Bad address
16pub const ENOTBLK = 15; // Block device required
17pub const EBUSY = 16; // Device busy
18pub const EEXIST = 17; // File exists
19pub const EXDEV = 18; // Cross-device link
20pub const ENODEV = 19; // Operation not supported by device
21pub const ENOTDIR = 20; // Not a directory
22pub const EISDIR = 21; // Is a directory
23pub const EINVAL = 22; // Invalid argument
24pub const ENFILE = 23; // Too many open files in system
25pub const EMFILE = 24; // Too many open files
26pub const ENOTTY = 25; // Inappropriate ioctl for device
27pub const ETXTBSY = 26; // Text file busy
28pub const EFBIG = 27; // File too large
29pub const ENOSPC = 28; // No space left on device
30pub const ESPIPE = 29; // Illegal seek
31pub const EROFS = 30; // Read-only filesystem
32pub const EMLINK = 31; // Too many links
33pub const EPIPE = 32; // Broken pipe
34
35// math software
36pub const EDOM = 33; // Numerical argument out of domain
37pub const ERANGE = 34; // Result too large
38
39// non-blocking and interrupt i/o
40pub const EAGAIN = 35; // Resource temporarily unavailable
41pub const EWOULDBLOCK = EAGAIN; // Operation would block
42pub const EINPROGRESS = 36; // Operation now in progress
43pub const EALREADY = 37; // Operation already in progress
44
45// ipc/network software -- argument errors
46pub const ENOTSOCK = 38; // Socket operation on non-socket
47pub const EDESTADDRREQ = 39; // Destination address required
48pub const EMSGSIZE = 40; // Message too long
49pub const EPROTOTYPE = 41; // Protocol wrong type for socket
50pub const ENOPROTOOPT = 42; // Protocol not available
51pub const EPROTONOSUPPORT = 43; // Protocol not supported
52pub const ESOCKTNOSUPPORT = 44; // Socket type not supported
53pub const EOPNOTSUPP = 45; // Operation not supported
54pub const ENOTSUP = EOPNOTSUPP; // Operation not supported
55pub const EPFNOSUPPORT = 46; // Protocol family not supported
56pub const EAFNOSUPPORT = 47; // Address family not supported by protocol family
57pub const EADDRINUSE = 48; // Address already in use
58pub const EADDRNOTAVAIL = 49; // Can't assign requested address
59
60// ipc/network software -- operational errors
61pub const ENETDOWN = 50; // Network is down
62pub const ENETUNREACH = 51; // Network is unreachable
63pub const ENETRESET = 52; // Network dropped connection on reset
64pub const ECONNABORTED = 53; // Software caused connection abort
65pub const ECONNRESET = 54; // Connection reset by peer
66pub const ENOBUFS = 55; // No buffer space available
67pub const EISCONN = 56; // Socket is already connected
68pub const ENOTCONN = 57; // Socket is not connected
69pub const ESHUTDOWN = 58; // Can't send after socket shutdown
70pub const ETOOMANYREFS = 59; // Too many references: can't splice
71pub const ETIMEDOUT = 60; // Operation timed out
72pub const ECONNREFUSED = 61; // Connection refused
73
74pub const ELOOP = 62; // Too many levels of symbolic links
75pub const ENAMETOOLONG = 63; // File name too long
76
77// should be rearranged
78pub const EHOSTDOWN = 64; // Host is down
79pub const EHOSTUNREACH = 65; // No route to host
80pub const ENOTEMPTY = 66; // Directory not empty
81
82// quotas & mush
83pub const EPROCLIM = 67; // Too many processes
84pub const EUSERS = 68; // Too many users
85pub const EDQUOT = 69; // Disc quota exceeded
86
87// Network File System
88pub const ESTALE = 70; // Stale NFS file handle
89pub const EREMOTE = 71; // Too many levels of remote in path
90pub const EBADRPC = 72; // RPC struct is bad
91pub const ERPCMISMATCH = 73; // RPC version wrong
92pub const EPROGUNAVAIL = 74; // RPC prog. not avail
93pub const EPROGMISMATCH = 75; // Program version wrong
94pub const EPROCUNAVAIL = 76; // Bad procedure for program
95
96pub const ENOLCK = 77; // No locks available
97pub const ENOSYS = 78; // Function not implemented
98
99pub const EFTYPE = 79; // Inappropriate file type or format
100pub const EAUTH = 80; // Authentication error
101pub const ENEEDAUTH = 81; // Need authenticator
102pub const EIDRM = 82; // Identifier removed
103pub const ENOMSG = 83; // No message of desired type
104pub const EOVERFLOW = 84; // Value too large to be stored in data type
105pub const ECANCELED = 85; // Operation canceled
106pub const EILSEQ = 86; // Illegal byte sequence
107pub const ENOATTR = 87; // Attribute not found
108
109pub const EDOOFUS = 88; // Programming error
110
111pub const EBADMSG = 89; // Bad message
112pub const EMULTIHOP = 90; // Multihop attempted
113pub const ENOLINK = 91; // Link has been severed
114pub const EPROTO = 92; // Protocol error
115
116pub const ENOTCAPABLE = 93; // Capabilities insufficient
117pub const ECAPMODE = 94; // Not permitted in capability mode
118pub const ENOTRECOVERABLE = 95; // State not recoverable
119pub const EOWNERDEAD = 96; // Previous owner died
120
121pub const ELAST = 96; // Must be equal largest errno
std/os/freebsd/index.zig created+801
...@@ -0,0 +1,801 @@
1const assert = @import("../debug.zig").assert;
2const builtin = @import("builtin");
3const arch = switch (builtin.arch) {
4 builtin.Arch.x86_64 => @import("x86_64.zig"),
5 else => @compileError("unsupported arch"),
6};
7pub use @import("syscall.zig");
8pub use @import("errno.zig");
9
10const std = @import("../../index.zig");
11const c = std.c;
12const maxInt = std.math.maxInt;
13pub const Kevent = c.Kevent;
14
15pub const PATH_MAX = 1024;
16
17pub const STDIN_FILENO = 0;
18pub const STDOUT_FILENO = 1;
19pub const STDERR_FILENO = 2;
20
21pub const PROT_NONE = 0;
22pub const PROT_READ = 1;
23pub const PROT_WRITE = 2;
24pub const PROT_EXEC = 4;
25
26pub const MAP_FAILED = maxInt(usize);
27pub const MAP_SHARED = 0x0001;
28pub const MAP_PRIVATE = 0x0002;
29pub const MAP_FIXED = 0x0010;
30pub const MAP_STACK = 0x0400;
31pub const MAP_NOSYNC = 0x0800;
32pub const MAP_ANON = 0x1000;
33pub const MAP_ANONYMOUS = MAP_ANON;
34pub const MAP_FILE = 0;
35pub const MAP_NORESERVE = 0;
36
37pub const MAP_GUARD = 0x00002000;
38pub const MAP_EXCL = 0x00004000;
39pub const MAP_NOCORE = 0x00020000;
40pub const MAP_PREFAULT_READ = 0x00040000;
41pub const MAP_32BIT = 0x00080000;
42
43pub const WNOHANG = 1;
44pub const WUNTRACED = 2;
45pub const WSTOPPED = WUNTRACED;
46pub const WCONTINUED = 4;
47pub const WNOWAIT = 8;
48pub const WEXITED = 16;
49pub const WTRAPPED = 32;
50
51pub const SA_ONSTACK = 0x0001;
52pub const SA_RESTART = 0x0002;
53pub const SA_RESETHAND = 0x0004;
54pub const SA_NOCLDSTOP = 0x0008;
55pub const SA_NODEFER = 0x0010;
56pub const SA_NOCLDWAIT = 0x0020;
57pub const SA_SIGINFO = 0x0040;
58
59pub const SIGHUP = 1;
60pub const SIGINT = 2;
61pub const SIGQUIT = 3;
62pub const SIGILL = 4;
63pub const SIGTRAP = 5;
64pub const SIGABRT = 6;
65pub const SIGIOT = SIGABRT;
66pub const SIGEMT = 7;
67pub const SIGFPE = 8;
68pub const SIGKILL = 9;
69pub const SIGBUS = 10;
70pub const SIGSEGV = 11;
71pub const SIGSYS = 12;
72pub const SIGPIPE = 13;
73pub const SIGALRM = 14;
74pub const SIGTERM = 15;
75pub const SIGURG = 16;
76pub const SIGSTOP = 17;
77pub const SIGTSTP = 18;
78pub const SIGCONT = 19;
79pub const SIGCHLD = 20;
80pub const SIGTTIN = 21;
81pub const SIGTTOU = 22;
82pub const SIGIO = 23;
83pub const SIGXCPU = 24;
84pub const SIGXFSZ = 25;
85pub const SIGVTALRM = 26;
86pub const SIGPROF = 27;
87pub const SIGWINCH = 28;
88pub const SIGINFO = 29;
89pub const SIGUSR1 = 30;
90pub const SIGUSR2 = 31;
91pub const SIGTHR = 32;
92pub const SIGLWP = SIGTHR;
93pub const SIGLIBRT = 33;
94
95pub const SIGRTMIN = 65;
96pub const SIGRTMAX = 126;
97
98pub const O_RDONLY = 0o0;
99pub const O_WRONLY = 0o1;
100pub const O_RDWR = 0o2;
101pub const O_ACCMODE = 0o3;
102
103pub const O_CREAT = 0o100;
104pub const O_EXCL = 0o200;
105pub const O_NOCTTY = 0o400;
106pub const O_TRUNC = 0o1000;
107pub const O_APPEND = 0o2000;
108pub const O_NONBLOCK = 0o4000;
109pub const O_DSYNC = 0o10000;
110pub const O_SYNC = 0o4010000;
111pub const O_RSYNC = 0o4010000;
112pub const O_DIRECTORY = 0o200000;
113pub const O_NOFOLLOW = 0o400000;
114pub const O_CLOEXEC = 0o2000000;
115
116pub const O_ASYNC = 0o20000;
117pub const O_DIRECT = 0o40000;
118pub const O_LARGEFILE = 0;
119pub const O_NOATIME = 0o1000000;
120pub const O_PATH = 0o10000000;
121pub const O_TMPFILE = 0o20200000;
122pub const O_NDELAY = O_NONBLOCK;
123
124pub const F_DUPFD = 0;
125pub const F_GETFD = 1;
126pub const F_SETFD = 2;
127pub const F_GETFL = 3;
128pub const F_SETFL = 4;
129
130pub const F_SETOWN = 8;
131pub const F_GETOWN = 9;
132pub const F_SETSIG = 10;
133pub const F_GETSIG = 11;
134
135pub const F_GETLK = 5;
136pub const F_SETLK = 6;
137pub const F_SETLKW = 7;
138
139pub const F_SETOWN_EX = 15;
140pub const F_GETOWN_EX = 16;
141
142pub const F_GETOWNER_UIDS = 17;
143
144pub const SEEK_SET = 0;
145pub const SEEK_CUR = 1;
146pub const SEEK_END = 2;
147
148pub const SIG_BLOCK = 1;
149pub const SIG_UNBLOCK = 2;
150pub const SIG_SETMASK = 3;
151
152pub const SOCK_STREAM = 1;
153pub const SOCK_DGRAM = 2;
154pub const SOCK_RAW = 3;
155pub const SOCK_RDM = 4;
156pub const SOCK_SEQPACKET = 5;
157
158pub const SOCK_CLOEXEC = 0x10000000;
159pub const SOCK_NONBLOCK = 0x20000000;
160
161pub const PROTO_ip = 0o000;
162pub const PROTO_icmp = 0o001;
163pub const PROTO_igmp = 0o002;
164pub const PROTO_ggp = 0o003;
165pub const PROTO_ipencap = 0o004;
166pub const PROTO_st = 0o005;
167pub const PROTO_tcp = 0o006;
168pub const PROTO_egp = 0o010;
169pub const PROTO_pup = 0o014;
170pub const PROTO_udp = 0o021;
171pub const PROTO_hmp = 0o024;
172pub const PROTO_xns_idp = 0o026;
173pub const PROTO_rdp = 0o033;
174pub const PROTO_iso_tp4 = 0o035;
175pub const PROTO_xtp = 0o044;
176pub const PROTO_ddp = 0o045;
177pub const PROTO_idpr_cmtp = 0o046;
178pub const PROTO_ipv6 = 0o051;
179pub const PROTO_ipv6_route = 0o053;
180pub const PROTO_ipv6_frag = 0o054;
181pub const PROTO_idrp = 0o055;
182pub const PROTO_rsvp = 0o056;
183pub const PROTO_gre = 0o057;
184pub const PROTO_esp = 0o062;
185pub const PROTO_ah = 0o063;
186pub const PROTO_skip = 0o071;
187pub const PROTO_ipv6_icmp = 0o072;
188pub const PROTO_ipv6_nonxt = 0o073;
189pub const PROTO_ipv6_opts = 0o074;
190pub const PROTO_rspf = 0o111;
191pub const PROTO_vmtp = 0o121;
192pub const PROTO_ospf = 0o131;
193pub const PROTO_ipip = 0o136;
194pub const PROTO_encap = 0o142;
195pub const PROTO_pim = 0o147;
196pub const PROTO_raw = 0o377;
197
198pub const PF_UNSPEC = 0;
199pub const PF_LOCAL = 1;
200pub const PF_UNIX = PF_LOCAL;
201pub const PF_FILE = PF_LOCAL;
202pub const PF_INET = 2;
203pub const PF_AX25 = 3;
204pub const PF_IPX = 4;
205pub const PF_APPLETALK = 5;
206pub const PF_NETROM = 6;
207pub const PF_BRIDGE = 7;
208pub const PF_ATMPVC = 8;
209pub const PF_X25 = 9;
210pub const PF_INET6 = 10;
211pub const PF_ROSE = 11;
212pub const PF_DECnet = 12;
213pub const PF_NETBEUI = 13;
214pub const PF_SECURITY = 14;
215pub const PF_KEY = 15;
216pub const PF_NETLINK = 16;
217pub const PF_ROUTE = PF_NETLINK;
218pub const PF_PACKET = 17;
219pub const PF_ASH = 18;
220pub const PF_ECONET = 19;
221pub const PF_ATMSVC = 20;
222pub const PF_RDS = 21;
223pub const PF_SNA = 22;
224pub const PF_IRDA = 23;
225pub const PF_PPPOX = 24;
226pub const PF_WANPIPE = 25;
227pub const PF_LLC = 26;
228pub const PF_IB = 27;
229pub const PF_MPLS = 28;
230pub const PF_CAN = 29;
231pub const PF_TIPC = 30;
232pub const PF_BLUETOOTH = 31;
233pub const PF_IUCV = 32;
234pub const PF_RXRPC = 33;
235pub const PF_ISDN = 34;
236pub const PF_PHONET = 35;
237pub const PF_IEEE802154 = 36;
238pub const PF_CAIF = 37;
239pub const PF_ALG = 38;
240pub const PF_NFC = 39;
241pub const PF_VSOCK = 40;
242pub const PF_MAX = 41;
243
244pub const AF_UNSPEC = PF_UNSPEC;
245pub const AF_LOCAL = PF_LOCAL;
246pub const AF_UNIX = AF_LOCAL;
247pub const AF_FILE = AF_LOCAL;
248pub const AF_INET = PF_INET;
249pub const AF_AX25 = PF_AX25;
250pub const AF_IPX = PF_IPX;
251pub const AF_APPLETALK = PF_APPLETALK;
252pub const AF_NETROM = PF_NETROM;
253pub const AF_BRIDGE = PF_BRIDGE;
254pub const AF_ATMPVC = PF_ATMPVC;
255pub const AF_X25 = PF_X25;
256pub const AF_INET6 = PF_INET6;
257pub const AF_ROSE = PF_ROSE;
258pub const AF_DECnet = PF_DECnet;
259pub const AF_NETBEUI = PF_NETBEUI;
260pub const AF_SECURITY = PF_SECURITY;
261pub const AF_KEY = PF_KEY;
262pub const AF_NETLINK = PF_NETLINK;
263pub const AF_ROUTE = PF_ROUTE;
264pub const AF_PACKET = PF_PACKET;
265pub const AF_ASH = PF_ASH;
266pub const AF_ECONET = PF_ECONET;
267pub const AF_ATMSVC = PF_ATMSVC;
268pub const AF_RDS = PF_RDS;
269pub const AF_SNA = PF_SNA;
270pub const AF_IRDA = PF_IRDA;
271pub const AF_PPPOX = PF_PPPOX;
272pub const AF_WANPIPE = PF_WANPIPE;
273pub const AF_LLC = PF_LLC;
274pub const AF_IB = PF_IB;
275pub const AF_MPLS = PF_MPLS;
276pub const AF_CAN = PF_CAN;
277pub const AF_TIPC = PF_TIPC;
278pub const AF_BLUETOOTH = PF_BLUETOOTH;
279pub const AF_IUCV = PF_IUCV;
280pub const AF_RXRPC = PF_RXRPC;
281pub const AF_ISDN = PF_ISDN;
282pub const AF_PHONET = PF_PHONET;
283pub const AF_IEEE802154 = PF_IEEE802154;
284pub const AF_CAIF = PF_CAIF;
285pub const AF_ALG = PF_ALG;
286pub const AF_NFC = PF_NFC;
287pub const AF_VSOCK = PF_VSOCK;
288pub const AF_MAX = PF_MAX;
289
290pub const DT_UNKNOWN = 0;
291pub const DT_FIFO = 1;
292pub const DT_CHR = 2;
293pub const DT_DIR = 4;
294pub const DT_BLK = 6;
295pub const DT_REG = 8;
296pub const DT_LNK = 10;
297pub const DT_SOCK = 12;
298pub const DT_WHT = 14;
299
300/// add event to kq (implies enable)
301pub const EV_ADD = 0x0001;
302
303/// delete event from kq
304pub const EV_DELETE = 0x0002;
305
306/// enable event
307pub const EV_ENABLE = 0x0004;
308
309/// disable event (not reported)
310pub const EV_DISABLE = 0x0008;
311
312/// only report one occurrence
313pub const EV_ONESHOT = 0x0010;
314
315/// clear event state after reporting
316pub 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
322pub const EV_RECEIPT = 0x0040;
323
324/// disable event after reporting
325pub const EV_DISPATCH = 0x0080;
326
327pub const EVFILT_READ = -1;
328pub const EVFILT_WRITE = -2;
329
330/// attached to aio requests
331pub const EVFILT_AIO = -3;
332
333/// attached to vnodes
334pub const EVFILT_VNODE = -4;
335
336/// attached to struct proc
337pub const EVFILT_PROC = -5;
338
339/// attached to struct proc
340pub const EVFILT_SIGNAL = -6;
341
342/// timers
343pub const EVFILT_TIMER = -7;
344
345/// Process descriptors
346pub const EVFILT_PROCDESC = -8;
347
348/// Filesystem events
349pub const EVFILT_FS = -9;
350
351pub const EVFILT_LIO = -10;
352
353/// User events
354pub const EVFILT_USER = -11;
355
356/// Sendfile events
357pub const EVFILT_SENDFILE = -12;
358
359pub const EVFILT_EMPTY = -13;
360
361/// On input, NOTE_TRIGGER causes the event to be triggered for output.
362pub const NOTE_TRIGGER = 0x01000000;
363
364/// ignore input fflags
365pub const NOTE_FFNOP = 0x00000000;
366
367/// and fflags
368pub const NOTE_FFAND = 0x40000000;
369
370/// or fflags
371pub const NOTE_FFOR = 0x80000000;
372
373/// copy fflags
374pub const NOTE_FFCOPY = 0xc0000000;
375
376/// mask for operations
377pub const NOTE_FFCTRLMASK = 0xc0000000;
378pub const NOTE_FFLAGSMASK = 0x00ffffff;
379
380/// low water mark
381pub const NOTE_LOWAT = 0x00000001;
382
383/// behave like poll()
384pub const NOTE_FILE_POLL = 0x00000002;
385
386/// vnode was removed
387pub const NOTE_DELETE = 0x00000001;
388
389/// data contents changed
390pub const NOTE_WRITE = 0x00000002;
391
392/// size increased
393pub const NOTE_EXTEND = 0x00000004;
394
395/// attributes changed
396pub const NOTE_ATTRIB = 0x00000008;
397
398/// link count changed
399pub const NOTE_LINK = 0x00000010;
400
401/// vnode was renamed
402pub const NOTE_RENAME = 0x00000020;
403
404/// vnode access was revoked
405pub const NOTE_REVOKE = 0x00000040;
406
407/// vnode was opened
408pub const NOTE_OPEN = 0x00000080;
409
410/// file closed, fd did not allow write
411pub const NOTE_CLOSE = 0x00000100;
412
413/// file closed, fd did allow write
414pub const NOTE_CLOSE_WRITE = 0x00000200;
415
416/// file was read
417pub const NOTE_READ = 0x00000400;
418
419/// process exited
420pub const NOTE_EXIT = 0x80000000;
421
422/// process forked
423pub const NOTE_FORK = 0x40000000;
424
425/// process exec'd
426pub const NOTE_EXEC = 0x20000000;
427
428/// mask for signal & exit status
429pub const NOTE_PDATAMASK = 0x000fffff;
430pub const NOTE_PCTRLMASK = (~NOTE_PDATAMASK);
431
432/// data is seconds
433pub const NOTE_SECONDS = 0x00000001;
434
435/// data is milliseconds
436pub const NOTE_MSECONDS = 0x00000002;
437
438/// data is microseconds
439pub const NOTE_USECONDS = 0x00000004;
440
441/// data is nanoseconds
442pub const NOTE_NSECONDS = 0x00000008;
443
444/// timeout is absolute
445pub const NOTE_ABSTIME = 0x00000010;
446
447pub const TCGETS = 0x5401;
448pub const TCSETS = 0x5402;
449pub const TCSETSW = 0x5403;
450pub const TCSETSF = 0x5404;
451pub const TCGETA = 0x5405;
452pub const TCSETA = 0x5406;
453pub const TCSETAW = 0x5407;
454pub const TCSETAF = 0x5408;
455pub const TCSBRK = 0x5409;
456pub const TCXONC = 0x540A;
457pub const TCFLSH = 0x540B;
458pub const TIOCEXCL = 0x540C;
459pub const TIOCNXCL = 0x540D;
460pub const TIOCSCTTY = 0x540E;
461pub const TIOCGPGRP = 0x540F;
462pub const TIOCSPGRP = 0x5410;
463pub const TIOCOUTQ = 0x5411;
464pub const TIOCSTI = 0x5412;
465pub const TIOCGWINSZ = 0x5413;
466pub const TIOCSWINSZ = 0x5414;
467pub const TIOCMGET = 0x5415;
468pub const TIOCMBIS = 0x5416;
469pub const TIOCMBIC = 0x5417;
470pub const TIOCMSET = 0x5418;
471pub const TIOCGSOFTCAR = 0x5419;
472pub const TIOCSSOFTCAR = 0x541A;
473pub const FIONREAD = 0x541B;
474pub const TIOCINQ = FIONREAD;
475pub const TIOCLINUX = 0x541C;
476pub const TIOCCONS = 0x541D;
477pub const TIOCGSERIAL = 0x541E;
478pub const TIOCSSERIAL = 0x541F;
479pub const TIOCPKT = 0x5420;
480pub const FIONBIO = 0x5421;
481pub const TIOCNOTTY = 0x5422;
482pub const TIOCSETD = 0x5423;
483pub const TIOCGETD = 0x5424;
484pub const TCSBRKP = 0x5425;
485pub const TIOCSBRK = 0x5427;
486pub const TIOCCBRK = 0x5428;
487pub const TIOCGSID = 0x5429;
488pub const TIOCGRS485 = 0x542E;
489pub const TIOCSRS485 = 0x542F;
490pub const TIOCGPTN = 0x80045430;
491pub const TIOCSPTLCK = 0x40045431;
492pub const TIOCGDEV = 0x80045432;
493pub const TCGETX = 0x5432;
494pub const TCSETX = 0x5433;
495pub const TCSETXF = 0x5434;
496pub const TCSETXW = 0x5435;
497pub const TIOCSIG = 0x40045436;
498pub const TIOCVHANGUP = 0x5437;
499pub const TIOCGPKT = 0x80045438;
500pub const TIOCGPTLCK = 0x80045439;
501pub const TIOCGEXCL = 0x80045440;
502
503fn unsigned(s: i32) u32 {
504 return @bitCast(u32, s);
505}
506fn signed(s: u32) i32 {
507 return @bitCast(i32, s);
508}
509pub fn WEXITSTATUS(s: i32) i32 {
510 return signed((unsigned(s) & 0xff00) >> 8);
511}
512pub fn WTERMSIG(s: i32) i32 {
513 return signed(unsigned(s) & 0x7f);
514}
515pub fn WSTOPSIG(s: i32) i32 {
516 return WEXITSTATUS(s);
517}
518pub fn WIFEXITED(s: i32) bool {
519 return WTERMSIG(s) == 0;
520}
521pub fn WIFSTOPPED(s: i32) bool {
522 return @intCast(u16, (((unsigned(s) & 0xffff) *% 0x10001) >> 8)) > 0x7f00;
523}
524pub fn WIFSIGNALED(s: i32) bool {
525 return (unsigned(s) & 0xffff) -% 1 < 0xff;
526}
527
528pub 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.
536pub 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
541pub fn dup2(old: i32, new: i32) usize {
542 return arch.syscall2(SYS_dup2, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)));
543}
544
545pub fn chdir(path: [*]const u8) usize {
546 return arch.syscall1(SYS_chdir, @ptrToInt(path));
547}
548
549pub 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
553pub fn fork() usize {
554 return arch.syscall0(SYS_fork);
555}
556
557pub fn getcwd(buf: [*]u8, size: usize) usize {
558 return arch.syscall2(SYS___getcwd, @ptrToInt(buf), size);
559}
560
561pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize {
562 return arch.syscall3(SYS_getdents, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count);
563}
564
565pub 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
570pub 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
574pub fn mkdir(path: [*]const u8, mode: u32) usize {
575 return arch.syscall2(SYS_mkdir, @ptrToInt(path), mode);
576}
577
578pub 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
582pub fn munmap(address: usize, length: usize) usize {
583 return arch.syscall2(SYS_munmap, address, length);
584}
585
586pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
587 return arch.syscall3(SYS_read, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
588}
589
590pub fn rmdir(path: [*]const u8) usize {
591 return arch.syscall1(SYS_rmdir, @ptrToInt(path));
592}
593
594pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
595 return arch.syscall2(SYS_symlink, @ptrToInt(existing), @ptrToInt(new));
596}
597
598pub 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
602pub 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
606pub fn pipe(fd: *[2]i32) usize {
607 return pipe2(fd, 0);
608}
609
610pub fn pipe2(fd: *[2]i32, flags: usize) usize {
611 return arch.syscall2(SYS_pipe2, @ptrToInt(fd), flags);
612}
613
614pub 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
618pub 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
622pub 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
626pub fn rename(old: [*]const u8, new: [*]const u8) usize {
627 return arch.syscall2(SYS_rename, @ptrToInt(old), @ptrToInt(new));
628}
629
630pub fn open(path: [*]const u8, flags: u32, perm: usize) usize {
631 return arch.syscall3(SYS_open, @ptrToInt(path), flags, perm);
632}
633
634pub fn create(path: [*]const u8, perm: usize) usize {
635 return arch.syscall2(SYS_creat, @ptrToInt(path), perm);
636}
637
638pub 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
642pub fn close(fd: i32) usize {
643 return arch.syscall1(SYS_close, @bitCast(usize, isize(fd)));
644}
645
646pub 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
650pub fn exit(status: i32) noreturn {
651 _ = arch.syscall1(SYS_exit, @bitCast(usize, isize(status)));
652 unreachable;
653}
654
655pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
656 return arch.syscall3(SYS_getrandom, @ptrToInt(buf), count, usize(flags));
657}
658
659pub fn kill(pid: i32, sig: i32) usize {
660 return arch.syscall2(SYS_kill, @bitCast(usize, isize(pid)), @bitCast(usize, isize(sig)));
661}
662
663pub fn unlink(path: [*]const u8) usize {
664 return arch.syscall1(SYS_unlink, @ptrToInt(path));
665}
666
667pub 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
671pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize {
672 return arch.syscall2(SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem));
673}
674
675pub fn setuid(uid: u32) usize {
676 return arch.syscall1(SYS_setuid, uid);
677}
678
679pub fn setgid(gid: u32) usize {
680 return arch.syscall1(SYS_setgid, gid);
681}
682
683pub fn setreuid(ruid: u32, euid: u32) usize {
684 return arch.syscall2(SYS_setreuid, ruid, euid);
685}
686
687pub fn setregid(rgid: u32, egid: u32) usize {
688 return arch.syscall2(SYS_setregid, rgid, egid);
689}
690
691const NSIG = 32;
692
693pub const SIG_ERR = @intToPtr(extern fn (i32) void, maxInt(usize));
694pub const SIG_DFL = @intToPtr(extern fn (i32) void, 0);
695pub const SIG_IGN = @intToPtr(extern fn (i32) void, 1);
696
697/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
698pub 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
712pub const _SIG_WORDS = 4;
713pub const _SIG_MAXSIG = 128;
714
715pub inline fn _SIG_IDX(sig: usize) usize {
716 return sig - 1;
717}
718pub inline fn _SIG_WORD(sig: usize) usize {
719 return_SIG_IDX(sig) >> 5;
720}
721pub inline fn _SIG_BIT(sig: usize) usize {
722 return 1 << (_SIG_IDX(sig) & 31);
723}
724pub inline fn _SIG_VALID(sig: usize) usize {
725 return sig <= _SIG_MAXSIG and sig > 0;
726}
727
728pub const sigset_t = extern struct {
729 __bits: [_SIG_WORDS]u32,
730};
731
732pub 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
745pub const Stat = arch.Stat;
746pub const timespec = arch.timespec;
747
748pub fn fstat(fd: i32, stat_buf: *Stat) usize {
749 return arch.syscall2(SYS_fstat, @bitCast(usize, isize(fd)), @ptrToInt(stat_buf));
750}
751
752pub const iovec = extern struct {
753 iov_base: [*]u8,
754 iov_len: usize,
755};
756
757pub const iovec_const = extern struct {
758 iov_base: [*]const u8,
759 iov_len: usize,
760};
761
762// TODO avoid libc dependency
763pub fn kqueue() usize {
764 return errnoWrap(c.kqueue());
765}
766
767// TODO avoid libc dependency
768pub 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
780pub 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
785pub 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
790pub 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.
799fn 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 @@
1pub const SYS_syscall = 0;
2pub const SYS_exit = 1;
3pub const SYS_fork = 2;
4pub const SYS_read = 3;
5pub const SYS_write = 4;
6pub const SYS_open = 5;
7pub const SYS_close = 6;
8pub const SYS_wait4 = 7;
9// 8 is old creat
10pub const SYS_link = 9;
11pub const SYS_unlink = 10;
12// 11 is obsolete execv
13pub const SYS_chdir = 12;
14pub const SYS_fchdir = 13;
15pub const SYS_freebsd11_mknod = 14;
16pub const SYS_chmod = 15;
17pub const SYS_chown = 16;
18pub const SYS_break = 17;
19// 18 is freebsd4 getfsstat
20// 19 is old lseek
21pub const SYS_getpid = 20;
22pub const SYS_mount = 21;
23pub const SYS_unmount = 22;
24pub const SYS_setuid = 23;
25pub const SYS_getuid = 24;
26pub const SYS_geteuid = 25;
27pub const SYS_ptrace = 26;
28pub const SYS_recvmsg = 27;
29pub const SYS_sendmsg = 28;
30pub const SYS_recvfrom = 29;
31pub const SYS_accept = 30;
32pub const SYS_getpeername = 31;
33pub const SYS_getsockname = 32;
34pub const SYS_access = 33;
35pub const SYS_chflags = 34;
36pub const SYS_fchflags = 35;
37pub const SYS_sync = 36;
38pub const SYS_kill = 37;
39// 38 is old stat
40pub const SYS_getppid = 39;
41// 40 is old lstat
42pub const SYS_dup = 41;
43pub const SYS_freebsd10_pipe = 42;
44pub const SYS_getegid = 43;
45pub const SYS_profil = 44;
46pub const SYS_ktrace = 45;
47// 46 is old sigaction
48pub const SYS_getgid = 47;
49// 48 is old sigprocmask
50pub const SYS_getlogin = 49;
51pub const SYS_setlogin = 50;
52pub const SYS_acct = 51;
53// 52 is old sigpending
54pub const SYS_sigaltstack = 53;
55pub const SYS_ioctl = 54;
56pub const SYS_reboot = 55;
57pub const SYS_revoke = 56;
58pub const SYS_symlink = 57;
59pub const SYS_readlink = 58;
60pub const SYS_execve = 59;
61pub const SYS_umask = 60;
62pub const SYS_chroot = 61;
63// 62 is old fstat
64// 63 is old getkerninfo
65// 64 is old getpagesize
66pub const SYS_msync = 65;
67pub const SYS_vfork = 66;
68// 67 is obsolete vread
69// 68 is obsolete vwrite
70// 69 is obsolete sbrk (still present on some platforms)
71pub const SYS_sstk = 70;
72// 71 is old mmap
73pub const SYS_vadvise = 72;
74pub const SYS_munmap = 73;
75pub const SYS_mprotect = 74;
76pub const SYS_madvise = 75;
77// 76 is obsolete vhangup
78// 77 is obsolete vlimit
79pub const SYS_mincore = 78;
80pub const SYS_getgroups = 79;
81pub const SYS_setgroups = 80;
82pub const SYS_getpgrp = 81;
83pub const SYS_setpgid = 82;
84pub const SYS_setitimer = 83;
85// 84 is old wait
86pub const SYS_swapon = 85;
87pub const SYS_getitimer = 86;
88// 87 is old gethostname
89// 88 is old sethostname
90pub const SYS_getdtablesize = 89;
91pub const SYS_dup2 = 90;
92pub const SYS_fcntl = 92;
93pub const SYS_select = 93;
94pub const SYS_fsync = 95;
95pub const SYS_setpriority = 96;
96pub const SYS_socket = 97;
97pub const SYS_connect = 98;
98// 99 is old accept
99pub const SYS_getpriority = 100;
100// 101 is old send
101// 102 is old recv
102// 103 is old sigreturn
103pub const SYS_bind = 104;
104pub const SYS_setsockopt = 105;
105pub 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
115pub const SYS_gettimeofday = 116;
116pub const SYS_getrusage = 117;
117pub const SYS_getsockopt = 118;
118pub const SYS_readv = 120;
119pub const SYS_writev = 121;
120pub const SYS_settimeofday = 122;
121pub const SYS_fchown = 123;
122pub const SYS_fchmod = 124;
123// 125 is old recvfrom
124pub const SYS_setreuid = 126;
125pub const SYS_setregid = 127;
126pub const SYS_rename = 128;
127// 129 is old truncate
128// 130 is old ftruncate
129pub const SYS_flock = 131;
130pub const SYS_mkfifo = 132;
131pub const SYS_sendto = 133;
132pub const SYS_shutdown = 134;
133pub const SYS_socketpair = 135;
134pub const SYS_mkdir = 136;
135pub const SYS_rmdir = 137;
136pub const SYS_utimes = 138;
137// 139 is obsolete 4.2 sigreturn
138pub 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
145pub const SYS_setsid = 147;
146pub const SYS_quotactl = 148;
147// 149 is old quota
148// 150 is old getsockname
149pub const SYS_nlm_syscall = 154;
150pub const SYS_nfssvc = 155;
151// 156 is old getdirentries
152// 157 is freebsd4 statfs
153// 158 is freebsd4 fstatfs
154pub const SYS_lgetfh = 160;
155pub const SYS_getfh = 161;
156// 162 is freebsd4 getdomainname
157// 163 is freebsd4 setdomainname
158// 164 is freebsd4 uname
159pub const SYS_sysarch = 165;
160pub const SYS_rtprio = 166;
161pub const SYS_semsys = 169;
162pub const SYS_msgsys = 170;
163pub const SYS_shmsys = 171;
164// 173 is freebsd6 pread
165// 174 is freebsd6 pwrite
166pub const SYS_setfib = 175;
167pub const SYS_ntp_adjtime = 176;
168pub const SYS_setgid = 181;
169pub const SYS_setegid = 182;
170pub 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
175pub const SYS_freebsd11_stat = 188;
176pub const SYS_freebsd11_fstat = 189;
177pub const SYS_freebsd11_lstat = 190;
178pub const SYS_pathconf = 191;
179pub const SYS_fpathconf = 192;
180pub const SYS_getrlimit = 194;
181pub const SYS_setrlimit = 195;
182pub const SYS_freebsd11_getdirentries = 196;
183// 197 is freebsd6 mmap
184pub const SYS___syscall = 198;
185// 199 is freebsd6 lseek
186// 200 is freebsd6 truncate
187// 201 is freebsd6 ftruncate
188pub const SYS___sysctl = 202;
189pub const SYS_mlock = 203;
190pub const SYS_munlock = 204;
191pub const SYS_undelete = 205;
192pub const SYS_futimes = 206;
193pub const SYS_getpgid = 207;
194pub const SYS_poll = 209;
195pub const SYS_freebsd7___semctl = 220;
196pub const SYS_semget = 221;
197pub const SYS_semop = 222;
198pub const SYS_freebsd7_msgctl = 224;
199pub const SYS_msgget = 225;
200pub const SYS_msgsnd = 226;
201pub const SYS_msgrcv = 227;
202pub const SYS_shmat = 228;
203pub const SYS_freebsd7_shmctl = 229;
204pub const SYS_shmdt = 230;
205pub const SYS_shmget = 231;
206pub const SYS_clock_gettime = 232;
207pub const SYS_clock_settime = 233;
208pub const SYS_clock_getres = 234;
209pub const SYS_ktimer_create = 235;
210pub const SYS_ktimer_delete = 236;
211pub const SYS_ktimer_settime = 237;
212pub const SYS_ktimer_gettime = 238;
213pub const SYS_ktimer_getoverrun = 239;
214pub const SYS_nanosleep = 240;
215pub const SYS_ffclock_getcounter = 241;
216pub const SYS_ffclock_setestimate = 242;
217pub const SYS_ffclock_getestimate = 243;
218pub const SYS_clock_nanosleep = 244;
219pub const SYS_clock_getcpuclockid2 = 247;
220pub const SYS_ntp_gettime = 248;
221pub const SYS_minherit = 250;
222pub const SYS_rfork = 251;
223// 252 is obsolete openbsd_poll
224pub const SYS_issetugid = 253;
225pub const SYS_lchown = 254;
226pub const SYS_aio_read = 255;
227pub const SYS_aio_write = 256;
228pub const SYS_lio_listio = 257;
229pub const SYS_freebsd11_getdents = 272;
230pub const SYS_lchmod = 274;
231// 275 is obsolete netbsd_lchown
232pub const SYS_lutimes = 276;
233// 277 is obsolete netbsd_msync
234pub const SYS_freebsd11_nstat = 278;
235pub const SYS_freebsd11_nfstat = 279;
236pub const SYS_freebsd11_nlstat = 280;
237pub const SYS_preadv = 289;
238pub const SYS_pwritev = 290;
239// 297 is freebsd4 fhstatfs
240pub const SYS_fhopen = 298;
241pub const SYS_freebsd11_fhstat = 299;
242pub const SYS_modnext = 300;
243pub const SYS_modstat = 301;
244pub const SYS_modfnext = 302;
245pub const SYS_modfind = 303;
246pub const SYS_kldload = 304;
247pub const SYS_kldunload = 305;
248pub const SYS_kldfind = 306;
249pub const SYS_kldnext = 307;
250pub const SYS_kldstat = 308;
251pub const SYS_kldfirstmod = 309;
252pub const SYS_getsid = 310;
253pub const SYS_setresuid = 311;
254pub const SYS_setresgid = 312;
255// 313 is obsolete signanosleep
256pub const SYS_aio_return = 314;
257pub const SYS_aio_suspend = 315;
258pub const SYS_aio_cancel = 316;
259pub const SYS_aio_error = 317;
260// 318 is freebsd6 aio_read
261// 319 is freebsd6 aio_write
262// 320 is freebsd6 lio_listio
263pub const SYS_yield = 321;
264// 322 is obsolete thr_sleep
265// 323 is obsolete thr_wakeup
266pub const SYS_mlockall = 324;
267pub const SYS_munlockall = 325;
268pub const SYS___getcwd = 326;
269pub const SYS_sched_setparam = 327;
270pub const SYS_sched_getparam = 328;
271pub const SYS_sched_setscheduler = 329;
272pub const SYS_sched_getscheduler = 330;
273pub const SYS_sched_yield = 331;
274pub const SYS_sched_get_priority_max = 332;
275pub const SYS_sched_get_priority_min = 333;
276pub const SYS_sched_rr_get_interval = 334;
277pub const SYS_utrace = 335;
278// 336 is freebsd4 sendfile
279pub const SYS_kldsym = 337;
280pub const SYS_jail = 338;
281pub const SYS_nnpfs_syscall = 339;
282pub const SYS_sigprocmask = 340;
283pub const SYS_sigsuspend = 341;
284// 342 is freebsd4 sigaction
285pub const SYS_sigpending = 343;
286// 344 is freebsd4 sigreturn
287pub const SYS_sigtimedwait = 345;
288pub const SYS_sigwaitinfo = 346;
289pub const SYS___acl_get_file = 347;
290pub const SYS___acl_set_file = 348;
291pub const SYS___acl_get_fd = 349;
292pub const SYS___acl_set_fd = 350;
293pub const SYS___acl_delete_file = 351;
294pub const SYS___acl_delete_fd = 352;
295pub const SYS___acl_aclcheck_file = 353;
296pub const SYS___acl_aclcheck_fd = 354;
297pub const SYS_extattrctl = 355;
298pub const SYS_extattr_set_file = 356;
299pub const SYS_extattr_get_file = 357;
300pub const SYS_extattr_delete_file = 358;
301pub const SYS_aio_waitcomplete = 359;
302pub const SYS_getresuid = 360;
303pub const SYS_getresgid = 361;
304pub const SYS_kqueue = 362;
305pub 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
312pub const SYS_extattr_set_fd = 371;
313pub const SYS_extattr_get_fd = 372;
314pub const SYS_extattr_delete_fd = 373;
315pub const SYS___setugid = 374;
316pub const SYS_eaccess = 376;
317pub const SYS_afs3_syscall = 377;
318pub 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
324pub const SYS___mac_get_proc = 384;
325pub const SYS___mac_set_proc = 385;
326pub const SYS___mac_get_fd = 386;
327pub const SYS___mac_get_file = 387;
328pub const SYS___mac_set_fd = 388;
329pub const SYS___mac_set_file = 389;
330pub const SYS_kenv = 390;
331pub const SYS_lchflags = 391;
332pub const SYS_uuidgen = 392;
333pub const SYS_sendfile = 393;
334pub const SYS_mac_syscall = 394;
335pub const SYS_freebsd11_getfsstat = 395;
336pub const SYS_freebsd11_statfs = 396;
337pub const SYS_freebsd11_fstatfs = 397;
338pub const SYS_freebsd11_fhstatfs = 398;
339pub const SYS_ksem_close = 400;
340pub const SYS_ksem_post = 401;
341pub const SYS_ksem_wait = 402;
342pub const SYS_ksem_trywait = 403;
343pub const SYS_ksem_init = 404;
344pub const SYS_ksem_open = 405;
345pub const SYS_ksem_unlink = 406;
346pub const SYS_ksem_getvalue = 407;
347pub const SYS_ksem_destroy = 408;
348pub const SYS___mac_get_pid = 409;
349pub const SYS___mac_get_link = 410;
350pub const SYS___mac_set_link = 411;
351pub const SYS_extattr_set_link = 412;
352pub const SYS_extattr_get_link = 413;
353pub const SYS_extattr_delete_link = 414;
354pub const SYS___mac_execve = 415;
355pub const SYS_sigaction = 416;
356pub const SYS_sigreturn = 417;
357pub const SYS_getcontext = 421;
358pub const SYS_setcontext = 422;
359pub const SYS_swapcontext = 423;
360pub const SYS_swapoff = 424;
361pub const SYS___acl_get_link = 425;
362pub const SYS___acl_set_link = 426;
363pub const SYS___acl_delete_link = 427;
364pub const SYS___acl_aclcheck_link = 428;
365pub const SYS_sigwait = 429;
366pub const SYS_thr_create = 430;
367pub const SYS_thr_exit = 431;
368pub const SYS_thr_self = 432;
369pub const SYS_thr_kill = 433;
370pub const SYS_jail_attach = 436;
371pub const SYS_extattr_list_fd = 437;
372pub const SYS_extattr_list_file = 438;
373pub const SYS_extattr_list_link = 439;
374// 440 is obsolete kse_switchin
375pub const SYS_ksem_timedwait = 441;
376pub const SYS_thr_suspend = 442;
377pub const SYS_thr_wake = 443;
378pub const SYS_kldunloadf = 444;
379pub const SYS_audit = 445;
380pub const SYS_auditon = 446;
381pub const SYS_getauid = 447;
382pub const SYS_setauid = 448;
383pub const SYS_getaudit = 449;
384pub const SYS_setaudit = 450;
385pub const SYS_getaudit_addr = 451;
386pub const SYS_setaudit_addr = 452;
387pub const SYS_auditctl = 453;
388pub const SYS__umtx_op = 454;
389pub const SYS_thr_new = 455;
390pub const SYS_sigqueue = 456;
391pub const SYS_kmq_open = 457;
392pub const SYS_kmq_setattr = 458;
393pub const SYS_kmq_timedreceive = 459;
394pub const SYS_kmq_timedsend = 460;
395pub const SYS_kmq_notify = 461;
396pub const SYS_kmq_unlink = 462;
397pub const SYS_abort2 = 463;
398pub const SYS_thr_set_name = 464;
399pub const SYS_aio_fsync = 465;
400pub const SYS_rtprio_thread = 466;
401pub const SYS_sctp_peeloff = 471;
402pub const SYS_sctp_generic_sendmsg = 472;
403pub const SYS_sctp_generic_sendmsg_iov = 473;
404pub const SYS_sctp_generic_recvmsg = 474;
405pub const SYS_pread = 475;
406pub const SYS_pwrite = 476;
407pub const SYS_mmap = 477;
408pub const SYS_lseek = 478;
409pub const SYS_truncate = 479;
410pub const SYS_ftruncate = 480;
411pub const SYS_thr_kill2 = 481;
412pub const SYS_shm_open = 482;
413pub const SYS_shm_unlink = 483;
414pub const SYS_cpuset = 484;
415pub const SYS_cpuset_setid = 485;
416pub const SYS_cpuset_getid = 486;
417pub const SYS_cpuset_getaffinity = 487;
418pub const SYS_cpuset_setaffinity = 488;
419pub const SYS_faccessat = 489;
420pub const SYS_fchmodat = 490;
421pub const SYS_fchownat = 491;
422pub const SYS_fexecve = 492;
423pub const SYS_freebsd11_fstatat = 493;
424pub const SYS_futimesat = 494;
425pub const SYS_linkat = 495;
426pub const SYS_mkdirat = 496;
427pub const SYS_mkfifoat = 497;
428pub const SYS_freebsd11_mknodat = 498;
429pub const SYS_openat = 499;
430pub const SYS_readlinkat = 500;
431pub const SYS_renameat = 501;
432pub const SYS_symlinkat = 502;
433pub const SYS_unlinkat = 503;
434pub const SYS_posix_openpt = 504;
435pub const SYS_gssd_syscall = 505;
436pub const SYS_jail_get = 506;
437pub const SYS_jail_set = 507;
438pub const SYS_jail_remove = 508;
439pub const SYS_closefrom = 509;
440pub const SYS___semctl = 510;
441pub const SYS_msgctl = 511;
442pub const SYS_shmctl = 512;
443pub const SYS_lpathconf = 513;
444// 514 is obsolete cap_new
445pub const SYS___cap_rights_get = 515;
446pub const SYS_cap_enter = 516;
447pub const SYS_cap_getmode = 517;
448pub const SYS_pdfork = 518;
449pub const SYS_pdkill = 519;
450pub const SYS_pdgetpid = 520;
451pub const SYS_pselect = 522;
452pub const SYS_getloginclass = 523;
453pub const SYS_setloginclass = 524;
454pub const SYS_rctl_get_racct = 525;
455pub const SYS_rctl_get_rules = 526;
456pub const SYS_rctl_get_limits = 527;
457pub const SYS_rctl_add_rule = 528;
458pub const SYS_rctl_remove_rule = 529;
459pub const SYS_posix_fallocate = 530;
460pub const SYS_posix_fadvise = 531;
461pub const SYS_wait6 = 532;
462pub const SYS_cap_rights_limit = 533;
463pub const SYS_cap_ioctls_limit = 534;
464pub const SYS_cap_ioctls_get = 535;
465pub const SYS_cap_fcntls_limit = 536;
466pub const SYS_cap_fcntls_get = 537;
467pub const SYS_bindat = 538;
468pub const SYS_connectat = 539;
469pub const SYS_chflagsat = 540;
470pub const SYS_accept4 = 541;
471pub const SYS_pipe2 = 542;
472pub const SYS_aio_mlock = 543;
473pub const SYS_procctl = 544;
474pub const SYS_ppoll = 545;
475pub const SYS_futimens = 546;
476pub const SYS_utimensat = 547;
477// 548 is obsolete numa_getaffinity
478// 549 is obsolete numa_setaffinity
479pub const SYS_fdatasync = 550;
480pub const SYS_fstat = 551;
481pub const SYS_fstatat = 552;
482pub const SYS_fhstat = 553;
483pub const SYS_getdirentries = 554;
484pub const SYS_statfs = 555;
485pub const SYS_fstatfs = 556;
486pub const SYS_getfsstat = 557;
487pub const SYS_fhstatfs = 558;
488pub const SYS_mknodat = 559;
489pub const SYS_kevent = 560;
490pub const SYS_cpuset_getdomain = 561;
491pub const SYS_cpuset_setdomain = 562;
492pub const SYS_getrandom = 563;
493pub const SYS_MAXSYSCALL = 564;
std/os/freebsd/x86_64.zig created+136
...@@ -0,0 +1,136 @@
1const freebsd = @import("index.zig");
2const socklen_t = freebsd.socklen_t;
3const iovec = freebsd.iovec;
4
5pub const SYS_sbrk = 69;
6
7pub fn syscall0(number: usize) usize {
8 return asm volatile ("syscall"
9 : [ret] "={rax}" (-> usize)
10 : [number] "{rax}" (number)
11 : "rcx", "r11"
12 );
13}
14
15pub 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
24pub 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
34pub 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
45pub 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
57pub 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
70pub 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
92pub nakedcc fn restore_rt() void {
93 asm volatile ("syscall"
94 :
95 : [number] "{rax}" (usize(SYS_rt_sigreturn))
96 : "rcx", "r11"
97 );
98}
99
100pub 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.
113pub 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
133pub const timespec = extern struct {
134 tv_sec: isize,
135 tv_nsec: isize,
136};
std/os/get_app_data_dir.zig+1-1
...@@ -43,7 +43,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD...@@ -43,7 +43,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD
43 };43 };
44 return os.path.join(allocator, home_dir, "Library", "Application Support", appname);44 return os.path.join(allocator, home_dir, "Library", "Application Support", appname);
45 },45 },
46 builtin.Os.linux => {46 builtin.Os.linux, builtin.Os.freebsd => {
47 const home_dir = os.getEnvPosix("HOME") orelse {47 const home_dir = os.getEnvPosix("HOME") orelse {
48 // TODO look in /etc/passwd48 // TODO look in /etc/passwd
49 return error.AppDataDirUnavailable;49 return error.AppDataDirUnavailable;
std/os/get_user_id.zig+1-1
...@@ -11,7 +11,7 @@ pub const UserInfo = struct {...@@ -11,7 +11,7 @@ pub const UserInfo = struct {
11/// POSIX function which gets a uid from username.11/// POSIX function which gets a uid from username.
12pub fn getUserInfo(name: []const u8) !UserInfo {12pub fn getUserInfo(name: []const u8) !UserInfo {
13 return switch (builtin.os) {13 return switch (builtin.os) {
14 Os.linux, Os.macosx, Os.ios => posixGetUserInfo(name),14 Os.linux, Os.macosx, Os.ios, Os.freebsd => posixGetUserInfo(name),
15 else => @compileError("Unsupported OS"),15 else => @compileError("Unsupported OS"),
16 };16 };
17}17}
std/os/index.zig+67-28
...@@ -3,7 +3,7 @@ const builtin = @import("builtin");...@@ -3,7 +3,7 @@ const builtin = @import("builtin");
3const Os = builtin.Os;3const Os = builtin.Os;
4const is_windows = builtin.os == Os.windows;4const is_windows = builtin.os == Os.windows;
5const is_posix = switch (builtin.os) {5const is_posix = switch (builtin.os) {
6 builtin.Os.linux, builtin.Os.macosx => true,6 builtin.Os.linux, builtin.Os.macosx, builtin.Os.freebsd => true,
7 else => false,7 else => false,
8};8};
9const os = @This();9const os = @This();
...@@ -24,10 +24,12 @@ test "std.os" {...@@ -24,10 +24,12 @@ test "std.os" {
24pub const windows = @import("windows/index.zig");24pub const windows = @import("windows/index.zig");
25pub const darwin = @import("darwin.zig");25pub const darwin = @import("darwin.zig");
26pub const linux = @import("linux/index.zig");26pub const linux = @import("linux/index.zig");
27pub const freebsd = @import("freebsd/index.zig");
27pub const zen = @import("zen.zig");28pub const zen = @import("zen.zig");
28pub const posix = switch (builtin.os) {29pub const posix = switch (builtin.os) {
29 Os.linux => linux,30 Os.linux => linux,
30 Os.macosx, Os.ios => darwin,31 Os.macosx, Os.ios => darwin,
32 Os.freebsd => freebsd,
31 Os.zen => zen,33 Os.zen => zen,
32 else => @compileError("Unsupported OS"),34 else => @compileError("Unsupported OS"),
33};35};
...@@ -40,7 +42,7 @@ pub const time = @import("time.zig");...@@ -40,7 +42,7 @@ pub const time = @import("time.zig");
4042
41pub const page_size = 4 * 1024;43pub const page_size = 4 * 1024;
42pub const MAX_PATH_BYTES = switch (builtin.os) {44pub const MAX_PATH_BYTES = switch (builtin.os) {
43 Os.linux, Os.macosx, Os.ios => posix.PATH_MAX,45 Os.linux, Os.macosx, Os.ios, Os.freebsd => posix.PATH_MAX,
44 // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.46 // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
45 // If it would require 4 UTF-8 bytes, then there would be a surrogate47 // If it would require 4 UTF-8 bytes, then there would be a surrogate
46 // pair in the UTF-16LE, and we (over)account 3 bytes for it that way.48 // pair in the UTF-16LE, and we (over)account 3 bytes for it that way.
...@@ -101,7 +103,7 @@ const math = std.math;...@@ -101,7 +103,7 @@ const math = std.math;
101/// library implementation.103/// library implementation.
102pub fn getRandomBytes(buf: []u8) !void {104pub fn getRandomBytes(buf: []u8) !void {
103 switch (builtin.os) {105 switch (builtin.os) {
104 Os.linux => while (true) {106 Os.linux, Os.freebsd => while (true) {
105 // TODO check libc version and potentially call c.getrandom.107 // TODO check libc version and potentially call c.getrandom.
106 // See #397108 // See #397
107 const errno = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0));109 const errno = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0));
...@@ -174,7 +176,7 @@ pub fn abort() noreturn {...@@ -174,7 +176,7 @@ pub fn abort() noreturn {
174 c.abort();176 c.abort();
175 }177 }
176 switch (builtin.os) {178 switch (builtin.os) {
177 Os.linux, Os.macosx, Os.ios => {179 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
178 _ = posix.raise(posix.SIGABRT);180 _ = posix.raise(posix.SIGABRT);
179 _ = posix.raise(posix.SIGKILL);181 _ = posix.raise(posix.SIGKILL);
180 while (true) {}182 while (true) {}
...@@ -196,7 +198,7 @@ pub fn exit(status: u8) noreturn {...@@ -196,7 +198,7 @@ pub fn exit(status: u8) noreturn {
196 c.exit(status);198 c.exit(status);
197 }199 }
198 switch (builtin.os) {200 switch (builtin.os) {
199 Os.linux, Os.macosx, Os.ios => {201 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
200 posix.exit(status);202 posix.exit(status);
201 },203 },
202 Os.windows => {204 Os.windows => {
...@@ -419,7 +421,7 @@ pub fn posix_pwritev(fd: i32, iov: [*]const posix.iovec_const, count: usize, off...@@ -419,7 +421,7 @@ pub fn posix_pwritev(fd: i32, iov: [*]const posix.iovec_const, count: usize, off
419 }421 }
420 }422 }
421 },423 },
422 builtin.Os.linux => while (true) {424 builtin.Os.linux, builtin.Os.freebsd => while (true) {
423 const rc = posix.pwritev(fd, iov, count, offset);425 const rc = posix.pwritev(fd, iov, count, offset);
424 const err = posix.getErrno(rc);426 const err = posix.getErrno(rc);
425 switch (err) {427 switch (err) {
...@@ -457,6 +459,7 @@ pub const PosixOpenError = error{...@@ -457,6 +459,7 @@ pub const PosixOpenError = error{
457 NoSpaceLeft,459 NoSpaceLeft,
458 NotDir,460 NotDir,
459 PathAlreadyExists,461 PathAlreadyExists,
462 DeviceBusy,
460463
461 /// See https://github.com/ziglang/zig/issues/1396464 /// See https://github.com/ziglang/zig/issues/1396
462 Unexpected,465 Unexpected,
...@@ -495,6 +498,7 @@ pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 {...@@ -495,6 +498,7 @@ pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 {
495 posix.ENOTDIR => return PosixOpenError.NotDir,498 posix.ENOTDIR => return PosixOpenError.NotDir,
496 posix.EPERM => return PosixOpenError.AccessDenied,499 posix.EPERM => return PosixOpenError.AccessDenied,
497 posix.EEXIST => return PosixOpenError.PathAlreadyExists,500 posix.EEXIST => return PosixOpenError.PathAlreadyExists,
501 posix.EBUSY => return PosixOpenError.DeviceBusy,
498 else => return unexpectedErrorPosix(err),502 else => return unexpectedErrorPosix(err),
499 }503 }
500 }504 }
...@@ -687,7 +691,7 @@ pub fn getBaseAddress() usize {...@@ -687,7 +691,7 @@ pub fn getBaseAddress() usize {
687 };691 };
688 return phdr - @sizeOf(ElfHeader);692 return phdr - @sizeOf(ElfHeader);
689 },693 },
690 builtin.Os.macosx => return @ptrToInt(&std.c._mh_execute_header),694 builtin.Os.macosx, builtin.Os.freebsd => return @ptrToInt(&std.c._mh_execute_header),
691 builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)),695 builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)),
692 else => @compileError("Unsupported OS"),696 else => @compileError("Unsupported OS"),
693 }697 }
...@@ -700,8 +704,8 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {...@@ -700,8 +704,8 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
700 errdefer result.deinit();704 errdefer result.deinit();
701705
702 if (is_windows) {706 if (is_windows) {
703 const ptr = windows.GetEnvironmentStringsA() orelse return error.OutOfMemory;707 const ptr = windows.GetEnvironmentStringsW() orelse return error.OutOfMemory;
704 defer assert(windows.FreeEnvironmentStringsA(ptr) != 0);708 defer assert(windows.FreeEnvironmentStringsW(ptr) != 0);
705709
706 var i: usize = 0;710 var i: usize = 0;
707 while (true) {711 while (true) {
...@@ -710,17 +714,21 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {...@@ -710,17 +714,21 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
710 const key_start = i;714 const key_start = i;
711715
712 while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {}716 while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {}
713 const key = ptr[key_start..i];717 const key_w = ptr[key_start..i];
718 const key = try std.unicode.utf16leToUtf8Alloc(allocator, key_w);
719 errdefer allocator.free(key);
714720
715 if (ptr[i] == '=') i += 1;721 if (ptr[i] == '=') i += 1;
716722
717 const value_start = i;723 const value_start = i;
718 while (ptr[i] != 0) : (i += 1) {}724 while (ptr[i] != 0) : (i += 1) {}
719 const value = ptr[value_start..i];725 const value_w = ptr[value_start..i];
726 const value = try std.unicode.utf16leToUtf8Alloc(allocator, value_w);
727 errdefer allocator.free(value);
720728
721 i += 1; // skip over null byte729 i += 1; // skip over null byte
722730
723 try result.set(key, value);731 try result.setMove(key, value);
724 }732 }
725 } else {733 } else {
726 for (posix_environ_raw) |ptr| {734 for (posix_environ_raw) |ptr| {
...@@ -738,6 +746,11 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {...@@ -738,6 +746,11 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
738 }746 }
739}747}
740748
749test "os.getEnvMap" {
750 var env = try getEnvMap(std.debug.global_allocator);
751 defer env.deinit();
752}
753
741/// TODO make this go through libc when we have it754/// TODO make this go through libc when we have it
742pub fn getEnvPosix(key: []const u8) ?[]const u8 {755pub fn getEnvPosix(key: []const u8) ?[]const u8 {
743 for (posix_environ_raw) |ptr| {756 for (posix_environ_raw) |ptr| {
...@@ -758,21 +771,24 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 {...@@ -758,21 +771,24 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 {
758pub const GetEnvVarOwnedError = error{771pub const GetEnvVarOwnedError = error{
759 OutOfMemory,772 OutOfMemory,
760 EnvironmentVariableNotFound,773 EnvironmentVariableNotFound,
774
775 /// See https://github.com/ziglang/zig/issues/1774
776 InvalidUtf8,
761};777};
762778
763/// Caller must free returned memory.779/// Caller must free returned memory.
764/// TODO make this go through libc when we have it780/// TODO make this go through libc when we have it
765pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 {781pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 {
766 if (is_windows) {782 if (is_windows) {
767 const key_with_null = try cstr.addNullByte(allocator, key);783 const key_with_null = try std.unicode.utf8ToUtf16LeWithNull(allocator, key);
768 defer allocator.free(key_with_null);784 defer allocator.free(key_with_null);
769785
770 var buf = try allocator.alloc(u8, 256);786 var buf = try allocator.alloc(u16, 256);
771 errdefer allocator.free(buf);787 defer allocator.free(buf);
772788
773 while (true) {789 while (true) {
774 const windows_buf_len = math.cast(windows.DWORD, buf.len) catch return error.OutOfMemory;790 const windows_buf_len = math.cast(windows.DWORD, buf.len) catch return error.OutOfMemory;
775 const result = windows.GetEnvironmentVariableA(key_with_null.ptr, buf.ptr, windows_buf_len);791 const result = windows.GetEnvironmentVariableW(key_with_null.ptr, buf.ptr, windows_buf_len);
776792
777 if (result == 0) {793 if (result == 0) {
778 const err = windows.GetLastError();794 const err = windows.GetLastError();
...@@ -786,11 +802,16 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned...@@ -786,11 +802,16 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned
786 }802 }
787803
788 if (result > buf.len) {804 if (result > buf.len) {
789 buf = try allocator.realloc(u8, buf, result);805 buf = try allocator.realloc(u16, buf, result);
790 continue;806 continue;
791 }807 }
792808
793 return allocator.shrink(u8, buf, result);809 return std.unicode.utf16leToUtf8Alloc(allocator, buf) catch |err| switch (err) {
810 error.DanglingSurrogateHalf => return error.InvalidUtf8,
811 error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8,
812 error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8,
813 error.OutOfMemory => return error.OutOfMemory,
814 };
794 }815 }
795 } else {816 } else {
796 const result = getEnvPosix(key) orelse return error.EnvironmentVariableNotFound;817 const result = getEnvPosix(key) orelse return error.EnvironmentVariableNotFound;
...@@ -798,6 +819,11 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned...@@ -798,6 +819,11 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned
798 }819 }
799}820}
800821
822test "os.getEnvVarOwned" {
823 var ga = debug.global_allocator;
824 debug.assertError(getEnvVarOwned(ga, "BADENV"), error.EnvironmentVariableNotFound);
825}
826
801/// Caller must free the returned memory.827/// Caller must free the returned memory.
802pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {828pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {
803 var buf: [MAX_PATH_BYTES]u8 = undefined;829 var buf: [MAX_PATH_BYTES]u8 = undefined;
...@@ -1305,7 +1331,7 @@ pub fn deleteDirC(dir_path: [*]const u8) DeleteDirError!void {...@@ -1305,7 +1331,7 @@ pub fn deleteDirC(dir_path: [*]const u8) DeleteDirError!void {
1305 const dir_path_w = try windows_util.cStrToPrefixedFileW(dir_path);1331 const dir_path_w = try windows_util.cStrToPrefixedFileW(dir_path);
1306 return deleteDirW(&dir_path_w);1332 return deleteDirW(&dir_path_w);
1307 },1333 },
1308 Os.linux, Os.macosx, Os.ios => {1334 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
1309 const err = posix.getErrno(posix.rmdir(dir_path));1335 const err = posix.getErrno(posix.rmdir(dir_path));
1310 switch (err) {1336 switch (err) {
1311 0 => return,1337 0 => return,
...@@ -1348,7 +1374,7 @@ pub fn deleteDir(dir_path: []const u8) DeleteDirError!void {...@@ -1348,7 +1374,7 @@ pub fn deleteDir(dir_path: []const u8) DeleteDirError!void {
1348 const dir_path_w = try windows_util.sliceToPrefixedFileW(dir_path);1374 const dir_path_w = try windows_util.sliceToPrefixedFileW(dir_path);
1349 return deleteDirW(&dir_path_w);1375 return deleteDirW(&dir_path_w);
1350 },1376 },
1351 Os.linux, Os.macosx, Os.ios => {1377 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
1352 const dir_path_c = try toPosixPath(dir_path);1378 const dir_path_c = try toPosixPath(dir_path);
1353 return deleteDirC(&dir_path_c);1379 return deleteDirC(&dir_path_c);
1354 },1380 },
...@@ -1378,6 +1404,7 @@ const DeleteTreeError = error{...@@ -1378,6 +1404,7 @@ const DeleteTreeError = error{
1378 FileSystem,1404 FileSystem,
1379 FileBusy,1405 FileBusy,
1380 DirNotEmpty,1406 DirNotEmpty,
1407 DeviceBusy,
13811408
1382 /// On Windows, file paths must be valid Unicode.1409 /// On Windows, file paths must be valid Unicode.
1383 InvalidUtf8,1410 InvalidUtf8,
...@@ -1439,6 +1466,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError!...@@ -1439,6 +1466,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError!
1439 error.Unexpected,1466 error.Unexpected,
1440 error.InvalidUtf8,1467 error.InvalidUtf8,
1441 error.BadPathName,1468 error.BadPathName,
1469 error.DeviceBusy,
1442 => return err,1470 => return err,
1443 };1471 };
1444 defer dir.close();1472 defer dir.close();
...@@ -1465,7 +1493,7 @@ pub const Dir = struct {...@@ -1465,7 +1493,7 @@ pub const Dir = struct {
1465 allocator: *Allocator,1493 allocator: *Allocator,
14661494
1467 pub const Handle = switch (builtin.os) {1495 pub const Handle = switch (builtin.os) {
1468 Os.macosx, Os.ios => struct {1496 Os.macosx, Os.ios, Os.freebsd => struct {
1469 fd: i32,1497 fd: i32,
1470 seek: i64,1498 seek: i64,
1471 buf: []u8,1499 buf: []u8,
...@@ -1521,6 +1549,7 @@ pub const Dir = struct {...@@ -1521,6 +1549,7 @@ pub const Dir = struct {
1521 OutOfMemory,1549 OutOfMemory,
1522 InvalidUtf8,1550 InvalidUtf8,
1523 BadPathName,1551 BadPathName,
1552 DeviceBusy,
15241553
1525 /// See https://github.com/ziglang/zig/issues/13961554 /// See https://github.com/ziglang/zig/issues/1396
1526 Unexpected,1555 Unexpected,
...@@ -1541,7 +1570,7 @@ pub const Dir = struct {...@@ -1541,7 +1570,7 @@ pub const Dir = struct {
1541 .name_data = undefined,1570 .name_data = undefined,
1542 };1571 };
1543 },1572 },
1544 Os.macosx, Os.ios => Handle{1573 Os.macosx, Os.ios, Os.freebsd => Handle{
1545 .fd = try posixOpen(1574 .fd = try posixOpen(
1546 dir_path,1575 dir_path,
1547 posix.O_RDONLY | posix.O_NONBLOCK | posix.O_DIRECTORY | posix.O_CLOEXEC,1576 posix.O_RDONLY | posix.O_NONBLOCK | posix.O_DIRECTORY | posix.O_CLOEXEC,
...@@ -1572,7 +1601,7 @@ pub const Dir = struct {...@@ -1572,7 +1601,7 @@ pub const Dir = struct {
1572 Os.windows => {1601 Os.windows => {
1573 _ = windows.FindClose(self.handle.handle);1602 _ = windows.FindClose(self.handle.handle);
1574 },1603 },
1575 Os.macosx, Os.ios, Os.linux => {1604 Os.macosx, Os.ios, Os.linux, Os.freebsd => {
1576 self.allocator.free(self.handle.buf);1605 self.allocator.free(self.handle.buf);
1577 os.close(self.handle.fd);1606 os.close(self.handle.fd);
1578 },1607 },
...@@ -1587,6 +1616,7 @@ pub const Dir = struct {...@@ -1587,6 +1616,7 @@ pub const Dir = struct {
1587 Os.linux => return self.nextLinux(),1616 Os.linux => return self.nextLinux(),
1588 Os.macosx, Os.ios => return self.nextDarwin(),1617 Os.macosx, Os.ios => return self.nextDarwin(),
1589 Os.windows => return self.nextWindows(),1618 Os.windows => return self.nextWindows(),
1619 Os.freebsd => return self.nextFreebsd(),
1590 else => @compileError("unimplemented"),1620 else => @compileError("unimplemented"),
1591 }1621 }
1592 }1622 }
...@@ -1726,6 +1756,11 @@ pub const Dir = struct {...@@ -1726,6 +1756,11 @@ pub const Dir = struct {
1726 };1756 };
1727 }1757 }
1728 }1758 }
1759
1760 fn nextFreebsd(self: *Dir) !?Entry {
1761 //self.handle.buf = try self.allocator.alloc(u8, page_size);
1762 @compileError("TODO implement dirs for FreeBSD");
1763 }
1729};1764};
17301765
1731pub fn changeCurDir(allocator: *Allocator, dir_path: []const u8) !void {1766pub fn changeCurDir(allocator: *Allocator, dir_path: []const u8) !void {
...@@ -2164,7 +2199,7 @@ pub fn unexpectedErrorWindows(err: windows.DWORD) UnexpectedError {...@@ -2164,7 +2199,7 @@ pub fn unexpectedErrorWindows(err: windows.DWORD) UnexpectedError {
2164pub fn openSelfExe() !os.File {2199pub fn openSelfExe() !os.File {
2165 switch (builtin.os) {2200 switch (builtin.os) {
2166 Os.linux => return os.File.openReadC(c"/proc/self/exe"),2201 Os.linux => return os.File.openReadC(c"/proc/self/exe"),
2167 Os.macosx, Os.ios => {2202 Os.macosx, Os.ios, Os.freebsd => {
2168 var buf: [MAX_PATH_BYTES]u8 = undefined;2203 var buf: [MAX_PATH_BYTES]u8 = undefined;
2169 const self_exe_path = try selfExePath(&buf);2204 const self_exe_path = try selfExePath(&buf);
2170 buf[self_exe_path.len] = 0;2205 buf[self_exe_path.len] = 0;
...@@ -2181,7 +2216,7 @@ pub fn openSelfExe() !os.File {...@@ -2181,7 +2216,7 @@ pub fn openSelfExe() !os.File {
21812216
2182test "openSelfExe" {2217test "openSelfExe" {
2183 switch (builtin.os) {2218 switch (builtin.os) {
2184 Os.linux, Os.macosx, Os.ios, Os.windows => (try openSelfExe()).close(),2219 Os.linux, Os.macosx, Os.ios, Os.windows, Os.freebsd => (try openSelfExe()).close(),
2185 else => return error.SkipZigTest, // Unsupported OS.2220 else => return error.SkipZigTest, // Unsupported OS.
2186 }2221 }
2187}2222}
...@@ -2212,6 +2247,7 @@ pub fn selfExePathW(out_buffer: *[windows_util.PATH_MAX_WIDE]u16) ![]u16 {...@@ -2212,6 +2247,7 @@ pub fn selfExePathW(out_buffer: *[windows_util.PATH_MAX_WIDE]u16) ![]u16 {
2212pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {2247pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
2213 switch (builtin.os) {2248 switch (builtin.os) {
2214 Os.linux => return readLink(out_buffer, "/proc/self/exe"),2249 Os.linux => return readLink(out_buffer, "/proc/self/exe"),
2250 Os.freebsd => return readLink(out_buffer, "/proc/curproc/file"),
2215 Os.windows => {2251 Os.windows => {
2216 var utf16le_buf: [windows_util.PATH_MAX_WIDE]u16 = undefined;2252 var utf16le_buf: [windows_util.PATH_MAX_WIDE]u16 = undefined;
2217 const utf16le_slice = try selfExePathW(&utf16le_buf);2253 const utf16le_slice = try selfExePathW(&utf16le_buf);
...@@ -2250,7 +2286,7 @@ pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) ![]const u8 {...@@ -2250,7 +2286,7 @@ pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) ![]const u8 {
2250 // will not return null.2286 // will not return null.
2251 return path.dirname(full_exe_path).?;2287 return path.dirname(full_exe_path).?;
2252 },2288 },
2253 Os.windows, Os.macosx, Os.ios => {2289 Os.windows, Os.macosx, Os.ios, Os.freebsd => {
2254 const self_exe_path = try selfExePath(out_buffer);2290 const self_exe_path = try selfExePath(out_buffer);
2255 // Assume that the OS APIs return absolute paths, and therefore dirname2291 // Assume that the OS APIs return absolute paths, and therefore dirname
2256 // will not return null.2292 // will not return null.
...@@ -3095,10 +3131,13 @@ pub const CpuCountError = error{...@@ -3095,10 +3131,13 @@ pub const CpuCountError = error{
30953131
3096pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize {3132pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize {
3097 switch (builtin.os) {3133 switch (builtin.os) {
3098 builtin.Os.macosx => {3134 builtin.Os.macosx, builtin.Os.freebsd => {
3099 var count: c_int = undefined;3135 var count: c_int = undefined;
3100 var count_len: usize = @sizeOf(c_int);3136 var count_len: usize = @sizeOf(c_int);
3101 const rc = posix.sysctlbyname(c"hw.logicalcpu", @ptrCast(*c_void, &count), &count_len, null, 0);3137 const rc = posix.sysctlbyname(switch (builtin.os) {
3138 builtin.Os.macosx => c"hw.logicalcpu",
3139 else => c"hw.ncpu",
3140 }, @ptrCast(*c_void, &count), &count_len, null, 0);
3102 const err = posix.getErrno(rc);3141 const err = posix.getErrno(rc);
3103 switch (err) {3142 switch (err) {
3104 0 => return @intCast(usize, count),3143 0 => return @intCast(usize, count),
std/os/linux/index.zig+56-47
...@@ -703,7 +703,7 @@ pub fn dup2(old: i32, new: i32) usize {...@@ -703,7 +703,7 @@ pub fn dup2(old: i32, new: i32) usize {
703}703}
704704
705pub fn dup3(old: i32, new: i32, flags: u32) usize {705pub 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}
708708
709// TODO https://github.com/ziglang/zig/issues/265709// TODO https://github.com/ziglang/zig/issues/265
...@@ -747,7 +747,7 @@ pub fn getcwd(buf: [*]u8, size: usize) usize {...@@ -747,7 +747,7 @@ pub fn getcwd(buf: [*]u8, size: usize) usize {
747}747}
748748
749pub fn getdents64(fd: i32, dirp: [*]u8, count: usize) usize {749pub 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}
752752
753pub fn inotify_init1(flags: u32) usize {753pub fn inotify_init1(flags: u32) usize {
...@@ -755,16 +755,16 @@ pub fn inotify_init1(flags: u32) usize {...@@ -755,16 +755,16 @@ pub fn inotify_init1(flags: u32) usize {
755}755}
756756
757pub fn inotify_add_watch(fd: i32, pathname: [*]const u8, mask: u32) usize {757pub 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}
760760
761pub fn inotify_rm_watch(fd: i32, wd: i32) usize {761pub 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}
764764
765pub fn isatty(fd: i32) bool {765pub fn isatty(fd: i32) bool {
766 var wsz: winsize = undefined;766 var wsz: winsize = undefined;
767 return syscall3(SYS_ioctl, @intCast(usize, fd), TIOCGWINSZ, @ptrToInt(&wsz)) == 0;767 return syscall3(SYS_ioctl, @bitCast(usize, isize(fd)), TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
768}768}
769769
770// TODO https://github.com/ziglang/zig/issues/265770// TODO https://github.com/ziglang/zig/issues/265
...@@ -774,7 +774,7 @@ pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usiz...@@ -774,7 +774,7 @@ pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usiz
774774
775// TODO https://github.com/ziglang/zig/issues/265775// TODO https://github.com/ziglang/zig/issues/265
776pub fn readlinkat(dirfd: i32, noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {776pub 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}
779779
780// TODO https://github.com/ziglang/zig/issues/265780// TODO https://github.com/ziglang/zig/issues/265
...@@ -784,7 +784,7 @@ pub fn mkdir(path: [*]const u8, mode: u32) usize {...@@ -784,7 +784,7 @@ pub fn mkdir(path: [*]const u8, mode: u32) usize {
784784
785// TODO https://github.com/ziglang/zig/issues/265785// TODO https://github.com/ziglang/zig/issues/265
786pub fn mkdirat(dirfd: i32, path: [*]const u8, mode: u32) usize {786pub 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}
789789
790// TODO https://github.com/ziglang/zig/issues/265790// TODO https://github.com/ziglang/zig/issues/265
...@@ -803,7 +803,7 @@ pub fn umount2(special: [*]const u8, flags: u32) usize {...@@ -803,7 +803,7 @@ pub fn umount2(special: [*]const u8, flags: u32) usize {
803}803}
804804
805pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {805pub 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}
808808
809pub fn munmap(address: usize, length: usize) usize {809pub fn munmap(address: usize, length: usize) usize {
...@@ -811,23 +811,23 @@ pub fn munmap(address: usize, length: usize) usize {...@@ -811,23 +811,23 @@ pub fn munmap(address: usize, length: usize) usize {
811}811}
812812
813pub fn read(fd: i32, buf: [*]u8, count: usize) usize {813pub 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}
816816
817pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize {817pub 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}
820820
821pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize {821pub 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}
824824
825pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize {825pub 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}
828828
829pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) usize {829pub 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}
832832
833// TODO https://github.com/ziglang/zig/issues/265833// TODO https://github.com/ziglang/zig/issues/265
...@@ -842,12 +842,12 @@ pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {...@@ -842,12 +842,12 @@ pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
842842
843// TODO https://github.com/ziglang/zig/issues/265843// TODO https://github.com/ziglang/zig/issues/265
844pub fn symlinkat(existing: [*]const u8, newfd: i32, newpath: [*]const u8) usize {844pub 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}
847847
848// TODO https://github.com/ziglang/zig/issues/265848// TODO https://github.com/ziglang/zig/issues/265
849pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize {849pub 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}
852852
853// TODO https://github.com/ziglang/zig/issues/265853// TODO https://github.com/ziglang/zig/issues/265
...@@ -856,7 +856,7 @@ pub fn access(path: [*]const u8, mode: u32) usize {...@@ -856,7 +856,7 @@ pub fn access(path: [*]const u8, mode: u32) usize {
856}856}
857857
858pub fn faccessat(dirfd: i32, path: [*]const u8, mode: u32) usize {858pub 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}
861861
862pub fn pipe(fd: *[2]i32) usize {862pub fn pipe(fd: *[2]i32) usize {
...@@ -868,11 +868,11 @@ pub fn pipe2(fd: *[2]i32, flags: u32) usize {...@@ -868,11 +868,11 @@ pub fn pipe2(fd: *[2]i32, flags: u32) usize {
868}868}
869869
870pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {870pub 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}
873873
874pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {874pub 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}
877877
878// TODO https://github.com/ziglang/zig/issues/265878// TODO https://github.com/ziglang/zig/issues/265
...@@ -882,7 +882,7 @@ pub fn rename(old: [*]const u8, new: [*]const u8) usize {...@@ -882,7 +882,7 @@ pub fn rename(old: [*]const u8, new: [*]const u8) usize {
882882
883// TODO https://github.com/ziglang/zig/issues/265883// TODO https://github.com/ziglang/zig/issues/265
884pub fn renameat2(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const u8, flags: u32) usize {884pub 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}
887887
888// TODO https://github.com/ziglang/zig/issues/265888// TODO https://github.com/ziglang/zig/issues/265
...@@ -897,7 +897,8 @@ pub fn create(path: [*]const u8, perm: usize) usize {...@@ -897,7 +897,8 @@ pub fn create(path: [*]const u8, perm: usize) usize {
897897
898// TODO https://github.com/ziglang/zig/issues/265898// TODO https://github.com/ziglang/zig/issues/265
899pub fn openat(dirfd: i32, path: [*]const u8, flags: u32, mode: usize) usize {899pub 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}
902903
903/// See also `clone` (from the arch-specific include)904/// See also `clone` (from the arch-specific include)
...@@ -911,11 +912,11 @@ pub fn clone2(flags: u32, child_stack_ptr: usize) usize {...@@ -911,11 +912,11 @@ pub fn clone2(flags: u32, child_stack_ptr: usize) usize {
911}912}
912913
913pub fn close(fd: i32) usize {914pub fn close(fd: i32) usize {
914 return syscall1(SYS_close, @intCast(usize, fd));915 return syscall1(SYS_close, @bitCast(usize, isize(fd)));
915}916}
916917
917pub fn lseek(fd: i32, offset: isize, ref_pos: usize) usize {918pub 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}
920921
921pub fn exit(status: i32) noreturn {922pub fn exit(status: i32) noreturn {
...@@ -933,7 +934,7 @@ pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {...@@ -933,7 +934,7 @@ pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
933}934}
934935
935pub fn kill(pid: i32, sig: i32) usize {936pub 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}
938939
939// TODO https://github.com/ziglang/zig/issues/265940// TODO https://github.com/ziglang/zig/issues/265
...@@ -943,7 +944,7 @@ pub fn unlink(path: [*]const u8) usize {...@@ -943,7 +944,7 @@ pub fn unlink(path: [*]const u8) usize {
943944
944// TODO https://github.com/ziglang/zig/issues/265945// TODO https://github.com/ziglang/zig/issues/265
945pub fn unlinkat(dirfd: i32, path: [*]const u8, flags: u32) usize {946pub 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}
948949
949pub fn waitpid(pid: i32, status: *i32, options: i32) usize {950pub fn waitpid(pid: i32, status: *i32, options: i32) usize {
...@@ -1120,8 +1121,8 @@ pub const empty_sigset = []usize{0} ** sigset_t.len;...@@ -1120,8 +1121,8 @@ pub const empty_sigset = []usize{0} ** sigset_t.len;
1120pub fn raise(sig: i32) usize {1121pub fn raise(sig: i32) usize {
1121 var set: sigset_t = undefined;1122 var set: sigset_t = undefined;
1122 blockAppSignals(&set);1123 blockAppSignals(&set);
1123 const tid = @intCast(i32, syscall0(SYS_gettid));1124 const tid = syscall0(SYS_gettid);
1124 const ret = syscall2(SYS_tkill, @intCast(usize, tid), @intCast(usize, sig));1125 const ret = syscall2(SYS_tkill, tid, @bitCast(usize, isize(sig)));
1125 restoreSignals(&set);1126 restoreSignals(&set);
1126 return ret;1127 return ret;
1127}1128}
...@@ -1189,11 +1190,11 @@ pub const iovec_const = extern struct {...@@ -1189,11 +1190,11 @@ pub const iovec_const = extern struct {
1189};1190};
11901191
1191pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {1192pub 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}
11941195
1195pub fn getpeername(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {1196pub 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}
11981199
1199pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {1200pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {
...@@ -1201,47 +1202,47 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {...@@ -1201,47 +1202,47 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {
1201}1202}
12021203
1203pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: [*]const u8, optlen: socklen_t) usize {1204pub 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}
12061207
1207pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noalias optlen: *socklen_t) usize {1208pub 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}
12101211
1211pub fn sendmsg(fd: i32, msg: *const msghdr, flags: u32) usize {1212pub 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}
12141215
1215pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize {1216pub 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}
12181219
1219pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize {1220pub 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}
12221223
1223pub fn recvfrom(fd: i32, noalias buf: [*]u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t) usize {1224pub 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}
12261227
1227pub fn shutdown(fd: i32, how: i32) usize {1228pub 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}
12301231
1231pub fn bind(fd: i32, addr: *const sockaddr, len: socklen_t) usize {1232pub 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}
12341235
1235pub fn listen(fd: i32, backlog: u32) usize {1236pub 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}
12381239
1239pub fn sendto(fd: i32, buf: [*]const u8, len: usize, flags: u32, addr: ?*const sockaddr, alen: socklen_t) usize {1240pub 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}
12421243
1243pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) usize {1244pub 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}
12461247
1247pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {1248pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
...@@ -1249,11 +1250,11 @@ pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {...@@ -1249,11 +1250,11 @@ pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
1249}1250}
12501251
1251pub fn accept4(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t, flags: u32) usize {1252pub 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}
12541255
1255pub fn fstat(fd: i32, stat_buf: *Stat) usize {1256pub 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}
12581259
1259// TODO https://github.com/ziglang/zig/issues/2651260// TODO https://github.com/ziglang/zig/issues/265
...@@ -1268,7 +1269,7 @@ pub fn lstat(pathname: [*]const u8, statbuf: *Stat) usize {...@@ -1268,7 +1269,7 @@ pub fn lstat(pathname: [*]const u8, statbuf: *Stat) usize {
12681269
1269// TODO https://github.com/ziglang/zig/issues/2651270// TODO https://github.com/ziglang/zig/issues/265
1270pub fn fstatat(dirfd: i32, path: [*]const u8, stat_buf: *Stat, flags: u32) usize {1271pub 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}
12731274
1274// TODO https://github.com/ziglang/zig/issues/2651275// TODO https://github.com/ziglang/zig/issues/265
...@@ -1355,7 +1356,7 @@ pub fn epoll_create1(flags: usize) usize {...@@ -1355,7 +1356,7 @@ pub fn epoll_create1(flags: usize) usize {
1355}1356}
13561357
1357pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: *epoll_event) usize {1358pub 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}
13601361
1361pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize {1362pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize {
...@@ -1363,7 +1364,15 @@ pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout...@@ -1363,7 +1364,15 @@ pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout
1363}1364}
13641365
1365pub fn epoll_pwait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32, sigmask: ?*sigset_t) usize {1366pub 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}
13681377
1369pub fn eventfd(count: u32, flags: u32) usize {1378pub fn eventfd(count: u32, flags: u32) usize {
...@@ -1371,7 +1380,7 @@ pub fn eventfd(count: u32, flags: u32) usize {...@@ -1371,7 +1380,7 @@ pub fn eventfd(count: u32, flags: u32) usize {
1371}1380}
13721381
1373pub fn timerfd_create(clockid: i32, flags: u32) usize {1382pub 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}
13761385
1377pub const itimerspec = extern struct {1386pub const itimerspec = extern struct {
...@@ -1380,11 +1389,11 @@ pub const itimerspec = extern struct {...@@ -1380,11 +1389,11 @@ pub const itimerspec = extern struct {
1380};1389};
13811390
1382pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize {1391pub 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}
13851394
1386pub fn timerfd_settime(fd: i32, flags: u32, new_value: *const itimerspec, old_value: ?*itimerspec) usize {1395pub 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}
13891398
1390pub const _LINUX_CAPABILITY_VERSION_1 = 0x19980330;1399pub const _LINUX_CAPABILITY_VERSION_1 = 0x19980330;
std/os/path.zig+12-2
...@@ -1093,6 +1093,7 @@ pub const RealError = error{...@@ -1093,6 +1093,7 @@ pub const RealError = error{
1093 NoSpaceLeft,1093 NoSpaceLeft,
1094 FileSystem,1094 FileSystem,
1095 BadPathName,1095 BadPathName,
1096 DeviceBusy,
10961097
1097 /// On Windows, file paths must be valid Unicode.1098 /// On Windows, file paths must be valid Unicode.
1098 InvalidUtf8,1099 InvalidUtf8,
...@@ -1183,11 +1184,20 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro...@@ -1183,11 +1184,20 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro
1183 const fd = try os.posixOpenC(pathname, posix.O_PATH | posix.O_NONBLOCK | posix.O_CLOEXEC, 0);1184 const fd = try os.posixOpenC(pathname, posix.O_PATH | posix.O_NONBLOCK | posix.O_CLOEXEC, 0);
1184 defer os.close(fd);1185 defer os.close(fd);
11851186
1186 var buf: ["/proc/self/fd/-2147483648".len]u8 = undefined;1187 var buf: ["/proc/self/fd/-2147483648\x00".len]u8 = undefined;
1187 const proc_path = fmt.bufPrint(buf[0..], "/proc/self/fd/{}\x00", fd) catch unreachable;1188 const proc_path = fmt.bufPrint(buf[0..], "/proc/self/fd/{}\x00", fd) catch unreachable;
11881189
1189 return os.readLinkC(out_buffer, proc_path.ptr);1190 return os.readLinkC(out_buffer, proc_path.ptr);
1190 },1191 },
1192 Os.freebsd => { // XXX requires fdescfs
1193 const fd = try os.posixOpenC(pathname, posix.O_PATH | posix.O_NONBLOCK | posix.O_CLOEXEC, 0);
1194 defer os.close(fd);
1195
1196 var buf: ["/dev/fd/-2147483648\x00".len]u8 = undefined;
1197 const proc_path = fmt.bufPrint(buf[0..], "/dev/fd/{}\x00", fd) catch unreachable;
1198
1199 return os.readLinkC(out_buffer, proc_path.ptr);
1200 },
1191 else => @compileError("TODO implement os.path.real for " ++ @tagName(builtin.os)),1201 else => @compileError("TODO implement os.path.real for " ++ @tagName(builtin.os)),
1192 }1202 }
1193}1203}
...@@ -1202,7 +1212,7 @@ pub fn real(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: []const u8) RealError!...@@ -1202,7 +1212,7 @@ pub fn real(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: []const u8) RealError!
1202 const pathname_w = try windows_util.sliceToPrefixedFileW(pathname);1212 const pathname_w = try windows_util.sliceToPrefixedFileW(pathname);
1203 return realW(out_buffer, &pathname_w);1213 return realW(out_buffer, &pathname_w);
1204 },1214 },
1205 Os.macosx, Os.ios, Os.linux => {1215 Os.macosx, Os.ios, Os.linux, Os.freebsd => {
1206 const pathname_c = try os.toPosixPath(pathname);1216 const pathname_c = try os.toPosixPath(pathname);
1207 return realC(out_buffer, &pathname_c);1217 return realC(out_buffer, &pathname_c);
1208 },1218 },
std/os/windows/kernel32.zig+3-3
...@@ -50,7 +50,7 @@ pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFi...@@ -50,7 +50,7 @@ pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFi
50pub extern "kernel32" stdcallcc fn FindClose(hFindFile: HANDLE) BOOL;50pub extern "kernel32" stdcallcc fn FindClose(hFindFile: HANDLE) BOOL;
51pub extern "kernel32" stdcallcc fn FindNextFileW(hFindFile: HANDLE, lpFindFileData: *WIN32_FIND_DATAW) BOOL;51pub extern "kernel32" stdcallcc fn FindNextFileW(hFindFile: HANDLE, lpFindFileData: *WIN32_FIND_DATAW) BOOL;
5252
53pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsA(penv: [*]u8) BOOL;53pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsW(penv: [*]u16) BOOL;
5454
55pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR;55pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR;
5656
...@@ -63,9 +63,9 @@ pub extern "kernel32" stdcallcc fn GetCurrentDirectoryW(nBufferLength: DWORD, lp...@@ -63,9 +63,9 @@ pub extern "kernel32" stdcallcc fn GetCurrentDirectoryW(nBufferLength: DWORD, lp
63pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE;63pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE;
64pub extern "kernel32" stdcallcc fn GetCurrentThreadId() DWORD;64pub extern "kernel32" stdcallcc fn GetCurrentThreadId() DWORD;
6565
66pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() ?[*]u8;66pub extern "kernel32" stdcallcc fn GetEnvironmentStringsW() ?[*]u16;
6767
68pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) DWORD;68pub extern "kernel32" stdcallcc fn GetEnvironmentVariableW(lpName: LPWSTR, lpBuffer: LPWSTR, nSize: DWORD) DWORD;
6969
70pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: *DWORD) BOOL;70pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: *DWORD) BOOL;
7171
std/os/zen.zig+11-11
...@@ -12,20 +12,20 @@ pub const Message = struct {...@@ -12,20 +12,20 @@ pub const Message = struct {
12 args: [5]usize,12 args: [5]usize,
13 payload: ?[]const u8,13 payload: ?[]const u8,
1414
15 pub fn from(mailbox_id: *const MailboxId) Message {15 pub fn from(mailbox_id: MailboxId) Message {
16 return Message{16 return Message{
17 .sender = MailboxId.Undefined,17 .sender = MailboxId.Undefined,
18 .receiver = mailbox_id.*,18 .receiver = mailbox_id,
19 .code = undefined,19 .code = undefined,
20 .args = undefined,20 .args = undefined,
21 .payload = null,21 .payload = null,
22 };22 };
23 }23 }
2424
25 pub fn to(mailbox_id: *const MailboxId, msg_code: usize, args: ...) Message {25 pub fn to(mailbox_id: MailboxId, msg_code: usize, args: ...) Message {
26 var message = Message{26 var message = Message{
27 .sender = MailboxId.This,27 .sender = MailboxId.This,
28 .receiver = mailbox_id.*,28 .receiver = mailbox_id,
29 .code = msg_code,29 .code = msg_code,
30 .args = undefined,30 .args = undefined,
31 .payload = null,31 .payload = null,
...@@ -40,14 +40,14 @@ pub const Message = struct {...@@ -40,14 +40,14 @@ pub const Message = struct {
40 return message;40 return message;
41 }41 }
4242
43 pub fn as(self: *const Message, sender: *const MailboxId) Message {43 pub fn as(self: Message, sender: MailboxId) Message {
44 var message = self.*;44 var message = self;
45 message.sender = sender.*;45 message.sender = sender;
46 return message;46 return message;
47 }47 }
4848
49 pub fn withPayload(self: *const Message, payload: []const u8) Message {49 pub fn withPayload(self: Message, payload: []const u8) Message {
50 var message = self.*;50 var message = self;
51 message.payload = payload;51 message.payload = payload;
52 return message;52 return message;
53 }53 }
...@@ -93,7 +93,7 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize {...@@ -93,7 +93,7 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
93 STDIN_FILENO => {93 STDIN_FILENO => {
94 var i: usize = 0;94 var i: usize = 0;
95 while (i < count) : (i += 1) {95 while (i < count) : (i += 1) {
96 send(Message.to(Server.Keyboard, 0));96 send(&Message.to(Server.Keyboard, 0));
9797
98 // FIXME: we should be certain that we are receiving from Keyboard.98 // FIXME: we should be certain that we are receiving from Keyboard.
99 var message = Message.from(MailboxId.This);99 var message = Message.from(MailboxId.This);
...@@ -111,7 +111,7 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize {...@@ -111,7 +111,7 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
111pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {111pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
112 switch (fd) {112 switch (fd) {
113 STDOUT_FILENO, STDERR_FILENO => {113 STDOUT_FILENO, STDERR_FILENO => {
114 send(Message.to(Server.Terminal, 1).withPayload(buf[0..count]));114 send(&Message.to(Server.Terminal, 1).withPayload(buf[0..count]));
115 },115 },
116 else => unreachable,116 else => unreachable,
117 }117 }
std/pdb.zig+4-3
...@@ -34,6 +34,7 @@ pub const DbiStreamHeader = packed struct {...@@ -34,6 +34,7 @@ pub const DbiStreamHeader = packed struct {
34};34};
3535
36pub const SectionContribEntry = packed struct {36pub const SectionContribEntry = packed struct {
37 /// COFF Section index, 1-based
37 Section: u16,38 Section: u16,
38 Padding1: [2]u8,39 Padding1: [2]u8,
39 Offset: u32,40 Offset: u32,
...@@ -507,11 +508,11 @@ const Msf = struct {...@@ -507,11 +508,11 @@ const Msf = struct {
507 allocator,508 allocator,
508 );509 );
509510
510 const stream_count = try self.directory.stream.readIntLe(u32);511 const stream_count = try self.directory.stream.readIntLittle(u32);
511512
512 const stream_sizes = try allocator.alloc(u32, stream_count);513 const stream_sizes = try allocator.alloc(u32, stream_count);
513 for (stream_sizes) |*s| {514 for (stream_sizes) |*s| {
514 const size = try self.directory.stream.readIntLe(u32);515 const size = try self.directory.stream.readIntLittle(u32);
515 s.* = blockCountFromSize(size, superblock.BlockSize);516 s.* = blockCountFromSize(size, superblock.BlockSize);
516 }517 }
517518
...@@ -602,7 +603,7 @@ const MsfStream = struct {...@@ -602,7 +603,7 @@ const MsfStream = struct {
602603
603 var i: u32 = 0;604 var i: u32 = 0;
604 while (i < block_count) : (i += 1) {605 while (i < block_count) : (i += 1) {
605 stream.blocks[i] = try in.readIntLe(u32);606 stream.blocks[i] = try in.readIntLittle(u32);
606 }607 }
607608
608 return stream;609 return stream;
std/rand/index.zig+160-41
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5// ```5// ```
6// var buf: [8]u8 = undefined;6// var buf: [8]u8 = undefined;
7// try std.os.getRandomBytes(buf[0..]);7// try std.os.getRandomBytes(buf[0..]);
8// const seed = mem.readIntLE(u64, buf[0..8]);8// const seed = mem.readIntSliceLittle(u64, buf[0..8]);
9//9//
10// var r = DefaultPrng.init(seed);10// var r = DefaultPrng.init(seed);
11//11//
...@@ -52,11 +52,24 @@ pub const Random = struct {...@@ -52,11 +52,24 @@ pub const Random = struct {
52 // use LE instead of native endian for better portability maybe?52 // use LE instead of native endian for better portability maybe?
53 // TODO: endian portability is pointless if the underlying prng isn't endian portable.53 // TODO: endian portability is pointless if the underlying prng isn't endian portable.
54 // TODO: document the endian portability of this library.54 // TODO: document the endian portability of this library.
55 const byte_aligned_result = mem.readIntLE(ByteAlignedT, rand_bytes);55 const byte_aligned_result = mem.readIntSliceLittle(ByteAlignedT, rand_bytes);
56 const unsigned_result = @truncate(UnsignedT, byte_aligned_result);56 const unsigned_result = @truncate(UnsignedT, byte_aligned_result);
57 return @bitCast(T, unsigned_result);57 return @bitCast(T, unsigned_result);
58 }58 }
5959
60 /// Constant-time implementation off ::uintLessThan.
61 /// The results of this function may be biased.
62 pub fn uintLessThanBiased(r: *Random, comptime T: type, less_than: T) T {
63 comptime assert(T.is_signed == false);
64 comptime assert(T.bit_count <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation!
65 assert(0 < less_than);
66 if (T.bit_count <= 32) {
67 return @intCast(T, limitRangeBiased(u32, r.int(u32), less_than));
68 } else {
69 return @intCast(T, limitRangeBiased(u64, r.int(u64), less_than));
70 }
71 }
72
60 /// Returns an evenly distributed random unsigned integer `0 <= i < less_than`.73 /// Returns an evenly distributed random unsigned integer `0 <= i < less_than`.
61 /// This function assumes that the underlying ::fillFn produces evenly distributed values.74 /// This function assumes that the underlying ::fillFn produces evenly distributed values.
62 /// Within this assumption, the runtime of this function is exponentially distributed.75 /// Within this assumption, the runtime of this function is exponentially distributed.
...@@ -64,27 +77,52 @@ pub const Random = struct {...@@ -64,27 +77,52 @@ pub const Random = struct {
64 /// the runtime of this function would technically be unbounded.77 /// the runtime of this function would technically be unbounded.
65 /// However, if ::fillFn is backed by any evenly distributed pseudo random number generator,78 /// However, if ::fillFn is backed by any evenly distributed pseudo random number generator,
66 /// this function is guaranteed to return.79 /// this function is guaranteed to return.
67 /// If you need deterministic runtime bounds, consider instead using `r.int(T) % less_than`,80 /// If you need deterministic runtime bounds, use `::uintLessThanBiased`.
68 /// which will usually be biased toward smaller values.
69 pub fn uintLessThan(r: *Random, comptime T: type, less_than: T) T {81 pub fn uintLessThan(r: *Random, comptime T: type, less_than: T) T {
70 assert(T.is_signed == false);82 comptime assert(T.is_signed == false);
83 comptime assert(T.bit_count <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation!
71 assert(0 < less_than);84 assert(0 < less_than);
7285 // Small is typically u32
73 const last_group_size_minus_one: T = maxInt(T) % less_than;86 const Small = @IntType(false, @divTrunc(T.bit_count + 31, 32) * 32);
74 if (last_group_size_minus_one == less_than - 1) {87 // Large is typically u64
75 // less_than is a power of two.88 const Large = @IntType(false, Small.bit_count * 2);
76 assert(math.floorPowerOfTwo(T, less_than) == less_than);89
77 // There is no retry zone. The optimal retry_zone_start would be maxInt(T) + 1.90 // adapted from:
78 return r.int(T) % less_than;91 // http://www.pcg-random.org/posts/bounded-rands.html
92 // "Lemire's (with an extra tweak from me)"
93 var x: Small = r.int(Small);
94 var m: Large = Large(x) * Large(less_than);
95 var l: Small = @truncate(Small, m);
96 if (l < less_than) {
97 // TODO: workaround for https://github.com/ziglang/zig/issues/1770
98 // should be:
99 // var t: Small = -%less_than;
100 var t: Small = @bitCast(Small, -%@bitCast(@IntType(true, Small.bit_count), Small(less_than)));
101
102 if (t >= less_than) {
103 t -= less_than;
104 if (t >= less_than) {
105 t %= less_than;
106 }
107 }
108 while (l < t) {
109 x = r.int(Small);
110 m = Large(x) * Large(less_than);
111 l = @truncate(Small, m);
112 }
79 }113 }
80 const retry_zone_start = maxInt(T) - last_group_size_minus_one;114 return @intCast(T, m >> Small.bit_count);
115 }
81116
82 while (true) {117 /// Constant-time implementation off ::uintAtMost.
83 const rand_val = r.int(T);118 /// The results of this function may be biased.
84 if (rand_val < retry_zone_start) {119 pub fn uintAtMostBiased(r: *Random, comptime T: type, at_most: T) T {
85 return rand_val % less_than;120 assert(T.is_signed == false);
86 }121 if (at_most == maxInt(T)) {
122 // have the full range
123 return r.int(T);
87 }124 }
125 return r.uintLessThanBiased(T, at_most + 1);
88 }126 }
89127
90 /// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`.128 /// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`.
...@@ -99,6 +137,23 @@ pub const Random = struct {...@@ -99,6 +137,23 @@ pub const Random = struct {
99 return r.uintLessThan(T, at_most + 1);137 return r.uintLessThan(T, at_most + 1);
100 }138 }
101139
140 /// Constant-time implementation off ::intRangeLessThan.
141 /// The results of this function may be biased.
142 pub fn intRangeLessThanBiased(r: *Random, comptime T: type, at_least: T, less_than: T) T {
143 assert(at_least < less_than);
144 if (T.is_signed) {
145 // Two's complement makes this math pretty easy.
146 const UnsignedT = @IntType(false, T.bit_count);
147 const lo = @bitCast(UnsignedT, at_least);
148 const hi = @bitCast(UnsignedT, less_than);
149 const result = lo +% r.uintLessThanBiased(UnsignedT, hi -% lo);
150 return @bitCast(T, result);
151 } else {
152 // The signed implementation would work fine, but we can use stricter arithmetic operators here.
153 return at_least + r.uintLessThanBiased(T, less_than - at_least);
154 }
155 }
156
102 /// Returns an evenly distributed random integer `at_least <= i < less_than`.157 /// Returns an evenly distributed random integer `at_least <= i < less_than`.
103 /// See ::uintLessThan, which this function uses in most cases,158 /// See ::uintLessThan, which this function uses in most cases,
104 /// for commentary on the runtime of this function.159 /// for commentary on the runtime of this function.
...@@ -117,6 +172,23 @@ pub const Random = struct {...@@ -117,6 +172,23 @@ pub const Random = struct {
117 }172 }
118 }173 }
119174
175 /// Constant-time implementation off ::intRangeAtMostBiased.
176 /// The results of this function may be biased.
177 pub fn intRangeAtMostBiased(r: *Random, comptime T: type, at_least: T, at_most: T) T {
178 assert(at_least <= at_most);
179 if (T.is_signed) {
180 // Two's complement makes this math pretty easy.
181 const UnsignedT = @IntType(false, T.bit_count);
182 const lo = @bitCast(UnsignedT, at_least);
183 const hi = @bitCast(UnsignedT, at_most);
184 const result = lo +% r.uintAtMostBiased(UnsignedT, hi -% lo);
185 return @bitCast(T, result);
186 } else {
187 // The signed implementation would work fine, but we can use stricter arithmetic operators here.
188 return at_least + r.uintAtMostBiased(T, at_most - at_least);
189 }
190 }
191
120 /// Returns an evenly distributed random integer `at_least <= i <= at_most`.192 /// Returns an evenly distributed random integer `at_least <= i <= at_most`.
121 /// See ::uintLessThan, which this function uses in most cases,193 /// See ::uintLessThan, which this function uses in most cases,
122 /// for commentary on the runtime of this function.194 /// for commentary on the runtime of this function.
...@@ -135,15 +207,11 @@ pub const Random = struct {...@@ -135,15 +207,11 @@ pub const Random = struct {
135 }207 }
136 }208 }
137209
138 /// Return a random integer/boolean type.
139 /// TODO: deprecated. use ::boolean or ::int instead.210 /// TODO: deprecated. use ::boolean or ::int instead.
140 pub fn scalar(r: *Random, comptime T: type) T {211 pub fn scalar(r: *Random, comptime T: type) T {
141 if (T == bool) return r.boolean();212 return if (T == bool) r.boolean() else r.int(T);
142 return r.int(T);
143 }213 }
144214
145 /// Return a random integer with even distribution between `start`
146 /// inclusive and `end` exclusive. `start` must be less than `end`.
147 /// TODO: deprecated. renamed to ::intRangeLessThan215 /// TODO: deprecated. renamed to ::intRangeLessThan
148 pub fn range(r: *Random, comptime T: type, start: T, end: T) T {216 pub fn range(r: *Random, comptime T: type, start: T, end: T) T {
149 return r.intRangeLessThan(T, start, end);217 return r.intRangeLessThan(T, start, end);
...@@ -206,6 +274,20 @@ pub const Random = struct {...@@ -206,6 +274,20 @@ pub const Random = struct {
206 }274 }
207};275};
208276
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.
280pub 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
209const SequentialPrng = struct {291const SequentialPrng = struct {
210 const Self = @This();292 const Self = @This();
211 random: Random,293 random: Random,
...@@ -294,10 +376,19 @@ fn testRandomIntLessThan() void {...@@ -294,10 +376,19 @@ fn testRandomIntLessThan() void {
294 var r = SequentialPrng.init();376 var r = SequentialPrng.init();
295 r.next_value = 0xff;377 r.next_value = 0xff;
296 assert(r.random.uintLessThan(u8, 4) == 3);378 assert(r.random.uintLessThan(u8, 4) == 3);
297 r.next_value = 0xff;379 assert(r.next_value == 0);
298 assert(r.random.uintLessThan(u8, 3) == 0);380 assert(r.random.uintLessThan(u8, 4) == 0);
299 assert(r.next_value == 1);381 assert(r.next_value == 1);
300382
383 r.next_value = 0;
384 assert(r.random.uintLessThan(u64, 32) == 0);
385
386 // trigger the bias rejection code path
387 r.next_value = 0;
388 assert(r.random.uintLessThan(u8, 3) == 0);
389 // verify we incremented twice
390 assert(r.next_value == 2);
391
301 r.next_value = 0xff;392 r.next_value = 0xff;
302 assert(r.random.intRangeLessThan(u8, 0, 0x80) == 0x7f);393 assert(r.random.intRangeLessThan(u8, 0, 0x80) == 0x7f);
303 r.next_value = 0xff;394 r.next_value = 0xff;
...@@ -310,17 +401,10 @@ fn testRandomIntLessThan() void {...@@ -310,17 +401,10 @@ fn testRandomIntLessThan() void {
310 r.next_value = 0xff;401 r.next_value = 0xff;
311 assert(r.random.intRangeLessThan(i8, -0x80, 0) == -1);402 assert(r.random.intRangeLessThan(i8, -0x80, 0) == -1);
312403
313 r.next_value = 0xff;
314 assert(r.random.intRangeLessThan(i64, -0x8000000000000000, 0) == -1);
315 r.next_value = 0xff;404 r.next_value = 0xff;
316 assert(r.random.intRangeLessThan(i3, -4, 0) == -1);405 assert(r.random.intRangeLessThan(i3, -4, 0) == -1);
317 r.next_value = 0xff;406 r.next_value = 0xff;
318 assert(r.random.intRangeLessThan(i3, -2, 2) == 1);407 assert(r.random.intRangeLessThan(i3, -2, 2) == 1);
319
320 // test retrying and eventually getting a good value
321 // start just out of bounds
322 r.next_value = 0x81;
323 assert(r.random.uintLessThan(u8, 0x81) == 0);
324}408}
325409
326test "Random intAtMost" {410test "Random intAtMost" {
...@@ -332,9 +416,14 @@ fn testRandomIntAtMost() void {...@@ -332,9 +416,14 @@ fn testRandomIntAtMost() void {
332 var r = SequentialPrng.init();416 var r = SequentialPrng.init();
333 r.next_value = 0xff;417 r.next_value = 0xff;
334 assert(r.random.uintAtMost(u8, 3) == 3);418 assert(r.random.uintAtMost(u8, 3) == 3);
335 r.next_value = 0xff;419 assert(r.next_value == 0);
420 assert(r.random.uintAtMost(u8, 3) == 0);
421
422 // trigger the bias rejection code path
423 r.next_value = 0;
336 assert(r.random.uintAtMost(u8, 2) == 0);424 assert(r.random.uintAtMost(u8, 2) == 0);
337 assert(r.next_value == 1);425 // verify we incremented twice
426 assert(r.next_value == 2);
338427
339 r.next_value = 0xff;428 r.next_value = 0xff;
340 assert(r.random.intRangeAtMost(u8, 0, 0x7f) == 0x7f);429 assert(r.random.intRangeAtMost(u8, 0, 0x7f) == 0x7f);
...@@ -348,17 +437,43 @@ fn testRandomIntAtMost() void {...@@ -348,17 +437,43 @@ fn testRandomIntAtMost() void {
348 r.next_value = 0xff;437 r.next_value = 0xff;
349 assert(r.random.intRangeAtMost(i8, -0x80, -1) == -1);438 assert(r.random.intRangeAtMost(i8, -0x80, -1) == -1);
350439
351 r.next_value = 0xff;
352 assert(r.random.intRangeAtMost(i64, -0x8000000000000000, -1) == -1);
353 r.next_value = 0xff;440 r.next_value = 0xff;
354 assert(r.random.intRangeAtMost(i3, -4, -1) == -1);441 assert(r.random.intRangeAtMost(i3, -4, -1) == -1);
355 r.next_value = 0xff;442 r.next_value = 0xff;
356 assert(r.random.intRangeAtMost(i3, -2, 1) == 1);443 assert(r.random.intRangeAtMost(i3, -2, 1) == 1);
357444
358 // test retrying and eventually getting a good value445 assert(r.random.uintAtMost(u0, 0) == 0);
359 // start just out of bounds446}
360 r.next_value = 0x81;447
361 assert(r.random.uintAtMost(u8, 0x80) == 0);448test "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}
363478
364// Generator to extend 64-bit seed values into longer sequences.479// Generator to extend 64-bit seed values into longer sequences.
...@@ -870,12 +985,16 @@ test "Random range" {...@@ -870,12 +985,16 @@ test "Random range" {
870}985}
871986
872fn testRange(r: *Random, start: i8, end: i8) void {987fn testRange(r: *Random, start: i8, end: i8) void {
988 testRangeBias(r, start, end, true);
989 testRangeBias(r, start, end, false);
990}
991fn testRangeBias(r: *Random, start: i8, end: i8, biased: bool) void {
873 const count = @intCast(usize, i32(end) - i32(start));992 const count = @intCast(usize, i32(end) - i32(start));
874 var values_buffer = []bool{false} ** 0x100;993 var values_buffer = []bool{false} ** 0x100;
875 const values = values_buffer[0..count];994 const values = values_buffer[0..count];
876 var i: usize = 0;995 var i: usize = 0;
877 while (i < count) {996 while (i < count) {
878 const value: i32 = r.intRangeLessThan(i8, start, end);997 const value: i32 = if (biased) r.intRangeLessThanBiased(i8, start, end) else r.intRangeLessThan(i8, start, end);
879 const index = @intCast(usize, value - start);998 const index = @intCast(usize, value - start);
880 if (!values[index]) {999 if (!values[index]) {
881 i += 1;1000 i += 1;
std/rand/ziggurat.zig+1-1
...@@ -12,7 +12,7 @@ const std = @import("../index.zig");...@@ -12,7 +12,7 @@ const std = @import("../index.zig");
12const math = std.math;12const math = std.math;
13const Random = std.rand.Random;13const Random = std.rand.Random;
1414
15pub fn next_f64(random: *Random, comptime tables: *const ZigTable) f64 {15pub fn next_f64(random: *Random, comptime tables: ZigTable) f64 {
16 while (true) {16 while (true) {
17 // We manually construct a float from parts as we can avoid an extra random lookup here by17 // We manually construct a float from parts as we can avoid an extra random lookup here by
18 // using the unused exponent for the lookup table entry.18 // using the unused exponent for the lookup table entry.
std/segmented_list.zig+5
...@@ -201,6 +201,11 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type...@@ -201,6 +201,11 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
201 self.dynamic_segments = self.allocator.shrink([*]T, self.dynamic_segments, new_cap_shelf_count);201 self.dynamic_segments = self.allocator.shrink([*]T, self.dynamic_segments, new_cap_shelf_count);
202 }202 }
203203
204 pub fn shrink(self: *Self, new_len: usize) void {
205 assert(new_len <= self.len);
206 self.len = new_len;
207 }
208
204 pub fn uncheckedAt(self: var, index: usize) AtType(@typeOf(self)) {209 pub fn uncheckedAt(self: var, index: usize) AtType(@typeOf(self)) {
205 if (index < prealloc_item_count) {210 if (index < prealloc_item_count) {
206 return &self.prealloc_segment[index];211 return &self.prealloc_segment[index];
std/special/bootstrap.zig+14-4
...@@ -20,10 +20,17 @@ comptime {...@@ -20,10 +20,17 @@ comptime {
2020
21nakedcc fn _start() noreturn {21nakedcc fn _start() noreturn {
22 switch (builtin.arch) {22 switch (builtin.arch) {
23 builtin.Arch.x86_64 => {23 builtin.Arch.x86_64 => switch (builtin.os) {
24 argc_ptr = asm ("lea (%%rsp), %[argc]"24 builtin.Os.freebsd => {
25 : [argc] "=r" (-> [*]usize)25 argc_ptr = asm ("lea (%%rdi), %[argc]"
26 );26 : [argc] "=r" (-> [*]usize)
27 );
28 },
29 else => {
30 argc_ptr = asm ("lea (%%rsp), %[argc]"
31 : [argc] "=r" (-> [*]usize)
32 );
33 },
27 },34 },
28 builtin.Arch.i386 => {35 builtin.Arch.i386 => {
29 argc_ptr = asm ("lea (%%esp), %[argc]"36 argc_ptr = asm ("lea (%%esp), %[argc]"
...@@ -50,6 +57,9 @@ extern fn WinMainCRTStartup() noreturn {...@@ -50,6 +57,9 @@ extern fn WinMainCRTStartup() noreturn {
5057
51// TODO https://github.com/ziglang/zig/issues/26558// TODO https://github.com/ziglang/zig/issues/265
52fn posixCallMainAndExit() noreturn {59fn posixCallMainAndExit() noreturn {
60 if (builtin.os == builtin.Os.freebsd) {
61 @setAlignStack(16);
62 }
53 const argc = argc_ptr[0];63 const argc = argc_ptr[0];
54 const argv = @ptrCast([*][*]u8, argc_ptr + 1);64 const argv = @ptrCast([*][*]u8, argc_ptr + 1);
5565
std/special/build_runner.zig-1
...@@ -164,7 +164,6 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {...@@ -164,7 +164,6 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
164 \\164 \\
165 \\General Options:165 \\General Options:
166 \\ --help Print this help and exit166 \\ --help Print this help and exit
167 \\ --init Generate a build.zig template
168 \\ --verbose Print commands before executing them167 \\ --verbose Print commands before executing them
169 \\ --prefix [path] Override default install prefix168 \\ --prefix [path] Override default install prefix
170 \\ --search-prefix [path] Add a path to look for binaries, libraries, headers169 \\ --search-prefix [path] Add a path to look for binaries, libraries, headers
std/special/compiler_rt/fixdfdi.zig created+11
...@@ -0,0 +1,11 @@
1const fixint = @import("fixint.zig").fixint;
2const builtin = @import("builtin");
3
4pub extern fn __fixdfdi(a: f64) i64 {
5 @setRuntimeSafety(builtin.is_test);
6 return fixint(f64, i64, a);
7}
8
9test "import fixdfdi" {
10 _ = @import("fixdfdi_test.zig");
11}
std/special/compiler_rt/fixdfdi_test.zig created+66
...@@ -0,0 +1,66 @@
1const __fixdfdi = @import("fixdfdi.zig").__fixdfdi;
2const std = @import("std");
3const math = std.math;
4const assert = std.debug.assert;
5const warn = std.debug.warn;
6
7fn 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
13test "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 @@
1const fixint = @import("fixint.zig").fixint;
2const builtin = @import("builtin");
3
4pub extern fn __fixdfsi(a: f64) i32 {
5 @setRuntimeSafety(builtin.is_test);
6 return fixint(f64, i32, a);
7}
8
9test "import fixdfsi" {
10 _ = @import("fixdfsi_test.zig");
11}
std/special/compiler_rt/fixdfsi_test.zig created+74
...@@ -0,0 +1,74 @@
1const __fixdfsi = @import("fixdfsi.zig").__fixdfsi;
2const std = @import("std");
3const math = std.math;
4const assert = std.debug.assert;
5const warn = std.debug.warn;
6
7fn 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
13test "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 @@
1const fixint = @import("fixint.zig").fixint;
2const builtin = @import("builtin");
3
4pub extern fn __fixdfti(a: f64) i128 {
5 @setRuntimeSafety(builtin.is_test);
6 return fixint(f64, i128, a);
7}
8
9test "import fixdfti" {
10 _ = @import("fixdfti_test.zig");
11}
std/special/compiler_rt/fixdfti_test.zig created+66
...@@ -0,0 +1,66 @@
1const __fixdfti = @import("fixdfti.zig").__fixdfti;
2const std = @import("std");
3const math = std.math;
4const assert = std.debug.assert;
5const warn = std.debug.warn;
6
7fn 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
13test "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 @@
1const is_test = @import("builtin").is_test;
2const std = @import("std");
3const math = std.math;
4const Log2Int = std.math.Log2Int;
5const maxInt = std.math.maxInt;
6const minInt = std.math.minInt;
7
8const DBG = false;
9
10pub 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
72test "import fixint" {
73 _ = @import("fixint_test.zig");
74}
std/special/compiler_rt/fixint_test.zig created+152
...@@ -0,0 +1,152 @@
1const is_test = @import("builtin").is_test;
2const std = @import("std");
3const math = std.math;
4const assert = std.debug.assert;
5const warn = std.debug.warn;
6
7const fixint = @import("fixint.zig").fixint;
8
9fn 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
15test "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
35test "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
56test "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
81test "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
105test "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
130test "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 @@
1const fixint = @import("fixint.zig").fixint;
2const builtin = @import("builtin");
3
4pub extern fn __fixsfdi(a: f32) i64 {
5 @setRuntimeSafety(builtin.is_test);
6 return fixint(f32, i64, a);
7}
8
9test "import fixsfdi" {
10 _ = @import("fixsfdi_test.zig");
11}
std/special/compiler_rt/fixsfdi_test.zig created+68
...@@ -0,0 +1,68 @@
1const __fixsfdi = @import("fixsfdi.zig").__fixsfdi;
2const std = @import("std");
3const math = std.math;
4const assert = std.debug.assert;
5const warn = std.debug.warn;
6
7fn 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
13test "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 @@
1const fixint = @import("fixint.zig").fixint;
2const builtin = @import("builtin");
3
4pub extern fn __fixsfsi(a: f32) i32 {
5 @setRuntimeSafety(builtin.is_test);
6 return fixint(f32, i32, a);
7}
8
9test "import fixsfsi" {
10 _ = @import("fixsfsi_test.zig");
11}
std/special/compiler_rt/fixsfsi_test.zig created+76
...@@ -0,0 +1,76 @@
1const __fixsfsi = @import("fixsfsi.zig").__fixsfsi;
2const std = @import("std");
3const math = std.math;
4const assert = std.debug.assert;
5const warn = std.debug.warn;
6
7fn 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
13test "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 @@
1const fixint = @import("fixint.zig").fixint;
2const builtin = @import("builtin");
3
4pub extern fn __fixsfti(a: f32) i128 {
5 @setRuntimeSafety(builtin.is_test);
6 return fixint(f32, i128, a);
7}
8
9test "import fixsfti" {
10 _ = @import("fixsfti_test.zig");
11}
std/special/compiler_rt/fixsfti_test.zig created+84
...@@ -0,0 +1,84 @@
1const __fixsfti = @import("fixsfti.zig").__fixsfti;
2const std = @import("std");
3const math = std.math;
4const assert = std.debug.assert;
5const warn = std.debug.warn;
6
7fn 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
13test "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 @@
1const fixint = @import("fixint.zig").fixint;
2const builtin = @import("builtin");
3
4pub extern fn __fixtfdi(a: f128) i64 {
5 @setRuntimeSafety(builtin.is_test);
6 return fixint(f128, i64, a);
7}
8
9test "import fixtfdi" {
10 _ = @import("fixtfdi_test.zig");
11}
std/special/compiler_rt/fixtfdi_test.zig created+76
...@@ -0,0 +1,76 @@
1const __fixtfdi = @import("fixtfdi.zig").__fixtfdi;
2const std = @import("std");
3const math = std.math;
4const assert = std.debug.assert;
5const warn = std.debug.warn;
6
7fn 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
13test "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 @@
1const fixint = @import("fixint.zig").fixint;
2const builtin = @import("builtin");
3
4pub extern fn __fixtfsi(a: f128) i32 {
5 @setRuntimeSafety(builtin.is_test);
6 return fixint(f128, i32, a);
7}
8
9test "import fixtfsi" {
10 _ = @import("fixtfsi_test.zig");
11}
std/special/compiler_rt/fixtfsi_test.zig created+76
...@@ -0,0 +1,76 @@
1const __fixtfsi = @import("fixtfsi.zig").__fixtfsi;
2const std = @import("std");
3const math = std.math;
4const assert = std.debug.assert;
5const warn = std.debug.warn;
6
7fn 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
13test "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 @@
1const fixint = @import("fixint.zig").fixint;
2const builtin = @import("builtin");
3
4pub extern fn __fixtfti(a: f128) i128 {
5 @setRuntimeSafety(builtin.is_test);
6 return fixint(f128, i128, a);
7}
8
9test "import fixtfti" {
10 _ = @import("fixtfti_test.zig");
11}
std/special/compiler_rt/fixtfti_test.zig created+66
...@@ -0,0 +1,66 @@
1const __fixtfti = @import("fixtfti.zig").__fixtfti;
2const std = @import("std");
3const math = std.math;
4const assert = std.debug.assert;
5const warn = std.debug.warn;
6
7fn 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
13test "fixtfti" {
14 //warn("\n");
15
16 test__fixtfti(-math.f128_max, math.minInt(i128));
17
18 test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
19 test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
20
21 test__fixtfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
22 test__fixtfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
23 test__fixtfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);
24
25 test__fixtfti(-0x1.0000000000001p+63, -0x8000000000000800);
26 test__fixtfti(-0x1.0000000000000p+63, -0x8000000000000000);
27 test__fixtfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
28 test__fixtfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
29
30 test__fixtfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);
31 test__fixtfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);
32
33 test__fixtfti(-2.01, -2);
34 test__fixtfti(-2.0, -2);
35 test__fixtfti(-1.99, -1);
36 test__fixtfti(-1.0, -1);
37 test__fixtfti(-0.99, 0);
38 test__fixtfti(-0.5, 0);
39 test__fixtfti(-math.f128_min, 0);
40 test__fixtfti(0.0, 0);
41 test__fixtfti(math.f128_min, 0);
42 test__fixtfti(0.5, 0);
43 test__fixtfti(0.99, 0);
44 test__fixtfti(1.0, 1);
45 test__fixtfti(1.5, 1);
46 test__fixtfti(1.99, 1);
47 test__fixtfti(2.0, 2);
48 test__fixtfti(2.01, 2);
49
50 test__fixtfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
51 test__fixtfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
52
53 test__fixtfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
54 test__fixtfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
55 test__fixtfti(0x1.0000000000000p+63, 0x8000000000000000);
56 test__fixtfti(0x1.0000000000001p+63, 0x8000000000000800);
57
58 test__fixtfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
59 test__fixtfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
60 test__fixtfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
61
62 test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
63 test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
64
65 test__fixtfti(math.f128_max, math.maxInt(i128));
66}
std/special/compiler_rt/index.zig+90-63
...@@ -52,6 +52,16 @@ comptime {...@@ -52,6 +52,16 @@ comptime {
52 @export("__fixunstfdi", @import("fixunstfdi.zig").__fixunstfdi, linkage);52 @export("__fixunstfdi", @import("fixunstfdi.zig").__fixunstfdi, linkage);
53 @export("__fixunstfti", @import("fixunstfti.zig").__fixunstfti, linkage);53 @export("__fixunstfti", @import("fixunstfti.zig").__fixunstfti, linkage);
5454
55 @export("__fixdfdi", @import("fixdfdi.zig").__fixdfdi, linkage);
56 @export("__fixdfsi", @import("fixdfsi.zig").__fixdfsi, linkage);
57 @export("__fixdfti", @import("fixdfti.zig").__fixdfti, linkage);
58 @export("__fixsfdi", @import("fixsfdi.zig").__fixsfdi, linkage);
59 @export("__fixsfsi", @import("fixsfsi.zig").__fixsfsi, linkage);
60 @export("__fixsfti", @import("fixsfti.zig").__fixsfti, linkage);
61 @export("__fixtfdi", @import("fixtfdi.zig").__fixtfdi, linkage);
62 @export("__fixtfsi", @import("fixtfsi.zig").__fixtfsi, linkage);
63 @export("__fixtfti", @import("fixtfti.zig").__fixtfti, linkage);
64
55 @export("__udivmoddi4", @import("udivmoddi4.zig").__udivmoddi4, linkage);65 @export("__udivmoddi4", @import("udivmoddi4.zig").__udivmoddi4, linkage);
5666
57 @export("__udivsi3", __udivsi3, linkage);67 @export("__udivsi3", __udivsi3, linkage);
...@@ -59,7 +69,7 @@ comptime {...@@ -59,7 +69,7 @@ comptime {
59 @export("__umoddi3", __umoddi3, linkage);69 @export("__umoddi3", __umoddi3, linkage);
60 @export("__udivmodsi4", __udivmodsi4, linkage);70 @export("__udivmodsi4", __udivmodsi4, linkage);
6171
62 if (isArmArch()) {72 if (is_arm_arch and !is_arm_64) {
63 @export("__aeabi_uldivmod", __aeabi_uldivmod, linkage);73 @export("__aeabi_uldivmod", __aeabi_uldivmod, linkage);
64 @export("__aeabi_uidivmod", __aeabi_uidivmod, linkage);74 @export("__aeabi_uidivmod", __aeabi_uidivmod, linkage);
65 @export("__aeabi_uidiv", __udivsi3, linkage);75 @export("__aeabi_uidiv", __udivsi3, linkage);
...@@ -149,68 +159,85 @@ extern fn __aeabi_uldivmod(numerator: u64, denominator: u64) AeabiUlDivModResult...@@ -149,68 +159,85 @@ extern fn __aeabi_uldivmod(numerator: u64, denominator: u64) AeabiUlDivModResult
149 return result;159 return result;
150}160}
151161
152fn isArmArch() bool {162const is_arm_64 = switch (builtin.arch) {
153 return switch (builtin.arch) {163 builtin.Arch.aarch64v8_3a,
154 builtin.Arch.armv8_3a,164 builtin.Arch.aarch64v8_2a,
155 builtin.Arch.armv8_2a,165 builtin.Arch.aarch64v8_1a,
156 builtin.Arch.armv8_1a,166 builtin.Arch.aarch64v8,
157 builtin.Arch.armv8,167 builtin.Arch.aarch64v8r,
158 builtin.Arch.armv8r,168 builtin.Arch.aarch64v8m_baseline,
159 builtin.Arch.armv8m_baseline,169 builtin.Arch.aarch64v8m_mainline,
160 builtin.Arch.armv8m_mainline,170 builtin.Arch.aarch64_bev8_3a,
161 builtin.Arch.armv7,171 builtin.Arch.aarch64_bev8_2a,
162 builtin.Arch.armv7em,172 builtin.Arch.aarch64_bev8_1a,
163 builtin.Arch.armv7m,173 builtin.Arch.aarch64_bev8,
164 builtin.Arch.armv7s,174 builtin.Arch.aarch64_bev8r,
165 builtin.Arch.armv7k,175 builtin.Arch.aarch64_bev8m_baseline,
166 builtin.Arch.armv7ve,176 builtin.Arch.aarch64_bev8m_mainline,
167 builtin.Arch.armv6,177 => true,
168 builtin.Arch.armv6m,178 else => false,
169 builtin.Arch.armv6k,179};
170 builtin.Arch.armv6t2,180
171 builtin.Arch.armv5,181const is_arm_arch = switch (builtin.arch) {
172 builtin.Arch.armv5te,182 builtin.Arch.armv8_3a,
173 builtin.Arch.armv4t,183 builtin.Arch.armv8_2a,
174 builtin.Arch.armebv8_3a,184 builtin.Arch.armv8_1a,
175 builtin.Arch.armebv8_2a,185 builtin.Arch.armv8,
176 builtin.Arch.armebv8_1a,186 builtin.Arch.armv8r,
177 builtin.Arch.armebv8,187 builtin.Arch.armv8m_baseline,
178 builtin.Arch.armebv8r,188 builtin.Arch.armv8m_mainline,
179 builtin.Arch.armebv8m_baseline,189 builtin.Arch.armv7,
180 builtin.Arch.armebv8m_mainline,190 builtin.Arch.armv7em,
181 builtin.Arch.armebv7,191 builtin.Arch.armv7m,
182 builtin.Arch.armebv7em,192 builtin.Arch.armv7s,
183 builtin.Arch.armebv7m,193 builtin.Arch.armv7k,
184 builtin.Arch.armebv7s,194 builtin.Arch.armv7ve,
185 builtin.Arch.armebv7k,195 builtin.Arch.armv6,
186 builtin.Arch.armebv7ve,196 builtin.Arch.armv6m,
187 builtin.Arch.armebv6,197 builtin.Arch.armv6k,
188 builtin.Arch.armebv6m,198 builtin.Arch.armv6t2,
189 builtin.Arch.armebv6k,199 builtin.Arch.armv5,
190 builtin.Arch.armebv6t2,200 builtin.Arch.armv5te,
191 builtin.Arch.armebv5,201 builtin.Arch.armv4t,
192 builtin.Arch.armebv5te,202 builtin.Arch.armebv8_3a,
193 builtin.Arch.armebv4t,203 builtin.Arch.armebv8_2a,
194 builtin.Arch.aarch64v8_3a,204 builtin.Arch.armebv8_1a,
195 builtin.Arch.aarch64v8_2a,205 builtin.Arch.armebv8,
196 builtin.Arch.aarch64v8_1a,206 builtin.Arch.armebv8r,
197 builtin.Arch.aarch64v8,207 builtin.Arch.armebv8m_baseline,
198 builtin.Arch.aarch64v8r,208 builtin.Arch.armebv8m_mainline,
199 builtin.Arch.aarch64v8m_baseline,209 builtin.Arch.armebv7,
200 builtin.Arch.aarch64v8m_mainline,210 builtin.Arch.armebv7em,
201 builtin.Arch.aarch64_bev8_3a,211 builtin.Arch.armebv7m,
202 builtin.Arch.aarch64_bev8_2a,212 builtin.Arch.armebv7s,
203 builtin.Arch.aarch64_bev8_1a,213 builtin.Arch.armebv7k,
204 builtin.Arch.aarch64_bev8,214 builtin.Arch.armebv7ve,
205 builtin.Arch.aarch64_bev8r,215 builtin.Arch.armebv6,
206 builtin.Arch.aarch64_bev8m_baseline,216 builtin.Arch.armebv6m,
207 builtin.Arch.aarch64_bev8m_mainline,217 builtin.Arch.armebv6k,
208 builtin.Arch.thumb,218 builtin.Arch.armebv6t2,
209 builtin.Arch.thumbeb,219 builtin.Arch.armebv5,
210 => true,220 builtin.Arch.armebv5te,
211 else => false,221 builtin.Arch.armebv4t,
212 };222 builtin.Arch.aarch64v8_3a,
213}223 builtin.Arch.aarch64v8_2a,
224 builtin.Arch.aarch64v8_1a,
225 builtin.Arch.aarch64v8,
226 builtin.Arch.aarch64v8r,
227 builtin.Arch.aarch64v8m_baseline,
228 builtin.Arch.aarch64v8m_mainline,
229 builtin.Arch.aarch64_bev8_3a,
230 builtin.Arch.aarch64_bev8_2a,
231 builtin.Arch.aarch64_bev8_1a,
232 builtin.Arch.aarch64_bev8,
233 builtin.Arch.aarch64_bev8r,
234 builtin.Arch.aarch64_bev8m_baseline,
235 builtin.Arch.aarch64_bev8m_mainline,
236 builtin.Arch.thumb,
237 builtin.Arch.thumbeb,
238 => true,
239 else => false,
240};
214241
215nakedcc fn __aeabi_uidivmod() void {242nakedcc fn __aeabi_uidivmod() void {
216 @setRuntimeSafety(false);243 @setRuntimeSafety(false);
std/unicode.zig+16-16
...@@ -208,7 +208,7 @@ pub const Utf8View = struct {...@@ -208,7 +208,7 @@ pub const Utf8View = struct {
208 }208 }
209};209};
210210
211const Utf8Iterator = struct {211pub const Utf8Iterator = struct {
212 bytes: []const u8,212 bytes: []const u8,
213 i: usize,213 i: usize,
214214
...@@ -249,12 +249,12 @@ pub const Utf16LeIterator = struct {...@@ -249,12 +249,12 @@ pub const Utf16LeIterator = struct {
249 pub fn nextCodepoint(it: *Utf16LeIterator) !?u32 {249 pub fn nextCodepoint(it: *Utf16LeIterator) !?u32 {
250 assert(it.i <= it.bytes.len);250 assert(it.i <= it.bytes.len);
251 if (it.i == it.bytes.len) return null;251 if (it.i == it.bytes.len) return null;
252 const c0: u32 = mem.readIntLE(u16, it.bytes[it.i .. it.i + 2]);252 const c0: u32 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]);
253 if (c0 & ~u32(0x03ff) == 0xd800) {253 if (c0 & ~u32(0x03ff) == 0xd800) {
254 // surrogate pair254 // surrogate pair
255 it.i += 2;255 it.i += 2;
256 if (it.i >= it.bytes.len) return error.DanglingSurrogateHalf;256 if (it.i >= it.bytes.len) return error.DanglingSurrogateHalf;
257 const c1: u32 = mem.readIntLE(u16, it.bytes[it.i .. it.i + 2]);257 const c1: u32 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]);
258 if (c1 & ~u32(0x03ff) != 0xdc00) return error.ExpectedSecondSurrogateHalf;258 if (c1 & ~u32(0x03ff) != 0xdc00) return error.ExpectedSecondSurrogateHalf;
259 it.i += 2;259 it.i += 2;
260 return 0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff));260 return 0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff));
...@@ -510,46 +510,46 @@ test "utf16leToUtf8" {...@@ -510,46 +510,46 @@ test "utf16leToUtf8" {
510 const utf16le_as_bytes = @sliceToBytes(utf16le[0..]);510 const utf16le_as_bytes = @sliceToBytes(utf16le[0..]);
511511
512 {512 {
513 mem.writeInt(utf16le_as_bytes[0..], u16('A'), builtin.Endian.Little);513 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 'A');
514 mem.writeInt(utf16le_as_bytes[2..], u16('a'), builtin.Endian.Little);514 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 'a');
515 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);515 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
516 assert(mem.eql(u8, utf8, "Aa"));516 assert(mem.eql(u8, utf8, "Aa"));
517 }517 }
518518
519 {519 {
520 mem.writeInt(utf16le_as_bytes[0..], u16(0x80), builtin.Endian.Little);520 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0x80);
521 mem.writeInt(utf16le_as_bytes[2..], u16(0xffff), builtin.Endian.Little);521 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xffff);
522 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);522 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
523 assert(mem.eql(u8, utf8, "\xc2\x80" ++ "\xef\xbf\xbf"));523 assert(mem.eql(u8, utf8, "\xc2\x80" ++ "\xef\xbf\xbf"));
524 }524 }
525525
526 {526 {
527 // the values just outside the surrogate half range527 // the values just outside the surrogate half range
528 mem.writeInt(utf16le_as_bytes[0..], u16(0xd7ff), builtin.Endian.Little);528 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd7ff);
529 mem.writeInt(utf16le_as_bytes[2..], u16(0xe000), builtin.Endian.Little);529 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xe000);
530 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);530 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
531 assert(mem.eql(u8, utf8, "\xed\x9f\xbf" ++ "\xee\x80\x80"));531 assert(mem.eql(u8, utf8, "\xed\x9f\xbf" ++ "\xee\x80\x80"));
532 }532 }
533533
534 {534 {
535 // smallest surrogate pair535 // smallest surrogate pair
536 mem.writeInt(utf16le_as_bytes[0..], u16(0xd800), builtin.Endian.Little);536 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd800);
537 mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little);537 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00);
538 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);538 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
539 assert(mem.eql(u8, utf8, "\xf0\x90\x80\x80"));539 assert(mem.eql(u8, utf8, "\xf0\x90\x80\x80"));
540 }540 }
541541
542 {542 {
543 // largest surrogate pair543 // largest surrogate pair
544 mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little);544 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff);
545 mem.writeInt(utf16le_as_bytes[2..], u16(0xdfff), builtin.Endian.Little);545 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdfff);
546 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);546 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
547 assert(mem.eql(u8, utf8, "\xf4\x8f\xbf\xbf"));547 assert(mem.eql(u8, utf8, "\xf4\x8f\xbf\xbf"));
548 }548 }
549549
550 {550 {
551 mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little);551 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff);
552 mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little);552 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00);
553 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);553 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
554 assert(mem.eql(u8, utf8, "\xf4\x8f\xb0\x80"));554 assert(mem.eql(u8, utf8, "\xf4\x8f\xb0\x80"));
555 }555 }
...@@ -583,7 +583,7 @@ pub fn utf8ToUtf16Le(utf16le: []u16, utf8: []const u8) !usize {...@@ -583,7 +583,7 @@ pub fn utf8ToUtf16Le(utf16le: []u16, utf8: []const u8) !usize {
583 while (it.nextCodepoint()) |codepoint| {583 while (it.nextCodepoint()) |codepoint| {
584 if (end_index == utf16le_as_bytes.len) return (end_index / 2) + 1;584 if (end_index == utf16le_as_bytes.len) return (end_index / 2) + 1;
585 // TODO surrogate pairs585 // TODO surrogate pairs
586 mem.writeInt(utf16le_as_bytes[end_index..], @intCast(u16, codepoint), builtin.Endian.Little);586 mem.writeIntSliceLittle(u16, utf16le_as_bytes[end_index..], @intCast(u16, codepoint));
587 end_index += 2;587 end_index += 2;
588 }588 }
589 return end_index / 2;589 return end_index / 2;
test/behavior.zig+4
...@@ -8,6 +8,7 @@ comptime {...@@ -8,6 +8,7 @@ comptime {
8 _ = @import("cases/atomics.zig");8 _ = @import("cases/atomics.zig");
9 _ = @import("cases/bitcast.zig");9 _ = @import("cases/bitcast.zig");
10 _ = @import("cases/bool.zig");10 _ = @import("cases/bool.zig");
11 _ = @import("cases/bswap.zig");
11 _ = @import("cases/bugs/1076.zig");12 _ = @import("cases/bugs/1076.zig");
12 _ = @import("cases/bugs/1111.zig");13 _ = @import("cases/bugs/1111.zig");
13 _ = @import("cases/bugs/1277.zig");14 _ = @import("cases/bugs/1277.zig");
...@@ -41,6 +42,7 @@ comptime {...@@ -41,6 +42,7 @@ comptime {
41 _ = @import("cases/if.zig");42 _ = @import("cases/if.zig");
42 _ = @import("cases/import.zig");43 _ = @import("cases/import.zig");
43 _ = @import("cases/incomplete_struct_param_tld.zig");44 _ = @import("cases/incomplete_struct_param_tld.zig");
45 _ = @import("cases/inttoptr.zig");
44 _ = @import("cases/ir_block_deps.zig");46 _ = @import("cases/ir_block_deps.zig");
45 _ = @import("cases/math.zig");47 _ = @import("cases/math.zig");
46 _ = @import("cases/merge_error_sets.zig");48 _ = @import("cases/merge_error_sets.zig");
...@@ -51,6 +53,7 @@ comptime {...@@ -51,6 +53,7 @@ comptime {
51 _ = @import("cases/optional.zig");53 _ = @import("cases/optional.zig");
52 _ = @import("cases/pointers.zig");54 _ = @import("cases/pointers.zig");
53 _ = @import("cases/popcount.zig");55 _ = @import("cases/popcount.zig");
56 _ = @import("cases/ptrcast.zig");
54 _ = @import("cases/pub_enum/index.zig");57 _ = @import("cases/pub_enum/index.zig");
55 _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");58 _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
56 _ = @import("cases/reflection.zig");59 _ = @import("cases/reflection.zig");
...@@ -64,6 +67,7 @@ comptime {...@@ -64,6 +67,7 @@ comptime {
64 _ = @import("cases/switch_prong_implicit_cast.zig");67 _ = @import("cases/switch_prong_implicit_cast.zig");
65 _ = @import("cases/syntax.zig");68 _ = @import("cases/syntax.zig");
66 _ = @import("cases/this.zig");69 _ = @import("cases/this.zig");
70 _ = @import("cases/truncate.zig");
67 _ = @import("cases/try.zig");71 _ = @import("cases/try.zig");
68 _ = @import("cases/type_info.zig");72 _ = @import("cases/type_info.zig");
69 _ = @import("cases/undefined.zig");73 _ = @import("cases/undefined.zig");
test/cases/asm.zig+24
...@@ -17,6 +17,30 @@ test "module level assembly" {...@@ -17,6 +17,30 @@ test "module level assembly" {
17 }17 }
18}18}
1919
20test "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
27test "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
33test "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
20extern fn aoeu() i32;44extern fn aoeu() i32;
2145
22export fn derp() i32 {46export fn derp() i32 {
test/cases/bswap.zig created+32
...@@ -0,0 +1,32 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "@bswap" {
5 comptime testByteSwap();
6 testByteSwap();
7}
8
9fn testByteSwap() void {
10 assert(@bswap(u0, 0) == 0);
11 assert(@bswap(u8, 0x12) == 0x12);
12 assert(@bswap(u16, 0x1234) == 0x3412);
13 assert(@bswap(u24, 0x123456) == 0x563412);
14 assert(@bswap(u32, 0x12345678) == 0x78563412);
15 assert(@bswap(u40, 0x123456789a) == 0x9a78563412);
16 assert(@bswap(u48, 0x123456789abc) == 0xbc9a78563412);
17 assert(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412);
18 assert(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412);
19 assert(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412);
20
21 assert(@bswap(i0, 0) == 0);
22 assert(@bswap(i8, -50) == -50);
23 assert(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412)));
24 assert(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412)));
25 assert(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412)));
26 assert(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412)));
27 assert(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412)));
28 assert(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412)));
29 assert(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412)));
30 assert(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) ==
31 @bitCast(i128, u128(0x8171615141312111f1debc9a78563412)));
32}
test/cases/cast.zig+18
...@@ -452,3 +452,21 @@ test "implicit ptr to *c_void" {...@@ -452,3 +452,21 @@ test "implicit ptr to *c_void" {
452 var c: *u32 = @ptrCast(*u32, ptr2.?);452 var c: *u32 = @ptrCast(*u32, ptr2.?);
453 assert(c.* == 1);453 assert(c.* == 1);
454}454}
455
456test "@intCast to comptime_int" {
457 assert(@intCast(comptime_int, 0) == 0);
458}
459
460test "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
466test "@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 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const assertOrPanic = std.debug.assertOrPanic;
4
5test "casting random address to function pointer" {
6 randomAddressToFunction();
7 comptime randomAddressToFunction();
8}
9
10fn 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 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const assertOrPanic = std.debug.assertOrPanic;
4
5test "reinterpret bytes as integer with nonzero offset" {
6 testReinterpretBytesAsInteger();
7 comptime testReinterpretBytesAsInteger();
8}
9
10fn 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
19test "reinterpret bytes of an array into an extern struct" {
20 testReinterpretBytesAsExternStruct();
21 comptime testReinterpretBytesAsExternStruct();
22}
23
24fn testReinterpretBytesAsExternStruct() void {
25 var bytes align(2) = []u8{ 1, 2, 3, 4, 5, 6 };
26
27 const S = extern struct {
28 a: u8,
29 b: u16,
30 c: u8,
31 };
32
33 var ptr = @ptrCast(*const S, &bytes);
34 var val = ptr.c;
35 assertOrPanic(val == 5);
36}
test/cases/struct_contains_slice_of_itself.zig+42
...@@ -5,6 +5,11 @@ const Node = struct {...@@ -5,6 +5,11 @@ const Node = struct {
5 children: []Node,5 children: []Node,
6};6};
77
8const NodeAligned = struct {
9 payload: i32,
10 children: []align(@alignOf(NodeAligned)) NodeAligned,
11};
12
8test "struct contains slice of itself" {13test "struct contains slice of itself" {
9 var other_nodes = []Node{14 var other_nodes = []Node{
10 Node{15 Node{
...@@ -41,3 +46,40 @@ test "struct contains slice of itself" {...@@ -41,3 +46,40 @@ test "struct contains slice of itself" {
41 assert(root.children[2].children[0].payload == 31);46 assert(root.children[2].children[0].payload == 31);
42 assert(root.children[2].children[1].payload == 32);47 assert(root.children[2].children[1].payload == 32);
43}48}
49
50test "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 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "truncate u0 to larger integer allowed and has comptime known result" {
5 var x: u0 = 0;
6 const y = @truncate(u8, x);
7 comptime assert(y == 0);
8}
test/compile_errors.zig+109-31
...@@ -1,6 +1,85 @@...@@ -1,6 +1,85 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
22
3pub fn addCases(cases: *tests.CompileErrorContext) void {3pub fn addCases(cases: *tests.CompileErrorContext) void {
4 cases.add(
5 "reading past end of pointer casted array",
6 \\comptime {
7 \\ const array = "aoeu";
8 \\ const slice = array[2..];
9 \\ const int_ptr = @ptrCast(*const u24, slice.ptr);
10 \\ const deref = int_ptr.*;
11 \\}
12 ,
13 ".tmp_source.zig:5:26: error: attempt to read 3 bytes from [4]u8 at index 2 which is 2 bytes",
14 );
15
16 cases.add(
17 "error note for function parameter incompatibility",
18 \\fn do_the_thing(func: fn (arg: i32) void) void {}
19 \\fn bar(arg: bool) void {}
20 \\export fn entry() void {
21 \\ do_the_thing(bar);
22 \\}
23 ,
24 ".tmp_source.zig:4:18: error: expected type 'fn(i32) void', found 'fn(bool) void",
25 ".tmp_source.zig:4:18: note: parameter 0: 'bool' cannot cast into 'i32'",
26 );
27
28 cases.add(
29 "cast negative value to unsigned integer",
30 \\comptime {
31 \\ const value: i32 = -1;
32 \\ const unsigned = @intCast(u32, value);
33 \\}
34 \\export fn entry1() void {
35 \\ const value: i32 = -1;
36 \\ const unsigned: u32 = value;
37 \\}
38 ,
39 ".tmp_source.zig:3:36: error: cannot cast negative value -1 to unsigned integer type 'u32'",
40 ".tmp_source.zig:7:27: error: cannot cast negative value -1 to unsigned integer type 'u32'",
41 );
42
43 cases.add(
44 "integer cast truncates bits",
45 \\export fn entry1() void {
46 \\ const spartan_count: u16 = 300;
47 \\ const byte = @intCast(u8, spartan_count);
48 \\}
49 \\export fn entry2() void {
50 \\ const spartan_count: u16 = 300;
51 \\ const byte: u8 = spartan_count;
52 \\}
53 \\export fn entry3() void {
54 \\ var spartan_count: u16 = 300;
55 \\ var byte: u8 = spartan_count;
56 \\}
57 ,
58 ".tmp_source.zig:3:31: error: integer value 300 cannot be implicitly casted to type 'u8'",
59 ".tmp_source.zig:7:22: error: integer value 300 cannot be implicitly casted to type 'u8'",
60 ".tmp_source.zig:11:20: error: expected type 'u8', found 'u16'",
61 );
62
63 cases.add(
64 "comptime implicit cast f64 to f32",
65 \\export fn entry() void {
66 \\ const x: f64 = 16777217;
67 \\ const y: f32 = x;
68 \\}
69 ,
70 ".tmp_source.zig:3:20: error: cast of value 16777217.000000 to type 'f32' loses information",
71 );
72
73 cases.add(
74 "implicit cast from f64 to f32",
75 \\var x: f64 = 1.0;
76 \\var y: f32 = x;
77 \\
78 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }
79 ,
80 ".tmp_source.zig:2:14: error: expected type 'f32', found 'f64'",
81 );
82
4 cases.add(83 cases.add(
5 "exceeded maximum bit width of integer",84 "exceeded maximum bit width of integer",
6 \\export fn entry1() void {85 \\export fn entry1() void {
...@@ -1819,7 +1898,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1819,7 +1898,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1819 \\ if (0) {}1898 \\ if (0) {}
1820 \\}1899 \\}
1821 ,1900 ,
1822 ".tmp_source.zig:2:9: error: integer value 0 cannot be implicitly casted to type 'bool'",1901 ".tmp_source.zig:2:9: error: expected type 'bool', found 'comptime_int'",
1823 );1902 );
18241903
1825 cases.add(1904 cases.add(
...@@ -2422,16 +2501,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2422,16 +2501,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2422 ".tmp_source.zig:1:36: error: expected type 'fn(i32) i32', found 'extern fn(i32) i32'",2501 ".tmp_source.zig:1:36: error: expected type 'fn(i32) i32', found 'extern fn(i32) i32'",
2423 );2502 );
24242503
2425 cases.add(
2426 "implicit cast from f64 to f32",
2427 \\const x : f64 = 1.0;
2428 \\const y : f32 = x;
2429 \\
2430 \\export fn entry() usize { return @sizeOf(@typeOf(y)); }
2431 ,
2432 ".tmp_source.zig:2:17: error: expected type 'f32', found 'f64'",
2433 );
2434
2435 cases.add(2504 cases.add(
2436 "colliding invalid top level functions",2505 "colliding invalid top level functions",
2437 \\fn func() bogus {}2506 \\fn func() bogus {}
...@@ -3174,6 +3243,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3174,6 +3243,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3174 \\fn something() anyerror!void { }3243 \\fn something() anyerror!void { }
3175 ,3244 ,
3176 ".tmp_source.zig:2:5: error: expected type 'void', found 'anyerror'",3245 ".tmp_source.zig:2:5: error: expected type 'void', found 'anyerror'",
3246 ".tmp_source.zig:1:15: note: return type declared here",
3177 );3247 );
31783248
3179 cases.add(3249 cases.add(
...@@ -4049,16 +4119,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4049,16 +4119,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4049 ".tmp_source.zig:2:14: error: remainder division with 'i32' and 'i32': signed integers and floats must use @rem or @mod",4119 ".tmp_source.zig:2:14: error: remainder division with 'i32' and 'i32': signed integers and floats must use @rem or @mod",
4050 );4120 );
40514121
4052 cases.add(
4053 "cast negative value to unsigned integer",
4054 \\comptime {
4055 \\ const value: i32 = -1;
4056 \\ const unsigned = @intCast(u32, value);
4057 \\}
4058 ,
4059 ".tmp_source.zig:3:22: error: attempt to cast negative value to unsigned integer",
4060 );
4061
4062 cases.add(4122 cases.add(
4063 "compile-time division by zero",4123 "compile-time division by zero",
4064 \\comptime {4124 \\comptime {
...@@ -4081,16 +4141,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4081,16 +4141,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4081 ".tmp_source.zig:4:17: error: division by zero",4141 ".tmp_source.zig:4:17: error: division by zero",
4082 );4142 );
40834143
4084 cases.add(
4085 "compile-time integer cast truncates bits",
4086 \\comptime {
4087 \\ const spartan_count: u16 = 300;
4088 \\ const byte = @intCast(u8, spartan_count);
4089 \\}
4090 ,
4091 ".tmp_source.zig:3:18: error: cast from 'u16' to 'u8' truncates bits",
4092 );
4093
4094 cases.add(4144 cases.add(
4095 "@setRuntimeSafety twice for same scope",4145 "@setRuntimeSafety twice for same scope",
4096 \\export fn foo() void {4146 \\export fn foo() void {
...@@ -5206,4 +5256,32 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5206,4 +5256,32 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5206 ,5256 ,
5207 ".tmp_source.zig:3:36: error: @ArgType could not resolve the type of arg 0 because 'fn(var)var' is generic",5257 ".tmp_source.zig:3:36: error: @ArgType could not resolve the type of arg 0 because 'fn(var)var' is generic",
5208 );5258 );
5259
5260 cases.add(
5261 "unsupported modifier at start of asm output constraint",
5262 \\export fn foo() void {
5263 \\ var bar: u32 = 3;
5264 \\ asm volatile ("" : [baz]"+r"(bar) : : "");
5265 \\}
5266 ,
5267 ".tmp_source.zig:3:5: error: invalid modifier starting output constraint for 'baz': '+', only '=' is supported. Compiler TODO: see https://github.com/ziglang/zig/issues/215",
5268 );
5269
5270 cases.add(
5271 "comptime_int in asm input",
5272 \\export fn foo() void {
5273 \\ asm volatile ("" : : [bar]"r"(3) : "");
5274 \\}
5275 ,
5276 ".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_int",
5277 );
5278
5279 cases.add(
5280 "comptime_float in asm input",
5281 \\export fn foo() void {
5282 \\ asm volatile ("" : : [bar]"r"(3.17) : "");
5283 \\}
5284 ,
5285 ".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_float",
5286 );
5209}5287}
test/runtime_safety.zig+10
...@@ -275,6 +275,16 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -275,6 +275,16 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
275 \\}275 \\}
276 );276 );
277277
278 cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer - widening",
279 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
280 \\ @import("std").os.exit(126);
281 \\}
282 \\pub fn main() void {
283 \\ var value: c_short = -1;
284 \\ var casted = @intCast(u32, value);
285 \\}
286 );
287
278 cases.addRuntimeSafety("unwrap error",288 cases.addRuntimeSafety("unwrap error",
279 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {289 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
280 \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) {290 \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) {