Merge remote-tracking branch 'origin/master' into llvm8
commit
c00216701c
|
@ -0,0 +1,22 @@
|
||||||
|
arch: x86_64
|
||||||
|
image: freebsd
|
||||||
|
packages:
|
||||||
|
- cmake
|
||||||
|
- ninja
|
||||||
|
- llvm70
|
||||||
|
sources:
|
||||||
|
- https://github.com/ziglang/zig.git
|
||||||
|
tasks:
|
||||||
|
- build: |
|
||||||
|
cd zig && mkdir build && cd build
|
||||||
|
cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release
|
||||||
|
ninja install
|
||||||
|
- test: |
|
||||||
|
cd zig/build
|
||||||
|
bin/zig test ../test/behavior.zig
|
||||||
|
# TODO enable all tests
|
||||||
|
#bin/zig build --build-file ../build.zig test
|
||||||
|
# TODO integrate with the download page updater and make a
|
||||||
|
# static build available to download for FreeBSD.
|
||||||
|
# This will require setting up a cache of LLVM/Clang built
|
||||||
|
# statically.
|
|
@ -444,6 +444,7 @@ set(ZIG_STD_FILES
|
||||||
"buffer.zig"
|
"buffer.zig"
|
||||||
"build.zig"
|
"build.zig"
|
||||||
"c/darwin.zig"
|
"c/darwin.zig"
|
||||||
|
"c/freebsd.zig"
|
||||||
"c/index.zig"
|
"c/index.zig"
|
||||||
"c/linux.zig"
|
"c/linux.zig"
|
||||||
"c/windows.zig"
|
"c/windows.zig"
|
||||||
|
@ -490,6 +491,7 @@ set(ZIG_STD_FILES
|
||||||
"heap.zig"
|
"heap.zig"
|
||||||
"index.zig"
|
"index.zig"
|
||||||
"io.zig"
|
"io.zig"
|
||||||
|
"io/seekable_stream.zig"
|
||||||
"json.zig"
|
"json.zig"
|
||||||
"lazy_init.zig"
|
"lazy_init.zig"
|
||||||
"linked_list.zig"
|
"linked_list.zig"
|
||||||
|
@ -582,6 +584,10 @@ set(ZIG_STD_FILES
|
||||||
"os/linux/vdso.zig"
|
"os/linux/vdso.zig"
|
||||||
"os/linux/x86_64.zig"
|
"os/linux/x86_64.zig"
|
||||||
"os/linux/arm64.zig"
|
"os/linux/arm64.zig"
|
||||||
|
"os/freebsd/errno.zig"
|
||||||
|
"os/freebsd/index.zig"
|
||||||
|
"os/freebsd/syscall.zig"
|
||||||
|
"os/freebsd/x86_64.zig"
|
||||||
"os/path.zig"
|
"os/path.zig"
|
||||||
"os/time.zig"
|
"os/time.zig"
|
||||||
"os/windows/advapi32.zig"
|
"os/windows/advapi32.zig"
|
||||||
|
@ -617,6 +623,16 @@ set(ZIG_STD_FILES
|
||||||
"special/compiler_rt/fixunstfdi.zig"
|
"special/compiler_rt/fixunstfdi.zig"
|
||||||
"special/compiler_rt/fixunstfsi.zig"
|
"special/compiler_rt/fixunstfsi.zig"
|
||||||
"special/compiler_rt/fixunstfti.zig"
|
"special/compiler_rt/fixunstfti.zig"
|
||||||
|
"special/compiler_rt/fixint.zig"
|
||||||
|
"special/compiler_rt/fixdfdi.zig"
|
||||||
|
"special/compiler_rt/fixdfsi.zig"
|
||||||
|
"special/compiler_rt/fixdfti.zig"
|
||||||
|
"special/compiler_rt/fixsfdi.zig"
|
||||||
|
"special/compiler_rt/fixsfsi.zig"
|
||||||
|
"special/compiler_rt/fixsfti.zig"
|
||||||
|
"special/compiler_rt/fixtfdi.zig"
|
||||||
|
"special/compiler_rt/fixtfsi.zig"
|
||||||
|
"special/compiler_rt/fixtfti.zig"
|
||||||
"special/compiler_rt/floattidf.zig"
|
"special/compiler_rt/floattidf.zig"
|
||||||
"special/compiler_rt/floattisf.zig"
|
"special/compiler_rt/floattisf.zig"
|
||||||
"special/compiler_rt/floattitf.zig"
|
"special/compiler_rt/floattitf.zig"
|
||||||
|
|
95
README.md
95
README.md
|
@ -42,33 +42,71 @@ clarity.
|
||||||
* In addition to creating executables, creating a C library is a primary use
|
* In addition to creating executables, creating a C library is a primary use
|
||||||
case. You can export an auto-generated .h file.
|
case. You can export an auto-generated .h file.
|
||||||
|
|
||||||
### Support Table
|
### Supported Targets
|
||||||
|
|
||||||
Freestanding means that you do not directly interact with the OS
|
#### Tier 1 Support
|
||||||
or you are writing your own OS.
|
|
||||||
|
|
||||||
Note that if you use libc or other libraries to interact with the OS,
|
* Not only can Zig generate machine code for these targets, but the standard
|
||||||
that counts as "freestanding" for the purposes of this table.
|
library cross-platform abstractions have implementations for these targets.
|
||||||
|
Thus it is practical to write a pure Zig application with no dependency on
|
||||||
|
libc.
|
||||||
|
* The CI server automatically tests these targets on every commit to master
|
||||||
|
branch, and updates ziglang.org/download with links to pre-built binaries.
|
||||||
|
* These targets have debug info capabilities and therefore produce stack
|
||||||
|
traces on failed assertions.
|
||||||
|
|
||||||
| | freestanding | linux | macosx | windows | other |
|
#### Tier 2 Support
|
||||||
|-------------|--------------|---------|---------|---------|---------|
|
|
||||||
|i386 | OK | planned | OK | planned | planned |
|
* There may be some standard library implementations, but many abstractions
|
||||||
|x86_64 | OK | OK | OK | OK | planned |
|
will give an "Unsupported OS" compile error. One can link with libc or other
|
||||||
|arm | OK | planned | planned | planned | planned |
|
libraries to fill in the gaps in the standard library.
|
||||||
|bpf | OK | planned | N/A | N/A | planned |
|
* These targets are known to work, but are not automatically tested, so there
|
||||||
|hexagon | OK | planned | N/A | N/A | planned |
|
are occasional regressions.
|
||||||
|mips | OK | planned | N/A | N/A | planned |
|
* Some tests may be disabled for these targets as we work toward Tier 1
|
||||||
|powerpc | OK | planned | N/A | N/A | planned |
|
support.
|
||||||
|r600 | OK | planned | N/A | N/A | planned |
|
|
||||||
|amdgcn | OK | planned | N/A | N/A | planned |
|
#### Tier 3 Support
|
||||||
|sparc | OK | planned | N/A | N/A | planned |
|
|
||||||
|s390x | OK | planned | N/A | N/A | planned |
|
* The standard library has little to no knowledge of the existence of this
|
||||||
|spir | OK | planned | N/A | N/A | planned |
|
target.
|
||||||
|lanai | OK | planned | N/A | N/A | planned |
|
* Because Zig is based on LLVM, it has the capability to build for these
|
||||||
|wasm32 | planned | N/A | N/A | N/A | N/A |
|
targets, and LLVM has the target enabled by default.
|
||||||
|wasm64 | planned | N/A | N/A | N/A | N/A |
|
* These targets are not frequently tested; one will likely need to contribute
|
||||||
|riscv32 | planned | planned | N/A | N/A | planned |
|
to Zig in order to build for these targets.
|
||||||
|riscv64 | planned | planned | N/A | N/A | planned |
|
* The Zig compiler might need to be updated with a few things such as
|
||||||
|
- what sizes are the C integer types
|
||||||
|
- C ABI calling convention for this target
|
||||||
|
- bootstrap code and default panic handler
|
||||||
|
|
||||||
|
#### Tier 4 Support
|
||||||
|
|
||||||
|
* Support for these targets is entirely experimental.
|
||||||
|
* LLVM may have the target as an experimental target, which means that you
|
||||||
|
need to use Zig-provided binaries for the target to be available, or
|
||||||
|
build LLVM from source with special configure flags.
|
||||||
|
|
||||||
|
#### Support Table
|
||||||
|
|
||||||
|
| | freestanding | linux | macosx | windows | freebsd | other |
|
||||||
|
|--------|--------------|--------|--------|---------|---------|--------|
|
||||||
|
|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 3 |
|
||||||
|
|i386 | Tier 2 | Tier 2 | Tier 2 | Tier 2 | Tier 3 | Tier 3 |
|
||||||
|
|arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
|
||||||
|
|arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
|
||||||
|
|bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
|
||||||
|
|hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
|
||||||
|
|mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
|
||||||
|
|powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
|
||||||
|
|r600 | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
|
||||||
|
|amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
|
||||||
|
|sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
|
||||||
|
|s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
|
||||||
|
|spir | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
|
||||||
|
|lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
|
||||||
|
|wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A |
|
||||||
|
|wasm64 | Tier 4 | N/A | N/A | N/A | N/A | N/A |
|
||||||
|
|riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 |
|
||||||
|
|riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 |
|
||||||
|
|
||||||
## Community
|
## Community
|
||||||
|
|
||||||
|
@ -133,7 +171,8 @@ See https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows
|
||||||
*Note: Stage 2 compiler is not complete. Beta users of Zig should use the
|
*Note: Stage 2 compiler is not complete. Beta users of Zig should use the
|
||||||
Stage 1 compiler for now.*
|
Stage 1 compiler for now.*
|
||||||
|
|
||||||
Dependencies are the same as Stage 1, except now you have a working zig compiler.
|
Dependencies are the same as Stage 1, except now you can use stage 1 to compile
|
||||||
|
Zig code.
|
||||||
|
|
||||||
```
|
```
|
||||||
bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install
|
bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install
|
||||||
|
@ -145,11 +184,13 @@ binary.
|
||||||
|
|
||||||
### Stage 3: Rebuild Self-Hosted Zig Using the Self-Hosted Compiler
|
### Stage 3: Rebuild Self-Hosted Zig Using the Self-Hosted Compiler
|
||||||
|
|
||||||
This is the actual compiler binary that we will install to the system.
|
|
||||||
|
|
||||||
*Note: Stage 2 compiler is not yet able to build Stage 3. Building Stage 3 is
|
*Note: Stage 2 compiler is not yet able to build Stage 3. Building Stage 3 is
|
||||||
not yet supported.*
|
not yet supported.*
|
||||||
|
|
||||||
|
Once the self-hosted compiler can build itself, this will be the actual
|
||||||
|
compiler binary that we will install to the system. Until then, users should
|
||||||
|
use stage 1.
|
||||||
|
|
||||||
#### Debug / Development Build
|
#### Debug / Development Build
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -297,7 +297,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
|
||||||
);
|
);
|
||||||
|
|
||||||
exe.linkSystemLibrary("pthread");
|
exe.linkSystemLibrary("pthread");
|
||||||
} else if (exe.target.isDarwin()) {
|
} else if (exe.target.isDarwin() or exe.target.isFreeBSD()) {
|
||||||
if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) {
|
if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) {
|
||||||
// Compiler is GCC.
|
// Compiler is GCC.
|
||||||
try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null);
|
try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null);
|
||||||
|
|
|
@ -34,6 +34,9 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then
|
||||||
|
|
||||||
SHASUM=$(sha256sum $ARTIFACTSDIR/$TARBALL | cut '-d ' -f1)
|
SHASUM=$(sha256sum $ARTIFACTSDIR/$TARBALL | cut '-d ' -f1)
|
||||||
BYTESIZE=$(wc -c < $ARTIFACTSDIR/$TARBALL)
|
BYTESIZE=$(wc -c < $ARTIFACTSDIR/$TARBALL)
|
||||||
|
# `set -x` causes these variables to be mangled.
|
||||||
|
# See https://developercommunity.visualstudio.com/content/problem/375679/pipeline-variable-incorrectly-inserts-single-quote.html
|
||||||
|
set +x
|
||||||
echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL"
|
echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL"
|
||||||
echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM"
|
echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM"
|
||||||
echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE"
|
echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE"
|
||||||
|
|
|
@ -98,6 +98,9 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then
|
||||||
|
|
||||||
SHASUM=$(shasum -a 256 $TARBALL | cut '-d ' -f1)
|
SHASUM=$(shasum -a 256 $TARBALL | cut '-d ' -f1)
|
||||||
BYTESIZE=$(wc -c < $TARBALL)
|
BYTESIZE=$(wc -c < $TARBALL)
|
||||||
|
# `set -x` causes these variables to be mangled.
|
||||||
|
# See https://developercommunity.visualstudio.com/content/problem/375679/pipeline-variable-incorrectly-inserts-single-quote.html
|
||||||
|
set +x
|
||||||
echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL"
|
echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL"
|
||||||
echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM"
|
echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM"
|
||||||
echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE"
|
echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE"
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
set -x
|
set -x
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
pacman -Su --needed --noconfirm
|
||||||
pacman -S --needed --noconfirm wget p7zip python3-pip
|
pacman -S --needed --noconfirm wget p7zip python3-pip
|
||||||
pip install s3cmd
|
pip install s3cmd
|
||||||
wget -nv "https://ziglang.org/deps/llvm%2bclang-8.0.0-win64-msvc-release.tar.xz"
|
wget -nv "https://ziglang.org/deps/llvm%2bclang-8.0.0-win64-msvc-release.tar.xz"
|
||||||
|
|
|
@ -25,6 +25,9 @@ if [ "${BUILD_REASON}" != "PullRequest" ]; then
|
||||||
|
|
||||||
SHASUM=$(sha256sum $TARBALL | cut '-d ' -f1)
|
SHASUM=$(sha256sum $TARBALL | cut '-d ' -f1)
|
||||||
BYTESIZE=$(wc -c < $TARBALL)
|
BYTESIZE=$(wc -c < $TARBALL)
|
||||||
|
# `set -x` causes these variables to be mangled.
|
||||||
|
# See https://developercommunity.visualstudio.com/content/problem/375679/pipeline-variable-incorrectly-inserts-single-quote.html
|
||||||
|
set +x
|
||||||
echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL"
|
echo "##vso[task.setvariable variable=tarball;isOutput=true]$TARBALL"
|
||||||
echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM"
|
echo "##vso[task.setvariable variable=shasum;isOutput=true]$SHASUM"
|
||||||
echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE"
|
echo "##vso[task.setvariable variable=bytesize;isOutput=true]$BYTESIZE"
|
||||||
|
|
|
@ -30,6 +30,7 @@ else()
|
||||||
/usr/lib/llvm/8/include
|
/usr/lib/llvm/8/include
|
||||||
/usr/lib/llvm-8/include
|
/usr/lib/llvm-8/include
|
||||||
/usr/lib/llvm-8.0/include
|
/usr/lib/llvm-8.0/include
|
||||||
|
/usr/local/llvm80/include
|
||||||
/mingw64/include)
|
/mingw64/include)
|
||||||
|
|
||||||
macro(FIND_AND_ADD_CLANG_LIB _libname_)
|
macro(FIND_AND_ADD_CLANG_LIB _libname_)
|
||||||
|
@ -40,6 +41,7 @@ else()
|
||||||
/usr/lib/llvm/8/lib
|
/usr/lib/llvm/8/lib
|
||||||
/usr/lib/llvm-8/lib
|
/usr/lib/llvm-8/lib
|
||||||
/usr/lib/llvm-8.0/lib
|
/usr/lib/llvm-8.0/lib
|
||||||
|
/usr/local/llvm80/lib
|
||||||
/mingw64/lib
|
/mingw64/lib
|
||||||
/c/msys64/mingw64/lib
|
/c/msys64/mingw64/lib
|
||||||
c:\\msys64\\mingw64\\lib)
|
c:\\msys64\\mingw64\\lib)
|
||||||
|
|
|
@ -9,9 +9,14 @@
|
||||||
find_path(LLD_INCLUDE_DIRS NAMES lld/Common/Driver.h
|
find_path(LLD_INCLUDE_DIRS NAMES lld/Common/Driver.h
|
||||||
PATHS
|
PATHS
|
||||||
/usr/lib/llvm-8.0/include
|
/usr/lib/llvm-8.0/include
|
||||||
|
/usr/local/llvm80/include
|
||||||
/mingw64/include)
|
/mingw64/include)
|
||||||
|
|
||||||
find_library(LLD_LIBRARY NAMES lld-8.0 lld PATHS /usr/lib/llvm-8.0/lib)
|
find_library(LLD_LIBRARY NAMES lld-8.0 lld80 lld
|
||||||
|
PATHS
|
||||||
|
/usr/lib/llvm-8.0/lib
|
||||||
|
/usr/local/llvm80/lib
|
||||||
|
)
|
||||||
if(EXISTS ${LLD_LIBRARY})
|
if(EXISTS ${LLD_LIBRARY})
|
||||||
set(LLD_LIBRARIES ${LLD_LIBRARY})
|
set(LLD_LIBRARIES ${LLD_LIBRARY})
|
||||||
else()
|
else()
|
||||||
|
@ -20,6 +25,7 @@ else()
|
||||||
find_library(LLD_${_prettylibname_}_LIB NAMES ${_libname_}
|
find_library(LLD_${_prettylibname_}_LIB NAMES ${_libname_}
|
||||||
PATHS
|
PATHS
|
||||||
/usr/lib/llvm-8.0/lib
|
/usr/lib/llvm-8.0/lib
|
||||||
|
/usr/local/llvm80/lib
|
||||||
/mingw64/lib
|
/mingw64/lib
|
||||||
/c/msys64/mingw64/lib
|
/c/msys64/mingw64/lib
|
||||||
c:/msys64/mingw64/lib)
|
c:/msys64/mingw64/lib)
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
# LLVM_LIBDIRS
|
# LLVM_LIBDIRS
|
||||||
|
|
||||||
find_program(LLVM_CONFIG_EXE
|
find_program(LLVM_CONFIG_EXE
|
||||||
NAMES llvm-config-8 llvm-config-8.0 llvm-config
|
NAMES llvm-config-8 llvm-config-8.0 llvm-config80 llvm-config
|
||||||
PATHS
|
PATHS
|
||||||
"/mingw64/bin"
|
"/mingw64/bin"
|
||||||
"/c/msys64/mingw64/bin"
|
"/c/msys64/mingw64/bin"
|
||||||
|
|
|
@ -95,7 +95,7 @@ void OutputSection::addSection(InputSection *IS) {
|
||||||
Flags = IS->Flags;
|
Flags = IS->Flags;
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, check if new type or flags are compatible with existing ones.
|
// Otherwise, check if new type or flags are compatible with existing ones.
|
||||||
unsigned Mask = SHF_ALLOC | SHF_TLS | SHF_LINK_ORDER;
|
unsigned Mask = SHF_TLS | SHF_LINK_ORDER;
|
||||||
if ((Flags & Mask) != (IS->Flags & Mask))
|
if ((Flags & Mask) != (IS->Flags & Mask))
|
||||||
error("incompatible section flags for " + Name + "\n>>> " + toString(IS) +
|
error("incompatible section flags for " + Name + "\n>>> " + toString(IS) +
|
||||||
": 0x" + utohexstr(IS->Flags) + "\n>>> output section " + Name +
|
": 0x" + utohexstr(IS->Flags) + "\n>>> output section " + Name +
|
||||||
|
|
|
@ -8,7 +8,13 @@
|
||||||
body{
|
body{
|
||||||
background-color:#111;
|
background-color:#111;
|
||||||
color: #bbb;
|
color: #bbb;
|
||||||
font-family: sans-serif;
|
font-family: system-ui,
|
||||||
|
/* Fallbacks for browsers that don't support system-ui */
|
||||||
|
/* https://caniuse.com/#search=system-ui */
|
||||||
|
-apple-system, /* iOS and macOS */
|
||||||
|
Roboto, /* Android */
|
||||||
|
"Segoe UI", /* Windows */
|
||||||
|
sans-serif;
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
color: #88f;
|
color: #88f;
|
||||||
|
@ -159,7 +165,7 @@ const std = @import("std");
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
// If this program is run without stdout attached, exit with an error.
|
// If this program is run without stdout attached, exit with an error.
|
||||||
var stdout_file = try std.io.getStdOut();
|
const stdout_file = try std.io.getStdOut();
|
||||||
// If this program encounters pipe failure when printing to stdout, exit
|
// If this program encounters pipe failure when printing to stdout, exit
|
||||||
// with an error.
|
// with an error.
|
||||||
try stdout_file.write("Hello, world!\n");
|
try stdout_file.write("Hello, world!\n");
|
||||||
|
@ -3273,13 +3279,13 @@ const err = (error {FileNotFound}).FileNotFound;
|
||||||
This becomes useful when using {#link|Inferred Error Sets#}.
|
This becomes useful when using {#link|Inferred Error Sets#}.
|
||||||
</p>
|
</p>
|
||||||
{#header_open|The Global Error Set#}
|
{#header_open|The Global Error Set#}
|
||||||
<p>{#syntax#}error{#endsyntax#} refers to the global error set.
|
<p>{#syntax#}anyerror{#endsyntax#} refers to the global error set.
|
||||||
This is the error set that contains all errors in the entire compilation unit.
|
This is the error set that contains all errors in the entire compilation unit.
|
||||||
It is a superset of all other error sets and a subset of none of them.
|
It is a superset of all other error sets and a subset of none of them.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
You can implicitly cast any error set to the global one, and you can explicitly
|
You can implicitly cast any error set to the global one, and you can explicitly
|
||||||
cast an error of global error set to a non-global one. This inserts a language-level
|
cast an error of the global error set to a non-global one. This inserts a language-level
|
||||||
assert to make sure the error value is in fact in the destination error set.
|
assert to make sure the error value is in fact in the destination error set.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
|
@ -4264,13 +4270,21 @@ fn foo() i32 {
|
||||||
return 1234;
|
return 1234;
|
||||||
}
|
}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
<p>However, if the expression has type {#syntax#}void{#endsyntax#}:</p>
|
<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>
|
||||||
{#code_begin|test#}
|
{#code_begin|test#}
|
||||||
test "ignoring expression value" {
|
test "void is ignored" {
|
||||||
foo();
|
returnsVoid();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn foo() void {}
|
test "explicitly ignoring expression value" {
|
||||||
|
_ = foo();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn returnsVoid() void {}
|
||||||
|
|
||||||
|
fn foo() i32 {
|
||||||
|
return 1234;
|
||||||
|
}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
|
@ -5155,6 +5169,34 @@ fn seq(c: u8) void {
|
||||||
If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
|
If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
|
||||||
</p>
|
</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
{#header_open|@alignCast#}
|
||||||
|
<pre>{#syntax#}@alignCast(comptime alignment: u29, ptr: var) var{#endsyntax#}</pre>
|
||||||
|
<p>
|
||||||
|
{#syntax#}ptr{#endsyntax#} can be {#syntax#}*T{#endsyntax#}, {#syntax#}fn(){#endsyntax#}, {#syntax#}?*T{#endsyntax#},
|
||||||
|
{#syntax#}?fn(){#endsyntax#}, or {#syntax#}[]T{#endsyntax#}. It returns the same type as {#syntax#}ptr{#endsyntax#}
|
||||||
|
except with the alignment adjusted to the new value.
|
||||||
|
</p>
|
||||||
|
<p>A {#link|pointer alignment safety check|Incorrect Pointer Alignment#} is added
|
||||||
|
to the generated code to make sure the pointer is aligned as promised.</p>
|
||||||
|
|
||||||
|
{#header_close#}
|
||||||
|
{#header_open|@alignOf#}
|
||||||
|
<pre>{#syntax#}@alignOf(comptime T: type) comptime_int{#endsyntax#}</pre>
|
||||||
|
<p>
|
||||||
|
This function returns the number of bytes that this type should be aligned to
|
||||||
|
for the current target to match the C ABI. When the child type of a pointer has
|
||||||
|
this alignment, the alignment can be omitted from the type.
|
||||||
|
</p>
|
||||||
|
<pre>{#syntax#}const assert = @import("std").debug.assert;
|
||||||
|
comptime {
|
||||||
|
assert(*u32 == *align(@alignOf(u32)) u32);
|
||||||
|
}{#endsyntax#}</pre>
|
||||||
|
<p>
|
||||||
|
The result is a target-specific compile time constant. It is guaranteed to be
|
||||||
|
less than or equal to {#link|@sizeOf(T)|@sizeOf#}.
|
||||||
|
</p>
|
||||||
|
{#see_also|Alignment#}
|
||||||
|
{#header_close#}
|
||||||
{#header_open|@ArgType#}
|
{#header_open|@ArgType#}
|
||||||
<pre>{#syntax#}@ArgType(comptime T: type, comptime n: usize) type{#endsyntax#}</pre>
|
<pre>{#syntax#}@ArgType(comptime T: type, comptime n: usize) type{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5227,6 +5269,7 @@ fn seq(c: u8) void {
|
||||||
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.
|
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.
|
||||||
</p>
|
</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@bitOffsetOf#}
|
{#header_open|@bitOffsetOf#}
|
||||||
<pre>{#syntax#}@bitOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre>
|
<pre>{#syntax#}@bitOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5239,52 +5282,6 @@ fn seq(c: u8) void {
|
||||||
</p>
|
</p>
|
||||||
{#see_also|@byteOffsetOf#}
|
{#see_also|@byteOffsetOf#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
{#header_open|@breakpoint#}
|
|
||||||
<pre>{#syntax#}@breakpoint(){#endsyntax#}</pre>
|
|
||||||
<p>
|
|
||||||
This function inserts a platform-specific debug trap instruction which causes
|
|
||||||
debuggers to break there.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
This function is only valid within function scope.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{#header_close#}
|
|
||||||
{#header_open|@byteOffsetOf#}
|
|
||||||
<pre>{#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre>
|
|
||||||
<p>
|
|
||||||
Returns the byte offset of a field relative to its containing struct.
|
|
||||||
</p>
|
|
||||||
{#see_also|@bitOffsetOf#}
|
|
||||||
{#header_close#}
|
|
||||||
{#header_open|@alignCast#}
|
|
||||||
<pre>{#syntax#}@alignCast(comptime alignment: u29, ptr: var) var{#endsyntax#}</pre>
|
|
||||||
<p>
|
|
||||||
{#syntax#}ptr{#endsyntax#} can be {#syntax#}*T{#endsyntax#}, {#syntax#}fn(){#endsyntax#}, {#syntax#}?*T{#endsyntax#},
|
|
||||||
{#syntax#}?fn(){#endsyntax#}, or {#syntax#}[]T{#endsyntax#}. It returns the same type as {#syntax#}ptr{#endsyntax#}
|
|
||||||
except with the alignment adjusted to the new value.
|
|
||||||
</p>
|
|
||||||
<p>A {#link|pointer alignment safety check|Incorrect Pointer Alignment#} is added
|
|
||||||
to the generated code to make sure the pointer is aligned as promised.</p>
|
|
||||||
|
|
||||||
{#header_close#}
|
|
||||||
{#header_open|@alignOf#}
|
|
||||||
<pre>{#syntax#}@alignOf(comptime T: type) comptime_int{#endsyntax#}</pre>
|
|
||||||
<p>
|
|
||||||
This function returns the number of bytes that this type should be aligned to
|
|
||||||
for the current target to match the C ABI. When the child type of a pointer has
|
|
||||||
this alignment, the alignment can be omitted from the type.
|
|
||||||
</p>
|
|
||||||
<pre>{#syntax#}const assert = @import("std").debug.assert;
|
|
||||||
comptime {
|
|
||||||
assert(*u32 == *align(@alignOf(u32)) u32);
|
|
||||||
}{#endsyntax#}</pre>
|
|
||||||
<p>
|
|
||||||
The result is a target-specific compile time constant. It is guaranteed to be
|
|
||||||
less than or equal to {#link|@sizeOf(T)|@sizeOf#}.
|
|
||||||
</p>
|
|
||||||
{#see_also|Alignment#}
|
|
||||||
{#header_close#}
|
|
||||||
|
|
||||||
{#header_open|@boolToInt#}
|
{#header_open|@boolToInt#}
|
||||||
<pre>{#syntax#}@boolToInt(value: bool) u1{#endsyntax#}</pre>
|
<pre>{#syntax#}@boolToInt(value: bool) u1{#endsyntax#}</pre>
|
||||||
|
@ -5298,6 +5295,35 @@ comptime {
|
||||||
</p>
|
</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
|
{#header_open|@breakpoint#}
|
||||||
|
<pre>{#syntax#}@breakpoint(){#endsyntax#}</pre>
|
||||||
|
<p>
|
||||||
|
This function inserts a platform-specific debug trap instruction which causes
|
||||||
|
debuggers to break there.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This function is only valid within function scope.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{#header_close#}
|
||||||
|
|
||||||
|
{#header_open|@bswap#}
|
||||||
|
<pre>{#syntax#}@bswap(comptime T: type, value: T) T{#endsyntax#}</pre>
|
||||||
|
<p>{#syntax#}T{#endsyntax#} must be an integer type with bit count evenly divisible by 8.</p>
|
||||||
|
<p>
|
||||||
|
Swaps the byte order of the integer. This converts a big endian integer to a little endian integer,
|
||||||
|
and converts a little endian integer to a big endian integer.
|
||||||
|
</p>
|
||||||
|
{#header_close#}
|
||||||
|
|
||||||
|
{#header_open|@byteOffsetOf#}
|
||||||
|
<pre>{#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre>
|
||||||
|
<p>
|
||||||
|
Returns the byte offset of a field relative to its containing struct.
|
||||||
|
</p>
|
||||||
|
{#see_also|@bitOffsetOf#}
|
||||||
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@bytesToSlice#}
|
{#header_open|@bytesToSlice#}
|
||||||
<pre>{#syntax#}@bytesToSlice(comptime Element: type, bytes: []u8) []Element{#endsyntax#}</pre>
|
<pre>{#syntax#}@bytesToSlice(comptime Element: type, bytes: []u8) []Element{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5364,17 +5390,7 @@ comptime {
|
||||||
</p>
|
</p>
|
||||||
{#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#}
|
{#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
{#header_open|@cUndef#}
|
|
||||||
<pre>{#syntax#}@cUndef(comptime name: []u8){#endsyntax#}</pre>
|
|
||||||
<p>
|
|
||||||
This function can only occur inside {#syntax#}@cImport{#endsyntax#}.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
This appends <code>#undef $name</code> to the {#syntax#}@cImport{#endsyntax#}
|
|
||||||
temporary buffer.
|
|
||||||
</p>
|
|
||||||
{#see_also|Import from C Header File|@cImport|@cDefine|@cInclude#}
|
|
||||||
{#header_close#}
|
|
||||||
{#header_open|@clz#}
|
{#header_open|@clz#}
|
||||||
<pre>{#syntax#}@clz(x: T) U{#endsyntax#}</pre>
|
<pre>{#syntax#}@clz(x: T) U{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5390,6 +5406,7 @@ comptime {
|
||||||
</p>
|
</p>
|
||||||
{#see_also|@ctz|@popCount#}
|
{#see_also|@ctz|@popCount#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@cmpxchgStrong#}
|
{#header_open|@cmpxchgStrong#}
|
||||||
<pre>{#syntax#}@cmpxchgStrong(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}</pre>
|
<pre>{#syntax#}@cmpxchgStrong(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5445,6 +5462,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
|
||||||
<p>{#syntax#}@typeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
|
<p>{#syntax#}@typeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
|
||||||
{#see_also|Compile Variables|cmpxchgStrong#}
|
{#see_also|Compile Variables|cmpxchgStrong#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@compileError#}
|
{#header_open|@compileError#}
|
||||||
<pre>{#syntax#}@compileError(comptime msg: []u8){#endsyntax#}</pre>
|
<pre>{#syntax#}@compileError(comptime msg: []u8){#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5457,6 +5475,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
|
||||||
and {#syntax#}comptime{#endsyntax#} functions.
|
and {#syntax#}comptime{#endsyntax#} functions.
|
||||||
</p>
|
</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@compileLog#}
|
{#header_open|@compileLog#}
|
||||||
<pre>{#syntax#}@compileLog(args: ...){#endsyntax#}</pre>
|
<pre>{#syntax#}@compileLog(args: ...){#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5511,6 +5530,7 @@ test "main" {
|
||||||
}
|
}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@ctz#}
|
{#header_open|@ctz#}
|
||||||
<pre>{#syntax#}@ctz(x: T) U{#endsyntax#}</pre>
|
<pre>{#syntax#}@ctz(x: T) U{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5526,6 +5546,19 @@ test "main" {
|
||||||
</p>
|
</p>
|
||||||
{#see_also|@clz|@popCount#}
|
{#see_also|@clz|@popCount#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
|
{#header_open|@cUndef#}
|
||||||
|
<pre>{#syntax#}@cUndef(comptime name: []u8){#endsyntax#}</pre>
|
||||||
|
<p>
|
||||||
|
This function can only occur inside {#syntax#}@cImport{#endsyntax#}.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This appends <code>#undef $name</code> to the {#syntax#}@cImport{#endsyntax#}
|
||||||
|
temporary buffer.
|
||||||
|
</p>
|
||||||
|
{#see_also|Import from C Header File|@cImport|@cDefine|@cInclude#}
|
||||||
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@divExact#}
|
{#header_open|@divExact#}
|
||||||
<pre>{#syntax#}@divExact(numerator: T, denominator: T) T{#endsyntax#}</pre>
|
<pre>{#syntax#}@divExact(numerator: T, denominator: T) T{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5592,23 +5625,11 @@ test "main" {
|
||||||
{#see_also|@intToEnum#}
|
{#see_also|@intToEnum#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@errSetCast#}
|
|
||||||
<pre>{#syntax#}@errSetCast(comptime T: DestType, value: var) DestType{#endsyntax#}</pre>
|
|
||||||
<p>
|
|
||||||
Converts an error value from one error set to another error set. Attempting to convert an error
|
|
||||||
which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}.
|
|
||||||
</p>
|
|
||||||
{#header_close#}
|
|
||||||
|
|
||||||
{#header_open|@errorName#}
|
{#header_open|@errorName#}
|
||||||
<pre>{#syntax#}@errorName(err: error) []u8{#endsyntax#}</pre>
|
<pre>{#syntax#}@errorName(err: anyerror) []const u8{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
This function returns the string representation of an error. If an error
|
This function returns the string representation of an error. The string representation
|
||||||
declaration is:
|
of {#syntax#}error.OutOfMem{#endsyntax#} is {#syntax#}"OutOfMem"{#endsyntax#}.
|
||||||
</p>
|
|
||||||
<pre>{#syntax#}error OutOfMem{#endsyntax#}</pre>
|
|
||||||
<p>
|
|
||||||
Then the string representation is {#syntax#}"OutOfMem"{#endsyntax#}.
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
If there are no calls to {#syntax#}@errorName{#endsyntax#} in an entire application,
|
If there are no calls to {#syntax#}@errorName{#endsyntax#} in an entire application,
|
||||||
|
@ -5627,13 +5648,14 @@ test "main" {
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@errorToInt#}
|
{#header_open|@errorToInt#}
|
||||||
<pre>{#syntax#}@errorToInt(err: var) @IntType(false, @sizeOf(error) * 8){#endsyntax#}</pre>
|
<pre>{#syntax#}@errorToInt(err: var) @IntType(false, @sizeOf(anyerror) * 8){#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
Supports the following types:
|
Supports the following types:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>error unions</li>
|
<li>{#link|The Global Error Set#}</li>
|
||||||
<li>{#syntax#}E!void{#endsyntax#}</li>
|
<li>{#link|Error Set Type#}</li>
|
||||||
|
<li>{#link|Error Union Type#}</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
Converts an error to the integer representation of an error.
|
Converts an error to the integer representation of an error.
|
||||||
|
@ -5645,6 +5667,14 @@ test "main" {
|
||||||
{#see_also|@intToError#}
|
{#see_also|@intToError#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
|
{#header_open|@errSetCast#}
|
||||||
|
<pre>{#syntax#}@errSetCast(comptime T: DestType, value: var) DestType{#endsyntax#}</pre>
|
||||||
|
<p>
|
||||||
|
Converts an error value from one error set to another error set. Attempting to convert an error
|
||||||
|
which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}.
|
||||||
|
</p>
|
||||||
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@export#}
|
{#header_open|@export#}
|
||||||
<pre>{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8{#endsyntax#}</pre>
|
<pre>{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5713,6 +5743,7 @@ test "main" {
|
||||||
This function is only valid within function scope.
|
This function is only valid within function scope.
|
||||||
</p>
|
</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@handle#}
|
{#header_open|@handle#}
|
||||||
<pre>{#syntax#}@handle(){#endsyntax#}</pre>
|
<pre>{#syntax#}@handle(){#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5723,6 +5754,7 @@ test "main" {
|
||||||
This function is only valid within an async function scope.
|
This function is only valid within an async function scope.
|
||||||
</p>
|
</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@import#}
|
{#header_open|@import#}
|
||||||
<pre>{#syntax#}@import(comptime path: []u8) (namespace){#endsyntax#}</pre>
|
<pre>{#syntax#}@import(comptime path: []u8) (namespace){#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5743,6 +5775,7 @@ test "main" {
|
||||||
</ul>
|
</ul>
|
||||||
{#see_also|Compile Variables|@embedFile#}
|
{#see_also|Compile Variables|@embedFile#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@inlineCall#}
|
{#header_open|@inlineCall#}
|
||||||
<pre>{#syntax#}@inlineCall(function: X, args: ...) Y{#endsyntax#}</pre>
|
<pre>{#syntax#}@inlineCall(function: X, args: ...) Y{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5788,7 +5821,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
|
||||||
{#header_open|@intToError#}
|
{#header_open|@intToError#}
|
||||||
<pre>{#syntax#}@intToError(value: @IntType(false, @sizeOf(anyerror) * 8)) anyerror{#endsyntax#}</pre>
|
<pre>{#syntax#}@intToError(value: @IntType(false, @sizeOf(anyerror) * 8)) anyerror{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
Converts from the integer representation of an error into the global error set type.
|
Converts from the integer representation of an error into {#link|The Global Error Set#} type.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
It is generally recommended to avoid this
|
It is generally recommended to avoid this
|
||||||
|
@ -5822,6 +5855,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
|
||||||
bit count for an integer type is {#syntax#}65535{#endsyntax#}.
|
bit count for an integer type is {#syntax#}65535{#endsyntax#}.
|
||||||
</p>
|
</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@memberCount#}
|
{#header_open|@memberCount#}
|
||||||
<pre>{#syntax#}@memberCount(comptime T: type) comptime_int{#endsyntax#}</pre>
|
<pre>{#syntax#}@memberCount(comptime T: type) comptime_int{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5848,6 +5882,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
|
||||||
<pre>{#syntax#}@memberType(comptime T: type, comptime index: usize) type{#endsyntax#}</pre>
|
<pre>{#syntax#}@memberType(comptime T: type, comptime index: usize) type{#endsyntax#}</pre>
|
||||||
<p>Returns the field type of a struct or union.</p>
|
<p>Returns the field type of a struct or union.</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@memcpy#}
|
{#header_open|@memcpy#}
|
||||||
<pre>{#syntax#}@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize){#endsyntax#}</pre>
|
<pre>{#syntax#}@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize){#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5866,6 +5901,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
|
||||||
<pre>{#syntax#}const mem = @import("std").mem;
|
<pre>{#syntax#}const mem = @import("std").mem;
|
||||||
mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>
|
mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@memset#}
|
{#header_open|@memset#}
|
||||||
<pre>{#syntax#}@memset(dest: [*]u8, c: u8, byte_count: usize){#endsyntax#}</pre>
|
<pre>{#syntax#}@memset(dest: [*]u8, c: u8, byte_count: usize){#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5883,6 +5919,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>
|
||||||
<pre>{#syntax#}const mem = @import("std").mem;
|
<pre>{#syntax#}const mem = @import("std").mem;
|
||||||
mem.set(u8, dest, c);{#endsyntax#}</pre>
|
mem.set(u8, dest, c);{#endsyntax#}</pre>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@mod#}
|
{#header_open|@mod#}
|
||||||
<pre>{#syntax#}@mod(numerator: T, denominator: T) T{#endsyntax#}</pre>
|
<pre>{#syntax#}@mod(numerator: T, denominator: T) T{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5896,6 +5933,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>
|
||||||
<p>For a function that returns an error code, see {#syntax#}@import("std").math.mod{#endsyntax#}.</p>
|
<p>For a function that returns an error code, see {#syntax#}@import("std").math.mod{#endsyntax#}.</p>
|
||||||
{#see_also|@rem#}
|
{#see_also|@rem#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@mulWithOverflow#}
|
{#header_open|@mulWithOverflow#}
|
||||||
<pre>{#syntax#}@mulWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre>
|
<pre>{#syntax#}@mulWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5904,6 +5942,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>
|
||||||
If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
|
If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
|
||||||
</p>
|
</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@newStackCall#}
|
{#header_open|@newStackCall#}
|
||||||
<pre>{#syntax#}@newStackCall(new_stack: []u8, function: var, args: ...) var{#endsyntax#}</pre>
|
<pre>{#syntax#}@newStackCall(new_stack: []u8, function: var, args: ...) var{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5940,6 +5979,7 @@ fn targetFunction(x: i32) usize {
|
||||||
}
|
}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@noInlineCall#}
|
{#header_open|@noInlineCall#}
|
||||||
<pre>{#syntax#}@noInlineCall(function: var, args: ...) var{#endsyntax#}</pre>
|
<pre>{#syntax#}@noInlineCall(function: var, args: ...) var{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5962,6 +6002,7 @@ fn add(a: i32, b: i32) i32 {
|
||||||
</p>
|
</p>
|
||||||
{#see_also|@inlineCall#}
|
{#see_also|@inlineCall#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@OpaqueType#}
|
{#header_open|@OpaqueType#}
|
||||||
<pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>
|
<pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -5985,6 +6026,7 @@ test "call foo" {
|
||||||
}
|
}
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@panic#}
|
{#header_open|@panic#}
|
||||||
<pre>{#syntax#}@panic(message: []const u8) noreturn{#endsyntax#}</pre>
|
<pre>{#syntax#}@panic(message: []const u8) noreturn{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -6001,6 +6043,7 @@ test "call foo" {
|
||||||
</ul>
|
</ul>
|
||||||
{#see_also|Root Source File#}
|
{#see_also|Root Source File#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@popCount#}
|
{#header_open|@popCount#}
|
||||||
<pre>{#syntax#}@popCount(integer: var) var{#endsyntax#}</pre>
|
<pre>{#syntax#}@popCount(integer: var) var{#endsyntax#}</pre>
|
||||||
<p>Counts the number of bits set in an integer.</p>
|
<p>Counts the number of bits set in an integer.</p>
|
||||||
|
@ -6011,12 +6054,14 @@ test "call foo" {
|
||||||
</p>
|
</p>
|
||||||
{#see_also|@ctz|@clz#}
|
{#see_also|@ctz|@clz#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@ptrCast#}
|
{#header_open|@ptrCast#}
|
||||||
<pre>{#syntax#}@ptrCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre>
|
<pre>{#syntax#}@ptrCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
Converts a pointer of one type to a pointer of another type.
|
Converts a pointer of one type to a pointer of another type.
|
||||||
</p>
|
</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@ptrToInt#}
|
{#header_open|@ptrToInt#}
|
||||||
<pre>{#syntax#}@ptrToInt(value: var) usize{#endsyntax#}</pre>
|
<pre>{#syntax#}@ptrToInt(value: var) usize{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -6031,6 +6076,7 @@ test "call foo" {
|
||||||
<p>To convert the other way, use {#link|@intToPtr#}</p>
|
<p>To convert the other way, use {#link|@intToPtr#}</p>
|
||||||
|
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@rem#}
|
{#header_open|@rem#}
|
||||||
<pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre>
|
<pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -6044,6 +6090,7 @@ test "call foo" {
|
||||||
<p>For a function that returns an error code, see {#syntax#}@import("std").math.rem{#endsyntax#}.</p>
|
<p>For a function that returns an error code, see {#syntax#}@import("std").math.rem{#endsyntax#}.</p>
|
||||||
{#see_also|@mod#}
|
{#see_also|@mod#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@returnAddress#}
|
{#header_open|@returnAddress#}
|
||||||
<pre>{#syntax#}@returnAddress(){#endsyntax#}</pre>
|
<pre>{#syntax#}@returnAddress(){#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -6064,19 +6111,14 @@ test "call foo" {
|
||||||
Ensures that a function will have a stack alignment of at least {#syntax#}alignment{#endsyntax#} bytes.
|
Ensures that a function will have a stack alignment of at least {#syntax#}alignment{#endsyntax#} bytes.
|
||||||
</p>
|
</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@setCold#}
|
{#header_open|@setCold#}
|
||||||
<pre>{#syntax#}@setCold(is_cold: bool){#endsyntax#}</pre>
|
<pre>{#syntax#}@setCold(is_cold: bool){#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
Tells the optimizer that a function is rarely called.
|
Tells the optimizer that a function is rarely called.
|
||||||
</p>
|
</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
{#header_open|@setRuntimeSafety#}
|
|
||||||
<pre>{#syntax#}@setRuntimeSafety(safety_on: bool){#endsyntax#}</pre>
|
|
||||||
<p>
|
|
||||||
Sets whether runtime safety checks are on for the scope that contains the function call.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{#header_close#}
|
|
||||||
{#header_open|@setEvalBranchQuota#}
|
{#header_open|@setEvalBranchQuota#}
|
||||||
<pre>{#syntax#}@setEvalBranchQuota(new_quota: usize){#endsyntax#}</pre>
|
<pre>{#syntax#}@setEvalBranchQuota(new_quota: usize){#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -6111,6 +6153,7 @@ test "foo" {
|
||||||
|
|
||||||
{#see_also|comptime#}
|
{#see_also|comptime#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@setFloatMode#}
|
{#header_open|@setFloatMode#}
|
||||||
<pre>{#syntax#}@setFloatMode(mode: @import("builtin").FloatMode){#endsyntax#}</pre>
|
<pre>{#syntax#}@setFloatMode(mode: @import("builtin").FloatMode){#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -6145,6 +6188,7 @@ pub const FloatMode = enum {
|
||||||
</p>
|
</p>
|
||||||
{#see_also|Floating Point Operations#}
|
{#see_also|Floating Point Operations#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@setGlobalLinkage#}
|
{#header_open|@setGlobalLinkage#}
|
||||||
<pre>{#syntax#}@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage){#endsyntax#}</pre>
|
<pre>{#syntax#}@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage){#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -6152,6 +6196,15 @@ pub const FloatMode = enum {
|
||||||
</p>
|
</p>
|
||||||
{#see_also|Compile Variables#}
|
{#see_also|Compile Variables#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
|
{#header_open|@setRuntimeSafety#}
|
||||||
|
<pre>{#syntax#}@setRuntimeSafety(safety_on: bool){#endsyntax#}</pre>
|
||||||
|
<p>
|
||||||
|
Sets whether runtime safety checks are on for the scope that contains the function call.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@shlExact#}
|
{#header_open|@shlExact#}
|
||||||
<pre>{#syntax#}@shlExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre>
|
<pre>{#syntax#}@shlExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -6164,6 +6217,7 @@ pub const FloatMode = enum {
|
||||||
</p>
|
</p>
|
||||||
{#see_also|@shrExact|@shlWithOverflow#}
|
{#see_also|@shrExact|@shlWithOverflow#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@shlWithOverflow#}
|
{#header_open|@shlWithOverflow#}
|
||||||
<pre>{#syntax#}@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: *T) bool{#endsyntax#}</pre>
|
<pre>{#syntax#}@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: *T) bool{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -6177,6 +6231,7 @@ pub const FloatMode = enum {
|
||||||
</p>
|
</p>
|
||||||
{#see_also|@shlExact|@shrExact#}
|
{#see_also|@shlExact|@shrExact#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@shrExact#}
|
{#header_open|@shrExact#}
|
||||||
<pre>{#syntax#}@shrExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre>
|
<pre>{#syntax#}@shrExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -6218,6 +6273,7 @@ pub const FloatMode = enum {
|
||||||
This is a low-level intrinsic. Most code can use {#syntax#}std.math.sqrt{#endsyntax#} instead.
|
This is a low-level intrinsic. Most code can use {#syntax#}std.math.sqrt{#endsyntax#} instead.
|
||||||
</p>
|
</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@subWithOverflow#}
|
{#header_open|@subWithOverflow#}
|
||||||
<pre>{#syntax#}@subWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre>
|
<pre>{#syntax#}@subWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -6226,12 +6282,14 @@ pub const FloatMode = enum {
|
||||||
If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
|
If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
|
||||||
</p>
|
</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@tagName#}
|
{#header_open|@tagName#}
|
||||||
<pre>{#syntax#}@tagName(value: var) []const u8{#endsyntax#}</pre>
|
<pre>{#syntax#}@tagName(value: var) []const u8{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
Converts an enum value or union value to a slice of bytes representing the name.
|
Converts an enum value or union value to a slice of bytes representing the name.
|
||||||
</p>
|
</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@TagType#}
|
{#header_open|@TagType#}
|
||||||
<pre>{#syntax#}@TagType(T: type) type{#endsyntax#}</pre>
|
<pre>{#syntax#}@TagType(T: type) type{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -6241,6 +6299,7 @@ pub const FloatMode = enum {
|
||||||
For a union, returns the enum type that is used to store the tag value.
|
For a union, returns the enum type that is used to store the tag value.
|
||||||
</p>
|
</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@This#}
|
{#header_open|@This#}
|
||||||
<pre>{#syntax#}@This() type{#endsyntax#}</pre>
|
<pre>{#syntax#}@This() type{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -6276,6 +6335,7 @@ fn List(comptime T: type) type {
|
||||||
<a href="https://github.com/ziglang/zig/issues/1047">#1047</a> for details.
|
<a href="https://github.com/ziglang/zig/issues/1047">#1047</a> for details.
|
||||||
</p>
|
</p>
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@truncate#}
|
{#header_open|@truncate#}
|
||||||
<pre>{#syntax#}@truncate(comptime T: type, integer) T{#endsyntax#}</pre>
|
<pre>{#syntax#}@truncate(comptime T: type, integer) T{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -6300,6 +6360,7 @@ const b: u8 = @truncate(u8, a);
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@typeId#}
|
{#header_open|@typeId#}
|
||||||
<pre>{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}</pre>
|
<pre>{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -6334,6 +6395,7 @@ pub const TypeId = enum {
|
||||||
};
|
};
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@typeInfo#}
|
{#header_open|@typeInfo#}
|
||||||
<pre>{#syntax#}@typeInfo(comptime T: type) @import("builtin").TypeInfo{#endsyntax#}</pre>
|
<pre>{#syntax#}@typeInfo(comptime T: type) @import("builtin").TypeInfo{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -6516,6 +6578,7 @@ pub const TypeInfo = union(TypeId) {
|
||||||
};
|
};
|
||||||
{#code_end#}
|
{#code_end#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@typeName#}
|
{#header_open|@typeName#}
|
||||||
<pre>{#syntax#}@typeName(T: type) []u8{#endsyntax#}</pre>
|
<pre>{#syntax#}@typeName(T: type) []u8{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -6523,6 +6586,7 @@ pub const TypeInfo = union(TypeId) {
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|@typeOf#}
|
{#header_open|@typeOf#}
|
||||||
<pre>{#syntax#}@typeOf(expression) type{#endsyntax#}</pre>
|
<pre>{#syntax#}@typeOf(expression) type{#endsyntax#}</pre>
|
||||||
<p>
|
<p>
|
||||||
|
@ -6532,6 +6596,7 @@ pub const TypeInfo = union(TypeId) {
|
||||||
|
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
|
|
||||||
{#header_open|Build Mode#}
|
{#header_open|Build Mode#}
|
||||||
<p>
|
<p>
|
||||||
Zig has four build modes:
|
Zig has four build modes:
|
||||||
|
@ -6659,7 +6724,7 @@ fn foo(x: []const u8) u8 {
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
{#header_open|Cast Negative Number to Unsigned Integer#}
|
{#header_open|Cast Negative Number to Unsigned Integer#}
|
||||||
<p>At compile-time:</p>
|
<p>At compile-time:</p>
|
||||||
{#code_begin|test_err|attempt to cast negative value to unsigned integer#}
|
{#code_begin|test_err|cannot cast negative value -1 to unsigned integer type 'u32'#}
|
||||||
comptime {
|
comptime {
|
||||||
const value: i32 = -1;
|
const value: i32 = -1;
|
||||||
const unsigned = @intCast(u32, value);
|
const unsigned = @intCast(u32, value);
|
||||||
|
@ -6681,7 +6746,7 @@ pub fn main() void {
|
||||||
{#header_close#}
|
{#header_close#}
|
||||||
{#header_open|Cast Truncates Data#}
|
{#header_open|Cast Truncates Data#}
|
||||||
<p>At compile-time:</p>
|
<p>At compile-time:</p>
|
||||||
{#code_begin|test_err|cast from 'u16' to 'u8' truncates bits#}
|
{#code_begin|test_err|integer value 300 cannot be implicitly casted to type 'u8'#}
|
||||||
comptime {
|
comptime {
|
||||||
const spartan_count: u16 = 300;
|
const spartan_count: u16 = 300;
|
||||||
const byte = @intCast(u8, spartan_count);
|
const byte = @intCast(u8, spartan_count);
|
||||||
|
@ -7830,11 +7895,11 @@ TypeExpr <- PrefixTypeOp* ErrorUnionExpr
|
||||||
ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)?
|
ErrorUnionExpr <- SuffixExpr (EXCLAMATIONMARK TypeExpr)?
|
||||||
|
|
||||||
SuffixExpr
|
SuffixExpr
|
||||||
<- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArgumnets
|
<- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArguments
|
||||||
/ PrimaryTypeExpr (SuffixOp / FnCallArgumnets)*
|
/ PrimaryTypeExpr (SuffixOp / FnCallArguments)*
|
||||||
|
|
||||||
PrimaryTypeExpr
|
PrimaryTypeExpr
|
||||||
<- BUILTININDENTIFIER FnCallArgumnets
|
<- BUILTINIDENTIFIER FnCallArguments
|
||||||
/ CHAR_LITERAL
|
/ CHAR_LITERAL
|
||||||
/ ContainerDecl
|
/ ContainerDecl
|
||||||
/ ErrorSetDecl
|
/ ErrorSetDecl
|
||||||
|
@ -7884,11 +7949,11 @@ AsmOutput <- COLON AsmOutputList AsmInput?
|
||||||
|
|
||||||
AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
|
AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
|
||||||
|
|
||||||
AsmInput <- COLON AsmInputList AsmCloppers?
|
AsmInput <- COLON AsmInputList AsmClobbers?
|
||||||
|
|
||||||
AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
|
AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
|
||||||
|
|
||||||
AsmCloppers <- COLON StringList
|
AsmClobbers <- COLON StringList
|
||||||
|
|
||||||
# *** Helper grammar ***
|
# *** Helper grammar ***
|
||||||
BreakLabel <- COLON IDENTIFIER
|
BreakLabel <- COLON IDENTIFIER
|
||||||
|
@ -8013,7 +8078,7 @@ SuffixOp
|
||||||
|
|
||||||
AsyncPrefix <- KEYWORD_async (LARROW PrefixExpr RARROW)?
|
AsyncPrefix <- KEYWORD_async (LARROW PrefixExpr RARROW)?
|
||||||
|
|
||||||
FnCallArgumnets <- LPAREN ExprList RPAREN
|
FnCallArguments <- LPAREN ExprList RPAREN
|
||||||
|
|
||||||
# Ptr specific
|
# Ptr specific
|
||||||
ArrayTypeStart <- LBRACKET Expr? RBRACKET
|
ArrayTypeStart <- LBRACKET Expr? RBRACKET
|
||||||
|
@ -8090,7 +8155,7 @@ STRINGLITERAL
|
||||||
IDENTIFIER
|
IDENTIFIER
|
||||||
<- !keyword ("c" !["\\] / [A-Zabd-z_]) [A-Za-z0-9_]* skip
|
<- !keyword ("c" !["\\] / [A-Zabd-z_]) [A-Za-z0-9_]* skip
|
||||||
/ "@\"" string_char* "\"" skip
|
/ "@\"" string_char* "\"" skip
|
||||||
BUILTININDENTIFIER <- "@"[A-Za-z_][A-Za-z0-9_]* skip
|
BUILTINIDENTIFIER <- "@"[A-Za-z_][A-Za-z0-9_]* skip
|
||||||
|
|
||||||
|
|
||||||
AMPERSAND <- '&' ![=] skip
|
AMPERSAND <- '&' ![=] skip
|
||||||
|
@ -8109,9 +8174,9 @@ DOT2 <- '..' ![.] skip
|
||||||
DOT3 <- '...' skip
|
DOT3 <- '...' skip
|
||||||
DOTASTERISK <- '.*' skip
|
DOTASTERISK <- '.*' skip
|
||||||
DOTQUESTIONMARK <- '.?' skip
|
DOTQUESTIONMARK <- '.?' skip
|
||||||
EQUAL <- '=' ![>=] skip
|
EQUAL <- '=' ![>=] skip
|
||||||
EQUALEQUAL <- '==' skip
|
EQUALEQUAL <- '==' skip
|
||||||
EQUALRARROW <- '=>' skip
|
EQUALRARROW <- '=>' skip
|
||||||
EXCLAMATIONMARK <- '!' ![=] skip
|
EXCLAMATIONMARK <- '!' ![=] skip
|
||||||
EXCLAMATIONMARKEQUAL <- '!=' skip
|
EXCLAMATIONMARKEQUAL <- '!=' skip
|
||||||
LARROW <- '<' ![<=] skip
|
LARROW <- '<' ![<=] skip
|
||||||
|
@ -8121,11 +8186,11 @@ LARROWEQUAL <- '<=' skip
|
||||||
LBRACE <- '{' skip
|
LBRACE <- '{' skip
|
||||||
LBRACKET <- '[' skip
|
LBRACKET <- '[' skip
|
||||||
LPAREN <- '(' skip
|
LPAREN <- '(' skip
|
||||||
MINUS <- '-' ![%=>] skip
|
MINUS <- '-' ![%=>] skip
|
||||||
MINUSEQUAL <- '-=' skip
|
MINUSEQUAL <- '-=' skip
|
||||||
MINUSPERCENT <- '-%' ![=] skip
|
MINUSPERCENT <- '-%' ![=] skip
|
||||||
MINUSPERCENTEQUAL <- '-%=' skip
|
MINUSPERCENTEQUAL <- '-%=' skip
|
||||||
MINUSRARROW <- '->' skip
|
MINUSRARROW <- '->' skip
|
||||||
PERCENT <- '%' ![=] skip
|
PERCENT <- '%' ![=] skip
|
||||||
PERCENTEQUAL <- '%=' skip
|
PERCENTEQUAL <- '%=' skip
|
||||||
PIPE <- '|' ![|=] skip
|
PIPE <- '|' ![|=] skip
|
||||||
|
@ -8137,10 +8202,10 @@ PLUSEQUAL <- '+=' skip
|
||||||
PLUSPERCENT <- '+%' ![=] skip
|
PLUSPERCENT <- '+%' ![=] skip
|
||||||
PLUSPERCENTEQUAL <- '+%=' skip
|
PLUSPERCENTEQUAL <- '+%=' skip
|
||||||
QUESTIONMARK <- '?' skip
|
QUESTIONMARK <- '?' skip
|
||||||
RARROW <- '>' ![>=] skip
|
RARROW <- '>' ![>=] skip
|
||||||
RARROW2 <- '>>' ![=] skip
|
RARROW2 <- '>>' ![=] skip
|
||||||
RARROW2EQUAL <- '>>=' skip
|
RARROW2EQUAL <- '>>=' skip
|
||||||
RARROWEQUAL <- '>=' skip
|
RARROWEQUAL <- '>=' skip
|
||||||
RBRACE <- '}' skip
|
RBRACE <- '}' skip
|
||||||
RBRACKET <- ']' skip
|
RBRACKET <- ']' skip
|
||||||
RPAREN <- ')' skip
|
RPAREN <- ')' skip
|
||||||
|
|
|
@ -15,7 +15,7 @@ pub fn main() !void {
|
||||||
std.debug.warn("unable to seed random number generator: {}", err);
|
std.debug.warn("unable to seed random number generator: {}", err);
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
const seed = std.mem.readInt(seed_bytes, u64, builtin.Endian.Big);
|
const seed = std.mem.readIntNative(u64, &seed_bytes);
|
||||||
var prng = std.rand.DefaultPrng.init(seed);
|
var prng = std.rand.DefaultPrng.init(seed);
|
||||||
|
|
||||||
const answer = prng.random.range(u8, 0, 100) + 1;
|
const answer = prng.random.range(u8, 0, 100) + 1;
|
||||||
|
@ -24,15 +24,15 @@ pub fn main() !void {
|
||||||
try stdout.print("\nGuess a number between 1 and 100: ");
|
try stdout.print("\nGuess a number between 1 and 100: ");
|
||||||
var line_buf: [20]u8 = undefined;
|
var line_buf: [20]u8 = undefined;
|
||||||
|
|
||||||
const line_len = io.readLine(line_buf[0..]) catch |err| switch (err) {
|
const line = io.readLineSlice(line_buf[0..]) catch |err| switch (err) {
|
||||||
error.InputTooLong => {
|
error.OutOfMemory => {
|
||||||
try stdout.print("Input too long.\n");
|
try stdout.print("Input too long.\n");
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
error.EndOfFile, error.StdInUnavailable => return err,
|
else => return err,
|
||||||
};
|
};
|
||||||
|
|
||||||
const guess = fmt.parseUnsigned(u8, line_buf[0..line_len], 10) catch {
|
const guess = fmt.parseUnsigned(u8, line, 10) catch {
|
||||||
try stdout.print("Invalid number.\n");
|
try stdout.print("Invalid number.\n");
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@ const std = @import("std");
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
// If this program is run without stdout attached, exit with an error.
|
// If this program is run without stdout attached, exit with an error.
|
||||||
var stdout_file = try std.io.getStdOut();
|
const stdout_file = try std.io.getStdOut();
|
||||||
// If this program encounters pipe failure when printing to stdout, exit
|
// If this program encounters pipe failure when printing to stdout, exit
|
||||||
// with an error.
|
// with an error.
|
||||||
try stdout_file.write("Hello, world!\n");
|
try stdout_file.write("Hello, world!\n");
|
||||||
|
|
|
@ -55,7 +55,7 @@ pub const ZigCompiler = struct {
|
||||||
|
|
||||||
var seed_bytes: [@sizeOf(u64)]u8 = undefined;
|
var seed_bytes: [@sizeOf(u64)]u8 = undefined;
|
||||||
try std.os.getRandomBytes(seed_bytes[0..]);
|
try std.os.getRandomBytes(seed_bytes[0..]);
|
||||||
const seed = std.mem.readInt(seed_bytes, u64, builtin.Endian.Big);
|
const seed = mem.readIntNative(u64, &seed_bytes);
|
||||||
|
|
||||||
return ZigCompiler{
|
return ZigCompiler{
|
||||||
.loop = loop,
|
.loop = loop,
|
||||||
|
@ -300,6 +300,7 @@ pub const Compilation = struct {
|
||||||
UserResourceLimitReached,
|
UserResourceLimitReached,
|
||||||
InvalidUtf8,
|
InvalidUtf8,
|
||||||
BadPathName,
|
BadPathName,
|
||||||
|
DeviceBusy,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Event = union(enum) {
|
pub const Event = union(enum) {
|
||||||
|
|
|
@ -172,7 +172,7 @@ pub const LibCInstallation = struct {
|
||||||
try group.call(findNativeStaticLibDir, self, loop);
|
try group.call(findNativeStaticLibDir, self, loop);
|
||||||
try group.call(findNativeDynamicLinker, self, loop);
|
try group.call(findNativeDynamicLinker, self, loop);
|
||||||
},
|
},
|
||||||
builtin.Os.macosx => {
|
builtin.Os.macosx, builtin.Os.freebsd => {
|
||||||
self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include");
|
self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include");
|
||||||
},
|
},
|
||||||
else => @compileError("unimplemented: find libc for this OS"),
|
else => @compileError("unimplemented: find libc for this OS"),
|
||||||
|
|
|
@ -311,6 +311,12 @@ pub const Target = union(enum) {
|
||||||
pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {
|
pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {
|
||||||
const env = self.getEnviron();
|
const env = self.getEnviron();
|
||||||
const arch = self.getArch();
|
const arch = self.getArch();
|
||||||
|
const os = self.getOs();
|
||||||
|
switch (os) {
|
||||||
|
builtin.Os.freebsd => {
|
||||||
|
return "/libexec/ld-elf.so.1";
|
||||||
|
},
|
||||||
|
builtin.Os.linux => {
|
||||||
switch (env) {
|
switch (env) {
|
||||||
builtin.Environ.android => {
|
builtin.Environ.android => {
|
||||||
if (self.is64bit()) {
|
if (self.is64bit()) {
|
||||||
|
@ -385,11 +391,6 @@ pub const Target = union(enum) {
|
||||||
builtin.Arch.armv5te,
|
builtin.Arch.armv5te,
|
||||||
builtin.Arch.armv4t,
|
builtin.Arch.armv4t,
|
||||||
builtin.Arch.thumb,
|
builtin.Arch.thumb,
|
||||||
=> return switch (self.getFloatAbi()) {
|
|
||||||
FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3",
|
|
||||||
else => return "/lib/ld-linux.so.3",
|
|
||||||
},
|
|
||||||
|
|
||||||
builtin.Arch.armebv8_5a,
|
builtin.Arch.armebv8_5a,
|
||||||
builtin.Arch.armebv8_4a,
|
builtin.Arch.armebv8_4a,
|
||||||
builtin.Arch.armebv8_3a,
|
builtin.Arch.armebv8_3a,
|
||||||
|
@ -466,6 +467,9 @@ pub const Target = union(enum) {
|
||||||
builtin.Arch.renderscript64,
|
builtin.Arch.renderscript64,
|
||||||
=> return null,
|
=> return null,
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
else => return null,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn llvmTargetFromTriple(triple: std.Buffer) !llvm.TargetRef {
|
pub fn llvmTargetFromTriple(triple: std.Buffer) !llvm.TargetRef {
|
||||||
|
@ -513,6 +517,7 @@ pub const Target = union(enum) {
|
||||||
|
|
||||||
builtin.Os.linux,
|
builtin.Os.linux,
|
||||||
builtin.Os.macosx,
|
builtin.Os.macosx,
|
||||||
|
builtin.Os.freebsd,
|
||||||
builtin.Os.openbsd,
|
builtin.Os.openbsd,
|
||||||
builtin.Os.zen,
|
builtin.Os.zen,
|
||||||
=> switch (id) {
|
=> switch (id) {
|
||||||
|
@ -547,7 +552,6 @@ pub const Target = union(enum) {
|
||||||
builtin.Os.ananas,
|
builtin.Os.ananas,
|
||||||
builtin.Os.cloudabi,
|
builtin.Os.cloudabi,
|
||||||
builtin.Os.dragonfly,
|
builtin.Os.dragonfly,
|
||||||
builtin.Os.freebsd,
|
|
||||||
builtin.Os.fuchsia,
|
builtin.Os.fuchsia,
|
||||||
builtin.Os.ios,
|
builtin.Os.ios,
|
||||||
builtin.Os.kfreebsd,
|
builtin.Os.kfreebsd,
|
||||||
|
|
|
@ -605,7 +605,6 @@ enum CastOp {
|
||||||
CastOpFloatToInt,
|
CastOpFloatToInt,
|
||||||
CastOpBoolToInt,
|
CastOpBoolToInt,
|
||||||
CastOpResizeSlice,
|
CastOpResizeSlice,
|
||||||
CastOpBytesToSlice,
|
|
||||||
CastOpNumLitToConcrete,
|
CastOpNumLitToConcrete,
|
||||||
CastOpErrSet,
|
CastOpErrSet,
|
||||||
CastOpBitCast,
|
CastOpBitCast,
|
||||||
|
@ -1415,6 +1414,7 @@ enum BuiltinFnId {
|
||||||
BuiltinFnIdErrorReturnTrace,
|
BuiltinFnIdErrorReturnTrace,
|
||||||
BuiltinFnIdAtomicRmw,
|
BuiltinFnIdAtomicRmw,
|
||||||
BuiltinFnIdAtomicLoad,
|
BuiltinFnIdAtomicLoad,
|
||||||
|
BuiltinFnIdBswap,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BuiltinFnEntry {
|
struct BuiltinFnEntry {
|
||||||
|
@ -1487,6 +1487,7 @@ enum ZigLLVMFnId {
|
||||||
ZigLLVMFnIdFloor,
|
ZigLLVMFnIdFloor,
|
||||||
ZigLLVMFnIdCeil,
|
ZigLLVMFnIdCeil,
|
||||||
ZigLLVMFnIdSqrt,
|
ZigLLVMFnIdSqrt,
|
||||||
|
ZigLLVMFnIdBswap,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum AddSubMul {
|
enum AddSubMul {
|
||||||
|
@ -1516,6 +1517,9 @@ struct ZigLLVMFnKey {
|
||||||
uint32_t bit_count;
|
uint32_t bit_count;
|
||||||
bool is_signed;
|
bool is_signed;
|
||||||
} overflow_arithmetic;
|
} overflow_arithmetic;
|
||||||
|
struct {
|
||||||
|
uint32_t bit_count;
|
||||||
|
} bswap;
|
||||||
} data;
|
} data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2158,6 +2162,7 @@ enum IrInstructionId {
|
||||||
IrInstructionIdMergeErrRetTraces,
|
IrInstructionIdMergeErrRetTraces,
|
||||||
IrInstructionIdMarkErrRetTracePtr,
|
IrInstructionIdMarkErrRetTracePtr,
|
||||||
IrInstructionIdSqrt,
|
IrInstructionIdSqrt,
|
||||||
|
IrInstructionIdBswap,
|
||||||
IrInstructionIdErrSetCast,
|
IrInstructionIdErrSetCast,
|
||||||
IrInstructionIdToBytes,
|
IrInstructionIdToBytes,
|
||||||
IrInstructionIdFromBytes,
|
IrInstructionIdFromBytes,
|
||||||
|
@ -3251,6 +3256,13 @@ struct IrInstructionCheckRuntimeScope {
|
||||||
IrInstruction *is_comptime;
|
IrInstruction *is_comptime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct IrInstructionBswap {
|
||||||
|
IrInstruction base;
|
||||||
|
|
||||||
|
IrInstruction *type;
|
||||||
|
IrInstruction *op;
|
||||||
|
};
|
||||||
|
|
||||||
static const size_t slice_ptr_index = 0;
|
static const size_t slice_ptr_index = 0;
|
||||||
static const size_t slice_len_index = 1;
|
static const size_t slice_len_index = 1;
|
||||||
|
|
||||||
|
|
120
src/analyze.cpp
120
src/analyze.cpp
|
@ -401,7 +401,8 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
|
ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
|
||||||
bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset_in_host, uint32_t host_int_bytes)
|
bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
|
||||||
|
uint32_t bit_offset_in_host, uint32_t host_int_bytes)
|
||||||
{
|
{
|
||||||
assert(!type_is_invalid(child_type));
|
assert(!type_is_invalid(child_type));
|
||||||
assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
|
assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
|
||||||
|
@ -1059,7 +1060,7 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
|
||||||
}
|
}
|
||||||
zig_panic("TODO implement C ABI for x86_64 return types. type '%s'\nSee https://github.com/ziglang/zig/issues/1481",
|
zig_panic("TODO implement C ABI for x86_64 return types. type '%s'\nSee https://github.com/ziglang/zig/issues/1481",
|
||||||
buf_ptr(&fn_type_id->return_type->name));
|
buf_ptr(&fn_type_id->return_type->name));
|
||||||
} else if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb) {
|
} else if (target_is_arm(&g->zig_target)) {
|
||||||
return type_size(g, fn_type_id->return_type) > 16;
|
return type_size(g, fn_type_id->return_type) > 16;
|
||||||
}
|
}
|
||||||
zig_panic("TODO implement C ABI for this architecture. See https://github.com/ziglang/zig/issues/1481");
|
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
|
||||||
case ZigTypeIdUnion:
|
case ZigTypeIdUnion:
|
||||||
case ZigTypeIdFn:
|
case ZigTypeIdFn:
|
||||||
case ZigTypeIdPromise:
|
case ZigTypeIdPromise:
|
||||||
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
|
switch (type_requires_comptime(g, type_entry)) {
|
||||||
return g->builtin_types.entry_invalid;
|
case ReqCompTimeNo:
|
||||||
if (type_requires_comptime(type_entry)) {
|
break;
|
||||||
|
case ReqCompTimeYes:
|
||||||
add_node_error(g, param_node->data.param_decl.type,
|
add_node_error(g, param_node->data.param_decl.type,
|
||||||
buf_sprintf("parameter of type '%s' must be declared comptime",
|
buf_sprintf("parameter of type '%s' must be declared comptime",
|
||||||
buf_ptr(&type_entry->name)));
|
buf_ptr(&type_entry->name)));
|
||||||
return g->builtin_types.entry_invalid;
|
return g->builtin_types.entry_invalid;
|
||||||
|
case ReqCompTimeInvalid:
|
||||||
|
return g->builtin_types.entry_invalid;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1711,10 +1715,13 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
|
||||||
case ZigTypeIdUnion:
|
case ZigTypeIdUnion:
|
||||||
case ZigTypeIdFn:
|
case ZigTypeIdFn:
|
||||||
case ZigTypeIdPromise:
|
case ZigTypeIdPromise:
|
||||||
if ((err = type_resolve(g, fn_type_id.return_type, ResolveStatusZeroBitsKnown)))
|
switch (type_requires_comptime(g, fn_type_id.return_type)) {
|
||||||
|
case ReqCompTimeInvalid:
|
||||||
return g->builtin_types.entry_invalid;
|
return g->builtin_types.entry_invalid;
|
||||||
if (type_requires_comptime(fn_type_id.return_type)) {
|
case ReqCompTimeYes:
|
||||||
return get_generic_fn_type(g, &fn_type_id);
|
return get_generic_fn_type(g, &fn_type_id);
|
||||||
|
case ReqCompTimeNo:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2560,8 +2567,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
|
||||||
static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
|
static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
|
||||||
assert(struct_type->id == ZigTypeIdStruct);
|
assert(struct_type->id == ZigTypeIdStruct);
|
||||||
|
|
||||||
Error err;
|
|
||||||
|
|
||||||
if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
|
if (struct_type->data.structure.resolve_status == ResolveStatusInvalid)
|
||||||
return ErrorSemanticAnalyzeFail;
|
return ErrorSemanticAnalyzeFail;
|
||||||
if (struct_type->data.structure.resolve_status >= ResolveStatusZeroBitsKnown)
|
if (struct_type->data.structure.resolve_status >= ResolveStatusZeroBitsKnown)
|
||||||
|
@ -2619,13 +2624,15 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
|
||||||
buf_sprintf("enums, not structs, support field assignment"));
|
buf_sprintf("enums, not structs, support field assignment"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = type_resolve(g, field_type, ResolveStatusZeroBitsKnown))) {
|
switch (type_requires_comptime(g, field_type)) {
|
||||||
|
case ReqCompTimeYes:
|
||||||
|
struct_type->data.structure.requires_comptime = true;
|
||||||
|
break;
|
||||||
|
case ReqCompTimeInvalid:
|
||||||
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
||||||
continue;
|
continue;
|
||||||
}
|
case ReqCompTimeNo:
|
||||||
|
break;
|
||||||
if (type_requires_comptime(field_type)) {
|
|
||||||
struct_type->data.structure.requires_comptime = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!type_has_bits(field_type))
|
if (!type_has_bits(field_type))
|
||||||
|
@ -2674,19 +2681,31 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
|
||||||
assert(decl_node->type == NodeTypeContainerDecl);
|
assert(decl_node->type == NodeTypeContainerDecl);
|
||||||
assert(struct_type->di_type);
|
assert(struct_type->di_type);
|
||||||
|
|
||||||
|
size_t field_count = struct_type->data.structure.src_field_count;
|
||||||
if (struct_type->data.structure.layout == ContainerLayoutPacked) {
|
if (struct_type->data.structure.layout == ContainerLayoutPacked) {
|
||||||
struct_type->data.structure.abi_alignment = 1;
|
struct_type->data.structure.abi_alignment = 1;
|
||||||
}
|
|
||||||
|
|
||||||
size_t field_count = struct_type->data.structure.src_field_count;
|
|
||||||
for (size_t i = 0; i < field_count; i += 1) {
|
for (size_t i = 0; i < field_count; i += 1) {
|
||||||
TypeStructField *field = &struct_type->data.structure.fields[i];
|
TypeStructField *field = &struct_type->data.structure.fields[i];
|
||||||
|
if (field->type_entry != nullptr && type_is_invalid(field->type_entry)) {
|
||||||
|
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else for (size_t i = 0; i < field_count; i += 1) {
|
||||||
|
TypeStructField *field = &struct_type->data.structure.fields[i];
|
||||||
|
uint32_t this_field_align;
|
||||||
|
|
||||||
// If this assertion trips, look up the call stack. Probably something is
|
// TODO If we have no type_entry for the field, we've already failed to
|
||||||
// calling type_resolve with ResolveStatusAlignmentKnown when it should only
|
// compile the program correctly. This stage1 compiler needs a deeper
|
||||||
// be resolving ResolveStatusZeroBitsKnown
|
// reworking to make this correct, or we can ignore the problem
|
||||||
assert(field->type_entry != nullptr);
|
// and make sure it is fixed in stage2. This workaround is for when
|
||||||
|
// there is a false positive of a dependency loop, of alignment depending
|
||||||
|
// on itself. When this false positive happens we assume a pointer-aligned
|
||||||
|
// field, which is usually fine but could be incorrectly over-aligned or
|
||||||
|
// even under-aligned. See https://github.com/ziglang/zig/issues/1512
|
||||||
|
if (field->type_entry == nullptr) {
|
||||||
|
this_field_align = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0));
|
||||||
|
} else {
|
||||||
if (type_is_invalid(field->type_entry)) {
|
if (type_is_invalid(field->type_entry)) {
|
||||||
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
||||||
break;
|
break;
|
||||||
|
@ -2695,20 +2714,19 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
|
||||||
if (!type_has_bits(field->type_entry))
|
if (!type_has_bits(field->type_entry))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// alignment of structs is the alignment of the most-aligned field
|
|
||||||
if (struct_type->data.structure.layout != ContainerLayoutPacked) {
|
|
||||||
if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {
|
if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {
|
||||||
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t this_field_align = get_abi_alignment(g, field->type_entry);
|
this_field_align = get_abi_alignment(g, field->type_entry);
|
||||||
assert(this_field_align != 0);
|
assert(this_field_align != 0);
|
||||||
|
}
|
||||||
|
// alignment of structs is the alignment of the most-aligned field
|
||||||
if (this_field_align > struct_type->data.structure.abi_alignment) {
|
if (this_field_align > struct_type->data.structure.abi_alignment) {
|
||||||
struct_type->data.structure.abi_alignment = this_field_align;
|
struct_type->data.structure.abi_alignment = this_field_align;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
struct_type->data.structure.resolve_loop_flag = false;
|
struct_type->data.structure.resolve_loop_flag = false;
|
||||||
|
|
||||||
|
@ -2890,11 +2908,17 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
|
||||||
}
|
}
|
||||||
union_field->type_entry = field_type;
|
union_field->type_entry = field_type;
|
||||||
|
|
||||||
if (type_requires_comptime(field_type)) {
|
switch (type_requires_comptime(g, field_type)) {
|
||||||
|
case ReqCompTimeInvalid:
|
||||||
|
union_type->data.unionation.is_invalid = true;
|
||||||
|
continue;
|
||||||
|
case ReqCompTimeYes:
|
||||||
union_type->data.unionation.requires_comptime = true;
|
union_type->data.unionation.requires_comptime = true;
|
||||||
|
break;
|
||||||
|
case ReqCompTimeNo:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) {
|
if (field_node->data.struct_field.value != nullptr && !decl_node->data.container_decl.auto_enum) {
|
||||||
ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value,
|
ErrorMsg *msg = add_node_error(g, field_node->data.struct_field.value,
|
||||||
buf_sprintf("non-enum union field assignment"));
|
buf_sprintf("non-enum union field assignment"));
|
||||||
|
@ -4579,7 +4603,10 @@ void find_libc_include_path(CodeGen *g) {
|
||||||
fprintf(stderr, "Unable to determine libc include path. --libc-include-dir");
|
fprintf(stderr, "Unable to determine libc include path. --libc-include-dir");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
} else if (g->zig_target.os == OsLinux || g->zig_target.os == OsMacOSX) {
|
} else if (g->zig_target.os == OsLinux ||
|
||||||
|
g->zig_target.os == OsMacOSX ||
|
||||||
|
g->zig_target.os == OsFreeBSD)
|
||||||
|
{
|
||||||
g->libc_include_dir = get_posix_libc_include_path();
|
g->libc_include_dir = get_posix_libc_include_path();
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Unable to determine libc include path.\n"
|
fprintf(stderr, "Unable to determine libc include path.\n"
|
||||||
|
@ -4627,6 +4654,8 @@ void find_libc_lib_path(CodeGen *g) {
|
||||||
|
|
||||||
} else if (g->zig_target.os == OsLinux) {
|
} else if (g->zig_target.os == OsLinux) {
|
||||||
g->libc_lib_dir = get_linux_libc_lib_path("crt1.o");
|
g->libc_lib_dir = get_linux_libc_lib_path("crt1.o");
|
||||||
|
} else if (g->zig_target.os == OsFreeBSD) {
|
||||||
|
g->libc_lib_dir = buf_create_from_str("/usr/lib");
|
||||||
} else {
|
} else {
|
||||||
zig_panic("Unable to determine libc lib path.");
|
zig_panic("Unable to determine libc lib path.");
|
||||||
}
|
}
|
||||||
|
@ -4639,6 +4668,8 @@ void find_libc_lib_path(CodeGen *g) {
|
||||||
return;
|
return;
|
||||||
} else if (g->zig_target.os == OsLinux) {
|
} else if (g->zig_target.os == OsLinux) {
|
||||||
g->libc_static_lib_dir = get_linux_libc_lib_path("crtbegin.o");
|
g->libc_static_lib_dir = get_linux_libc_lib_path("crtbegin.o");
|
||||||
|
} else if (g->zig_target.os == OsFreeBSD) {
|
||||||
|
g->libc_static_lib_dir = buf_create_from_str("/usr/lib");
|
||||||
} else {
|
} else {
|
||||||
zig_panic("Unable to determine libc static lib path.");
|
zig_panic("Unable to determine libc static lib path.");
|
||||||
}
|
}
|
||||||
|
@ -5089,7 +5120,10 @@ bool type_has_bits(ZigType *type_entry) {
|
||||||
return !type_entry->zero_bits;
|
return !type_entry->zero_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool type_requires_comptime(ZigType *type_entry) {
|
ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
|
||||||
|
Error err;
|
||||||
|
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
|
||||||
|
return ReqCompTimeInvalid;
|
||||||
switch (type_entry->id) {
|
switch (type_entry->id) {
|
||||||
case ZigTypeIdInvalid:
|
case ZigTypeIdInvalid:
|
||||||
case ZigTypeIdOpaque:
|
case ZigTypeIdOpaque:
|
||||||
|
@ -5102,27 +5136,25 @@ bool type_requires_comptime(ZigType *type_entry) {
|
||||||
case ZigTypeIdNamespace:
|
case ZigTypeIdNamespace:
|
||||||
case ZigTypeIdBoundFn:
|
case ZigTypeIdBoundFn:
|
||||||
case ZigTypeIdArgTuple:
|
case ZigTypeIdArgTuple:
|
||||||
return true;
|
return ReqCompTimeYes;
|
||||||
case ZigTypeIdArray:
|
case ZigTypeIdArray:
|
||||||
return type_requires_comptime(type_entry->data.array.child_type);
|
return type_requires_comptime(g, type_entry->data.array.child_type);
|
||||||
case ZigTypeIdStruct:
|
case ZigTypeIdStruct:
|
||||||
assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));
|
return type_entry->data.structure.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo;
|
||||||
return type_entry->data.structure.requires_comptime;
|
|
||||||
case ZigTypeIdUnion:
|
case ZigTypeIdUnion:
|
||||||
assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown));
|
return type_entry->data.unionation.requires_comptime ? ReqCompTimeYes : ReqCompTimeNo;
|
||||||
return type_entry->data.unionation.requires_comptime;
|
|
||||||
case ZigTypeIdOptional:
|
case ZigTypeIdOptional:
|
||||||
return type_requires_comptime(type_entry->data.maybe.child_type);
|
return type_requires_comptime(g, type_entry->data.maybe.child_type);
|
||||||
case ZigTypeIdErrorUnion:
|
case ZigTypeIdErrorUnion:
|
||||||
return type_requires_comptime(type_entry->data.error_union.payload_type);
|
return type_requires_comptime(g, type_entry->data.error_union.payload_type);
|
||||||
case ZigTypeIdPointer:
|
case ZigTypeIdPointer:
|
||||||
if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) {
|
if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) {
|
||||||
return false;
|
return ReqCompTimeNo;
|
||||||
} else {
|
} else {
|
||||||
return type_requires_comptime(type_entry->data.pointer.child_type);
|
return type_requires_comptime(g, type_entry->data.pointer.child_type);
|
||||||
}
|
}
|
||||||
case ZigTypeIdFn:
|
case ZigTypeIdFn:
|
||||||
return type_entry->data.fn.is_generic;
|
return type_entry->data.fn.is_generic ? ReqCompTimeYes : ReqCompTimeNo;
|
||||||
case ZigTypeIdEnum:
|
case ZigTypeIdEnum:
|
||||||
case ZigTypeIdErrorSet:
|
case ZigTypeIdErrorSet:
|
||||||
case ZigTypeIdBool:
|
case ZigTypeIdBool:
|
||||||
|
@ -5131,7 +5163,7 @@ bool type_requires_comptime(ZigType *type_entry) {
|
||||||
case ZigTypeIdVoid:
|
case ZigTypeIdVoid:
|
||||||
case ZigTypeIdUnreachable:
|
case ZigTypeIdUnreachable:
|
||||||
case ZigTypeIdPromise:
|
case ZigTypeIdPromise:
|
||||||
return false;
|
return ReqCompTimeNo;
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
@ -6090,6 +6122,8 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {
|
||||||
return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089;
|
return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089;
|
||||||
case ZigLLVMFnIdSqrt:
|
case ZigLLVMFnIdSqrt:
|
||||||
return (uint32_t)(x.data.floating.bit_count) * (uint32_t)2225366385;
|
return (uint32_t)(x.data.floating.bit_count) * (uint32_t)2225366385;
|
||||||
|
case ZigLLVMFnIdBswap:
|
||||||
|
return (uint32_t)(x.data.bswap.bit_count) * (uint32_t)3661994335;
|
||||||
case ZigLLVMFnIdOverflowArithmetic:
|
case ZigLLVMFnIdOverflowArithmetic:
|
||||||
return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) +
|
return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) +
|
||||||
((uint32_t)(x.data.overflow_arithmetic.add_sub_mul) * 31640542) +
|
((uint32_t)(x.data.overflow_arithmetic.add_sub_mul) * 31640542) +
|
||||||
|
@ -6108,6 +6142,8 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
|
||||||
return a.data.clz.bit_count == b.data.clz.bit_count;
|
return a.data.clz.bit_count == b.data.clz.bit_count;
|
||||||
case ZigLLVMFnIdPopCount:
|
case ZigLLVMFnIdPopCount:
|
||||||
return a.data.pop_count.bit_count == b.data.pop_count.bit_count;
|
return a.data.pop_count.bit_count == b.data.pop_count.bit_count;
|
||||||
|
case ZigLLVMFnIdBswap:
|
||||||
|
return a.data.bswap.bit_count == b.data.bswap.bit_count;
|
||||||
case ZigLLVMFnIdFloor:
|
case ZigLLVMFnIdFloor:
|
||||||
case ZigLLVMFnIdCeil:
|
case ZigLLVMFnIdCeil:
|
||||||
case ZigLLVMFnIdSqrt:
|
case ZigLLVMFnIdSqrt:
|
||||||
|
|
|
@ -87,7 +87,6 @@ ZigFn *create_fn(CodeGen *g, AstNode *proto_node);
|
||||||
ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);
|
ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);
|
||||||
void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc);
|
void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc);
|
||||||
AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);
|
AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);
|
||||||
bool type_requires_comptime(ZigType *type_entry);
|
|
||||||
Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry);
|
Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry);
|
||||||
Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status);
|
Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status);
|
||||||
void complete_enum(CodeGen *g, ZigType *enum_type);
|
void complete_enum(CodeGen *g, ZigType *enum_type);
|
||||||
|
@ -216,4 +215,11 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);
|
||||||
|
|
||||||
uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field);
|
uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field);
|
||||||
|
|
||||||
|
enum ReqCompTime {
|
||||||
|
ReqCompTimeInvalid,
|
||||||
|
ReqCompTimeNo,
|
||||||
|
ReqCompTimeYes,
|
||||||
|
};
|
||||||
|
ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -181,5 +181,15 @@ static inline Slice<uint8_t> buf_to_slice(Buf *buf) {
|
||||||
return Slice<uint8_t>{reinterpret_cast<uint8_t*>(buf_ptr(buf)), buf_len(buf)};
|
return Slice<uint8_t>{reinterpret_cast<uint8_t*>(buf_ptr(buf)), buf_len(buf)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void buf_replace(Buf* buf, char from, char to) {
|
||||||
|
const size_t count = buf_len(buf);
|
||||||
|
char* ptr = buf_ptr(buf);
|
||||||
|
for (size_t i = 0; i < count; ++i) {
|
||||||
|
char& l = ptr[i];
|
||||||
|
if (l == from)
|
||||||
|
l = to;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -352,8 +352,9 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
|
||||||
// if the mtime matches we can trust the digest
|
// if the mtime matches we can trust the digest
|
||||||
OsFile this_file;
|
OsFile this_file;
|
||||||
if ((err = os_file_open_r(chf->path, &this_file))) {
|
if ((err = os_file_open_r(chf->path, &this_file))) {
|
||||||
|
fprintf(stderr, "Unable to open %s\n: %s", buf_ptr(chf->path), err_str(err));
|
||||||
os_file_close(ch->manifest_file);
|
os_file_close(ch->manifest_file);
|
||||||
return err;
|
return ErrorCacheUnavailable;
|
||||||
}
|
}
|
||||||
OsTimeStamp actual_mtime;
|
OsTimeStamp actual_mtime;
|
||||||
if ((err = os_file_mtime(this_file, &actual_mtime))) {
|
if ((err = os_file_mtime(this_file, &actual_mtime))) {
|
||||||
|
@ -392,8 +393,9 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
|
||||||
for (; file_i < input_file_count; file_i += 1) {
|
for (; file_i < input_file_count; file_i += 1) {
|
||||||
CacheHashFile *chf = &ch->files.at(file_i);
|
CacheHashFile *chf = &ch->files.at(file_i);
|
||||||
if ((err = populate_file_hash(ch, chf, nullptr))) {
|
if ((err = populate_file_hash(ch, chf, nullptr))) {
|
||||||
|
fprintf(stderr, "Unable to hash %s: %s\n", buf_ptr(chf->path), err_str(err));
|
||||||
os_file_close(ch->manifest_file);
|
os_file_close(ch->manifest_file);
|
||||||
return err;
|
return ErrorCacheUnavailable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ErrorNone;
|
return ErrorNone;
|
||||||
|
|
107
src/codegen.cpp
107
src/codegen.cpp
|
@ -129,6 +129,11 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
|
||||||
Buf *src_dir = buf_alloc();
|
Buf *src_dir = buf_alloc();
|
||||||
os_path_split(root_src_path, src_dir, src_basename);
|
os_path_split(root_src_path, src_dir, src_basename);
|
||||||
|
|
||||||
|
if (buf_len(src_basename) == 0) {
|
||||||
|
fprintf(stderr, "Invalid root source path: %s\n", buf_ptr(root_src_path));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
g->root_package = new_package(buf_ptr(src_dir), buf_ptr(src_basename));
|
g->root_package = new_package(buf_ptr(src_dir), buf_ptr(src_basename));
|
||||||
g->std_package = new_package(buf_ptr(g->zig_std_dir), "index.zig");
|
g->std_package = new_package(buf_ptr(g->zig_std_dir), "index.zig");
|
||||||
g->root_package->package_table.put(buf_create_from_str("std"), g->std_package);
|
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
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actual_bits >= wanted_bits && actual_type->id == ZigTypeIdInt &&
|
if (actual_type->id == ZigTypeIdInt &&
|
||||||
!wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed &&
|
!wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed &&
|
||||||
want_runtime_safety)
|
want_runtime_safety)
|
||||||
{
|
{
|
||||||
|
@ -2877,32 +2882,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
|
||||||
gen_store_untyped(g, new_len, dest_len_ptr, 0, false);
|
gen_store_untyped(g, new_len, dest_len_ptr, 0, false);
|
||||||
|
|
||||||
|
|
||||||
return cast_instruction->tmp_ptr;
|
|
||||||
}
|
|
||||||
case CastOpBytesToSlice:
|
|
||||||
{
|
|
||||||
assert(cast_instruction->tmp_ptr);
|
|
||||||
assert(wanted_type->id == ZigTypeIdStruct);
|
|
||||||
assert(wanted_type->data.structure.is_slice);
|
|
||||||
assert(actual_type->id == ZigTypeIdArray);
|
|
||||||
|
|
||||||
ZigType *wanted_pointer_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
|
|
||||||
ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
|
|
||||||
|
|
||||||
|
|
||||||
size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index;
|
|
||||||
LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
|
|
||||||
(unsigned)wanted_ptr_index, "");
|
|
||||||
LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, expr_val, wanted_pointer_type->type_ref, "");
|
|
||||||
gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false);
|
|
||||||
|
|
||||||
size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index;
|
|
||||||
LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
|
|
||||||
(unsigned)wanted_len_index, "");
|
|
||||||
LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
|
|
||||||
actual_type->data.array.len / type_size(g, wanted_child_type), false);
|
|
||||||
gen_store_untyped(g, len_val, len_ptr, 0, false);
|
|
||||||
|
|
||||||
return cast_instruction->tmp_ptr;
|
return cast_instruction->tmp_ptr;
|
||||||
}
|
}
|
||||||
case CastOpIntToFloat:
|
case CastOpIntToFloat:
|
||||||
|
@ -3660,6 +3639,13 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru
|
||||||
AsmOutput *asm_output = asm_expr->output_list.at(i);
|
AsmOutput *asm_output = asm_expr->output_list.at(i);
|
||||||
bool is_return = (asm_output->return_type != nullptr);
|
bool is_return = (asm_output->return_type != nullptr);
|
||||||
assert(*buf_ptr(asm_output->constraint) == '=');
|
assert(*buf_ptr(asm_output->constraint) == '=');
|
||||||
|
// LLVM uses commas internally to separate different constraints,
|
||||||
|
// alternative constraints are achieved with pipes.
|
||||||
|
// We still allow the user to use commas in a way that is similar
|
||||||
|
// to GCC's inline assembly.
|
||||||
|
// http://llvm.org/docs/LangRef.html#constraint-codes
|
||||||
|
buf_replace(asm_output->constraint, ',', '|');
|
||||||
|
|
||||||
if (is_return) {
|
if (is_return) {
|
||||||
buf_appendf(&constraint_buf, "=%s", buf_ptr(asm_output->constraint) + 1);
|
buf_appendf(&constraint_buf, "=%s", buf_ptr(asm_output->constraint) + 1);
|
||||||
} else {
|
} else {
|
||||||
|
@ -3679,14 +3665,30 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < asm_expr->input_list.length; i += 1, total_index += 1, param_index += 1) {
|
for (size_t i = 0; i < asm_expr->input_list.length; i += 1, total_index += 1, param_index += 1) {
|
||||||
AsmInput *asm_input = asm_expr->input_list.at(i);
|
AsmInput *asm_input = asm_expr->input_list.at(i);
|
||||||
|
buf_replace(asm_input->constraint, ',', '|');
|
||||||
IrInstruction *ir_input = instruction->input_list[i];
|
IrInstruction *ir_input = instruction->input_list[i];
|
||||||
buf_append_buf(&constraint_buf, asm_input->constraint);
|
buf_append_buf(&constraint_buf, asm_input->constraint);
|
||||||
if (total_index + 1 < total_constraint_count) {
|
if (total_index + 1 < total_constraint_count) {
|
||||||
buf_append_char(&constraint_buf, ',');
|
buf_append_char(&constraint_buf, ',');
|
||||||
}
|
}
|
||||||
|
|
||||||
param_types[param_index] = ir_input->value.type->type_ref;
|
ZigType *const type = ir_input->value.type;
|
||||||
param_values[param_index] = ir_llvm_value(g, ir_input);
|
LLVMTypeRef type_ref = type->type_ref;
|
||||||
|
LLVMValueRef value_ref = ir_llvm_value(g, ir_input);
|
||||||
|
// Handle integers of non pot bitsize by widening them.
|
||||||
|
if (type->id == ZigTypeIdInt) {
|
||||||
|
const size_t bitsize = type->data.integral.bit_count;
|
||||||
|
if (bitsize < 8 || !is_power_of_2(bitsize)) {
|
||||||
|
const bool is_signed = type->data.integral.is_signed;
|
||||||
|
const size_t wider_bitsize = bitsize < 8 ? 8 : round_to_next_power_of_2(bitsize);
|
||||||
|
ZigType *const wider_type = get_int_type(g, is_signed, wider_bitsize);
|
||||||
|
type_ref = wider_type->type_ref;
|
||||||
|
value_ref = gen_widen_or_shorten(g, false, type, wider_type, value_ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
param_types[param_index] = type_ref;
|
||||||
|
param_values[param_index] = value_ref;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1, total_index += 1) {
|
for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1, total_index += 1) {
|
||||||
Buf *clobber_buf = asm_expr->clobber_list.at(i);
|
Buf *clobber_buf = asm_expr->clobber_list.at(i);
|
||||||
|
@ -3705,8 +3707,8 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru
|
||||||
LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, (unsigned)input_and_output_count, false);
|
LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, (unsigned)input_and_output_count, false);
|
||||||
|
|
||||||
bool is_volatile = asm_expr->is_volatile || (asm_expr->output_list.length == 0);
|
bool is_volatile = asm_expr->is_volatile || (asm_expr->output_list.length == 0);
|
||||||
LLVMValueRef asm_fn = LLVMConstInlineAsm(function_type, buf_ptr(&llvm_template),
|
LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(&llvm_template), buf_len(&llvm_template),
|
||||||
buf_ptr(&constraint_buf), is_volatile, false);
|
buf_ptr(&constraint_buf), buf_len(&constraint_buf), is_volatile, false, LLVMInlineAsmDialectATT);
|
||||||
|
|
||||||
return LLVMBuildCall(g->builder, asm_fn, param_values, (unsigned)input_and_output_count, "");
|
return LLVMBuildCall(g->builder, asm_fn, param_values, (unsigned)input_and_output_count, "");
|
||||||
}
|
}
|
||||||
|
@ -3786,6 +3788,11 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI
|
||||||
n_args = 1;
|
n_args = 1;
|
||||||
key.id = ZigLLVMFnIdPopCount;
|
key.id = ZigLLVMFnIdPopCount;
|
||||||
key.data.pop_count.bit_count = (uint32_t)int_type->data.integral.bit_count;
|
key.data.pop_count.bit_count = (uint32_t)int_type->data.integral.bit_count;
|
||||||
|
} else if (fn_id == BuiltinFnIdBswap) {
|
||||||
|
fn_name = "bswap";
|
||||||
|
n_args = 1;
|
||||||
|
key.id = ZigLLVMFnIdBswap;
|
||||||
|
key.data.bswap.bit_count = (uint32_t)int_type->data.integral.bit_count;
|
||||||
} else {
|
} else {
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
@ -5070,6 +5077,29 @@ static LLVMValueRef ir_render_sqrt(CodeGen *g, IrExecutable *executable, IrInstr
|
||||||
return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
|
return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInstructionBswap *instruction) {
|
||||||
|
LLVMValueRef op = ir_llvm_value(g, instruction->op);
|
||||||
|
ZigType *int_type = instruction->base.value.type;
|
||||||
|
assert(int_type->id == ZigTypeIdInt);
|
||||||
|
if (int_type->data.integral.bit_count % 16 == 0) {
|
||||||
|
LLVMValueRef fn_val = get_int_builtin_fn(g, instruction->base.value.type, BuiltinFnIdBswap);
|
||||||
|
return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
|
||||||
|
}
|
||||||
|
// Not an even number of bytes, so we zext 1 byte, then bswap, shift right 1 byte, truncate
|
||||||
|
ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed,
|
||||||
|
int_type->data.integral.bit_count + 8);
|
||||||
|
// aabbcc
|
||||||
|
LLVMValueRef extended = LLVMBuildZExt(g->builder, op, extended_type->type_ref, "");
|
||||||
|
// 00aabbcc
|
||||||
|
LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap);
|
||||||
|
LLVMValueRef swapped = LLVMBuildCall(g->builder, fn_val, &extended, 1, "");
|
||||||
|
// ccbbaa00
|
||||||
|
LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped,
|
||||||
|
LLVMConstInt(extended_type->type_ref, 8, false), "");
|
||||||
|
// 00ccbbaa
|
||||||
|
return LLVMBuildTrunc(g->builder, shifted, int_type->type_ref, "");
|
||||||
|
}
|
||||||
|
|
||||||
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
|
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
|
||||||
AstNode *source_node = instruction->source_node;
|
AstNode *source_node = instruction->source_node;
|
||||||
Scope *scope = instruction->scope;
|
Scope *scope = instruction->scope;
|
||||||
|
@ -5307,6 +5337,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
||||||
return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction);
|
return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction);
|
||||||
case IrInstructionIdSqrt:
|
case IrInstructionIdSqrt:
|
||||||
return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction);
|
return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction);
|
||||||
|
case IrInstructionIdBswap:
|
||||||
|
return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction);
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
@ -6258,8 +6290,14 @@ static void do_code_gen(CodeGen *g) {
|
||||||
}
|
}
|
||||||
if (ir_get_var_is_comptime(var))
|
if (ir_get_var_is_comptime(var))
|
||||||
continue;
|
continue;
|
||||||
if (type_requires_comptime(var->value->type))
|
switch (type_requires_comptime(g, var->value->type)) {
|
||||||
|
case ReqCompTimeInvalid:
|
||||||
|
zig_unreachable();
|
||||||
|
case ReqCompTimeYes:
|
||||||
continue;
|
continue;
|
||||||
|
case ReqCompTimeNo:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (var->src_arg_index == SIZE_MAX) {
|
if (var->src_arg_index == SIZE_MAX) {
|
||||||
var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);
|
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) {
|
||||||
create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);
|
create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);
|
||||||
create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
|
create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
|
||||||
create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
|
create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
|
||||||
|
create_builtin_fn(g, BuiltinFnIdBswap, "bswap", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *bool_to_str(bool b) {
|
static const char *bool_to_str(bool b) {
|
||||||
|
@ -8149,7 +8188,11 @@ void codegen_build_and_link(CodeGen *g) {
|
||||||
os_path_join(stage1_dir, buf_create_from_str("build"), manifest_dir);
|
os_path_join(stage1_dir, buf_create_from_str("build"), manifest_dir);
|
||||||
|
|
||||||
if ((err = check_cache(g, manifest_dir, &digest))) {
|
if ((err = check_cache(g, manifest_dir, &digest))) {
|
||||||
|
if (err == ErrorCacheUnavailable) {
|
||||||
|
// message already printed
|
||||||
|
} else {
|
||||||
fprintf(stderr, "Unable to check cache: %s\n", err_str(err));
|
fprintf(stderr, "Unable to check cache: %s\n", err_str(err));
|
||||||
|
}
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ const char *err_str(Error err) {
|
||||||
case ErrorSharingViolation: return "sharing violation";
|
case ErrorSharingViolation: return "sharing violation";
|
||||||
case ErrorPipeBusy: return "pipe busy";
|
case ErrorPipeBusy: return "pipe busy";
|
||||||
case ErrorPrimitiveTypeNotFound: return "primitive type not found";
|
case ErrorPrimitiveTypeNotFound: return "primitive type not found";
|
||||||
|
case ErrorCacheUnavailable: return "cache unavailable";
|
||||||
}
|
}
|
||||||
return "(invalid error)";
|
return "(invalid error)";
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ enum Error {
|
||||||
ErrorSharingViolation,
|
ErrorSharingViolation,
|
||||||
ErrorPipeBusy,
|
ErrorPipeBusy,
|
||||||
ErrorPrimitiveTypeNotFound,
|
ErrorPrimitiveTypeNotFound,
|
||||||
|
ErrorCacheUnavailable,
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *err_str(Error err);
|
const char *err_str(Error err);
|
||||||
|
|
761
src/ir.cpp
761
src/ir.cpp
File diff suppressed because it is too large
Load Diff
|
@ -1323,6 +1323,18 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) {
|
||||||
fprintf(irp->f, ")");
|
fprintf(irp->f, ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) {
|
||||||
|
fprintf(irp->f, "@bswap(");
|
||||||
|
if (instruction->type != nullptr) {
|
||||||
|
ir_print_other_instruction(irp, instruction->type);
|
||||||
|
} else {
|
||||||
|
fprintf(irp->f, "null");
|
||||||
|
}
|
||||||
|
fprintf(irp->f, ",");
|
||||||
|
ir_print_other_instruction(irp, instruction->op);
|
||||||
|
fprintf(irp->f, ")");
|
||||||
|
}
|
||||||
|
|
||||||
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||||
ir_print_prefix(irp, instruction);
|
ir_print_prefix(irp, instruction);
|
||||||
switch (instruction->id) {
|
switch (instruction->id) {
|
||||||
|
@ -1736,6 +1748,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||||
case IrInstructionIdSqrt:
|
case IrInstructionIdSqrt:
|
||||||
ir_print_sqrt(irp, (IrInstructionSqrt *)instruction);
|
ir_print_sqrt(irp, (IrInstructionSqrt *)instruction);
|
||||||
break;
|
break;
|
||||||
|
case IrInstructionIdBswap:
|
||||||
|
ir_print_bswap(irp, (IrInstructionBswap *)instruction);
|
||||||
|
break;
|
||||||
case IrInstructionIdAtomicLoad:
|
case IrInstructionIdAtomicLoad:
|
||||||
ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);
|
ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -150,6 +150,10 @@ static const char *getLDMOption(const ZigTarget *t) {
|
||||||
if (t->env_type == ZigLLVM_GNUX32) {
|
if (t->env_type == ZigLLVM_GNUX32) {
|
||||||
return "elf32_x86_64";
|
return "elf32_x86_64";
|
||||||
}
|
}
|
||||||
|
// Any target elf will use the freebsd osabi if suffixed with "_fbsd".
|
||||||
|
if (t->os == OsFreeBSD) {
|
||||||
|
return "elf_x86_64_fbsd";
|
||||||
|
}
|
||||||
return "elf_x86_64";
|
return "elf_x86_64";
|
||||||
default:
|
default:
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
|
@ -191,6 +195,9 @@ static Buf *try_dynamic_linker_path(const char *ld_name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static Buf *get_dynamic_linker_path(CodeGen *g) {
|
static Buf *get_dynamic_linker_path(CodeGen *g) {
|
||||||
|
if (g->zig_target.os == OsFreeBSD) {
|
||||||
|
return buf_create_from_str("/libexec/ld-elf.so.1");
|
||||||
|
}
|
||||||
if (g->is_native_target && g->zig_target.arch.arch == ZigLLVM_x86_64) {
|
if (g->is_native_target && g->zig_target.arch.arch == ZigLLVM_x86_64) {
|
||||||
static const char *ld_names[] = {
|
static const char *ld_names[] = {
|
||||||
"ld-linux-x86-64.so.2",
|
"ld-linux-x86-64.so.2",
|
||||||
|
|
|
@ -466,16 +466,9 @@ int main(int argc, char **argv) {
|
||||||
"\n"
|
"\n"
|
||||||
"General Options:\n"
|
"General Options:\n"
|
||||||
" --help Print this help and exit\n"
|
" --help Print this help and exit\n"
|
||||||
" --build-file [file] Override path to build.zig\n"
|
|
||||||
" --cache-dir [path] Override path to cache directory\n"
|
|
||||||
" --verbose Print commands before executing them\n"
|
" --verbose Print commands before executing them\n"
|
||||||
" --verbose-tokenize Enable compiler debug output for tokenization\n"
|
|
||||||
" --verbose-ast Enable compiler debug output for parsing into an AST\n"
|
|
||||||
" --verbose-link Enable compiler debug output for linking\n"
|
|
||||||
" --verbose-ir Enable compiler debug output for Zig IR\n"
|
|
||||||
" --verbose-llvm-ir Enable compiler debug output for LLVM IR\n"
|
|
||||||
" --verbose-cimport Enable compiler debug output for C imports\n"
|
|
||||||
" --prefix [path] Override default install prefix\n"
|
" --prefix [path] Override default install prefix\n"
|
||||||
|
" --search-prefix [path] Add a path to look for binaries, libraries, headers\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Project-specific options become available when the build file is found.\n"
|
"Project-specific options become available when the build file is found.\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
36
src/os.cpp
36
src/os.cpp
|
@ -50,10 +50,13 @@ typedef SSIZE_T ssize_t;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ZIG_OS_LINUX)
|
#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD)
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(ZIG_OS_FREEBSD)
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__MACH__)
|
#if defined(__MACH__)
|
||||||
#include <mach/clock.h>
|
#include <mach/clock.h>
|
||||||
|
@ -75,6 +78,8 @@ static clock_serv_t cclock;
|
||||||
#if defined(__APPLE__) && !defined(environ)
|
#if defined(__APPLE__) && !defined(environ)
|
||||||
#include <crt_externs.h>
|
#include <crt_externs.h>
|
||||||
#define environ (*_NSGetEnviron())
|
#define environ (*_NSGetEnviron())
|
||||||
|
#elif defined(ZIG_OS_FREEBSD)
|
||||||
|
extern char **environ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ZIG_OS_POSIX)
|
#if defined(ZIG_OS_POSIX)
|
||||||
|
@ -188,14 +193,20 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename) {
|
||||||
size_t len = buf_len(full_path);
|
size_t len = buf_len(full_path);
|
||||||
if (len != 0) {
|
if (len != 0) {
|
||||||
size_t last_index = len - 1;
|
size_t last_index = len - 1;
|
||||||
if (os_is_sep(buf_ptr(full_path)[last_index])) {
|
char last_char = buf_ptr(full_path)[last_index];
|
||||||
|
if (os_is_sep(last_char)) {
|
||||||
|
if (last_index == 0) {
|
||||||
|
if (out_dirname) buf_init_from_mem(out_dirname, &last_char, 1);
|
||||||
|
if (out_basename) buf_init_from_str(out_basename, "");
|
||||||
|
return;
|
||||||
|
}
|
||||||
last_index -= 1;
|
last_index -= 1;
|
||||||
}
|
}
|
||||||
for (size_t i = last_index;;) {
|
for (size_t i = last_index;;) {
|
||||||
uint8_t c = buf_ptr(full_path)[i];
|
uint8_t c = buf_ptr(full_path)[i];
|
||||||
if (os_is_sep(c)) {
|
if (os_is_sep(c)) {
|
||||||
if (out_dirname) {
|
if (out_dirname) {
|
||||||
buf_init_from_mem(out_dirname, buf_ptr(full_path), i);
|
buf_init_from_mem(out_dirname, buf_ptr(full_path), (i == 0) ? 1 : i);
|
||||||
}
|
}
|
||||||
if (out_basename) {
|
if (out_basename) {
|
||||||
buf_init_from_mem(out_basename, buf_ptr(full_path) + i + 1, buf_len(full_path) - (i + 1));
|
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) {
|
||||||
}
|
}
|
||||||
buf_resize(out_path, amt);
|
buf_resize(out_path, amt);
|
||||||
return ErrorNone;
|
return ErrorNone;
|
||||||
|
#elif defined(ZIG_OS_FREEBSD)
|
||||||
|
buf_resize(out_path, PATH_MAX);
|
||||||
|
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
|
||||||
|
size_t cb = PATH_MAX;
|
||||||
|
if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) {
|
||||||
|
return ErrorUnexpected;
|
||||||
|
}
|
||||||
|
buf_resize(out_path, cb - 1);
|
||||||
|
return ErrorNone;
|
||||||
#endif
|
#endif
|
||||||
return ErrorFileNotFound;
|
return ErrorFileNotFound;
|
||||||
}
|
}
|
||||||
|
@ -1743,7 +1763,7 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) {
|
||||||
buf_resize(out_path, 0);
|
buf_resize(out_path, 0);
|
||||||
buf_appendf(out_path, "%s/Library/Application Support/%s", home_dir, appname);
|
buf_appendf(out_path, "%s/Library/Application Support/%s", home_dir, appname);
|
||||||
return ErrorNone;
|
return ErrorNone;
|
||||||
#elif defined(ZIG_OS_LINUX)
|
#elif defined(ZIG_OS_POSIX)
|
||||||
const char *home_dir = getenv("HOME");
|
const char *home_dir = getenv("HOME");
|
||||||
if (home_dir == nullptr) {
|
if (home_dir == nullptr) {
|
||||||
// TODO use /etc/passwd
|
// TODO use /etc/passwd
|
||||||
|
@ -1756,7 +1776,7 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined(ZIG_OS_LINUX)
|
#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD)
|
||||||
static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, void *data) {
|
static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, void *data) {
|
||||||
ZigList<Buf *> *libs = reinterpret_cast< ZigList<Buf *> *>(data);
|
ZigList<Buf *> *libs = reinterpret_cast< ZigList<Buf *> *>(data);
|
||||||
if (info->dlpi_name[0] == '/') {
|
if (info->dlpi_name[0] == '/') {
|
||||||
|
@ -1767,7 +1787,7 @@ static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {
|
Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {
|
||||||
#if defined(ZIG_OS_LINUX)
|
#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD)
|
||||||
paths.resize(0);
|
paths.resize(0);
|
||||||
dl_iterate_phdr(self_exe_shared_libs_callback, &paths);
|
dl_iterate_phdr(self_exe_shared_libs_callback, &paths);
|
||||||
return ErrorNone;
|
return ErrorNone;
|
||||||
|
@ -1936,7 +1956,7 @@ Error os_file_mtime(OsFile file, OsTimeStamp *mtime) {
|
||||||
mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime;
|
mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime;
|
||||||
mtime->nsec = 0;
|
mtime->nsec = 0;
|
||||||
return ErrorNone;
|
return ErrorNone;
|
||||||
#elif defined(ZIG_OS_LINUX)
|
#elif defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD)
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
if (fstat(file, &statbuf) == -1)
|
if (fstat(file, &statbuf) == -1)
|
||||||
return ErrorFileSystem;
|
return ErrorFileSystem;
|
||||||
|
@ -1976,7 +1996,7 @@ Error os_file_read(OsFile file, void *ptr, size_t *len) {
|
||||||
case EFAULT:
|
case EFAULT:
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
case EISDIR:
|
case EISDIR:
|
||||||
zig_unreachable();
|
return ErrorIsDir;
|
||||||
default:
|
default:
|
||||||
return ErrorFileSystem;
|
return ErrorFileSystem;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#define ZIG_OS_WINDOWS
|
#define ZIG_OS_WINDOWS
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
#define ZIG_OS_LINUX
|
#define ZIG_OS_LINUX
|
||||||
|
#elif defined(__FreeBSD__)
|
||||||
|
#define ZIG_OS_FREEBSD
|
||||||
#else
|
#else
|
||||||
#define ZIG_OS_UNKNOWN
|
#define ZIG_OS_UNKNOWN
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -91,7 +91,7 @@ static Token *ast_parse_break_label(ParseContext *pc);
|
||||||
static Token *ast_parse_block_label(ParseContext *pc);
|
static Token *ast_parse_block_label(ParseContext *pc);
|
||||||
static AstNode *ast_parse_field_init(ParseContext *pc);
|
static AstNode *ast_parse_field_init(ParseContext *pc);
|
||||||
static AstNode *ast_parse_while_continue_expr(ParseContext *pc);
|
static AstNode *ast_parse_while_continue_expr(ParseContext *pc);
|
||||||
static AstNode *ast_parse_section(ParseContext *pc);
|
static AstNode *ast_parse_link_section(ParseContext *pc);
|
||||||
static Optional<AstNodeFnProto> ast_parse_fn_cc(ParseContext *pc);
|
static Optional<AstNodeFnProto> ast_parse_fn_cc(ParseContext *pc);
|
||||||
static AstNode *ast_parse_param_decl(ParseContext *pc);
|
static AstNode *ast_parse_param_decl(ParseContext *pc);
|
||||||
static AstNode *ast_parse_param_type(ParseContext *pc);
|
static AstNode *ast_parse_param_type(ParseContext *pc);
|
||||||
|
@ -775,7 +775,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? Section? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
|
// FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
|
||||||
static AstNode *ast_parse_fn_proto(ParseContext *pc) {
|
static AstNode *ast_parse_fn_proto(ParseContext *pc) {
|
||||||
Token *first = peek_token(pc);
|
Token *first = peek_token(pc);
|
||||||
AstNodeFnProto fn_cc;
|
AstNodeFnProto fn_cc;
|
||||||
|
@ -806,7 +806,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {
|
||||||
expect_token(pc, TokenIdRParen);
|
expect_token(pc, TokenIdRParen);
|
||||||
|
|
||||||
AstNode *align_expr = ast_parse_byte_align(pc);
|
AstNode *align_expr = ast_parse_byte_align(pc);
|
||||||
AstNode *section_expr = ast_parse_section(pc);
|
AstNode *section_expr = ast_parse_link_section(pc);
|
||||||
Token *var = eat_token_if(pc, TokenIdKeywordVar);
|
Token *var = eat_token_if(pc, TokenIdKeywordVar);
|
||||||
Token *exmark = nullptr;
|
Token *exmark = nullptr;
|
||||||
AstNode *return_type = nullptr;
|
AstNode *return_type = nullptr;
|
||||||
|
@ -842,7 +842,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? Section? (EQUAL Expr)? SEMICOLON
|
// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON
|
||||||
static AstNode *ast_parse_var_decl(ParseContext *pc) {
|
static AstNode *ast_parse_var_decl(ParseContext *pc) {
|
||||||
Token *first = eat_token_if(pc, TokenIdKeywordConst);
|
Token *first = eat_token_if(pc, TokenIdKeywordConst);
|
||||||
if (first == nullptr)
|
if (first == nullptr)
|
||||||
|
@ -856,7 +856,7 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) {
|
||||||
type_expr = ast_expect(pc, ast_parse_type_expr);
|
type_expr = ast_expect(pc, ast_parse_type_expr);
|
||||||
|
|
||||||
AstNode *align_expr = ast_parse_byte_align(pc);
|
AstNode *align_expr = ast_parse_byte_align(pc);
|
||||||
AstNode *section_expr = ast_parse_section(pc);
|
AstNode *section_expr = ast_parse_link_section(pc);
|
||||||
AstNode *expr = nullptr;
|
AstNode *expr = nullptr;
|
||||||
if (eat_token_if(pc, TokenIdEq) != nullptr)
|
if (eat_token_if(pc, TokenIdEq) != nullptr)
|
||||||
expr = ast_expect(pc, ast_parse_expr);
|
expr = ast_expect(pc, ast_parse_expr);
|
||||||
|
@ -1490,8 +1490,8 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SuffixExpr
|
// SuffixExpr
|
||||||
// <- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArgumnets
|
// <- AsyncPrefix PrimaryTypeExpr SuffixOp* FnCallArguments
|
||||||
// / PrimaryTypeExpr (SuffixOp / FnCallArgumnets)*
|
// / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
|
||||||
static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
|
static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
|
||||||
AstNode *async_call = ast_parse_async_prefix(pc);
|
AstNode *async_call = ast_parse_async_prefix(pc);
|
||||||
if (async_call != nullptr) {
|
if (async_call != nullptr) {
|
||||||
|
@ -1599,7 +1599,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrimaryTypeExpr
|
// PrimaryTypeExpr
|
||||||
// <- BUILTININDENTIFIER FnCallArgumnets
|
// <- BUILTINIDENTIFIER FnCallArguments
|
||||||
// / CHAR_LITERAL
|
// / CHAR_LITERAL
|
||||||
// / ContainerDecl
|
// / ContainerDecl
|
||||||
// / ErrorSetDecl
|
// / ErrorSetDecl
|
||||||
|
@ -1978,7 +1978,7 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// AsmInput <- COLON AsmInputList AsmCloppers?
|
// AsmInput <- COLON AsmInputList AsmClobbers?
|
||||||
static AstNode *ast_parse_asm_input(ParseContext *pc) {
|
static AstNode *ast_parse_asm_input(ParseContext *pc) {
|
||||||
if (eat_token_if(pc, TokenIdColon) == nullptr)
|
if (eat_token_if(pc, TokenIdColon) == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -2011,7 +2011,7 @@ static AsmInput *ast_parse_asm_input_item(ParseContext *pc) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// AsmCloppers <- COLON StringList
|
// AsmClobbers <- COLON StringList
|
||||||
static AstNode *ast_parse_asm_cloppers(ParseContext *pc) {
|
static AstNode *ast_parse_asm_cloppers(ParseContext *pc) {
|
||||||
if (eat_token_if(pc, TokenIdColon) == nullptr)
|
if (eat_token_if(pc, TokenIdColon) == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -2080,8 +2080,8 @@ static AstNode *ast_parse_while_continue_expr(ParseContext *pc) {
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Section <- KEYWORD_section LPAREN Expr RPAREN
|
// LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN
|
||||||
static AstNode *ast_parse_section(ParseContext *pc) {
|
static AstNode *ast_parse_link_section(ParseContext *pc) {
|
||||||
Token *first = eat_token_if(pc, TokenIdKeywordLinkSection);
|
Token *first = eat_token_if(pc, TokenIdKeywordLinkSection);
|
||||||
if (first == nullptr)
|
if (first == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -2742,7 +2742,7 @@ static AstNode *ast_parse_async_prefix(ParseContext *pc) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FnCallArgumnets <- LPAREN ExprList RPAREN
|
// FnCallArguments <- LPAREN ExprList RPAREN
|
||||||
static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) {
|
static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) {
|
||||||
Token *paren = eat_token_if(pc, TokenIdLParen);
|
Token *paren = eat_token_if(pc, TokenIdLParen);
|
||||||
if (paren == nullptr)
|
if (paren == nullptr)
|
||||||
|
|
|
@ -754,6 +754,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
|
||||||
case OsLinux:
|
case OsLinux:
|
||||||
case OsMacOSX:
|
case OsMacOSX:
|
||||||
case OsZen:
|
case OsZen:
|
||||||
|
case OsFreeBSD:
|
||||||
case OsOpenBSD:
|
case OsOpenBSD:
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case CIntTypeShort:
|
case CIntTypeShort:
|
||||||
|
@ -790,7 +791,6 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
|
||||||
case OsAnanas:
|
case OsAnanas:
|
||||||
case OsCloudABI:
|
case OsCloudABI:
|
||||||
case OsDragonFly:
|
case OsDragonFly:
|
||||||
case OsFreeBSD:
|
|
||||||
case OsIOS:
|
case OsIOS:
|
||||||
case OsKFreeBSD:
|
case OsKFreeBSD:
|
||||||
case OsLv2:
|
case OsLv2:
|
||||||
|
@ -1028,3 +1028,64 @@ const char *arch_stack_pointer_register_name(const ArchType *arch) {
|
||||||
}
|
}
|
||||||
zig_unreachable();
|
zig_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool target_is_arm(const ZigTarget *target) {
|
||||||
|
switch (target->arch.arch) {
|
||||||
|
case ZigLLVM_UnknownArch:
|
||||||
|
zig_unreachable();
|
||||||
|
case ZigLLVM_aarch64:
|
||||||
|
case ZigLLVM_arm:
|
||||||
|
case ZigLLVM_thumb:
|
||||||
|
case ZigLLVM_aarch64_be:
|
||||||
|
case ZigLLVM_armeb:
|
||||||
|
case ZigLLVM_thumbeb:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case ZigLLVM_x86:
|
||||||
|
case ZigLLVM_x86_64:
|
||||||
|
case ZigLLVM_amdgcn:
|
||||||
|
case ZigLLVM_amdil:
|
||||||
|
case ZigLLVM_amdil64:
|
||||||
|
case ZigLLVM_arc:
|
||||||
|
case ZigLLVM_avr:
|
||||||
|
case ZigLLVM_bpfeb:
|
||||||
|
case ZigLLVM_bpfel:
|
||||||
|
case ZigLLVM_hexagon:
|
||||||
|
case ZigLLVM_lanai:
|
||||||
|
case ZigLLVM_hsail:
|
||||||
|
case ZigLLVM_hsail64:
|
||||||
|
case ZigLLVM_kalimba:
|
||||||
|
case ZigLLVM_le32:
|
||||||
|
case ZigLLVM_le64:
|
||||||
|
case ZigLLVM_mips:
|
||||||
|
case ZigLLVM_mips64:
|
||||||
|
case ZigLLVM_mips64el:
|
||||||
|
case ZigLLVM_mipsel:
|
||||||
|
case ZigLLVM_msp430:
|
||||||
|
case ZigLLVM_nios2:
|
||||||
|
case ZigLLVM_nvptx:
|
||||||
|
case ZigLLVM_nvptx64:
|
||||||
|
case ZigLLVM_ppc64le:
|
||||||
|
case ZigLLVM_r600:
|
||||||
|
case ZigLLVM_renderscript32:
|
||||||
|
case ZigLLVM_renderscript64:
|
||||||
|
case ZigLLVM_riscv32:
|
||||||
|
case ZigLLVM_riscv64:
|
||||||
|
case ZigLLVM_shave:
|
||||||
|
case ZigLLVM_sparc:
|
||||||
|
case ZigLLVM_sparcel:
|
||||||
|
case ZigLLVM_sparcv9:
|
||||||
|
case ZigLLVM_spir:
|
||||||
|
case ZigLLVM_spir64:
|
||||||
|
case ZigLLVM_systemz:
|
||||||
|
case ZigLLVM_tce:
|
||||||
|
case ZigLLVM_tcele:
|
||||||
|
case ZigLLVM_wasm32:
|
||||||
|
case ZigLLVM_wasm64:
|
||||||
|
case ZigLLVM_xcore:
|
||||||
|
case ZigLLVM_ppc:
|
||||||
|
case ZigLLVM_ppc64:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
zig_unreachable();
|
||||||
|
}
|
||||||
|
|
|
@ -122,4 +122,6 @@ Buf *target_dynamic_linker(ZigTarget *target);
|
||||||
bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target);
|
bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target);
|
||||||
ZigLLVM_OSType get_llvm_os_type(Os os_type);
|
ZigLLVM_OSType get_llvm_os_type(Os os_type);
|
||||||
|
|
||||||
|
bool target_is_arm(const ZigTarget *target);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4784,6 +4784,14 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
|
||||||
|
|
||||||
clang_argv.append(target_file);
|
clang_argv.append(target_file);
|
||||||
|
|
||||||
|
if (codegen->verbose_cimport) {
|
||||||
|
fprintf(stderr, "clang");
|
||||||
|
for (size_t i = 0; i < clang_argv.length; i += 1) {
|
||||||
|
fprintf(stderr, " %s", clang_argv.at(i));
|
||||||
|
}
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
// to make the [start...end] argument work
|
// to make the [start...end] argument work
|
||||||
clang_argv.append(nullptr);
|
clang_argv.append(nullptr);
|
||||||
|
|
||||||
|
|
11
src/util.hpp
11
src/util.hpp
|
@ -158,6 +158,17 @@ static inline bool is_power_of_2(uint64_t x) {
|
||||||
return x != 0 && ((x & (~x + 1)) == x);
|
return x != 0 && ((x & (~x + 1)) == x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint64_t round_to_next_power_of_2(uint64_t x) {
|
||||||
|
--x;
|
||||||
|
x |= x >> 1;
|
||||||
|
x |= x >> 2;
|
||||||
|
x |= x >> 4;
|
||||||
|
x |= x >> 8;
|
||||||
|
x |= x >> 16;
|
||||||
|
x |= x >> 32;
|
||||||
|
return x + 1;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t int_hash(int i);
|
uint32_t int_hash(int i);
|
||||||
bool int_eq(int a, int b);
|
bool int_eq(int a, int b);
|
||||||
uint32_t uint64_hash(uint64_t i);
|
uint32_t uint64_hash(uint64_t i);
|
||||||
|
|
175
src/zig_llvm.cpp
175
src/zig_llvm.cpp
|
@ -680,20 +680,6 @@ void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) {
|
||||||
llvm::cl::ParseCommandLineOptions(argc, argv);
|
llvm::cl::ParseCommandLineOptions(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static_assert((Triple::ArchType)ZigLLVM_LastArchType == Triple::LastArchType, "");
|
|
||||||
static_assert((Triple::VendorType)ZigLLVM_LastVendorType == Triple::LastVendorType, "");
|
|
||||||
static_assert((Triple::OSType)ZigLLVM_LastOSType == Triple::LastOSType, "");
|
|
||||||
static_assert((Triple::EnvironmentType)ZigLLVM_LastEnvironmentType == Triple::LastEnvironmentType, "");
|
|
||||||
static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v5 == Triple::KalimbaSubArch_v5, "");
|
|
||||||
static_assert((Triple::SubArchType)ZigLLVM_MipsSubArch_r6 == Triple::MipsSubArch_r6, "");
|
|
||||||
|
|
||||||
static_assert((Triple::ObjectFormatType)ZigLLVM_UnknownObjectFormat == Triple::UnknownObjectFormat, "");
|
|
||||||
static_assert((Triple::ObjectFormatType)ZigLLVM_COFF == Triple::COFF, "");
|
|
||||||
static_assert((Triple::ObjectFormatType)ZigLLVM_ELF == Triple::ELF, "");
|
|
||||||
static_assert((Triple::ObjectFormatType)ZigLLVM_MachO == Triple::MachO, "");
|
|
||||||
static_assert((Triple::ObjectFormatType)ZigLLVM_Wasm == Triple::Wasm, "");
|
|
||||||
|
|
||||||
const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch) {
|
const char *ZigLLVMGetArchTypeName(ZigLLVM_ArchType arch) {
|
||||||
return (const char*)Triple::getArchTypeName((Triple::ArchType)arch).bytes_begin();
|
return (const char*)Triple::getArchTypeName((Triple::ArchType)arch).bytes_begin();
|
||||||
}
|
}
|
||||||
|
@ -924,3 +910,164 @@ bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_
|
||||||
assert(false); // unreachable
|
assert(false); // unreachable
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_UnknownArch == Triple::UnknownArch, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_arm == Triple::arm, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_armeb == Triple::armeb, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_aarch64 == Triple::aarch64, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_aarch64_be == Triple::aarch64_be, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_arc == Triple::arc, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_avr == Triple::avr, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_bpfel == Triple::bpfel, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_bpfeb == Triple::bpfeb, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_hexagon == Triple::hexagon, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_mips == Triple::mips, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_mipsel == Triple::mipsel, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_mips64 == Triple::mips64, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_mips64el == Triple::mips64el, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_msp430 == Triple::msp430, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_nios2 == Triple::nios2, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_ppc == Triple::ppc, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_ppc64 == Triple::ppc64, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_ppc64le == Triple::ppc64le, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_r600 == Triple::r600, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_amdgcn == Triple::amdgcn, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_riscv32 == Triple::riscv32, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_riscv64 == Triple::riscv64, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_sparc == Triple::sparc, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_sparcv9 == Triple::sparcv9, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_sparcel == Triple::sparcel, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_systemz == Triple::systemz, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_tce == Triple::tce, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_tcele == Triple::tcele, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_thumb == Triple::thumb, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_thumbeb == Triple::thumbeb, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_x86 == Triple::x86, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_x86_64 == Triple::x86_64, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_xcore == Triple::xcore, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_nvptx == Triple::nvptx, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_nvptx64 == Triple::nvptx64, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_le32 == Triple::le32, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_le64 == Triple::le64, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_amdil == Triple::amdil, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_amdil64 == Triple::amdil64, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_hsail == Triple::hsail, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_hsail64 == Triple::hsail64, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_spir == Triple::spir, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_spir64 == Triple::spir64, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_kalimba == Triple::kalimba, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_shave == Triple::shave, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_lanai == Triple::lanai, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_wasm32 == Triple::wasm32, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_wasm64 == Triple::wasm64, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_renderscript32 == Triple::renderscript32, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_renderscript64 == Triple::renderscript64, "");
|
||||||
|
static_assert((Triple::ArchType)ZigLLVM_LastArchType == Triple::LastArchType, "");
|
||||||
|
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_NoSubArch == Triple::NoSubArch, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_4a == Triple::ARMSubArch_v8_4a, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_3a == Triple::ARMSubArch_v8_3a, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_2a == Triple::ARMSubArch_v8_2a, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8_1a == Triple::ARMSubArch_v8_1a, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8 == Triple::ARMSubArch_v8, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8r == Triple::ARMSubArch_v8r, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8m_baseline == Triple::ARMSubArch_v8m_baseline, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v8m_mainline == Triple::ARMSubArch_v8m_mainline, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7 == Triple::ARMSubArch_v7, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7em == Triple::ARMSubArch_v7em, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7m == Triple::ARMSubArch_v7m, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7s == Triple::ARMSubArch_v7s, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7k == Triple::ARMSubArch_v7k, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v7ve == Triple::ARMSubArch_v7ve, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6 == Triple::ARMSubArch_v6, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6m == Triple::ARMSubArch_v6m, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6k == Triple::ARMSubArch_v6k, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v6t2 == Triple::ARMSubArch_v6t2, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v5 == Triple::ARMSubArch_v5, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v5te == Triple::ARMSubArch_v5te, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_ARMSubArch_v4t == Triple::ARMSubArch_v4t, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v3 == Triple::KalimbaSubArch_v3, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v4 == Triple::KalimbaSubArch_v4, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v5 == Triple::KalimbaSubArch_v5, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_KalimbaSubArch_v5 == Triple::KalimbaSubArch_v5, "");
|
||||||
|
static_assert((Triple::SubArchType)ZigLLVM_MipsSubArch_r6 == Triple::MipsSubArch_r6, "");
|
||||||
|
|
||||||
|
static_assert((Triple::VendorType)ZigLLVM_UnknownVendor == Triple::UnknownVendor, "");
|
||||||
|
static_assert((Triple::VendorType)ZigLLVM_Apple == Triple::Apple, "");
|
||||||
|
static_assert((Triple::VendorType)ZigLLVM_PC == Triple::PC, "");
|
||||||
|
static_assert((Triple::VendorType)ZigLLVM_SCEI == Triple::SCEI, "");
|
||||||
|
static_assert((Triple::VendorType)ZigLLVM_BGP == Triple::BGP, "");
|
||||||
|
static_assert((Triple::VendorType)ZigLLVM_BGQ == Triple::BGQ, "");
|
||||||
|
static_assert((Triple::VendorType)ZigLLVM_Freescale == Triple::Freescale, "");
|
||||||
|
static_assert((Triple::VendorType)ZigLLVM_IBM == Triple::IBM, "");
|
||||||
|
static_assert((Triple::VendorType)ZigLLVM_ImaginationTechnologies == Triple::ImaginationTechnologies, "");
|
||||||
|
static_assert((Triple::VendorType)ZigLLVM_MipsTechnologies == Triple::MipsTechnologies, "");
|
||||||
|
static_assert((Triple::VendorType)ZigLLVM_NVIDIA == Triple::NVIDIA, "");
|
||||||
|
static_assert((Triple::VendorType)ZigLLVM_CSR == Triple::CSR, "");
|
||||||
|
static_assert((Triple::VendorType)ZigLLVM_Myriad == Triple::Myriad, "");
|
||||||
|
static_assert((Triple::VendorType)ZigLLVM_AMD == Triple::AMD, "");
|
||||||
|
static_assert((Triple::VendorType)ZigLLVM_Mesa == Triple::Mesa, "");
|
||||||
|
static_assert((Triple::VendorType)ZigLLVM_SUSE == Triple::SUSE, "");
|
||||||
|
static_assert((Triple::VendorType)ZigLLVM_OpenEmbedded == Triple::OpenEmbedded, "");
|
||||||
|
static_assert((Triple::VendorType)ZigLLVM_LastVendorType == Triple::LastVendorType, "");
|
||||||
|
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_UnknownOS == Triple::UnknownOS, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_Ananas == Triple::Ananas, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_CloudABI == Triple::CloudABI, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_Darwin == Triple::Darwin, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_DragonFly == Triple::DragonFly, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_FreeBSD == Triple::FreeBSD, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_Fuchsia == Triple::Fuchsia, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_IOS == Triple::IOS, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_KFreeBSD == Triple::KFreeBSD, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_Linux == Triple::Linux, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_Lv2 == Triple::Lv2, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_MacOSX == Triple::MacOSX, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_NetBSD == Triple::NetBSD, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_OpenBSD == Triple::OpenBSD, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_Solaris == Triple::Solaris, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_Win32 == Triple::Win32, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_Haiku == Triple::Haiku, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_Minix == Triple::Minix, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_RTEMS == Triple::RTEMS, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_NaCl == Triple::NaCl, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_CNK == Triple::CNK, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_AIX == Triple::AIX, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_CUDA == Triple::CUDA, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_NVCL == Triple::NVCL, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_AMDHSA == Triple::AMDHSA, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_PS4 == Triple::PS4, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_ELFIAMCU == Triple::ELFIAMCU, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_TvOS == Triple::TvOS, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_WatchOS == Triple::WatchOS, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_Mesa3D == Triple::Mesa3D, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_Contiki == Triple::Contiki, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_AMDPAL == Triple::AMDPAL, "");
|
||||||
|
static_assert((Triple::OSType)ZigLLVM_LastOSType == Triple::LastOSType, "");
|
||||||
|
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_UnknownEnvironment == Triple::UnknownEnvironment, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_GNU == Triple::GNU, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_GNUABIN32 == Triple::GNUABIN32, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_GNUABI64 == Triple::GNUABI64, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_GNUEABI == Triple::GNUEABI, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_GNUEABIHF == Triple::GNUEABIHF, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_GNUX32 == Triple::GNUX32, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_CODE16 == Triple::CODE16, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_EABI == Triple::EABI, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_EABIHF == Triple::EABIHF, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_Android == Triple::Android, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_Musl == Triple::Musl, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_MuslEABI == Triple::MuslEABI, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_MuslEABIHF == Triple::MuslEABIHF, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_MSVC == Triple::MSVC, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_Itanium == Triple::Itanium, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_Cygnus == Triple::Cygnus, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_CoreCLR == Triple::CoreCLR, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_Simulator == Triple::Simulator, "");
|
||||||
|
static_assert((Triple::EnvironmentType)ZigLLVM_LastEnvironmentType == Triple::LastEnvironmentType, "");
|
||||||
|
|
||||||
|
static_assert((Triple::ObjectFormatType)ZigLLVM_UnknownObjectFormat == Triple::UnknownObjectFormat, "");
|
||||||
|
static_assert((Triple::ObjectFormatType)ZigLLVM_COFF == Triple::COFF, "");
|
||||||
|
static_assert((Triple::ObjectFormatType)ZigLLVM_ELF == Triple::ELF, "");
|
||||||
|
static_assert((Triple::ObjectFormatType)ZigLLVM_MachO == Triple::MachO, "");
|
||||||
|
static_assert((Triple::ObjectFormatType)ZigLLVM_Wasm == Triple::Wasm, "");
|
||||||
|
|
|
@ -398,3 +398,14 @@ test "std.ArrayList.insertSlice" {
|
||||||
assert(list.len == 6);
|
assert(list.len == 6);
|
||||||
assert(list.items[0] == 1);
|
assert(list.items[0] == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Item = struct {
|
||||||
|
integer: i32,
|
||||||
|
sub_items: ArrayList(Item),
|
||||||
|
};
|
||||||
|
|
||||||
|
test "std.ArrayList: ArrayList(T) of struct T" {
|
||||||
|
var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(debug.global_allocator) };
|
||||||
|
try root.sub_items.append( Item{ .integer = 42, .sub_items = ArrayList(Item).init(debug.global_allocator) } );
|
||||||
|
assert(root.sub_items.items[0].integer == 42);
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,10 @@ pub fn Int(comptime T: type) type {
|
||||||
return @atomicLoad(T, &self.unprotected_value, AtomicOrder.SeqCst);
|
return @atomicLoad(T, &self.unprotected_value, AtomicOrder.SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set(self: *Self, new_value: T) void {
|
||||||
|
_ = self.xchg(new_value);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn xchg(self: *Self, new_value: T) T {
|
pub fn xchg(self: *Self, new_value: T) T {
|
||||||
return @atomicRmw(T, &self.unprotected_value, builtin.AtomicRmwOp.Xchg, new_value, AtomicOrder.SeqCst);
|
return @atomicRmw(T, &self.unprotected_value, builtin.AtomicRmwOp.Xchg, new_value, AtomicOrder.SeqCst);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub const BufMap = struct {
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *const BufMap) void {
|
pub fn deinit(self: *BufMap) void {
|
||||||
var it = self.hash_map.iterator();
|
var it = self.hash_map.iterator();
|
||||||
while (true) {
|
while (true) {
|
||||||
const entry = it.next() orelse break;
|
const entry = it.next() orelse break;
|
||||||
|
@ -27,16 +27,34 @@ pub const BufMap = struct {
|
||||||
self.hash_map.deinit();
|
self.hash_map.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(self: *BufMap, key: []const u8, value: []const u8) !void {
|
/// Same as `set` but the key and value become owned by the BufMap rather
|
||||||
self.delete(key);
|
/// than being copied.
|
||||||
const key_copy = try self.copy(key);
|
/// If `setMove` fails, the ownership of key and value does not transfer.
|
||||||
errdefer self.free(key_copy);
|
pub fn setMove(self: *BufMap, key: []u8, value: []u8) !void {
|
||||||
const value_copy = try self.copy(value);
|
const get_or_put = try self.hash_map.getOrPut(key);
|
||||||
errdefer self.free(value_copy);
|
if (get_or_put.found_existing) {
|
||||||
_ = try self.hash_map.put(key_copy, value_copy);
|
self.free(get_or_put.kv.key);
|
||||||
|
get_or_put.kv.key = key;
|
||||||
|
}
|
||||||
|
get_or_put.kv.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(self: *const BufMap, key: []const u8) ?[]const u8 {
|
/// `key` and `value` are copied into the BufMap.
|
||||||
|
pub fn set(self: *BufMap, key: []const u8, value: []const u8) !void {
|
||||||
|
const value_copy = try self.copy(value);
|
||||||
|
errdefer self.free(value_copy);
|
||||||
|
// Avoid copying key if it already exists
|
||||||
|
const get_or_put = try self.hash_map.getOrPut(key);
|
||||||
|
if (!get_or_put.found_existing) {
|
||||||
|
get_or_put.kv.key = self.copy(key) catch |err| {
|
||||||
|
_ = self.hash_map.remove(key);
|
||||||
|
return err;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
get_or_put.kv.value = value_copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(self: BufMap, key: []const u8) ?[]const u8 {
|
||||||
const entry = self.hash_map.get(key) orelse return null;
|
const entry = self.hash_map.get(key) orelse return null;
|
||||||
return entry.value;
|
return entry.value;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +65,7 @@ pub const BufMap = struct {
|
||||||
self.free(entry.value);
|
self.free(entry.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn count(self: *const BufMap) usize {
|
pub fn count(self: BufMap) usize {
|
||||||
return self.hash_map.count();
|
return self.hash_map.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,11 +73,11 @@ pub const BufMap = struct {
|
||||||
return self.hash_map.iterator();
|
return self.hash_map.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn free(self: *const BufMap, value: []const u8) void {
|
fn free(self: BufMap, value: []const u8) void {
|
||||||
self.hash_map.allocator.free(value);
|
self.hash_map.allocator.free(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn copy(self: *const BufMap, value: []const u8) ![]const u8 {
|
fn copy(self: BufMap, value: []const u8) ![]u8 {
|
||||||
return mem.dupe(self.hash_map.allocator, u8, value);
|
return mem.dupe(self.hash_map.allocator, u8, value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -150,7 +150,11 @@ pub const Builder = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
|
pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
|
||||||
return LibExeObjStep.createExecutable(self, name, root_src);
|
return LibExeObjStep.createExecutable(self, name, root_src, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn addStaticExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
|
||||||
|
return LibExeObjStep.createExecutable(self, name, root_src, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addObject(self: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep {
|
pub fn addObject(self: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep {
|
||||||
|
@ -795,11 +799,23 @@ pub const Target = union(enum) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn isFreeBSD(self: *const Target) bool {
|
||||||
|
return switch (self.getOs()) {
|
||||||
|
builtin.Os.freebsd => true,
|
||||||
|
else => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn wantSharedLibSymLinks(self: *const Target) bool {
|
pub fn wantSharedLibSymLinks(self: *const Target) bool {
|
||||||
return !self.isWindows();
|
return !self.isWindows();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Pkg = struct {
|
||||||
|
name: []const u8,
|
||||||
|
path: []const u8,
|
||||||
|
};
|
||||||
|
|
||||||
pub const LibExeObjStep = struct {
|
pub const LibExeObjStep = struct {
|
||||||
step: Step,
|
step: Step,
|
||||||
builder: *Builder,
|
builder: *Builder,
|
||||||
|
@ -842,11 +858,6 @@ pub const LibExeObjStep = struct {
|
||||||
source_files: ArrayList([]const u8),
|
source_files: ArrayList([]const u8),
|
||||||
object_src: []const u8,
|
object_src: []const u8,
|
||||||
|
|
||||||
const Pkg = struct {
|
|
||||||
name: []const u8,
|
|
||||||
path: []const u8,
|
|
||||||
};
|
|
||||||
|
|
||||||
const Kind = enum {
|
const Kind = enum {
|
||||||
Exe,
|
Exe,
|
||||||
Lib,
|
Lib,
|
||||||
|
@ -884,8 +895,8 @@ pub const LibExeObjStep = struct {
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
|
pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8, static: bool) *LibExeObjStep {
|
||||||
const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0))) catch unreachable;
|
const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Exe, static, builder.version(0, 0, 0))) catch unreachable;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1263,6 +1274,9 @@ pub const LibExeObjStep = struct {
|
||||||
zig_args.append("--ver-patch") catch unreachable;
|
zig_args.append("--ver-patch") catch unreachable;
|
||||||
zig_args.append(builder.fmt("{}", self.version.patch)) catch unreachable;
|
zig_args.append(builder.fmt("{}", self.version.patch)) catch unreachable;
|
||||||
}
|
}
|
||||||
|
if (self.kind == Kind.Exe and self.static) {
|
||||||
|
zig_args.append("--static") catch unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
switch (self.target) {
|
switch (self.target) {
|
||||||
Target.Native => {},
|
Target.Native => {},
|
||||||
|
@ -1653,6 +1667,7 @@ pub const TestStep = struct {
|
||||||
exec_cmd_args: ?[]const ?[]const u8,
|
exec_cmd_args: ?[]const ?[]const u8,
|
||||||
include_dirs: ArrayList([]const u8),
|
include_dirs: ArrayList([]const u8),
|
||||||
lib_paths: ArrayList([]const u8),
|
lib_paths: ArrayList([]const u8),
|
||||||
|
packages: ArrayList(Pkg),
|
||||||
object_files: ArrayList([]const u8),
|
object_files: ArrayList([]const u8),
|
||||||
no_rosegment: bool,
|
no_rosegment: bool,
|
||||||
output_path: ?[]const u8,
|
output_path: ?[]const u8,
|
||||||
|
@ -1673,6 +1688,7 @@ pub const TestStep = struct {
|
||||||
.exec_cmd_args = null,
|
.exec_cmd_args = null,
|
||||||
.include_dirs = ArrayList([]const u8).init(builder.allocator),
|
.include_dirs = ArrayList([]const u8).init(builder.allocator),
|
||||||
.lib_paths = ArrayList([]const u8).init(builder.allocator),
|
.lib_paths = ArrayList([]const u8).init(builder.allocator),
|
||||||
|
.packages = ArrayList(Pkg).init(builder.allocator),
|
||||||
.object_files = ArrayList([]const u8).init(builder.allocator),
|
.object_files = ArrayList([]const u8).init(builder.allocator),
|
||||||
.no_rosegment = false,
|
.no_rosegment = false,
|
||||||
.output_path = null,
|
.output_path = null,
|
||||||
|
@ -1688,6 +1704,13 @@ pub const TestStep = struct {
|
||||||
self.lib_paths.append(path) catch unreachable;
|
self.lib_paths.append(path) catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn addPackagePath(self: *TestStep, name: []const u8, pkg_index_path: []const u8) void {
|
||||||
|
self.packages.append(Pkg{
|
||||||
|
.name = name,
|
||||||
|
.path = pkg_index_path,
|
||||||
|
}) catch unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn setVerbose(self: *TestStep, value: bool) void {
|
pub fn setVerbose(self: *TestStep, value: bool) void {
|
||||||
self.verbose = value;
|
self.verbose = value;
|
||||||
}
|
}
|
||||||
|
@ -1864,6 +1887,13 @@ pub const TestStep = struct {
|
||||||
try zig_args.append(lib_path);
|
try zig_args.append(lib_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (self.packages.toSliceConst()) |pkg| {
|
||||||
|
zig_args.append("--pkg-begin") catch unreachable;
|
||||||
|
zig_args.append(pkg.name) catch unreachable;
|
||||||
|
zig_args.append(builder.pathFromRoot(pkg.path)) catch unreachable;
|
||||||
|
zig_args.append("--pkg-end") catch unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
if (self.no_rosegment) {
|
if (self.no_rosegment) {
|
||||||
try zig_args.append("--no-rosegment");
|
try zig_args.append("--no-rosegment");
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
const timespec = @import("../os/freebsd/index.zig").timespec;
|
||||||
|
|
||||||
|
extern "c" fn __error() *c_int;
|
||||||
|
pub const _errno = __error;
|
||||||
|
|
||||||
|
pub extern "c" fn kqueue() c_int;
|
||||||
|
pub extern "c" fn kevent(
|
||||||
|
kq: c_int,
|
||||||
|
changelist: [*]const Kevent,
|
||||||
|
nchanges: c_int,
|
||||||
|
eventlist: [*]Kevent,
|
||||||
|
nevents: c_int,
|
||||||
|
timeout: ?*const timespec,
|
||||||
|
) c_int;
|
||||||
|
pub extern "c" fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
|
||||||
|
pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
|
||||||
|
pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) c_int;
|
||||||
|
|
||||||
|
/// Renamed from `kevent` to `Kevent` to avoid conflict with function name.
|
||||||
|
pub const Kevent = extern struct {
|
||||||
|
ident: usize,
|
||||||
|
filter: i16,
|
||||||
|
flags: u16,
|
||||||
|
fflags: u32,
|
||||||
|
data: i64,
|
||||||
|
udata: usize,
|
||||||
|
// TODO ext
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const pthread_attr_t = extern struct {
|
||||||
|
__size: [56]u8,
|
||||||
|
__align: c_long,
|
||||||
|
};
|
|
@ -5,6 +5,7 @@ pub use switch (builtin.os) {
|
||||||
Os.linux => @import("linux.zig"),
|
Os.linux => @import("linux.zig"),
|
||||||
Os.windows => @import("windows.zig"),
|
Os.windows => @import("windows.zig"),
|
||||||
Os.macosx, Os.ios => @import("darwin.zig"),
|
Os.macosx, Os.ios => @import("darwin.zig"),
|
||||||
|
Os.freebsd => @import("freebsd.zig"),
|
||||||
else => empty_import,
|
else => empty_import,
|
||||||
};
|
};
|
||||||
const empty_import = @import("../empty.zig");
|
const empty_import = @import("../empty.zig");
|
||||||
|
|
44
std/coff.zig
44
std/coff.zig
|
@ -51,7 +51,7 @@ pub const Coff = struct {
|
||||||
|
|
||||||
// Seek to PE File Header (coff header)
|
// Seek to PE File Header (coff header)
|
||||||
try self.in_file.seekTo(pe_pointer_offset);
|
try self.in_file.seekTo(pe_pointer_offset);
|
||||||
const pe_magic_offset = try in.readIntLe(u32);
|
const pe_magic_offset = try in.readIntLittle(u32);
|
||||||
try self.in_file.seekTo(pe_magic_offset);
|
try self.in_file.seekTo(pe_magic_offset);
|
||||||
|
|
||||||
var pe_header_magic: [4]u8 = undefined;
|
var pe_header_magic: [4]u8 = undefined;
|
||||||
|
@ -60,13 +60,13 @@ pub const Coff = struct {
|
||||||
return error.InvalidPEHeader;
|
return error.InvalidPEHeader;
|
||||||
|
|
||||||
self.coff_header = CoffHeader{
|
self.coff_header = CoffHeader{
|
||||||
.machine = try in.readIntLe(u16),
|
.machine = try in.readIntLittle(u16),
|
||||||
.number_of_sections = try in.readIntLe(u16),
|
.number_of_sections = try in.readIntLittle(u16),
|
||||||
.timedate_stamp = try in.readIntLe(u32),
|
.timedate_stamp = try in.readIntLittle(u32),
|
||||||
.pointer_to_symbol_table = try in.readIntLe(u32),
|
.pointer_to_symbol_table = try in.readIntLittle(u32),
|
||||||
.number_of_symbols = try in.readIntLe(u32),
|
.number_of_symbols = try in.readIntLittle(u32),
|
||||||
.size_of_optional_header = try in.readIntLe(u16),
|
.size_of_optional_header = try in.readIntLittle(u16),
|
||||||
.characteristics = try in.readIntLe(u16),
|
.characteristics = try in.readIntLittle(u16),
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (self.coff_header.machine) {
|
switch (self.coff_header.machine) {
|
||||||
|
@ -79,7 +79,7 @@ pub const Coff = struct {
|
||||||
|
|
||||||
fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void {
|
fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void {
|
||||||
const in = &file_stream.stream;
|
const in = &file_stream.stream;
|
||||||
self.pe_header.magic = try in.readIntLe(u16);
|
self.pe_header.magic = try in.readIntLittle(u16);
|
||||||
// For now we're only interested in finding the reference to the .pdb,
|
// For now we're only interested in finding the reference to the .pdb,
|
||||||
// so we'll skip most of this header, which size is different in 32
|
// so we'll skip most of this header, which size is different in 32
|
||||||
// 64 bits by the way.
|
// 64 bits by the way.
|
||||||
|
@ -93,14 +93,14 @@ pub const Coff = struct {
|
||||||
|
|
||||||
try self.in_file.seekForward(skip_size);
|
try self.in_file.seekForward(skip_size);
|
||||||
|
|
||||||
const number_of_rva_and_sizes = try in.readIntLe(u32);
|
const number_of_rva_and_sizes = try in.readIntLittle(u32);
|
||||||
if (number_of_rva_and_sizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
|
if (number_of_rva_and_sizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
|
||||||
return error.InvalidPEHeader;
|
return error.InvalidPEHeader;
|
||||||
|
|
||||||
for (self.pe_header.data_directory) |*data_dir| {
|
for (self.pe_header.data_directory) |*data_dir| {
|
||||||
data_dir.* = OptionalHeader.DataDirectory{
|
data_dir.* = OptionalHeader.DataDirectory{
|
||||||
.virtual_address = try in.readIntLe(u32),
|
.virtual_address = try in.readIntLittle(u32),
|
||||||
.size = try in.readIntLe(u32),
|
.size = try in.readIntLittle(u32),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ pub const Coff = struct {
|
||||||
if (!mem.eql(u8, cv_signature, "RSDS"))
|
if (!mem.eql(u8, cv_signature, "RSDS"))
|
||||||
return error.InvalidPEMagic;
|
return error.InvalidPEMagic;
|
||||||
try in.readNoEof(self.guid[0..]);
|
try in.readNoEof(self.guid[0..]);
|
||||||
self.age = try in.readIntLe(u32);
|
self.age = try in.readIntLittle(u32);
|
||||||
|
|
||||||
// Finally read the null-terminated string.
|
// Finally read the null-terminated string.
|
||||||
var byte = try in.readByte();
|
var byte = try in.readByte();
|
||||||
|
@ -157,15 +157,15 @@ pub const Coff = struct {
|
||||||
try self.sections.append(Section{
|
try self.sections.append(Section{
|
||||||
.header = SectionHeader{
|
.header = SectionHeader{
|
||||||
.name = name,
|
.name = name,
|
||||||
.misc = SectionHeader.Misc{ .physical_address = try in.readIntLe(u32) },
|
.misc = SectionHeader.Misc{ .physical_address = try in.readIntLittle(u32) },
|
||||||
.virtual_address = try in.readIntLe(u32),
|
.virtual_address = try in.readIntLittle(u32),
|
||||||
.size_of_raw_data = try in.readIntLe(u32),
|
.size_of_raw_data = try in.readIntLittle(u32),
|
||||||
.pointer_to_raw_data = try in.readIntLe(u32),
|
.pointer_to_raw_data = try in.readIntLittle(u32),
|
||||||
.pointer_to_relocations = try in.readIntLe(u32),
|
.pointer_to_relocations = try in.readIntLittle(u32),
|
||||||
.pointer_to_line_numbers = try in.readIntLe(u32),
|
.pointer_to_line_numbers = try in.readIntLittle(u32),
|
||||||
.number_of_relocations = try in.readIntLe(u16),
|
.number_of_relocations = try in.readIntLittle(u16),
|
||||||
.number_of_line_numbers = try in.readIntLe(u16),
|
.number_of_line_numbers = try in.readIntLittle(u16),
|
||||||
.characteristics = try in.readIntLe(u32),
|
.characteristics = try in.readIntLittle(u32),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,8 @@ fn Blake2s(comptime out_len: usize) type {
|
||||||
const rr = d.h[0 .. out_len / 32];
|
const rr = d.h[0 .. out_len / 32];
|
||||||
|
|
||||||
for (rr) |s, j| {
|
for (rr) |s, j| {
|
||||||
mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Little);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +135,8 @@ fn Blake2s(comptime out_len: usize) type {
|
||||||
var v: [16]u32 = undefined;
|
var v: [16]u32 = undefined;
|
||||||
|
|
||||||
for (m) |*r, i| {
|
for (m) |*r, i| {
|
||||||
r.* = mem.readIntLE(u32, b[4 * i .. 4 * i + 4]);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
r.* = mem.readIntSliceLittle(u32, b[4 * i .. 4 * i + 4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var k: usize = 0;
|
var k: usize = 0;
|
||||||
|
@ -356,7 +358,8 @@ fn Blake2b(comptime out_len: usize) type {
|
||||||
const rr = d.h[0 .. out_len / 64];
|
const rr = d.h[0 .. out_len / 64];
|
||||||
|
|
||||||
for (rr) |s, j| {
|
for (rr) |s, j| {
|
||||||
mem.writeInt(out[8 * j .. 8 * j + 8], s, builtin.Endian.Little);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
mem.writeIntSliceLittle(u64, out[8 * j .. 8 * j + 8], s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,7 +370,7 @@ fn Blake2b(comptime out_len: usize) type {
|
||||||
var v: [16]u64 = undefined;
|
var v: [16]u64 = undefined;
|
||||||
|
|
||||||
for (m) |*r, i| {
|
for (m) |*r, i| {
|
||||||
r.* = mem.readIntLE(u64, b[8 * i .. 8 * i + 8]);
|
r.* = mem.readIntSliceLittle(u64, b[8 * i .. 8 * i + 8]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var k: usize = 0;
|
var k: usize = 0;
|
||||||
|
|
|
@ -59,7 +59,8 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (x) |_, i| {
|
for (x) |_, i| {
|
||||||
mem.writeInt(out[4 * i .. 4 * i + 4], x[i] +% input[i], builtin.Endian.Little);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
mem.writeIntSliceLittle(u32, out[4 * i .. 4 * i + 4], x[i] +% input[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,10 +71,10 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo
|
||||||
|
|
||||||
const c = "expand 32-byte k";
|
const c = "expand 32-byte k";
|
||||||
const constant_le = []u32{
|
const constant_le = []u32{
|
||||||
mem.readIntLE(u32, c[0..4]),
|
mem.readIntSliceLittle(u32, c[0..4]),
|
||||||
mem.readIntLE(u32, c[4..8]),
|
mem.readIntSliceLittle(u32, c[4..8]),
|
||||||
mem.readIntLE(u32, c[8..12]),
|
mem.readIntSliceLittle(u32, c[8..12]),
|
||||||
mem.readIntLE(u32, c[12..16]),
|
mem.readIntSliceLittle(u32, c[12..16]),
|
||||||
};
|
};
|
||||||
|
|
||||||
mem.copy(u32, ctx[0..], constant_le[0..4]);
|
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:
|
||||||
var k: [8]u32 = undefined;
|
var k: [8]u32 = undefined;
|
||||||
var c: [4]u32 = undefined;
|
var c: [4]u32 = undefined;
|
||||||
|
|
||||||
k[0] = mem.readIntLE(u32, key[0..4]);
|
k[0] = mem.readIntSliceLittle(u32, key[0..4]);
|
||||||
k[1] = mem.readIntLE(u32, key[4..8]);
|
k[1] = mem.readIntSliceLittle(u32, key[4..8]);
|
||||||
k[2] = mem.readIntLE(u32, key[8..12]);
|
k[2] = mem.readIntSliceLittle(u32, key[8..12]);
|
||||||
k[3] = mem.readIntLE(u32, key[12..16]);
|
k[3] = mem.readIntSliceLittle(u32, key[12..16]);
|
||||||
k[4] = mem.readIntLE(u32, key[16..20]);
|
k[4] = mem.readIntSliceLittle(u32, key[16..20]);
|
||||||
k[5] = mem.readIntLE(u32, key[20..24]);
|
k[5] = mem.readIntSliceLittle(u32, key[20..24]);
|
||||||
k[6] = mem.readIntLE(u32, key[24..28]);
|
k[6] = mem.readIntSliceLittle(u32, key[24..28]);
|
||||||
k[7] = mem.readIntLE(u32, key[28..32]);
|
k[7] = mem.readIntSliceLittle(u32, key[28..32]);
|
||||||
|
|
||||||
c[0] = counter;
|
c[0] = counter;
|
||||||
c[1] = mem.readIntLE(u32, nonce[0..4]);
|
c[1] = mem.readIntSliceLittle(u32, nonce[0..4]);
|
||||||
c[2] = mem.readIntLE(u32, nonce[4..8]);
|
c[2] = mem.readIntSliceLittle(u32, nonce[4..8]);
|
||||||
c[3] = mem.readIntLE(u32, nonce[8..12]);
|
c[3] = mem.readIntSliceLittle(u32, nonce[8..12]);
|
||||||
chaCha20_internal(out, in, k, c);
|
chaCha20_internal(out, in, k, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,19 +145,19 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]
|
||||||
var k: [8]u32 = undefined;
|
var k: [8]u32 = undefined;
|
||||||
var c: [4]u32 = undefined;
|
var c: [4]u32 = undefined;
|
||||||
|
|
||||||
k[0] = mem.readIntLE(u32, key[0..4]);
|
k[0] = mem.readIntSliceLittle(u32, key[0..4]);
|
||||||
k[1] = mem.readIntLE(u32, key[4..8]);
|
k[1] = mem.readIntSliceLittle(u32, key[4..8]);
|
||||||
k[2] = mem.readIntLE(u32, key[8..12]);
|
k[2] = mem.readIntSliceLittle(u32, key[8..12]);
|
||||||
k[3] = mem.readIntLE(u32, key[12..16]);
|
k[3] = mem.readIntSliceLittle(u32, key[12..16]);
|
||||||
k[4] = mem.readIntLE(u32, key[16..20]);
|
k[4] = mem.readIntSliceLittle(u32, key[16..20]);
|
||||||
k[5] = mem.readIntLE(u32, key[20..24]);
|
k[5] = mem.readIntSliceLittle(u32, key[20..24]);
|
||||||
k[6] = mem.readIntLE(u32, key[24..28]);
|
k[6] = mem.readIntSliceLittle(u32, key[24..28]);
|
||||||
k[7] = mem.readIntLE(u32, key[28..32]);
|
k[7] = mem.readIntSliceLittle(u32, key[28..32]);
|
||||||
|
|
||||||
c[0] = @truncate(u32, counter);
|
c[0] = @truncate(u32, counter);
|
||||||
c[1] = @truncate(u32, counter >> 32);
|
c[1] = @truncate(u32, counter >> 32);
|
||||||
c[2] = mem.readIntLE(u32, nonce[0..4]);
|
c[2] = mem.readIntSliceLittle(u32, nonce[0..4]);
|
||||||
c[3] = mem.readIntLE(u32, nonce[4..8]);
|
c[3] = mem.readIntSliceLittle(u32, nonce[4..8]);
|
||||||
|
|
||||||
const block_size = (1 << 6);
|
const block_size = (1 << 6);
|
||||||
const big_block = (block_size << 32);
|
const big_block = (block_size << 32);
|
||||||
|
|
|
@ -112,7 +112,8 @@ pub const Md5 = struct {
|
||||||
d.round(d.buf[0..]);
|
d.round(d.buf[0..]);
|
||||||
|
|
||||||
for (d.s) |s, j| {
|
for (d.s) |s, j| {
|
||||||
mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Little);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@ const std = @import("../index.zig");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
const Endian = builtin.Endian;
|
const Endian = builtin.Endian;
|
||||||
const readInt = std.mem.readInt;
|
const readIntSliceLittle = std.mem.readIntSliceLittle;
|
||||||
const writeInt = std.mem.writeInt;
|
const writeIntSliceLittle = std.mem.writeIntSliceLittle;
|
||||||
|
|
||||||
pub const Poly1305 = struct {
|
pub const Poly1305 = struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
@ -59,19 +59,19 @@ pub const Poly1305 = struct {
|
||||||
{
|
{
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < 1) : (i += 1) {
|
while (i < 1) : (i += 1) {
|
||||||
ctx.r[0] = readInt(key[0..4], u32, Endian.Little) & 0x0fffffff;
|
ctx.r[0] = readIntSliceLittle(u32, key[0..4]) & 0x0fffffff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var i: usize = 1;
|
var i: usize = 1;
|
||||||
while (i < 4) : (i += 1) {
|
while (i < 4) : (i += 1) {
|
||||||
ctx.r[i] = readInt(key[i * 4 .. i * 4 + 4], u32, Endian.Little) & 0x0ffffffc;
|
ctx.r[i] = readIntSliceLittle(u32, key[i * 4 .. i * 4 + 4]) & 0x0ffffffc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < 4) : (i += 1) {
|
while (i < 4) : (i += 1) {
|
||||||
ctx.pad[i] = readInt(key[i * 4 + 16 .. i * 4 + 16 + 4], u32, Endian.Little);
|
ctx.pad[i] = readIntSliceLittle(u32, key[i * 4 + 16 .. i * 4 + 16 + 4]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,10 +168,10 @@ pub const Poly1305 = struct {
|
||||||
const nb_blocks = nmsg.len >> 4;
|
const nb_blocks = nmsg.len >> 4;
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < nb_blocks) : (i += 1) {
|
while (i < nb_blocks) : (i += 1) {
|
||||||
ctx.c[0] = readInt(nmsg[0..4], u32, Endian.Little);
|
ctx.c[0] = readIntSliceLittle(u32, nmsg[0..4]);
|
||||||
ctx.c[1] = readInt(nmsg[4..8], u32, Endian.Little);
|
ctx.c[1] = readIntSliceLittle(u32, nmsg[4..8]);
|
||||||
ctx.c[2] = readInt(nmsg[8..12], u32, Endian.Little);
|
ctx.c[2] = readIntSliceLittle(u32, nmsg[8..12]);
|
||||||
ctx.c[3] = readInt(nmsg[12..16], u32, Endian.Little);
|
ctx.c[3] = readIntSliceLittle(u32, nmsg[12..16]);
|
||||||
polyBlock(ctx);
|
polyBlock(ctx);
|
||||||
nmsg = nmsg[16..];
|
nmsg = nmsg[16..];
|
||||||
}
|
}
|
||||||
|
@ -210,10 +210,11 @@ pub const Poly1305 = struct {
|
||||||
const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000
|
const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000
|
||||||
const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000
|
const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000
|
||||||
|
|
||||||
writeInt(out[0..], @truncate(u32, uu0), Endian.Little);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
writeInt(out[4..], @truncate(u32, uu1), Endian.Little);
|
writeIntSliceLittle(u32, out[0..], @truncate(u32, uu0));
|
||||||
writeInt(out[8..], @truncate(u32, uu2), Endian.Little);
|
writeIntSliceLittle(u32, out[4..], @truncate(u32, uu1));
|
||||||
writeInt(out[12..], @truncate(u32, uu3), Endian.Little);
|
writeIntSliceLittle(u32, out[8..], @truncate(u32, uu2));
|
||||||
|
writeIntSliceLittle(u32, out[12..], @truncate(u32, uu3));
|
||||||
|
|
||||||
ctx.secureZero();
|
ctx.secureZero();
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,8 @@ pub const Sha1 = struct {
|
||||||
d.round(d.buf[0..]);
|
d.round(d.buf[0..]);
|
||||||
|
|
||||||
for (d.s) |s, j| {
|
for (d.s) |s, j| {
|
||||||
mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Big);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -167,7 +167,8 @@ fn Sha2_32(comptime params: Sha2Params32) type {
|
||||||
const rr = d.s[0 .. params.out_len / 32];
|
const rr = d.s[0 .. params.out_len / 32];
|
||||||
|
|
||||||
for (rr) |s, j| {
|
for (rr) |s, j| {
|
||||||
mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Big);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,7 +509,8 @@ fn Sha2_64(comptime params: Sha2Params64) type {
|
||||||
const rr = d.s[0 .. params.out_len / 64];
|
const rr = d.s[0 .. params.out_len / 64];
|
||||||
|
|
||||||
for (rr) |s, j| {
|
for (rr) |s, j| {
|
||||||
mem.writeInt(out[8 * j .. 8 * j + 8], s, builtin.Endian.Big);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
mem.writeIntSliceBig(u64, out[8 * j .. 8 * j + 8], s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ fn keccak_f(comptime F: usize, d: []u8) void {
|
||||||
var c = []const u64{0} ** 5;
|
var c = []const u64{0} ** 5;
|
||||||
|
|
||||||
for (s) |*r, i| {
|
for (s) |*r, i| {
|
||||||
r.* = mem.readIntLE(u64, d[8 * i .. 8 * i + 8]);
|
r.* = mem.readIntSliceLittle(u64, d[8 * i .. 8 * i + 8]);
|
||||||
}
|
}
|
||||||
|
|
||||||
comptime var x: usize = 0;
|
comptime var x: usize = 0;
|
||||||
|
@ -167,7 +167,8 @@ fn keccak_f(comptime F: usize, d: []u8) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (s) |r, i| {
|
for (s) |r, i| {
|
||||||
mem.writeInt(d[8 * i .. 8 * i + 8], r, builtin.Endian.Little);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
mem.writeIntSliceLittle(u64, d[8 * i .. 8 * i + 8], r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@ const builtin = @import("builtin");
|
||||||
const fmt = std.fmt;
|
const fmt = std.fmt;
|
||||||
|
|
||||||
const Endian = builtin.Endian;
|
const Endian = builtin.Endian;
|
||||||
const readInt = std.mem.readInt;
|
const readIntSliceLittle = std.mem.readIntSliceLittle;
|
||||||
const writeInt = std.mem.writeInt;
|
const writeIntSliceLittle = std.mem.writeIntSliceLittle;
|
||||||
|
|
||||||
// Based on Supercop's ref10 implementation.
|
// Based on Supercop's ref10 implementation.
|
||||||
pub const X25519 = struct {
|
pub const X25519 = struct {
|
||||||
|
@ -255,16 +255,16 @@ const Fe = struct {
|
||||||
|
|
||||||
var t: [10]i64 = undefined;
|
var t: [10]i64 = undefined;
|
||||||
|
|
||||||
t[0] = readInt(s[0..4], u32, Endian.Little);
|
t[0] = readIntSliceLittle(u32, s[0..4]);
|
||||||
t[1] = readInt(s[4..7], u32, Endian.Little) << 6;
|
t[1] = u32(readIntSliceLittle(u24, s[4..7])) << 6;
|
||||||
t[2] = readInt(s[7..10], u32, Endian.Little) << 5;
|
t[2] = u32(readIntSliceLittle(u24, s[7..10])) << 5;
|
||||||
t[3] = readInt(s[10..13], u32, Endian.Little) << 3;
|
t[3] = u32(readIntSliceLittle(u24, s[10..13])) << 3;
|
||||||
t[4] = readInt(s[13..16], u32, Endian.Little) << 2;
|
t[4] = u32(readIntSliceLittle(u24, s[13..16])) << 2;
|
||||||
t[5] = readInt(s[16..20], u32, Endian.Little);
|
t[5] = readIntSliceLittle(u32, s[16..20]);
|
||||||
t[6] = readInt(s[20..23], u32, Endian.Little) << 7;
|
t[6] = u32(readIntSliceLittle(u24, s[20..23])) << 7;
|
||||||
t[7] = readInt(s[23..26], u32, Endian.Little) << 5;
|
t[7] = u32(readIntSliceLittle(u24, s[23..26])) << 5;
|
||||||
t[8] = readInt(s[26..29], u32, Endian.Little) << 4;
|
t[8] = u32(readIntSliceLittle(u24, s[26..29])) << 4;
|
||||||
t[9] = (readInt(s[29..32], u32, Endian.Little) & 0x7fffff) << 2;
|
t[9] = (u32(readIntSliceLittle(u24, s[29..32])) & 0x7fffff) << 2;
|
||||||
|
|
||||||
carry1(h, t[0..]);
|
carry1(h, t[0..]);
|
||||||
}
|
}
|
||||||
|
@ -544,14 +544,15 @@ const Fe = struct {
|
||||||
ut[i] = @bitCast(u32, @intCast(i32, t[i]));
|
ut[i] = @bitCast(u32, @intCast(i32, t[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
writeInt(s[0..], (ut[0] >> 0) | (ut[1] << 26), Endian.Little);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
writeInt(s[4..], (ut[1] >> 6) | (ut[2] << 19), Endian.Little);
|
writeIntSliceLittle(u32, s[0..4], (ut[0] >> 0) | (ut[1] << 26));
|
||||||
writeInt(s[8..], (ut[2] >> 13) | (ut[3] << 13), Endian.Little);
|
writeIntSliceLittle(u32, s[4..8], (ut[1] >> 6) | (ut[2] << 19));
|
||||||
writeInt(s[12..], (ut[3] >> 19) | (ut[4] << 6), Endian.Little);
|
writeIntSliceLittle(u32, s[8..12], (ut[2] >> 13) | (ut[3] << 13));
|
||||||
writeInt(s[16..], (ut[5] >> 0) | (ut[6] << 25), Endian.Little);
|
writeIntSliceLittle(u32, s[12..16], (ut[3] >> 19) | (ut[4] << 6));
|
||||||
writeInt(s[20..], (ut[6] >> 7) | (ut[7] << 19), Endian.Little);
|
writeIntSliceLittle(u32, s[16..20], (ut[5] >> 0) | (ut[6] << 25));
|
||||||
writeInt(s[24..], (ut[7] >> 13) | (ut[8] << 12), Endian.Little);
|
writeIntSliceLittle(u32, s[20..24], (ut[6] >> 7) | (ut[7] << 19));
|
||||||
writeInt(s[28..], (ut[8] >> 20) | (ut[9] << 6), Endian.Little);
|
writeIntSliceLittle(u32, s[24..28], (ut[7] >> 13) | (ut[8] << 12));
|
||||||
|
writeIntSliceLittle(u32, s[28..], (ut[8] >> 20) | (ut[9] << 6));
|
||||||
|
|
||||||
std.mem.secureZero(i64, t[0..]);
|
std.mem.secureZero(i64, t[0..]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,49 +198,44 @@ pub fn writeStackTrace(stack_trace: *const builtin.StackTrace, out_stream: var,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub inline fn getReturnAddress(frame_count: usize) usize {
|
pub const StackIterator = struct {
|
||||||
var fp = @ptrToInt(@frameAddress());
|
first_addr: ?usize,
|
||||||
var i: usize = 0;
|
fp: usize,
|
||||||
while (fp != 0 and i < frame_count) {
|
|
||||||
fp = @intToPtr(*const usize, fp).*;
|
pub fn init(first_addr: ?usize) StackIterator {
|
||||||
i += 1;
|
return StackIterator{
|
||||||
|
.first_addr = first_addr,
|
||||||
|
.fp = @ptrToInt(@frameAddress()),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return @intToPtr(*const usize, fp + @sizeOf(usize)).*;
|
|
||||||
|
fn next(self: *StackIterator) ?usize {
|
||||||
|
if (self.fp == 0) return null;
|
||||||
|
self.fp = @intToPtr(*const usize, self.fp).*;
|
||||||
|
if (self.fp == 0) return null;
|
||||||
|
|
||||||
|
if (self.first_addr) |addr| {
|
||||||
|
while (self.fp != 0) : (self.fp = @intToPtr(*const usize, self.fp).*) {
|
||||||
|
const return_address = @intToPtr(*const usize, self.fp + @sizeOf(usize)).*;
|
||||||
|
if (addr == return_address) {
|
||||||
|
self.first_addr = null;
|
||||||
|
return return_address;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const return_address = @intToPtr(*const usize, self.fp + @sizeOf(usize)).*;
|
||||||
|
return return_address;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void {
|
pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr),
|
builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr),
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
const AddressState = union(enum) {
|
var it = StackIterator.init(start_addr);
|
||||||
NotLookingForStartAddress,
|
while (it.next()) |return_address| {
|
||||||
LookingForStartAddress: usize,
|
|
||||||
};
|
|
||||||
// TODO: I want to express like this:
|
|
||||||
//var addr_state = if (start_addr) |addr| AddressState { .LookingForStartAddress = addr }
|
|
||||||
// else AddressState.NotLookingForStartAddress;
|
|
||||||
var addr_state: AddressState = undefined;
|
|
||||||
if (start_addr) |addr| {
|
|
||||||
addr_state = AddressState{ .LookingForStartAddress = addr };
|
|
||||||
} else {
|
|
||||||
addr_state = AddressState.NotLookingForStartAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
var fp = @ptrToInt(@frameAddress());
|
|
||||||
while (fp != 0) : (fp = @intToPtr(*const usize, fp).*) {
|
|
||||||
const return_address = @intToPtr(*const usize, fp + @sizeOf(usize)).*;
|
|
||||||
|
|
||||||
switch (addr_state) {
|
|
||||||
AddressState.NotLookingForStartAddress => {},
|
|
||||||
AddressState.LookingForStartAddress => |addr| {
|
|
||||||
if (return_address == addr) {
|
|
||||||
addr_state = AddressState.NotLookingForStartAddress;
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
try printSourceAtAddress(debug_info, out_stream, return_address, tty_color);
|
try printSourceAtAddress(debug_info, out_stream, return_address, tty_color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,8 +277,9 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
|
||||||
|
|
||||||
var coff_section: *coff.Section = undefined;
|
var coff_section: *coff.Section = undefined;
|
||||||
const mod_index = for (di.sect_contribs) |sect_contrib| {
|
const mod_index = for (di.sect_contribs) |sect_contrib| {
|
||||||
if (sect_contrib.Section >= di.coff.sections.len) continue;
|
if (sect_contrib.Section > di.coff.sections.len) continue;
|
||||||
coff_section = &di.coff.sections.toSlice()[sect_contrib.Section];
|
// Remember that SectionContribEntry.Section is 1-based.
|
||||||
|
coff_section = &di.coff.sections.toSlice()[sect_contrib.Section - 1];
|
||||||
|
|
||||||
const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset;
|
const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset;
|
||||||
const vaddr_end = vaddr_start + sect_contrib.Size;
|
const vaddr_end = vaddr_start + sect_contrib.Size;
|
||||||
|
@ -413,7 +409,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
|
||||||
|
|
||||||
if (opt_line_info) |line_info| {
|
if (opt_line_info) |line_info| {
|
||||||
try out_stream.print("\n");
|
try out_stream.print("\n");
|
||||||
if (printLineFromFile(out_stream, line_info)) {
|
if (printLineFromFileAnyOs(out_stream, line_info)) {
|
||||||
if (line_info.column == 0) {
|
if (line_info.column == 0) {
|
||||||
try out_stream.write("\n");
|
try out_stream.write("\n");
|
||||||
} else {
|
} else {
|
||||||
|
@ -527,7 +523,7 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void {
|
||||||
|
|
||||||
const modi = di.pdb.getStreamById(mod.mod_info.ModuleSymStream) orelse return error.MissingDebugInfo;
|
const modi = di.pdb.getStreamById(mod.mod_info.ModuleSymStream) orelse return error.MissingDebugInfo;
|
||||||
|
|
||||||
const signature = try modi.stream.readIntLe(u32);
|
const signature = try modi.stream.readIntLittle(u32);
|
||||||
if (signature != 4)
|
if (signature != 4)
|
||||||
return error.InvalidDebugInfo;
|
return error.InvalidDebugInfo;
|
||||||
|
|
||||||
|
@ -597,7 +593,15 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
|
||||||
} else "???";
|
} else "???";
|
||||||
if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| {
|
if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| {
|
||||||
defer line_info.deinit();
|
defer line_info.deinit();
|
||||||
try printLineInfo(di, out_stream, line_info, address, symbol_name, compile_unit_name, tty_color);
|
try printLineInfo(
|
||||||
|
out_stream,
|
||||||
|
line_info,
|
||||||
|
address,
|
||||||
|
symbol_name,
|
||||||
|
compile_unit_name,
|
||||||
|
tty_color,
|
||||||
|
printLineFromFileAnyOs,
|
||||||
|
);
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
error.MissingDebugInfo, error.InvalidDebugInfo => {
|
error.MissingDebugInfo, error.InvalidDebugInfo => {
|
||||||
if (tty_color) {
|
if (tty_color) {
|
||||||
|
@ -610,7 +614,15 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {
|
/// This function works in freestanding mode.
|
||||||
|
/// fn printLineFromFile(out_stream: var, line_info: LineInfo) !void
|
||||||
|
pub fn printSourceAtAddressDwarf(
|
||||||
|
debug_info: *DwarfInfo,
|
||||||
|
out_stream: var,
|
||||||
|
address: usize,
|
||||||
|
tty_color: bool,
|
||||||
|
comptime printLineFromFile: var,
|
||||||
|
) !void {
|
||||||
const compile_unit = findCompileUnit(debug_info, address) catch {
|
const compile_unit = findCompileUnit(debug_info, address) catch {
|
||||||
if (tty_color) {
|
if (tty_color) {
|
||||||
try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? (???)" ++ RESET ++ "\n\n\n", address);
|
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
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name);
|
const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name);
|
||||||
if (getLineNumberInfoLinux(debug_info, compile_unit, address - 1)) |line_info| {
|
if (getLineNumberInfoDwarf(debug_info, compile_unit.*, address - 1)) |line_info| {
|
||||||
defer line_info.deinit();
|
defer line_info.deinit();
|
||||||
const symbol_name = "???";
|
const symbol_name = "???";
|
||||||
try printLineInfo(debug_info, out_stream, line_info, address, symbol_name, compile_unit_name, tty_color);
|
try printLineInfo(
|
||||||
|
out_stream,
|
||||||
|
line_info,
|
||||||
|
address,
|
||||||
|
symbol_name,
|
||||||
|
compile_unit_name,
|
||||||
|
tty_color,
|
||||||
|
printLineFromFile,
|
||||||
|
);
|
||||||
} else |err| switch (err) {
|
} else |err| switch (err) {
|
||||||
error.MissingDebugInfo, error.InvalidDebugInfo => {
|
error.MissingDebugInfo, error.InvalidDebugInfo => {
|
||||||
if (tty_color) {
|
if (tty_color) {
|
||||||
|
@ -636,14 +656,18 @@ pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, addres
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {
|
||||||
|
return printSourceAtAddressDwarf(debug_info, out_stream, address, tty_color, printLineFromFileAnyOs);
|
||||||
|
}
|
||||||
|
|
||||||
fn printLineInfo(
|
fn printLineInfo(
|
||||||
debug_info: *DebugInfo,
|
|
||||||
out_stream: var,
|
out_stream: var,
|
||||||
line_info: LineInfo,
|
line_info: LineInfo,
|
||||||
address: usize,
|
address: usize,
|
||||||
symbol_name: []const u8,
|
symbol_name: []const u8,
|
||||||
compile_unit_name: []const u8,
|
compile_unit_name: []const u8,
|
||||||
tty_color: bool,
|
tty_color: bool,
|
||||||
|
comptime printLineFromFile: var,
|
||||||
) !void {
|
) !void {
|
||||||
if (tty_color) {
|
if (tty_color) {
|
||||||
try out_stream.print(
|
try out_stream.print(
|
||||||
|
@ -733,9 +757,9 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
|
||||||
try di.pdb.openFile(di.coff, path);
|
try di.pdb.openFile(di.coff, path);
|
||||||
|
|
||||||
var pdb_stream = di.pdb.getStream(pdb.StreamType.Pdb) orelse return error.InvalidDebugInfo;
|
var pdb_stream = di.pdb.getStream(pdb.StreamType.Pdb) orelse return error.InvalidDebugInfo;
|
||||||
const version = try pdb_stream.stream.readIntLe(u32);
|
const version = try pdb_stream.stream.readIntLittle(u32);
|
||||||
const signature = try pdb_stream.stream.readIntLe(u32);
|
const signature = try pdb_stream.stream.readIntLittle(u32);
|
||||||
const age = try pdb_stream.stream.readIntLe(u32);
|
const age = try pdb_stream.stream.readIntLittle(u32);
|
||||||
var guid: [16]u8 = undefined;
|
var guid: [16]u8 = undefined;
|
||||||
try pdb_stream.stream.readNoEof(guid[0..]);
|
try pdb_stream.stream.readNoEof(guid[0..]);
|
||||||
if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age)
|
if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age)
|
||||||
|
@ -743,7 +767,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
|
||||||
// We validated the executable and pdb match.
|
// We validated the executable and pdb match.
|
||||||
|
|
||||||
const string_table_index = str_tab_index: {
|
const string_table_index = str_tab_index: {
|
||||||
const name_bytes_len = try pdb_stream.stream.readIntLe(u32);
|
const name_bytes_len = try pdb_stream.stream.readIntLittle(u32);
|
||||||
const name_bytes = try allocator.alloc(u8, name_bytes_len);
|
const name_bytes = try allocator.alloc(u8, name_bytes_len);
|
||||||
try pdb_stream.stream.readNoEof(name_bytes);
|
try pdb_stream.stream.readNoEof(name_bytes);
|
||||||
|
|
||||||
|
@ -773,8 +797,8 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
|
||||||
};
|
};
|
||||||
const bucket_list = try allocator.alloc(Bucket, present.len);
|
const bucket_list = try allocator.alloc(Bucket, present.len);
|
||||||
for (present) |_| {
|
for (present) |_| {
|
||||||
const name_offset = try pdb_stream.stream.readIntLe(u32);
|
const name_offset = try pdb_stream.stream.readIntLittle(u32);
|
||||||
const name_index = try pdb_stream.stream.readIntLe(u32);
|
const name_index = try pdb_stream.stream.readIntLittle(u32);
|
||||||
const name = mem.toSlice(u8, name_bytes.ptr + name_offset);
|
const name = mem.toSlice(u8, name_bytes.ptr + name_offset);
|
||||||
if (mem.eql(u8, name, "/names")) {
|
if (mem.eql(u8, name, "/names")) {
|
||||||
break :str_tab_index name_index;
|
break :str_tab_index name_index;
|
||||||
|
@ -835,7 +859,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
|
||||||
var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator);
|
var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator);
|
||||||
var sect_cont_offset: usize = 0;
|
var sect_cont_offset: usize = 0;
|
||||||
if (section_contrib_size != 0) {
|
if (section_contrib_size != 0) {
|
||||||
const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLe(u32));
|
const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLittle(u32));
|
||||||
if (ver != pdb.SectionContrSubstreamVersion.Ver60)
|
if (ver != pdb.SectionContrSubstreamVersion.Ver60)
|
||||||
return error.InvalidDebugInfo;
|
return error.InvalidDebugInfo;
|
||||||
sect_cont_offset += @sizeOf(u32);
|
sect_cont_offset += @sizeOf(u32);
|
||||||
|
@ -855,11 +879,11 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {
|
fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {
|
||||||
const num_words = try stream.readIntLe(u32);
|
const num_words = try stream.readIntLittle(u32);
|
||||||
var word_i: usize = 0;
|
var word_i: usize = 0;
|
||||||
var list = ArrayList(usize).init(allocator);
|
var list = ArrayList(usize).init(allocator);
|
||||||
while (word_i != num_words) : (word_i += 1) {
|
while (word_i != num_words) : (word_i += 1) {
|
||||||
const word = try stream.readIntLe(u32);
|
const word = try stream.readIntLittle(u32);
|
||||||
var bit_i: u5 = 0;
|
var bit_i: u5 = 0;
|
||||||
while (true) : (bit_i += 1) {
|
while (true) : (bit_i += 1) {
|
||||||
if (word & (u32(1) << bit_i) != 0) {
|
if (word & (u32(1) << bit_i) != 0) {
|
||||||
|
@ -871,55 +895,68 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {
|
||||||
return list.toOwnedSlice();
|
return list.toOwnedSlice();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo {
|
fn findDwarfSectionFromElf(elf_file: *elf.Elf, name: []const u8) !?DwarfInfo.Section {
|
||||||
var di = DebugInfo{
|
const elf_header = (try elf_file.findSection(name)) orelse return null;
|
||||||
.self_exe_file = undefined,
|
return DwarfInfo.Section{
|
||||||
.elf = undefined,
|
.offset = elf_header.offset,
|
||||||
.debug_info = undefined,
|
.size = elf_header.size,
|
||||||
.debug_abbrev = undefined,
|
|
||||||
.debug_str = undefined,
|
|
||||||
.debug_line = undefined,
|
|
||||||
.debug_ranges = null,
|
|
||||||
.abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator),
|
|
||||||
.compile_unit_list = ArrayList(CompileUnit).init(allocator),
|
|
||||||
};
|
};
|
||||||
di.self_exe_file = try os.openSelfExe();
|
}
|
||||||
errdefer di.self_exe_file.close();
|
|
||||||
|
|
||||||
try di.elf.openFile(allocator, di.self_exe_file);
|
/// Initialize DWARF info. The caller has the responsibility to initialize most
|
||||||
errdefer di.elf.close();
|
/// the DwarfInfo fields before calling. These fields can be left undefined:
|
||||||
|
/// * abbrev_table_list
|
||||||
|
/// * compile_unit_list
|
||||||
|
pub fn openDwarfDebugInfo(di: *DwarfInfo, allocator: *mem.Allocator) !void {
|
||||||
|
di.abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator);
|
||||||
|
di.compile_unit_list = ArrayList(CompileUnit).init(allocator);
|
||||||
|
try scanAllCompileUnits(di);
|
||||||
|
}
|
||||||
|
|
||||||
di.debug_info = (try di.elf.findSection(".debug_info")) orelse return error.MissingDebugInfo;
|
pub fn openElfDebugInfo(
|
||||||
di.debug_abbrev = (try di.elf.findSection(".debug_abbrev")) orelse return error.MissingDebugInfo;
|
allocator: *mem.Allocator,
|
||||||
di.debug_str = (try di.elf.findSection(".debug_str")) orelse return error.MissingDebugInfo;
|
elf_seekable_stream: *DwarfSeekableStream,
|
||||||
di.debug_line = (try di.elf.findSection(".debug_line")) orelse return error.MissingDebugInfo;
|
elf_in_stream: *DwarfInStream,
|
||||||
di.debug_ranges = (try di.elf.findSection(".debug_ranges"));
|
) !DwarfInfo {
|
||||||
try scanAllCompileUnits(&di);
|
var efile: elf.Elf = undefined;
|
||||||
|
try efile.openStream(allocator, elf_seekable_stream, elf_in_stream);
|
||||||
|
errdefer efile.close();
|
||||||
|
|
||||||
|
var di = DwarfInfo{
|
||||||
|
.dwarf_seekable_stream = elf_seekable_stream,
|
||||||
|
.dwarf_in_stream = elf_in_stream,
|
||||||
|
.endian = efile.endian,
|
||||||
|
.debug_info = (try findDwarfSectionFromElf(&efile, ".debug_info")) orelse return error.MissingDebugInfo,
|
||||||
|
.debug_abbrev = (try findDwarfSectionFromElf(&efile, ".debug_abbrev")) orelse return error.MissingDebugInfo,
|
||||||
|
.debug_str = (try findDwarfSectionFromElf(&efile, ".debug_str")) orelse return error.MissingDebugInfo,
|
||||||
|
.debug_line = (try findDwarfSectionFromElf(&efile, ".debug_line")) orelse return error.MissingDebugInfo,
|
||||||
|
.debug_ranges = (try findDwarfSectionFromElf(&efile, ".debug_ranges")),
|
||||||
|
.abbrev_table_list = undefined,
|
||||||
|
.compile_unit_list = undefined,
|
||||||
|
};
|
||||||
|
try openDwarfDebugInfo(&di, allocator);
|
||||||
return di;
|
return di;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn findElfSection(elf: *Elf, name: []const u8) ?*elf.Shdr {
|
fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo {
|
||||||
var file_stream = elf.in_file.inStream();
|
const S = struct {
|
||||||
const in = &file_stream.stream;
|
var self_exe_file: os.File = undefined;
|
||||||
|
var self_exe_seekable_stream: os.File.SeekableStream = undefined;
|
||||||
|
var self_exe_in_stream: os.File.InStream = undefined;
|
||||||
|
};
|
||||||
|
S.self_exe_file = try os.openSelfExe();
|
||||||
|
errdefer S.self_exe_file.close();
|
||||||
|
|
||||||
section_loop: for (elf.section_headers) |*elf_section| {
|
S.self_exe_seekable_stream = S.self_exe_file.seekableStream();
|
||||||
if (elf_section.sh_type == SHT_NULL) continue;
|
S.self_exe_in_stream = S.self_exe_file.inStream();
|
||||||
|
|
||||||
const name_offset = elf.string_section.offset + elf_section.name;
|
return openElfDebugInfo(
|
||||||
try elf.in_file.seekTo(name_offset);
|
allocator,
|
||||||
|
// TODO https://github.com/ziglang/zig/issues/764
|
||||||
for (name) |expected_c| {
|
@ptrCast(*DwarfSeekableStream, &S.self_exe_seekable_stream.stream),
|
||||||
const target_c = try in.readByte();
|
// TODO https://github.com/ziglang/zig/issues/764
|
||||||
if (target_c == 0 or expected_c != target_c) continue :section_loop;
|
@ptrCast(*DwarfInStream, &S.self_exe_in_stream.stream),
|
||||||
}
|
);
|
||||||
|
|
||||||
{
|
|
||||||
const null_byte = try in.readByte();
|
|
||||||
if (null_byte == 0) return elf_section;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
|
fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
|
||||||
|
@ -999,7 +1036,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printLineFromFile(out_stream: var, line_info: LineInfo) !void {
|
fn printLineFromFileAnyOs(out_stream: var, line_info: LineInfo) !void {
|
||||||
var f = try os.File.openRead(line_info.file_name);
|
var f = try os.File.openRead(line_info.file_name);
|
||||||
defer f.close();
|
defer f.close();
|
||||||
// TODO fstat and make sure that the file has the correct size
|
// TODO fstat and make sure that the file has the correct size
|
||||||
|
@ -1052,6 +1089,35 @@ const MachOFile = struct {
|
||||||
sect_debug_line: ?*const macho.section_64,
|
sect_debug_line: ?*const macho.section_64,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const DwarfSeekableStream = io.SeekableStream(anyerror, anyerror);
|
||||||
|
pub const DwarfInStream = io.InStream(anyerror);
|
||||||
|
|
||||||
|
pub const DwarfInfo = struct {
|
||||||
|
dwarf_seekable_stream: *DwarfSeekableStream,
|
||||||
|
dwarf_in_stream: *DwarfInStream,
|
||||||
|
endian: builtin.Endian,
|
||||||
|
debug_info: Section,
|
||||||
|
debug_abbrev: Section,
|
||||||
|
debug_str: Section,
|
||||||
|
debug_line: Section,
|
||||||
|
debug_ranges: ?Section,
|
||||||
|
abbrev_table_list: ArrayList(AbbrevTableHeader),
|
||||||
|
compile_unit_list: ArrayList(CompileUnit),
|
||||||
|
|
||||||
|
pub const Section = struct {
|
||||||
|
offset: usize,
|
||||||
|
size: usize,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn allocator(self: DwarfInfo) *mem.Allocator {
|
||||||
|
return self.abbrev_table_list.allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn readString(self: *DwarfInfo) ![]u8 {
|
||||||
|
return readStringRaw(self.allocator(), self.dwarf_in_stream);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub const DebugInfo = switch (builtin.os) {
|
pub const DebugInfo = switch (builtin.os) {
|
||||||
builtin.Os.macosx => struct {
|
builtin.Os.macosx => struct {
|
||||||
symbols: []const MachoSymbol,
|
symbols: []const MachoSymbol,
|
||||||
|
@ -1075,32 +1141,8 @@ pub const DebugInfo = switch (builtin.os) {
|
||||||
sect_contribs: []pdb.SectionContribEntry,
|
sect_contribs: []pdb.SectionContribEntry,
|
||||||
modules: []Module,
|
modules: []Module,
|
||||||
},
|
},
|
||||||
builtin.Os.linux => struct {
|
builtin.Os.linux => DwarfInfo,
|
||||||
self_exe_file: os.File,
|
builtin.Os.freebsd => struct {},
|
||||||
elf: elf.Elf,
|
|
||||||
debug_info: *elf.SectionHeader,
|
|
||||||
debug_abbrev: *elf.SectionHeader,
|
|
||||||
debug_str: *elf.SectionHeader,
|
|
||||||
debug_line: *elf.SectionHeader,
|
|
||||||
debug_ranges: ?*elf.SectionHeader,
|
|
||||||
abbrev_table_list: ArrayList(AbbrevTableHeader),
|
|
||||||
compile_unit_list: ArrayList(CompileUnit),
|
|
||||||
|
|
||||||
pub fn allocator(self: DebugInfo) *mem.Allocator {
|
|
||||||
return self.abbrev_table_list.allocator;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn readString(self: *DebugInfo) ![]u8 {
|
|
||||||
var in_file_stream = self.self_exe_file.inStream();
|
|
||||||
const in_stream = &in_file_stream.stream;
|
|
||||||
return readStringRaw(self.allocator(), in_stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn close(self: *DebugInfo) void {
|
|
||||||
self.self_exe_file.close();
|
|
||||||
self.elf.close();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
else => @compileError("Unsupported OS"),
|
else => @compileError("Unsupported OS"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1158,7 +1200,7 @@ const Constant = struct {
|
||||||
fn asUnsignedLe(self: *const Constant) !u64 {
|
fn asUnsignedLe(self: *const Constant) !u64 {
|
||||||
if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo;
|
if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo;
|
||||||
if (self.signed) return error.InvalidDebugInfo;
|
if (self.signed) return error.InvalidDebugInfo;
|
||||||
return mem.readInt(self.payload, u64, builtin.Endian.Little);
|
return mem.readVarInt(u64, self.payload, builtin.Endian.Little);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1204,11 +1246,11 @@ const Die = struct {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getAttrString(self: *const Die, st: *DebugInfo, id: u64) ![]u8 {
|
fn getAttrString(self: *const Die, di: *DwarfInfo, id: u64) ![]u8 {
|
||||||
const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
|
const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
|
||||||
return switch (form_value.*) {
|
return switch (form_value.*) {
|
||||||
FormValue.String => |value| value,
|
FormValue.String => |value| value,
|
||||||
FormValue.StrPtr => |offset| getString(st, offset),
|
FormValue.StrPtr => |offset| getString(di, offset),
|
||||||
else => error.InvalidDebugInfo,
|
else => error.InvalidDebugInfo,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1221,14 +1263,15 @@ const FileEntry = struct {
|
||||||
len_bytes: usize,
|
len_bytes: usize,
|
||||||
};
|
};
|
||||||
|
|
||||||
const LineInfo = struct {
|
pub const LineInfo = struct {
|
||||||
line: usize,
|
line: usize,
|
||||||
column: usize,
|
column: usize,
|
||||||
file_name: []u8,
|
file_name: []const u8,
|
||||||
allocator: *mem.Allocator,
|
allocator: ?*mem.Allocator,
|
||||||
|
|
||||||
fn deinit(self: *const LineInfo) void {
|
fn deinit(self: LineInfo) void {
|
||||||
self.allocator.free(self.file_name);
|
const allocator = self.allocator orelse return;
|
||||||
|
allocator.free(self.file_name);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1319,10 +1362,10 @@ fn readStringRaw(allocator: *mem.Allocator, in_stream: var) ![]u8 {
|
||||||
return buf.toSlice();
|
return buf.toSlice();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getString(st: *DebugInfo, offset: u64) ![]u8 {
|
fn getString(di: *DwarfInfo, offset: u64) ![]u8 {
|
||||||
const pos = st.debug_str.offset + offset;
|
const pos = di.debug_str.offset + offset;
|
||||||
try st.self_exe_file.seekTo(pos);
|
try di.dwarf_seekable_stream.seekTo(pos);
|
||||||
return st.readString();
|
return di.readString();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8 {
|
fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8 {
|
||||||
|
@ -1338,7 +1381,7 @@ fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
|
fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
|
||||||
const block_len = try in_stream.readVarInt(builtin.Endian.Little, usize, size);
|
const block_len = try in_stream.readVarInt(usize, builtin.Endian.Little, size);
|
||||||
return parseFormValueBlockLen(allocator, in_stream, block_len);
|
return parseFormValueBlockLen(allocator, in_stream, block_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1352,11 +1395,11 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {
|
fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {
|
||||||
return if (is_64) try in_stream.readIntLe(u64) else u64(try in_stream.readIntLe(u32));
|
return if (is_64) try in_stream.readIntLittle(u64) else u64(try in_stream.readIntLittle(u32));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseFormValueTargetAddrSize(in_stream: var) !u64 {
|
fn parseFormValueTargetAddrSize(in_stream: var) !u64 {
|
||||||
return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64) else unreachable;
|
return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLittle(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLittle(u64) else unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
|
fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
|
||||||
|
@ -1365,18 +1408,11 @@ fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue {
|
fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue {
|
||||||
const block_len = try in_stream.readIntLe(T);
|
const block_len = try in_stream.readIntLittle(T);
|
||||||
return parseFormValueRefLen(allocator, in_stream, block_len);
|
return parseFormValueRefLen(allocator, in_stream, block_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ParseFormValueError = error{
|
fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue {
|
||||||
EndOfStream,
|
|
||||||
InvalidDebugInfo,
|
|
||||||
EndOfFile,
|
|
||||||
OutOfMemory,
|
|
||||||
} || std.os.File.ReadError;
|
|
||||||
|
|
||||||
fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) ParseFormValueError!FormValue {
|
|
||||||
return switch (form_id) {
|
return switch (form_id) {
|
||||||
DW.FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) },
|
DW.FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) },
|
||||||
DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1),
|
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
|
||||||
},
|
},
|
||||||
|
|
||||||
DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
|
DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
|
||||||
DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLe(u64) },
|
DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLittle(u64) },
|
||||||
|
|
||||||
DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },
|
DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },
|
||||||
DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
|
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
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable {
|
fn parseAbbrevTable(di: *DwarfInfo) !AbbrevTable {
|
||||||
const in_file = st.self_exe_file;
|
var result = AbbrevTable.init(di.allocator());
|
||||||
var in_file_stream = in_file.inStream();
|
|
||||||
const in_stream = &in_file_stream.stream;
|
|
||||||
var result = AbbrevTable.init(st.allocator());
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const abbrev_code = try readULeb128(in_stream);
|
const abbrev_code = try readULeb128(di.dwarf_in_stream);
|
||||||
if (abbrev_code == 0) return result;
|
if (abbrev_code == 0) return result;
|
||||||
try result.append(AbbrevTableEntry{
|
try result.append(AbbrevTableEntry{
|
||||||
.abbrev_code = abbrev_code,
|
.abbrev_code = abbrev_code,
|
||||||
.tag_id = try readULeb128(in_stream),
|
.tag_id = try readULeb128(di.dwarf_in_stream),
|
||||||
.has_children = (try in_stream.readByte()) == DW.CHILDREN_yes,
|
.has_children = (try di.dwarf_in_stream.readByte()) == DW.CHILDREN_yes,
|
||||||
.attrs = ArrayList(AbbrevAttr).init(st.allocator()),
|
.attrs = ArrayList(AbbrevAttr).init(di.allocator()),
|
||||||
});
|
});
|
||||||
const attrs = &result.items[result.len - 1].attrs;
|
const attrs = &result.items[result.len - 1].attrs;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const attr_id = try readULeb128(in_stream);
|
const attr_id = try readULeb128(di.dwarf_in_stream);
|
||||||
const form_id = try readULeb128(in_stream);
|
const form_id = try readULeb128(di.dwarf_in_stream);
|
||||||
if (attr_id == 0 and form_id == 0) break;
|
if (attr_id == 0 and form_id == 0) break;
|
||||||
try attrs.append(AbbrevAttr{
|
try attrs.append(AbbrevAttr{
|
||||||
.attr_id = attr_id,
|
.attr_id = attr_id,
|
||||||
|
@ -1456,18 +1489,18 @@ fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable {
|
||||||
|
|
||||||
/// Gets an already existing AbbrevTable given the abbrev_offset, or if not found,
|
/// Gets an already existing AbbrevTable given the abbrev_offset, or if not found,
|
||||||
/// seeks in the stream and parses it.
|
/// seeks in the stream and parses it.
|
||||||
fn getAbbrevTable(st: *DebugInfo, abbrev_offset: u64) !*const AbbrevTable {
|
fn getAbbrevTable(di: *DwarfInfo, abbrev_offset: u64) !*const AbbrevTable {
|
||||||
for (st.abbrev_table_list.toSlice()) |*header| {
|
for (di.abbrev_table_list.toSlice()) |*header| {
|
||||||
if (header.offset == abbrev_offset) {
|
if (header.offset == abbrev_offset) {
|
||||||
return &header.table;
|
return &header.table;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try st.self_exe_file.seekTo(st.debug_abbrev.offset + abbrev_offset);
|
try di.dwarf_seekable_stream.seekTo(di.debug_abbrev.offset + abbrev_offset);
|
||||||
try st.abbrev_table_list.append(AbbrevTableHeader{
|
try di.abbrev_table_list.append(AbbrevTableHeader{
|
||||||
.offset = abbrev_offset,
|
.offset = abbrev_offset,
|
||||||
.table = try parseAbbrevTable(st),
|
.table = try parseAbbrevTable(di),
|
||||||
});
|
});
|
||||||
return &st.abbrev_table_list.items[st.abbrev_table_list.len - 1].table;
|
return &di.abbrev_table_list.items[di.abbrev_table_list.len - 1].table;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*const AbbrevTableEntry {
|
fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*const AbbrevTableEntry {
|
||||||
|
@ -1477,23 +1510,20 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseDie(st: *DebugInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die {
|
fn parseDie(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die {
|
||||||
const in_file = st.self_exe_file;
|
const abbrev_code = try readULeb128(di.dwarf_in_stream);
|
||||||
var in_file_stream = in_file.inStream();
|
|
||||||
const in_stream = &in_file_stream.stream;
|
|
||||||
const abbrev_code = try readULeb128(in_stream);
|
|
||||||
const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;
|
const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;
|
||||||
|
|
||||||
var result = Die{
|
var result = Die{
|
||||||
.tag_id = table_entry.tag_id,
|
.tag_id = table_entry.tag_id,
|
||||||
.has_children = table_entry.has_children,
|
.has_children = table_entry.has_children,
|
||||||
.attrs = ArrayList(Die.Attr).init(st.allocator()),
|
.attrs = ArrayList(Die.Attr).init(di.allocator()),
|
||||||
};
|
};
|
||||||
try result.attrs.resize(table_entry.attrs.len);
|
try result.attrs.resize(table_entry.attrs.len);
|
||||||
for (table_entry.attrs.toSliceConst()) |attr, i| {
|
for (table_entry.attrs.toSliceConst()) |attr, i| {
|
||||||
result.attrs.items[i] = Die.Attr{
|
result.attrs.items[i] = Die.Attr{
|
||||||
.id = attr.attr_id,
|
.id = attr.attr_id,
|
||||||
.value = try parseFormValue(st.allocator(), in_stream, attr.form_id, is_64),
|
.value = try parseFormValue(di.allocator(), di.dwarf_in_stream, attr.form_id, is_64),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -1697,22 +1727,18 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
|
||||||
return error.MissingDebugInfo;
|
return error.MissingDebugInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, target_address: usize) !LineInfo {
|
fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo {
|
||||||
const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir);
|
const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir);
|
||||||
|
|
||||||
const in_file = di.self_exe_file;
|
|
||||||
const debug_line_end = di.debug_line.offset + di.debug_line.size;
|
const debug_line_end = di.debug_line.offset + di.debug_line.size;
|
||||||
var this_offset = di.debug_line.offset;
|
var this_offset = di.debug_line.offset;
|
||||||
var this_index: usize = 0;
|
var this_index: usize = 0;
|
||||||
|
|
||||||
var in_file_stream = in_file.inStream();
|
|
||||||
const in_stream = &in_file_stream.stream;
|
|
||||||
|
|
||||||
while (this_offset < debug_line_end) : (this_index += 1) {
|
while (this_offset < debug_line_end) : (this_index += 1) {
|
||||||
try in_file.seekTo(this_offset);
|
try di.dwarf_seekable_stream.seekTo(this_offset);
|
||||||
|
|
||||||
var is_64: bool = undefined;
|
var is_64: bool = undefined;
|
||||||
const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64);
|
const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64);
|
||||||
if (unit_length == 0) return error.MissingDebugInfo;
|
if (unit_length == 0) return error.MissingDebugInfo;
|
||||||
const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
|
const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
|
||||||
|
|
||||||
|
@ -1721,35 +1747,35 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const version = try in_stream.readInt(di.elf.endian, u16);
|
const version = try di.dwarf_in_stream.readInt(u16, di.endian);
|
||||||
// TODO support 3 and 5
|
// TODO support 3 and 5
|
||||||
if (version != 2 and version != 4) return error.InvalidDebugInfo;
|
if (version != 2 and version != 4) return error.InvalidDebugInfo;
|
||||||
|
|
||||||
const prologue_length = if (is_64) try in_stream.readInt(di.elf.endian, u64) else try in_stream.readInt(di.elf.endian, u32);
|
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);
|
||||||
const prog_start_offset = (try in_file.getPos()) + prologue_length;
|
const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length;
|
||||||
|
|
||||||
const minimum_instruction_length = try in_stream.readByte();
|
const minimum_instruction_length = try di.dwarf_in_stream.readByte();
|
||||||
if (minimum_instruction_length == 0) return error.InvalidDebugInfo;
|
if (minimum_instruction_length == 0) return error.InvalidDebugInfo;
|
||||||
|
|
||||||
if (version >= 4) {
|
if (version >= 4) {
|
||||||
// maximum_operations_per_instruction
|
// maximum_operations_per_instruction
|
||||||
_ = try in_stream.readByte();
|
_ = try di.dwarf_in_stream.readByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
const default_is_stmt = (try in_stream.readByte()) != 0;
|
const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0;
|
||||||
const line_base = try in_stream.readByteSigned();
|
const line_base = try di.dwarf_in_stream.readByteSigned();
|
||||||
|
|
||||||
const line_range = try in_stream.readByte();
|
const line_range = try di.dwarf_in_stream.readByte();
|
||||||
if (line_range == 0) return error.InvalidDebugInfo;
|
if (line_range == 0) return error.InvalidDebugInfo;
|
||||||
|
|
||||||
const opcode_base = try in_stream.readByte();
|
const opcode_base = try di.dwarf_in_stream.readByte();
|
||||||
|
|
||||||
const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1);
|
const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1);
|
||||||
|
|
||||||
{
|
{
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < opcode_base - 1) : (i += 1) {
|
while (i < opcode_base - 1) : (i += 1) {
|
||||||
standard_opcode_lengths[i] = try in_stream.readByte();
|
standard_opcode_lengths[i] = try di.dwarf_in_stream.readByte();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1767,9 +1793,9 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
|
||||||
while (true) {
|
while (true) {
|
||||||
const file_name = try di.readString();
|
const file_name = try di.readString();
|
||||||
if (file_name.len == 0) break;
|
if (file_name.len == 0) break;
|
||||||
const dir_index = try readULeb128(in_stream);
|
const dir_index = try readULeb128(di.dwarf_in_stream);
|
||||||
const mtime = try readULeb128(in_stream);
|
const mtime = try readULeb128(di.dwarf_in_stream);
|
||||||
const len_bytes = try readULeb128(in_stream);
|
const len_bytes = try readULeb128(di.dwarf_in_stream);
|
||||||
try file_entries.append(FileEntry{
|
try file_entries.append(FileEntry{
|
||||||
.file_name = file_name,
|
.file_name = file_name,
|
||||||
.dir_index = dir_index,
|
.dir_index = dir_index,
|
||||||
|
@ -1778,15 +1804,15 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try in_file.seekTo(prog_start_offset);
|
try di.dwarf_seekable_stream.seekTo(prog_start_offset);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const opcode = try in_stream.readByte();
|
const opcode = try di.dwarf_in_stream.readByte();
|
||||||
|
|
||||||
if (opcode == DW.LNS_extended_op) {
|
if (opcode == DW.LNS_extended_op) {
|
||||||
const op_size = try readULeb128(in_stream);
|
const op_size = try readULeb128(di.dwarf_in_stream);
|
||||||
if (op_size < 1) return error.InvalidDebugInfo;
|
if (op_size < 1) return error.InvalidDebugInfo;
|
||||||
var sub_op = try in_stream.readByte();
|
var sub_op = try di.dwarf_in_stream.readByte();
|
||||||
switch (sub_op) {
|
switch (sub_op) {
|
||||||
DW.LNE_end_sequence => {
|
DW.LNE_end_sequence => {
|
||||||
prog.end_sequence = true;
|
prog.end_sequence = true;
|
||||||
|
@ -1794,14 +1820,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
|
||||||
return error.MissingDebugInfo;
|
return error.MissingDebugInfo;
|
||||||
},
|
},
|
||||||
DW.LNE_set_address => {
|
DW.LNE_set_address => {
|
||||||
const addr = try in_stream.readInt(di.elf.endian, usize);
|
const addr = try di.dwarf_in_stream.readInt(usize, di.endian);
|
||||||
prog.address = addr;
|
prog.address = addr;
|
||||||
},
|
},
|
||||||
DW.LNE_define_file => {
|
DW.LNE_define_file => {
|
||||||
const file_name = try di.readString();
|
const file_name = try di.readString();
|
||||||
const dir_index = try readULeb128(in_stream);
|
const dir_index = try readULeb128(di.dwarf_in_stream);
|
||||||
const mtime = try readULeb128(in_stream);
|
const mtime = try readULeb128(di.dwarf_in_stream);
|
||||||
const len_bytes = try readULeb128(in_stream);
|
const len_bytes = try readULeb128(di.dwarf_in_stream);
|
||||||
try file_entries.append(FileEntry{
|
try file_entries.append(FileEntry{
|
||||||
.file_name = file_name,
|
.file_name = file_name,
|
||||||
.dir_index = dir_index,
|
.dir_index = dir_index,
|
||||||
|
@ -1811,7 +1837,7 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo;
|
const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo;
|
||||||
try in_file.seekForward(fwd_amt);
|
try di.dwarf_seekable_stream.seekForward(fwd_amt);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else if (opcode >= opcode_base) {
|
} else if (opcode >= opcode_base) {
|
||||||
|
@ -1830,19 +1856,19 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
|
||||||
prog.basic_block = false;
|
prog.basic_block = false;
|
||||||
},
|
},
|
||||||
DW.LNS_advance_pc => {
|
DW.LNS_advance_pc => {
|
||||||
const arg = try readULeb128(in_stream);
|
const arg = try readULeb128(di.dwarf_in_stream);
|
||||||
prog.address += arg * minimum_instruction_length;
|
prog.address += arg * minimum_instruction_length;
|
||||||
},
|
},
|
||||||
DW.LNS_advance_line => {
|
DW.LNS_advance_line => {
|
||||||
const arg = try readILeb128(in_stream);
|
const arg = try readILeb128(di.dwarf_in_stream);
|
||||||
prog.line += arg;
|
prog.line += arg;
|
||||||
},
|
},
|
||||||
DW.LNS_set_file => {
|
DW.LNS_set_file => {
|
||||||
const arg = try readULeb128(in_stream);
|
const arg = try readULeb128(di.dwarf_in_stream);
|
||||||
prog.file = arg;
|
prog.file = arg;
|
||||||
},
|
},
|
||||||
DW.LNS_set_column => {
|
DW.LNS_set_column => {
|
||||||
const arg = try readULeb128(in_stream);
|
const arg = try readULeb128(di.dwarf_in_stream);
|
||||||
prog.column = arg;
|
prog.column = arg;
|
||||||
},
|
},
|
||||||
DW.LNS_negate_stmt => {
|
DW.LNS_negate_stmt => {
|
||||||
|
@ -1856,14 +1882,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
|
||||||
prog.address += inc_addr;
|
prog.address += inc_addr;
|
||||||
},
|
},
|
||||||
DW.LNS_fixed_advance_pc => {
|
DW.LNS_fixed_advance_pc => {
|
||||||
const arg = try in_stream.readInt(di.elf.endian, u16);
|
const arg = try di.dwarf_in_stream.readInt(u16, di.endian);
|
||||||
prog.address += arg;
|
prog.address += arg;
|
||||||
},
|
},
|
||||||
DW.LNS_set_prologue_end => {},
|
DW.LNS_set_prologue_end => {},
|
||||||
else => {
|
else => {
|
||||||
if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo;
|
if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo;
|
||||||
const len_bytes = standard_opcode_lengths[opcode - 1];
|
const len_bytes = standard_opcode_lengths[opcode - 1];
|
||||||
try in_file.seekForward(len_bytes);
|
try di.dwarf_seekable_stream.seekForward(len_bytes);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1875,36 +1901,33 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ
|
||||||
return error.MissingDebugInfo;
|
return error.MissingDebugInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scanAllCompileUnits(st: *DebugInfo) !void {
|
fn scanAllCompileUnits(di: *DwarfInfo) !void {
|
||||||
const debug_info_end = st.debug_info.offset + st.debug_info.size;
|
const debug_info_end = di.debug_info.offset + di.debug_info.size;
|
||||||
var this_unit_offset = st.debug_info.offset;
|
var this_unit_offset = di.debug_info.offset;
|
||||||
var cu_index: usize = 0;
|
var cu_index: usize = 0;
|
||||||
|
|
||||||
var in_file_stream = st.self_exe_file.inStream();
|
|
||||||
const in_stream = &in_file_stream.stream;
|
|
||||||
|
|
||||||
while (this_unit_offset < debug_info_end) {
|
while (this_unit_offset < debug_info_end) {
|
||||||
try st.self_exe_file.seekTo(this_unit_offset);
|
try di.dwarf_seekable_stream.seekTo(this_unit_offset);
|
||||||
|
|
||||||
var is_64: bool = undefined;
|
var is_64: bool = undefined;
|
||||||
const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64);
|
const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64);
|
||||||
if (unit_length == 0) return;
|
if (unit_length == 0) return;
|
||||||
const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
|
const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
|
||||||
|
|
||||||
const version = try in_stream.readInt(st.elf.endian, u16);
|
const version = try di.dwarf_in_stream.readInt(u16, di.endian);
|
||||||
if (version < 2 or version > 5) return error.InvalidDebugInfo;
|
if (version < 2 or version > 5) return error.InvalidDebugInfo;
|
||||||
|
|
||||||
const debug_abbrev_offset = if (is_64) try in_stream.readInt(st.elf.endian, u64) else try in_stream.readInt(st.elf.endian, u32);
|
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);
|
||||||
|
|
||||||
const address_size = try in_stream.readByte();
|
const address_size = try di.dwarf_in_stream.readByte();
|
||||||
if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
|
if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
|
||||||
|
|
||||||
const compile_unit_pos = try st.self_exe_file.getPos();
|
const compile_unit_pos = try di.dwarf_seekable_stream.getPos();
|
||||||
const abbrev_table = try getAbbrevTable(st, debug_abbrev_offset);
|
const abbrev_table = try getAbbrevTable(di, debug_abbrev_offset);
|
||||||
|
|
||||||
try st.self_exe_file.seekTo(compile_unit_pos);
|
try di.dwarf_seekable_stream.seekTo(compile_unit_pos);
|
||||||
|
|
||||||
const compile_unit_die = try st.allocator().create(try parseDie(st, abbrev_table, is_64));
|
const compile_unit_die = try di.allocator().create(try parseDie(di, abbrev_table, is_64));
|
||||||
|
|
||||||
if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo;
|
if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo;
|
||||||
|
|
||||||
|
@ -1932,7 +1955,7 @@ fn scanAllCompileUnits(st: *DebugInfo) !void {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
try st.compile_unit_list.append(CompileUnit{
|
try di.compile_unit_list.append(CompileUnit{
|
||||||
.version = version,
|
.version = version,
|
||||||
.is_64 = is_64,
|
.is_64 = is_64,
|
||||||
.pc_range = pc_range,
|
.pc_range = pc_range,
|
||||||
|
@ -1945,20 +1968,18 @@ fn scanAllCompileUnits(st: *DebugInfo) !void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn findCompileUnit(st: *DebugInfo, target_address: u64) !*const CompileUnit {
|
fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit {
|
||||||
var in_file_stream = st.self_exe_file.inStream();
|
for (di.compile_unit_list.toSlice()) |*compile_unit| {
|
||||||
const in_stream = &in_file_stream.stream;
|
|
||||||
for (st.compile_unit_list.toSlice()) |*compile_unit| {
|
|
||||||
if (compile_unit.pc_range) |range| {
|
if (compile_unit.pc_range) |range| {
|
||||||
if (target_address >= range.start and target_address < range.end) return compile_unit;
|
if (target_address >= range.start and target_address < range.end) return compile_unit;
|
||||||
}
|
}
|
||||||
if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| {
|
if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| {
|
||||||
var base_address: usize = 0;
|
var base_address: usize = 0;
|
||||||
if (st.debug_ranges) |debug_ranges| {
|
if (di.debug_ranges) |debug_ranges| {
|
||||||
try st.self_exe_file.seekTo(debug_ranges.offset + ranges_offset);
|
try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset);
|
||||||
while (true) {
|
while (true) {
|
||||||
const begin_addr = try in_stream.readIntLe(usize);
|
const begin_addr = try di.dwarf_in_stream.readIntLittle(usize);
|
||||||
const end_addr = try in_stream.readIntLe(usize);
|
const end_addr = try di.dwarf_in_stream.readIntLittle(usize);
|
||||||
if (begin_addr == 0 and end_addr == 0) {
|
if (begin_addr == 0 and end_addr == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1980,7 +2001,8 @@ fn findCompileUnit(st: *DebugInfo, target_address: u64) !*const CompileUnit {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readIntMem(ptr: *[*]const u8, comptime T: type, endian: builtin.Endian) T {
|
fn readIntMem(ptr: *[*]const u8, comptime T: type, endian: builtin.Endian) T {
|
||||||
const result = mem.readInt(ptr.*[0..@sizeOf(T)], T, endian);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
const result = mem.readIntSlice(T, ptr.*[0..@sizeOf(T)], endian);
|
||||||
ptr.* += @sizeOf(T);
|
ptr.* += @sizeOf(T);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1996,11 +2018,12 @@ fn readByteSignedMem(ptr: *[*]const u8) i8 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 {
|
fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 {
|
||||||
const first_32_bits = mem.readIntLE(u32, ptr.*[0..4]);
|
// TODO this code can be improved with https://github.com/ziglang/zig/issues/863
|
||||||
|
const first_32_bits = mem.readIntSliceLittle(u32, ptr.*[0..4]);
|
||||||
is_64.* = (first_32_bits == 0xffffffff);
|
is_64.* = (first_32_bits == 0xffffffff);
|
||||||
if (is_64.*) {
|
if (is_64.*) {
|
||||||
ptr.* += 4;
|
ptr.* += 4;
|
||||||
const result = mem.readIntLE(u64, ptr.*[0..8]);
|
const result = mem.readIntSliceLittle(u64, ptr.*[0..8]);
|
||||||
ptr.* += 8;
|
ptr.* += 8;
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2063,10 +2086,10 @@ fn readILeb128Mem(ptr: *[*]const u8) !i64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 {
|
fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 {
|
||||||
const first_32_bits = try in_stream.readIntLe(u32);
|
const first_32_bits = try in_stream.readIntLittle(u32);
|
||||||
is_64.* = (first_32_bits == 0xffffffff);
|
is_64.* = (first_32_bits == 0xffffffff);
|
||||||
if (is_64.*) {
|
if (is_64.*) {
|
||||||
return in_stream.readIntLe(u64);
|
return in_stream.readIntLittle(u64);
|
||||||
} else {
|
} else {
|
||||||
if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo;
|
if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo;
|
||||||
return u64(first_32_bits);
|
return u64(first_32_bits);
|
||||||
|
|
|
@ -19,7 +19,6 @@ pub const DynLib = switch (builtin.os) {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const LinuxDynLib = struct {
|
pub const LinuxDynLib = struct {
|
||||||
allocator: *mem.Allocator,
|
|
||||||
elf_lib: ElfLib,
|
elf_lib: ElfLib,
|
||||||
fd: i32,
|
fd: i32,
|
||||||
map_addr: usize,
|
map_addr: usize,
|
||||||
|
@ -27,7 +26,7 @@ pub const LinuxDynLib = struct {
|
||||||
|
|
||||||
/// Trusts the file
|
/// Trusts the file
|
||||||
pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib {
|
pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib {
|
||||||
const fd = try std.os.posixOpen(allocator, path, 0, linux.O_RDONLY | linux.O_CLOEXEC);
|
const fd = try std.os.posixOpen(path, 0, linux.O_RDONLY | linux.O_CLOEXEC);
|
||||||
errdefer std.os.close(fd);
|
errdefer std.os.close(fd);
|
||||||
|
|
||||||
const size = @intCast(usize, (try std.os.posixFStat(fd)).size);
|
const size = @intCast(usize, (try std.os.posixFStat(fd)).size);
|
||||||
|
@ -45,7 +44,6 @@ pub const LinuxDynLib = struct {
|
||||||
const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size];
|
const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size];
|
||||||
|
|
||||||
return DynLib{
|
return DynLib{
|
||||||
.allocator = allocator,
|
|
||||||
.elf_lib = try ElfLib.init(bytes),
|
.elf_lib = try ElfLib.init(bytes),
|
||||||
.fd = fd,
|
.fd = fd,
|
||||||
.map_addr = addr,
|
.map_addr = addr,
|
||||||
|
|
115
std/elf.zig
115
std/elf.zig
|
@ -353,7 +353,8 @@ pub const SectionHeader = struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Elf = struct {
|
pub const Elf = struct {
|
||||||
in_file: os.File,
|
seekable_stream: *io.SeekableStream(anyerror, anyerror),
|
||||||
|
in_stream: *io.InStream(anyerror),
|
||||||
auto_close_stream: bool,
|
auto_close_stream: bool,
|
||||||
is_64: bool,
|
is_64: bool,
|
||||||
endian: builtin.Endian,
|
endian: builtin.Endian,
|
||||||
|
@ -370,19 +371,24 @@ pub const Elf = struct {
|
||||||
|
|
||||||
/// Call close when done.
|
/// Call close when done.
|
||||||
pub fn openPath(elf: *Elf, allocator: *mem.Allocator, path: []const u8) !void {
|
pub fn openPath(elf: *Elf, allocator: *mem.Allocator, path: []const u8) !void {
|
||||||
try elf.prealloc_file.open(path);
|
@compileError("TODO implement");
|
||||||
try elf.openFile(allocator, *elf.prealloc_file);
|
|
||||||
elf.auto_close_stream = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call close when done.
|
/// Call close when done.
|
||||||
pub fn openFile(elf: *Elf, allocator: *mem.Allocator, file: os.File) !void {
|
pub fn openFile(elf: *Elf, allocator: *mem.Allocator, file: os.File) !void {
|
||||||
elf.allocator = allocator;
|
@compileError("TODO implement");
|
||||||
elf.in_file = file;
|
}
|
||||||
elf.auto_close_stream = false;
|
|
||||||
|
|
||||||
var file_stream = elf.in_file.inStream();
|
pub fn openStream(
|
||||||
const in = &file_stream.stream;
|
elf: *Elf,
|
||||||
|
allocator: *mem.Allocator,
|
||||||
|
seekable_stream: *io.SeekableStream(anyerror, anyerror),
|
||||||
|
in: *io.InStream(anyerror),
|
||||||
|
) !void {
|
||||||
|
elf.auto_close_stream = false;
|
||||||
|
elf.allocator = allocator;
|
||||||
|
elf.seekable_stream = seekable_stream;
|
||||||
|
elf.in_stream = in;
|
||||||
|
|
||||||
var magic: [4]u8 = undefined;
|
var magic: [4]u8 = undefined;
|
||||||
try in.readNoEof(magic[0..]);
|
try in.readNoEof(magic[0..]);
|
||||||
|
@ -404,9 +410,9 @@ pub const Elf = struct {
|
||||||
if (version_byte != 1) return error.InvalidFormat;
|
if (version_byte != 1) return error.InvalidFormat;
|
||||||
|
|
||||||
// skip over padding
|
// skip over padding
|
||||||
try elf.in_file.seekForward(9);
|
try seekable_stream.seekForward(9);
|
||||||
|
|
||||||
elf.file_type = switch (try in.readInt(elf.endian, u16)) {
|
elf.file_type = switch (try in.readInt(u16, elf.endian)) {
|
||||||
1 => FileType.Relocatable,
|
1 => FileType.Relocatable,
|
||||||
2 => FileType.Executable,
|
2 => FileType.Executable,
|
||||||
3 => FileType.Shared,
|
3 => FileType.Shared,
|
||||||
|
@ -414,7 +420,7 @@ pub const Elf = struct {
|
||||||
else => return error.InvalidFormat,
|
else => return error.InvalidFormat,
|
||||||
};
|
};
|
||||||
|
|
||||||
elf.arch = switch (try in.readInt(elf.endian, u16)) {
|
elf.arch = switch (try in.readInt(u16, elf.endian)) {
|
||||||
0x02 => Arch.Sparc,
|
0x02 => Arch.Sparc,
|
||||||
0x03 => Arch.x86,
|
0x03 => Arch.x86,
|
||||||
0x08 => Arch.Mips,
|
0x08 => Arch.Mips,
|
||||||
|
@ -427,32 +433,32 @@ pub const Elf = struct {
|
||||||
else => return error.InvalidFormat,
|
else => return error.InvalidFormat,
|
||||||
};
|
};
|
||||||
|
|
||||||
const elf_version = try in.readInt(elf.endian, u32);
|
const elf_version = try in.readInt(u32, elf.endian);
|
||||||
if (elf_version != 1) return error.InvalidFormat;
|
if (elf_version != 1) return error.InvalidFormat;
|
||||||
|
|
||||||
if (elf.is_64) {
|
if (elf.is_64) {
|
||||||
elf.entry_addr = try in.readInt(elf.endian, u64);
|
elf.entry_addr = try in.readInt(u64, elf.endian);
|
||||||
elf.program_header_offset = try in.readInt(elf.endian, u64);
|
elf.program_header_offset = try in.readInt(u64, elf.endian);
|
||||||
elf.section_header_offset = try in.readInt(elf.endian, u64);
|
elf.section_header_offset = try in.readInt(u64, elf.endian);
|
||||||
} else {
|
} else {
|
||||||
elf.entry_addr = u64(try in.readInt(elf.endian, u32));
|
elf.entry_addr = u64(try in.readInt(u32, elf.endian));
|
||||||
elf.program_header_offset = u64(try in.readInt(elf.endian, u32));
|
elf.program_header_offset = u64(try in.readInt(u32, elf.endian));
|
||||||
elf.section_header_offset = u64(try in.readInt(elf.endian, u32));
|
elf.section_header_offset = u64(try in.readInt(u32, elf.endian));
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip over flags
|
// skip over flags
|
||||||
try elf.in_file.seekForward(4);
|
try seekable_stream.seekForward(4);
|
||||||
|
|
||||||
const header_size = try in.readInt(elf.endian, u16);
|
const header_size = try in.readInt(u16, elf.endian);
|
||||||
if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) {
|
if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) {
|
||||||
return error.InvalidFormat;
|
return error.InvalidFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ph_entry_size = try in.readInt(elf.endian, u16);
|
const ph_entry_size = try in.readInt(u16, elf.endian);
|
||||||
const ph_entry_count = try in.readInt(elf.endian, u16);
|
const ph_entry_count = try in.readInt(u16, elf.endian);
|
||||||
const sh_entry_size = try in.readInt(elf.endian, u16);
|
const sh_entry_size = try in.readInt(u16, elf.endian);
|
||||||
const sh_entry_count = try in.readInt(elf.endian, u16);
|
const sh_entry_count = try in.readInt(u16, elf.endian);
|
||||||
elf.string_section_index = u64(try in.readInt(elf.endian, u16));
|
elf.string_section_index = u64(try in.readInt(u16, elf.endian));
|
||||||
|
|
||||||
if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat;
|
if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat;
|
||||||
|
|
||||||
|
@ -461,12 +467,12 @@ pub const Elf = struct {
|
||||||
const ph_byte_count = u64(ph_entry_size) * u64(ph_entry_count);
|
const ph_byte_count = u64(ph_entry_size) * u64(ph_entry_count);
|
||||||
const end_ph = try math.add(u64, elf.program_header_offset, ph_byte_count);
|
const end_ph = try math.add(u64, elf.program_header_offset, ph_byte_count);
|
||||||
|
|
||||||
const stream_end = try elf.in_file.getEndPos();
|
const stream_end = try seekable_stream.getEndPos();
|
||||||
if (stream_end < end_sh or stream_end < end_ph) {
|
if (stream_end < end_sh or stream_end < end_ph) {
|
||||||
return error.InvalidFormat;
|
return error.InvalidFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
try elf.in_file.seekTo(elf.section_header_offset);
|
try seekable_stream.seekTo(elf.section_header_offset);
|
||||||
|
|
||||||
elf.section_headers = try elf.allocator.alloc(SectionHeader, sh_entry_count);
|
elf.section_headers = try elf.allocator.alloc(SectionHeader, sh_entry_count);
|
||||||
errdefer elf.allocator.free(elf.section_headers);
|
errdefer elf.allocator.free(elf.section_headers);
|
||||||
|
@ -475,32 +481,32 @@ pub const Elf = struct {
|
||||||
if (sh_entry_size != 64) return error.InvalidFormat;
|
if (sh_entry_size != 64) return error.InvalidFormat;
|
||||||
|
|
||||||
for (elf.section_headers) |*elf_section| {
|
for (elf.section_headers) |*elf_section| {
|
||||||
elf_section.name = try in.readInt(elf.endian, u32);
|
elf_section.name = try in.readInt(u32, elf.endian);
|
||||||
elf_section.sh_type = try in.readInt(elf.endian, u32);
|
elf_section.sh_type = try in.readInt(u32, elf.endian);
|
||||||
elf_section.flags = try in.readInt(elf.endian, u64);
|
elf_section.flags = try in.readInt(u64, elf.endian);
|
||||||
elf_section.addr = try in.readInt(elf.endian, u64);
|
elf_section.addr = try in.readInt(u64, elf.endian);
|
||||||
elf_section.offset = try in.readInt(elf.endian, u64);
|
elf_section.offset = try in.readInt(u64, elf.endian);
|
||||||
elf_section.size = try in.readInt(elf.endian, u64);
|
elf_section.size = try in.readInt(u64, elf.endian);
|
||||||
elf_section.link = try in.readInt(elf.endian, u32);
|
elf_section.link = try in.readInt(u32, elf.endian);
|
||||||
elf_section.info = try in.readInt(elf.endian, u32);
|
elf_section.info = try in.readInt(u32, elf.endian);
|
||||||
elf_section.addr_align = try in.readInt(elf.endian, u64);
|
elf_section.addr_align = try in.readInt(u64, elf.endian);
|
||||||
elf_section.ent_size = try in.readInt(elf.endian, u64);
|
elf_section.ent_size = try in.readInt(u64, elf.endian);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (sh_entry_size != 40) return error.InvalidFormat;
|
if (sh_entry_size != 40) return error.InvalidFormat;
|
||||||
|
|
||||||
for (elf.section_headers) |*elf_section| {
|
for (elf.section_headers) |*elf_section| {
|
||||||
// TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ?
|
// TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ?
|
||||||
elf_section.name = try in.readInt(elf.endian, u32);
|
elf_section.name = try in.readInt(u32, elf.endian);
|
||||||
elf_section.sh_type = try in.readInt(elf.endian, u32);
|
elf_section.sh_type = try in.readInt(u32, elf.endian);
|
||||||
elf_section.flags = u64(try in.readInt(elf.endian, u32));
|
elf_section.flags = u64(try in.readInt(u32, elf.endian));
|
||||||
elf_section.addr = u64(try in.readInt(elf.endian, u32));
|
elf_section.addr = u64(try in.readInt(u32, elf.endian));
|
||||||
elf_section.offset = u64(try in.readInt(elf.endian, u32));
|
elf_section.offset = u64(try in.readInt(u32, elf.endian));
|
||||||
elf_section.size = u64(try in.readInt(elf.endian, u32));
|
elf_section.size = u64(try in.readInt(u32, elf.endian));
|
||||||
elf_section.link = try in.readInt(elf.endian, u32);
|
elf_section.link = try in.readInt(u32, elf.endian);
|
||||||
elf_section.info = try in.readInt(elf.endian, u32);
|
elf_section.info = try in.readInt(u32, elf.endian);
|
||||||
elf_section.addr_align = u64(try in.readInt(elf.endian, u32));
|
elf_section.addr_align = u64(try in.readInt(u32, elf.endian));
|
||||||
elf_section.ent_size = u64(try in.readInt(elf.endian, u32));
|
elf_section.ent_size = u64(try in.readInt(u32, elf.endian));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,26 +527,23 @@ pub const Elf = struct {
|
||||||
pub fn close(elf: *Elf) void {
|
pub fn close(elf: *Elf) void {
|
||||||
elf.allocator.free(elf.section_headers);
|
elf.allocator.free(elf.section_headers);
|
||||||
|
|
||||||
if (elf.auto_close_stream) elf.in_file.close();
|
if (elf.auto_close_stream) elf.prealloc_file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn findSection(elf: *Elf, name: []const u8) !?*SectionHeader {
|
pub fn findSection(elf: *Elf, name: []const u8) !?*SectionHeader {
|
||||||
var file_stream = elf.in_file.inStream();
|
|
||||||
const in = &file_stream.stream;
|
|
||||||
|
|
||||||
section_loop: for (elf.section_headers) |*elf_section| {
|
section_loop: for (elf.section_headers) |*elf_section| {
|
||||||
if (elf_section.sh_type == SHT_NULL) continue;
|
if (elf_section.sh_type == SHT_NULL) continue;
|
||||||
|
|
||||||
const name_offset = elf.string_section.offset + elf_section.name;
|
const name_offset = elf.string_section.offset + elf_section.name;
|
||||||
try elf.in_file.seekTo(name_offset);
|
try elf.seekable_stream.seekTo(name_offset);
|
||||||
|
|
||||||
for (name) |expected_c| {
|
for (name) |expected_c| {
|
||||||
const target_c = try in.readByte();
|
const target_c = try elf.in_stream.readByte();
|
||||||
if (target_c == 0 or expected_c != target_c) continue :section_loop;
|
if (target_c == 0 or expected_c != target_c) continue :section_loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const null_byte = try in.readByte();
|
const null_byte = try elf.in_stream.readByte();
|
||||||
if (null_byte == 0) return elf_section;
|
if (null_byte == 0) return elf_section;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -549,7 +552,7 @@ pub const Elf = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn seekToSection(elf: *Elf, elf_section: *SectionHeader) !void {
|
pub fn seekToSection(elf: *Elf, elf_section: *SectionHeader) !void {
|
||||||
try elf.in_file.seekTo(elf_section.offset);
|
try elf.seekable_stream.seekTo(elf_section.offset);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,7 @@ pub async fn pwritev(loop: *Loop, fd: os.FileHandle, data: []const []const u8, o
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
builtin.Os.macosx,
|
builtin.Os.macosx,
|
||||||
builtin.Os.linux,
|
builtin.Os.linux,
|
||||||
|
builtin.Os.freebsd,
|
||||||
=> {
|
=> {
|
||||||
const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);
|
const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);
|
||||||
defer loop.allocator.free(iovecs);
|
defer loop.allocator.free(iovecs);
|
||||||
|
@ -219,6 +220,7 @@ pub async fn preadv(loop: *Loop, fd: os.FileHandle, data: []const []u8, offset:
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
builtin.Os.macosx,
|
builtin.Os.macosx,
|
||||||
builtin.Os.linux,
|
builtin.Os.linux,
|
||||||
|
builtin.Os.freebsd,
|
||||||
=> {
|
=> {
|
||||||
const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);
|
const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);
|
||||||
defer loop.allocator.free(iovecs);
|
defer loop.allocator.free(iovecs);
|
||||||
|
@ -399,7 +401,7 @@ pub async fn openPosix(
|
||||||
|
|
||||||
pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!os.FileHandle {
|
pub async fn openRead(loop: *Loop, path: []const u8) os.File.OpenError!os.FileHandle {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
builtin.Os.macosx, builtin.Os.linux => {
|
builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd => {
|
||||||
const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC;
|
const flags = posix.O_LARGEFILE | posix.O_RDONLY | posix.O_CLOEXEC;
|
||||||
return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);
|
return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);
|
||||||
},
|
},
|
||||||
|
@ -427,6 +429,7 @@ pub async fn openWriteMode(loop: *Loop, path: []const u8, mode: os.File.Mode) os
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
builtin.Os.macosx,
|
builtin.Os.macosx,
|
||||||
builtin.Os.linux,
|
builtin.Os.linux,
|
||||||
|
builtin.Os.freebsd,
|
||||||
=> {
|
=> {
|
||||||
const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC;
|
const flags = posix.O_LARGEFILE | posix.O_WRONLY | posix.O_CREAT | posix.O_CLOEXEC | posix.O_TRUNC;
|
||||||
return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);
|
return await (async openPosix(loop, path, flags, os.File.default_mode) catch unreachable);
|
||||||
|
@ -449,7 +452,7 @@ pub async fn openReadWrite(
|
||||||
mode: os.File.Mode,
|
mode: os.File.Mode,
|
||||||
) os.File.OpenError!os.FileHandle {
|
) os.File.OpenError!os.FileHandle {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
builtin.Os.macosx, builtin.Os.linux => {
|
builtin.Os.macosx, builtin.Os.linux, builtin.Os.freebsd => {
|
||||||
const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC;
|
const flags = posix.O_LARGEFILE | posix.O_RDWR | posix.O_CREAT | posix.O_CLOEXEC;
|
||||||
return await (async openPosix(loop, path, flags, mode) catch unreachable);
|
return await (async openPosix(loop, path, flags, mode) catch unreachable);
|
||||||
},
|
},
|
||||||
|
@ -477,7 +480,7 @@ pub const CloseOperation = struct {
|
||||||
os_data: OsData,
|
os_data: OsData,
|
||||||
|
|
||||||
const OsData = switch (builtin.os) {
|
const OsData = switch (builtin.os) {
|
||||||
builtin.Os.linux, builtin.Os.macosx => OsDataPosix,
|
builtin.Os.linux, builtin.Os.macosx, builtin.Os.freebsd => OsDataPosix,
|
||||||
|
|
||||||
builtin.Os.windows => struct {
|
builtin.Os.windows => struct {
|
||||||
handle: ?os.FileHandle,
|
handle: ?os.FileHandle,
|
||||||
|
@ -496,7 +499,7 @@ pub const CloseOperation = struct {
|
||||||
self.* = CloseOperation{
|
self.* = CloseOperation{
|
||||||
.loop = loop,
|
.loop = loop,
|
||||||
.os_data = switch (builtin.os) {
|
.os_data = switch (builtin.os) {
|
||||||
builtin.Os.linux, builtin.Os.macosx => initOsDataPosix(self),
|
builtin.Os.linux, builtin.Os.macosx, builtin.Os.freebsd => initOsDataPosix(self),
|
||||||
builtin.Os.windows => OsData{ .handle = null },
|
builtin.Os.windows => OsData{ .handle = null },
|
||||||
else => @compileError("Unsupported OS"),
|
else => @compileError("Unsupported OS"),
|
||||||
},
|
},
|
||||||
|
@ -525,6 +528,7 @@ pub const CloseOperation = struct {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
builtin.Os.linux,
|
builtin.Os.linux,
|
||||||
builtin.Os.macosx,
|
builtin.Os.macosx,
|
||||||
|
builtin.Os.freebsd,
|
||||||
=> {
|
=> {
|
||||||
if (self.os_data.have_fd) {
|
if (self.os_data.have_fd) {
|
||||||
self.loop.posixFsRequest(&self.os_data.close_req_node);
|
self.loop.posixFsRequest(&self.os_data.close_req_node);
|
||||||
|
@ -546,6 +550,7 @@ pub const CloseOperation = struct {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
builtin.Os.linux,
|
builtin.Os.linux,
|
||||||
builtin.Os.macosx,
|
builtin.Os.macosx,
|
||||||
|
builtin.Os.freebsd,
|
||||||
=> {
|
=> {
|
||||||
self.os_data.close_req_node.data.msg.Close.fd = handle;
|
self.os_data.close_req_node.data.msg.Close.fd = handle;
|
||||||
self.os_data.have_fd = true;
|
self.os_data.have_fd = true;
|
||||||
|
@ -562,6 +567,7 @@ pub const CloseOperation = struct {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
builtin.Os.linux,
|
builtin.Os.linux,
|
||||||
builtin.Os.macosx,
|
builtin.Os.macosx,
|
||||||
|
builtin.Os.freebsd,
|
||||||
=> {
|
=> {
|
||||||
self.os_data.have_fd = false;
|
self.os_data.have_fd = false;
|
||||||
},
|
},
|
||||||
|
@ -576,6 +582,7 @@ pub const CloseOperation = struct {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
builtin.Os.linux,
|
builtin.Os.linux,
|
||||||
builtin.Os.macosx,
|
builtin.Os.macosx,
|
||||||
|
builtin.Os.freebsd,
|
||||||
=> {
|
=> {
|
||||||
assert(self.os_data.have_fd);
|
assert(self.os_data.have_fd);
|
||||||
return self.os_data.close_req_node.data.msg.Close.fd;
|
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,
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
builtin.Os.linux,
|
builtin.Os.linux,
|
||||||
builtin.Os.macosx,
|
builtin.Os.macosx,
|
||||||
|
builtin.Os.freebsd,
|
||||||
=> return await (async writeFileModeThread(loop, path, contents, mode) catch unreachable),
|
=> return await (async writeFileModeThread(loop, path, contents, mode) catch unreachable),
|
||||||
builtin.Os.windows => return await (async writeFileWindows(loop, path, contents) catch unreachable),
|
builtin.Os.windows => return await (async writeFileWindows(loop, path, contents) catch unreachable),
|
||||||
else => @compileError("Unsupported OS"),
|
else => @compileError("Unsupported OS"),
|
||||||
|
@ -704,7 +712,7 @@ pub fn Watch(comptime V: type) type {
|
||||||
os_data: OsData,
|
os_data: OsData,
|
||||||
|
|
||||||
const OsData = switch (builtin.os) {
|
const OsData = switch (builtin.os) {
|
||||||
builtin.Os.macosx => struct {
|
builtin.Os.macosx, builtin.Os.freebsd => struct {
|
||||||
file_table: FileTable,
|
file_table: FileTable,
|
||||||
table_lock: event.Lock,
|
table_lock: event.Lock,
|
||||||
|
|
||||||
|
@ -793,7 +801,7 @@ pub fn Watch(comptime V: type) type {
|
||||||
return self;
|
return self;
|
||||||
},
|
},
|
||||||
|
|
||||||
builtin.Os.macosx => {
|
builtin.Os.macosx, builtin.Os.freebsd => {
|
||||||
const self = try loop.allocator.createOne(Self);
|
const self = try loop.allocator.createOne(Self);
|
||||||
errdefer loop.allocator.destroy(self);
|
errdefer loop.allocator.destroy(self);
|
||||||
|
|
||||||
|
@ -813,7 +821,7 @@ pub fn Watch(comptime V: type) type {
|
||||||
/// All addFile calls and removeFile calls must have completed.
|
/// All addFile calls and removeFile calls must have completed.
|
||||||
pub fn destroy(self: *Self) void {
|
pub fn destroy(self: *Self) void {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
builtin.Os.macosx => {
|
builtin.Os.macosx, builtin.Os.freebsd => {
|
||||||
// TODO we need to cancel the coroutines before destroying the lock
|
// TODO we need to cancel the coroutines before destroying the lock
|
||||||
self.os_data.table_lock.deinit();
|
self.os_data.table_lock.deinit();
|
||||||
var it = self.os_data.file_table.iterator();
|
var it = self.os_data.file_table.iterator();
|
||||||
|
@ -855,14 +863,14 @@ pub fn Watch(comptime V: type) type {
|
||||||
|
|
||||||
pub async fn addFile(self: *Self, file_path: []const u8, value: V) !?V {
|
pub async fn addFile(self: *Self, file_path: []const u8, value: V) !?V {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
builtin.Os.macosx => return await (async addFileMacosx(self, file_path, value) catch unreachable),
|
builtin.Os.macosx, builtin.Os.freebsd => return await (async addFileKEvent(self, file_path, value) catch unreachable),
|
||||||
builtin.Os.linux => return await (async addFileLinux(self, file_path, value) catch unreachable),
|
builtin.Os.linux => return await (async addFileLinux(self, file_path, value) catch unreachable),
|
||||||
builtin.Os.windows => return await (async addFileWindows(self, file_path, value) catch unreachable),
|
builtin.Os.windows => return await (async addFileWindows(self, file_path, value) catch unreachable),
|
||||||
else => @compileError("Unsupported OS"),
|
else => @compileError("Unsupported OS"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn addFileMacosx(self: *Self, file_path: []const u8, value: V) !?V {
|
async fn addFileKEvent(self: *Self, file_path: []const u8, value: V) !?V {
|
||||||
const resolved_path = try os.path.resolve(self.channel.loop.allocator, file_path);
|
const resolved_path = try os.path.resolve(self.channel.loop.allocator, file_path);
|
||||||
var resolved_path_consumed = false;
|
var resolved_path_consumed = false;
|
||||||
defer if (!resolved_path_consumed) self.channel.loop.allocator.free(resolved_path);
|
defer if (!resolved_path_consumed) self.channel.loop.allocator.free(resolved_path);
|
||||||
|
@ -871,7 +879,10 @@ pub fn Watch(comptime V: type) type {
|
||||||
var close_op_consumed = false;
|
var close_op_consumed = false;
|
||||||
defer if (!close_op_consumed) close_op.finish();
|
defer if (!close_op_consumed) close_op.finish();
|
||||||
|
|
||||||
const flags = posix.O_SYMLINK | posix.O_EVTONLY;
|
const flags = switch (builtin.os) {
|
||||||
|
builtin.Os.macosx => posix.O_SYMLINK | posix.O_EVTONLY,
|
||||||
|
else => 0,
|
||||||
|
};
|
||||||
const mode = 0;
|
const mode = 0;
|
||||||
const fd = try await (async openPosix(self.channel.loop, resolved_path, flags, mode) catch unreachable);
|
const fd = try await (async openPosix(self.channel.loop, resolved_path, flags, mode) catch unreachable);
|
||||||
close_op.setHandle(fd);
|
close_op.setHandle(fd);
|
||||||
|
|
|
@ -39,18 +39,22 @@ pub fn InStream(comptime ReadError: type) type {
|
||||||
if (amt_read < buf.len) return error.EndOfStream;
|
if (amt_read < buf.len) return error.EndOfStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn readIntLe(self: *Self, comptime T: type) !T {
|
pub async fn readIntLittle(self: *Self, comptime T: type) !T {
|
||||||
return await (async self.readInt(builtin.Endian.Little, T) catch unreachable);
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
|
try await (async self.readNoEof(bytes[0..]) catch unreachable);
|
||||||
|
return mem.readIntLittle(T, &bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn readIntBe(self: *Self, comptime T: type) !T {
|
pub async fn readIntBe(self: *Self, comptime T: type) !T {
|
||||||
return await (async self.readInt(builtin.Endian.Big, T) catch unreachable);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T {
|
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
try await (async self.readNoEof(bytes[0..]) catch unreachable);
|
try await (async self.readNoEof(bytes[0..]) catch unreachable);
|
||||||
return mem.readInt(bytes, T, endian);
|
return mem.readIntBig(T, &bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
|
||||||
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
|
try await (async self.readNoEof(bytes[0..]) catch unreachable);
|
||||||
|
return mem.readInt(T, &bytes, endian);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn readStruct(self: *Self, comptime T: type) !T {
|
pub async fn readStruct(self: *Self, comptime T: type) !T {
|
||||||
|
|
|
@ -49,7 +49,7 @@ pub const Loop = struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const EventFd = switch (builtin.os) {
|
pub const EventFd = switch (builtin.os) {
|
||||||
builtin.Os.macosx => MacOsEventFd,
|
builtin.Os.macosx, builtin.Os.freebsd => KEventFd,
|
||||||
builtin.Os.linux => struct {
|
builtin.Os.linux => struct {
|
||||||
base: ResumeNode,
|
base: ResumeNode,
|
||||||
epoll_op: u32,
|
epoll_op: u32,
|
||||||
|
@ -62,13 +62,13 @@ pub const Loop = struct {
|
||||||
else => @compileError("unsupported OS"),
|
else => @compileError("unsupported OS"),
|
||||||
};
|
};
|
||||||
|
|
||||||
const MacOsEventFd = struct {
|
const KEventFd = struct {
|
||||||
base: ResumeNode,
|
base: ResumeNode,
|
||||||
kevent: posix.Kevent,
|
kevent: posix.Kevent,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Basic = switch (builtin.os) {
|
pub const Basic = switch (builtin.os) {
|
||||||
builtin.Os.macosx => MacOsBasic,
|
builtin.Os.macosx, builtin.Os.freebsd => KEventBasic,
|
||||||
builtin.Os.linux => struct {
|
builtin.Os.linux => struct {
|
||||||
base: ResumeNode,
|
base: ResumeNode,
|
||||||
},
|
},
|
||||||
|
@ -78,7 +78,7 @@ pub const Loop = struct {
|
||||||
else => @compileError("unsupported OS"),
|
else => @compileError("unsupported OS"),
|
||||||
};
|
};
|
||||||
|
|
||||||
const MacOsBasic = struct {
|
const KEventBasic = struct {
|
||||||
base: ResumeNode,
|
base: ResumeNode,
|
||||||
kev: posix.Kevent,
|
kev: posix.Kevent,
|
||||||
};
|
};
|
||||||
|
@ -214,7 +214,7 @@ pub const Loop = struct {
|
||||||
self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun);
|
self.extra_threads[extra_thread_index] = try os.spawnThread(self, workerRun);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
builtin.Os.macosx => {
|
builtin.Os.macosx, builtin.Os.freebsd => {
|
||||||
self.os_data.kqfd = try os.bsdKQueue();
|
self.os_data.kqfd = try os.bsdKQueue();
|
||||||
errdefer os.close(self.os_data.kqfd);
|
errdefer os.close(self.os_data.kqfd);
|
||||||
|
|
||||||
|
@ -369,7 +369,7 @@ pub const Loop = struct {
|
||||||
os.close(self.os_data.epollfd);
|
os.close(self.os_data.epollfd);
|
||||||
self.allocator.free(self.eventfd_resume_nodes);
|
self.allocator.free(self.eventfd_resume_nodes);
|
||||||
},
|
},
|
||||||
builtin.Os.macosx => {
|
builtin.Os.macosx, builtin.Os.freebsd => {
|
||||||
os.close(self.os_data.kqfd);
|
os.close(self.os_data.kqfd);
|
||||||
os.close(self.os_data.fs_kqfd);
|
os.close(self.os_data.fs_kqfd);
|
||||||
},
|
},
|
||||||
|
@ -484,7 +484,7 @@ pub const Loop = struct {
|
||||||
const eventfd_node = &resume_stack_node.data;
|
const eventfd_node = &resume_stack_node.data;
|
||||||
eventfd_node.base.handle = next_tick_node.data;
|
eventfd_node.base.handle = next_tick_node.data;
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
builtin.Os.macosx => {
|
builtin.Os.macosx, builtin.Os.freebsd => {
|
||||||
const kevent_array = (*[1]posix.Kevent)(&eventfd_node.kevent);
|
const kevent_array = (*[1]posix.Kevent)(&eventfd_node.kevent);
|
||||||
const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
|
const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
|
||||||
_ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch {
|
_ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch {
|
||||||
|
@ -546,6 +546,7 @@ pub const Loop = struct {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
builtin.Os.linux,
|
builtin.Os.linux,
|
||||||
builtin.Os.macosx,
|
builtin.Os.macosx,
|
||||||
|
builtin.Os.freebsd,
|
||||||
=> self.os_data.fs_thread.wait(),
|
=> self.os_data.fs_thread.wait(),
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
|
@ -610,7 +611,7 @@ pub const Loop = struct {
|
||||||
os.posixWrite(self.os_data.final_eventfd, wakeup_bytes) catch unreachable;
|
os.posixWrite(self.os_data.final_eventfd, wakeup_bytes) catch unreachable;
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
builtin.Os.macosx => {
|
builtin.Os.macosx, builtin.Os.freebsd => {
|
||||||
self.posixFsRequest(&self.os_data.fs_end_request);
|
self.posixFsRequest(&self.os_data.fs_end_request);
|
||||||
const final_kevent = (*[1]posix.Kevent)(&self.os_data.final_kevent);
|
const final_kevent = (*[1]posix.Kevent)(&self.os_data.final_kevent);
|
||||||
const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
|
const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
|
||||||
|
@ -668,7 +669,7 @@ pub const Loop = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
builtin.Os.macosx => {
|
builtin.Os.macosx, builtin.Os.freebsd => {
|
||||||
var eventlist: [1]posix.Kevent = undefined;
|
var eventlist: [1]posix.Kevent = undefined;
|
||||||
const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
|
const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
|
||||||
const count = os.bsdKEvent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable;
|
const count = os.bsdKEvent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable;
|
||||||
|
@ -731,7 +732,7 @@ pub const Loop = struct {
|
||||||
self.beginOneEvent(); // finished in posixFsRun after processing the msg
|
self.beginOneEvent(); // finished in posixFsRun after processing the msg
|
||||||
self.os_data.fs_queue.put(request_node);
|
self.os_data.fs_queue.put(request_node);
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
builtin.Os.macosx => {
|
builtin.Os.macosx, builtin.Os.freebsd => {
|
||||||
const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wake);
|
const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wake);
|
||||||
const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
|
const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
|
||||||
_ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable;
|
_ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable;
|
||||||
|
@ -801,7 +802,7 @@ pub const Loop = struct {
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
builtin.Os.macosx => {
|
builtin.Os.macosx, builtin.Os.freebsd => {
|
||||||
const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wait);
|
const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wait);
|
||||||
var out_kevs: [1]posix.Kevent = undefined;
|
var out_kevs: [1]posix.Kevent = undefined;
|
||||||
_ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable;
|
_ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable;
|
||||||
|
@ -813,7 +814,7 @@ pub const Loop = struct {
|
||||||
|
|
||||||
const OsData = switch (builtin.os) {
|
const OsData = switch (builtin.os) {
|
||||||
builtin.Os.linux => LinuxOsData,
|
builtin.Os.linux => LinuxOsData,
|
||||||
builtin.Os.macosx => MacOsData,
|
builtin.Os.macosx, builtin.Os.freebsd => KEventData,
|
||||||
builtin.Os.windows => struct {
|
builtin.Os.windows => struct {
|
||||||
io_port: windows.HANDLE,
|
io_port: windows.HANDLE,
|
||||||
extra_thread_count: usize,
|
extra_thread_count: usize,
|
||||||
|
@ -821,7 +822,7 @@ pub const Loop = struct {
|
||||||
else => struct {},
|
else => struct {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const MacOsData = struct {
|
const KEventData = struct {
|
||||||
kqfd: i32,
|
kqfd: i32,
|
||||||
final_kevent: posix.Kevent,
|
final_kevent: posix.Kevent,
|
||||||
fs_kevent_wake: posix.Kevent,
|
fs_kevent_wake: posix.Kevent,
|
||||||
|
|
|
@ -2,6 +2,7 @@ const std = @import("../index.zig");
|
||||||
const math = std.math;
|
const math = std.math;
|
||||||
const debug = std.debug;
|
const debug = std.debug;
|
||||||
const assert = debug.assert;
|
const assert = debug.assert;
|
||||||
|
const assertError = debug.assertError;
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const errol = @import("errol/index.zig");
|
const errol = @import("errol/index.zig");
|
||||||
|
@ -116,7 +117,7 @@ pub fn formatType(
|
||||||
return output(context, @errorName(value));
|
return output(context, @errorName(value));
|
||||||
}
|
}
|
||||||
switch (@typeInfo(T)) {
|
switch (@typeInfo(T)) {
|
||||||
builtin.TypeId.Int, builtin.TypeId.Float => {
|
builtin.TypeId.ComptimeInt, builtin.TypeId.Int, builtin.TypeId.Float => {
|
||||||
return formatValue(value, fmt, context, Errors, output);
|
return formatValue(value, fmt, context, Errors, output);
|
||||||
},
|
},
|
||||||
builtin.TypeId.Void => {
|
builtin.TypeId.Void => {
|
||||||
|
@ -242,6 +243,9 @@ pub fn formatType(
|
||||||
}
|
}
|
||||||
return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));
|
return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));
|
||||||
},
|
},
|
||||||
|
builtin.TypeId.Fn => {
|
||||||
|
return format(context, Errors, output, "{}@{x}", @typeName(T), @ptrToInt(value));
|
||||||
|
},
|
||||||
else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
|
else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,11 +271,15 @@ fn formatValue(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
comptime var T = @typeOf(value);
|
const T = @typeOf(value);
|
||||||
switch (@typeId(T)) {
|
switch (@typeId(T)) {
|
||||||
builtin.TypeId.Float => return formatFloatValue(value, fmt, context, Errors, output),
|
builtin.TypeId.Float => return formatFloatValue(value, fmt, context, Errors, output),
|
||||||
builtin.TypeId.Int => return formatIntValue(value, fmt, context, Errors, output),
|
builtin.TypeId.Int => return formatIntValue(value, fmt, context, Errors, output),
|
||||||
else => unreachable,
|
builtin.TypeId.ComptimeInt => {
|
||||||
|
const Int = math.IntFittingRange(value, value);
|
||||||
|
return formatIntValue(Int(value), fmt, context, Errors, output);
|
||||||
|
},
|
||||||
|
else => comptime unreachable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,9 +296,10 @@ pub fn formatIntValue(
|
||||||
if (fmt.len > 0) {
|
if (fmt.len > 0) {
|
||||||
switch (fmt[0]) {
|
switch (fmt[0]) {
|
||||||
'c' => {
|
'c' => {
|
||||||
if (@typeOf(value) == u8) {
|
if (@typeOf(value).bit_count <= 8) {
|
||||||
if (fmt.len > 1) @compileError("Unknown format character: " ++ []u8{fmt[1]});
|
if (fmt.len > 1)
|
||||||
return formatAsciiChar(value, context, Errors, output);
|
@compileError("Unknown format character: " ++ []u8{fmt[1]});
|
||||||
|
return formatAsciiChar(u8(value), context, Errors, output);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'b' => {
|
'b' => {
|
||||||
|
@ -811,13 +820,41 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned
|
||||||
|
|
||||||
for (buf) |c| {
|
for (buf) |c| {
|
||||||
const digit = try charToDigit(c, radix);
|
const digit = try charToDigit(c, radix);
|
||||||
x = try math.mul(T, x, radix);
|
|
||||||
x = try math.add(T, x, digit);
|
if (x != 0) x = try math.mul(T, x, try math.cast(T, radix));
|
||||||
|
x = try math.add(T, x, try math.cast(T, digit));
|
||||||
}
|
}
|
||||||
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "parseUnsigned" {
|
||||||
|
assert((try parseUnsigned(u16, "050124", 10)) == 50124);
|
||||||
|
assert((try parseUnsigned(u16, "65535", 10)) == 65535);
|
||||||
|
assertError(parseUnsigned(u16, "65536", 10), error.Overflow);
|
||||||
|
|
||||||
|
assert((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);
|
||||||
|
assertError(parseUnsigned(u64, "10000000000000000", 16), error.Overflow);
|
||||||
|
|
||||||
|
assert((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF);
|
||||||
|
|
||||||
|
assert((try parseUnsigned(u7, "1", 10)) == 1);
|
||||||
|
assert((try parseUnsigned(u7, "1000", 2)) == 8);
|
||||||
|
|
||||||
|
assertError(parseUnsigned(u32, "f", 10), error.InvalidCharacter);
|
||||||
|
assertError(parseUnsigned(u8, "109", 8), error.InvalidCharacter);
|
||||||
|
|
||||||
|
assert((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747);
|
||||||
|
|
||||||
|
// these numbers should fit even though the radix itself doesn't fit in the destination type
|
||||||
|
assert((try parseUnsigned(u1, "0", 10)) == 0);
|
||||||
|
assert((try parseUnsigned(u1, "1", 10)) == 1);
|
||||||
|
assertError(parseUnsigned(u1, "2", 10), error.Overflow);
|
||||||
|
assert((try parseUnsigned(u1, "001", 16)) == 1);
|
||||||
|
assert((try parseUnsigned(u2, "3", 16)) == 3);
|
||||||
|
assertError(parseUnsigned(u2, "4", 16), error.Overflow);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
|
pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
|
||||||
const value = switch (c) {
|
const value = switch (c) {
|
||||||
'0'...'9' => c - '0',
|
'0'...'9' => c - '0',
|
||||||
|
@ -935,6 +972,25 @@ test "fmt.format" {
|
||||||
const value: u8 = 0b1100;
|
const value: u8 = 0b1100;
|
||||||
try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", value);
|
try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", value);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
var buf1: [32]u8 = undefined;
|
||||||
|
var context = BufPrintContext{ .remaining = buf1[0..] };
|
||||||
|
try formatType(1234, "", &context, error{BufferTooSmall}, bufPrintWrite);
|
||||||
|
var res = buf1[0 .. buf1.len - context.remaining.len];
|
||||||
|
assert(mem.eql(u8, res, "1234"));
|
||||||
|
|
||||||
|
context = BufPrintContext{ .remaining = buf1[0..] };
|
||||||
|
try formatType('a', "c", &context, error{BufferTooSmall}, bufPrintWrite);
|
||||||
|
res = buf1[0 .. buf1.len - context.remaining.len];
|
||||||
|
debug.warn("{}\n", res);
|
||||||
|
assert(mem.eql(u8, res, "a"));
|
||||||
|
|
||||||
|
context = BufPrintContext{ .remaining = buf1[0..] };
|
||||||
|
try formatType(0b1100, "b", &context, error{BufferTooSmall}, bufPrintWrite);
|
||||||
|
res = buf1[0 .. buf1.len - context.remaining.len];
|
||||||
|
debug.warn("{}\n", res);
|
||||||
|
assert(mem.eql(u8, res, "1100"));
|
||||||
|
}
|
||||||
{
|
{
|
||||||
const value: [3]u8 = "abc";
|
const value: [3]u8 = "abc";
|
||||||
try testFmt("array: abc\n", "array: {}\n", value);
|
try testFmt("array: abc\n", "array: {}\n", value);
|
||||||
|
@ -956,6 +1012,14 @@ test "fmt.format" {
|
||||||
try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", value);
|
try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", value);
|
||||||
try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", value);
|
try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", value);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
const value = @intToPtr(fn () void, 0xdeadbeef);
|
||||||
|
try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const value = @intToPtr(fn () void, 0xdeadbeef);
|
||||||
|
try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value);
|
||||||
|
}
|
||||||
try testFmt("buf: Test \n", "buf: {s5}\n", "Test");
|
try testFmt("buf: Test \n", "buf: {s5}\n", "Test");
|
||||||
try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test");
|
try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test");
|
||||||
try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C");
|
try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C");
|
||||||
|
|
|
@ -42,8 +42,8 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
|
||||||
pub fn init(key: []const u8) Self {
|
pub fn init(key: []const u8) Self {
|
||||||
debug.assert(key.len >= 16);
|
debug.assert(key.len >= 16);
|
||||||
|
|
||||||
const k0 = mem.readInt(key[0..8], u64, Endian.Little);
|
const k0 = mem.readIntSliceLittle(u64, key[0..8]);
|
||||||
const k1 = mem.readInt(key[8..16], u64, Endian.Little);
|
const k1 = mem.readIntSliceLittle(u64, key[8..16]);
|
||||||
|
|
||||||
var d = Self{
|
var d = Self{
|
||||||
.v0 = k0 ^ 0x736f6d6570736575,
|
.v0 = k0 ^ 0x736f6d6570736575,
|
||||||
|
@ -121,7 +121,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
|
||||||
fn round(d: *Self, b: []const u8) void {
|
fn round(d: *Self, b: []const u8) void {
|
||||||
debug.assert(b.len == 8);
|
debug.assert(b.len == 8);
|
||||||
|
|
||||||
const m = mem.readInt(b[0..], u64, Endian.Little);
|
const m = mem.readIntSliceLittle(u64, b[0..]);
|
||||||
d.v3 ^= m;
|
d.v3 ^= m;
|
||||||
|
|
||||||
comptime var i: usize = 0;
|
comptime var i: usize = 0;
|
||||||
|
@ -162,7 +162,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
|
||||||
const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";
|
const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";
|
||||||
|
|
||||||
test "siphash64-2-4 sanity" {
|
test "siphash64-2-4 sanity" {
|
||||||
const vectors = [][]const u8{
|
const vectors = [][8]u8{
|
||||||
"\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // ""
|
"\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // ""
|
||||||
"\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00"
|
"\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00"
|
||||||
"\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc
|
"\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc
|
||||||
|
@ -235,13 +235,13 @@ test "siphash64-2-4 sanity" {
|
||||||
for (vectors) |vector, i| {
|
for (vectors) |vector, i| {
|
||||||
buffer[i] = @intCast(u8, i);
|
buffer[i] = @intCast(u8, i);
|
||||||
|
|
||||||
const expected = mem.readInt(vector, u64, Endian.Little);
|
const expected = mem.readIntLittle(u64, &vector);
|
||||||
debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
|
debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "siphash128-2-4 sanity" {
|
test "siphash128-2-4 sanity" {
|
||||||
const vectors = [][]const u8{
|
const vectors = [][16]u8{
|
||||||
"\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93",
|
"\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93",
|
||||||
"\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45",
|
"\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45",
|
||||||
"\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4",
|
"\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" {
|
||||||
for (vectors) |vector, i| {
|
for (vectors) |vector, i| {
|
||||||
buffer[i] = @intCast(u8, i);
|
buffer[i] = @intCast(u8, i);
|
||||||
|
|
||||||
const expected = mem.readInt(vector, u128, Endian.Little);
|
const expected = mem.readIntLittle(u128, &vector);
|
||||||
debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
|
debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,6 +126,14 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn getOrPutValue(self: *Self, key: K, value: V) !*KV {
|
||||||
|
const res = try self.getOrPut(key);
|
||||||
|
if (!res.found_existing)
|
||||||
|
res.kv.value = value;
|
||||||
|
|
||||||
|
return res.kv;
|
||||||
|
}
|
||||||
|
|
||||||
fn ensureCapacity(self: *Self) !void {
|
fn ensureCapacity(self: *Self) !void {
|
||||||
if (self.entries.len == 0) {
|
if (self.entries.len == 0) {
|
||||||
return self.initCapacity(16);
|
return self.initCapacity(16);
|
||||||
|
@ -354,6 +362,12 @@ test "basic hash map usage" {
|
||||||
gop2.kv.value = 42;
|
gop2.kv.value = 42;
|
||||||
assert(map.get(99).?.value == 42);
|
assert(map.get(99).?.value == 42);
|
||||||
|
|
||||||
|
const gop3 = try map.getOrPutValue(5, 5);
|
||||||
|
assert(gop3.value == 77);
|
||||||
|
|
||||||
|
const gop4 = try map.getOrPutValue(100, 41);
|
||||||
|
assert(gop4.value == 41);
|
||||||
|
|
||||||
assert(map.contains(2));
|
assert(map.contains(2));
|
||||||
assert(map.get(2).?.value == 22);
|
assert(map.get(2).?.value == 22);
|
||||||
_ = map.remove(2);
|
_ = map.remove(2);
|
||||||
|
|
|
@ -66,11 +66,11 @@ pub const DirectAllocator = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 {
|
fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 {
|
||||||
const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
|
const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
|
||||||
|
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
Os.linux, Os.macosx, Os.ios => {
|
Os.linux, Os.macosx, Os.ios, Os.freebsd => {
|
||||||
const p = os.posix;
|
const p = os.posix;
|
||||||
const alloc_size = if (alignment <= os.page_size) n else n + alignment;
|
const alloc_size = if (alignment <= os.page_size) n else n + alignment;
|
||||||
const addr = p.mmap(null, alloc_size, p.PROT_READ | p.PROT_WRITE, p.MAP_PRIVATE | p.MAP_ANONYMOUS, -1, 0);
|
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 {
|
||||||
const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
|
const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
|
||||||
|
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
Os.linux, Os.macosx, Os.ios => {
|
Os.linux, Os.macosx, Os.ios, Os.freebsd => {
|
||||||
if (new_size <= old_mem.len) {
|
if (new_size <= old_mem.len) {
|
||||||
const base_addr = @ptrToInt(old_mem.ptr);
|
const base_addr = @ptrToInt(old_mem.ptr);
|
||||||
const old_addr_end = base_addr + old_mem.len;
|
const old_addr_end = base_addr + old_mem.len;
|
||||||
|
@ -166,7 +166,7 @@ pub const DirectAllocator = struct {
|
||||||
const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
|
const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
|
||||||
|
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
Os.linux, Os.macosx, Os.ios => {
|
Os.linux, Os.macosx, Os.ios, Os.freebsd => {
|
||||||
_ = os.posix.munmap(@ptrToInt(bytes.ptr), bytes.len);
|
_ = os.posix.munmap(@ptrToInt(bytes.ptr), bytes.len);
|
||||||
},
|
},
|
||||||
Os.windows => {
|
Os.windows => {
|
||||||
|
|
|
@ -58,6 +58,7 @@ test "std" {
|
||||||
_ = @import("segmented_list.zig");
|
_ = @import("segmented_list.zig");
|
||||||
_ = @import("spinlock.zig");
|
_ = @import("spinlock.zig");
|
||||||
|
|
||||||
|
_ = @import("dynamic_library.zig");
|
||||||
_ = @import("base64.zig");
|
_ = @import("base64.zig");
|
||||||
_ = @import("build.zig");
|
_ = @import("build.zig");
|
||||||
_ = @import("c/index.zig");
|
_ = @import("c/index.zig");
|
||||||
|
|
149
std/io.zig
149
std/io.zig
|
@ -32,6 +32,8 @@ pub fn getStdIn() GetStdIoErrs!File {
|
||||||
return File.openHandle(handle);
|
return File.openHandle(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;
|
||||||
|
|
||||||
pub fn InStream(comptime ReadError: type) type {
|
pub fn InStream(comptime ReadError: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
@ -150,35 +152,43 @@ pub fn InStream(comptime ReadError: type) type {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a native-endian integer
|
/// Reads a native-endian integer
|
||||||
pub fn readIntNe(self: *Self, comptime T: type) !T {
|
pub fn readIntNative(self: *Self, comptime T: type) !T {
|
||||||
return self.readInt(builtin.endian, T);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn readIntLe(self: *Self, comptime T: type) !T {
|
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
try self.readNoEof(bytes[0..]);
|
try self.readNoEof(bytes[0..]);
|
||||||
return mem.readIntLE(T, bytes);
|
return mem.readIntNative(T, &bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readIntBe(self: *Self, comptime T: type) !T {
|
/// Reads a foreign-endian integer
|
||||||
|
pub fn readIntForeign(self: *Self, comptime T: type) !T {
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
try self.readNoEof(bytes[0..]);
|
try self.readNoEof(bytes[0..]);
|
||||||
return mem.readIntBE(T, bytes);
|
return mem.readIntForeign(T, &bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T {
|
pub fn readIntLittle(self: *Self, comptime T: type) !T {
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
try self.readNoEof(bytes[0..]);
|
try self.readNoEof(bytes[0..]);
|
||||||
return mem.readInt(bytes, T, endian);
|
return mem.readIntLittle(T, &bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readVarInt(self: *Self, endian: builtin.Endian, comptime T: type, size: usize) !T {
|
pub fn readIntBig(self: *Self, comptime T: type) !T {
|
||||||
assert(size <= @sizeOf(T));
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
assert(size <= 8);
|
try self.readNoEof(bytes[0..]);
|
||||||
var input_buf: [8]u8 = undefined;
|
return mem.readIntBig(T, &bytes);
|
||||||
const input_slice = input_buf[0..size];
|
}
|
||||||
try self.readNoEof(input_slice);
|
|
||||||
return mem.readInt(input_slice, T, endian);
|
pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
|
||||||
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
|
try self.readNoEof(bytes[0..]);
|
||||||
|
return mem.readInt(T, &bytes, endian);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn readVarInt(self: *Self, comptime ReturnType: type, endian: builtin.Endian, size: usize) !ReturnType {
|
||||||
|
assert(size <= @sizeOf(ReturnType));
|
||||||
|
var bytes_buf: [@sizeOf(ReturnType)]u8 = undefined;
|
||||||
|
const bytes = bytes_buf[0..size];
|
||||||
|
try self.readNoEof(bytes);
|
||||||
|
return mem.readVarInt(ReturnType, bytes, endian);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn skipBytes(self: *Self, num_bytes: usize) !void {
|
pub fn skipBytes(self: *Self, num_bytes: usize) !void {
|
||||||
|
@ -227,25 +237,34 @@ pub fn OutStream(comptime WriteError: type) type {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write a native-endian integer.
|
/// Write a native-endian integer.
|
||||||
pub fn writeIntNe(self: *Self, comptime T: type, value: T) Error!void {
|
pub fn writeIntNative(self: *Self, comptime T: type, value: T) Error!void {
|
||||||
return self.writeInt(builtin.endian, T, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn writeIntLe(self: *Self, comptime T: type, value: T) Error!void {
|
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
mem.writeIntLE(T, &bytes, value);
|
mem.writeIntNative(T, &bytes, value);
|
||||||
return self.writeFn(self, bytes);
|
return self.writeFn(self, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn writeIntBe(self: *Self, comptime T: type, value: T) Error!void {
|
/// Write a foreign-endian integer.
|
||||||
|
pub fn writeIntForeign(self: *Self, comptime T: type, value: T) Error!void {
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
mem.writeIntBE(T, &bytes, value);
|
mem.writeIntForeign(T, &bytes, value);
|
||||||
return self.writeFn(self, bytes);
|
return self.writeFn(self, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn writeInt(self: *Self, endian: builtin.Endian, comptime T: type, value: T) Error!void {
|
pub fn writeIntLittle(self: *Self, comptime T: type, value: T) Error!void {
|
||||||
var bytes: [@sizeOf(T)]u8 = undefined;
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
mem.writeInt(bytes[0..], value, endian);
|
mem.writeIntLittle(T, &bytes, value);
|
||||||
|
return self.writeFn(self, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn writeIntBig(self: *Self, comptime T: type, value: T) Error!void {
|
||||||
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
|
mem.writeIntBig(T, &bytes, value);
|
||||||
|
return self.writeFn(self, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn writeInt(self: *Self, comptime T: type, value: T, endian: builtin.Endian) Error!void {
|
||||||
|
var bytes: [@sizeOf(T)]u8 = undefined;
|
||||||
|
mem.writeInt(T, &bytes, value, endian);
|
||||||
return self.writeFn(self, bytes);
|
return self.writeFn(self, bytes);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -683,25 +702,73 @@ test "import io tests" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readLine(buf: []u8) !usize {
|
pub fn readLine(buf: *std.Buffer) ![]u8 {
|
||||||
var stdin = getStdIn() catch return error.StdInUnavailable;
|
var stdin = try getStdIn();
|
||||||
var adapter = stdin.inStream();
|
var stdin_stream = stdin.inStream();
|
||||||
var stream = &adapter.stream;
|
return readLineFrom(&stdin_stream.stream, buf);
|
||||||
var index: usize = 0;
|
}
|
||||||
|
|
||||||
|
/// Reads all characters until the next newline into buf, and returns
|
||||||
|
/// a slice of the characters read (excluding the newline character(s)).
|
||||||
|
pub fn readLineFrom(stream: var, buf: *std.Buffer) ![]u8 {
|
||||||
|
const start = buf.len();
|
||||||
while (true) {
|
while (true) {
|
||||||
const byte = stream.readByte() catch return error.EndOfFile;
|
const byte = try stream.readByte();
|
||||||
switch (byte) {
|
switch (byte) {
|
||||||
'\r' => {
|
'\r' => {
|
||||||
// trash the following \n
|
// trash the following \n
|
||||||
_ = stream.readByte() catch return error.EndOfFile;
|
_ = try stream.readByte();
|
||||||
return index;
|
return buf.toSlice()[start..];
|
||||||
},
|
|
||||||
'\n' => return index,
|
|
||||||
else => {
|
|
||||||
if (index == buf.len) return error.InputTooLong;
|
|
||||||
buf[index] = byte;
|
|
||||||
index += 1;
|
|
||||||
},
|
},
|
||||||
|
'\n' => return buf.toSlice()[start..],
|
||||||
|
else => try buf.appendByte(byte),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "io.readLineFrom" {
|
||||||
|
var bytes: [128]u8 = undefined;
|
||||||
|
const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
|
||||||
|
|
||||||
|
var buf = try std.Buffer.initSize(allocator, 0);
|
||||||
|
var mem_stream = SliceInStream.init(
|
||||||
|
\\Line 1
|
||||||
|
\\Line 22
|
||||||
|
\\Line 333
|
||||||
|
);
|
||||||
|
const stream = &mem_stream.stream;
|
||||||
|
|
||||||
|
debug.assert(mem.eql(u8, "Line 1", try readLineFrom(stream, &buf)));
|
||||||
|
debug.assert(mem.eql(u8, "Line 22", try readLineFrom(stream, &buf)));
|
||||||
|
debug.assertError(readLineFrom(stream, &buf), error.EndOfStream);
|
||||||
|
debug.assert(mem.eql(u8, buf.toSlice(), "Line 1Line 22Line 333"));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn readLineSlice(slice: []u8) ![]u8 {
|
||||||
|
var stdin = try getStdIn();
|
||||||
|
var stdin_stream = stdin.inStream();
|
||||||
|
return readLineSliceFrom(&stdin_stream.stream, slice);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reads all characters until the next newline into slice, and returns
|
||||||
|
/// a slice of the characters read (excluding the newline character(s)).
|
||||||
|
pub fn readLineSliceFrom(stream: var, slice: []u8) ![]u8 {
|
||||||
|
// We cannot use Buffer.fromOwnedSlice, as it wants to append a null byte
|
||||||
|
// after taking ownership, which would always require an allocation.
|
||||||
|
var buf = std.Buffer{ .list = std.ArrayList(u8).fromOwnedSlice(debug.failing_allocator, slice) };
|
||||||
|
try buf.resize(0);
|
||||||
|
return try readLineFrom(stream, &buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "io.readLineSliceFrom" {
|
||||||
|
var buf: [7]u8 = undefined;
|
||||||
|
var mem_stream = SliceInStream.init(
|
||||||
|
\\Line 1
|
||||||
|
\\Line 22
|
||||||
|
\\Line 333
|
||||||
|
);
|
||||||
|
const stream = &mem_stream.stream;
|
||||||
|
|
||||||
|
debug.assert(mem.eql(u8, "Line 1", try readLineSliceFrom(stream, buf[0..])));
|
||||||
|
debug.assertError(readLineSliceFrom(stream, buf[0..]), error.OutOfMemory);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
const std = @import("../index.zig");
|
||||||
|
const InStream = std.io.InStream;
|
||||||
|
|
||||||
|
pub fn SeekableStream(comptime SeekErrorType: type, comptime GetSeekPosErrorType: type) type {
|
||||||
|
return struct {
|
||||||
|
const Self = @This();
|
||||||
|
pub const SeekError = SeekErrorType;
|
||||||
|
pub const GetSeekPosError = GetSeekPosErrorType;
|
||||||
|
|
||||||
|
seekToFn: fn (self: *Self, pos: usize) SeekError!void,
|
||||||
|
seekForwardFn: fn (self: *Self, pos: isize) SeekError!void,
|
||||||
|
|
||||||
|
getPosFn: fn (self: *Self) GetSeekPosError!usize,
|
||||||
|
getEndPosFn: fn (self: *Self) GetSeekPosError!usize,
|
||||||
|
|
||||||
|
pub fn seekTo(self: *Self, pos: usize) SeekError!void {
|
||||||
|
return self.seekToFn(self, pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn seekForward(self: *Self, amt: isize) SeekError!void {
|
||||||
|
return self.seekForwardFn(self, amt);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getEndPos(self: *Self) GetSeekPosError!usize {
|
||||||
|
return self.getEndPosFn(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getPos(self: *Self) GetSeekPosError!usize {
|
||||||
|
return self.getPosFn(self);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
27
std/json.zig
27
std/json.zig
|
@ -910,7 +910,7 @@ fn checkNext(p: *TokenStream, id: Token.Id) void {
|
||||||
debug.assert(token.id == id);
|
debug.assert(token.id == id);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "token" {
|
test "json.token" {
|
||||||
const s =
|
const s =
|
||||||
\\{
|
\\{
|
||||||
\\ "Image": {
|
\\ "Image": {
|
||||||
|
@ -980,7 +980,7 @@ pub fn validate(s: []const u8) bool {
|
||||||
return p.complete;
|
return p.complete;
|
||||||
}
|
}
|
||||||
|
|
||||||
test "json validate" {
|
test "json.validate" {
|
||||||
debug.assert(validate("{}"));
|
debug.assert(validate("{}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1188,7 +1188,7 @@ pub const Parser = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var value = p.stack.pop();
|
var value = p.stack.pop();
|
||||||
try p.pushToParent(value);
|
try p.pushToParent(&value);
|
||||||
},
|
},
|
||||||
Token.Id.String => {
|
Token.Id.String => {
|
||||||
try p.stack.append(try p.parseString(allocator, token, input, i));
|
try p.stack.append(try p.parseString(allocator, token, input, i));
|
||||||
|
@ -1251,7 +1251,7 @@ pub const Parser = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var value = p.stack.pop();
|
var value = p.stack.pop();
|
||||||
try p.pushToParent(value);
|
try p.pushToParent(&value);
|
||||||
},
|
},
|
||||||
Token.Id.ObjectBegin => {
|
Token.Id.ObjectBegin => {
|
||||||
try p.stack.append(Value{ .Object = ObjectMap.init(allocator) });
|
try p.stack.append(Value{ .Object = ObjectMap.init(allocator) });
|
||||||
|
@ -1312,19 +1312,19 @@ pub const Parser = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pushToParent(p: *Parser, value: Value) !void {
|
fn pushToParent(p: *Parser, value: *const Value) !void {
|
||||||
switch (p.stack.at(p.stack.len - 1)) {
|
switch (p.stack.toSlice()[p.stack.len - 1]) {
|
||||||
// Object Parent -> [ ..., object, <key>, value ]
|
// Object Parent -> [ ..., object, <key>, value ]
|
||||||
Value.String => |key| {
|
Value.String => |key| {
|
||||||
_ = p.stack.pop();
|
_ = p.stack.pop();
|
||||||
|
|
||||||
var object = &p.stack.items[p.stack.len - 1].Object;
|
var object = &p.stack.items[p.stack.len - 1].Object;
|
||||||
_ = try object.put(key, value);
|
_ = try object.put(key, value.*);
|
||||||
p.state = State.ObjectKey;
|
p.state = State.ObjectKey;
|
||||||
},
|
},
|
||||||
// Array Parent -> [ ..., <array>, value ]
|
// Array Parent -> [ ..., <array>, value ]
|
||||||
Value.Array => |*array| {
|
Value.Array => |*array| {
|
||||||
try array.append(value);
|
try array.append(value.*);
|
||||||
p.state = State.ArrayValue;
|
p.state = State.ArrayValue;
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
|
@ -1348,7 +1348,7 @@ pub const Parser = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
test "json parser dynamic" {
|
test "json.parser.dynamic" {
|
||||||
var p = Parser.init(debug.global_allocator, false);
|
var p = Parser.init(debug.global_allocator, false);
|
||||||
defer p.deinit();
|
defer p.deinit();
|
||||||
|
|
||||||
|
@ -1364,7 +1364,8 @@ test "json parser dynamic" {
|
||||||
\\ "Width": 100
|
\\ "Width": 100
|
||||||
\\ },
|
\\ },
|
||||||
\\ "Animated" : false,
|
\\ "Animated" : false,
|
||||||
\\ "IDs": [116, 943, 234, 38793]
|
\\ "IDs": [116, 943, 234, 38793],
|
||||||
|
\\ "ArrayOfObject": [{"n": "m"}]
|
||||||
\\ }
|
\\ }
|
||||||
\\}
|
\\}
|
||||||
;
|
;
|
||||||
|
@ -1387,4 +1388,10 @@ test "json parser dynamic" {
|
||||||
|
|
||||||
const animated = image.Object.get("Animated").?.value;
|
const animated = image.Object.get("Animated").?.value;
|
||||||
debug.assert(animated.Bool == false);
|
debug.assert(animated.Bool == false);
|
||||||
|
|
||||||
|
const array_of_object = image.Object.get("ArrayOfObject").?.value;
|
||||||
|
debug.assert(array_of_object.Array.len == 1);
|
||||||
|
|
||||||
|
const obj0 = array_of_object.Array.at(0).Object.get("n").?.value;
|
||||||
|
debug.assert(mem.eql(u8, obj0.String, "m"));
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -82,6 +82,28 @@ pub fn LinkedList(comptime T: type) type {
|
||||||
list.len += 1;
|
list.len += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Concatenate list2 onto the end of list1, removing all entries from the former.
|
||||||
|
///
|
||||||
|
/// Arguments:
|
||||||
|
/// list1: the list to concatenate onto
|
||||||
|
/// list2: the list to be concatenated
|
||||||
|
pub fn concatByMoving(list1: *Self, list2: *Self) void {
|
||||||
|
const l2_first = list2.first orelse return;
|
||||||
|
if (list1.last) |l1_last| {
|
||||||
|
l1_last.next = list2.first;
|
||||||
|
l2_first.prev = list1.last;
|
||||||
|
list1.len += list2.len;
|
||||||
|
} else {
|
||||||
|
// list1 was empty
|
||||||
|
list1.first = list2.first;
|
||||||
|
list1.len = list2.len;
|
||||||
|
}
|
||||||
|
list1.last = list2.last;
|
||||||
|
list2.first = null;
|
||||||
|
list2.last = null;
|
||||||
|
list2.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// Insert a new node at the end of the list.
|
/// Insert a new node at the end of the list.
|
||||||
///
|
///
|
||||||
/// Arguments:
|
/// Arguments:
|
||||||
|
@ -247,3 +269,77 @@ test "basic linked list test" {
|
||||||
assert(list.last.?.data == 4);
|
assert(list.last.?.data == 4);
|
||||||
assert(list.len == 2);
|
assert(list.len == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "linked list concatenation" {
|
||||||
|
const allocator = debug.global_allocator;
|
||||||
|
var list1 = LinkedList(u32).init();
|
||||||
|
var list2 = LinkedList(u32).init();
|
||||||
|
|
||||||
|
var one = try list1.createNode(1, allocator);
|
||||||
|
defer list1.destroyNode(one, allocator);
|
||||||
|
var two = try list1.createNode(2, allocator);
|
||||||
|
defer list1.destroyNode(two, allocator);
|
||||||
|
var three = try list1.createNode(3, allocator);
|
||||||
|
defer list1.destroyNode(three, allocator);
|
||||||
|
var four = try list1.createNode(4, allocator);
|
||||||
|
defer list1.destroyNode(four, allocator);
|
||||||
|
var five = try list1.createNode(5, allocator);
|
||||||
|
defer list1.destroyNode(five, allocator);
|
||||||
|
|
||||||
|
list1.append(one);
|
||||||
|
list1.append(two);
|
||||||
|
list2.append(three);
|
||||||
|
list2.append(four);
|
||||||
|
list2.append(five);
|
||||||
|
|
||||||
|
list1.concatByMoving(&list2);
|
||||||
|
|
||||||
|
assert(list1.last == five);
|
||||||
|
assert(list1.len == 5);
|
||||||
|
assert(list2.first == null);
|
||||||
|
assert(list2.last == null);
|
||||||
|
assert(list2.len == 0);
|
||||||
|
|
||||||
|
// Traverse forwards.
|
||||||
|
{
|
||||||
|
var it = list1.first;
|
||||||
|
var index: u32 = 1;
|
||||||
|
while (it) |node| : (it = node.next) {
|
||||||
|
assert(node.data == index);
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Traverse backwards.
|
||||||
|
{
|
||||||
|
var it = list1.last;
|
||||||
|
var index: u32 = 1;
|
||||||
|
while (it) |node| : (it = node.prev) {
|
||||||
|
assert(node.data == (6 - index));
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap them back, this verifies that concating to an empty list works.
|
||||||
|
list2.concatByMoving(&list1);
|
||||||
|
|
||||||
|
// Traverse forwards.
|
||||||
|
{
|
||||||
|
var it = list2.first;
|
||||||
|
var index: u32 = 1;
|
||||||
|
while (it) |node| : (it = node.next) {
|
||||||
|
assert(node.data == index);
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Traverse backwards.
|
||||||
|
{
|
||||||
|
var it = list2.last;
|
||||||
|
var index: u32 = 1;
|
||||||
|
while (it) |node| : (it = node.prev) {
|
||||||
|
assert(node.data == (6 - index));
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,13 @@ const assert = std.debug.assert;
|
||||||
pub const e = 2.71828182845904523536028747135266249775724709369995;
|
pub const e = 2.71828182845904523536028747135266249775724709369995;
|
||||||
pub const pi = 3.14159265358979323846264338327950288419716939937510;
|
pub const pi = 3.14159265358979323846264338327950288419716939937510;
|
||||||
|
|
||||||
|
// From a small c++ [program using boost float128](https://github.com/winksaville/cpp_boost_float128)
|
||||||
|
pub const f128_true_min = @bitCast(f128, u128(0x00000000000000000000000000000001));
|
||||||
|
pub const f128_min = @bitCast(f128, u128(0x00010000000000000000000000000000));
|
||||||
|
pub const f128_max = @bitCast(f128, u128(0x7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFF));
|
||||||
|
pub const f128_epsilon = @bitCast(f128, u128(0x3F8F0000000000000000000000000000));
|
||||||
|
pub const f128_toint = 1.0 / f128_epsilon;
|
||||||
|
|
||||||
// float.h details
|
// float.h details
|
||||||
pub const f64_true_min = 4.94065645841246544177e-324;
|
pub const f64_true_min = 4.94065645841246544177e-324;
|
||||||
pub const f64_min = 2.2250738585072014e-308;
|
pub const f64_min = 2.2250738585072014e-308;
|
||||||
|
@ -365,6 +372,69 @@ pub fn Log2Int(comptime T: type) type {
|
||||||
return @IntType(false, count);
|
return @IntType(false, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) type {
|
||||||
|
assert(from <= to);
|
||||||
|
if (from == 0 and to == 0) {
|
||||||
|
return u0;
|
||||||
|
}
|
||||||
|
const is_signed = from < 0;
|
||||||
|
const largest_positive_integer = max(if (from<0) (-from)-1 else from, to); // two's complement
|
||||||
|
const base = log2(largest_positive_integer);
|
||||||
|
const upper = (1 << base) - 1;
|
||||||
|
var magnitude_bits = if (upper >= largest_positive_integer) base else base + 1;
|
||||||
|
if (is_signed) {
|
||||||
|
magnitude_bits += 1;
|
||||||
|
}
|
||||||
|
return @IntType(is_signed, magnitude_bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "math.IntFittingRange" {
|
||||||
|
assert(IntFittingRange(0, 0) == u0);
|
||||||
|
assert(IntFittingRange(0, 1) == u1);
|
||||||
|
assert(IntFittingRange(0, 2) == u2);
|
||||||
|
assert(IntFittingRange(0, 3) == u2);
|
||||||
|
assert(IntFittingRange(0, 4) == u3);
|
||||||
|
assert(IntFittingRange(0, 7) == u3);
|
||||||
|
assert(IntFittingRange(0, 8) == u4);
|
||||||
|
assert(IntFittingRange(0, 9) == u4);
|
||||||
|
assert(IntFittingRange(0, 15) == u4);
|
||||||
|
assert(IntFittingRange(0, 16) == u5);
|
||||||
|
assert(IntFittingRange(0, 17) == u5);
|
||||||
|
assert(IntFittingRange(0, 4095) == u12);
|
||||||
|
assert(IntFittingRange(2000, 4095) == u12);
|
||||||
|
assert(IntFittingRange(0, 4096) == u13);
|
||||||
|
assert(IntFittingRange(2000, 4096) == u13);
|
||||||
|
assert(IntFittingRange(0, 4097) == u13);
|
||||||
|
assert(IntFittingRange(2000, 4097) == u13);
|
||||||
|
assert(IntFittingRange(0, 123456789123456798123456789) == u87);
|
||||||
|
assert(IntFittingRange(0, 123456789123456798123456789123456789123456798123456789) == u177);
|
||||||
|
|
||||||
|
assert(IntFittingRange(-1, -1) == i1);
|
||||||
|
assert(IntFittingRange(-1, 0) == i1);
|
||||||
|
assert(IntFittingRange(-1, 1) == i2);
|
||||||
|
assert(IntFittingRange(-2, -2) == i2);
|
||||||
|
assert(IntFittingRange(-2, -1) == i2);
|
||||||
|
assert(IntFittingRange(-2, 0) == i2);
|
||||||
|
assert(IntFittingRange(-2, 1) == i2);
|
||||||
|
assert(IntFittingRange(-2, 2) == i3);
|
||||||
|
assert(IntFittingRange(-1, 2) == i3);
|
||||||
|
assert(IntFittingRange(-1, 3) == i3);
|
||||||
|
assert(IntFittingRange(-1, 4) == i4);
|
||||||
|
assert(IntFittingRange(-1, 7) == i4);
|
||||||
|
assert(IntFittingRange(-1, 8) == i5);
|
||||||
|
assert(IntFittingRange(-1, 9) == i5);
|
||||||
|
assert(IntFittingRange(-1, 15) == i5);
|
||||||
|
assert(IntFittingRange(-1, 16) == i6);
|
||||||
|
assert(IntFittingRange(-1, 17) == i6);
|
||||||
|
assert(IntFittingRange(-1, 4095) == i13);
|
||||||
|
assert(IntFittingRange(-4096, 4095) == i13);
|
||||||
|
assert(IntFittingRange(-1, 4096) == i14);
|
||||||
|
assert(IntFittingRange(-4097, 4095) == i14);
|
||||||
|
assert(IntFittingRange(-1, 4097) == i14);
|
||||||
|
assert(IntFittingRange(-1, 123456789123456798123456789) == i88);
|
||||||
|
assert(IntFittingRange(-1, 123456789123456798123456789123456789123456798123456789) == i178);
|
||||||
|
}
|
||||||
|
|
||||||
test "math overflow functions" {
|
test "math overflow functions" {
|
||||||
testOverflow();
|
testOverflow();
|
||||||
comptime testOverflow();
|
comptime testOverflow();
|
||||||
|
|
459
std/mem.zig
459
std/mem.zig
|
@ -410,12 +410,8 @@ test "mem.indexOf" {
|
||||||
/// Reads an integer from memory with size equal to bytes.len.
|
/// Reads an integer from memory with size equal to bytes.len.
|
||||||
/// T specifies the return type, which must be large enough to store
|
/// T specifies the return type, which must be large enough to store
|
||||||
/// the result.
|
/// the result.
|
||||||
/// See also ::readIntBE or ::readIntLE.
|
pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: builtin.Endian) ReturnType {
|
||||||
pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T {
|
var result: ReturnType = 0;
|
||||||
if (T.bit_count == 8) {
|
|
||||||
return bytes[0];
|
|
||||||
}
|
|
||||||
var result: T = 0;
|
|
||||||
switch (endian) {
|
switch (endian) {
|
||||||
builtin.Endian.Big => {
|
builtin.Endian.Big => {
|
||||||
for (bytes) |b| {
|
for (bytes) |b| {
|
||||||
|
@ -423,172 +419,270 @@ pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
builtin.Endian.Little => {
|
builtin.Endian.Little => {
|
||||||
const ShiftType = math.Log2Int(T);
|
const ShiftType = math.Log2Int(ReturnType);
|
||||||
for (bytes) |b, index| {
|
for (bytes) |b, index| {
|
||||||
result = result | (T(b) << @intCast(ShiftType, index * 8));
|
result = result | (ReturnType(b) << @intCast(ShiftType, index * 8));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a big-endian int of type T from bytes.
|
/// Reads an integer from memory with bit count specified by T.
|
||||||
/// bytes.len must be exactly @sizeOf(T).
|
/// The bit count of T must be evenly divisible by 8.
|
||||||
pub fn readIntBE(comptime T: type, bytes: []const u8) T {
|
/// This function cannot fail and cannot cause undefined behavior.
|
||||||
if (T.is_signed) {
|
/// Assumes the endianness of memory is native. This means the function can
|
||||||
return @bitCast(T, readIntBE(@IntType(false, T.bit_count), bytes));
|
/// simply pointer cast memory.
|
||||||
}
|
pub fn readIntNative(comptime T: type, bytes: *const [@sizeOf(T)]u8) T {
|
||||||
assert(bytes.len == @sizeOf(T));
|
comptime assert(T.bit_count % 8 == 0);
|
||||||
if (T == u8) return bytes[0];
|
return @ptrCast(*align(1) const T, bytes).*;
|
||||||
var result: T = 0;
|
|
||||||
{
|
|
||||||
comptime var i = 0;
|
|
||||||
inline while (i < @sizeOf(T)) : (i += 1) {
|
|
||||||
result = (result << 8) | T(bytes[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a little-endian int of type T from bytes.
|
/// Reads an integer from memory with bit count specified by T.
|
||||||
/// bytes.len must be exactly @sizeOf(T).
|
/// The bit count of T must be evenly divisible by 8.
|
||||||
pub fn readIntLE(comptime T: type, bytes: []const u8) T {
|
/// This function cannot fail and cannot cause undefined behavior.
|
||||||
if (T.is_signed) {
|
/// Assumes the endianness of memory is foreign, so it must byte-swap.
|
||||||
return @bitCast(T, readIntLE(@IntType(false, T.bit_count), bytes));
|
pub fn readIntForeign(comptime T: type, bytes: *const [@sizeOf(T)]u8) T {
|
||||||
}
|
return @bswap(T, readIntNative(T, bytes));
|
||||||
assert(bytes.len == @sizeOf(T));
|
|
||||||
if (T == u8) return bytes[0];
|
|
||||||
var result: T = 0;
|
|
||||||
{
|
|
||||||
comptime var i = 0;
|
|
||||||
inline while (i < @sizeOf(T)) : (i += 1) {
|
|
||||||
result |= T(bytes[i]) << i * 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "readIntBE/LE" {
|
pub const readIntLittle = switch (builtin.endian) {
|
||||||
assert(readIntBE(u0, []u8{}) == 0x0);
|
builtin.Endian.Little => readIntNative,
|
||||||
assert(readIntLE(u0, []u8{}) == 0x0);
|
builtin.Endian.Big => readIntForeign,
|
||||||
|
};
|
||||||
|
|
||||||
assert(readIntBE(u8, []u8{0x32}) == 0x32);
|
pub const readIntBig = switch (builtin.endian) {
|
||||||
assert(readIntLE(u8, []u8{0x12}) == 0x12);
|
builtin.Endian.Little => readIntForeign,
|
||||||
|
builtin.Endian.Big => readIntNative,
|
||||||
|
};
|
||||||
|
|
||||||
assert(readIntBE(u16, []u8{0x12, 0x34}) == 0x1234);
|
/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0
|
||||||
assert(readIntLE(u16, []u8{0x12, 0x34}) == 0x3412);
|
/// and ignores extra bytes.
|
||||||
|
/// Note that @sizeOf(u24) is 3.
|
||||||
assert(readIntBE(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024);
|
/// The bit count of T must be evenly divisible by 8.
|
||||||
assert(readIntLE(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec);
|
/// Assumes the endianness of memory is native. This means the function can
|
||||||
|
/// simply pointer cast memory.
|
||||||
assert(readIntBE(i8, []u8{0xff}) == -1);
|
pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T {
|
||||||
assert(readIntLE(i8, []u8{0xfe}) == -2);
|
assert(@sizeOf(u24) == 3);
|
||||||
|
assert(bytes.len >= @sizeOf(T));
|
||||||
assert(readIntBE(i16, []u8{0xff, 0xfd}) == -3);
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
assert(readIntLE(i16, []u8{0xfc, 0xff}) == -4);
|
return readIntNative(T, @ptrCast(*const [@sizeOf(T)]u8, bytes.ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes an integer to memory with size equal to bytes.len. Pads with zeroes
|
/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0
|
||||||
/// to fill the entire buffer provided.
|
/// and ignores extra bytes.
|
||||||
/// value must be an integer.
|
/// Note that @sizeOf(u24) is 3.
|
||||||
pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void {
|
/// The bit count of T must be evenly divisible by 8.
|
||||||
const uint = @IntType(false, @typeOf(value).bit_count);
|
/// Assumes the endianness of memory is foreign, so it must byte-swap.
|
||||||
|
pub fn readIntSliceForeign(comptime T: type, bytes: []const u8) T {
|
||||||
|
return @bswap(T, readIntSliceNative(T, bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const readIntSliceLittle = switch (builtin.endian) {
|
||||||
|
builtin.Endian.Little => readIntSliceNative,
|
||||||
|
builtin.Endian.Big => readIntSliceForeign,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const readIntSliceBig = switch (builtin.endian) {
|
||||||
|
builtin.Endian.Little => readIntSliceForeign,
|
||||||
|
builtin.Endian.Big => readIntSliceNative,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Reads an integer from memory with bit count specified by T.
|
||||||
|
/// The bit count of T must be evenly divisible by 8.
|
||||||
|
/// This function cannot fail and cannot cause undefined behavior.
|
||||||
|
pub fn readInt(comptime T: type, bytes: *const [@sizeOf(T)]u8, endian: builtin.Endian) T {
|
||||||
|
if (endian == builtin.endian) {
|
||||||
|
return readIntNative(T, bytes);
|
||||||
|
} else {
|
||||||
|
return readIntForeign(T, bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Asserts that bytes.len >= @sizeOf(T). Reads the integer starting from index 0
|
||||||
|
/// and ignores extra bytes.
|
||||||
|
/// Note that @sizeOf(u24) is 3.
|
||||||
|
/// The bit count of T must be evenly divisible by 8.
|
||||||
|
pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T {
|
||||||
|
assert(@sizeOf(u24) == 3);
|
||||||
|
assert(bytes.len >= @sizeOf(T));
|
||||||
|
// TODO https://github.com/ziglang/zig/issues/863
|
||||||
|
return readInt(T, @ptrCast(*const [@sizeOf(T)]u8, bytes.ptr), endian);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "comptime read/write int" {
|
||||||
|
comptime {
|
||||||
|
var bytes: [2]u8 = undefined;
|
||||||
|
std.mem.writeIntLittle(u16, &bytes, 0x1234);
|
||||||
|
const result = std.mem.readIntBig(u16, &bytes);
|
||||||
|
std.debug.assert(result == 0x3412);
|
||||||
|
}
|
||||||
|
comptime {
|
||||||
|
var bytes: [2]u8 = undefined;
|
||||||
|
std.mem.writeIntBig(u16, &bytes, 0x1234);
|
||||||
|
const result = std.mem.readIntLittle(u16, &bytes);
|
||||||
|
std.debug.assert(result == 0x3412);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test "readIntBig and readIntLittle" {
|
||||||
|
assert(readIntSliceBig(u0, []u8{}) == 0x0);
|
||||||
|
assert(readIntSliceLittle(u0, []u8{}) == 0x0);
|
||||||
|
|
||||||
|
assert(readIntSliceBig(u8, []u8{0x32}) == 0x32);
|
||||||
|
assert(readIntSliceLittle(u8, []u8{0x12}) == 0x12);
|
||||||
|
|
||||||
|
assert(readIntSliceBig(u16, []u8{ 0x12, 0x34 }) == 0x1234);
|
||||||
|
assert(readIntSliceLittle(u16, []u8{ 0x12, 0x34 }) == 0x3412);
|
||||||
|
|
||||||
|
assert(readIntSliceBig(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024);
|
||||||
|
assert(readIntSliceLittle(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec);
|
||||||
|
|
||||||
|
assert(readIntSliceBig(i8, []u8{0xff}) == -1);
|
||||||
|
assert(readIntSliceLittle(i8, []u8{0xfe}) == -2);
|
||||||
|
|
||||||
|
assert(readIntSliceBig(i16, []u8{ 0xff, 0xfd }) == -3);
|
||||||
|
assert(readIntSliceLittle(i16, []u8{ 0xfc, 0xff }) == -4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes an integer to memory, storing it in twos-complement.
|
||||||
|
/// This function always succeeds, has defined behavior for all inputs, and
|
||||||
|
/// accepts any integer bit width.
|
||||||
|
/// This function stores in native endian, which means it is implemented as a simple
|
||||||
|
/// memory store.
|
||||||
|
pub fn writeIntNative(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
|
||||||
|
@ptrCast(*align(1) T, buf).* = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes an integer to memory, storing it in twos-complement.
|
||||||
|
/// This function always succeeds, has defined behavior for all inputs, but
|
||||||
|
/// the integer bit width must be divisible by 8.
|
||||||
|
/// This function stores in foreign endian, which means it does a @bswap first.
|
||||||
|
pub fn writeIntForeign(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
|
||||||
|
writeIntNative(T, buf, @bswap(T, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const writeIntLittle = switch (builtin.endian) {
|
||||||
|
builtin.Endian.Little => writeIntNative,
|
||||||
|
builtin.Endian.Big => writeIntForeign,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const writeIntBig = switch (builtin.endian) {
|
||||||
|
builtin.Endian.Little => writeIntForeign,
|
||||||
|
builtin.Endian.Big => writeIntNative,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Writes an integer to memory, storing it in twos-complement.
|
||||||
|
/// This function always succeeds, has defined behavior for all inputs, but
|
||||||
|
/// the integer bit width must be divisible by 8.
|
||||||
|
pub fn writeInt(comptime T: type, buffer: *[@sizeOf(T)]u8, value: T, endian: builtin.Endian) void {
|
||||||
|
comptime assert(T.bit_count % 8 == 0);
|
||||||
|
if (endian == builtin.endian) {
|
||||||
|
return writeIntNative(T, buffer, value);
|
||||||
|
} else {
|
||||||
|
return writeIntForeign(T, buffer, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes a twos-complement little-endian integer to memory.
|
||||||
|
/// Asserts that buf.len >= @sizeOf(T). Note that @sizeOf(u24) is 3.
|
||||||
|
/// The bit count of T must be divisible by 8.
|
||||||
|
/// Any extra bytes in buffer after writing the integer are set to zero. To
|
||||||
|
/// avoid the branch to check for extra buffer bytes, use writeIntLittle
|
||||||
|
/// instead.
|
||||||
|
pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {
|
||||||
|
comptime assert(@sizeOf(u24) == 3);
|
||||||
|
comptime assert(T.bit_count % 8 == 0);
|
||||||
|
assert(buffer.len >= @sizeOf(T));
|
||||||
|
|
||||||
|
// TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough
|
||||||
|
const uint = @IntType(false, T.bit_count);
|
||||||
var bits = @truncate(uint, value);
|
var bits = @truncate(uint, value);
|
||||||
|
for (buffer) |*b| {
|
||||||
|
b.* = @truncate(u8, bits);
|
||||||
|
bits >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes a twos-complement big-endian integer to memory.
|
||||||
|
/// Asserts that buffer.len >= @sizeOf(T). Note that @sizeOf(u24) is 3.
|
||||||
|
/// The bit count of T must be divisible by 8.
|
||||||
|
/// Any extra bytes in buffer before writing the integer are set to zero. To
|
||||||
|
/// avoid the branch to check for extra buffer bytes, use writeIntBig instead.
|
||||||
|
pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void {
|
||||||
|
comptime assert(@sizeOf(u24) == 3);
|
||||||
|
comptime assert(T.bit_count % 8 == 0);
|
||||||
|
assert(buffer.len >= @sizeOf(T));
|
||||||
|
|
||||||
|
// TODO I want to call writeIntBig here but comptime eval facilities aren't good enough
|
||||||
|
const uint = @IntType(false, T.bit_count);
|
||||||
|
var bits = @truncate(uint, value);
|
||||||
|
var index: usize = buffer.len;
|
||||||
|
while (index != 0) {
|
||||||
|
index -= 1;
|
||||||
|
buffer[index] = @truncate(u8, bits);
|
||||||
|
bits >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const writeIntSliceNative = switch (builtin.endian) {
|
||||||
|
builtin.Endian.Little => writeIntSliceLittle,
|
||||||
|
builtin.Endian.Big => writeIntSliceBig,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const writeIntSliceForeign = switch (builtin.endian) {
|
||||||
|
builtin.Endian.Little => writeIntSliceBig,
|
||||||
|
builtin.Endian.Big => writeIntSliceLittle,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Writes a twos-complement integer to memory, with the specified endianness.
|
||||||
|
/// Asserts that buf.len >= @sizeOf(T). Note that @sizeOf(u24) is 3.
|
||||||
|
/// The bit count of T must be evenly divisible by 8.
|
||||||
|
/// Any extra bytes in buffer not part of the integer are set to zero, with
|
||||||
|
/// respect to endianness. To avoid the branch to check for extra buffer bytes,
|
||||||
|
/// use writeInt instead.
|
||||||
|
pub fn writeIntSlice(comptime T: type, buffer: []u8, value: T, endian: builtin.Endian) void {
|
||||||
|
comptime assert(T.bit_count % 8 == 0);
|
||||||
switch (endian) {
|
switch (endian) {
|
||||||
builtin.Endian.Big => {
|
builtin.Endian.Little => return writeIntSliceLittle(T, buffer, value),
|
||||||
var index: usize = buf.len;
|
builtin.Endian.Big => return writeIntSliceBig(T, buffer, value),
|
||||||
while (index != 0) {
|
|
||||||
index -= 1;
|
|
||||||
|
|
||||||
buf[index] = @truncate(u8, bits);
|
|
||||||
bits >>= 8;
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
builtin.Endian.Little => {
|
|
||||||
for (buf) |*b| {
|
|
||||||
b.* = @truncate(u8, bits);
|
|
||||||
bits >>= 8;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
assert(bits == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn writeIntBE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
|
test "writeIntBig and writeIntLittle" {
|
||||||
assert(T.bit_count % 8 == 0);
|
|
||||||
const uint = @IntType(false, T.bit_count);
|
|
||||||
if (uint == u0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var bits = @bitCast(uint, value);
|
|
||||||
if (uint == u8) {
|
|
||||||
buf[0] = bits;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var index: usize = buf.len;
|
|
||||||
while (index != 0) {
|
|
||||||
index -= 1;
|
|
||||||
|
|
||||||
buf[index] = @truncate(u8, bits);
|
|
||||||
bits >>= 8;
|
|
||||||
}
|
|
||||||
assert(bits == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn writeIntLE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
|
|
||||||
assert(T.bit_count % 8 == 0);
|
|
||||||
const uint = @IntType(false, T.bit_count);
|
|
||||||
if (uint == u0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var bits = @bitCast(uint, value);
|
|
||||||
if (uint == u8) {
|
|
||||||
buf[0] = bits;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// FIXME: this should just be for (buf).
|
|
||||||
// See https://github.com/ziglang/zig/issues/1663
|
|
||||||
for (buf.*) |*b| {
|
|
||||||
b.* = @truncate(u8, bits);
|
|
||||||
bits >>= 8;
|
|
||||||
}
|
|
||||||
assert(bits == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "writeIntBE/LE" {
|
|
||||||
var buf0: [0]u8 = undefined;
|
var buf0: [0]u8 = undefined;
|
||||||
var buf1: [1]u8 = undefined;
|
var buf1: [1]u8 = undefined;
|
||||||
var buf2: [2]u8 = undefined;
|
var buf2: [2]u8 = undefined;
|
||||||
var buf9: [9]u8 = undefined;
|
var buf9: [9]u8 = undefined;
|
||||||
|
|
||||||
writeIntBE(u0, &buf0, 0x0);
|
writeIntBig(u0, &buf0, 0x0);
|
||||||
assert(eql_slice_u8(buf0[0..], []u8{}));
|
assert(eql_slice_u8(buf0[0..], []u8{}));
|
||||||
writeIntLE(u0, &buf0, 0x0);
|
writeIntLittle(u0, &buf0, 0x0);
|
||||||
assert(eql_slice_u8(buf0[0..], []u8{}));
|
assert(eql_slice_u8(buf0[0..], []u8{}));
|
||||||
|
|
||||||
writeIntBE(u8, &buf1, 0x12);
|
writeIntBig(u8, &buf1, 0x12);
|
||||||
assert(eql_slice_u8(buf1[0..], []u8{0x12}));
|
assert(eql_slice_u8(buf1[0..], []u8{0x12}));
|
||||||
writeIntLE(u8, &buf1, 0x34);
|
writeIntLittle(u8, &buf1, 0x34);
|
||||||
assert(eql_slice_u8(buf1[0..], []u8{0x34}));
|
assert(eql_slice_u8(buf1[0..], []u8{0x34}));
|
||||||
|
|
||||||
writeIntBE(u16, &buf2, 0x1234);
|
writeIntBig(u16, &buf2, 0x1234);
|
||||||
assert(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 }));
|
assert(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 }));
|
||||||
writeIntLE(u16, &buf2, 0x5678);
|
writeIntLittle(u16, &buf2, 0x5678);
|
||||||
assert(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 }));
|
assert(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 }));
|
||||||
|
|
||||||
writeIntBE(u72, &buf9, 0x123456789abcdef024);
|
writeIntBig(u72, &buf9, 0x123456789abcdef024);
|
||||||
assert(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }));
|
assert(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }));
|
||||||
writeIntLE(u72, &buf9, 0xfedcba9876543210ec);
|
writeIntLittle(u72, &buf9, 0xfedcba9876543210ec);
|
||||||
assert(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }));
|
assert(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }));
|
||||||
|
|
||||||
writeIntBE(i8, &buf1, -1);
|
writeIntBig(i8, &buf1, -1);
|
||||||
assert(eql_slice_u8(buf1[0..], []u8{0xff}));
|
assert(eql_slice_u8(buf1[0..], []u8{0xff}));
|
||||||
writeIntLE(i8, &buf1, -2);
|
writeIntLittle(i8, &buf1, -2);
|
||||||
assert(eql_slice_u8(buf1[0..], []u8{0xfe}));
|
assert(eql_slice_u8(buf1[0..], []u8{0xfe}));
|
||||||
|
|
||||||
writeIntBE(i16, &buf2, -3);
|
writeIntBig(i16, &buf2, -3);
|
||||||
assert(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd }));
|
assert(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd }));
|
||||||
writeIntLE(i16, &buf2, -4);
|
writeIntLittle(i16, &buf2, -4);
|
||||||
assert(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff }));
|
assert(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,12 +831,12 @@ fn testReadIntImpl() void {
|
||||||
0x56,
|
0x56,
|
||||||
0x78,
|
0x78,
|
||||||
};
|
};
|
||||||
assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678);
|
assert(readInt(u32, &bytes, builtin.Endian.Big) == 0x12345678);
|
||||||
assert(readIntBE(u32, bytes) == 0x12345678);
|
assert(readIntBig(u32, &bytes) == 0x12345678);
|
||||||
assert(readIntBE(i32, bytes) == 0x12345678);
|
assert(readIntBig(i32, &bytes) == 0x12345678);
|
||||||
assert(readInt(bytes, u32, builtin.Endian.Little) == 0x78563412);
|
assert(readInt(u32, &bytes, builtin.Endian.Little) == 0x78563412);
|
||||||
assert(readIntLE(u32, bytes) == 0x78563412);
|
assert(readIntLittle(u32, &bytes) == 0x78563412);
|
||||||
assert(readIntLE(i32, bytes) == 0x78563412);
|
assert(readIntLittle(i32, &bytes) == 0x78563412);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const buf = []u8{
|
const buf = []u8{
|
||||||
|
@ -751,7 +845,7 @@ fn testReadIntImpl() void {
|
||||||
0x12,
|
0x12,
|
||||||
0x34,
|
0x34,
|
||||||
};
|
};
|
||||||
const answer = readInt(buf, u64, builtin.Endian.Big);
|
const answer = readInt(u32, &buf, builtin.Endian.Big);
|
||||||
assert(answer == 0x00001234);
|
assert(answer == 0x00001234);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -761,7 +855,7 @@ fn testReadIntImpl() void {
|
||||||
0x00,
|
0x00,
|
||||||
0x00,
|
0x00,
|
||||||
};
|
};
|
||||||
const answer = readInt(buf, u64, builtin.Endian.Little);
|
const answer = readInt(u32, &buf, builtin.Endian.Little);
|
||||||
assert(answer == 0x00003412);
|
assert(answer == 0x00003412);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -769,21 +863,33 @@ fn testReadIntImpl() void {
|
||||||
0xff,
|
0xff,
|
||||||
0xfe,
|
0xfe,
|
||||||
};
|
};
|
||||||
assert(readIntBE(u16, bytes) == 0xfffe);
|
assert(readIntBig(u16, &bytes) == 0xfffe);
|
||||||
assert(readIntBE(i16, bytes) == -0x0002);
|
assert(readIntBig(i16, &bytes) == -0x0002);
|
||||||
assert(readIntLE(u16, bytes) == 0xfeff);
|
assert(readIntLittle(u16, &bytes) == 0xfeff);
|
||||||
assert(readIntLE(i16, bytes) == -0x0101);
|
assert(readIntLittle(i16, &bytes) == -0x0101);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "testWriteInt" {
|
test "std.mem.writeIntSlice" {
|
||||||
testWriteIntImpl();
|
testWriteIntImpl();
|
||||||
comptime testWriteIntImpl();
|
comptime testWriteIntImpl();
|
||||||
}
|
}
|
||||||
fn testWriteIntImpl() void {
|
fn testWriteIntImpl() void {
|
||||||
var bytes: [8]u8 = undefined;
|
var bytes: [8]u8 = undefined;
|
||||||
|
|
||||||
writeInt(bytes[0..], u64(0x12345678CAFEBABE), builtin.Endian.Big);
|
writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Big);
|
||||||
|
assert(eql(u8, bytes, []u8{
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
}));
|
||||||
|
|
||||||
|
writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Little);
|
||||||
|
assert(eql(u8, bytes, []u8{
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
}));
|
||||||
|
|
||||||
|
writeIntSlice(u64, bytes[0..], 0x12345678CAFEBABE, builtin.Endian.Big);
|
||||||
assert(eql(u8, bytes, []u8{
|
assert(eql(u8, bytes, []u8{
|
||||||
0x12,
|
0x12,
|
||||||
0x34,
|
0x34,
|
||||||
|
@ -795,7 +901,7 @@ fn testWriteIntImpl() void {
|
||||||
0xBE,
|
0xBE,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
writeInt(bytes[0..], u64(0xBEBAFECA78563412), builtin.Endian.Little);
|
writeIntSlice(u64, bytes[0..], 0xBEBAFECA78563412, builtin.Endian.Little);
|
||||||
assert(eql(u8, bytes, []u8{
|
assert(eql(u8, bytes, []u8{
|
||||||
0x12,
|
0x12,
|
||||||
0x34,
|
0x34,
|
||||||
|
@ -807,7 +913,7 @@ fn testWriteIntImpl() void {
|
||||||
0xBE,
|
0xBE,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big);
|
writeIntSlice(u32, bytes[0..], 0x12345678, builtin.Endian.Big);
|
||||||
assert(eql(u8, bytes, []u8{
|
assert(eql(u8, bytes, []u8{
|
||||||
0x00,
|
0x00,
|
||||||
0x00,
|
0x00,
|
||||||
|
@ -819,7 +925,7 @@ fn testWriteIntImpl() void {
|
||||||
0x78,
|
0x78,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
writeInt(bytes[0..], u32(0x78563412), builtin.Endian.Little);
|
writeIntSlice(u32, bytes[0..], 0x78563412, builtin.Endian.Little);
|
||||||
assert(eql(u8, bytes, []u8{
|
assert(eql(u8, bytes, []u8{
|
||||||
0x12,
|
0x12,
|
||||||
0x34,
|
0x34,
|
||||||
|
@ -831,7 +937,7 @@ fn testWriteIntImpl() void {
|
||||||
0x00,
|
0x00,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
writeInt(bytes[0..], u16(0x1234), builtin.Endian.Big);
|
writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Big);
|
||||||
assert(eql(u8, bytes, []u8{
|
assert(eql(u8, bytes, []u8{
|
||||||
0x00,
|
0x00,
|
||||||
0x00,
|
0x00,
|
||||||
|
@ -843,7 +949,7 @@ fn testWriteIntImpl() void {
|
||||||
0x34,
|
0x34,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
writeInt(bytes[0..], u16(0x1234), builtin.Endian.Little);
|
writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Little);
|
||||||
assert(eql(u8, bytes, []u8{
|
assert(eql(u8, bytes, []u8{
|
||||||
0x34,
|
0x34,
|
||||||
0x12,
|
0x12,
|
||||||
|
@ -941,29 +1047,52 @@ test "std.mem.rotate" {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: When https://github.com/ziglang/zig/issues/649 is solved these can be done by
|
/// Converts a little-endian integer to host endianness.
|
||||||
// endian-casting the pointer and then dereferencing
|
pub fn littleToNative(comptime T: type, x: T) T {
|
||||||
|
return switch (builtin.endian) {
|
||||||
pub fn endianSwapIfLe(comptime T: type, x: T) T {
|
builtin.Endian.Little => x,
|
||||||
return endianSwapIf(builtin.Endian.Little, T, x);
|
builtin.Endian.Big => @bswap(T, x),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn endianSwapIfBe(comptime T: type, x: T) T {
|
/// Converts a big-endian integer to host endianness.
|
||||||
return endianSwapIf(builtin.Endian.Big, T, x);
|
pub fn bigToNative(comptime T: type, x: T) T {
|
||||||
|
return switch (builtin.endian) {
|
||||||
|
builtin.Endian.Little => @bswap(T, x),
|
||||||
|
builtin.Endian.Big => x,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn endianSwapIf(endian: builtin.Endian, comptime T: type, x: T) T {
|
/// Converts an integer from specified endianness to host endianness.
|
||||||
return if (builtin.endian == endian) endianSwap(T, x) else x;
|
pub fn toNative(comptime T: type, x: T, endianness_of_x: builtin.Endian) T {
|
||||||
|
return switch (endianness_of_x) {
|
||||||
|
builtin.Endian.Little => littleToNative(T, x),
|
||||||
|
builtin.Endian.Big => bigToNative(T, x),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn endianSwap(comptime T: type, x: T) T {
|
/// Converts an integer which has host endianness to the desired endianness.
|
||||||
var buf: [@sizeOf(T)]u8 = undefined;
|
pub fn nativeTo(comptime T: type, x: T, desired_endianness: builtin.Endian) T {
|
||||||
mem.writeInt(buf[0..], x, builtin.Endian.Little);
|
return switch (desired_endianness) {
|
||||||
return mem.readInt(buf, T, builtin.Endian.Big);
|
builtin.Endian.Little => nativeToLittle(T, x),
|
||||||
|
builtin.Endian.Big => nativeToBig(T, x),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
test "std.mem.endianSwap" {
|
/// Converts an integer which has host endianness to little endian.
|
||||||
assert(endianSwap(u32, 0xDEADBEEF) == 0xEFBEADDE);
|
pub fn nativeToLittle(comptime T: type, x: T) T {
|
||||||
|
return switch (builtin.endian) {
|
||||||
|
builtin.Endian.Little => x,
|
||||||
|
builtin.Endian.Big => @bswap(T, x),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts an integer which has host endianness to big endian.
|
||||||
|
pub fn nativeToBig(comptime T: type, x: T) T {
|
||||||
|
return switch (builtin.endian) {
|
||||||
|
builtin.Endian.Little => @bswap(T, x),
|
||||||
|
builtin.Endian.Big => x,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn AsBytesReturnType(comptime P: type) type {
|
fn AsBytesReturnType(comptime P: type) type {
|
||||||
|
|
|
@ -76,6 +76,25 @@ test "std.meta.tagName" {
|
||||||
debug.assert(mem.eql(u8, tagName(u2b), "D"));
|
debug.assert(mem.eql(u8, tagName(u2b), "D"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn stringToEnum(comptime T: type, str: []const u8) ?T {
|
||||||
|
inline for (@typeInfo(T).Enum.fields) |enumField| {
|
||||||
|
if (std.mem.eql(u8, str, enumField.name)) {
|
||||||
|
return @field(T, enumField.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
test "std.meta.stringToEnum" {
|
||||||
|
const E1 = enum {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
};
|
||||||
|
debug.assert(E1.A == stringToEnum(E1, "A").?);
|
||||||
|
debug.assert(E1.B == stringToEnum(E1, "B").?);
|
||||||
|
debug.assert(null == stringToEnum(E1, "C"));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bitCount(comptime T: type) u32 {
|
pub fn bitCount(comptime T: type) u32 {
|
||||||
return switch (@typeInfo(T)) {
|
return switch (@typeInfo(T)) {
|
||||||
TypeId.Int => |info| info.bits,
|
TypeId.Int => |info| info.bits,
|
||||||
|
@ -483,3 +502,32 @@ test "std.meta.eql" {
|
||||||
debug.assert(eql(EU.tst(false), EU.tst(false)));
|
debug.assert(eql(EU.tst(false), EU.tst(false)));
|
||||||
debug.assert(!eql(EU.tst(false), EU.tst(true)));
|
debug.assert(!eql(EU.tst(false), EU.tst(true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "intToEnum with error return" {
|
||||||
|
const E1 = enum {
|
||||||
|
A,
|
||||||
|
};
|
||||||
|
const E2 = enum {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
};
|
||||||
|
|
||||||
|
var zero: u8 = 0;
|
||||||
|
var one: u16 = 1;
|
||||||
|
debug.assert(intToEnum(E1, zero) catch unreachable == E1.A);
|
||||||
|
debug.assert(intToEnum(E2, one) catch unreachable == E2.B);
|
||||||
|
debug.assertError(intToEnum(E1, one), error.InvalidEnumTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const IntToEnumError = error{InvalidEnumTag};
|
||||||
|
|
||||||
|
pub fn intToEnum(comptime Tag: type, tag_int: var) IntToEnumError!Tag {
|
||||||
|
comptime var i = 0;
|
||||||
|
inline while (i != @memberCount(Tag)) : (i += 1) {
|
||||||
|
const this_tag_value = @field(Tag, @memberName(Tag, i));
|
||||||
|
if (tag_int == @enumToInt(this_tag_value)) {
|
||||||
|
return this_tag_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error.InvalidEnumTag;
|
||||||
|
}
|
||||||
|
|
12
std/net.zig
12
std/net.zig
|
@ -23,7 +23,7 @@ pub const Address = struct {
|
||||||
.os_addr = posix.sockaddr{
|
.os_addr = posix.sockaddr{
|
||||||
.in = posix.sockaddr_in{
|
.in = posix.sockaddr_in{
|
||||||
.family = posix.AF_INET,
|
.family = posix.AF_INET,
|
||||||
.port = std.mem.endianSwapIfLe(u16, _port),
|
.port = mem.nativeToBig(u16, _port),
|
||||||
.addr = ip4,
|
.addr = ip4,
|
||||||
.zero = []u8{0} ** 8,
|
.zero = []u8{0} ** 8,
|
||||||
},
|
},
|
||||||
|
@ -37,7 +37,7 @@ pub const Address = struct {
|
||||||
.os_addr = posix.sockaddr{
|
.os_addr = posix.sockaddr{
|
||||||
.in6 = posix.sockaddr_in6{
|
.in6 = posix.sockaddr_in6{
|
||||||
.family = posix.AF_INET6,
|
.family = posix.AF_INET6,
|
||||||
.port = std.mem.endianSwapIfLe(u16, _port),
|
.port = mem.nativeToBig(u16, _port),
|
||||||
.flowinfo = 0,
|
.flowinfo = 0,
|
||||||
.addr = ip6.addr,
|
.addr = ip6.addr,
|
||||||
.scope_id = ip6.scope_id,
|
.scope_id = ip6.scope_id,
|
||||||
|
@ -47,7 +47,7 @@ pub const Address = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn port(self: Address) u16 {
|
pub fn port(self: Address) u16 {
|
||||||
return std.mem.endianSwapIfLe(u16, self.os_addr.in.port);
|
return mem.bigToNative(u16, self.os_addr.in.port);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initPosix(addr: posix.sockaddr) Address {
|
pub fn initPosix(addr: posix.sockaddr) Address {
|
||||||
|
@ -57,12 +57,12 @@ pub const Address = struct {
|
||||||
pub fn format(self: *const Address, out_stream: var) !void {
|
pub fn format(self: *const Address, out_stream: var) !void {
|
||||||
switch (self.os_addr.in.family) {
|
switch (self.os_addr.in.family) {
|
||||||
posix.AF_INET => {
|
posix.AF_INET => {
|
||||||
const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in.port);
|
const native_endian_port = mem.bigToNative(u16, self.os_addr.in.port);
|
||||||
const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]);
|
const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]);
|
||||||
try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port);
|
try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port);
|
||||||
},
|
},
|
||||||
posix.AF_INET6 => {
|
posix.AF_INET6 => {
|
||||||
const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in6.port);
|
const native_endian_port = mem.bigToNative(u16, self.os_addr.in6.port);
|
||||||
try out_stream.print("[TODO render ip6 address]:{}", native_endian_port);
|
try out_stream.print("[TODO render ip6 address]:{}", native_endian_port);
|
||||||
},
|
},
|
||||||
else => try out_stream.write("(unrecognized address family)"),
|
else => try out_stream.write("(unrecognized address family)"),
|
||||||
|
@ -193,7 +193,7 @@ pub fn parseIp6(buf: []const u8) !Ip6Addr {
|
||||||
}
|
}
|
||||||
|
|
||||||
test "std.net.parseIp4" {
|
test "std.net.parseIp4" {
|
||||||
assert((try parseIp4("127.0.0.1")) == std.mem.endianSwapIfLe(u32, 0x7f000001));
|
assert((try parseIp4("127.0.0.1")) == mem.bigToNative(u32, 0x7f000001));
|
||||||
|
|
||||||
testParseIp4Fail("256.0.0.1", error.Overflow);
|
testParseIp4Fail("256.0.0.1", error.Overflow);
|
||||||
testParseIp4Fail("x.0.0.1", error.InvalidCharacter);
|
testParseIp4Fail("x.0.0.1", error.InvalidCharacter);
|
||||||
|
|
|
@ -390,6 +390,19 @@ pub const ChildProcess = struct {
|
||||||
setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
|
setUpChildIo(self.stdout_behavior, stdout_pipe[1], posix.STDOUT_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
|
||||||
setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
|
setUpChildIo(self.stderr_behavior, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) catch |err| forkChildErrReport(err_pipe[1], err);
|
||||||
|
|
||||||
|
if (self.stdin_behavior == StdIo.Pipe) {
|
||||||
|
os.close(stdin_pipe[0]);
|
||||||
|
os.close(stdin_pipe[1]);
|
||||||
|
}
|
||||||
|
if (self.stdout_behavior == StdIo.Pipe) {
|
||||||
|
os.close(stdout_pipe[0]);
|
||||||
|
os.close(stdout_pipe[1]);
|
||||||
|
}
|
||||||
|
if (self.stderr_behavior == StdIo.Pipe) {
|
||||||
|
os.close(stderr_pipe[0]);
|
||||||
|
os.close(stderr_pipe[1]);
|
||||||
|
}
|
||||||
|
|
||||||
if (self.cwd) |cwd| {
|
if (self.cwd) |cwd| {
|
||||||
os.changeCurDir(self.allocator, cwd) catch |err| forkChildErrReport(err_pipe[1], err);
|
os.changeCurDir(self.allocator, cwd) catch |err| forkChildErrReport(err_pipe[1], err);
|
||||||
}
|
}
|
||||||
|
@ -794,10 +807,10 @@ const ErrInt = @IntType(false, @sizeOf(anyerror) * 8);
|
||||||
|
|
||||||
fn writeIntFd(fd: i32, value: ErrInt) !void {
|
fn writeIntFd(fd: i32, value: ErrInt) !void {
|
||||||
const stream = &os.File.openHandle(fd).outStream().stream;
|
const stream = &os.File.openHandle(fd).outStream().stream;
|
||||||
stream.writeIntNe(ErrInt, value) catch return error.SystemResources;
|
stream.writeIntNative(ErrInt, value) catch return error.SystemResources;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn readIntFd(fd: i32) !ErrInt {
|
fn readIntFd(fd: i32) !ErrInt {
|
||||||
const stream = &os.File.openHandle(fd).inStream().stream;
|
const stream = &os.File.openHandle(fd).inStream().stream;
|
||||||
return stream.readIntNe(ErrInt) catch return error.SystemResources;
|
return stream.readIntNative(ErrInt) catch return error.SystemResources;
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,9 +228,16 @@ pub const File = struct {
|
||||||
return os.isTty(self.handle);
|
return os.isTty(self.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn seekForward(self: File, amount: isize) !void {
|
pub const SeekError = error{
|
||||||
|
/// TODO make this error impossible to get
|
||||||
|
Overflow,
|
||||||
|
Unseekable,
|
||||||
|
Unexpected,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn seekForward(self: File, amount: isize) SeekError!void {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
Os.linux, Os.macosx, Os.ios => {
|
Os.linux, Os.macosx, Os.ios, Os.freebsd => {
|
||||||
const result = posix.lseek(self.handle, amount, posix.SEEK_CUR);
|
const result = posix.lseek(self.handle, amount, posix.SEEK_CUR);
|
||||||
const err = posix.getErrno(result);
|
const err = posix.getErrno(result);
|
||||||
if (err > 0) {
|
if (err > 0) {
|
||||||
|
@ -259,9 +266,9 @@ pub const File = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn seekTo(self: File, pos: usize) !void {
|
pub fn seekTo(self: File, pos: usize) SeekError!void {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
Os.linux, Os.macosx, Os.ios => {
|
Os.linux, Os.macosx, Os.ios, Os.freebsd => {
|
||||||
const ipos = try math.cast(isize, pos);
|
const ipos = try math.cast(isize, pos);
|
||||||
const result = posix.lseek(self.handle, ipos, posix.SEEK_SET);
|
const result = posix.lseek(self.handle, ipos, posix.SEEK_SET);
|
||||||
const err = posix.getErrno(result);
|
const err = posix.getErrno(result);
|
||||||
|
@ -293,9 +300,16 @@ pub const File = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getPos(self: File) !usize {
|
pub const GetSeekPosError = error{
|
||||||
|
Overflow,
|
||||||
|
SystemResources,
|
||||||
|
Unseekable,
|
||||||
|
Unexpected,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn getPos(self: File) GetSeekPosError!usize {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
Os.linux, Os.macosx, Os.ios => {
|
Os.linux, Os.macosx, Os.ios, Os.freebsd => {
|
||||||
const result = posix.lseek(self.handle, 0, posix.SEEK_CUR);
|
const result = posix.lseek(self.handle, 0, posix.SEEK_CUR);
|
||||||
const err = posix.getErrno(result);
|
const err = posix.getErrno(result);
|
||||||
if (err > 0) {
|
if (err > 0) {
|
||||||
|
@ -323,13 +337,13 @@ pub const File = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(pos >= 0);
|
assert(pos >= 0);
|
||||||
return math.cast(usize, pos) catch error.FilePosLargerThanPointerRange;
|
return math.cast(usize, pos);
|
||||||
},
|
},
|
||||||
else => @compileError("unsupported OS"),
|
else => @compileError("unsupported OS"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getEndPos(self: File) !usize {
|
pub fn getEndPos(self: File) GetSeekPosError!usize {
|
||||||
if (is_posix) {
|
if (is_posix) {
|
||||||
const stat = try os.posixFStat(self.handle);
|
const stat = try os.posixFStat(self.handle);
|
||||||
return @intCast(usize, stat.size);
|
return @intCast(usize, stat.size);
|
||||||
|
@ -431,6 +445,18 @@ pub const File = struct {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn seekableStream(file: File) SeekableStream {
|
||||||
|
return SeekableStream{
|
||||||
|
.file = file,
|
||||||
|
.stream = SeekableStream.Stream{
|
||||||
|
.seekToFn = SeekableStream.seekToFn,
|
||||||
|
.seekForwardFn = SeekableStream.seekForwardFn,
|
||||||
|
.getPosFn = SeekableStream.getPosFn,
|
||||||
|
.getEndPosFn = SeekableStream.getEndPosFn,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// Implementation of io.InStream trait for File
|
/// Implementation of io.InStream trait for File
|
||||||
pub const InStream = struct {
|
pub const InStream = struct {
|
||||||
file: File,
|
file: File,
|
||||||
|
@ -458,4 +484,32 @@ pub const File = struct {
|
||||||
return self.file.write(bytes);
|
return self.file.write(bytes);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Implementation of io.SeekableStream trait for File
|
||||||
|
pub const SeekableStream = struct {
|
||||||
|
file: File,
|
||||||
|
stream: Stream,
|
||||||
|
|
||||||
|
pub const Stream = io.SeekableStream(SeekError, GetSeekPosError);
|
||||||
|
|
||||||
|
pub fn seekToFn(seekable_stream: *Stream, pos: usize) SeekError!void {
|
||||||
|
const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
|
||||||
|
return self.file.seekTo(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn seekForwardFn(seekable_stream: *Stream, amt: isize) SeekError!void {
|
||||||
|
const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
|
||||||
|
return self.file.seekForward(amt);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getEndPosFn(seekable_stream: *Stream) GetSeekPosError!usize {
|
||||||
|
const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
|
||||||
|
return self.file.getEndPos();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getPosFn(seekable_stream: *Stream) GetSeekPosError!usize {
|
||||||
|
const self = @fieldParentPtr(SeekableStream, "stream", seekable_stream);
|
||||||
|
return self.file.getPos();
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
pub const EPERM = 1; // Operation not permitted
|
||||||
|
pub const ENOENT = 2; // No such file or directory
|
||||||
|
pub const ESRCH = 3; // No such process
|
||||||
|
pub const EINTR = 4; // Interrupted system call
|
||||||
|
pub const EIO = 5; // Input/output error
|
||||||
|
pub const ENXIO = 6; // Device not configured
|
||||||
|
pub const E2BIG = 7; // Argument list too long
|
||||||
|
pub const ENOEXEC = 8; // Exec format error
|
||||||
|
pub const EBADF = 9; // Bad file descriptor
|
||||||
|
pub const ECHILD = 10; // No child processes
|
||||||
|
pub const EDEADLK = 11; // Resource deadlock avoided
|
||||||
|
// 11 was EAGAIN
|
||||||
|
pub const ENOMEM = 12; // Cannot allocate memory
|
||||||
|
pub const EACCES = 13; // Permission denied
|
||||||
|
pub const EFAULT = 14; // Bad address
|
||||||
|
pub const ENOTBLK = 15; // Block device required
|
||||||
|
pub const EBUSY = 16; // Device busy
|
||||||
|
pub const EEXIST = 17; // File exists
|
||||||
|
pub const EXDEV = 18; // Cross-device link
|
||||||
|
pub const ENODEV = 19; // Operation not supported by device
|
||||||
|
pub const ENOTDIR = 20; // Not a directory
|
||||||
|
pub const EISDIR = 21; // Is a directory
|
||||||
|
pub const EINVAL = 22; // Invalid argument
|
||||||
|
pub const ENFILE = 23; // Too many open files in system
|
||||||
|
pub const EMFILE = 24; // Too many open files
|
||||||
|
pub const ENOTTY = 25; // Inappropriate ioctl for device
|
||||||
|
pub const ETXTBSY = 26; // Text file busy
|
||||||
|
pub const EFBIG = 27; // File too large
|
||||||
|
pub const ENOSPC = 28; // No space left on device
|
||||||
|
pub const ESPIPE = 29; // Illegal seek
|
||||||
|
pub const EROFS = 30; // Read-only filesystem
|
||||||
|
pub const EMLINK = 31; // Too many links
|
||||||
|
pub const EPIPE = 32; // Broken pipe
|
||||||
|
|
||||||
|
// math software
|
||||||
|
pub const EDOM = 33; // Numerical argument out of domain
|
||||||
|
pub const ERANGE = 34; // Result too large
|
||||||
|
|
||||||
|
// non-blocking and interrupt i/o
|
||||||
|
pub const EAGAIN = 35; // Resource temporarily unavailable
|
||||||
|
pub const EWOULDBLOCK = EAGAIN; // Operation would block
|
||||||
|
pub const EINPROGRESS = 36; // Operation now in progress
|
||||||
|
pub const EALREADY = 37; // Operation already in progress
|
||||||
|
|
||||||
|
// ipc/network software -- argument errors
|
||||||
|
pub const ENOTSOCK = 38; // Socket operation on non-socket
|
||||||
|
pub const EDESTADDRREQ = 39; // Destination address required
|
||||||
|
pub const EMSGSIZE = 40; // Message too long
|
||||||
|
pub const EPROTOTYPE = 41; // Protocol wrong type for socket
|
||||||
|
pub const ENOPROTOOPT = 42; // Protocol not available
|
||||||
|
pub const EPROTONOSUPPORT = 43; // Protocol not supported
|
||||||
|
pub const ESOCKTNOSUPPORT = 44; // Socket type not supported
|
||||||
|
pub const EOPNOTSUPP = 45; // Operation not supported
|
||||||
|
pub const ENOTSUP = EOPNOTSUPP; // Operation not supported
|
||||||
|
pub const EPFNOSUPPORT = 46; // Protocol family not supported
|
||||||
|
pub const EAFNOSUPPORT = 47; // Address family not supported by protocol family
|
||||||
|
pub const EADDRINUSE = 48; // Address already in use
|
||||||
|
pub const EADDRNOTAVAIL = 49; // Can't assign requested address
|
||||||
|
|
||||||
|
// ipc/network software -- operational errors
|
||||||
|
pub const ENETDOWN = 50; // Network is down
|
||||||
|
pub const ENETUNREACH = 51; // Network is unreachable
|
||||||
|
pub const ENETRESET = 52; // Network dropped connection on reset
|
||||||
|
pub const ECONNABORTED = 53; // Software caused connection abort
|
||||||
|
pub const ECONNRESET = 54; // Connection reset by peer
|
||||||
|
pub const ENOBUFS = 55; // No buffer space available
|
||||||
|
pub const EISCONN = 56; // Socket is already connected
|
||||||
|
pub const ENOTCONN = 57; // Socket is not connected
|
||||||
|
pub const ESHUTDOWN = 58; // Can't send after socket shutdown
|
||||||
|
pub const ETOOMANYREFS = 59; // Too many references: can't splice
|
||||||
|
pub const ETIMEDOUT = 60; // Operation timed out
|
||||||
|
pub const ECONNREFUSED = 61; // Connection refused
|
||||||
|
|
||||||
|
pub const ELOOP = 62; // Too many levels of symbolic links
|
||||||
|
pub const ENAMETOOLONG = 63; // File name too long
|
||||||
|
|
||||||
|
// should be rearranged
|
||||||
|
pub const EHOSTDOWN = 64; // Host is down
|
||||||
|
pub const EHOSTUNREACH = 65; // No route to host
|
||||||
|
pub const ENOTEMPTY = 66; // Directory not empty
|
||||||
|
|
||||||
|
// quotas & mush
|
||||||
|
pub const EPROCLIM = 67; // Too many processes
|
||||||
|
pub const EUSERS = 68; // Too many users
|
||||||
|
pub const EDQUOT = 69; // Disc quota exceeded
|
||||||
|
|
||||||
|
// Network File System
|
||||||
|
pub const ESTALE = 70; // Stale NFS file handle
|
||||||
|
pub const EREMOTE = 71; // Too many levels of remote in path
|
||||||
|
pub const EBADRPC = 72; // RPC struct is bad
|
||||||
|
pub const ERPCMISMATCH = 73; // RPC version wrong
|
||||||
|
pub const EPROGUNAVAIL = 74; // RPC prog. not avail
|
||||||
|
pub const EPROGMISMATCH = 75; // Program version wrong
|
||||||
|
pub const EPROCUNAVAIL = 76; // Bad procedure for program
|
||||||
|
|
||||||
|
pub const ENOLCK = 77; // No locks available
|
||||||
|
pub const ENOSYS = 78; // Function not implemented
|
||||||
|
|
||||||
|
pub const EFTYPE = 79; // Inappropriate file type or format
|
||||||
|
pub const EAUTH = 80; // Authentication error
|
||||||
|
pub const ENEEDAUTH = 81; // Need authenticator
|
||||||
|
pub const EIDRM = 82; // Identifier removed
|
||||||
|
pub const ENOMSG = 83; // No message of desired type
|
||||||
|
pub const EOVERFLOW = 84; // Value too large to be stored in data type
|
||||||
|
pub const ECANCELED = 85; // Operation canceled
|
||||||
|
pub const EILSEQ = 86; // Illegal byte sequence
|
||||||
|
pub const ENOATTR = 87; // Attribute not found
|
||||||
|
|
||||||
|
pub const EDOOFUS = 88; // Programming error
|
||||||
|
|
||||||
|
pub const EBADMSG = 89; // Bad message
|
||||||
|
pub const EMULTIHOP = 90; // Multihop attempted
|
||||||
|
pub const ENOLINK = 91; // Link has been severed
|
||||||
|
pub const EPROTO = 92; // Protocol error
|
||||||
|
|
||||||
|
pub const ENOTCAPABLE = 93; // Capabilities insufficient
|
||||||
|
pub const ECAPMODE = 94; // Not permitted in capability mode
|
||||||
|
pub const ENOTRECOVERABLE = 95; // State not recoverable
|
||||||
|
pub const EOWNERDEAD = 96; // Previous owner died
|
||||||
|
|
||||||
|
pub const ELAST = 96; // Must be equal largest errno
|
|
@ -0,0 +1,801 @@
|
||||||
|
const assert = @import("../debug.zig").assert;
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
const arch = switch (builtin.arch) {
|
||||||
|
builtin.Arch.x86_64 => @import("x86_64.zig"),
|
||||||
|
else => @compileError("unsupported arch"),
|
||||||
|
};
|
||||||
|
pub use @import("syscall.zig");
|
||||||
|
pub use @import("errno.zig");
|
||||||
|
|
||||||
|
const std = @import("../../index.zig");
|
||||||
|
const c = std.c;
|
||||||
|
const maxInt = std.math.maxInt;
|
||||||
|
pub const Kevent = c.Kevent;
|
||||||
|
|
||||||
|
pub const PATH_MAX = 1024;
|
||||||
|
|
||||||
|
pub const STDIN_FILENO = 0;
|
||||||
|
pub const STDOUT_FILENO = 1;
|
||||||
|
pub const STDERR_FILENO = 2;
|
||||||
|
|
||||||
|
pub const PROT_NONE = 0;
|
||||||
|
pub const PROT_READ = 1;
|
||||||
|
pub const PROT_WRITE = 2;
|
||||||
|
pub const PROT_EXEC = 4;
|
||||||
|
|
||||||
|
pub const MAP_FAILED = maxInt(usize);
|
||||||
|
pub const MAP_SHARED = 0x0001;
|
||||||
|
pub const MAP_PRIVATE = 0x0002;
|
||||||
|
pub const MAP_FIXED = 0x0010;
|
||||||
|
pub const MAP_STACK = 0x0400;
|
||||||
|
pub const MAP_NOSYNC = 0x0800;
|
||||||
|
pub const MAP_ANON = 0x1000;
|
||||||
|
pub const MAP_ANONYMOUS = MAP_ANON;
|
||||||
|
pub const MAP_FILE = 0;
|
||||||
|
pub const MAP_NORESERVE = 0;
|
||||||
|
|
||||||
|
pub const MAP_GUARD = 0x00002000;
|
||||||
|
pub const MAP_EXCL = 0x00004000;
|
||||||
|
pub const MAP_NOCORE = 0x00020000;
|
||||||
|
pub const MAP_PREFAULT_READ = 0x00040000;
|
||||||
|
pub const MAP_32BIT = 0x00080000;
|
||||||
|
|
||||||
|
pub const WNOHANG = 1;
|
||||||
|
pub const WUNTRACED = 2;
|
||||||
|
pub const WSTOPPED = WUNTRACED;
|
||||||
|
pub const WCONTINUED = 4;
|
||||||
|
pub const WNOWAIT = 8;
|
||||||
|
pub const WEXITED = 16;
|
||||||
|
pub const WTRAPPED = 32;
|
||||||
|
|
||||||
|
pub const SA_ONSTACK = 0x0001;
|
||||||
|
pub const SA_RESTART = 0x0002;
|
||||||
|
pub const SA_RESETHAND = 0x0004;
|
||||||
|
pub const SA_NOCLDSTOP = 0x0008;
|
||||||
|
pub const SA_NODEFER = 0x0010;
|
||||||
|
pub const SA_NOCLDWAIT = 0x0020;
|
||||||
|
pub const SA_SIGINFO = 0x0040;
|
||||||
|
|
||||||
|
pub const SIGHUP = 1;
|
||||||
|
pub const SIGINT = 2;
|
||||||
|
pub const SIGQUIT = 3;
|
||||||
|
pub const SIGILL = 4;
|
||||||
|
pub const SIGTRAP = 5;
|
||||||
|
pub const SIGABRT = 6;
|
||||||
|
pub const SIGIOT = SIGABRT;
|
||||||
|
pub const SIGEMT = 7;
|
||||||
|
pub const SIGFPE = 8;
|
||||||
|
pub const SIGKILL = 9;
|
||||||
|
pub const SIGBUS = 10;
|
||||||
|
pub const SIGSEGV = 11;
|
||||||
|
pub const SIGSYS = 12;
|
||||||
|
pub const SIGPIPE = 13;
|
||||||
|
pub const SIGALRM = 14;
|
||||||
|
pub const SIGTERM = 15;
|
||||||
|
pub const SIGURG = 16;
|
||||||
|
pub const SIGSTOP = 17;
|
||||||
|
pub const SIGTSTP = 18;
|
||||||
|
pub const SIGCONT = 19;
|
||||||
|
pub const SIGCHLD = 20;
|
||||||
|
pub const SIGTTIN = 21;
|
||||||
|
pub const SIGTTOU = 22;
|
||||||
|
pub const SIGIO = 23;
|
||||||
|
pub const SIGXCPU = 24;
|
||||||
|
pub const SIGXFSZ = 25;
|
||||||
|
pub const SIGVTALRM = 26;
|
||||||
|
pub const SIGPROF = 27;
|
||||||
|
pub const SIGWINCH = 28;
|
||||||
|
pub const SIGINFO = 29;
|
||||||
|
pub const SIGUSR1 = 30;
|
||||||
|
pub const SIGUSR2 = 31;
|
||||||
|
pub const SIGTHR = 32;
|
||||||
|
pub const SIGLWP = SIGTHR;
|
||||||
|
pub const SIGLIBRT = 33;
|
||||||
|
|
||||||
|
pub const SIGRTMIN = 65;
|
||||||
|
pub const SIGRTMAX = 126;
|
||||||
|
|
||||||
|
pub const O_RDONLY = 0o0;
|
||||||
|
pub const O_WRONLY = 0o1;
|
||||||
|
pub const O_RDWR = 0o2;
|
||||||
|
pub const O_ACCMODE = 0o3;
|
||||||
|
|
||||||
|
pub const O_CREAT = 0o100;
|
||||||
|
pub const O_EXCL = 0o200;
|
||||||
|
pub const O_NOCTTY = 0o400;
|
||||||
|
pub const O_TRUNC = 0o1000;
|
||||||
|
pub const O_APPEND = 0o2000;
|
||||||
|
pub const O_NONBLOCK = 0o4000;
|
||||||
|
pub const O_DSYNC = 0o10000;
|
||||||
|
pub const O_SYNC = 0o4010000;
|
||||||
|
pub const O_RSYNC = 0o4010000;
|
||||||
|
pub const O_DIRECTORY = 0o200000;
|
||||||
|
pub const O_NOFOLLOW = 0o400000;
|
||||||
|
pub const O_CLOEXEC = 0o2000000;
|
||||||
|
|
||||||
|
pub const O_ASYNC = 0o20000;
|
||||||
|
pub const O_DIRECT = 0o40000;
|
||||||
|
pub const O_LARGEFILE = 0;
|
||||||
|
pub const O_NOATIME = 0o1000000;
|
||||||
|
pub const O_PATH = 0o10000000;
|
||||||
|
pub const O_TMPFILE = 0o20200000;
|
||||||
|
pub const O_NDELAY = O_NONBLOCK;
|
||||||
|
|
||||||
|
pub const F_DUPFD = 0;
|
||||||
|
pub const F_GETFD = 1;
|
||||||
|
pub const F_SETFD = 2;
|
||||||
|
pub const F_GETFL = 3;
|
||||||
|
pub const F_SETFL = 4;
|
||||||
|
|
||||||
|
pub const F_SETOWN = 8;
|
||||||
|
pub const F_GETOWN = 9;
|
||||||
|
pub const F_SETSIG = 10;
|
||||||
|
pub const F_GETSIG = 11;
|
||||||
|
|
||||||
|
pub const F_GETLK = 5;
|
||||||
|
pub const F_SETLK = 6;
|
||||||
|
pub const F_SETLKW = 7;
|
||||||
|
|
||||||
|
pub const F_SETOWN_EX = 15;
|
||||||
|
pub const F_GETOWN_EX = 16;
|
||||||
|
|
||||||
|
pub const F_GETOWNER_UIDS = 17;
|
||||||
|
|
||||||
|
pub const SEEK_SET = 0;
|
||||||
|
pub const SEEK_CUR = 1;
|
||||||
|
pub const SEEK_END = 2;
|
||||||
|
|
||||||
|
pub const SIG_BLOCK = 1;
|
||||||
|
pub const SIG_UNBLOCK = 2;
|
||||||
|
pub const SIG_SETMASK = 3;
|
||||||
|
|
||||||
|
pub const SOCK_STREAM = 1;
|
||||||
|
pub const SOCK_DGRAM = 2;
|
||||||
|
pub const SOCK_RAW = 3;
|
||||||
|
pub const SOCK_RDM = 4;
|
||||||
|
pub const SOCK_SEQPACKET = 5;
|
||||||
|
|
||||||
|
pub const SOCK_CLOEXEC = 0x10000000;
|
||||||
|
pub const SOCK_NONBLOCK = 0x20000000;
|
||||||
|
|
||||||
|
pub const PROTO_ip = 0o000;
|
||||||
|
pub const PROTO_icmp = 0o001;
|
||||||
|
pub const PROTO_igmp = 0o002;
|
||||||
|
pub const PROTO_ggp = 0o003;
|
||||||
|
pub const PROTO_ipencap = 0o004;
|
||||||
|
pub const PROTO_st = 0o005;
|
||||||
|
pub const PROTO_tcp = 0o006;
|
||||||
|
pub const PROTO_egp = 0o010;
|
||||||
|
pub const PROTO_pup = 0o014;
|
||||||
|
pub const PROTO_udp = 0o021;
|
||||||
|
pub const PROTO_hmp = 0o024;
|
||||||
|
pub const PROTO_xns_idp = 0o026;
|
||||||
|
pub const PROTO_rdp = 0o033;
|
||||||
|
pub const PROTO_iso_tp4 = 0o035;
|
||||||
|
pub const PROTO_xtp = 0o044;
|
||||||
|
pub const PROTO_ddp = 0o045;
|
||||||
|
pub const PROTO_idpr_cmtp = 0o046;
|
||||||
|
pub const PROTO_ipv6 = 0o051;
|
||||||
|
pub const PROTO_ipv6_route = 0o053;
|
||||||
|
pub const PROTO_ipv6_frag = 0o054;
|
||||||
|
pub const PROTO_idrp = 0o055;
|
||||||
|
pub const PROTO_rsvp = 0o056;
|
||||||
|
pub const PROTO_gre = 0o057;
|
||||||
|
pub const PROTO_esp = 0o062;
|
||||||
|
pub const PROTO_ah = 0o063;
|
||||||
|
pub const PROTO_skip = 0o071;
|
||||||
|
pub const PROTO_ipv6_icmp = 0o072;
|
||||||
|
pub const PROTO_ipv6_nonxt = 0o073;
|
||||||
|
pub const PROTO_ipv6_opts = 0o074;
|
||||||
|
pub const PROTO_rspf = 0o111;
|
||||||
|
pub const PROTO_vmtp = 0o121;
|
||||||
|
pub const PROTO_ospf = 0o131;
|
||||||
|
pub const PROTO_ipip = 0o136;
|
||||||
|
pub const PROTO_encap = 0o142;
|
||||||
|
pub const PROTO_pim = 0o147;
|
||||||
|
pub const PROTO_raw = 0o377;
|
||||||
|
|
||||||
|
pub const PF_UNSPEC = 0;
|
||||||
|
pub const PF_LOCAL = 1;
|
||||||
|
pub const PF_UNIX = PF_LOCAL;
|
||||||
|
pub const PF_FILE = PF_LOCAL;
|
||||||
|
pub const PF_INET = 2;
|
||||||
|
pub const PF_AX25 = 3;
|
||||||
|
pub const PF_IPX = 4;
|
||||||
|
pub const PF_APPLETALK = 5;
|
||||||
|
pub const PF_NETROM = 6;
|
||||||
|
pub const PF_BRIDGE = 7;
|
||||||
|
pub const PF_ATMPVC = 8;
|
||||||
|
pub const PF_X25 = 9;
|
||||||
|
pub const PF_INET6 = 10;
|
||||||
|
pub const PF_ROSE = 11;
|
||||||
|
pub const PF_DECnet = 12;
|
||||||
|
pub const PF_NETBEUI = 13;
|
||||||
|
pub const PF_SECURITY = 14;
|
||||||
|
pub const PF_KEY = 15;
|
||||||
|
pub const PF_NETLINK = 16;
|
||||||
|
pub const PF_ROUTE = PF_NETLINK;
|
||||||
|
pub const PF_PACKET = 17;
|
||||||
|
pub const PF_ASH = 18;
|
||||||
|
pub const PF_ECONET = 19;
|
||||||
|
pub const PF_ATMSVC = 20;
|
||||||
|
pub const PF_RDS = 21;
|
||||||
|
pub const PF_SNA = 22;
|
||||||
|
pub const PF_IRDA = 23;
|
||||||
|
pub const PF_PPPOX = 24;
|
||||||
|
pub const PF_WANPIPE = 25;
|
||||||
|
pub const PF_LLC = 26;
|
||||||
|
pub const PF_IB = 27;
|
||||||
|
pub const PF_MPLS = 28;
|
||||||
|
pub const PF_CAN = 29;
|
||||||
|
pub const PF_TIPC = 30;
|
||||||
|
pub const PF_BLUETOOTH = 31;
|
||||||
|
pub const PF_IUCV = 32;
|
||||||
|
pub const PF_RXRPC = 33;
|
||||||
|
pub const PF_ISDN = 34;
|
||||||
|
pub const PF_PHONET = 35;
|
||||||
|
pub const PF_IEEE802154 = 36;
|
||||||
|
pub const PF_CAIF = 37;
|
||||||
|
pub const PF_ALG = 38;
|
||||||
|
pub const PF_NFC = 39;
|
||||||
|
pub const PF_VSOCK = 40;
|
||||||
|
pub const PF_MAX = 41;
|
||||||
|
|
||||||
|
pub const AF_UNSPEC = PF_UNSPEC;
|
||||||
|
pub const AF_LOCAL = PF_LOCAL;
|
||||||
|
pub const AF_UNIX = AF_LOCAL;
|
||||||
|
pub const AF_FILE = AF_LOCAL;
|
||||||
|
pub const AF_INET = PF_INET;
|
||||||
|
pub const AF_AX25 = PF_AX25;
|
||||||
|
pub const AF_IPX = PF_IPX;
|
||||||
|
pub const AF_APPLETALK = PF_APPLETALK;
|
||||||
|
pub const AF_NETROM = PF_NETROM;
|
||||||
|
pub const AF_BRIDGE = PF_BRIDGE;
|
||||||
|
pub const AF_ATMPVC = PF_ATMPVC;
|
||||||
|
pub const AF_X25 = PF_X25;
|
||||||
|
pub const AF_INET6 = PF_INET6;
|
||||||
|
pub const AF_ROSE = PF_ROSE;
|
||||||
|
pub const AF_DECnet = PF_DECnet;
|
||||||
|
pub const AF_NETBEUI = PF_NETBEUI;
|
||||||
|
pub const AF_SECURITY = PF_SECURITY;
|
||||||
|
pub const AF_KEY = PF_KEY;
|
||||||
|
pub const AF_NETLINK = PF_NETLINK;
|
||||||
|
pub const AF_ROUTE = PF_ROUTE;
|
||||||
|
pub const AF_PACKET = PF_PACKET;
|
||||||
|
pub const AF_ASH = PF_ASH;
|
||||||
|
pub const AF_ECONET = PF_ECONET;
|
||||||
|
pub const AF_ATMSVC = PF_ATMSVC;
|
||||||
|
pub const AF_RDS = PF_RDS;
|
||||||
|
pub const AF_SNA = PF_SNA;
|
||||||
|
pub const AF_IRDA = PF_IRDA;
|
||||||
|
pub const AF_PPPOX = PF_PPPOX;
|
||||||
|
pub const AF_WANPIPE = PF_WANPIPE;
|
||||||
|
pub const AF_LLC = PF_LLC;
|
||||||
|
pub const AF_IB = PF_IB;
|
||||||
|
pub const AF_MPLS = PF_MPLS;
|
||||||
|
pub const AF_CAN = PF_CAN;
|
||||||
|
pub const AF_TIPC = PF_TIPC;
|
||||||
|
pub const AF_BLUETOOTH = PF_BLUETOOTH;
|
||||||
|
pub const AF_IUCV = PF_IUCV;
|
||||||
|
pub const AF_RXRPC = PF_RXRPC;
|
||||||
|
pub const AF_ISDN = PF_ISDN;
|
||||||
|
pub const AF_PHONET = PF_PHONET;
|
||||||
|
pub const AF_IEEE802154 = PF_IEEE802154;
|
||||||
|
pub const AF_CAIF = PF_CAIF;
|
||||||
|
pub const AF_ALG = PF_ALG;
|
||||||
|
pub const AF_NFC = PF_NFC;
|
||||||
|
pub const AF_VSOCK = PF_VSOCK;
|
||||||
|
pub const AF_MAX = PF_MAX;
|
||||||
|
|
||||||
|
pub const DT_UNKNOWN = 0;
|
||||||
|
pub const DT_FIFO = 1;
|
||||||
|
pub const DT_CHR = 2;
|
||||||
|
pub const DT_DIR = 4;
|
||||||
|
pub const DT_BLK = 6;
|
||||||
|
pub const DT_REG = 8;
|
||||||
|
pub const DT_LNK = 10;
|
||||||
|
pub const DT_SOCK = 12;
|
||||||
|
pub const DT_WHT = 14;
|
||||||
|
|
||||||
|
/// add event to kq (implies enable)
|
||||||
|
pub const EV_ADD = 0x0001;
|
||||||
|
|
||||||
|
/// delete event from kq
|
||||||
|
pub const EV_DELETE = 0x0002;
|
||||||
|
|
||||||
|
/// enable event
|
||||||
|
pub const EV_ENABLE = 0x0004;
|
||||||
|
|
||||||
|
/// disable event (not reported)
|
||||||
|
pub const EV_DISABLE = 0x0008;
|
||||||
|
|
||||||
|
/// only report one occurrence
|
||||||
|
pub const EV_ONESHOT = 0x0010;
|
||||||
|
|
||||||
|
/// clear event state after reporting
|
||||||
|
pub const EV_CLEAR = 0x0020;
|
||||||
|
|
||||||
|
/// force immediate event output
|
||||||
|
/// ... with or without EV_ERROR
|
||||||
|
/// ... use KEVENT_FLAG_ERROR_EVENTS
|
||||||
|
/// on syscalls supporting flags
|
||||||
|
pub const EV_RECEIPT = 0x0040;
|
||||||
|
|
||||||
|
/// disable event after reporting
|
||||||
|
pub const EV_DISPATCH = 0x0080;
|
||||||
|
|
||||||
|
pub const EVFILT_READ = -1;
|
||||||
|
pub const EVFILT_WRITE = -2;
|
||||||
|
|
||||||
|
/// attached to aio requests
|
||||||
|
pub const EVFILT_AIO = -3;
|
||||||
|
|
||||||
|
/// attached to vnodes
|
||||||
|
pub const EVFILT_VNODE = -4;
|
||||||
|
|
||||||
|
/// attached to struct proc
|
||||||
|
pub const EVFILT_PROC = -5;
|
||||||
|
|
||||||
|
/// attached to struct proc
|
||||||
|
pub const EVFILT_SIGNAL = -6;
|
||||||
|
|
||||||
|
/// timers
|
||||||
|
pub const EVFILT_TIMER = -7;
|
||||||
|
|
||||||
|
/// Process descriptors
|
||||||
|
pub const EVFILT_PROCDESC = -8;
|
||||||
|
|
||||||
|
/// Filesystem events
|
||||||
|
pub const EVFILT_FS = -9;
|
||||||
|
|
||||||
|
pub const EVFILT_LIO = -10;
|
||||||
|
|
||||||
|
/// User events
|
||||||
|
pub const EVFILT_USER = -11;
|
||||||
|
|
||||||
|
/// Sendfile events
|
||||||
|
pub const EVFILT_SENDFILE = -12;
|
||||||
|
|
||||||
|
pub const EVFILT_EMPTY = -13;
|
||||||
|
|
||||||
|
/// On input, NOTE_TRIGGER causes the event to be triggered for output.
|
||||||
|
pub const NOTE_TRIGGER = 0x01000000;
|
||||||
|
|
||||||
|
/// ignore input fflags
|
||||||
|
pub const NOTE_FFNOP = 0x00000000;
|
||||||
|
|
||||||
|
/// and fflags
|
||||||
|
pub const NOTE_FFAND = 0x40000000;
|
||||||
|
|
||||||
|
/// or fflags
|
||||||
|
pub const NOTE_FFOR = 0x80000000;
|
||||||
|
|
||||||
|
/// copy fflags
|
||||||
|
pub const NOTE_FFCOPY = 0xc0000000;
|
||||||
|
|
||||||
|
/// mask for operations
|
||||||
|
pub const NOTE_FFCTRLMASK = 0xc0000000;
|
||||||
|
pub const NOTE_FFLAGSMASK = 0x00ffffff;
|
||||||
|
|
||||||
|
/// low water mark
|
||||||
|
pub const NOTE_LOWAT = 0x00000001;
|
||||||
|
|
||||||
|
/// behave like poll()
|
||||||
|
pub const NOTE_FILE_POLL = 0x00000002;
|
||||||
|
|
||||||
|
/// vnode was removed
|
||||||
|
pub const NOTE_DELETE = 0x00000001;
|
||||||
|
|
||||||
|
/// data contents changed
|
||||||
|
pub const NOTE_WRITE = 0x00000002;
|
||||||
|
|
||||||
|
/// size increased
|
||||||
|
pub const NOTE_EXTEND = 0x00000004;
|
||||||
|
|
||||||
|
/// attributes changed
|
||||||
|
pub const NOTE_ATTRIB = 0x00000008;
|
||||||
|
|
||||||
|
/// link count changed
|
||||||
|
pub const NOTE_LINK = 0x00000010;
|
||||||
|
|
||||||
|
/// vnode was renamed
|
||||||
|
pub const NOTE_RENAME = 0x00000020;
|
||||||
|
|
||||||
|
/// vnode access was revoked
|
||||||
|
pub const NOTE_REVOKE = 0x00000040;
|
||||||
|
|
||||||
|
/// vnode was opened
|
||||||
|
pub const NOTE_OPEN = 0x00000080;
|
||||||
|
|
||||||
|
/// file closed, fd did not allow write
|
||||||
|
pub const NOTE_CLOSE = 0x00000100;
|
||||||
|
|
||||||
|
/// file closed, fd did allow write
|
||||||
|
pub const NOTE_CLOSE_WRITE = 0x00000200;
|
||||||
|
|
||||||
|
/// file was read
|
||||||
|
pub const NOTE_READ = 0x00000400;
|
||||||
|
|
||||||
|
/// process exited
|
||||||
|
pub const NOTE_EXIT = 0x80000000;
|
||||||
|
|
||||||
|
/// process forked
|
||||||
|
pub const NOTE_FORK = 0x40000000;
|
||||||
|
|
||||||
|
/// process exec'd
|
||||||
|
pub const NOTE_EXEC = 0x20000000;
|
||||||
|
|
||||||
|
/// mask for signal & exit status
|
||||||
|
pub const NOTE_PDATAMASK = 0x000fffff;
|
||||||
|
pub const NOTE_PCTRLMASK = (~NOTE_PDATAMASK);
|
||||||
|
|
||||||
|
/// data is seconds
|
||||||
|
pub const NOTE_SECONDS = 0x00000001;
|
||||||
|
|
||||||
|
/// data is milliseconds
|
||||||
|
pub const NOTE_MSECONDS = 0x00000002;
|
||||||
|
|
||||||
|
/// data is microseconds
|
||||||
|
pub const NOTE_USECONDS = 0x00000004;
|
||||||
|
|
||||||
|
/// data is nanoseconds
|
||||||
|
pub const NOTE_NSECONDS = 0x00000008;
|
||||||
|
|
||||||
|
/// timeout is absolute
|
||||||
|
pub const NOTE_ABSTIME = 0x00000010;
|
||||||
|
|
||||||
|
pub const TCGETS = 0x5401;
|
||||||
|
pub const TCSETS = 0x5402;
|
||||||
|
pub const TCSETSW = 0x5403;
|
||||||
|
pub const TCSETSF = 0x5404;
|
||||||
|
pub const TCGETA = 0x5405;
|
||||||
|
pub const TCSETA = 0x5406;
|
||||||
|
pub const TCSETAW = 0x5407;
|
||||||
|
pub const TCSETAF = 0x5408;
|
||||||
|
pub const TCSBRK = 0x5409;
|
||||||
|
pub const TCXONC = 0x540A;
|
||||||
|
pub const TCFLSH = 0x540B;
|
||||||
|
pub const TIOCEXCL = 0x540C;
|
||||||
|
pub const TIOCNXCL = 0x540D;
|
||||||
|
pub const TIOCSCTTY = 0x540E;
|
||||||
|
pub const TIOCGPGRP = 0x540F;
|
||||||
|
pub const TIOCSPGRP = 0x5410;
|
||||||
|
pub const TIOCOUTQ = 0x5411;
|
||||||
|
pub const TIOCSTI = 0x5412;
|
||||||
|
pub const TIOCGWINSZ = 0x5413;
|
||||||
|
pub const TIOCSWINSZ = 0x5414;
|
||||||
|
pub const TIOCMGET = 0x5415;
|
||||||
|
pub const TIOCMBIS = 0x5416;
|
||||||
|
pub const TIOCMBIC = 0x5417;
|
||||||
|
pub const TIOCMSET = 0x5418;
|
||||||
|
pub const TIOCGSOFTCAR = 0x5419;
|
||||||
|
pub const TIOCSSOFTCAR = 0x541A;
|
||||||
|
pub const FIONREAD = 0x541B;
|
||||||
|
pub const TIOCINQ = FIONREAD;
|
||||||
|
pub const TIOCLINUX = 0x541C;
|
||||||
|
pub const TIOCCONS = 0x541D;
|
||||||
|
pub const TIOCGSERIAL = 0x541E;
|
||||||
|
pub const TIOCSSERIAL = 0x541F;
|
||||||
|
pub const TIOCPKT = 0x5420;
|
||||||
|
pub const FIONBIO = 0x5421;
|
||||||
|
pub const TIOCNOTTY = 0x5422;
|
||||||
|
pub const TIOCSETD = 0x5423;
|
||||||
|
pub const TIOCGETD = 0x5424;
|
||||||
|
pub const TCSBRKP = 0x5425;
|
||||||
|
pub const TIOCSBRK = 0x5427;
|
||||||
|
pub const TIOCCBRK = 0x5428;
|
||||||
|
pub const TIOCGSID = 0x5429;
|
||||||
|
pub const TIOCGRS485 = 0x542E;
|
||||||
|
pub const TIOCSRS485 = 0x542F;
|
||||||
|
pub const TIOCGPTN = 0x80045430;
|
||||||
|
pub const TIOCSPTLCK = 0x40045431;
|
||||||
|
pub const TIOCGDEV = 0x80045432;
|
||||||
|
pub const TCGETX = 0x5432;
|
||||||
|
pub const TCSETX = 0x5433;
|
||||||
|
pub const TCSETXF = 0x5434;
|
||||||
|
pub const TCSETXW = 0x5435;
|
||||||
|
pub const TIOCSIG = 0x40045436;
|
||||||
|
pub const TIOCVHANGUP = 0x5437;
|
||||||
|
pub const TIOCGPKT = 0x80045438;
|
||||||
|
pub const TIOCGPTLCK = 0x80045439;
|
||||||
|
pub const TIOCGEXCL = 0x80045440;
|
||||||
|
|
||||||
|
fn unsigned(s: i32) u32 {
|
||||||
|
return @bitCast(u32, s);
|
||||||
|
}
|
||||||
|
fn signed(s: u32) i32 {
|
||||||
|
return @bitCast(i32, s);
|
||||||
|
}
|
||||||
|
pub fn WEXITSTATUS(s: i32) i32 {
|
||||||
|
return signed((unsigned(s) & 0xff00) >> 8);
|
||||||
|
}
|
||||||
|
pub fn WTERMSIG(s: i32) i32 {
|
||||||
|
return signed(unsigned(s) & 0x7f);
|
||||||
|
}
|
||||||
|
pub fn WSTOPSIG(s: i32) i32 {
|
||||||
|
return WEXITSTATUS(s);
|
||||||
|
}
|
||||||
|
pub fn WIFEXITED(s: i32) bool {
|
||||||
|
return WTERMSIG(s) == 0;
|
||||||
|
}
|
||||||
|
pub fn WIFSTOPPED(s: i32) bool {
|
||||||
|
return @intCast(u16, (((unsigned(s) & 0xffff) *% 0x10001) >> 8)) > 0x7f00;
|
||||||
|
}
|
||||||
|
pub fn WIFSIGNALED(s: i32) bool {
|
||||||
|
return (unsigned(s) & 0xffff) -% 1 < 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const winsize = extern struct {
|
||||||
|
ws_row: u16,
|
||||||
|
ws_col: u16,
|
||||||
|
ws_xpixel: u16,
|
||||||
|
ws_ypixel: u16,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Get the errno from a syscall return value, or 0 for no error.
|
||||||
|
pub fn getErrno(r: usize) usize {
|
||||||
|
const signed_r = @bitCast(isize, r);
|
||||||
|
return if (signed_r > -4096 and signed_r < 0) @intCast(usize, -signed_r) else 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dup2(old: i32, new: i32) usize {
|
||||||
|
return arch.syscall2(SYS_dup2, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn chdir(path: [*]const u8) usize {
|
||||||
|
return arch.syscall1(SYS_chdir, @ptrToInt(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) usize {
|
||||||
|
return arch.syscall3(SYS_execve, @ptrToInt(path), @ptrToInt(argv), @ptrToInt(envp));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fork() usize {
|
||||||
|
return arch.syscall0(SYS_fork);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getcwd(buf: [*]u8, size: usize) usize {
|
||||||
|
return arch.syscall2(SYS___getcwd, @ptrToInt(buf), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize {
|
||||||
|
return arch.syscall3(SYS_getdents, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn isatty(fd: i32) bool {
|
||||||
|
var wsz: winsize = undefined;
|
||||||
|
return arch.syscall3(SYS_ioctl, @bitCast(usize, isize(fd)), TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
|
||||||
|
return arch.syscall3(SYS_readlink, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mkdir(path: [*]const u8, mode: u32) usize {
|
||||||
|
return arch.syscall2(SYS_mkdir, @ptrToInt(path), mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mmap(address: ?*u8, length: usize, prot: usize, flags: usize, fd: i32, offset: isize) usize {
|
||||||
|
return arch.syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @bitCast(usize, isize(fd)), @bitCast(usize, offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn munmap(address: usize, length: usize) usize {
|
||||||
|
return arch.syscall2(SYS_munmap, address, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
|
||||||
|
return arch.syscall3(SYS_read, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rmdir(path: [*]const u8) usize {
|
||||||
|
return arch.syscall1(SYS_rmdir, @ptrToInt(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
|
||||||
|
return arch.syscall2(SYS_symlink, @ptrToInt(existing), @ptrToInt(new));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize {
|
||||||
|
return arch.syscall4(SYS_pread, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: usize) usize {
|
||||||
|
return arch.syscall4(SYS_preadv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pipe(fd: *[2]i32) usize {
|
||||||
|
return pipe2(fd, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pipe2(fd: *[2]i32, flags: usize) usize {
|
||||||
|
return arch.syscall2(SYS_pipe2, @ptrToInt(fd), flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
|
||||||
|
return arch.syscall3(SYS_write, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
|
||||||
|
return arch.syscall4(SYS_pwrite, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: usize) usize {
|
||||||
|
return arch.syscall4(SYS_pwritev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rename(old: [*]const u8, new: [*]const u8) usize {
|
||||||
|
return arch.syscall2(SYS_rename, @ptrToInt(old), @ptrToInt(new));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn open(path: [*]const u8, flags: u32, perm: usize) usize {
|
||||||
|
return arch.syscall3(SYS_open, @ptrToInt(path), flags, perm);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create(path: [*]const u8, perm: usize) usize {
|
||||||
|
return arch.syscall2(SYS_creat, @ptrToInt(path), perm);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn openat(dirfd: i32, path: [*]const u8, flags: usize, mode: usize) usize {
|
||||||
|
return arch.syscall4(SYS_openat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn close(fd: i32) usize {
|
||||||
|
return arch.syscall1(SYS_close, @bitCast(usize, isize(fd)));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lseek(fd: i32, offset: isize, ref_pos: usize) usize {
|
||||||
|
return arch.syscall3(SYS_lseek, @bitCast(usize, isize(fd)), @bitCast(usize, offset), ref_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn exit(status: i32) noreturn {
|
||||||
|
_ = arch.syscall1(SYS_exit, @bitCast(usize, isize(status)));
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
|
||||||
|
return arch.syscall3(SYS_getrandom, @ptrToInt(buf), count, usize(flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kill(pid: i32, sig: i32) usize {
|
||||||
|
return arch.syscall2(SYS_kill, @bitCast(usize, isize(pid)), @bitCast(usize, isize(sig)));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unlink(path: [*]const u8) usize {
|
||||||
|
return arch.syscall1(SYS_unlink, @ptrToInt(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn waitpid(pid: i32, status: *i32, options: i32) usize {
|
||||||
|
return arch.syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize {
|
||||||
|
return arch.syscall2(SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setuid(uid: u32) usize {
|
||||||
|
return arch.syscall1(SYS_setuid, uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setgid(gid: u32) usize {
|
||||||
|
return arch.syscall1(SYS_setgid, gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setreuid(ruid: u32, euid: u32) usize {
|
||||||
|
return arch.syscall2(SYS_setreuid, ruid, euid);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setregid(rgid: u32, egid: u32) usize {
|
||||||
|
return arch.syscall2(SYS_setregid, rgid, egid);
|
||||||
|
}
|
||||||
|
|
||||||
|
const NSIG = 32;
|
||||||
|
|
||||||
|
pub const SIG_ERR = @intToPtr(extern fn (i32) void, maxInt(usize));
|
||||||
|
pub const SIG_DFL = @intToPtr(extern fn (i32) void, 0);
|
||||||
|
pub const SIG_IGN = @intToPtr(extern fn (i32) void, 1);
|
||||||
|
|
||||||
|
/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
|
||||||
|
pub const Sigaction = extern struct {
|
||||||
|
/// signal handler
|
||||||
|
__sigaction_u: extern union {
|
||||||
|
__sa_handler: extern fn (i32) void,
|
||||||
|
__sa_sigaction: extern fn (i32, *__siginfo, usize) void,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// see signal options
|
||||||
|
sa_flags: u32,
|
||||||
|
|
||||||
|
/// signal mask to apply
|
||||||
|
sa_mask: sigset_t,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const _SIG_WORDS = 4;
|
||||||
|
pub const _SIG_MAXSIG = 128;
|
||||||
|
|
||||||
|
pub inline fn _SIG_IDX(sig: usize) usize {
|
||||||
|
return sig - 1;
|
||||||
|
}
|
||||||
|
pub inline fn _SIG_WORD(sig: usize) usize {
|
||||||
|
return_SIG_IDX(sig) >> 5;
|
||||||
|
}
|
||||||
|
pub inline fn _SIG_BIT(sig: usize) usize {
|
||||||
|
return 1 << (_SIG_IDX(sig) & 31);
|
||||||
|
}
|
||||||
|
pub inline fn _SIG_VALID(sig: usize) usize {
|
||||||
|
return sig <= _SIG_MAXSIG and sig > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const sigset_t = extern struct {
|
||||||
|
__bits: [_SIG_WORDS]u32,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn raise(sig: i32) usize {
|
||||||
|
// TODO have a chat with the freebsd folks and make sure there's no bug in
|
||||||
|
// their libc. musl-libc blocks signals in between these calls because
|
||||||
|
// if a signal handler runs and forks between the gettid and sending the
|
||||||
|
// signal, the parent will get 2 signals, one from itself and one from the child
|
||||||
|
// if the protection does not belong here, then it belongs in abort(),
|
||||||
|
// like it does in freebsd's libc.
|
||||||
|
var id: usize = undefined;
|
||||||
|
const rc = arch.syscall1(SYS_thr_self, @ptrToInt(&id));
|
||||||
|
if (getErrno(rc) != 0) return rc;
|
||||||
|
return arch.syscall2(SYS_thr_kill, id, @bitCast(usize, isize(sig)));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const Stat = arch.Stat;
|
||||||
|
pub const timespec = arch.timespec;
|
||||||
|
|
||||||
|
pub fn fstat(fd: i32, stat_buf: *Stat) usize {
|
||||||
|
return arch.syscall2(SYS_fstat, @bitCast(usize, isize(fd)), @ptrToInt(stat_buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const iovec = extern struct {
|
||||||
|
iov_base: [*]u8,
|
||||||
|
iov_len: usize,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const iovec_const = extern struct {
|
||||||
|
iov_base: [*]const u8,
|
||||||
|
iov_len: usize,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO avoid libc dependency
|
||||||
|
pub fn kqueue() usize {
|
||||||
|
return errnoWrap(c.kqueue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO avoid libc dependency
|
||||||
|
pub fn kevent(kq: i32, changelist: []const Kevent, eventlist: []Kevent, timeout: ?*const timespec) usize {
|
||||||
|
return errnoWrap(c.kevent(
|
||||||
|
kq,
|
||||||
|
changelist.ptr,
|
||||||
|
@intCast(c_int, changelist.len),
|
||||||
|
eventlist.ptr,
|
||||||
|
@intCast(c_int, eventlist.len),
|
||||||
|
timeout,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO avoid libc dependency
|
||||||
|
pub fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize {
|
||||||
|
return errnoWrap(c.sysctl(name, namelen, oldp, oldlenp, newp, newlen));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO avoid libc dependency
|
||||||
|
pub fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize {
|
||||||
|
return errnoWrap(c.sysctlbyname(name, oldp, oldlenp, newp, newlen));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO avoid libc dependency
|
||||||
|
pub fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) usize {
|
||||||
|
return errnoWrap(c.sysctlnametomib(name, wibp, sizep));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO avoid libc dependency
|
||||||
|
|
||||||
|
/// Takes the return value from a syscall and formats it back in the way
|
||||||
|
/// that the kernel represents it to libc. Errno was a mistake, let's make
|
||||||
|
/// it go away forever.
|
||||||
|
fn errnoWrap(value: isize) usize {
|
||||||
|
return @bitCast(usize, if (value == -1) -isize(c._errno().*) else value);
|
||||||
|
}
|
|
@ -0,0 +1,493 @@
|
||||||
|
pub const SYS_syscall = 0;
|
||||||
|
pub const SYS_exit = 1;
|
||||||
|
pub const SYS_fork = 2;
|
||||||
|
pub const SYS_read = 3;
|
||||||
|
pub const SYS_write = 4;
|
||||||
|
pub const SYS_open = 5;
|
||||||
|
pub const SYS_close = 6;
|
||||||
|
pub const SYS_wait4 = 7;
|
||||||
|
// 8 is old creat
|
||||||
|
pub const SYS_link = 9;
|
||||||
|
pub const SYS_unlink = 10;
|
||||||
|
// 11 is obsolete execv
|
||||||
|
pub const SYS_chdir = 12;
|
||||||
|
pub const SYS_fchdir = 13;
|
||||||
|
pub const SYS_freebsd11_mknod = 14;
|
||||||
|
pub const SYS_chmod = 15;
|
||||||
|
pub const SYS_chown = 16;
|
||||||
|
pub const SYS_break = 17;
|
||||||
|
// 18 is freebsd4 getfsstat
|
||||||
|
// 19 is old lseek
|
||||||
|
pub const SYS_getpid = 20;
|
||||||
|
pub const SYS_mount = 21;
|
||||||
|
pub const SYS_unmount = 22;
|
||||||
|
pub const SYS_setuid = 23;
|
||||||
|
pub const SYS_getuid = 24;
|
||||||
|
pub const SYS_geteuid = 25;
|
||||||
|
pub const SYS_ptrace = 26;
|
||||||
|
pub const SYS_recvmsg = 27;
|
||||||
|
pub const SYS_sendmsg = 28;
|
||||||
|
pub const SYS_recvfrom = 29;
|
||||||
|
pub const SYS_accept = 30;
|
||||||
|
pub const SYS_getpeername = 31;
|
||||||
|
pub const SYS_getsockname = 32;
|
||||||
|
pub const SYS_access = 33;
|
||||||
|
pub const SYS_chflags = 34;
|
||||||
|
pub const SYS_fchflags = 35;
|
||||||
|
pub const SYS_sync = 36;
|
||||||
|
pub const SYS_kill = 37;
|
||||||
|
// 38 is old stat
|
||||||
|
pub const SYS_getppid = 39;
|
||||||
|
// 40 is old lstat
|
||||||
|
pub const SYS_dup = 41;
|
||||||
|
pub const SYS_freebsd10_pipe = 42;
|
||||||
|
pub const SYS_getegid = 43;
|
||||||
|
pub const SYS_profil = 44;
|
||||||
|
pub const SYS_ktrace = 45;
|
||||||
|
// 46 is old sigaction
|
||||||
|
pub const SYS_getgid = 47;
|
||||||
|
// 48 is old sigprocmask
|
||||||
|
pub const SYS_getlogin = 49;
|
||||||
|
pub const SYS_setlogin = 50;
|
||||||
|
pub const SYS_acct = 51;
|
||||||
|
// 52 is old sigpending
|
||||||
|
pub const SYS_sigaltstack = 53;
|
||||||
|
pub const SYS_ioctl = 54;
|
||||||
|
pub const SYS_reboot = 55;
|
||||||
|
pub const SYS_revoke = 56;
|
||||||
|
pub const SYS_symlink = 57;
|
||||||
|
pub const SYS_readlink = 58;
|
||||||
|
pub const SYS_execve = 59;
|
||||||
|
pub const SYS_umask = 60;
|
||||||
|
pub const SYS_chroot = 61;
|
||||||
|
// 62 is old fstat
|
||||||
|
// 63 is old getkerninfo
|
||||||
|
// 64 is old getpagesize
|
||||||
|
pub const SYS_msync = 65;
|
||||||
|
pub const SYS_vfork = 66;
|
||||||
|
// 67 is obsolete vread
|
||||||
|
// 68 is obsolete vwrite
|
||||||
|
// 69 is obsolete sbrk (still present on some platforms)
|
||||||
|
pub const SYS_sstk = 70;
|
||||||
|
// 71 is old mmap
|
||||||
|
pub const SYS_vadvise = 72;
|
||||||
|
pub const SYS_munmap = 73;
|
||||||
|
pub const SYS_mprotect = 74;
|
||||||
|
pub const SYS_madvise = 75;
|
||||||
|
// 76 is obsolete vhangup
|
||||||
|
// 77 is obsolete vlimit
|
||||||
|
pub const SYS_mincore = 78;
|
||||||
|
pub const SYS_getgroups = 79;
|
||||||
|
pub const SYS_setgroups = 80;
|
||||||
|
pub const SYS_getpgrp = 81;
|
||||||
|
pub const SYS_setpgid = 82;
|
||||||
|
pub const SYS_setitimer = 83;
|
||||||
|
// 84 is old wait
|
||||||
|
pub const SYS_swapon = 85;
|
||||||
|
pub const SYS_getitimer = 86;
|
||||||
|
// 87 is old gethostname
|
||||||
|
// 88 is old sethostname
|
||||||
|
pub const SYS_getdtablesize = 89;
|
||||||
|
pub const SYS_dup2 = 90;
|
||||||
|
pub const SYS_fcntl = 92;
|
||||||
|
pub const SYS_select = 93;
|
||||||
|
pub const SYS_fsync = 95;
|
||||||
|
pub const SYS_setpriority = 96;
|
||||||
|
pub const SYS_socket = 97;
|
||||||
|
pub const SYS_connect = 98;
|
||||||
|
// 99 is old accept
|
||||||
|
pub const SYS_getpriority = 100;
|
||||||
|
// 101 is old send
|
||||||
|
// 102 is old recv
|
||||||
|
// 103 is old sigreturn
|
||||||
|
pub const SYS_bind = 104;
|
||||||
|
pub const SYS_setsockopt = 105;
|
||||||
|
pub const SYS_listen = 106;
|
||||||
|
// 107 is obsolete vtimes
|
||||||
|
// 108 is old sigvec
|
||||||
|
// 109 is old sigblock
|
||||||
|
// 110 is old sigsetmask
|
||||||
|
// 111 is old sigsuspend
|
||||||
|
// 112 is old sigstack
|
||||||
|
// 113 is old recvmsg
|
||||||
|
// 114 is old sendmsg
|
||||||
|
// 115 is obsolete vtrace
|
||||||
|
pub const SYS_gettimeofday = 116;
|
||||||
|
pub const SYS_getrusage = 117;
|
||||||
|
pub const SYS_getsockopt = 118;
|
||||||
|
pub const SYS_readv = 120;
|
||||||
|
pub const SYS_writev = 121;
|
||||||
|
pub const SYS_settimeofday = 122;
|
||||||
|
pub const SYS_fchown = 123;
|
||||||
|
pub const SYS_fchmod = 124;
|
||||||
|
// 125 is old recvfrom
|
||||||
|
pub const SYS_setreuid = 126;
|
||||||
|
pub const SYS_setregid = 127;
|
||||||
|
pub const SYS_rename = 128;
|
||||||
|
// 129 is old truncate
|
||||||
|
// 130 is old ftruncate
|
||||||
|
pub const SYS_flock = 131;
|
||||||
|
pub const SYS_mkfifo = 132;
|
||||||
|
pub const SYS_sendto = 133;
|
||||||
|
pub const SYS_shutdown = 134;
|
||||||
|
pub const SYS_socketpair = 135;
|
||||||
|
pub const SYS_mkdir = 136;
|
||||||
|
pub const SYS_rmdir = 137;
|
||||||
|
pub const SYS_utimes = 138;
|
||||||
|
// 139 is obsolete 4.2 sigreturn
|
||||||
|
pub const SYS_adjtime = 140;
|
||||||
|
// 141 is old getpeername
|
||||||
|
// 142 is old gethostid
|
||||||
|
// 143 is old sethostid
|
||||||
|
// 144 is old getrlimit
|
||||||
|
// 145 is old setrlimit
|
||||||
|
// 146 is old killpg
|
||||||
|
pub const SYS_setsid = 147;
|
||||||
|
pub const SYS_quotactl = 148;
|
||||||
|
// 149 is old quota
|
||||||
|
// 150 is old getsockname
|
||||||
|
pub const SYS_nlm_syscall = 154;
|
||||||
|
pub const SYS_nfssvc = 155;
|
||||||
|
// 156 is old getdirentries
|
||||||
|
// 157 is freebsd4 statfs
|
||||||
|
// 158 is freebsd4 fstatfs
|
||||||
|
pub const SYS_lgetfh = 160;
|
||||||
|
pub const SYS_getfh = 161;
|
||||||
|
// 162 is freebsd4 getdomainname
|
||||||
|
// 163 is freebsd4 setdomainname
|
||||||
|
// 164 is freebsd4 uname
|
||||||
|
pub const SYS_sysarch = 165;
|
||||||
|
pub const SYS_rtprio = 166;
|
||||||
|
pub const SYS_semsys = 169;
|
||||||
|
pub const SYS_msgsys = 170;
|
||||||
|
pub const SYS_shmsys = 171;
|
||||||
|
// 173 is freebsd6 pread
|
||||||
|
// 174 is freebsd6 pwrite
|
||||||
|
pub const SYS_setfib = 175;
|
||||||
|
pub const SYS_ntp_adjtime = 176;
|
||||||
|
pub const SYS_setgid = 181;
|
||||||
|
pub const SYS_setegid = 182;
|
||||||
|
pub const SYS_seteuid = 183;
|
||||||
|
// 184 is obsolete lfs_bmapv
|
||||||
|
// 185 is obsolete lfs_markv
|
||||||
|
// 186 is obsolete lfs_segclean
|
||||||
|
// 187 is obsolete lfs_segwait
|
||||||
|
pub const SYS_freebsd11_stat = 188;
|
||||||
|
pub const SYS_freebsd11_fstat = 189;
|
||||||
|
pub const SYS_freebsd11_lstat = 190;
|
||||||
|
pub const SYS_pathconf = 191;
|
||||||
|
pub const SYS_fpathconf = 192;
|
||||||
|
pub const SYS_getrlimit = 194;
|
||||||
|
pub const SYS_setrlimit = 195;
|
||||||
|
pub const SYS_freebsd11_getdirentries = 196;
|
||||||
|
// 197 is freebsd6 mmap
|
||||||
|
pub const SYS___syscall = 198;
|
||||||
|
// 199 is freebsd6 lseek
|
||||||
|
// 200 is freebsd6 truncate
|
||||||
|
// 201 is freebsd6 ftruncate
|
||||||
|
pub const SYS___sysctl = 202;
|
||||||
|
pub const SYS_mlock = 203;
|
||||||
|
pub const SYS_munlock = 204;
|
||||||
|
pub const SYS_undelete = 205;
|
||||||
|
pub const SYS_futimes = 206;
|
||||||
|
pub const SYS_getpgid = 207;
|
||||||
|
pub const SYS_poll = 209;
|
||||||
|
pub const SYS_freebsd7___semctl = 220;
|
||||||
|
pub const SYS_semget = 221;
|
||||||
|
pub const SYS_semop = 222;
|
||||||
|
pub const SYS_freebsd7_msgctl = 224;
|
||||||
|
pub const SYS_msgget = 225;
|
||||||
|
pub const SYS_msgsnd = 226;
|
||||||
|
pub const SYS_msgrcv = 227;
|
||||||
|
pub const SYS_shmat = 228;
|
||||||
|
pub const SYS_freebsd7_shmctl = 229;
|
||||||
|
pub const SYS_shmdt = 230;
|
||||||
|
pub const SYS_shmget = 231;
|
||||||
|
pub const SYS_clock_gettime = 232;
|
||||||
|
pub const SYS_clock_settime = 233;
|
||||||
|
pub const SYS_clock_getres = 234;
|
||||||
|
pub const SYS_ktimer_create = 235;
|
||||||
|
pub const SYS_ktimer_delete = 236;
|
||||||
|
pub const SYS_ktimer_settime = 237;
|
||||||
|
pub const SYS_ktimer_gettime = 238;
|
||||||
|
pub const SYS_ktimer_getoverrun = 239;
|
||||||
|
pub const SYS_nanosleep = 240;
|
||||||
|
pub const SYS_ffclock_getcounter = 241;
|
||||||
|
pub const SYS_ffclock_setestimate = 242;
|
||||||
|
pub const SYS_ffclock_getestimate = 243;
|
||||||
|
pub const SYS_clock_nanosleep = 244;
|
||||||
|
pub const SYS_clock_getcpuclockid2 = 247;
|
||||||
|
pub const SYS_ntp_gettime = 248;
|
||||||
|
pub const SYS_minherit = 250;
|
||||||
|
pub const SYS_rfork = 251;
|
||||||
|
// 252 is obsolete openbsd_poll
|
||||||
|
pub const SYS_issetugid = 253;
|
||||||
|
pub const SYS_lchown = 254;
|
||||||
|
pub const SYS_aio_read = 255;
|
||||||
|
pub const SYS_aio_write = 256;
|
||||||
|
pub const SYS_lio_listio = 257;
|
||||||
|
pub const SYS_freebsd11_getdents = 272;
|
||||||
|
pub const SYS_lchmod = 274;
|
||||||
|
// 275 is obsolete netbsd_lchown
|
||||||
|
pub const SYS_lutimes = 276;
|
||||||
|
// 277 is obsolete netbsd_msync
|
||||||
|
pub const SYS_freebsd11_nstat = 278;
|
||||||
|
pub const SYS_freebsd11_nfstat = 279;
|
||||||
|
pub const SYS_freebsd11_nlstat = 280;
|
||||||
|
pub const SYS_preadv = 289;
|
||||||
|
pub const SYS_pwritev = 290;
|
||||||
|
// 297 is freebsd4 fhstatfs
|
||||||
|
pub const SYS_fhopen = 298;
|
||||||
|
pub const SYS_freebsd11_fhstat = 299;
|
||||||
|
pub const SYS_modnext = 300;
|
||||||
|
pub const SYS_modstat = 301;
|
||||||
|
pub const SYS_modfnext = 302;
|
||||||
|
pub const SYS_modfind = 303;
|
||||||
|
pub const SYS_kldload = 304;
|
||||||
|
pub const SYS_kldunload = 305;
|
||||||
|
pub const SYS_kldfind = 306;
|
||||||
|
pub const SYS_kldnext = 307;
|
||||||
|
pub const SYS_kldstat = 308;
|
||||||
|
pub const SYS_kldfirstmod = 309;
|
||||||
|
pub const SYS_getsid = 310;
|
||||||
|
pub const SYS_setresuid = 311;
|
||||||
|
pub const SYS_setresgid = 312;
|
||||||
|
// 313 is obsolete signanosleep
|
||||||
|
pub const SYS_aio_return = 314;
|
||||||
|
pub const SYS_aio_suspend = 315;
|
||||||
|
pub const SYS_aio_cancel = 316;
|
||||||
|
pub const SYS_aio_error = 317;
|
||||||
|
// 318 is freebsd6 aio_read
|
||||||
|
// 319 is freebsd6 aio_write
|
||||||
|
// 320 is freebsd6 lio_listio
|
||||||
|
pub const SYS_yield = 321;
|
||||||
|
// 322 is obsolete thr_sleep
|
||||||
|
// 323 is obsolete thr_wakeup
|
||||||
|
pub const SYS_mlockall = 324;
|
||||||
|
pub const SYS_munlockall = 325;
|
||||||
|
pub const SYS___getcwd = 326;
|
||||||
|
pub const SYS_sched_setparam = 327;
|
||||||
|
pub const SYS_sched_getparam = 328;
|
||||||
|
pub const SYS_sched_setscheduler = 329;
|
||||||
|
pub const SYS_sched_getscheduler = 330;
|
||||||
|
pub const SYS_sched_yield = 331;
|
||||||
|
pub const SYS_sched_get_priority_max = 332;
|
||||||
|
pub const SYS_sched_get_priority_min = 333;
|
||||||
|
pub const SYS_sched_rr_get_interval = 334;
|
||||||
|
pub const SYS_utrace = 335;
|
||||||
|
// 336 is freebsd4 sendfile
|
||||||
|
pub const SYS_kldsym = 337;
|
||||||
|
pub const SYS_jail = 338;
|
||||||
|
pub const SYS_nnpfs_syscall = 339;
|
||||||
|
pub const SYS_sigprocmask = 340;
|
||||||
|
pub const SYS_sigsuspend = 341;
|
||||||
|
// 342 is freebsd4 sigaction
|
||||||
|
pub const SYS_sigpending = 343;
|
||||||
|
// 344 is freebsd4 sigreturn
|
||||||
|
pub const SYS_sigtimedwait = 345;
|
||||||
|
pub const SYS_sigwaitinfo = 346;
|
||||||
|
pub const SYS___acl_get_file = 347;
|
||||||
|
pub const SYS___acl_set_file = 348;
|
||||||
|
pub const SYS___acl_get_fd = 349;
|
||||||
|
pub const SYS___acl_set_fd = 350;
|
||||||
|
pub const SYS___acl_delete_file = 351;
|
||||||
|
pub const SYS___acl_delete_fd = 352;
|
||||||
|
pub const SYS___acl_aclcheck_file = 353;
|
||||||
|
pub const SYS___acl_aclcheck_fd = 354;
|
||||||
|
pub const SYS_extattrctl = 355;
|
||||||
|
pub const SYS_extattr_set_file = 356;
|
||||||
|
pub const SYS_extattr_get_file = 357;
|
||||||
|
pub const SYS_extattr_delete_file = 358;
|
||||||
|
pub const SYS_aio_waitcomplete = 359;
|
||||||
|
pub const SYS_getresuid = 360;
|
||||||
|
pub const SYS_getresgid = 361;
|
||||||
|
pub const SYS_kqueue = 362;
|
||||||
|
pub const SYS_freebsd11_kevent = 363;
|
||||||
|
// 364 is obsolete __cap_get_proc
|
||||||
|
// 365 is obsolete __cap_set_proc
|
||||||
|
// 366 is obsolete __cap_get_fd
|
||||||
|
// 367 is obsolete __cap_get_file
|
||||||
|
// 368 is obsolete __cap_set_fd
|
||||||
|
// 369 is obsolete __cap_set_file
|
||||||
|
pub const SYS_extattr_set_fd = 371;
|
||||||
|
pub const SYS_extattr_get_fd = 372;
|
||||||
|
pub const SYS_extattr_delete_fd = 373;
|
||||||
|
pub const SYS___setugid = 374;
|
||||||
|
pub const SYS_eaccess = 376;
|
||||||
|
pub const SYS_afs3_syscall = 377;
|
||||||
|
pub const SYS_nmount = 378;
|
||||||
|
// 379 is obsolete kse_exit
|
||||||
|
// 380 is obsolete kse_wakeup
|
||||||
|
// 381 is obsolete kse_create
|
||||||
|
// 382 is obsolete kse_thr_interrupt
|
||||||
|
// 383 is obsolete kse_release
|
||||||
|
pub const SYS___mac_get_proc = 384;
|
||||||
|
pub const SYS___mac_set_proc = 385;
|
||||||
|
pub const SYS___mac_get_fd = 386;
|
||||||
|
pub const SYS___mac_get_file = 387;
|
||||||
|
pub const SYS___mac_set_fd = 388;
|
||||||
|
pub const SYS___mac_set_file = 389;
|
||||||
|
pub const SYS_kenv = 390;
|
||||||
|
pub const SYS_lchflags = 391;
|
||||||
|
pub const SYS_uuidgen = 392;
|
||||||
|
pub const SYS_sendfile = 393;
|
||||||
|
pub const SYS_mac_syscall = 394;
|
||||||
|
pub const SYS_freebsd11_getfsstat = 395;
|
||||||
|
pub const SYS_freebsd11_statfs = 396;
|
||||||
|
pub const SYS_freebsd11_fstatfs = 397;
|
||||||
|
pub const SYS_freebsd11_fhstatfs = 398;
|
||||||
|
pub const SYS_ksem_close = 400;
|
||||||
|
pub const SYS_ksem_post = 401;
|
||||||
|
pub const SYS_ksem_wait = 402;
|
||||||
|
pub const SYS_ksem_trywait = 403;
|
||||||
|
pub const SYS_ksem_init = 404;
|
||||||
|
pub const SYS_ksem_open = 405;
|
||||||
|
pub const SYS_ksem_unlink = 406;
|
||||||
|
pub const SYS_ksem_getvalue = 407;
|
||||||
|
pub const SYS_ksem_destroy = 408;
|
||||||
|
pub const SYS___mac_get_pid = 409;
|
||||||
|
pub const SYS___mac_get_link = 410;
|
||||||
|
pub const SYS___mac_set_link = 411;
|
||||||
|
pub const SYS_extattr_set_link = 412;
|
||||||
|
pub const SYS_extattr_get_link = 413;
|
||||||
|
pub const SYS_extattr_delete_link = 414;
|
||||||
|
pub const SYS___mac_execve = 415;
|
||||||
|
pub const SYS_sigaction = 416;
|
||||||
|
pub const SYS_sigreturn = 417;
|
||||||
|
pub const SYS_getcontext = 421;
|
||||||
|
pub const SYS_setcontext = 422;
|
||||||
|
pub const SYS_swapcontext = 423;
|
||||||
|
pub const SYS_swapoff = 424;
|
||||||
|
pub const SYS___acl_get_link = 425;
|
||||||
|
pub const SYS___acl_set_link = 426;
|
||||||
|
pub const SYS___acl_delete_link = 427;
|
||||||
|
pub const SYS___acl_aclcheck_link = 428;
|
||||||
|
pub const SYS_sigwait = 429;
|
||||||
|
pub const SYS_thr_create = 430;
|
||||||
|
pub const SYS_thr_exit = 431;
|
||||||
|
pub const SYS_thr_self = 432;
|
||||||
|
pub const SYS_thr_kill = 433;
|
||||||
|
pub const SYS_jail_attach = 436;
|
||||||
|
pub const SYS_extattr_list_fd = 437;
|
||||||
|
pub const SYS_extattr_list_file = 438;
|
||||||
|
pub const SYS_extattr_list_link = 439;
|
||||||
|
// 440 is obsolete kse_switchin
|
||||||
|
pub const SYS_ksem_timedwait = 441;
|
||||||
|
pub const SYS_thr_suspend = 442;
|
||||||
|
pub const SYS_thr_wake = 443;
|
||||||
|
pub const SYS_kldunloadf = 444;
|
||||||
|
pub const SYS_audit = 445;
|
||||||
|
pub const SYS_auditon = 446;
|
||||||
|
pub const SYS_getauid = 447;
|
||||||
|
pub const SYS_setauid = 448;
|
||||||
|
pub const SYS_getaudit = 449;
|
||||||
|
pub const SYS_setaudit = 450;
|
||||||
|
pub const SYS_getaudit_addr = 451;
|
||||||
|
pub const SYS_setaudit_addr = 452;
|
||||||
|
pub const SYS_auditctl = 453;
|
||||||
|
pub const SYS__umtx_op = 454;
|
||||||
|
pub const SYS_thr_new = 455;
|
||||||
|
pub const SYS_sigqueue = 456;
|
||||||
|
pub const SYS_kmq_open = 457;
|
||||||
|
pub const SYS_kmq_setattr = 458;
|
||||||
|
pub const SYS_kmq_timedreceive = 459;
|
||||||
|
pub const SYS_kmq_timedsend = 460;
|
||||||
|
pub const SYS_kmq_notify = 461;
|
||||||
|
pub const SYS_kmq_unlink = 462;
|
||||||
|
pub const SYS_abort2 = 463;
|
||||||
|
pub const SYS_thr_set_name = 464;
|
||||||
|
pub const SYS_aio_fsync = 465;
|
||||||
|
pub const SYS_rtprio_thread = 466;
|
||||||
|
pub const SYS_sctp_peeloff = 471;
|
||||||
|
pub const SYS_sctp_generic_sendmsg = 472;
|
||||||
|
pub const SYS_sctp_generic_sendmsg_iov = 473;
|
||||||
|
pub const SYS_sctp_generic_recvmsg = 474;
|
||||||
|
pub const SYS_pread = 475;
|
||||||
|
pub const SYS_pwrite = 476;
|
||||||
|
pub const SYS_mmap = 477;
|
||||||
|
pub const SYS_lseek = 478;
|
||||||
|
pub const SYS_truncate = 479;
|
||||||
|
pub const SYS_ftruncate = 480;
|
||||||
|
pub const SYS_thr_kill2 = 481;
|
||||||
|
pub const SYS_shm_open = 482;
|
||||||
|
pub const SYS_shm_unlink = 483;
|
||||||
|
pub const SYS_cpuset = 484;
|
||||||
|
pub const SYS_cpuset_setid = 485;
|
||||||
|
pub const SYS_cpuset_getid = 486;
|
||||||
|
pub const SYS_cpuset_getaffinity = 487;
|
||||||
|
pub const SYS_cpuset_setaffinity = 488;
|
||||||
|
pub const SYS_faccessat = 489;
|
||||||
|
pub const SYS_fchmodat = 490;
|
||||||
|
pub const SYS_fchownat = 491;
|
||||||
|
pub const SYS_fexecve = 492;
|
||||||
|
pub const SYS_freebsd11_fstatat = 493;
|
||||||
|
pub const SYS_futimesat = 494;
|
||||||
|
pub const SYS_linkat = 495;
|
||||||
|
pub const SYS_mkdirat = 496;
|
||||||
|
pub const SYS_mkfifoat = 497;
|
||||||
|
pub const SYS_freebsd11_mknodat = 498;
|
||||||
|
pub const SYS_openat = 499;
|
||||||
|
pub const SYS_readlinkat = 500;
|
||||||
|
pub const SYS_renameat = 501;
|
||||||
|
pub const SYS_symlinkat = 502;
|
||||||
|
pub const SYS_unlinkat = 503;
|
||||||
|
pub const SYS_posix_openpt = 504;
|
||||||
|
pub const SYS_gssd_syscall = 505;
|
||||||
|
pub const SYS_jail_get = 506;
|
||||||
|
pub const SYS_jail_set = 507;
|
||||||
|
pub const SYS_jail_remove = 508;
|
||||||
|
pub const SYS_closefrom = 509;
|
||||||
|
pub const SYS___semctl = 510;
|
||||||
|
pub const SYS_msgctl = 511;
|
||||||
|
pub const SYS_shmctl = 512;
|
||||||
|
pub const SYS_lpathconf = 513;
|
||||||
|
// 514 is obsolete cap_new
|
||||||
|
pub const SYS___cap_rights_get = 515;
|
||||||
|
pub const SYS_cap_enter = 516;
|
||||||
|
pub const SYS_cap_getmode = 517;
|
||||||
|
pub const SYS_pdfork = 518;
|
||||||
|
pub const SYS_pdkill = 519;
|
||||||
|
pub const SYS_pdgetpid = 520;
|
||||||
|
pub const SYS_pselect = 522;
|
||||||
|
pub const SYS_getloginclass = 523;
|
||||||
|
pub const SYS_setloginclass = 524;
|
||||||
|
pub const SYS_rctl_get_racct = 525;
|
||||||
|
pub const SYS_rctl_get_rules = 526;
|
||||||
|
pub const SYS_rctl_get_limits = 527;
|
||||||
|
pub const SYS_rctl_add_rule = 528;
|
||||||
|
pub const SYS_rctl_remove_rule = 529;
|
||||||
|
pub const SYS_posix_fallocate = 530;
|
||||||
|
pub const SYS_posix_fadvise = 531;
|
||||||
|
pub const SYS_wait6 = 532;
|
||||||
|
pub const SYS_cap_rights_limit = 533;
|
||||||
|
pub const SYS_cap_ioctls_limit = 534;
|
||||||
|
pub const SYS_cap_ioctls_get = 535;
|
||||||
|
pub const SYS_cap_fcntls_limit = 536;
|
||||||
|
pub const SYS_cap_fcntls_get = 537;
|
||||||
|
pub const SYS_bindat = 538;
|
||||||
|
pub const SYS_connectat = 539;
|
||||||
|
pub const SYS_chflagsat = 540;
|
||||||
|
pub const SYS_accept4 = 541;
|
||||||
|
pub const SYS_pipe2 = 542;
|
||||||
|
pub const SYS_aio_mlock = 543;
|
||||||
|
pub const SYS_procctl = 544;
|
||||||
|
pub const SYS_ppoll = 545;
|
||||||
|
pub const SYS_futimens = 546;
|
||||||
|
pub const SYS_utimensat = 547;
|
||||||
|
// 548 is obsolete numa_getaffinity
|
||||||
|
// 549 is obsolete numa_setaffinity
|
||||||
|
pub const SYS_fdatasync = 550;
|
||||||
|
pub const SYS_fstat = 551;
|
||||||
|
pub const SYS_fstatat = 552;
|
||||||
|
pub const SYS_fhstat = 553;
|
||||||
|
pub const SYS_getdirentries = 554;
|
||||||
|
pub const SYS_statfs = 555;
|
||||||
|
pub const SYS_fstatfs = 556;
|
||||||
|
pub const SYS_getfsstat = 557;
|
||||||
|
pub const SYS_fhstatfs = 558;
|
||||||
|
pub const SYS_mknodat = 559;
|
||||||
|
pub const SYS_kevent = 560;
|
||||||
|
pub const SYS_cpuset_getdomain = 561;
|
||||||
|
pub const SYS_cpuset_setdomain = 562;
|
||||||
|
pub const SYS_getrandom = 563;
|
||||||
|
pub const SYS_MAXSYSCALL = 564;
|
|
@ -0,0 +1,136 @@
|
||||||
|
const freebsd = @import("index.zig");
|
||||||
|
const socklen_t = freebsd.socklen_t;
|
||||||
|
const iovec = freebsd.iovec;
|
||||||
|
|
||||||
|
pub const SYS_sbrk = 69;
|
||||||
|
|
||||||
|
pub fn syscall0(number: usize) usize {
|
||||||
|
return asm volatile ("syscall"
|
||||||
|
: [ret] "={rax}" (-> usize)
|
||||||
|
: [number] "{rax}" (number)
|
||||||
|
: "rcx", "r11"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn syscall1(number: usize, arg1: usize) usize {
|
||||||
|
return asm volatile ("syscall"
|
||||||
|
: [ret] "={rax}" (-> usize)
|
||||||
|
: [number] "{rax}" (number),
|
||||||
|
[arg1] "{rdi}" (arg1)
|
||||||
|
: "rcx", "r11"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn syscall2(number: usize, arg1: usize, arg2: usize) usize {
|
||||||
|
return asm volatile ("syscall"
|
||||||
|
: [ret] "={rax}" (-> usize)
|
||||||
|
: [number] "{rax}" (number),
|
||||||
|
[arg1] "{rdi}" (arg1),
|
||||||
|
[arg2] "{rsi}" (arg2)
|
||||||
|
: "rcx", "r11"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize {
|
||||||
|
return asm volatile ("syscall"
|
||||||
|
: [ret] "={rax}" (-> usize)
|
||||||
|
: [number] "{rax}" (number),
|
||||||
|
[arg1] "{rdi}" (arg1),
|
||||||
|
[arg2] "{rsi}" (arg2),
|
||||||
|
[arg3] "{rdx}" (arg3)
|
||||||
|
: "rcx", "r11"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
|
||||||
|
return asm volatile ("syscall"
|
||||||
|
: [ret] "={rax}" (-> usize)
|
||||||
|
: [number] "{rax}" (number),
|
||||||
|
[arg1] "{rdi}" (arg1),
|
||||||
|
[arg2] "{rsi}" (arg2),
|
||||||
|
[arg3] "{rdx}" (arg3),
|
||||||
|
[arg4] "{r10}" (arg4)
|
||||||
|
: "rcx", "r11"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
|
||||||
|
return asm volatile ("syscall"
|
||||||
|
: [ret] "={rax}" (-> usize)
|
||||||
|
: [number] "{rax}" (number),
|
||||||
|
[arg1] "{rdi}" (arg1),
|
||||||
|
[arg2] "{rsi}" (arg2),
|
||||||
|
[arg3] "{rdx}" (arg3),
|
||||||
|
[arg4] "{r10}" (arg4),
|
||||||
|
[arg5] "{r8}" (arg5)
|
||||||
|
: "rcx", "r11"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn syscall6(
|
||||||
|
number: usize,
|
||||||
|
arg1: usize,
|
||||||
|
arg2: usize,
|
||||||
|
arg3: usize,
|
||||||
|
arg4: usize,
|
||||||
|
arg5: usize,
|
||||||
|
arg6: usize,
|
||||||
|
) usize {
|
||||||
|
return asm volatile ("syscall"
|
||||||
|
: [ret] "={rax}" (-> usize)
|
||||||
|
: [number] "{rax}" (number),
|
||||||
|
[arg1] "{rdi}" (arg1),
|
||||||
|
[arg2] "{rsi}" (arg2),
|
||||||
|
[arg3] "{rdx}" (arg3),
|
||||||
|
[arg4] "{r10}" (arg4),
|
||||||
|
[arg5] "{r8}" (arg5),
|
||||||
|
[arg6] "{r9}" (arg6)
|
||||||
|
: "rcx", "r11"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub nakedcc fn restore_rt() void {
|
||||||
|
asm volatile ("syscall"
|
||||||
|
:
|
||||||
|
: [number] "{rax}" (usize(SYS_rt_sigreturn))
|
||||||
|
: "rcx", "r11"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const msghdr = extern struct {
|
||||||
|
msg_name: *u8,
|
||||||
|
msg_namelen: socklen_t,
|
||||||
|
msg_iov: *iovec,
|
||||||
|
msg_iovlen: i32,
|
||||||
|
__pad1: i32,
|
||||||
|
msg_control: *u8,
|
||||||
|
msg_controllen: socklen_t,
|
||||||
|
__pad2: socklen_t,
|
||||||
|
msg_flags: i32,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Renamed to Stat to not conflict with the stat function.
|
||||||
|
pub const Stat = extern struct {
|
||||||
|
dev: u64,
|
||||||
|
ino: u64,
|
||||||
|
nlink: usize,
|
||||||
|
|
||||||
|
mode: u32,
|
||||||
|
uid: u32,
|
||||||
|
gid: u32,
|
||||||
|
__pad0: u32,
|
||||||
|
rdev: u64,
|
||||||
|
size: i64,
|
||||||
|
blksize: isize,
|
||||||
|
blocks: i64,
|
||||||
|
|
||||||
|
atim: timespec,
|
||||||
|
mtim: timespec,
|
||||||
|
ctim: timespec,
|
||||||
|
__unused: [3]isize,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const timespec = extern struct {
|
||||||
|
tv_sec: isize,
|
||||||
|
tv_nsec: isize,
|
||||||
|
};
|
|
@ -43,7 +43,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD
|
||||||
};
|
};
|
||||||
return os.path.join(allocator, home_dir, "Library", "Application Support", appname);
|
return os.path.join(allocator, home_dir, "Library", "Application Support", appname);
|
||||||
},
|
},
|
||||||
builtin.Os.linux => {
|
builtin.Os.linux, builtin.Os.freebsd => {
|
||||||
const home_dir = os.getEnvPosix("HOME") orelse {
|
const home_dir = os.getEnvPosix("HOME") orelse {
|
||||||
// TODO look in /etc/passwd
|
// TODO look in /etc/passwd
|
||||||
return error.AppDataDirUnavailable;
|
return error.AppDataDirUnavailable;
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub const UserInfo = struct {
|
||||||
/// POSIX function which gets a uid from username.
|
/// POSIX function which gets a uid from username.
|
||||||
pub fn getUserInfo(name: []const u8) !UserInfo {
|
pub fn getUserInfo(name: []const u8) !UserInfo {
|
||||||
return switch (builtin.os) {
|
return switch (builtin.os) {
|
||||||
Os.linux, Os.macosx, Os.ios => posixGetUserInfo(name),
|
Os.linux, Os.macosx, Os.ios, Os.freebsd => posixGetUserInfo(name),
|
||||||
else => @compileError("Unsupported OS"),
|
else => @compileError("Unsupported OS"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ const builtin = @import("builtin");
|
||||||
const Os = builtin.Os;
|
const Os = builtin.Os;
|
||||||
const is_windows = builtin.os == Os.windows;
|
const is_windows = builtin.os == Os.windows;
|
||||||
const is_posix = switch (builtin.os) {
|
const is_posix = switch (builtin.os) {
|
||||||
builtin.Os.linux, builtin.Os.macosx => true,
|
builtin.Os.linux, builtin.Os.macosx, builtin.Os.freebsd => true,
|
||||||
else => false,
|
else => false,
|
||||||
};
|
};
|
||||||
const os = @This();
|
const os = @This();
|
||||||
|
@ -24,10 +24,12 @@ test "std.os" {
|
||||||
pub const windows = @import("windows/index.zig");
|
pub const windows = @import("windows/index.zig");
|
||||||
pub const darwin = @import("darwin.zig");
|
pub const darwin = @import("darwin.zig");
|
||||||
pub const linux = @import("linux/index.zig");
|
pub const linux = @import("linux/index.zig");
|
||||||
|
pub const freebsd = @import("freebsd/index.zig");
|
||||||
pub const zen = @import("zen.zig");
|
pub const zen = @import("zen.zig");
|
||||||
pub const posix = switch (builtin.os) {
|
pub const posix = switch (builtin.os) {
|
||||||
Os.linux => linux,
|
Os.linux => linux,
|
||||||
Os.macosx, Os.ios => darwin,
|
Os.macosx, Os.ios => darwin,
|
||||||
|
Os.freebsd => freebsd,
|
||||||
Os.zen => zen,
|
Os.zen => zen,
|
||||||
else => @compileError("Unsupported OS"),
|
else => @compileError("Unsupported OS"),
|
||||||
};
|
};
|
||||||
|
@ -40,7 +42,7 @@ pub const time = @import("time.zig");
|
||||||
|
|
||||||
pub const page_size = 4 * 1024;
|
pub const page_size = 4 * 1024;
|
||||||
pub const MAX_PATH_BYTES = switch (builtin.os) {
|
pub const MAX_PATH_BYTES = switch (builtin.os) {
|
||||||
Os.linux, Os.macosx, Os.ios => posix.PATH_MAX,
|
Os.linux, Os.macosx, Os.ios, Os.freebsd => posix.PATH_MAX,
|
||||||
// Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
|
// Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
|
||||||
// If it would require 4 UTF-8 bytes, then there would be a surrogate
|
// If it would require 4 UTF-8 bytes, then there would be a surrogate
|
||||||
// pair in the UTF-16LE, and we (over)account 3 bytes for it that way.
|
// pair in the UTF-16LE, and we (over)account 3 bytes for it that way.
|
||||||
|
@ -101,7 +103,7 @@ const math = std.math;
|
||||||
/// library implementation.
|
/// library implementation.
|
||||||
pub fn getRandomBytes(buf: []u8) !void {
|
pub fn getRandomBytes(buf: []u8) !void {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
Os.linux => while (true) {
|
Os.linux, Os.freebsd => while (true) {
|
||||||
// TODO check libc version and potentially call c.getrandom.
|
// TODO check libc version and potentially call c.getrandom.
|
||||||
// See #397
|
// See #397
|
||||||
const errno = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0));
|
const errno = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0));
|
||||||
|
@ -174,7 +176,7 @@ pub fn abort() noreturn {
|
||||||
c.abort();
|
c.abort();
|
||||||
}
|
}
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
Os.linux, Os.macosx, Os.ios => {
|
Os.linux, Os.macosx, Os.ios, Os.freebsd => {
|
||||||
_ = posix.raise(posix.SIGABRT);
|
_ = posix.raise(posix.SIGABRT);
|
||||||
_ = posix.raise(posix.SIGKILL);
|
_ = posix.raise(posix.SIGKILL);
|
||||||
while (true) {}
|
while (true) {}
|
||||||
|
@ -196,7 +198,7 @@ pub fn exit(status: u8) noreturn {
|
||||||
c.exit(status);
|
c.exit(status);
|
||||||
}
|
}
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
Os.linux, Os.macosx, Os.ios => {
|
Os.linux, Os.macosx, Os.ios, Os.freebsd => {
|
||||||
posix.exit(status);
|
posix.exit(status);
|
||||||
},
|
},
|
||||||
Os.windows => {
|
Os.windows => {
|
||||||
|
@ -419,7 +421,7 @@ pub fn posix_pwritev(fd: i32, iov: [*]const posix.iovec_const, count: usize, off
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
builtin.Os.linux => while (true) {
|
builtin.Os.linux, builtin.Os.freebsd => while (true) {
|
||||||
const rc = posix.pwritev(fd, iov, count, offset);
|
const rc = posix.pwritev(fd, iov, count, offset);
|
||||||
const err = posix.getErrno(rc);
|
const err = posix.getErrno(rc);
|
||||||
switch (err) {
|
switch (err) {
|
||||||
|
@ -457,6 +459,7 @@ pub const PosixOpenError = error{
|
||||||
NoSpaceLeft,
|
NoSpaceLeft,
|
||||||
NotDir,
|
NotDir,
|
||||||
PathAlreadyExists,
|
PathAlreadyExists,
|
||||||
|
DeviceBusy,
|
||||||
|
|
||||||
/// See https://github.com/ziglang/zig/issues/1396
|
/// See https://github.com/ziglang/zig/issues/1396
|
||||||
Unexpected,
|
Unexpected,
|
||||||
|
@ -495,6 +498,7 @@ pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 {
|
||||||
posix.ENOTDIR => return PosixOpenError.NotDir,
|
posix.ENOTDIR => return PosixOpenError.NotDir,
|
||||||
posix.EPERM => return PosixOpenError.AccessDenied,
|
posix.EPERM => return PosixOpenError.AccessDenied,
|
||||||
posix.EEXIST => return PosixOpenError.PathAlreadyExists,
|
posix.EEXIST => return PosixOpenError.PathAlreadyExists,
|
||||||
|
posix.EBUSY => return PosixOpenError.DeviceBusy,
|
||||||
else => return unexpectedErrorPosix(err),
|
else => return unexpectedErrorPosix(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -687,7 +691,7 @@ pub fn getBaseAddress() usize {
|
||||||
};
|
};
|
||||||
return phdr - @sizeOf(ElfHeader);
|
return phdr - @sizeOf(ElfHeader);
|
||||||
},
|
},
|
||||||
builtin.Os.macosx => return @ptrToInt(&std.c._mh_execute_header),
|
builtin.Os.macosx, builtin.Os.freebsd => return @ptrToInt(&std.c._mh_execute_header),
|
||||||
builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)),
|
builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)),
|
||||||
else => @compileError("Unsupported OS"),
|
else => @compileError("Unsupported OS"),
|
||||||
}
|
}
|
||||||
|
@ -700,8 +704,8 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
|
||||||
errdefer result.deinit();
|
errdefer result.deinit();
|
||||||
|
|
||||||
if (is_windows) {
|
if (is_windows) {
|
||||||
const ptr = windows.GetEnvironmentStringsA() orelse return error.OutOfMemory;
|
const ptr = windows.GetEnvironmentStringsW() orelse return error.OutOfMemory;
|
||||||
defer assert(windows.FreeEnvironmentStringsA(ptr) != 0);
|
defer assert(windows.FreeEnvironmentStringsW(ptr) != 0);
|
||||||
|
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -710,17 +714,21 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
|
||||||
const key_start = i;
|
const key_start = i;
|
||||||
|
|
||||||
while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {}
|
while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {}
|
||||||
const key = ptr[key_start..i];
|
const key_w = ptr[key_start..i];
|
||||||
|
const key = try std.unicode.utf16leToUtf8Alloc(allocator, key_w);
|
||||||
|
errdefer allocator.free(key);
|
||||||
|
|
||||||
if (ptr[i] == '=') i += 1;
|
if (ptr[i] == '=') i += 1;
|
||||||
|
|
||||||
const value_start = i;
|
const value_start = i;
|
||||||
while (ptr[i] != 0) : (i += 1) {}
|
while (ptr[i] != 0) : (i += 1) {}
|
||||||
const value = ptr[value_start..i];
|
const value_w = ptr[value_start..i];
|
||||||
|
const value = try std.unicode.utf16leToUtf8Alloc(allocator, value_w);
|
||||||
|
errdefer allocator.free(value);
|
||||||
|
|
||||||
i += 1; // skip over null byte
|
i += 1; // skip over null byte
|
||||||
|
|
||||||
try result.set(key, value);
|
try result.setMove(key, value);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (posix_environ_raw) |ptr| {
|
for (posix_environ_raw) |ptr| {
|
||||||
|
@ -738,6 +746,11 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "os.getEnvMap" {
|
||||||
|
var env = try getEnvMap(std.debug.global_allocator);
|
||||||
|
defer env.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
/// TODO make this go through libc when we have it
|
/// TODO make this go through libc when we have it
|
||||||
pub fn getEnvPosix(key: []const u8) ?[]const u8 {
|
pub fn getEnvPosix(key: []const u8) ?[]const u8 {
|
||||||
for (posix_environ_raw) |ptr| {
|
for (posix_environ_raw) |ptr| {
|
||||||
|
@ -758,21 +771,24 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 {
|
||||||
pub const GetEnvVarOwnedError = error{
|
pub const GetEnvVarOwnedError = error{
|
||||||
OutOfMemory,
|
OutOfMemory,
|
||||||
EnvironmentVariableNotFound,
|
EnvironmentVariableNotFound,
|
||||||
|
|
||||||
|
/// See https://github.com/ziglang/zig/issues/1774
|
||||||
|
InvalidUtf8,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Caller must free returned memory.
|
/// Caller must free returned memory.
|
||||||
/// TODO make this go through libc when we have it
|
/// TODO make this go through libc when we have it
|
||||||
pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 {
|
pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 {
|
||||||
if (is_windows) {
|
if (is_windows) {
|
||||||
const key_with_null = try cstr.addNullByte(allocator, key);
|
const key_with_null = try std.unicode.utf8ToUtf16LeWithNull(allocator, key);
|
||||||
defer allocator.free(key_with_null);
|
defer allocator.free(key_with_null);
|
||||||
|
|
||||||
var buf = try allocator.alloc(u8, 256);
|
var buf = try allocator.alloc(u16, 256);
|
||||||
errdefer allocator.free(buf);
|
defer allocator.free(buf);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const windows_buf_len = math.cast(windows.DWORD, buf.len) catch return error.OutOfMemory;
|
const windows_buf_len = math.cast(windows.DWORD, buf.len) catch return error.OutOfMemory;
|
||||||
const result = windows.GetEnvironmentVariableA(key_with_null.ptr, buf.ptr, windows_buf_len);
|
const result = windows.GetEnvironmentVariableW(key_with_null.ptr, buf.ptr, windows_buf_len);
|
||||||
|
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
const err = windows.GetLastError();
|
const err = windows.GetLastError();
|
||||||
|
@ -786,11 +802,16 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result > buf.len) {
|
if (result > buf.len) {
|
||||||
buf = try allocator.realloc(u8, buf, result);
|
buf = try allocator.realloc(u16, buf, result);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return allocator.shrink(u8, buf, result);
|
return std.unicode.utf16leToUtf8Alloc(allocator, buf) catch |err| switch (err) {
|
||||||
|
error.DanglingSurrogateHalf => return error.InvalidUtf8,
|
||||||
|
error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8,
|
||||||
|
error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8,
|
||||||
|
error.OutOfMemory => return error.OutOfMemory,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const result = getEnvPosix(key) orelse return error.EnvironmentVariableNotFound;
|
const result = getEnvPosix(key) orelse return error.EnvironmentVariableNotFound;
|
||||||
|
@ -798,6 +819,11 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "os.getEnvVarOwned" {
|
||||||
|
var ga = debug.global_allocator;
|
||||||
|
debug.assertError(getEnvVarOwned(ga, "BADENV"), error.EnvironmentVariableNotFound);
|
||||||
|
}
|
||||||
|
|
||||||
/// Caller must free the returned memory.
|
/// Caller must free the returned memory.
|
||||||
pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {
|
pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {
|
||||||
var buf: [MAX_PATH_BYTES]u8 = undefined;
|
var buf: [MAX_PATH_BYTES]u8 = undefined;
|
||||||
|
@ -1305,7 +1331,7 @@ pub fn deleteDirC(dir_path: [*]const u8) DeleteDirError!void {
|
||||||
const dir_path_w = try windows_util.cStrToPrefixedFileW(dir_path);
|
const dir_path_w = try windows_util.cStrToPrefixedFileW(dir_path);
|
||||||
return deleteDirW(&dir_path_w);
|
return deleteDirW(&dir_path_w);
|
||||||
},
|
},
|
||||||
Os.linux, Os.macosx, Os.ios => {
|
Os.linux, Os.macosx, Os.ios, Os.freebsd => {
|
||||||
const err = posix.getErrno(posix.rmdir(dir_path));
|
const err = posix.getErrno(posix.rmdir(dir_path));
|
||||||
switch (err) {
|
switch (err) {
|
||||||
0 => return,
|
0 => return,
|
||||||
|
@ -1348,7 +1374,7 @@ pub fn deleteDir(dir_path: []const u8) DeleteDirError!void {
|
||||||
const dir_path_w = try windows_util.sliceToPrefixedFileW(dir_path);
|
const dir_path_w = try windows_util.sliceToPrefixedFileW(dir_path);
|
||||||
return deleteDirW(&dir_path_w);
|
return deleteDirW(&dir_path_w);
|
||||||
},
|
},
|
||||||
Os.linux, Os.macosx, Os.ios => {
|
Os.linux, Os.macosx, Os.ios, Os.freebsd => {
|
||||||
const dir_path_c = try toPosixPath(dir_path);
|
const dir_path_c = try toPosixPath(dir_path);
|
||||||
return deleteDirC(&dir_path_c);
|
return deleteDirC(&dir_path_c);
|
||||||
},
|
},
|
||||||
|
@ -1378,6 +1404,7 @@ const DeleteTreeError = error{
|
||||||
FileSystem,
|
FileSystem,
|
||||||
FileBusy,
|
FileBusy,
|
||||||
DirNotEmpty,
|
DirNotEmpty,
|
||||||
|
DeviceBusy,
|
||||||
|
|
||||||
/// On Windows, file paths must be valid Unicode.
|
/// On Windows, file paths must be valid Unicode.
|
||||||
InvalidUtf8,
|
InvalidUtf8,
|
||||||
|
@ -1439,6 +1466,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError!
|
||||||
error.Unexpected,
|
error.Unexpected,
|
||||||
error.InvalidUtf8,
|
error.InvalidUtf8,
|
||||||
error.BadPathName,
|
error.BadPathName,
|
||||||
|
error.DeviceBusy,
|
||||||
=> return err,
|
=> return err,
|
||||||
};
|
};
|
||||||
defer dir.close();
|
defer dir.close();
|
||||||
|
@ -1465,7 +1493,7 @@ pub const Dir = struct {
|
||||||
allocator: *Allocator,
|
allocator: *Allocator,
|
||||||
|
|
||||||
pub const Handle = switch (builtin.os) {
|
pub const Handle = switch (builtin.os) {
|
||||||
Os.macosx, Os.ios => struct {
|
Os.macosx, Os.ios, Os.freebsd => struct {
|
||||||
fd: i32,
|
fd: i32,
|
||||||
seek: i64,
|
seek: i64,
|
||||||
buf: []u8,
|
buf: []u8,
|
||||||
|
@ -1521,6 +1549,7 @@ pub const Dir = struct {
|
||||||
OutOfMemory,
|
OutOfMemory,
|
||||||
InvalidUtf8,
|
InvalidUtf8,
|
||||||
BadPathName,
|
BadPathName,
|
||||||
|
DeviceBusy,
|
||||||
|
|
||||||
/// See https://github.com/ziglang/zig/issues/1396
|
/// See https://github.com/ziglang/zig/issues/1396
|
||||||
Unexpected,
|
Unexpected,
|
||||||
|
@ -1541,7 +1570,7 @@ pub const Dir = struct {
|
||||||
.name_data = undefined,
|
.name_data = undefined,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
Os.macosx, Os.ios => Handle{
|
Os.macosx, Os.ios, Os.freebsd => Handle{
|
||||||
.fd = try posixOpen(
|
.fd = try posixOpen(
|
||||||
dir_path,
|
dir_path,
|
||||||
posix.O_RDONLY | posix.O_NONBLOCK | posix.O_DIRECTORY | posix.O_CLOEXEC,
|
posix.O_RDONLY | posix.O_NONBLOCK | posix.O_DIRECTORY | posix.O_CLOEXEC,
|
||||||
|
@ -1572,7 +1601,7 @@ pub const Dir = struct {
|
||||||
Os.windows => {
|
Os.windows => {
|
||||||
_ = windows.FindClose(self.handle.handle);
|
_ = windows.FindClose(self.handle.handle);
|
||||||
},
|
},
|
||||||
Os.macosx, Os.ios, Os.linux => {
|
Os.macosx, Os.ios, Os.linux, Os.freebsd => {
|
||||||
self.allocator.free(self.handle.buf);
|
self.allocator.free(self.handle.buf);
|
||||||
os.close(self.handle.fd);
|
os.close(self.handle.fd);
|
||||||
},
|
},
|
||||||
|
@ -1587,6 +1616,7 @@ pub const Dir = struct {
|
||||||
Os.linux => return self.nextLinux(),
|
Os.linux => return self.nextLinux(),
|
||||||
Os.macosx, Os.ios => return self.nextDarwin(),
|
Os.macosx, Os.ios => return self.nextDarwin(),
|
||||||
Os.windows => return self.nextWindows(),
|
Os.windows => return self.nextWindows(),
|
||||||
|
Os.freebsd => return self.nextFreebsd(),
|
||||||
else => @compileError("unimplemented"),
|
else => @compileError("unimplemented"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1726,6 +1756,11 @@ pub const Dir = struct {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn nextFreebsd(self: *Dir) !?Entry {
|
||||||
|
//self.handle.buf = try self.allocator.alloc(u8, page_size);
|
||||||
|
@compileError("TODO implement dirs for FreeBSD");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn changeCurDir(allocator: *Allocator, dir_path: []const u8) !void {
|
pub fn changeCurDir(allocator: *Allocator, dir_path: []const u8) !void {
|
||||||
|
@ -2164,7 +2199,7 @@ pub fn unexpectedErrorWindows(err: windows.DWORD) UnexpectedError {
|
||||||
pub fn openSelfExe() !os.File {
|
pub fn openSelfExe() !os.File {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
Os.linux => return os.File.openReadC(c"/proc/self/exe"),
|
Os.linux => return os.File.openReadC(c"/proc/self/exe"),
|
||||||
Os.macosx, Os.ios => {
|
Os.macosx, Os.ios, Os.freebsd => {
|
||||||
var buf: [MAX_PATH_BYTES]u8 = undefined;
|
var buf: [MAX_PATH_BYTES]u8 = undefined;
|
||||||
const self_exe_path = try selfExePath(&buf);
|
const self_exe_path = try selfExePath(&buf);
|
||||||
buf[self_exe_path.len] = 0;
|
buf[self_exe_path.len] = 0;
|
||||||
|
@ -2181,7 +2216,7 @@ pub fn openSelfExe() !os.File {
|
||||||
|
|
||||||
test "openSelfExe" {
|
test "openSelfExe" {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
Os.linux, Os.macosx, Os.ios, Os.windows => (try openSelfExe()).close(),
|
Os.linux, Os.macosx, Os.ios, Os.windows, Os.freebsd => (try openSelfExe()).close(),
|
||||||
else => return error.SkipZigTest, // Unsupported OS.
|
else => return error.SkipZigTest, // Unsupported OS.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2212,6 +2247,7 @@ pub fn selfExePathW(out_buffer: *[windows_util.PATH_MAX_WIDE]u16) ![]u16 {
|
||||||
pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
|
pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
Os.linux => return readLink(out_buffer, "/proc/self/exe"),
|
Os.linux => return readLink(out_buffer, "/proc/self/exe"),
|
||||||
|
Os.freebsd => return readLink(out_buffer, "/proc/curproc/file"),
|
||||||
Os.windows => {
|
Os.windows => {
|
||||||
var utf16le_buf: [windows_util.PATH_MAX_WIDE]u16 = undefined;
|
var utf16le_buf: [windows_util.PATH_MAX_WIDE]u16 = undefined;
|
||||||
const utf16le_slice = try selfExePathW(&utf16le_buf);
|
const utf16le_slice = try selfExePathW(&utf16le_buf);
|
||||||
|
@ -2250,7 +2286,7 @@ pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) ![]const u8 {
|
||||||
// will not return null.
|
// will not return null.
|
||||||
return path.dirname(full_exe_path).?;
|
return path.dirname(full_exe_path).?;
|
||||||
},
|
},
|
||||||
Os.windows, Os.macosx, Os.ios => {
|
Os.windows, Os.macosx, Os.ios, Os.freebsd => {
|
||||||
const self_exe_path = try selfExePath(out_buffer);
|
const self_exe_path = try selfExePath(out_buffer);
|
||||||
// Assume that the OS APIs return absolute paths, and therefore dirname
|
// Assume that the OS APIs return absolute paths, and therefore dirname
|
||||||
// will not return null.
|
// will not return null.
|
||||||
|
@ -3095,10 +3131,13 @@ pub const CpuCountError = error{
|
||||||
|
|
||||||
pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize {
|
pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize {
|
||||||
switch (builtin.os) {
|
switch (builtin.os) {
|
||||||
builtin.Os.macosx => {
|
builtin.Os.macosx, builtin.Os.freebsd => {
|
||||||
var count: c_int = undefined;
|
var count: c_int = undefined;
|
||||||
var count_len: usize = @sizeOf(c_int);
|
var count_len: usize = @sizeOf(c_int);
|
||||||
const rc = posix.sysctlbyname(c"hw.logicalcpu", @ptrCast(*c_void, &count), &count_len, null, 0);
|
const rc = posix.sysctlbyname(switch (builtin.os) {
|
||||||
|
builtin.Os.macosx => c"hw.logicalcpu",
|
||||||
|
else => c"hw.ncpu",
|
||||||
|
}, @ptrCast(*c_void, &count), &count_len, null, 0);
|
||||||
const err = posix.getErrno(rc);
|
const err = posix.getErrno(rc);
|
||||||
switch (err) {
|
switch (err) {
|
||||||
0 => return @intCast(usize, count),
|
0 => return @intCast(usize, count),
|
||||||
|
|
|
@ -703,7 +703,7 @@ pub fn dup2(old: i32, new: i32) usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dup3(old: i32, new: i32, flags: u32) usize {
|
pub fn dup3(old: i32, new: i32, flags: u32) usize {
|
||||||
return syscall3(SYS_dup3, @intCast(usize, old), @intCast(usize, new), flags);
|
return syscall3(SYS_dup3, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
|
@ -747,7 +747,7 @@ pub fn getcwd(buf: [*]u8, size: usize) usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getdents64(fd: i32, dirp: [*]u8, count: usize) usize {
|
pub fn getdents64(fd: i32, dirp: [*]u8, count: usize) usize {
|
||||||
return syscall3(SYS_getdents64, @intCast(usize, fd), @ptrToInt(dirp), count);
|
return syscall3(SYS_getdents64, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inotify_init1(flags: u32) usize {
|
pub fn inotify_init1(flags: u32) usize {
|
||||||
|
@ -755,16 +755,16 @@ pub fn inotify_init1(flags: u32) usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inotify_add_watch(fd: i32, pathname: [*]const u8, mask: u32) usize {
|
pub fn inotify_add_watch(fd: i32, pathname: [*]const u8, mask: u32) usize {
|
||||||
return syscall3(SYS_inotify_add_watch, @intCast(usize, fd), @ptrToInt(pathname), mask);
|
return syscall3(SYS_inotify_add_watch, @bitCast(usize, isize(fd)), @ptrToInt(pathname), mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inotify_rm_watch(fd: i32, wd: i32) usize {
|
pub fn inotify_rm_watch(fd: i32, wd: i32) usize {
|
||||||
return syscall2(SYS_inotify_rm_watch, @intCast(usize, fd), @intCast(usize, wd));
|
return syscall2(SYS_inotify_rm_watch, @bitCast(usize, isize(fd)), @bitCast(usize, isize(wd)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn isatty(fd: i32) bool {
|
pub fn isatty(fd: i32) bool {
|
||||||
var wsz: winsize = undefined;
|
var wsz: winsize = undefined;
|
||||||
return syscall3(SYS_ioctl, @intCast(usize, fd), TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
|
return syscall3(SYS_ioctl, @bitCast(usize, isize(fd)), TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// 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
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
pub fn readlinkat(dirfd: i32, noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
|
pub fn readlinkat(dirfd: i32, noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
|
||||||
return syscall4(SYS_readlinkat, @intCast(usize, dirfd), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
|
return syscall4(SYS_readlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
|
@ -784,7 +784,7 @@ pub fn mkdir(path: [*]const u8, mode: u32) usize {
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
pub fn mkdirat(dirfd: i32, path: [*]const u8, mode: u32) usize {
|
pub fn mkdirat(dirfd: i32, path: [*]const u8, mode: u32) usize {
|
||||||
return syscall3(SYS_mkdirat, @intCast(usize, dirfd), @ptrToInt(path), mode);
|
return syscall3(SYS_mkdirat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
|
@ -803,7 +803,7 @@ pub fn umount2(special: [*]const u8, flags: u32) usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
|
pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
|
||||||
return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @intCast(usize, fd), @bitCast(usize, offset));
|
return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @bitCast(usize, isize(fd)), @bitCast(usize, offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn munmap(address: usize, length: usize) usize {
|
pub fn munmap(address: usize, length: usize) usize {
|
||||||
|
@ -811,23 +811,23 @@ pub fn munmap(address: usize, length: usize) usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
|
pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
|
||||||
return syscall3(SYS_read, @intCast(usize, fd), @ptrToInt(buf), count);
|
return syscall3(SYS_read, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize {
|
pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize {
|
||||||
return syscall4(SYS_preadv, @intCast(usize, fd), @ptrToInt(iov), count, offset);
|
return syscall4(SYS_preadv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize {
|
pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize {
|
||||||
return syscall3(SYS_readv, @intCast(usize, fd), @ptrToInt(iov), count);
|
return syscall3(SYS_readv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize {
|
pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize {
|
||||||
return syscall3(SYS_writev, @intCast(usize, fd), @ptrToInt(iov), count);
|
return syscall3(SYS_writev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) usize {
|
pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) usize {
|
||||||
return syscall4(SYS_pwritev, @intCast(usize, fd), @ptrToInt(iov), count, offset);
|
return syscall4(SYS_pwritev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
|
@ -842,12 +842,12 @@ pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
pub fn symlinkat(existing: [*]const u8, newfd: i32, newpath: [*]const u8) usize {
|
pub fn symlinkat(existing: [*]const u8, newfd: i32, newpath: [*]const u8) usize {
|
||||||
return syscall3(SYS_symlinkat, @ptrToInt(existing), @intCast(usize, newfd), @ptrToInt(newpath));
|
return syscall3(SYS_symlinkat, @ptrToInt(existing), @bitCast(usize, isize(newfd)), @ptrToInt(newpath));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize {
|
pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize {
|
||||||
return syscall4(SYS_pread, @intCast(usize, fd), @ptrToInt(buf), count, offset);
|
return syscall4(SYS_pread, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
|
@ -856,7 +856,7 @@ pub fn access(path: [*]const u8, mode: u32) usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn faccessat(dirfd: i32, path: [*]const u8, mode: u32) usize {
|
pub fn faccessat(dirfd: i32, path: [*]const u8, mode: u32) usize {
|
||||||
return syscall3(SYS_faccessat, @intCast(usize, dirfd), @ptrToInt(path), mode);
|
return syscall3(SYS_faccessat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pipe(fd: *[2]i32) usize {
|
pub fn pipe(fd: *[2]i32) usize {
|
||||||
|
@ -868,11 +868,11 @@ pub fn pipe2(fd: *[2]i32, flags: u32) usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
|
pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
|
||||||
return syscall3(SYS_write, @intCast(usize, fd), @ptrToInt(buf), count);
|
return syscall3(SYS_write, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
|
pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
|
||||||
return syscall4(SYS_pwrite, @intCast(usize, fd), @ptrToInt(buf), count, offset);
|
return syscall4(SYS_pwrite, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
|
@ -882,7 +882,7 @@ pub fn rename(old: [*]const u8, new: [*]const u8) usize {
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
pub fn renameat2(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const u8, flags: u32) usize {
|
pub fn renameat2(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const u8, flags: u32) usize {
|
||||||
return syscall5(SYS_renameat2, @intCast(usize, oldfd), @ptrToInt(oldpath), @intCast(usize, newfd), @ptrToInt(newpath), flags);
|
return syscall5(SYS_renameat2, @bitCast(usize, isize(oldfd)), @ptrToInt(oldpath), @bitCast(usize, isize(newfd)), @ptrToInt(newpath), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
|
@ -897,7 +897,8 @@ pub fn create(path: [*]const u8, perm: usize) usize {
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
pub fn openat(dirfd: i32, path: [*]const u8, flags: u32, mode: usize) usize {
|
pub fn openat(dirfd: i32, path: [*]const u8, flags: u32, mode: usize) usize {
|
||||||
return syscall4(SYS_openat, @intCast(usize, dirfd), @ptrToInt(path), flags, mode);
|
// dirfd could be negative, for example AT_FDCWD is -100
|
||||||
|
return syscall4(SYS_openat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See also `clone` (from the arch-specific include)
|
/// See also `clone` (from the arch-specific include)
|
||||||
|
@ -911,11 +912,11 @@ pub fn clone2(flags: u32, child_stack_ptr: usize) usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close(fd: i32) usize {
|
pub fn close(fd: i32) usize {
|
||||||
return syscall1(SYS_close, @intCast(usize, fd));
|
return syscall1(SYS_close, @bitCast(usize, isize(fd)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lseek(fd: i32, offset: isize, ref_pos: usize) usize {
|
pub fn lseek(fd: i32, offset: isize, ref_pos: usize) usize {
|
||||||
return syscall3(SYS_lseek, @intCast(usize, fd), @bitCast(usize, offset), ref_pos);
|
return syscall3(SYS_lseek, @bitCast(usize, isize(fd)), @bitCast(usize, offset), ref_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exit(status: i32) noreturn {
|
pub fn exit(status: i32) noreturn {
|
||||||
|
@ -933,7 +934,7 @@ pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kill(pid: i32, sig: i32) usize {
|
pub fn kill(pid: i32, sig: i32) usize {
|
||||||
return syscall2(SYS_kill, @bitCast(usize, isize(pid)), @intCast(usize, sig));
|
return syscall2(SYS_kill, @bitCast(usize, isize(pid)), @bitCast(usize, isize(sig)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
|
@ -943,7 +944,7 @@ pub fn unlink(path: [*]const u8) usize {
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
pub fn unlinkat(dirfd: i32, path: [*]const u8, flags: u32) usize {
|
pub fn unlinkat(dirfd: i32, path: [*]const u8, flags: u32) usize {
|
||||||
return syscall3(SYS_unlinkat, @intCast(usize, dirfd), @ptrToInt(path), flags);
|
return syscall3(SYS_unlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn waitpid(pid: i32, status: *i32, options: i32) usize {
|
pub fn waitpid(pid: i32, status: *i32, options: i32) usize {
|
||||||
|
@ -1120,8 +1121,8 @@ pub const empty_sigset = []usize{0} ** sigset_t.len;
|
||||||
pub fn raise(sig: i32) usize {
|
pub fn raise(sig: i32) usize {
|
||||||
var set: sigset_t = undefined;
|
var set: sigset_t = undefined;
|
||||||
blockAppSignals(&set);
|
blockAppSignals(&set);
|
||||||
const tid = @intCast(i32, syscall0(SYS_gettid));
|
const tid = syscall0(SYS_gettid);
|
||||||
const ret = syscall2(SYS_tkill, @intCast(usize, tid), @intCast(usize, sig));
|
const ret = syscall2(SYS_tkill, tid, @bitCast(usize, isize(sig)));
|
||||||
restoreSignals(&set);
|
restoreSignals(&set);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1189,11 +1190,11 @@ pub const iovec_const = extern struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
|
pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
|
||||||
return syscall3(SYS_getsockname, @intCast(usize, fd), @ptrToInt(addr), @ptrToInt(len));
|
return syscall3(SYS_getsockname, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getpeername(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
|
pub fn getpeername(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
|
||||||
return syscall3(SYS_getpeername, @intCast(usize, fd), @ptrToInt(addr), @ptrToInt(len));
|
return syscall3(SYS_getpeername, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {
|
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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: [*]const u8, optlen: socklen_t) usize {
|
pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: [*]const u8, optlen: socklen_t) usize {
|
||||||
return syscall5(SYS_setsockopt, @intCast(usize, fd), level, optname, @intCast(usize, optval), @ptrToInt(optlen));
|
return syscall5(SYS_setsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @intCast(usize, optlen));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noalias optlen: *socklen_t) usize {
|
pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noalias optlen: *socklen_t) usize {
|
||||||
return syscall5(SYS_getsockopt, @intCast(usize, fd), level, optname, @ptrToInt(optval), @ptrToInt(optlen));
|
return syscall5(SYS_getsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sendmsg(fd: i32, msg: *const msghdr, flags: u32) usize {
|
pub fn sendmsg(fd: i32, msg: *const msghdr, flags: u32) usize {
|
||||||
return syscall3(SYS_sendmsg, @intCast(usize, fd), @ptrToInt(msg), flags);
|
return syscall3(SYS_sendmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize {
|
pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize {
|
||||||
return syscall3(SYS_connect, @intCast(usize, fd), @ptrToInt(addr), len);
|
return syscall3(SYS_connect, @bitCast(usize, isize(fd)), @ptrToInt(addr), len);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize {
|
pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize {
|
||||||
return syscall3(SYS_recvmsg, @intCast(usize, fd), @ptrToInt(msg), flags);
|
return syscall3(SYS_recvmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recvfrom(fd: i32, noalias buf: [*]u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t) usize {
|
pub fn recvfrom(fd: i32, noalias buf: [*]u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t) usize {
|
||||||
return syscall6(SYS_recvfrom, @intCast(usize, fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen));
|
return syscall6(SYS_recvfrom, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shutdown(fd: i32, how: i32) usize {
|
pub fn shutdown(fd: i32, how: i32) usize {
|
||||||
return syscall2(SYS_shutdown, @intCast(usize, fd), @intCast(usize, how));
|
return syscall2(SYS_shutdown, @bitCast(usize, isize(fd)), @bitCast(usize, isize(how)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bind(fd: i32, addr: *const sockaddr, len: socklen_t) usize {
|
pub fn bind(fd: i32, addr: *const sockaddr, len: socklen_t) usize {
|
||||||
return syscall3(SYS_bind, @intCast(usize, fd), @ptrToInt(addr), @intCast(usize, len));
|
return syscall3(SYS_bind, @bitCast(usize, isize(fd)), @ptrToInt(addr), @intCast(usize, len));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn listen(fd: i32, backlog: u32) usize {
|
pub fn listen(fd: i32, backlog: u32) usize {
|
||||||
return syscall2(SYS_listen, @intCast(usize, fd), backlog);
|
return syscall2(SYS_listen, @bitCast(usize, isize(fd)), backlog);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sendto(fd: i32, buf: [*]const u8, len: usize, flags: u32, addr: ?*const sockaddr, alen: socklen_t) usize {
|
pub fn sendto(fd: i32, buf: [*]const u8, len: usize, flags: u32, addr: ?*const sockaddr, alen: socklen_t) usize {
|
||||||
return syscall6(SYS_sendto, @intCast(usize, fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen));
|
return syscall6(SYS_sendto, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) usize {
|
pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) usize {
|
||||||
return syscall4(SYS_socketpair, @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(*fd[0]));
|
return syscall4(SYS_socketpair, @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(&fd[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
|
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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn accept4(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t, flags: u32) usize {
|
pub fn accept4(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t, flags: u32) usize {
|
||||||
return syscall4(SYS_accept4, @intCast(usize, fd), @ptrToInt(addr), @ptrToInt(len), flags);
|
return syscall4(SYS_accept4, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fstat(fd: i32, stat_buf: *Stat) usize {
|
pub fn fstat(fd: i32, stat_buf: *Stat) usize {
|
||||||
return syscall2(SYS_fstat, @intCast(usize, fd), @ptrToInt(stat_buf));
|
return syscall2(SYS_fstat, @bitCast(usize, isize(fd)), @ptrToInt(stat_buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
|
@ -1268,7 +1269,7 @@ pub fn lstat(pathname: [*]const u8, statbuf: *Stat) usize {
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
pub fn fstatat(dirfd: i32, path: [*]const u8, stat_buf: *Stat, flags: u32) usize {
|
pub fn fstatat(dirfd: i32, path: [*]const u8, stat_buf: *Stat, flags: u32) usize {
|
||||||
return syscall4(SYS_fstatat, @intCast(usize, dirfd), @ptrToInt(path), @ptrToInt(stat_buf), flags);
|
return syscall4(SYS_fstatat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
|
@ -1355,7 +1356,7 @@ pub fn epoll_create1(flags: usize) usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: *epoll_event) usize {
|
pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: *epoll_event) usize {
|
||||||
return syscall4(SYS_epoll_ctl, @intCast(usize, epoll_fd), @intCast(usize, op), @intCast(usize, fd), @ptrToInt(ev));
|
return syscall4(SYS_epoll_ctl, @bitCast(usize, isize(epoll_fd)), @intCast(usize, op), @bitCast(usize, isize(fd)), @ptrToInt(ev));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize {
|
pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize {
|
||||||
|
@ -1363,7 +1364,15 @@ pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn epoll_pwait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32, sigmask: ?*sigset_t) usize {
|
pub fn epoll_pwait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32, sigmask: ?*sigset_t) usize {
|
||||||
return syscall6(SYS_epoll_pwait, @intCast(usize, epoll_fd), @ptrToInt(events), @intCast(usize, maxevents), @intCast(usize, timeout), @ptrToInt(sigmask), @sizeOf(sigset_t));
|
return syscall6(
|
||||||
|
SYS_epoll_pwait,
|
||||||
|
@bitCast(usize, isize(epoll_fd)),
|
||||||
|
@ptrToInt(events),
|
||||||
|
@intCast(usize, maxevents),
|
||||||
|
@bitCast(usize, isize(timeout)),
|
||||||
|
@ptrToInt(sigmask),
|
||||||
|
@sizeOf(sigset_t),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eventfd(count: u32, flags: u32) usize {
|
pub fn eventfd(count: u32, flags: u32) usize {
|
||||||
|
@ -1371,7 +1380,7 @@ pub fn eventfd(count: u32, flags: u32) usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn timerfd_create(clockid: i32, flags: u32) usize {
|
pub fn timerfd_create(clockid: i32, flags: u32) usize {
|
||||||
return syscall2(SYS_timerfd_create, @intCast(usize, clockid), flags);
|
return syscall2(SYS_timerfd_create, @bitCast(usize, isize(clockid)), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const itimerspec = extern struct {
|
pub const itimerspec = extern struct {
|
||||||
|
@ -1380,11 +1389,11 @@ pub const itimerspec = extern struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize {
|
pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize {
|
||||||
return syscall2(SYS_timerfd_gettime, @intCast(usize, fd), @ptrToInt(curr_value));
|
return syscall2(SYS_timerfd_gettime, @bitCast(usize, isize(fd)), @ptrToInt(curr_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn timerfd_settime(fd: i32, flags: u32, new_value: *const itimerspec, old_value: ?*itimerspec) usize {
|
pub fn timerfd_settime(fd: i32, flags: u32, new_value: *const itimerspec, old_value: ?*itimerspec) usize {
|
||||||
return syscall4(SYS_timerfd_settime, @intCast(usize, fd), flags, @ptrToInt(new_value), @ptrToInt(old_value));
|
return syscall4(SYS_timerfd_settime, @bitCast(usize, isize(fd)), flags, @ptrToInt(new_value), @ptrToInt(old_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const _LINUX_CAPABILITY_VERSION_1 = 0x19980330;
|
pub const _LINUX_CAPABILITY_VERSION_1 = 0x19980330;
|
||||||
|
|
|
@ -1093,6 +1093,7 @@ pub const RealError = error{
|
||||||
NoSpaceLeft,
|
NoSpaceLeft,
|
||||||
FileSystem,
|
FileSystem,
|
||||||
BadPathName,
|
BadPathName,
|
||||||
|
DeviceBusy,
|
||||||
|
|
||||||
/// On Windows, file paths must be valid Unicode.
|
/// On Windows, file paths must be valid Unicode.
|
||||||
InvalidUtf8,
|
InvalidUtf8,
|
||||||
|
@ -1183,11 +1184,20 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro
|
||||||
const fd = try os.posixOpenC(pathname, posix.O_PATH | posix.O_NONBLOCK | posix.O_CLOEXEC, 0);
|
const fd = try os.posixOpenC(pathname, posix.O_PATH | posix.O_NONBLOCK | posix.O_CLOEXEC, 0);
|
||||||
defer os.close(fd);
|
defer os.close(fd);
|
||||||
|
|
||||||
var buf: ["/proc/self/fd/-2147483648".len]u8 = undefined;
|
var buf: ["/proc/self/fd/-2147483648\x00".len]u8 = undefined;
|
||||||
const proc_path = fmt.bufPrint(buf[0..], "/proc/self/fd/{}\x00", fd) catch unreachable;
|
const proc_path = fmt.bufPrint(buf[0..], "/proc/self/fd/{}\x00", fd) catch unreachable;
|
||||||
|
|
||||||
return os.readLinkC(out_buffer, proc_path.ptr);
|
return os.readLinkC(out_buffer, proc_path.ptr);
|
||||||
},
|
},
|
||||||
|
Os.freebsd => { // XXX requires fdescfs
|
||||||
|
const fd = try os.posixOpenC(pathname, posix.O_PATH | posix.O_NONBLOCK | posix.O_CLOEXEC, 0);
|
||||||
|
defer os.close(fd);
|
||||||
|
|
||||||
|
var buf: ["/dev/fd/-2147483648\x00".len]u8 = undefined;
|
||||||
|
const proc_path = fmt.bufPrint(buf[0..], "/dev/fd/{}\x00", fd) catch unreachable;
|
||||||
|
|
||||||
|
return os.readLinkC(out_buffer, proc_path.ptr);
|
||||||
|
},
|
||||||
else => @compileError("TODO implement os.path.real for " ++ @tagName(builtin.os)),
|
else => @compileError("TODO implement os.path.real for " ++ @tagName(builtin.os)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1202,7 +1212,7 @@ pub fn real(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: []const u8) RealError!
|
||||||
const pathname_w = try windows_util.sliceToPrefixedFileW(pathname);
|
const pathname_w = try windows_util.sliceToPrefixedFileW(pathname);
|
||||||
return realW(out_buffer, &pathname_w);
|
return realW(out_buffer, &pathname_w);
|
||||||
},
|
},
|
||||||
Os.macosx, Os.ios, Os.linux => {
|
Os.macosx, Os.ios, Os.linux, Os.freebsd => {
|
||||||
const pathname_c = try os.toPosixPath(pathname);
|
const pathname_c = try os.toPosixPath(pathname);
|
||||||
return realC(out_buffer, &pathname_c);
|
return realC(out_buffer, &pathname_c);
|
||||||
},
|
},
|
||||||
|
|
|
@ -50,7 +50,7 @@ pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFi
|
||||||
pub extern "kernel32" stdcallcc fn FindClose(hFindFile: HANDLE) BOOL;
|
pub extern "kernel32" stdcallcc fn FindClose(hFindFile: HANDLE) BOOL;
|
||||||
pub extern "kernel32" stdcallcc fn FindNextFileW(hFindFile: HANDLE, lpFindFileData: *WIN32_FIND_DATAW) BOOL;
|
pub extern "kernel32" stdcallcc fn FindNextFileW(hFindFile: HANDLE, lpFindFileData: *WIN32_FIND_DATAW) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsA(penv: [*]u8) BOOL;
|
pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsW(penv: [*]u16) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR;
|
pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR;
|
||||||
|
|
||||||
|
@ -63,9 +63,9 @@ pub extern "kernel32" stdcallcc fn GetCurrentDirectoryW(nBufferLength: DWORD, lp
|
||||||
pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE;
|
pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE;
|
||||||
pub extern "kernel32" stdcallcc fn GetCurrentThreadId() DWORD;
|
pub extern "kernel32" stdcallcc fn GetCurrentThreadId() DWORD;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() ?[*]u8;
|
pub extern "kernel32" stdcallcc fn GetEnvironmentStringsW() ?[*]u16;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) DWORD;
|
pub extern "kernel32" stdcallcc fn GetEnvironmentVariableW(lpName: LPWSTR, lpBuffer: LPWSTR, nSize: DWORD) DWORD;
|
||||||
|
|
||||||
pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: *DWORD) BOOL;
|
pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: *DWORD) BOOL;
|
||||||
|
|
||||||
|
|
|
@ -12,20 +12,20 @@ pub const Message = struct {
|
||||||
args: [5]usize,
|
args: [5]usize,
|
||||||
payload: ?[]const u8,
|
payload: ?[]const u8,
|
||||||
|
|
||||||
pub fn from(mailbox_id: *const MailboxId) Message {
|
pub fn from(mailbox_id: MailboxId) Message {
|
||||||
return Message{
|
return Message{
|
||||||
.sender = MailboxId.Undefined,
|
.sender = MailboxId.Undefined,
|
||||||
.receiver = mailbox_id.*,
|
.receiver = mailbox_id,
|
||||||
.code = undefined,
|
.code = undefined,
|
||||||
.args = undefined,
|
.args = undefined,
|
||||||
.payload = null,
|
.payload = null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to(mailbox_id: *const MailboxId, msg_code: usize, args: ...) Message {
|
pub fn to(mailbox_id: MailboxId, msg_code: usize, args: ...) Message {
|
||||||
var message = Message{
|
var message = Message{
|
||||||
.sender = MailboxId.This,
|
.sender = MailboxId.This,
|
||||||
.receiver = mailbox_id.*,
|
.receiver = mailbox_id,
|
||||||
.code = msg_code,
|
.code = msg_code,
|
||||||
.args = undefined,
|
.args = undefined,
|
||||||
.payload = null,
|
.payload = null,
|
||||||
|
@ -40,14 +40,14 @@ pub const Message = struct {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as(self: *const Message, sender: *const MailboxId) Message {
|
pub fn as(self: Message, sender: MailboxId) Message {
|
||||||
var message = self.*;
|
var message = self;
|
||||||
message.sender = sender.*;
|
message.sender = sender;
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn withPayload(self: *const Message, payload: []const u8) Message {
|
pub fn withPayload(self: Message, payload: []const u8) Message {
|
||||||
var message = self.*;
|
var message = self;
|
||||||
message.payload = payload;
|
message.payload = payload;
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
|
||||||
STDIN_FILENO => {
|
STDIN_FILENO => {
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < count) : (i += 1) {
|
while (i < count) : (i += 1) {
|
||||||
send(Message.to(Server.Keyboard, 0));
|
send(&Message.to(Server.Keyboard, 0));
|
||||||
|
|
||||||
// FIXME: we should be certain that we are receiving from Keyboard.
|
// FIXME: we should be certain that we are receiving from Keyboard.
|
||||||
var message = Message.from(MailboxId.This);
|
var message = Message.from(MailboxId.This);
|
||||||
|
@ -111,7 +111,7 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
|
||||||
pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
|
pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
|
||||||
switch (fd) {
|
switch (fd) {
|
||||||
STDOUT_FILENO, STDERR_FILENO => {
|
STDOUT_FILENO, STDERR_FILENO => {
|
||||||
send(Message.to(Server.Terminal, 1).withPayload(buf[0..count]));
|
send(&Message.to(Server.Terminal, 1).withPayload(buf[0..count]));
|
||||||
},
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ pub const DbiStreamHeader = packed struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const SectionContribEntry = packed struct {
|
pub const SectionContribEntry = packed struct {
|
||||||
|
/// COFF Section index, 1-based
|
||||||
Section: u16,
|
Section: u16,
|
||||||
Padding1: [2]u8,
|
Padding1: [2]u8,
|
||||||
Offset: u32,
|
Offset: u32,
|
||||||
|
@ -507,11 +508,11 @@ const Msf = struct {
|
||||||
allocator,
|
allocator,
|
||||||
);
|
);
|
||||||
|
|
||||||
const stream_count = try self.directory.stream.readIntLe(u32);
|
const stream_count = try self.directory.stream.readIntLittle(u32);
|
||||||
|
|
||||||
const stream_sizes = try allocator.alloc(u32, stream_count);
|
const stream_sizes = try allocator.alloc(u32, stream_count);
|
||||||
for (stream_sizes) |*s| {
|
for (stream_sizes) |*s| {
|
||||||
const size = try self.directory.stream.readIntLe(u32);
|
const size = try self.directory.stream.readIntLittle(u32);
|
||||||
s.* = blockCountFromSize(size, superblock.BlockSize);
|
s.* = blockCountFromSize(size, superblock.BlockSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -602,7 +603,7 @@ const MsfStream = struct {
|
||||||
|
|
||||||
var i: u32 = 0;
|
var i: u32 = 0;
|
||||||
while (i < block_count) : (i += 1) {
|
while (i < block_count) : (i += 1) {
|
||||||
stream.blocks[i] = try in.readIntLe(u32);
|
stream.blocks[i] = try in.readIntLittle(u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
return stream;
|
return stream;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
// ```
|
// ```
|
||||||
// var buf: [8]u8 = undefined;
|
// var buf: [8]u8 = undefined;
|
||||||
// try std.os.getRandomBytes(buf[0..]);
|
// try std.os.getRandomBytes(buf[0..]);
|
||||||
// const seed = mem.readIntLE(u64, buf[0..8]);
|
// const seed = mem.readIntSliceLittle(u64, buf[0..8]);
|
||||||
//
|
//
|
||||||
// var r = DefaultPrng.init(seed);
|
// var r = DefaultPrng.init(seed);
|
||||||
//
|
//
|
||||||
|
@ -52,11 +52,24 @@ pub const Random = struct {
|
||||||
// use LE instead of native endian for better portability maybe?
|
// use LE instead of native endian for better portability maybe?
|
||||||
// TODO: endian portability is pointless if the underlying prng isn't endian portable.
|
// TODO: endian portability is pointless if the underlying prng isn't endian portable.
|
||||||
// TODO: document the endian portability of this library.
|
// TODO: document the endian portability of this library.
|
||||||
const byte_aligned_result = mem.readIntLE(ByteAlignedT, rand_bytes);
|
const byte_aligned_result = mem.readIntSliceLittle(ByteAlignedT, rand_bytes);
|
||||||
const unsigned_result = @truncate(UnsignedT, byte_aligned_result);
|
const unsigned_result = @truncate(UnsignedT, byte_aligned_result);
|
||||||
return @bitCast(T, unsigned_result);
|
return @bitCast(T, unsigned_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constant-time implementation off ::uintLessThan.
|
||||||
|
/// The results of this function may be biased.
|
||||||
|
pub fn uintLessThanBiased(r: *Random, comptime T: type, less_than: T) T {
|
||||||
|
comptime assert(T.is_signed == false);
|
||||||
|
comptime assert(T.bit_count <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation!
|
||||||
|
assert(0 < less_than);
|
||||||
|
if (T.bit_count <= 32) {
|
||||||
|
return @intCast(T, limitRangeBiased(u32, r.int(u32), less_than));
|
||||||
|
} else {
|
||||||
|
return @intCast(T, limitRangeBiased(u64, r.int(u64), less_than));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns an evenly distributed random unsigned integer `0 <= i < less_than`.
|
/// Returns an evenly distributed random unsigned integer `0 <= i < less_than`.
|
||||||
/// This function assumes that the underlying ::fillFn produces evenly distributed values.
|
/// This function assumes that the underlying ::fillFn produces evenly distributed values.
|
||||||
/// Within this assumption, the runtime of this function is exponentially distributed.
|
/// Within this assumption, the runtime of this function is exponentially distributed.
|
||||||
|
@ -64,27 +77,52 @@ pub const Random = struct {
|
||||||
/// the runtime of this function would technically be unbounded.
|
/// the runtime of this function would technically be unbounded.
|
||||||
/// However, if ::fillFn is backed by any evenly distributed pseudo random number generator,
|
/// However, if ::fillFn is backed by any evenly distributed pseudo random number generator,
|
||||||
/// this function is guaranteed to return.
|
/// this function is guaranteed to return.
|
||||||
/// If you need deterministic runtime bounds, consider instead using `r.int(T) % less_than`,
|
/// If you need deterministic runtime bounds, use `::uintLessThanBiased`.
|
||||||
/// which will usually be biased toward smaller values.
|
|
||||||
pub fn uintLessThan(r: *Random, comptime T: type, less_than: T) T {
|
pub fn uintLessThan(r: *Random, comptime T: type, less_than: T) T {
|
||||||
assert(T.is_signed == false);
|
comptime assert(T.is_signed == false);
|
||||||
|
comptime assert(T.bit_count <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation!
|
||||||
assert(0 < less_than);
|
assert(0 < less_than);
|
||||||
|
// Small is typically u32
|
||||||
|
const Small = @IntType(false, @divTrunc(T.bit_count + 31, 32) * 32);
|
||||||
|
// Large is typically u64
|
||||||
|
const Large = @IntType(false, Small.bit_count * 2);
|
||||||
|
|
||||||
const last_group_size_minus_one: T = maxInt(T) % less_than;
|
// adapted from:
|
||||||
if (last_group_size_minus_one == less_than - 1) {
|
// http://www.pcg-random.org/posts/bounded-rands.html
|
||||||
// less_than is a power of two.
|
// "Lemire's (with an extra tweak from me)"
|
||||||
assert(math.floorPowerOfTwo(T, less_than) == less_than);
|
var x: Small = r.int(Small);
|
||||||
// There is no retry zone. The optimal retry_zone_start would be maxInt(T) + 1.
|
var m: Large = Large(x) * Large(less_than);
|
||||||
return r.int(T) % less_than;
|
var l: Small = @truncate(Small, m);
|
||||||
}
|
if (l < less_than) {
|
||||||
const retry_zone_start = maxInt(T) - last_group_size_minus_one;
|
// TODO: workaround for https://github.com/ziglang/zig/issues/1770
|
||||||
|
// should be:
|
||||||
|
// var t: Small = -%less_than;
|
||||||
|
var t: Small = @bitCast(Small, -%@bitCast(@IntType(true, Small.bit_count), Small(less_than)));
|
||||||
|
|
||||||
while (true) {
|
if (t >= less_than) {
|
||||||
const rand_val = r.int(T);
|
t -= less_than;
|
||||||
if (rand_val < retry_zone_start) {
|
if (t >= less_than) {
|
||||||
return rand_val % less_than;
|
t %= less_than;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
while (l < t) {
|
||||||
|
x = r.int(Small);
|
||||||
|
m = Large(x) * Large(less_than);
|
||||||
|
l = @truncate(Small, m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return @intCast(T, m >> Small.bit_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constant-time implementation off ::uintAtMost.
|
||||||
|
/// The results of this function may be biased.
|
||||||
|
pub fn uintAtMostBiased(r: *Random, comptime T: type, at_most: T) T {
|
||||||
|
assert(T.is_signed == false);
|
||||||
|
if (at_most == maxInt(T)) {
|
||||||
|
// have the full range
|
||||||
|
return r.int(T);
|
||||||
|
}
|
||||||
|
return r.uintLessThanBiased(T, at_most + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`.
|
/// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`.
|
||||||
|
@ -99,6 +137,23 @@ pub const Random = struct {
|
||||||
return r.uintLessThan(T, at_most + 1);
|
return r.uintLessThan(T, at_most + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constant-time implementation off ::intRangeLessThan.
|
||||||
|
/// The results of this function may be biased.
|
||||||
|
pub fn intRangeLessThanBiased(r: *Random, comptime T: type, at_least: T, less_than: T) T {
|
||||||
|
assert(at_least < less_than);
|
||||||
|
if (T.is_signed) {
|
||||||
|
// Two's complement makes this math pretty easy.
|
||||||
|
const UnsignedT = @IntType(false, T.bit_count);
|
||||||
|
const lo = @bitCast(UnsignedT, at_least);
|
||||||
|
const hi = @bitCast(UnsignedT, less_than);
|
||||||
|
const result = lo +% r.uintLessThanBiased(UnsignedT, hi -% lo);
|
||||||
|
return @bitCast(T, result);
|
||||||
|
} else {
|
||||||
|
// The signed implementation would work fine, but we can use stricter arithmetic operators here.
|
||||||
|
return at_least + r.uintLessThanBiased(T, less_than - at_least);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns an evenly distributed random integer `at_least <= i < less_than`.
|
/// Returns an evenly distributed random integer `at_least <= i < less_than`.
|
||||||
/// See ::uintLessThan, which this function uses in most cases,
|
/// See ::uintLessThan, which this function uses in most cases,
|
||||||
/// for commentary on the runtime of this function.
|
/// for commentary on the runtime of this function.
|
||||||
|
@ -117,6 +172,23 @@ pub const Random = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constant-time implementation off ::intRangeAtMostBiased.
|
||||||
|
/// The results of this function may be biased.
|
||||||
|
pub fn intRangeAtMostBiased(r: *Random, comptime T: type, at_least: T, at_most: T) T {
|
||||||
|
assert(at_least <= at_most);
|
||||||
|
if (T.is_signed) {
|
||||||
|
// Two's complement makes this math pretty easy.
|
||||||
|
const UnsignedT = @IntType(false, T.bit_count);
|
||||||
|
const lo = @bitCast(UnsignedT, at_least);
|
||||||
|
const hi = @bitCast(UnsignedT, at_most);
|
||||||
|
const result = lo +% r.uintAtMostBiased(UnsignedT, hi -% lo);
|
||||||
|
return @bitCast(T, result);
|
||||||
|
} else {
|
||||||
|
// The signed implementation would work fine, but we can use stricter arithmetic operators here.
|
||||||
|
return at_least + r.uintAtMostBiased(T, at_most - at_least);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns an evenly distributed random integer `at_least <= i <= at_most`.
|
/// Returns an evenly distributed random integer `at_least <= i <= at_most`.
|
||||||
/// See ::uintLessThan, which this function uses in most cases,
|
/// See ::uintLessThan, which this function uses in most cases,
|
||||||
/// for commentary on the runtime of this function.
|
/// for commentary on the runtime of this function.
|
||||||
|
@ -135,15 +207,11 @@ pub const Random = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a random integer/boolean type.
|
|
||||||
/// TODO: deprecated. use ::boolean or ::int instead.
|
/// TODO: deprecated. use ::boolean or ::int instead.
|
||||||
pub fn scalar(r: *Random, comptime T: type) T {
|
pub fn scalar(r: *Random, comptime T: type) T {
|
||||||
if (T == bool) return r.boolean();
|
return if (T == bool) r.boolean() else r.int(T);
|
||||||
return r.int(T);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a random integer with even distribution between `start`
|
|
||||||
/// inclusive and `end` exclusive. `start` must be less than `end`.
|
|
||||||
/// TODO: deprecated. renamed to ::intRangeLessThan
|
/// TODO: deprecated. renamed to ::intRangeLessThan
|
||||||
pub fn range(r: *Random, comptime T: type, start: T, end: T) T {
|
pub fn range(r: *Random, comptime T: type, start: T, end: T) T {
|
||||||
return r.intRangeLessThan(T, start, end);
|
return r.intRangeLessThan(T, start, end);
|
||||||
|
@ -206,6 +274,20 @@ pub const Random = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Convert a random integer 0 <= random_int <= maxValue(T),
|
||||||
|
/// into an integer 0 <= result < less_than.
|
||||||
|
/// This function introduces a minor bias.
|
||||||
|
pub fn limitRangeBiased(comptime T: type, random_int: T, less_than: T) T {
|
||||||
|
comptime assert(T.is_signed == false);
|
||||||
|
const T2 = @IntType(false, T.bit_count * 2);
|
||||||
|
|
||||||
|
// adapted from:
|
||||||
|
// http://www.pcg-random.org/posts/bounded-rands.html
|
||||||
|
// "Integer Multiplication (Biased)"
|
||||||
|
var m: T2 = T2(random_int) * T2(less_than);
|
||||||
|
return @intCast(T, m >> T.bit_count);
|
||||||
|
}
|
||||||
|
|
||||||
const SequentialPrng = struct {
|
const SequentialPrng = struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
random: Random,
|
random: Random,
|
||||||
|
@ -294,10 +376,19 @@ fn testRandomIntLessThan() void {
|
||||||
var r = SequentialPrng.init();
|
var r = SequentialPrng.init();
|
||||||
r.next_value = 0xff;
|
r.next_value = 0xff;
|
||||||
assert(r.random.uintLessThan(u8, 4) == 3);
|
assert(r.random.uintLessThan(u8, 4) == 3);
|
||||||
r.next_value = 0xff;
|
assert(r.next_value == 0);
|
||||||
assert(r.random.uintLessThan(u8, 3) == 0);
|
assert(r.random.uintLessThan(u8, 4) == 0);
|
||||||
assert(r.next_value == 1);
|
assert(r.next_value == 1);
|
||||||
|
|
||||||
|
r.next_value = 0;
|
||||||
|
assert(r.random.uintLessThan(u64, 32) == 0);
|
||||||
|
|
||||||
|
// trigger the bias rejection code path
|
||||||
|
r.next_value = 0;
|
||||||
|
assert(r.random.uintLessThan(u8, 3) == 0);
|
||||||
|
// verify we incremented twice
|
||||||
|
assert(r.next_value == 2);
|
||||||
|
|
||||||
r.next_value = 0xff;
|
r.next_value = 0xff;
|
||||||
assert(r.random.intRangeLessThan(u8, 0, 0x80) == 0x7f);
|
assert(r.random.intRangeLessThan(u8, 0, 0x80) == 0x7f);
|
||||||
r.next_value = 0xff;
|
r.next_value = 0xff;
|
||||||
|
@ -310,17 +401,10 @@ fn testRandomIntLessThan() void {
|
||||||
r.next_value = 0xff;
|
r.next_value = 0xff;
|
||||||
assert(r.random.intRangeLessThan(i8, -0x80, 0) == -1);
|
assert(r.random.intRangeLessThan(i8, -0x80, 0) == -1);
|
||||||
|
|
||||||
r.next_value = 0xff;
|
|
||||||
assert(r.random.intRangeLessThan(i64, -0x8000000000000000, 0) == -1);
|
|
||||||
r.next_value = 0xff;
|
r.next_value = 0xff;
|
||||||
assert(r.random.intRangeLessThan(i3, -4, 0) == -1);
|
assert(r.random.intRangeLessThan(i3, -4, 0) == -1);
|
||||||
r.next_value = 0xff;
|
r.next_value = 0xff;
|
||||||
assert(r.random.intRangeLessThan(i3, -2, 2) == 1);
|
assert(r.random.intRangeLessThan(i3, -2, 2) == 1);
|
||||||
|
|
||||||
// test retrying and eventually getting a good value
|
|
||||||
// start just out of bounds
|
|
||||||
r.next_value = 0x81;
|
|
||||||
assert(r.random.uintLessThan(u8, 0x81) == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "Random intAtMost" {
|
test "Random intAtMost" {
|
||||||
|
@ -332,9 +416,14 @@ fn testRandomIntAtMost() void {
|
||||||
var r = SequentialPrng.init();
|
var r = SequentialPrng.init();
|
||||||
r.next_value = 0xff;
|
r.next_value = 0xff;
|
||||||
assert(r.random.uintAtMost(u8, 3) == 3);
|
assert(r.random.uintAtMost(u8, 3) == 3);
|
||||||
r.next_value = 0xff;
|
assert(r.next_value == 0);
|
||||||
|
assert(r.random.uintAtMost(u8, 3) == 0);
|
||||||
|
|
||||||
|
// trigger the bias rejection code path
|
||||||
|
r.next_value = 0;
|
||||||
assert(r.random.uintAtMost(u8, 2) == 0);
|
assert(r.random.uintAtMost(u8, 2) == 0);
|
||||||
assert(r.next_value == 1);
|
// verify we incremented twice
|
||||||
|
assert(r.next_value == 2);
|
||||||
|
|
||||||
r.next_value = 0xff;
|
r.next_value = 0xff;
|
||||||
assert(r.random.intRangeAtMost(u8, 0, 0x7f) == 0x7f);
|
assert(r.random.intRangeAtMost(u8, 0, 0x7f) == 0x7f);
|
||||||
|
@ -348,17 +437,43 @@ fn testRandomIntAtMost() void {
|
||||||
r.next_value = 0xff;
|
r.next_value = 0xff;
|
||||||
assert(r.random.intRangeAtMost(i8, -0x80, -1) == -1);
|
assert(r.random.intRangeAtMost(i8, -0x80, -1) == -1);
|
||||||
|
|
||||||
r.next_value = 0xff;
|
|
||||||
assert(r.random.intRangeAtMost(i64, -0x8000000000000000, -1) == -1);
|
|
||||||
r.next_value = 0xff;
|
r.next_value = 0xff;
|
||||||
assert(r.random.intRangeAtMost(i3, -4, -1) == -1);
|
assert(r.random.intRangeAtMost(i3, -4, -1) == -1);
|
||||||
r.next_value = 0xff;
|
r.next_value = 0xff;
|
||||||
assert(r.random.intRangeAtMost(i3, -2, 1) == 1);
|
assert(r.random.intRangeAtMost(i3, -2, 1) == 1);
|
||||||
|
|
||||||
// test retrying and eventually getting a good value
|
assert(r.random.uintAtMost(u0, 0) == 0);
|
||||||
// start just out of bounds
|
}
|
||||||
r.next_value = 0x81;
|
|
||||||
assert(r.random.uintAtMost(u8, 0x80) == 0);
|
test "Random Biased" {
|
||||||
|
var r = DefaultPrng.init(0);
|
||||||
|
// Not thoroughly checking the logic here.
|
||||||
|
// Just want to execute all the paths with different types.
|
||||||
|
|
||||||
|
assert(r.random.uintLessThanBiased(u1, 1) == 0);
|
||||||
|
assert(r.random.uintLessThanBiased(u32, 10) < 10);
|
||||||
|
assert(r.random.uintLessThanBiased(u64, 20) < 20);
|
||||||
|
|
||||||
|
assert(r.random.uintAtMostBiased(u0, 0) == 0);
|
||||||
|
assert(r.random.uintAtMostBiased(u1, 0) <= 0);
|
||||||
|
assert(r.random.uintAtMostBiased(u32, 10) <= 10);
|
||||||
|
assert(r.random.uintAtMostBiased(u64, 20) <= 20);
|
||||||
|
|
||||||
|
assert(r.random.intRangeLessThanBiased(u1, 0, 1) == 0);
|
||||||
|
assert(r.random.intRangeLessThanBiased(i1, -1, 0) == -1);
|
||||||
|
assert(r.random.intRangeLessThanBiased(u32, 10, 20) >= 10);
|
||||||
|
assert(r.random.intRangeLessThanBiased(i32, 10, 20) >= 10);
|
||||||
|
assert(r.random.intRangeLessThanBiased(u64, 20, 40) >= 20);
|
||||||
|
assert(r.random.intRangeLessThanBiased(i64, 20, 40) >= 20);
|
||||||
|
|
||||||
|
// uncomment for broken module error:
|
||||||
|
//assert(r.random.intRangeAtMostBiased(u0, 0, 0) == 0);
|
||||||
|
assert(r.random.intRangeAtMostBiased(u1, 0, 1) >= 0);
|
||||||
|
assert(r.random.intRangeAtMostBiased(i1, -1, 0) >= -1);
|
||||||
|
assert(r.random.intRangeAtMostBiased(u32, 10, 20) >= 10);
|
||||||
|
assert(r.random.intRangeAtMostBiased(i32, 10, 20) >= 10);
|
||||||
|
assert(r.random.intRangeAtMostBiased(u64, 20, 40) >= 20);
|
||||||
|
assert(r.random.intRangeAtMostBiased(i64, 20, 40) >= 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generator to extend 64-bit seed values into longer sequences.
|
// Generator to extend 64-bit seed values into longer sequences.
|
||||||
|
@ -870,12 +985,16 @@ test "Random range" {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testRange(r: *Random, start: i8, end: i8) void {
|
fn testRange(r: *Random, start: i8, end: i8) void {
|
||||||
|
testRangeBias(r, start, end, true);
|
||||||
|
testRangeBias(r, start, end, false);
|
||||||
|
}
|
||||||
|
fn testRangeBias(r: *Random, start: i8, end: i8, biased: bool) void {
|
||||||
const count = @intCast(usize, i32(end) - i32(start));
|
const count = @intCast(usize, i32(end) - i32(start));
|
||||||
var values_buffer = []bool{false} ** 0x100;
|
var values_buffer = []bool{false} ** 0x100;
|
||||||
const values = values_buffer[0..count];
|
const values = values_buffer[0..count];
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < count) {
|
while (i < count) {
|
||||||
const value: i32 = r.intRangeLessThan(i8, start, end);
|
const value: i32 = if (biased) r.intRangeLessThanBiased(i8, start, end) else r.intRangeLessThan(i8, start, end);
|
||||||
const index = @intCast(usize, value - start);
|
const index = @intCast(usize, value - start);
|
||||||
if (!values[index]) {
|
if (!values[index]) {
|
||||||
i += 1;
|
i += 1;
|
||||||
|
|
|
@ -12,7 +12,7 @@ const std = @import("../index.zig");
|
||||||
const math = std.math;
|
const math = std.math;
|
||||||
const Random = std.rand.Random;
|
const Random = std.rand.Random;
|
||||||
|
|
||||||
pub fn next_f64(random: *Random, comptime tables: *const ZigTable) f64 {
|
pub fn next_f64(random: *Random, comptime tables: ZigTable) f64 {
|
||||||
while (true) {
|
while (true) {
|
||||||
// We manually construct a float from parts as we can avoid an extra random lookup here by
|
// We manually construct a float from parts as we can avoid an extra random lookup here by
|
||||||
// using the unused exponent for the lookup table entry.
|
// using the unused exponent for the lookup table entry.
|
||||||
|
|
|
@ -201,6 +201,11 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
|
||||||
self.dynamic_segments = self.allocator.shrink([*]T, self.dynamic_segments, new_cap_shelf_count);
|
self.dynamic_segments = self.allocator.shrink([*]T, self.dynamic_segments, new_cap_shelf_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn shrink(self: *Self, new_len: usize) void {
|
||||||
|
assert(new_len <= self.len);
|
||||||
|
self.len = new_len;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn uncheckedAt(self: var, index: usize) AtType(@typeOf(self)) {
|
pub fn uncheckedAt(self: var, index: usize) AtType(@typeOf(self)) {
|
||||||
if (index < prealloc_item_count) {
|
if (index < prealloc_item_count) {
|
||||||
return &self.prealloc_segment[index];
|
return &self.prealloc_segment[index];
|
||||||
|
|
|
@ -20,11 +20,18 @@ comptime {
|
||||||
|
|
||||||
nakedcc fn _start() noreturn {
|
nakedcc fn _start() noreturn {
|
||||||
switch (builtin.arch) {
|
switch (builtin.arch) {
|
||||||
builtin.Arch.x86_64 => {
|
builtin.Arch.x86_64 => switch (builtin.os) {
|
||||||
|
builtin.Os.freebsd => {
|
||||||
|
argc_ptr = asm ("lea (%%rdi), %[argc]"
|
||||||
|
: [argc] "=r" (-> [*]usize)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
else => {
|
||||||
argc_ptr = asm ("lea (%%rsp), %[argc]"
|
argc_ptr = asm ("lea (%%rsp), %[argc]"
|
||||||
: [argc] "=r" (-> [*]usize)
|
: [argc] "=r" (-> [*]usize)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
},
|
||||||
builtin.Arch.i386 => {
|
builtin.Arch.i386 => {
|
||||||
argc_ptr = asm ("lea (%%esp), %[argc]"
|
argc_ptr = asm ("lea (%%esp), %[argc]"
|
||||||
: [argc] "=r" (-> [*]usize)
|
: [argc] "=r" (-> [*]usize)
|
||||||
|
@ -50,6 +57,9 @@ extern fn WinMainCRTStartup() noreturn {
|
||||||
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/265
|
// TODO https://github.com/ziglang/zig/issues/265
|
||||||
fn posixCallMainAndExit() noreturn {
|
fn posixCallMainAndExit() noreturn {
|
||||||
|
if (builtin.os == builtin.Os.freebsd) {
|
||||||
|
@setAlignStack(16);
|
||||||
|
}
|
||||||
const argc = argc_ptr[0];
|
const argc = argc_ptr[0];
|
||||||
const argv = @ptrCast([*][*]u8, argc_ptr + 1);
|
const argv = @ptrCast([*][*]u8, argc_ptr + 1);
|
||||||
|
|
||||||
|
|
|
@ -164,7 +164,6 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
|
||||||
\\
|
\\
|
||||||
\\General Options:
|
\\General Options:
|
||||||
\\ --help Print this help and exit
|
\\ --help Print this help and exit
|
||||||
\\ --init Generate a build.zig template
|
|
||||||
\\ --verbose Print commands before executing them
|
\\ --verbose Print commands before executing them
|
||||||
\\ --prefix [path] Override default install prefix
|
\\ --prefix [path] Override default install prefix
|
||||||
\\ --search-prefix [path] Add a path to look for binaries, libraries, headers
|
\\ --search-prefix [path] Add a path to look for binaries, libraries, headers
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
const fixint = @import("fixint.zig").fixint;
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
|
pub extern fn __fixdfdi(a: f64) i64 {
|
||||||
|
@setRuntimeSafety(builtin.is_test);
|
||||||
|
return fixint(f64, i64, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "import fixdfdi" {
|
||||||
|
_ = @import("fixdfdi_test.zig");
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
const __fixdfdi = @import("fixdfdi.zig").__fixdfdi;
|
||||||
|
const std = @import("std");
|
||||||
|
const math = std.math;
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
const warn = std.debug.warn;
|
||||||
|
|
||||||
|
fn test__fixdfdi(a: f64, expected: i64) void {
|
||||||
|
const x = __fixdfdi(a);
|
||||||
|
//warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u64, expected));
|
||||||
|
assert(x == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "fixdfdi" {
|
||||||
|
//warn("\n");
|
||||||
|
|
||||||
|
test__fixdfdi(-math.f64_max, math.minInt(i64));
|
||||||
|
|
||||||
|
test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
|
||||||
|
test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
|
||||||
|
|
||||||
|
test__fixdfdi(-0x1.0000000000000p+127, -0x8000000000000000);
|
||||||
|
test__fixdfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
|
||||||
|
test__fixdfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
|
||||||
|
|
||||||
|
test__fixdfdi(-0x1.0000000000001p+63, -0x8000000000000000);
|
||||||
|
test__fixdfdi(-0x1.0000000000000p+63, -0x8000000000000000);
|
||||||
|
test__fixdfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
|
||||||
|
test__fixdfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
|
||||||
|
|
||||||
|
test__fixdfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000);
|
||||||
|
test__fixdfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000);
|
||||||
|
|
||||||
|
test__fixdfdi(-2.01, -2);
|
||||||
|
test__fixdfdi(-2.0, -2);
|
||||||
|
test__fixdfdi(-1.99, -1);
|
||||||
|
test__fixdfdi(-1.0, -1);
|
||||||
|
test__fixdfdi(-0.99, 0);
|
||||||
|
test__fixdfdi(-0.5, 0);
|
||||||
|
test__fixdfdi(-math.f64_min, 0);
|
||||||
|
test__fixdfdi(0.0, 0);
|
||||||
|
test__fixdfdi(math.f64_min, 0);
|
||||||
|
test__fixdfdi(0.5, 0);
|
||||||
|
test__fixdfdi(0.99, 0);
|
||||||
|
test__fixdfdi(1.0, 1);
|
||||||
|
test__fixdfdi(1.5, 1);
|
||||||
|
test__fixdfdi(1.99, 1);
|
||||||
|
test__fixdfdi(2.0, 2);
|
||||||
|
test__fixdfdi(2.01, 2);
|
||||||
|
|
||||||
|
test__fixdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
|
||||||
|
test__fixdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
|
||||||
|
|
||||||
|
test__fixdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
|
||||||
|
test__fixdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
|
||||||
|
test__fixdfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
|
||||||
|
test__fixdfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
|
||||||
|
|
||||||
|
test__fixdfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
|
||||||
|
test__fixdfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
|
||||||
|
test__fixdfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
|
||||||
|
|
||||||
|
test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
|
||||||
|
test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
|
||||||
|
|
||||||
|
test__fixdfdi(math.f64_max, math.maxInt(i64));
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
const fixint = @import("fixint.zig").fixint;
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
|
pub extern fn __fixdfsi(a: f64) i32 {
|
||||||
|
@setRuntimeSafety(builtin.is_test);
|
||||||
|
return fixint(f64, i32, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "import fixdfsi" {
|
||||||
|
_ = @import("fixdfsi_test.zig");
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
const __fixdfsi = @import("fixdfsi.zig").__fixdfsi;
|
||||||
|
const std = @import("std");
|
||||||
|
const math = std.math;
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
const warn = std.debug.warn;
|
||||||
|
|
||||||
|
fn test__fixdfsi(a: f64, expected: i32) void {
|
||||||
|
const x = __fixdfsi(a);
|
||||||
|
//warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u32, expected));
|
||||||
|
assert(x == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "fixdfsi" {
|
||||||
|
//warn("\n");
|
||||||
|
|
||||||
|
test__fixdfsi(-math.f64_max, math.minInt(i32));
|
||||||
|
|
||||||
|
test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
|
||||||
|
test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
|
||||||
|
|
||||||
|
test__fixdfsi(-0x1.0000000000000p+127, -0x80000000);
|
||||||
|
test__fixdfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
|
||||||
|
test__fixdfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
|
||||||
|
|
||||||
|
test__fixdfsi(-0x1.0000000000001p+63, -0x80000000);
|
||||||
|
test__fixdfsi(-0x1.0000000000000p+63, -0x80000000);
|
||||||
|
test__fixdfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
|
||||||
|
test__fixdfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
|
||||||
|
|
||||||
|
test__fixdfsi(-0x1.FFFFFEp+62, -0x80000000);
|
||||||
|
test__fixdfsi(-0x1.FFFFFCp+62, -0x80000000);
|
||||||
|
|
||||||
|
test__fixdfsi(-0x1.000000p+31, -0x80000000);
|
||||||
|
test__fixdfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0);
|
||||||
|
test__fixdfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);
|
||||||
|
|
||||||
|
test__fixdfsi(-2.01, -2);
|
||||||
|
test__fixdfsi(-2.0, -2);
|
||||||
|
test__fixdfsi(-1.99, -1);
|
||||||
|
test__fixdfsi(-1.0, -1);
|
||||||
|
test__fixdfsi(-0.99, 0);
|
||||||
|
test__fixdfsi(-0.5, 0);
|
||||||
|
test__fixdfsi(-math.f64_min, 0);
|
||||||
|
test__fixdfsi(0.0, 0);
|
||||||
|
test__fixdfsi(math.f64_min, 0);
|
||||||
|
test__fixdfsi(0.5, 0);
|
||||||
|
test__fixdfsi(0.99, 0);
|
||||||
|
test__fixdfsi(1.0, 1);
|
||||||
|
test__fixdfsi(1.5, 1);
|
||||||
|
test__fixdfsi(1.99, 1);
|
||||||
|
test__fixdfsi(2.0, 2);
|
||||||
|
test__fixdfsi(2.01, 2);
|
||||||
|
|
||||||
|
test__fixdfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
|
||||||
|
test__fixdfsi(0x1.FFFFFFp+30, 0x7FFFFFC0);
|
||||||
|
test__fixdfsi(0x1.000000p+31, 0x7FFFFFFF);
|
||||||
|
|
||||||
|
test__fixdfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);
|
||||||
|
test__fixdfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);
|
||||||
|
|
||||||
|
test__fixdfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
|
||||||
|
test__fixdfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
|
||||||
|
test__fixdfsi(0x1.0000000000000p+63, 0x7FFFFFFF);
|
||||||
|
test__fixdfsi(0x1.0000000000001p+63, 0x7FFFFFFF);
|
||||||
|
|
||||||
|
test__fixdfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
|
||||||
|
test__fixdfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
|
||||||
|
test__fixdfsi(0x1.0000000000000p+127, 0x7FFFFFFF);
|
||||||
|
|
||||||
|
test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
|
||||||
|
test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
|
||||||
|
|
||||||
|
test__fixdfsi(math.f64_max, math.maxInt(i32));
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
const fixint = @import("fixint.zig").fixint;
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
|
pub extern fn __fixdfti(a: f64) i128 {
|
||||||
|
@setRuntimeSafety(builtin.is_test);
|
||||||
|
return fixint(f64, i128, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "import fixdfti" {
|
||||||
|
_ = @import("fixdfti_test.zig");
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
const __fixdfti = @import("fixdfti.zig").__fixdfti;
|
||||||
|
const std = @import("std");
|
||||||
|
const math = std.math;
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
const warn = std.debug.warn;
|
||||||
|
|
||||||
|
fn test__fixdfti(a: f64, expected: i128) void {
|
||||||
|
const x = __fixdfti(a);
|
||||||
|
//warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u128, expected));
|
||||||
|
assert(x == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "fixdfti" {
|
||||||
|
//warn("\n");
|
||||||
|
|
||||||
|
test__fixdfti(-math.f64_max, math.minInt(i128));
|
||||||
|
|
||||||
|
test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
|
||||||
|
test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
|
||||||
|
|
||||||
|
test__fixdfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
|
||||||
|
test__fixdfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
|
||||||
|
test__fixdfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);
|
||||||
|
|
||||||
|
test__fixdfti(-0x1.0000000000001p+63, -0x8000000000000800);
|
||||||
|
test__fixdfti(-0x1.0000000000000p+63, -0x8000000000000000);
|
||||||
|
test__fixdfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
|
||||||
|
test__fixdfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
|
||||||
|
|
||||||
|
test__fixdfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);
|
||||||
|
test__fixdfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);
|
||||||
|
|
||||||
|
test__fixdfti(-2.01, -2);
|
||||||
|
test__fixdfti(-2.0, -2);
|
||||||
|
test__fixdfti(-1.99, -1);
|
||||||
|
test__fixdfti(-1.0, -1);
|
||||||
|
test__fixdfti(-0.99, 0);
|
||||||
|
test__fixdfti(-0.5, 0);
|
||||||
|
test__fixdfti(-math.f64_min, 0);
|
||||||
|
test__fixdfti(0.0, 0);
|
||||||
|
test__fixdfti(math.f64_min, 0);
|
||||||
|
test__fixdfti(0.5, 0);
|
||||||
|
test__fixdfti(0.99, 0);
|
||||||
|
test__fixdfti(1.0, 1);
|
||||||
|
test__fixdfti(1.5, 1);
|
||||||
|
test__fixdfti(1.99, 1);
|
||||||
|
test__fixdfti(2.0, 2);
|
||||||
|
test__fixdfti(2.01, 2);
|
||||||
|
|
||||||
|
test__fixdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
|
||||||
|
test__fixdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
|
||||||
|
|
||||||
|
test__fixdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
|
||||||
|
test__fixdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
|
||||||
|
test__fixdfti(0x1.0000000000000p+63, 0x8000000000000000);
|
||||||
|
test__fixdfti(0x1.0000000000001p+63, 0x8000000000000800);
|
||||||
|
|
||||||
|
test__fixdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
|
||||||
|
test__fixdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
|
||||||
|
test__fixdfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
|
||||||
|
|
||||||
|
test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
|
||||||
|
test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
|
||||||
|
|
||||||
|
test__fixdfti(math.f64_max, math.maxInt(i128));
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
const is_test = @import("builtin").is_test;
|
||||||
|
const std = @import("std");
|
||||||
|
const math = std.math;
|
||||||
|
const Log2Int = std.math.Log2Int;
|
||||||
|
const maxInt = std.math.maxInt;
|
||||||
|
const minInt = std.math.minInt;
|
||||||
|
|
||||||
|
const DBG = false;
|
||||||
|
|
||||||
|
pub fn fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t) fixint_t {
|
||||||
|
@setRuntimeSafety(is_test);
|
||||||
|
|
||||||
|
const rep_t = switch (fp_t) {
|
||||||
|
f32 => u32,
|
||||||
|
f64 => u64,
|
||||||
|
f128 => u128,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
const significandBits = switch (fp_t) {
|
||||||
|
f32 => 23,
|
||||||
|
f64 => 52,
|
||||||
|
f128 => 112,
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
|
||||||
|
const typeWidth = rep_t.bit_count;
|
||||||
|
const exponentBits = (typeWidth - significandBits - 1);
|
||||||
|
const signBit = (rep_t(1) << (significandBits + exponentBits));
|
||||||
|
const maxExponent = ((1 << exponentBits) - 1);
|
||||||
|
const exponentBias = (maxExponent >> 1);
|
||||||
|
|
||||||
|
const implicitBit = (rep_t(1) << significandBits);
|
||||||
|
const significandMask = (implicitBit - 1);
|
||||||
|
|
||||||
|
// Break a into sign, exponent, significand
|
||||||
|
const aRep: rep_t = @bitCast(rep_t, a);
|
||||||
|
const absMask = signBit - 1;
|
||||||
|
const aAbs: rep_t = aRep & absMask;
|
||||||
|
|
||||||
|
const negative = (aRep & signBit) != 0;
|
||||||
|
const exponent = @intCast(i32, aAbs >> significandBits) - exponentBias;
|
||||||
|
const significand: rep_t = (aAbs & significandMask) | implicitBit;
|
||||||
|
|
||||||
|
// If exponent is negative, the uint_result is zero.
|
||||||
|
if (exponent < 0) return 0;
|
||||||
|
|
||||||
|
// The unsigned result needs to be large enough to handle an fixint_t or rep_t
|
||||||
|
const fixuint_t = @IntType(false, fixint_t.bit_count);
|
||||||
|
const UintResultType = if (fixint_t.bit_count > rep_t.bit_count) fixuint_t else rep_t;
|
||||||
|
var uint_result: UintResultType = undefined;
|
||||||
|
|
||||||
|
// If the value is too large for the integer type, saturate.
|
||||||
|
if (@intCast(usize, exponent) >= fixint_t.bit_count) {
|
||||||
|
return if (negative) fixint_t(minInt(fixint_t)) else fixint_t(maxInt(fixint_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If 0 <= exponent < significandBits, right shift else left shift
|
||||||
|
if (exponent < significandBits) {
|
||||||
|
uint_result = @intCast(UintResultType, significand) >> @intCast(Log2Int(UintResultType), significandBits - exponent);
|
||||||
|
} else {
|
||||||
|
uint_result = @intCast(UintResultType, significand) << @intCast(Log2Int(UintResultType), exponent - significandBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cast to final signed result
|
||||||
|
if (negative) {
|
||||||
|
return if (uint_result >= -math.minInt(fixint_t)) math.minInt(fixint_t) else -@intCast(fixint_t, uint_result);
|
||||||
|
} else {
|
||||||
|
return if (uint_result >= math.maxInt(fixint_t)) math.maxInt(fixint_t) else @intCast(fixint_t, uint_result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test "import fixint" {
|
||||||
|
_ = @import("fixint_test.zig");
|
||||||
|
}
|
|
@ -0,0 +1,152 @@
|
||||||
|
const is_test = @import("builtin").is_test;
|
||||||
|
const std = @import("std");
|
||||||
|
const math = std.math;
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
const warn = std.debug.warn;
|
||||||
|
|
||||||
|
const fixint = @import("fixint.zig").fixint;
|
||||||
|
|
||||||
|
fn test__fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t, expected: fixint_t) void {
|
||||||
|
const x = fixint(fp_t, fixint_t, a);
|
||||||
|
//warn("a={} x={}:{x} expected={}:{x})\n", a, x, x, expected, expected);
|
||||||
|
assert(x == expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "fixint.i1" {
|
||||||
|
test__fixint(f32, i1, -math.inf_f32, -1);
|
||||||
|
test__fixint(f32, i1, -math.f32_max, -1);
|
||||||
|
test__fixint(f32, i1, -2.0, -1);
|
||||||
|
test__fixint(f32, i1, -1.1, -1);
|
||||||
|
test__fixint(f32, i1, -1.0, -1);
|
||||||
|
test__fixint(f32, i1, -0.9, 0);
|
||||||
|
test__fixint(f32, i1, -0.1, 0);
|
||||||
|
test__fixint(f32, i1, -math.f32_min, 0);
|
||||||
|
test__fixint(f32, i1, -0.0, 0);
|
||||||
|
test__fixint(f32, i1, 0.0, 0);
|
||||||
|
test__fixint(f32, i1, math.f32_min, 0);
|
||||||
|
test__fixint(f32, i1, 0.1, 0);
|
||||||
|
test__fixint(f32, i1, 0.9, 0);
|
||||||
|
test__fixint(f32, i1, 1.0, 0);
|
||||||
|
test__fixint(f32, i1, 2.0, 0);
|
||||||
|
test__fixint(f32, i1, math.f32_max, 0);
|
||||||
|
test__fixint(f32, i1, math.inf_f32, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "fixint.i2" {
|
||||||
|
test__fixint(f32, i2, -math.inf_f32, -2);
|
||||||
|
test__fixint(f32, i2, -math.f32_max, -2);
|
||||||
|
test__fixint(f32, i2, -2.0, -2);
|
||||||
|
test__fixint(f32, i2, -1.9, -1);
|
||||||
|
test__fixint(f32, i2, -1.1, -1);
|
||||||
|
test__fixint(f32, i2, -1.0, -1);
|
||||||
|
test__fixint(f32, i2, -0.9, 0);
|
||||||
|
test__fixint(f32, i2, -0.1, 0);
|
||||||
|
test__fixint(f32, i2, -math.f32_min, 0);
|
||||||
|
test__fixint(f32, i2, -0.0, 0);
|
||||||
|
test__fixint(f32, i2, 0.0, 0);
|
||||||
|
test__fixint(f32, i2, math.f32_min, 0);
|
||||||
|
test__fixint(f32, i2, 0.1, 0);
|
||||||
|
test__fixint(f32, i2, 0.9, 0);
|
||||||
|
test__fixint(f32, i2, 1.0, 1);
|
||||||
|
test__fixint(f32, i2, 2.0, 1);
|
||||||
|
test__fixint(f32, i2, math.f32_max, 1);
|
||||||
|
test__fixint(f32, i2, math.inf_f32, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "fixint.i3" {
|
||||||
|
test__fixint(f32, i3, -math.inf_f32, -4);
|
||||||
|
test__fixint(f32, i3, -math.f32_max, -4);
|
||||||
|
test__fixint(f32, i3, -4.0, -4);
|
||||||
|
test__fixint(f32, i3, -3.0, -3);
|
||||||
|
test__fixint(f32, i3, -2.0, -2);
|
||||||
|
test__fixint(f32, i3, -1.9, -1);
|
||||||
|
test__fixint(f32, i3, -1.1, -1);
|
||||||
|
test__fixint(f32, i3, -1.0, -1);
|
||||||
|
test__fixint(f32, i3, -0.9, 0);
|
||||||
|
test__fixint(f32, i3, -0.1, 0);
|
||||||
|
test__fixint(f32, i3, -math.f32_min, 0);
|
||||||
|
test__fixint(f32, i3, -0.0, 0);
|
||||||
|
test__fixint(f32, i3, 0.0, 0);
|
||||||
|
test__fixint(f32, i3, math.f32_min, 0);
|
||||||
|
test__fixint(f32, i3, 0.1, 0);
|
||||||
|
test__fixint(f32, i3, 0.9, 0);
|
||||||
|
test__fixint(f32, i3, 1.0, 1);
|
||||||
|
test__fixint(f32, i3, 2.0, 2);
|
||||||
|
test__fixint(f32, i3, 3.0, 3);
|
||||||
|
test__fixint(f32, i3, 4.0, 3);
|
||||||
|
test__fixint(f32, i3, math.f32_max, 3);
|
||||||
|
test__fixint(f32, i3, math.inf_f32, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "fixint.i32" {
|
||||||
|
test__fixint(f64, i32, -math.inf_f64, math.minInt(i32));
|
||||||
|
test__fixint(f64, i32, -math.f64_max, math.minInt(i32));
|
||||||
|
test__fixint(f64, i32, f64(math.minInt(i32)), math.minInt(i32));
|
||||||
|
test__fixint(f64, i32, f64(math.minInt(i32))+1, math.minInt(i32)+1);
|
||||||
|
test__fixint(f64, i32, -2.0, -2);
|
||||||
|
test__fixint(f64, i32, -1.9, -1);
|
||||||
|
test__fixint(f64, i32, -1.1, -1);
|
||||||
|
test__fixint(f64, i32, -1.0, -1);
|
||||||
|
test__fixint(f64, i32, -0.9, 0);
|
||||||
|
test__fixint(f64, i32, -0.1, 0);
|
||||||
|
test__fixint(f64, i32, -math.f32_min, 0);
|
||||||
|
test__fixint(f64, i32, -0.0, 0);
|
||||||
|
test__fixint(f64, i32, 0.0, 0);
|
||||||
|
test__fixint(f64, i32, math.f32_min, 0);
|
||||||
|
test__fixint(f64, i32, 0.1, 0);
|
||||||
|
test__fixint(f64, i32, 0.9, 0);
|
||||||
|
test__fixint(f64, i32, 1.0, 1);
|
||||||
|
test__fixint(f64, i32, f64(math.maxInt(i32))-1, math.maxInt(i32)-1);
|
||||||
|
test__fixint(f64, i32, f64(math.maxInt(i32)), math.maxInt(i32));
|
||||||
|
test__fixint(f64, i32, math.f64_max, math.maxInt(i32));
|
||||||
|
test__fixint(f64, i32, math.inf_f64, math.maxInt(i32));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "fixint.i64" {
|
||||||
|
test__fixint(f64, i64, -math.inf_f64, math.minInt(i64));
|
||||||
|
test__fixint(f64, i64, -math.f64_max, math.minInt(i64));
|
||||||
|
test__fixint(f64, i64, f64(math.minInt(i64)), math.minInt(i64));
|
||||||
|
test__fixint(f64, i64, f64(math.minInt(i64))+1, math.minInt(i64));
|
||||||
|
test__fixint(f64, i64, f64(math.minInt(i64)/2), math.minInt(i64)/2);
|
||||||
|
test__fixint(f64, i64, -2.0, -2);
|
||||||
|
test__fixint(f64, i64, -1.9, -1);
|
||||||
|
test__fixint(f64, i64, -1.1, -1);
|
||||||
|
test__fixint(f64, i64, -1.0, -1);
|
||||||
|
test__fixint(f64, i64, -0.9, 0);
|
||||||
|
test__fixint(f64, i64, -0.1, 0);
|
||||||
|
test__fixint(f64, i64, -math.f32_min, 0);
|
||||||
|
test__fixint(f64, i64, -0.0, 0);
|
||||||
|
test__fixint(f64, i64, 0.0, 0);
|
||||||
|
test__fixint(f64, i64, math.f32_min, 0);
|
||||||
|
test__fixint(f64, i64, 0.1, 0);
|
||||||
|
test__fixint(f64, i64, 0.9, 0);
|
||||||
|
test__fixint(f64, i64, 1.0, 1);
|
||||||
|
test__fixint(f64, i64, f64(math.maxInt(i64))-1, math.maxInt(i64));
|
||||||
|
test__fixint(f64, i64, f64(math.maxInt(i64)), math.maxInt(i64));
|
||||||
|
test__fixint(f64, i64, math.f64_max, math.maxInt(i64));
|
||||||
|
test__fixint(f64, i64, math.inf_f64, math.maxInt(i64));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "fixint.i128" {
|
||||||
|
test__fixint(f64, i128, -math.inf_f64, math.minInt(i128));
|
||||||
|
test__fixint(f64, i128, -math.f64_max, math.minInt(i128));
|
||||||
|
test__fixint(f64, i128, f64(math.minInt(i128)), math.minInt(i128));
|
||||||
|
test__fixint(f64, i128, f64(math.minInt(i128))+1, math.minInt(i128));
|
||||||
|
test__fixint(f64, i128, -2.0, -2);
|
||||||
|
test__fixint(f64, i128, -1.9, -1);
|
||||||
|
test__fixint(f64, i128, -1.1, -1);
|
||||||
|
test__fixint(f64, i128, -1.0, -1);
|
||||||
|
test__fixint(f64, i128, -0.9, 0);
|
||||||
|
test__fixint(f64, i128, -0.1, 0);
|
||||||
|
test__fixint(f64, i128, -math.f32_min, 0);
|
||||||
|
test__fixint(f64, i128, -0.0, 0);
|
||||||
|
test__fixint(f64, i128, 0.0, 0);
|
||||||
|
test__fixint(f64, i128, math.f32_min, 0);
|
||||||
|
test__fixint(f64, i128, 0.1, 0);
|
||||||
|
test__fixint(f64, i128, 0.9, 0);
|
||||||
|
test__fixint(f64, i128, 1.0, 1);
|
||||||
|
test__fixint(f64, i128, f64(math.maxInt(i128))-1, math.maxInt(i128));
|
||||||
|
test__fixint(f64, i128, f64(math.maxInt(i128)), math.maxInt(i128));
|
||||||
|
test__fixint(f64, i128, math.f64_max, math.maxInt(i128));
|
||||||
|
test__fixint(f64, i128, math.inf_f64, math.maxInt(i128));
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue