95 Commits

Author SHA1 Message Date
Andrew Kelley
6d44a6222d Release 0.9.1 2022-02-14 13:03:19 -07:00
Andrew Kelley
be097cdba8 langref: correct info about type info of declarations 2022-02-14 12:57:57 -07:00
Al Hoang
9f6b9850ac haiku add missing cimport include for compilation 2022-02-14 12:57:46 -07:00
Tw
f9af406341 Fix preadv/pwritev bug on 64bit platform
Signed-off-by: Tw <wei.tan@intel.com>
2022-02-14 12:48:55 -07:00
Jakub Konka
8bf14231b2 macho: put linker symlink for cache invalidation in zig-cache
Due to differences in where the output gets emitted in stage1 and stage2,
we were putting the symlink next to the binary rather than in `zig-cache`
directory when building with stage2.
2022-02-14 12:48:13 -07:00
Andrew Kelley
d2398cf009 CLI: ignore -lgcc_s when it is redundant with compiler-rt
For some projects, they can't help themselves, -lgcc_s ends up on the
compiler command line even though it does not belong there. In Zig we
know what -lgcc_s does. It's an alternative to compiler-rt. With this
commit we emit a warning telling that it is unnecessary to put such
thing on the command line, and happily ignore it, since we will fulfill
the dependency with compiler-rt.
2022-02-11 12:14:42 -07:00
Andrew Kelley
0d006afb23 Merge pull request #10834 from ziglang/fix-x86-i128-c-abi
stage1: fix x86 i128 C ABI for extern structs
2022-02-11 12:14:32 -07:00
billzez
bf6af1963c update RwLock to use static initialization (#10838) 2022-02-11 12:13:51 -07:00
Andrew Kelley
45d4e2f816 cmake: fix -DZIG_SINGLE_THREADED option
It was still passing --single-threaded instead of -fsingle-threaded.
2022-02-11 12:13:22 -07:00
Andrew Kelley
46c3d9c571 stage2: fix crash_report segfault compile error
Regressed in 05cf69209e.
2022-02-11 12:13:03 -07:00
Andrew Kelley
c4458e1b45 Merge pull request #10813 from marler8997/windowsChildHang
child_process: collectOutputWindows handle broken_pipe from ReadFile
2022-02-11 12:12:49 -07:00
John Schmidt
fbde43524f debug: implement segfault handler for macOS aarch64
Tested on a M1 MacBook Pro, macOS Monterey 12.2.
2022-02-11 12:12:38 -07:00
Andrew Kelley
8e10c80c5f std: fix i386-openbsd failing to build from source
closes #9705
2022-02-07 12:24:19 -07:00
Evan Haas
a8bd36c3d2 std: Allow mem.zeroes to work at comptime with extern union
Fixes #10797
2022-02-07 12:23:56 -07:00
boofexxx
2e95bb0e29 std: fix doc comment typo in os.zig 2022-02-07 12:23:11 -07:00
Kirk Scheibelhut
3c40cf1693 Various documentation fixes
Co-authored-by: Kirk Scheibelhut <kjs@scheibo.com>
Co-authored-by: extrasharp <genericpb@gmail.com>
2022-02-07 12:22:06 -07:00
Kazuki Sakamoto
5cfc22bd36 stage1: Fix missing LLD library 2022-02-07 12:21:59 -07:00
Andrew Kelley
a418c59546 link.MachO: fix merge conflict artifact
This happened from cherry-picking bug fixes from master branch.
2022-02-02 22:13:45 -07:00
Andrew Kelley
a0cd4c0f32 CLI: link_libcpp implies link_libc
Improves a warning message for some cases of using `zig run -lc++`.
2022-02-02 22:11:08 -07:00
Jakub Konka
d107ef8697 Merge pull request #10769 from ziglang/link-lib-fixes
stage2: handle name-qualified imports in sema, add a zerofill sections workaround to incremental macho
2022-02-02 22:10:59 -07:00
Andrew Kelley
cee0f082df Merge pull request #10743 from m-radomski/master
std: correct rounding in parse_hex_float.zig
2022-02-02 22:07:56 -07:00
John Schmidt
23d148e5c7 debug: fix edge cases in macOS debug symbol lookup
This commit fixes two related things:

1. If the loop goes all the way through the slice without a match, on
   the last iteration `mid == symbols.len - 1` which causes
   `&symbols[mid + 1]` to be out of bounds. End one step before that
   instead.

2. If the address we're looking for is greater than the address of the
   last symbol in the slice, we now match it to that symbol. Previously,
   we would miss this case since we only matched if the address was _in
   between_ the address of two symbols.
2022-02-02 22:06:32 -07:00
Jonathan Marler
eace6906ce remove __muloti4 from libc++
fixes https://github.com/ziglang/zig/issues/10719

compiler_rt already provides __muloti4 but libc++ is also providing it and when linking libc++ it causes a crash on my windows x86_64 machine.
2022-02-02 22:04:42 -07:00
Jakub Konka
ac3ac255a2 Merge pull request #10404 from ominitay/iterator
std: Fix using `fs.Dir.Iterator` twice
2022-02-02 22:04:36 -07:00
Jean Dao
69f46cab55 fix argsAlloc buffer size
The buffer `buf` contains N (= `slice_sizes.len`) slices followed by the
N null-terminated arguments. The N null-terminated arguments are stored
in the `contents` array list. Thus, `buf` size should be:
    @sizeOf([]u8) * slice_sizes.len + contents_slice.len

Instead of:
    @sizeOf([]u8) * slice_sizes.len + contents_slice.len + slice_sizes.len

This bug was found thanks to the gpa allocator which checks if freed
size matches allocated sizes for large allocations.
2022-02-02 22:04:02 -07:00
Andrew Kelley
452c35656e ci: azure: update to newer msys2 release 2022-02-02 22:03:55 -07:00
Jonathan S
a24f4d8da4 Fix overflow in std.math.isNormal when applied to -Inf or a negative NaN 2022-02-02 22:03:47 -07:00
John Schmidt
5762b6d218 std.fmt: fix out-of-bounds array write in float printing
This commit fixes an out of bounds write that can occur when
formatting certain float values. The write messes up the stack and
causes incorrect results, segfaults, or nothing at all, depending on the
optimization mode used.

The `errol` function writes the digits of the float into `buffer`
starting from index 1, leaving index 0 untouched, and returns `buffer[1..]`
and the exponent. This is because `roundToPrecision` relies on index 0 being
unused in case the rounding adds a digit (e.g rounding 999.99
to 1000.00). When this happens, pointer arithmetic is used
[here](0e6d2184ca/lib/std/fmt/errol.zig (L61-L65))
to access index 0 and put the ones digit in the right place.

However, `errol3u` contains two special cases: `errolInt` and `errolFixed`,
which return from the function early. For these two special cases
index 0 was never reserved, and the return value contains `buffer`
instead of `buffer[1..]`. This causes the pointer arithmetic in
`roundToPrecision` to write out of bounds, which in the case of
`std.fmt.formatFloatDecimal` messes up the stack and causes undefined behavior.

The fix is to move the slicing of `buffer` to `buffer[1..]` from `errol3u`
to `errol` so that both the default and the special cases operate on the sliced
buffer.
2022-02-02 22:01:47 -07:00
John Schmidt
8b5e4af78e fmt: handle doc comments on struct members
Closes https://github.com/ziglang/zig/issues/10443.
2022-02-02 22:01:38 -07:00
Andrew Kelley
aad6ef1fc3 glibc: version-gate _DYNAMIC_STACK_SIZE_SOURCE
This is a patch to glibc features.h which makes
_DYNAMIC_STACK_SIZE_SOURCE undefined unless the version is >= 2.34.

This feature was introduced with glibc 2.34 and without this patch, code
built against these headers but then run on an older glibc will end up
making a call to sysconf() that returns -1 for the value of SIGSTKSZ
and MINSIGSTKSZ.

Closes #10713
2022-02-02 22:01:09 -07:00
Andrew Kelley
b54f6186ac build.zig: fix single-threaded option
Instead of defaulting to false, just keep the option as optional to
communicate default to the build system.

Fixes one problem with building the compiler for single-threaded
targets.
2022-02-02 22:01:04 -07:00
Andrew Kelley
e2f36c292e std: break up some long lines
This makes packaging Zig for Debian slightly easier since it will no
longer trigger a Lintian warning for long lines.
2022-02-02 22:00:55 -07:00
Andrew Kelley
e9d916571a link: ELF, COFF, WASM: honor the "must_link" flag of positionals
Previously only the MachO linker was honoring the flag.
2022-02-02 22:00:38 -07:00
Andrew Kelley
021c1190af stage2: .stub files are yet another c++ source file extension
however .cu files are a superset of c++.
2022-02-02 22:00:16 -07:00
Andrew Kelley
45cd1114f7 stage2: make cuda file extensions a separate enum tag than c++
follow-up to 2f41bd3be4.
2022-02-02 22:00:12 -07:00
Vesim
d7feeaaa2c fchown: use the 32-bit uid/gid variant of the syscall on 32-bit linux targets 2022-02-02 22:00:06 -07:00
praschke
2b29424efd docs: reorganize @truncate and @intCast for clarity 2022-02-02 22:00:00 -07:00
vnc5
8f89056dc2 fix startup procedure for async WinMain 2022-02-02 21:59:47 -07:00
Philipp Lühmann
e8c4fec1b2 fix precedence in langref or example 2022-02-02 21:59:40 -07:00
Exonorid
ac3d9759ed Added documentation for implicit struct pointer dereferencing 2022-02-02 21:53:00 -07:00
Daniel Saier
922d33e5b9 zig cc: Treat cu files as C++ source files
First step towards #10634.

Treating stub files as C++ allows to use zig c++ as a host
compiler for nvcc.

Treating cu files as C++ allow using zig c++ as a host compiler in
CMake. CMake calls the host compiler with -E on a cu file to identify
the compiler.

Using zig c++ to directly compile CUDA code is untested.
2022-02-02 21:52:52 -07:00
Andrew Kelley
936294e32a Merge pull request #10699 from motiejus/arm64
[linux headers] rename arm64 to aarch64
2022-02-02 21:51:58 -07:00
Andrew Kelley
7e61bdbaa4 zig cc: add --hash-style linker parameter
This is only relevant for ELF files.

I also fixed a bug where passing a zig source file to `zig cc` would
incorrectly punt to clang because it thought there were no positional
arguments.
2022-02-02 21:50:52 -07:00
Josh Hannaford
340bb8198f Update the documentation for std.mem.sliceTo for readability 2022-02-02 21:48:48 -07:00
Andrew Kelley
e37c55bae0 link: Elf, Wasm: forward strip flag when linking with LLD 2022-02-02 21:47:28 -07:00
Andrew Kelley
93545fe74f zig cc: detect more linker args
* --whole-archive, -whole-archive
 * --no-whole-archive, -no-whole-archive
 * -s, --strip-all
 * -S, --strip-debug
2022-02-02 21:46:28 -07:00
Meghan
8ed432fe3c std.crypto.random: Randoms are no longer passed by reference 2022-02-02 21:46:22 -07:00
Andrew Kelley
148b963a60 Merge pull request #10584 from ziglang/macho-rustc-fixes
zld: a couple of fixes which result in better rustc support
2022-02-02 21:45:44 -07:00
Sizhe Zhao
b713ce0249 Avoid duplicate TLS startup symbols 2022-02-02 21:25:40 -07:00
Pablo Santiago Blum de Aguiar
4d5a598599 readUntilDelimiter*: read only if buffer not full
Ref.: #9594
2022-02-02 21:25:03 -07:00
fifty-six
aa8112c847 std/fs: Support XDG_DATA_HOME
This is generally used for user-specific data on linux, with the
default being ~/.local/share
2022-02-02 21:24:40 -07:00
joachimschmidt557
3d52a322ab std: Add some missing termios types to c/linux.zig and os.zig 2022-02-02 21:23:34 -07:00
Andrew Kelley
af844d865f stage1: remove the "referenced here" error note
It's generally noise. The parts where it is useful will need to be
redone to not be annoying for the general case.
2022-02-02 21:22:57 -07:00
Jakub Konka
252fb642d5 macho: do not write out ZEROFILL physically to file
Prior to this change, `__DATA,__bss` and `__DATA,__thread_bss` would
get actually, physically written out to the output file, unnecessarily
filling the output file with 0s.
2022-02-02 21:22:15 -07:00
Daniel Saier
dcbab17b62 glibc: fix passing of __GNU_MINOR__
This was originally introduced in 4d48948b52
but broken immediately afterwards in c8af00c66e.
2022-02-02 21:19:42 -07:00
C-BJ
881e507ac5 Update CONTRIBUTING.md
Delete unavailable content!
2022-02-02 21:19:36 -07:00
Andrew Kelley
18fabd99cc Merge pull request #10475 from lithdew/master
lld: allow for entrypoint symbol name to be set
2022-02-02 21:19:18 -07:00
John Schmidt
afd1f7ed47 Implement segfault handler for macOS x86_64 2022-02-02 21:18:45 -07:00
riverbl
2ac7aefe2f stage2: do not interpret identifier containing underscores (eg: u3_2) as int primitive type 2022-02-02 21:17:25 -07:00
johnLate
bb9399cc5d Fix os.rusage when linking with c library on Linux
Fixes ziglang#10543 on Linux.
2022-02-02 21:17:15 -07:00
riverbl
bc90a2a083 translate-c: Fix issues translating macro define of hex float constant
* Fix incorrect result when the first digit after the decimal point is not 0-9 - eg 0x0.ap0
* Fix compiler panic when the number starts with `0X` with a capital `X` - eg 0X0p0
* Fix compiler panic when the number has a decimal point immediately after `0x` - eg 0x.0p0
2022-02-02 21:15:15 -07:00
Jakub Konka
1e6de105c8 Merge branch 'Jarred-Sumner-patch-1' 2022-02-02 21:14:59 -07:00
Jakub Konka
385b7e4808 Merge pull request #10576 from schmee/macos-resolve-ip
Use libc if_nametoindex for macOS when parsing IPs
2022-02-02 21:12:24 -07:00
Jakub Konka
57d7ad9172 macho: code signature needs to be 16 bytes aligned 2022-02-02 21:10:23 -07:00
Andrew Kelley
e67e15a29a Merge pull request #10587 from xxxbxxx/master
restore compatibility with glibc<=2.33 for global initializers
2022-02-02 21:10:05 -07:00
Marc Tiehuis
06ae13fe35 stage1: fix bigint_init_bigfloat for single-limb negative floats
Fixes #10592.
2022-02-02 21:09:36 -07:00
Jakub Konka
dafbc6eb25 Merge branch 'Luukdegram-linker-eport-symbols' 2022-01-12 12:01:32 -07:00
Andrew Kelley
6f49233ac6 Merge pull request #10572 from Luukdegram/wasm-linker-stack
Stage2: wasm-linker - Place stack at the beginning of the linear memory
2022-01-12 12:00:03 -07:00
riverbl
bb8eef8d24 translate-c: Fix macro define of float constant using scientific notation
Fixes compiler attempting to use null value when translating macro define of float constant using scientific notation with no decimal point
2022-01-12 11:59:30 -07:00
afranchuk
511990c83b Fix a bug in std.Thread.Condition and add a basic Condition test. (#10538)
* Fix FUTEX usage in std.Thread.Condition - It was using an old name.
2022-01-12 11:59:09 -07:00
Andrew Kelley
9fa55ae777 Merge pull request #10566 from fifty-six/master
std.os.uefi improvements/fixes
2022-01-12 11:59:02 -07:00
Evan Haas
53e41682ba translate-c: Handle typedef'ed void return type for functions.
Fixes #10356
2022-01-12 11:58:42 -07:00
Jakub Konka
3542dcad33 zig cc: integration with sysroot arg (#10568)
Prior to this change, even if the use specified the sysroot on the
compiler line like so

```
zig cc --sysroot=/path/to/sdk
```

it would only be used as a prefix to include paths and not as a prefix
for `zig ld` linker.
2022-01-12 11:58:36 -07:00
djg
9b97edb012 std: hash_map: optimize isFree/isTombstone (#10562)
- Add an `Metadata.isFree` helper method.
- Implement `Metadata.isTombstone` and `Metadata.isFree` with `@bitCast` then comparing to a constant. I assume `@bitCast`-then-compare is faster than the old method because it only involves one comparison, and doesn't require bitmasking.
- Summary of benchmarked changes (`gotta-go-fast`, run locally, compared to master):
  - 3/4 of the hash map benchmarks used ~10% fewer cycles
  - The last one (project Euler) shows 4% fewer cycles.
2022-01-12 11:58:24 -07:00
Jakub Konka
1c61038255 Build fs/filesystem libcxx module when targeting GNU Win 2022-01-12 11:57:40 -07:00
Meghan Denny
73cbc13a97 std: fix zig.Ast being called Tree internally 2022-01-12 11:56:45 -07:00
r00ster
adf7c654d4 Add missing package to the langref that's always available 2022-01-12 11:56:10 -07:00
Ryan Liptak
2304dbaba4 Add CANNOT_DELETE as a possible error in os.windows.DeleteFile
Can happen when e.g. trying to delete a file with the Read Only flag set
2022-01-12 11:54:31 -07:00
Andrew Kelley
675590cd44 Merge pull request #10499 from paulsnar/paulsnar/stage1-packed-structs-cabi
stage1: Fix LLVM C ABI type resolution for small packed structs
2022-01-12 11:54:04 -07:00
Vincent Rischmann
4d38f456ea io_uring: improve IO_Uring.copy_cqe
copy_cqes() is not guaranteed to return as many CQEs as provided in the
`wait_nr` argument, meaning the assert in `copy_cqe` can trigger.

Instead, loop until we do get at least one CQE returned.

This mimics the behaviour of liburing's _io_uring_get_cqe.
2022-01-12 11:53:42 -07:00
Andrew Kelley
8771ef897a readme: dynamic logo light/dark 2022-01-12 11:53:28 -07:00
Jimmi Holst Christensen
1676729c66 fmt: Refactor parsing of placeholders into its own function
This saves on comptime format string parsing, as the compiler caches
comptime calls. The catch here, is that parsePlaceHolder cannot take the
placeholder string as a slice. It must take it as an array by value for
the caching to occure.

There is also some logic in here that ensures that the specifier_arg is
always them same slice when the items they contain are the same. This
makes the compiler stamp out less copies of formatType.
2022-01-12 11:53:07 -07:00
Vincent Rischmann
eee395287f io_uring: fix version check in tests
For renameat, unlinkat, mkdirat, symlinkat and linkat the error code
differs between kernel 5.4 which returns EBADF and kernel 5.10 which returns EINVAL.

Fixes #10466
2022-01-12 11:52:11 -07:00
r00ster
419499b252 std.fmt: improve @compileError message 2022-01-12 11:51:26 -07:00
Marian Beermann
47e3deeeaa stage1: fix @errorName null termination 2022-01-12 11:51:10 -07:00
Frank Denis
c4b4192d20 Y++ 2022-01-12 11:50:57 -07:00
Tom Manner
64a2b14f26 Fixed typo in deprecation error for E format specifier where it would instead complain about a specifier of X. 2021-12-31 14:23:59 -07:00
Veikka Tuominen
9a0010b186 stage1: fix access of slice sentinel at comptime 2021-12-31 14:23:49 -07:00
Ali Chraghi
b86aadfa38 std: Skip comptime struct fields in mem.zeroes() (#10406)
closes #9934
2021-12-31 14:22:38 -07:00
Dante Catalfamo
4d9377923d Add BSD Authentication constants (#10376) 2021-12-31 14:21:22 -07:00
Stephen Lumenta
cfc00e743e fix expectStringEndsWith error output.
before it started outputting the actual starting, not ending characters.
2021-12-31 14:20:09 -07:00
Jonathan S
f5cb3fc688 Only check the file's length once in pdb.Msf.init 2021-12-31 14:20:02 -07:00
ominitay
acdb859644 Fix dead link 2021-12-31 14:19:36 -07:00
John Schmidt
20f073dcdd Langref: replace mentions of c_void with anyopaque 2021-12-31 14:19:11 -07:00
Andrew Kelley
69e2b712bc start the 0.9.1 release cycle 2021-12-31 14:17:52 -07:00
146 changed files with 5319 additions and 975 deletions

View File

@@ -26,7 +26,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
set(ZIG_VERSION_MAJOR 0) set(ZIG_VERSION_MAJOR 0)
set(ZIG_VERSION_MINOR 9) set(ZIG_VERSION_MINOR 9)
set(ZIG_VERSION_PATCH 0) set(ZIG_VERSION_PATCH 1)
set(ZIG_VERSION "" CACHE STRING "Override Zig version string. Default is to find out with git.") set(ZIG_VERSION "" CACHE STRING "Override Zig version string. Default is to find out with git.")
if("${ZIG_VERSION}" STREQUAL "") if("${ZIG_VERSION}" STREQUAL "")
@@ -787,7 +787,7 @@ else()
set(ZIG1_RELEASE_ARG -OReleaseFast --strip) set(ZIG1_RELEASE_ARG -OReleaseFast --strip)
endif() endif()
if(ZIG_SINGLE_THREADED) if(ZIG_SINGLE_THREADED)
set(ZIG1_SINGLE_THREADED_ARG "--single-threaded") set(ZIG1_SINGLE_THREADED_ARG "-fsingle-threaded")
else() else()
set(ZIG1_SINGLE_THREADED_ARG "") set(ZIG1_SINGLE_THREADED_ARG "")
endif() endif()

View File

@@ -5,7 +5,6 @@
One of the best ways you can contribute to Zig is to start using it for a One of the best ways you can contribute to Zig is to start using it for a
personal project. Here are some great examples: personal project. Here are some great examples:
* [Oxid](https://github.com/dbandstra/oxid) - arcade style game
* [TM35-Metronome](https://github.com/TM35-Metronome) - tools for modifying and randomizing Pokémon games * [TM35-Metronome](https://github.com/TM35-Metronome) - tools for modifying and randomizing Pokémon games
* [River](https://github.com/ifreund/river/) - a dynamic tiling wayland compositor * [River](https://github.com/ifreund/river/) - a dynamic tiling wayland compositor

View File

@@ -1,6 +1,6 @@
The MIT License (Expat) The MIT License (Expat)
Copyright (c) 2015-2021, Zig contributors Copyright (c) 2015-2022, Zig contributors
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,4 +1,4 @@
![ZIG](https://ziglang.org/zig-logo.svg) ![ZIG](https://ziglang.org/img/zig-logo-dynamic.svg)
A general-purpose programming language and toolchain for maintaining A general-purpose programming language and toolchain for maintaining
**robust**, **optimal**, and **reusable** software. **robust**, **optimal**, and **reusable** software.

View File

@@ -10,13 +10,13 @@ const fs = std.fs;
const InstallDirectoryOptions = std.build.InstallDirectoryOptions; const InstallDirectoryOptions = std.build.InstallDirectoryOptions;
const assert = std.debug.assert; const assert = std.debug.assert;
const zig_version = std.builtin.Version{ .major = 0, .minor = 9, .patch = 0 }; const zig_version = std.builtin.Version{ .major = 0, .minor = 9, .patch = 1 };
pub fn build(b: *Builder) !void { pub fn build(b: *Builder) !void {
b.setPreferredReleaseMode(.ReleaseFast); b.setPreferredReleaseMode(.ReleaseFast);
const mode = b.standardReleaseOptions(); const mode = b.standardReleaseOptions();
const target = b.standardTargetOptions(.{}); const target = b.standardTargetOptions(.{});
const single_threaded = b.option(bool, "single-threaded", "Build artifacts that run in single threaded mode") orelse false; const single_threaded = b.option(bool, "single-threaded", "Build artifacts that run in single threaded mode");
const use_zig_libcxx = b.option(bool, "use-zig-libcxx", "If libc++ is needed, use zig's bundled version, don't try to integrate with the system") orelse false; const use_zig_libcxx = b.option(bool, "use-zig-libcxx", "If libc++ is needed, use zig's bundled version, don't try to integrate with the system") orelse false;
var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig"); var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");

View File

@@ -27,7 +27,7 @@ jobs:
timeoutInMinutes: 360 timeoutInMinutes: 360
steps: steps:
- powershell: | - powershell: |
(New-Object Net.WebClient).DownloadFile("https://github.com/msys2/msys2-installer/releases/download/2021-07-25/msys2-base-x86_64-20210725.sfx.exe", "sfx.exe") (New-Object Net.WebClient).DownloadFile("https://github.com/msys2/msys2-installer/releases/download/2022-01-28/msys2-base-x86_64-20220128.sfx.exe", "sfx.exe")
.\sfx.exe -y -o\ .\sfx.exe -y -o\
displayName: Download/Extract/Install MSYS2 displayName: Download/Extract/Install MSYS2
- script: | - script: |

View File

@@ -49,6 +49,7 @@ else()
FIND_AND_ADD_LLD_LIB(lldELF) FIND_AND_ADD_LLD_LIB(lldELF)
FIND_AND_ADD_LLD_LIB(lldCOFF) FIND_AND_ADD_LLD_LIB(lldCOFF)
FIND_AND_ADD_LLD_LIB(lldWasm) FIND_AND_ADD_LLD_LIB(lldWasm)
FIND_AND_ADD_LLD_LIB(lldMachO)
FIND_AND_ADD_LLD_LIB(lldReaderWriter) FIND_AND_ADD_LLD_LIB(lldReaderWriter)
FIND_AND_ADD_LLD_LIB(lldCore) FIND_AND_ADD_LLD_LIB(lldCore)
FIND_AND_ADD_LLD_LIB(lldYAML) FIND_AND_ADD_LLD_LIB(lldYAML)

View File

@@ -1290,13 +1290,39 @@ test "expectError demo" {
A variable is a unit of {#link|Memory#} storage. A variable is a unit of {#link|Memory#} storage.
</p> </p>
<p> <p>
Variables are never allowed to shadow identifiers from an outer scope.
</p>
<p>
It is generally preferable to use {#syntax#}const{#endsyntax#} rather than It is generally preferable to use {#syntax#}const{#endsyntax#} rather than
{#syntax#}var{#endsyntax#} when declaring a variable. This causes less work for both {#syntax#}var{#endsyntax#} when declaring a variable. This causes less work for both
humans and computers to do when reading code, and creates more optimization opportunities. humans and computers to do when reading code, and creates more optimization opportunities.
</p> </p>
{#header_open|Identifiers#}
<p>
Variable identifiers are never allowed to shadow identifiers from an outer scope.
</p>
<p>
Identifiers must start with an alphabetic character or underscore and may be followed
by any number of alphanumeric characters or underscores.
They must not overlap with any keywords. See {#link|Keyword Reference#}.
</p>
<p>
If a name that does not fit these requirements is needed, such as for linking with external libraries, the {#syntax#}@""{#endsyntax#} syntax may be used.
</p>
{#code_begin|syntax#}
const @"identifier with spaces in it" = 0xff;
const @"1SmallStep4Man" = 112358;
const c = @import("std").c;
pub extern "c" fn @"error"() anyopaque;
pub extern "c" fn @"fstat$INODE64"(fd: c.fd_t, buf: *c.Stat) c_int;
const Color = enum {
red,
@"really red",
};
const color: Color = .@"really red";
{#code_end#}
{#header_close#}
{#header_open|Container Level Variables#} {#header_open|Container Level Variables#}
<p> <p>
Container level variables have static lifetime and are order-independent and lazily analyzed. Container level variables have static lifetime and are order-independent and lazily analyzed.
@@ -1481,7 +1507,7 @@ fn divide(a: i32, b: i32) i32 {
</p> </p>
<p> <p>
Operators such as {#syntax#}+{#endsyntax#} and {#syntax#}-{#endsyntax#} cause undefined behavior on Operators such as {#syntax#}+{#endsyntax#} and {#syntax#}-{#endsyntax#} cause undefined behavior on
integer overflow. Alternative operators are provided for wrapping and saturating arithmetic on all targets. integer overflow. Alternative operators are provided for wrapping and saturating arithmetic on all targets.
{#syntax#}+%{#endsyntax#} and {#syntax#}-%{#endsyntax#} perform wrapping arithmetic {#syntax#}+%{#endsyntax#} and {#syntax#}-%{#endsyntax#} perform wrapping arithmetic
while {#syntax#}+|{#endsyntax#} and {#syntax#}-|{#endsyntax#} perform saturating arithmetic. while {#syntax#}+|{#endsyntax#} and {#syntax#}-|{#endsyntax#} perform saturating arithmetic.
</p> </p>
@@ -2048,7 +2074,7 @@ unwrapped == 1234{#endsyntax#}</pre>
without evaluating {#syntax#}b{#endsyntax#}. Otherwise, returns {#syntax#}b{#endsyntax#}. without evaluating {#syntax#}b{#endsyntax#}. Otherwise, returns {#syntax#}b{#endsyntax#}.
</td> </td>
<td> <td>
<pre>{#syntax#}false or true == true{#endsyntax#}</pre> <pre>{#syntax#}(false or true) == true{#endsyntax#}</pre>
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -2488,32 +2514,32 @@ test "null terminated array" {
or using the shorthand function {#syntax#}std.meta.Vector{#endsyntax#}. or using the shorthand function {#syntax#}std.meta.Vector{#endsyntax#}.
</p> </p>
<p> <p>
Vectors support the same builtin operators as their underlying base types. These operations are performed Vectors support the same builtin operators as their underlying base types. These operations are performed
element-wise, and return a vector of the same length as the input vectors. This includes: element-wise, and return a vector of the same length as the input vectors. This includes:
</p> </p>
<ul> <ul>
<li>Arithmetic ({#syntax#}+{#endsyntax#}, {#syntax#}-{#endsyntax#}, {#syntax#}/{#endsyntax#}, {#syntax#}*{#endsyntax#}, <li>Arithmetic ({#syntax#}+{#endsyntax#}, {#syntax#}-{#endsyntax#}, {#syntax#}/{#endsyntax#}, {#syntax#}*{#endsyntax#},
{#syntax#}@divFloor{#endsyntax#}, {#syntax#}@sqrt{#endsyntax#}, {#syntax#}@ceil{#endsyntax#}, {#syntax#}@divFloor{#endsyntax#}, {#syntax#}@sqrt{#endsyntax#}, {#syntax#}@ceil{#endsyntax#},
{#syntax#}@log{#endsyntax#}, etc.)</li> {#syntax#}@log{#endsyntax#}, etc.)</li>
<li>Bitwise operators ({#syntax#}>>{#endsyntax#}, {#syntax#}<<{#endsyntax#}, {#syntax#}&{#endsyntax#}, <li>Bitwise operators ({#syntax#}>>{#endsyntax#}, {#syntax#}<<{#endsyntax#}, {#syntax#}&{#endsyntax#},
{#syntax#}|{#endsyntax#}, {#syntax#}~{#endsyntax#}, etc.)</li> {#syntax#}|{#endsyntax#}, {#syntax#}~{#endsyntax#}, etc.)</li>
<li>Comparison operators ({#syntax#}<{#endsyntax#}, {#syntax#}>{#endsyntax#}, {#syntax#}=={#endsyntax#}, etc.)</li> <li>Comparison operators ({#syntax#}<{#endsyntax#}, {#syntax#}>{#endsyntax#}, {#syntax#}=={#endsyntax#}, etc.)</li>
</ul> </ul>
<p> <p>
It is prohibited to use a math operator on a mixture of scalars (individual numbers) and vectors. It is prohibited to use a math operator on a mixture of scalars (individual numbers) and vectors.
Zig provides the {#link|@splat#} builtin to easily convert from scalars to vectors, and it supports {#link|@reduce#} Zig provides the {#link|@splat#} builtin to easily convert from scalars to vectors, and it supports {#link|@reduce#}
and array indexing syntax to convert from vectors to scalars. Vectors also support assignment to and from and array indexing syntax to convert from vectors to scalars. Vectors also support assignment to and from
fixed-length arrays with comptime known length. fixed-length arrays with comptime known length.
</p> </p>
<p> <p>
For rearranging elements within and between vectors, Zig provides the {#link|@shuffle#} and {#link|@select#} functions. For rearranging elements within and between vectors, Zig provides the {#link|@shuffle#} and {#link|@select#} functions.
</p> </p>
<p> <p>
Operations on vectors shorter than the target machine's native SIMD size will typically compile to single SIMD Operations on vectors shorter than the target machine's native SIMD size will typically compile to single SIMD
instructions, while vectors longer than the target machine's native SIMD size will compile to multiple SIMD instructions, while vectors longer than the target machine's native SIMD size will compile to multiple SIMD
instructions. If a given operation doesn't have SIMD support on the target architecture, the compiler will default instructions. If a given operation doesn't have SIMD support on the target architecture, the compiler will default
to operating on each vector element one at a time. Zig supports any comptime-known vector length up to 2^32-1, to operating on each vector element one at a time. Zig supports any comptime-known vector length up to 2^32-1,
although small powers of two (2-64) are most typical. Note that excessively long vector lengths (e.g. 2^20) may although small powers of two (2-64) are most typical. Note that excessively long vector lengths (e.g. 2^20) may
result in compiler crashes on current versions of Zig. result in compiler crashes on current versions of Zig.
</p> </p>
{#code_begin|test|vector_example#} {#code_begin|test|vector_example#}
@@ -2563,7 +2589,7 @@ test "Conversion between vectors, arrays, and slices" {
TODO consider suggesting std.MultiArrayList TODO consider suggesting std.MultiArrayList
</p> </p>
{#see_also|@splat|@shuffle|@select|@reduce#} {#see_also|@splat|@shuffle|@select|@reduce#}
{#header_close#} {#header_close#}
{#header_open|Pointers#} {#header_open|Pointers#}
@@ -2582,7 +2608,7 @@ test "Conversion between vectors, arrays, and slices" {
<li>Supports slice syntax: {#syntax#}ptr[start..end]{#endsyntax#}</li> <li>Supports slice syntax: {#syntax#}ptr[start..end]{#endsyntax#}</li>
<li>Supports pointer arithmetic: {#syntax#}ptr + x{#endsyntax#}, {#syntax#}ptr - x{#endsyntax#}</li> <li>Supports pointer arithmetic: {#syntax#}ptr + x{#endsyntax#}, {#syntax#}ptr - x{#endsyntax#}</li>
<li>{#syntax#}T{#endsyntax#} must have a known size, which means that it cannot be <li>{#syntax#}T{#endsyntax#} must have a known size, which means that it cannot be
{#syntax#}c_void{#endsyntax#} or any other {#link|opaque type|opaque#}.</li> {#syntax#}anyopaque{#endsyntax#} or any other {#link|opaque type|opaque#}.</li>
</ul> </ul>
</li> </li>
</ul> </ul>
@@ -2981,8 +3007,8 @@ test "null terminated slice" {
} }
{#code_end#} {#code_end#}
<p> <p>
Sentinel-terminated slices can also be created using a variation of the slice syntax Sentinel-terminated slices can also be created using a variation of the slice syntax
{#syntax#}data[start..end :x]{#endsyntax#}, where {#syntax#}data{#endsyntax#} is a many-item pointer, {#syntax#}data[start..end :x]{#endsyntax#}, where {#syntax#}data{#endsyntax#} is a many-item pointer,
array or slice and {#syntax#}x{#endsyntax#} is the sentinel value. array or slice and {#syntax#}x{#endsyntax#} is the sentinel value.
</p> </p>
{#code_begin|test|null_terminated_slicing#} {#code_begin|test|null_terminated_slicing#}
@@ -2999,7 +3025,7 @@ test "null terminated slicing" {
} }
{#code_end#} {#code_end#}
<p> <p>
Sentinel-terminated slicing asserts that the element in the sentinel position of the backing data is Sentinel-terminated slicing asserts that the element in the sentinel position of the backing data is
actually the sentinel value. If this is not the case, safety-protected {#link|Undefined Behavior#} results. actually the sentinel value. If this is not the case, safety-protected {#link|Undefined Behavior#} results.
</p> </p>
{#code_begin|test_safety|sentinel mismatch#} {#code_begin|test_safety|sentinel mismatch#}
@@ -3008,10 +3034,10 @@ const expect = std.testing.expect;
test "sentinel mismatch" { test "sentinel mismatch" {
var array = [_]u8{ 3, 2, 1, 0 }; var array = [_]u8{ 3, 2, 1, 0 };
// Creating a sentinel-terminated slice from the array with a length of 2 // Creating a sentinel-terminated slice from the array with a length of 2
// will result in the value `1` occupying the sentinel element position. // will result in the value `1` occupying the sentinel element position.
// This does not match the indicated sentinel value of `0` and will lead // This does not match the indicated sentinel value of `0` and will lead
// to a runtime panic. // to a runtime panic.
var runtime_length: usize = 2; var runtime_length: usize = 2;
const slice = array[0..runtime_length :0]; const slice = array[0..runtime_length :0];
@@ -3159,7 +3185,12 @@ test "linked list" {
.last = &node, .last = &node,
.len = 1, .len = 1,
}; };
// When using a pointer to a struct, fields can be accessed directly,
// without explicitly dereferencing the pointer.
// So you can do
try expect(list2.first.?.data == 1234); try expect(list2.first.?.data == 1234);
// instead of try expect(list2.first.?.*.data == 1234);
} }
{#code_end#} {#code_end#}
@@ -3486,7 +3517,7 @@ fn dump(args: anytype) !void {
</p> </p>
<p> <p>
The fields are implicitly named using numbers starting from 0. Because their names are integers, The fields are implicitly named using numbers starting from 0. Because their names are integers,
the {#syntax#}@"0"{#endsyntax#} syntax must be used to access them. Names inside {#syntax#}@""{#endsyntax#} are always recognised as identifiers. the {#syntax#}@"0"{#endsyntax#} syntax must be used to access them. Names inside {#syntax#}@""{#endsyntax#} are always recognised as {#link|identifiers|Identifiers#}.
</p> </p>
<p> <p>
Like arrays, tuples have a .len field, can be indexed and work with the ++ and ** operators. They can also be iterated over with {#link|inline for#}. Like arrays, tuples have a .len field, can be indexed and work with the ++ and ** operators. They can also be iterated over with {#link|inline for#}.
@@ -3975,7 +4006,7 @@ test "labeled break from labeled block expression" {
{#see_also|Labeled while|Labeled for#} {#see_also|Labeled while|Labeled for#}
{#header_open|Shadowing#} {#header_open|Shadowing#}
<p>Identifiers are never allowed to "hide" other identifiers by using the same name:</p> <p>{#link|Identifiers#} are never allowed to "hide" other identifiers by using the same name:</p>
{#code_begin|test_err|local shadows declaration#} {#code_begin|test_err|local shadows declaration#}
const pi = 3.14; const pi = 3.14;
@@ -3987,8 +4018,8 @@ test "inside test block" {
} }
{#code_end#} {#code_end#}
<p> <p>
Because of this, when you read Zig code you can always rely on an identifier to consistently mean Because of this, when you read Zig code you can always rely on an identifier to consistently mean
the same thing within the scope it is defined. Note that you can, however, use the same name if the same thing within the scope it is defined. Note that you can, however, use the same name if
the scopes are separate: the scopes are separate:
</p> </p>
{#code_begin|test|test_scopes#} {#code_begin|test|test_scopes#}
@@ -4026,7 +4057,7 @@ test "switch simple" {
1, 2, 3 => 0, 1, 2, 3 => 0,
// Ranges can be specified using the ... syntax. These are inclusive // Ranges can be specified using the ... syntax. These are inclusive
// both ends. // of both ends.
5...100 => 1, 5...100 => 1,
// Branches can be arbitrarily complex. // Branches can be arbitrarily complex.
@@ -4798,7 +4829,7 @@ test "errdefer unwinding" {
</p> </p>
{#header_open|Basics#} {#header_open|Basics#}
{#code_begin|test|test_unreachable#} {#code_begin|test|test_unreachable#}
// unreachable is used to assert that control flow will never happen upon a // unreachable is used to assert that control flow will never reach a
// particular location: // particular location:
test "basic math" { test "basic math" {
const x = 1; const x = 1;
@@ -6269,8 +6300,8 @@ test "turn HashMap into a set with void" {
value is deleted, as seen above. value is deleted, as seen above.
</p> </p>
<p> <p>
{#syntax#}void{#endsyntax#} is distinct from {#syntax#}c_void{#endsyntax#}. {#syntax#}void{#endsyntax#} is distinct from {#syntax#}anyopaque{#endsyntax#}.
{#syntax#}void{#endsyntax#} has a known size of 0 bytes, and {#syntax#}c_void{#endsyntax#} has an unknown, but non-zero, size. {#syntax#}void{#endsyntax#} has a known size of 0 bytes, and {#syntax#}anyopaque{#endsyntax#} has an unknown, but non-zero, size.
</p> </p>
<p> <p>
Expressions of type {#syntax#}void{#endsyntax#} are the only ones whose value can be ignored. For example: Expressions of type {#syntax#}void{#endsyntax#} are the only ones whose value can be ignored. For example:
@@ -6766,8 +6797,7 @@ test "variable values" {
generic data structure. generic data structure.
</p> </p>
<p> <p>
Here is an example of a generic {#syntax#}List{#endsyntax#} data structure, that we will instantiate with Here is an example of a generic {#syntax#}List{#endsyntax#} data structure.
the type {#syntax#}i32{#endsyntax#}. In Zig we refer to the type as {#syntax#}List(i32){#endsyntax#}.
</p> </p>
{#code_begin|syntax#} {#code_begin|syntax#}
fn List(comptime T: type) type { fn List(comptime T: type) type {
@@ -6776,27 +6806,46 @@ fn List(comptime T: type) type {
len: usize, len: usize,
}; };
} }
{#code_end#}
<p> // The generic List data structure can be instantiated by passing in a type:
That's it. It's a function that returns an anonymous {#syntax#}struct{#endsyntax#}. For the purposes of error messages var buffer: [10]i32 = undefined;
and debugging, Zig infers the name {#syntax#}"List(i32)"{#endsyntax#} from the function name and parameters invoked when creating var list = List(i32){
the anonymous struct. .items = &buffer,
</p> .len = 0,
<p>
To keep the language small and uniform, all aggregate types in Zig are anonymous. To give a type
a name, we assign it to a constant:
</p>
{#code_begin|syntax#}
const Node = struct {
next: *Node,
name: []u8,
}; };
{#code_end#} {#code_end#}
<p> <p>
This works because all top level declarations are order-independent, and as long as there isn't That's it. It's a function that returns an anonymous {#syntax#}struct{#endsyntax#}.
an actual infinite regression, values can refer to themselves, directly or indirectly. In this case, To keep the language small and uniform, all aggregate types in Zig are anonymous.
{#syntax#}Node{#endsyntax#} refers to itself as a pointer, which is not actually an infinite regression, so For the purposes of error messages and debugging, Zig infers the name
it works fine. {#syntax#}"List(i32)"{#endsyntax#} from the function name and parameters invoked when creating
the anonymous struct.
</p>
<p>
To explicitly give a type a name, we assign it to a constant.
</p>
{#code_begin|syntax#}
const Node = struct {
next: ?*Node,
name: []const u8,
};
var node_a = Node{
.next = null,
.name = &"Node A",
};
var node_b = Node{
.next = &node_a,
.name = &"Node B",
};
{#code_end#}
<p>
In this example, the {#syntax#}Node{#endsyntax#} struct refers to itself.
This works because all top level declarations are order-independent.
As long as the compiler can determine the size of the struct, it is free to refer to itself.
In this case, {#syntax#}Node{#endsyntax#} refers to itself as a pointer, which has a
well-defined size at compile time, so it works fine.
</p> </p>
{#header_close#} {#header_close#}
{#header_open|Case Study: print in Zig#} {#header_open|Case Study: print in Zig#}
@@ -7209,10 +7258,10 @@ test "global assembly" {
provided explicitly by the caller, and it can be suspended and resumed any number of times. provided explicitly by the caller, and it can be suspended and resumed any number of times.
</p> </p>
<p> <p>
The code following the {#syntax#}async{#endsyntax#} callsite runs immediately after the async The code following the {#syntax#}async{#endsyntax#} callsite runs immediately after the async
function first suspends. When the return value of the async function is needed, function first suspends. When the return value of the async function is needed,
the calling code can {#syntax#}await{#endsyntax#} on the async function frame. the calling code can {#syntax#}await{#endsyntax#} on the async function frame.
This will suspend the calling code until the async function completes, at which point This will suspend the calling code until the async function completes, at which point
execution resumes just after the {#syntax#}await{#endsyntax#} callsite. execution resumes just after the {#syntax#}await{#endsyntax#} callsite.
</p> </p>
<p> <p>
@@ -7322,8 +7371,8 @@ fn testResumeFromSuspend(my_result: *i32) void {
in standard code. in standard code.
</p> </p>
<p> <p>
However, it is possible to have an {#syntax#}async{#endsyntax#} call However, it is possible to have an {#syntax#}async{#endsyntax#} call
without a matching {#syntax#}await{#endsyntax#}. Upon completion of the async function, without a matching {#syntax#}await{#endsyntax#}. Upon completion of the async function,
execution would continue at the most recent {#syntax#}async{#endsyntax#} callsite or {#syntax#}resume{#endsyntax#} callsite, execution would continue at the most recent {#syntax#}async{#endsyntax#} callsite or {#syntax#}resume{#endsyntax#} callsite,
and the return value of the async function would be lost. and the return value of the async function would be lost.
</p> </p>
@@ -7360,8 +7409,8 @@ fn func() void {
</p> </p>
<p> <p>
{#syntax#}await{#endsyntax#} is a suspend point, and takes as an operand anything that {#syntax#}await{#endsyntax#} is a suspend point, and takes as an operand anything that
coerces to {#syntax#}anyframe->T{#endsyntax#}. Calling {#syntax#}await{#endsyntax#} on coerces to {#syntax#}anyframe->T{#endsyntax#}. Calling {#syntax#}await{#endsyntax#} on
the frame of an async function will cause execution to continue at the the frame of an async function will cause execution to continue at the
{#syntax#}await{#endsyntax#} callsite once the target function completes. {#syntax#}await{#endsyntax#} callsite once the target function completes.
</p> </p>
<p> <p>
@@ -8286,8 +8335,8 @@ fn internalName() callconv(.C) void {}
{#code_begin|obj#} {#code_begin|obj#}
export fn foo() void {} export fn foo() void {}
{#code_end#} {#code_end#}
<p>Note that even when using {#syntax#}export{#endsyntax#}, {#syntax#}@"foo"{#endsyntax#} syntax can <p>Note that even when using {#syntax#}export{#endsyntax#}, the {#syntax#}@"foo"{#endsyntax#} syntax for
be used to choose any string for the symbol name:</p> {#link|identifiers|Identifiers#} can be used to choose any string for the symbol name:</p>
{#code_begin|obj#} {#code_begin|obj#}
export fn @"A function name that is a complete sentence."() void {} export fn @"A function name that is a complete sentence."() void {}
{#code_end#} {#code_end#}
@@ -8518,6 +8567,9 @@ test "@hasDecl" {
<li>{#syntax#}@import("builtin"){#endsyntax#} - Target-specific information <li>{#syntax#}@import("builtin"){#endsyntax#} - Target-specific information
The command <code>zig build-exe --show-builtin</code> outputs the source to stdout for reference. The command <code>zig build-exe --show-builtin</code> outputs the source to stdout for reference.
</li> </li>
<li>{#syntax#}@import("root"){#endsyntax#} - Points to the root source file
This is usually `src/main.zig` but it depends on what file is chosen to be built.
</li>
</ul> </ul>
{#see_also|Compile Variables|@embedFile#} {#see_also|Compile Variables|@embedFile#}
{#header_close#} {#header_close#}
@@ -8529,6 +8581,16 @@ test "@hasDecl" {
Attempting to convert a number which is out of range of the destination type results in Attempting to convert a number which is out of range of the destination type results in
safety-protected {#link|Undefined Behavior#}. safety-protected {#link|Undefined Behavior#}.
</p> </p>
{#code_begin|test_err|cast truncated bits#}
test "integer cast panic" {
var a: u16 = 0xabcd;
var b: u8 = @intCast(u8, a);
_ = b;
}
{#code_end#}
<p>
To truncate the significant bits of a number out of range of the destination type, use {#link|@truncate#}.
</p>
<p> <p>
If {#syntax#}T{#endsyntax#} is {#syntax#}comptime_int{#endsyntax#}, If {#syntax#}T{#endsyntax#} is {#syntax#}comptime_int{#endsyntax#},
then this is semantically equivalent to {#link|Type Coercion#}. then this is semantically equivalent to {#link|Type Coercion#}.
@@ -8573,7 +8635,9 @@ test "@hasDecl" {
{#header_open|@intToPtr#} {#header_open|@intToPtr#}
<pre>{#syntax#}@intToPtr(comptime DestType: type, address: usize) DestType{#endsyntax#}</pre> <pre>{#syntax#}@intToPtr(comptime DestType: type, address: usize) DestType{#endsyntax#}</pre>
<p> <p>
Converts an integer to a {#link|pointer|Pointers#}. To convert the other way, use {#link|@ptrToInt#}. Converts an integer to a {#link|pointer|Pointers#}. To convert the other way, use {#link|@ptrToInt#}. Casting an address of 0 to a destination type
which in not {#link|optional|Optional Pointers#} and does not have the {#syntax#}allowzero{#endsyntax#} attribute will result in a
{#link|Pointer Cast Invalid Null#} panic when runtime safety checks are enabled.
</p> </p>
<p> <p>
If the destination pointer type does not allow address zero and {#syntax#}address{#endsyntax#} If the destination pointer type does not allow address zero and {#syntax#}address{#endsyntax#}
@@ -8687,7 +8751,8 @@ test "@wasmMemoryGrow" {
<pre>{#syntax#}@mod(numerator: T, denominator: T) T{#endsyntax#}</pre> <pre>{#syntax#}@mod(numerator: T, denominator: T) T{#endsyntax#}</pre>
<p> <p>
Modulus division. For unsigned integers this is the same as Modulus division. For unsigned integers this is the same as
{#syntax#}numerator % denominator{#endsyntax#}. Caller guarantees {#syntax#}denominator > 0{#endsyntax#}. {#syntax#}numerator % denominator{#endsyntax#}. Caller guarantees {#syntax#}denominator > 0{#endsyntax#}, otherwise the
operation will result in a {#link|Remainder Division by Zero#} when runtime safety checks are enabled.
</p> </p>
<ul> <ul>
<li>{#syntax#}@mod(-5, 3) == 1{#endsyntax#}</li> <li>{#syntax#}@mod(-5, 3) == 1{#endsyntax#}</li>
@@ -8705,7 +8770,7 @@ test "@wasmMemoryGrow" {
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|@panic#} {#header_open|@panic#}
<pre>{#syntax#}@panic(message: []const u8) noreturn{#endsyntax#}</pre> <pre>{#syntax#}@panic(message: []const u8) noreturn{#endsyntax#}</pre>
<p> <p>
@@ -8812,7 +8877,8 @@ pub const PrefetchOptions = struct {
<pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre> <pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre>
<p> <p>
Remainder division. For unsigned integers this is the same as Remainder division. For unsigned integers this is the same as
{#syntax#}numerator % denominator{#endsyntax#}. Caller guarantees {#syntax#}denominator > 0{#endsyntax#}. {#syntax#}numerator % denominator{#endsyntax#}. Caller guarantees {#syntax#}denominator > 0{#endsyntax#}, otherwise the
operation will result in a {#link|Remainder Division by Zero#} when runtime safety checks are enabled.
</p> </p>
<ul> <ul>
<li>{#syntax#}@rem(-5, 3) == -2{#endsyntax#}</li> <li>{#syntax#}@rem(-5, 3) == -2{#endsyntax#}</li>
@@ -8854,14 +8920,14 @@ pub const PrefetchOptions = struct {
{#header_close#} {#header_close#}
{#header_open|@setCold#} {#header_open|@setCold#}
<pre>{#syntax#}@setCold(is_cold: bool){#endsyntax#}</pre> <pre>{#syntax#}@setCold(comptime 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|@setEvalBranchQuota#} {#header_open|@setEvalBranchQuota#}
<pre>{#syntax#}@setEvalBranchQuota(new_quota: u32){#endsyntax#}</pre> <pre>{#syntax#}@setEvalBranchQuota(comptime new_quota: u32){#endsyntax#}</pre>
<p> <p>
Changes the maximum number of backwards branches that compile-time code Changes the maximum number of backwards branches that compile-time code
execution can use before giving up and making a compile error. execution can use before giving up and making a compile error.
@@ -8896,7 +8962,7 @@ test "foo" {
{#header_close#} {#header_close#}
{#header_open|@setFloatMode#} {#header_open|@setFloatMode#}
<pre>{#syntax#}@setFloatMode(mode: @import("std").builtin.FloatMode){#endsyntax#}</pre> <pre>{#syntax#}@setFloatMode(comptime mode: @import("std").builtin.FloatMode){#endsyntax#}</pre>
<p> <p>
Sets the floating point mode of the current scope. Possible values are: Sets the floating point mode of the current scope. Possible values are:
</p> </p>
@@ -8931,7 +8997,7 @@ pub const FloatMode = enum {
{#header_close#} {#header_close#}
{#header_open|@setRuntimeSafety#} {#header_open|@setRuntimeSafety#}
<pre>{#syntax#}@setRuntimeSafety(safety_on: bool) void{#endsyntax#}</pre> <pre>{#syntax#}@setRuntimeSafety(comptime safety_on: bool) void{#endsyntax#}</pre>
<p> <p>
Sets whether runtime safety checks are enabled for the scope that contains the function call. Sets whether runtime safety checks are enabled for the scope that contains the function call.
</p> </p>
@@ -8992,7 +9058,7 @@ test "@setRuntimeSafety" {
</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>
@@ -9323,7 +9389,7 @@ fn doTheTest() !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|@tagName#} {#header_open|@tagName#}
<pre>{#syntax#}@tagName(value: anytype) [:0]const u8{#endsyntax#}</pre> <pre>{#syntax#}@tagName(value: anytype) [:0]const u8{#endsyntax#}</pre>
<p> <p>
@@ -9372,17 +9438,11 @@ fn List(comptime T: type) type {
or same-sized integer type. or same-sized integer type.
</p> </p>
<p> <p>
The following produces safety-checked {#link|Undefined Behavior#}: This function always truncates the significant bits of the integer, regardless
of endianness on the target platform.
</p> </p>
{#code_begin|test_err|cast truncated bits#}
test "integer cast panic" {
var a: u16 = 0xabcd;
var b: u8 = @intCast(u8, a);
_ = b;
}
{#code_end#}
<p> <p>
However this is well defined and working code: Calling {#syntax#}@truncate{#endsyntax#} on a number out of range of the destination type is well defined and working code:
</p> </p>
{#code_begin|test|truncate#} {#code_begin|test|truncate#}
const std = @import("std"); const std = @import("std");
@@ -9395,8 +9455,7 @@ test "integer truncation" {
} }
{#code_end#} {#code_end#}
<p> <p>
This function always truncates the significant bits of the integer, regardless Use {#link|@intCast#} to convert numbers guaranteed to fit the destination type.
of endianness on the target platform.
</p> </p>
{#header_close#} {#header_close#}
@@ -9448,9 +9507,14 @@ test "integer truncation" {
Provides type reflection. Provides type reflection.
</p> </p>
<p> <p>
For {#link|structs|struct#}, {#link|unions|union#}, {#link|enums|enum#}, and Type information of {#link|structs|struct#}, {#link|unions|union#}, {#link|enums|enum#}, and
{#link|error sets|Error Set Type#}, the fields are guaranteed to be in the same {#link|error sets|Error Set Type#} has fields which are are guaranteed to be in the same
order as declared. For declarations, the order is unspecified. order as appearance in the source file.
</p>
<p>
Type information of {#link|structs|struct#}, {#link|unions|union#}, {#link|enums|enum#}, and
{#link|opaques|opaque#} has declarations, which are also guaranteed to be in the same
order as appearance in the source file.
</p> </p>
{#header_close#} {#header_close#}
@@ -10618,8 +10682,10 @@ lib.addCSourceFile("src/lib.c", &[_][]const u8{
<li>{#syntax#}c_longlong{#endsyntax#}</li> <li>{#syntax#}c_longlong{#endsyntax#}</li>
<li>{#syntax#}c_ulonglong{#endsyntax#}</li> <li>{#syntax#}c_ulonglong{#endsyntax#}</li>
<li>{#syntax#}c_longdouble{#endsyntax#}</li> <li>{#syntax#}c_longdouble{#endsyntax#}</li>
<li>{#syntax#}c_void{#endsyntax#}</li>
</ul> </ul>
<p>
To interop with the C {#syntax#}void{#endsyntax#} type, use {#syntax#}anyopaque{#endsyntax#}.
</p>
{#see_also|Primitive Types#} {#see_also|Primitive Types#}
{#header_close#} {#header_close#}
{#header_open|Import from C Header File#} {#header_open|Import from C Header File#}

106
lib/libc/glibc/csu/elf-init-2.33.c vendored Normal file
View File

@@ -0,0 +1,106 @@
/* Startup support for ELF initializers/finalizers in the main executable.
Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <stddef.h>
/* These magic symbols are provided by the linker. */
extern void (*__preinit_array_start []) (int, char **, char **)
attribute_hidden;
extern void (*__preinit_array_end []) (int, char **, char **)
attribute_hidden;
extern void (*__init_array_start []) (int, char **, char **)
attribute_hidden;
extern void (*__init_array_end []) (int, char **, char **)
attribute_hidden;
extern void (*__fini_array_start []) (void) attribute_hidden;
extern void (*__fini_array_end []) (void) attribute_hidden;
#ifndef NO_INITFINI
/* These function symbols are provided for the .init/.fini section entry
points automagically by the linker. */
extern void _init (void);
extern void _fini (void);
#endif
/* These functions are passed to __libc_start_main by the startup code.
These get statically linked into each program. For dynamically linked
programs, this module will come from libc_nonshared.a and differs from
the libc.a module in that it doesn't call the preinit array. */
void
__libc_csu_init (int argc, char **argv, char **envp)
{
/* For dynamically linked executables the preinit array is executed by
the dynamic linker (before initializing any shared object). */
#ifndef LIBC_NONSHARED
/* For static executables, preinit happens right before init. */
{
const size_t size = __preinit_array_end - __preinit_array_start;
size_t i;
for (i = 0; i < size; i++)
(*__preinit_array_start [i]) (argc, argv, envp);
}
#endif
#ifndef NO_INITFINI
_init ();
#endif
const size_t size = __init_array_end - __init_array_start;
for (size_t i = 0; i < size; i++)
(*__init_array_start [i]) (argc, argv, envp);
}
/* This function should not be used anymore. We run the executable's
destructor now just like any other. We cannot remove the function,
though. */
void
__libc_csu_fini (void)
{
#ifndef LIBC_NONSHARED
size_t i = __fini_array_end - __fini_array_start;
while (i-- > 0)
(*__fini_array_start [i]) ();
# ifndef NO_INITFINI
_fini ();
# endif
#endif
}

View File

@@ -0,0 +1,112 @@
/* Copyright (C) 1995-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
/* This is the canonical entry point, usually the first thing in the text
segment.
Note that the code in the .init section has already been run.
This includes _init and _libc_init
At this entry point, most registers' values are unspecified, except:
x0/w0 Contains a function pointer to be registered with `atexit'.
This is how the dynamic linker arranges to have DT_FINI
functions called for shared libraries that have been loaded
before this code runs.
sp The stack contains the arguments and environment:
0(sp) argc
8(sp) argv[0]
...
(8*argc)(sp) NULL
(8*(argc+1))(sp) envp[0]
...
NULL
*/
.text
.globl _start
.type _start,#function
_start:
/* Create an initial frame with 0 LR and FP */
mov x29, #0
mov x30, #0
/* Setup rtld_fini in argument register */
mov x5, x0
/* Load argc and a pointer to argv */
ldr PTR_REG (1), [sp, #0]
add x2, sp, #PTR_SIZE
/* Setup stack limit in argument register */
mov x6, sp
#ifdef PIC
# ifdef SHARED
adrp x0, :got:main
ldr PTR_REG (0), [x0, #:got_lo12:main]
adrp x3, :got:__libc_csu_init
ldr PTR_REG (3), [x3, #:got_lo12:__libc_csu_init]
adrp x4, :got:__libc_csu_fini
ldr PTR_REG (4), [x4, #:got_lo12:__libc_csu_fini]
# else
adrp x0, __wrap_main
add x0, x0, :lo12:__wrap_main
adrp x3, __libc_csu_init
add x3, x3, :lo12:__libc_csu_init
adrp x4, __libc_csu_fini
add x4, x4, :lo12:__libc_csu_fini
# endif
#else
/* Set up the other arguments in registers */
MOVL (0, main)
MOVL (3, __libc_csu_init)
MOVL (4, __libc_csu_fini)
#endif
/* __libc_start_main (main, argc, argv, init, fini, rtld_fini,
stack_end) */
/* Let the libc call main and exit with its return code. */
bl __libc_start_main
/* should never get here....*/
bl abort
#if defined PIC && !defined SHARED
/* When main is not defined in the executable but in a shared library
then a wrapper is needed in crt1.o of the static-pie enabled libc,
because crt1.o and rcrt1.o share code and the later must avoid the
use of GOT relocations before __libc_start_main is called. */
__wrap_main:
b main
#endif
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.long 0
.weak data_start
data_start = __data_start

View File

@@ -0,0 +1,85 @@
/* Startup code for Alpha/ELF.
Copyright (C) 1993-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson <rth@tamu.edu>
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
.text
.align 3
.globl _start
.ent _start, 0
.type _start,@function
_start:
.frame $15, 0, $15
br gp, 1f
1: ldgp gp, 0(gp)
subq sp, 16, sp
mov 0, $15
.prologue 0
/* Load address of the user's main function. */
lda a0, main
ldl a1, 16(sp) /* get argc */
lda a2, 24(sp) /* get argv */
/* Load address of our own entry points to .fini and .init. */
lda a3, __libc_csu_init
lda a4, __libc_csu_fini
/* Store address of the shared library termination function. */
mov v0, a5
/* Provide the highest stack address to the user code. */
stq sp, 0(sp)
/* Call the user's main function, and exit with its value.
But let the libc call main. */
jsr ra, __libc_start_main
/* Die very horribly if exit returns. Call_pal hlt is callable from
kernel mode only; this will result in an illegal instruction trap. */
call_pal 0
.end _start
/* For ECOFF backwards compatibility. */
weak_alias (_start, __start)
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.weak data_start
data_start = __data_start

148
lib/libc/glibc/sysdeps/arm/start-2.33.S vendored Normal file
View File

@@ -0,0 +1,148 @@
/* Startup code for ARM & ELF
Copyright (C) 1995-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
/* This is the canonical entry point, usually the first thing in the text
segment.
Note that the code in the .init section has already been run.
This includes _init and _libc_init
At this entry point, most registers' values are unspecified, except:
a1 Contains a function pointer to be registered with `atexit'.
This is how the dynamic linker arranges to have DT_FINI
functions called for shared libraries that have been loaded
before this code runs.
sp The stack contains the arguments and environment:
0(sp) argc
4(sp) argv[0]
...
(4*argc)(sp) NULL
(4*(argc+1))(sp) envp[0]
...
NULL
*/
/* Tag_ABI_align8_preserved: This code preserves 8-byte
alignment in any callee. */
.eabi_attribute 25, 1
/* Tag_ABI_align8_needed: This code may require 8-byte alignment from
the caller. */
.eabi_attribute 24, 1
#if defined(__thumb2__)
.thumb
.syntax unified
#endif
.text
.globl _start
.type _start,#function
_start:
/* Protect against unhandled exceptions. */
.fnstart
/* Clear the frame pointer and link register since this is the outermost frame. */
mov fp, #0
mov lr, #0
/* Pop argc off the stack and save a pointer to argv */
pop { a2 }
mov a3, sp
/* Push stack limit */
push { a3 }
/* Push rtld_fini */
push { a1 }
#ifdef PIC
ldr sl, .L_GOT
adr a4, .L_GOT
add sl, sl, a4
ldr ip, .L_GOT+4 /* __libc_csu_fini */
ldr ip, [sl, ip]
push { ip } /* Push __libc_csu_fini */
ldr a4, .L_GOT+8 /* __libc_csu_init */
ldr a4, [sl, a4]
ldr a1, .L_GOT+12 /* main */
ldr a1, [sl, a1]
/* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
/* Let the libc call main and exit with its return code. */
bl __libc_start_main(PLT)
#else
/* Fetch address of __libc_csu_fini */
ldr ip, =__libc_csu_fini
/* Push __libc_csu_fini */
push { ip }
/* Set up the other arguments in registers */
ldr a1, =main
ldr a4, =__libc_csu_init
/* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end) */
/* Let the libc call main and exit with its return code. */
bl __libc_start_main
#endif
/* should never get here....*/
bl abort
#ifdef PIC
.align 2
.L_GOT:
.word _GLOBAL_OFFSET_TABLE_ - .L_GOT
.word __libc_csu_fini(GOT)
.word __libc_csu_init(GOT)
.word main(GOT)
#endif
.cantunwind
.fnend
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.long 0
.weak data_start
data_start = __data_start

152
lib/libc/glibc/sysdeps/hppa/start-2.33.S vendored Normal file
View File

@@ -0,0 +1,152 @@
/* ELF startup code for HPPA.
Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
.import main, code
.import $global$, data
.import __libc_start_main, code
.import __libc_csu_fini, code
.import __libc_csu_init, code
/* Have the linker create plabel words so we get PLABEL32
relocs and not 21/14. The use of 21/14 relocs is only
supported in the latest dynamic linker. */
#ifdef PIC
.section .data.rel.ro,"aw",@progbits
#else
.section .rodata,"a",@progbits
#endif
.align 4
.Lpmain:
.word P%main
.Lp__libc_start_main:
.word P%__libc_start_main
.Lp__libc_csu_fini:
.word P%__libc_csu_fini
.Lp__libc_csu_init:
.word P%__libc_csu_init
.text
.align 4
.globl _start
.export _start, ENTRY
.type _start,@function
_start:
/* At entry to the function we have:
r26 - Unused
r25 - argc
r24 - argv
r23 - False _dl_fini plabel address
This function is called from the lower half of RTLD_START.
The call to __libc_start_main expects:
1. r26 - Application main
2. r25 - argc
3. r24 - argv
4. r23 - __libc_csu_init
5. sp-52 - __libc_csu_fini
6. sp-56 - rtld_fini
7. sp-60 - stackend */
.proc
.callinfo
/* Clear previous-sp. */
stw %r0, -4(%sp)
/* Setup the stack and frame. */
stw %rp, -20(%sp)
ldo 64(%sp), %sp
stw %sp, -4(%sp)
stw %r19, -32(%sp)
/* argc and argv should be in 25 and 24 (2nd and 3rd argument) */
/* void (*rtld_fini) (void) (6th argument) */
stw %r23, -56(%sp)
/* Need to setup 1, 4, 5, and 7th arguments */
#ifdef PIC
/* Load $global$ address into %dp */
bl .+8, %dp
addil L'$global$-$PIC_pcrel$0+1, %dp
ldo R'$global$-$PIC_pcrel$0+5(%r1), %dp
/* load main (1st argument) */
addil LT'.Lpmain, %r19
ldw RT'.Lpmain(%r1), %r26
ldw 0(%r26),%r26
/* void (*init) (void) (4th argument) */
addil LT'.Lp__libc_csu_init, %r19
ldw RT'.Lp__libc_csu_init(%r1), %r23
ldw 0(%r23), %r23
/* void (*fini) (void) (5th argument) */
addil LT'.Lp__libc_csu_fini, %r19
ldw RT'.Lp__libc_csu_fini(%r1), %r22
ldw 0(%r22), %r22
#else
/* Load $global$ address into %dp */
ldil L%$global$, %dp
ldo R%$global$(%dp), %dp
/* load main (1st argument) */
ldil LR'.Lpmain, %r26
ldw RR'.Lpmain(%r26), %r26
/* void (*init) (void) (4th argument) */
ldil LR'.Lp__libc_csu_init, %r23
ldw RR'.Lp__libc_csu_init(%r23), %r23
/* void (*fini) (void) (5th argument) */
ldil LR'.Lp__libc_csu_fini, %r22
ldw RR'.Lp__libc_csu_fini(%r22), %r22
#endif
/* Store 5th argument */
stw %r22, -52(%sp)
/* void *stack_end (7th argument) */
stw %sp, -60(%sp)
bl __libc_start_main,%r2
nop
/* die horribly if it returned (it shouldn't) */
iitlbp %r0,(%sr0,%r0)
nop
.procend
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.long 0
.weak data_start
data_start = __data_start

151
lib/libc/glibc/sysdeps/i386/start-2.33.S vendored Normal file
View File

@@ -0,0 +1,151 @@
/* Startup code compliant to the ELF i386 ABI.
Copyright (C) 1995-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
/* This is the canonical entry point, usually the first thing in the text
segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
point runs, most registers' values are unspecified, except for:
%edx Contains a function pointer to be registered with `atexit'.
This is how the dynamic linker arranges to have DT_FINI
functions called for shared libraries that have been loaded
before this code runs.
%esp The stack contains the arguments and environment:
0(%esp) argc
4(%esp) argv[0]
...
(4*argc)(%esp) NULL
(4*(argc+1))(%esp) envp[0]
...
NULL
*/
#include <sysdep.h>
ENTRY (_start)
/* Clearing frame pointer is insufficient, use CFI. */
cfi_undefined (eip)
/* Clear the frame pointer. The ABI suggests this be done, to mark
the outermost frame obviously. */
xorl %ebp, %ebp
/* Extract the arguments as encoded on the stack and set up
the arguments for `main': argc, argv. envp will be determined
later in __libc_start_main. */
popl %esi /* Pop the argument count. */
movl %esp, %ecx /* argv starts just at the current stack top.*/
/* Before pushing the arguments align the stack to a 16-byte
(SSE needs 16-byte alignment) boundary to avoid penalties from
misaligned accesses. Thanks to Edward Seidl <seidl@janed.com>
for pointing this out. */
andl $0xfffffff0, %esp
pushl %eax /* Push garbage because we allocate
28 more bytes. */
/* Provide the highest stack address to the user code (for stacks
which grow downwards). */
pushl %esp
pushl %edx /* Push address of the shared library
termination function. */
#ifdef PIC
/* Load PIC register. */
call 1f
addl $_GLOBAL_OFFSET_TABLE_, %ebx
/* Push address of our own entry points to .fini and .init. */
leal __libc_csu_fini@GOTOFF(%ebx), %eax
pushl %eax
leal __libc_csu_init@GOTOFF(%ebx), %eax
pushl %eax
pushl %ecx /* Push second argument: argv. */
pushl %esi /* Push first argument: argc. */
# ifdef SHARED
pushl main@GOT(%ebx)
# else
/* Avoid relocation in static PIE since _start is called before
it is relocated. Don't use "leal main@GOTOFF(%ebx), %eax"
since main may be in a shared object. Linker will convert
"movl main@GOT(%ebx), %eax" to "leal main@GOTOFF(%ebx), %eax"
if main is defined locally. */
movl main@GOT(%ebx), %eax
pushl %eax
# endif
/* Call the user's main function, and exit with its value.
But let the libc call main. */
call __libc_start_main@PLT
#else
/* Push address of our own entry points to .fini and .init. */
pushl $__libc_csu_fini
pushl $__libc_csu_init
pushl %ecx /* Push second argument: argv. */
pushl %esi /* Push first argument: argc. */
pushl $main
/* Call the user's main function, and exit with its value.
But let the libc call main. */
call __libc_start_main
#endif
hlt /* Crash if somehow `exit' does return. */
#ifdef PIC
1: movl (%esp), %ebx
ret
#endif
END (_start)
/* To fulfill the System V/i386 ABI we need this symbol. Yuck, it's so
meaningless since we don't support machines < 80386. */
.section .rodata
.globl _fp_hw
_fp_hw: .long 3
.size _fp_hw, 4
.type _fp_hw,@object
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.long 0
.weak data_start
data_start = __data_start

118
lib/libc/glibc/sysdeps/ia64/start-2.33.S vendored Normal file
View File

@@ -0,0 +1,118 @@
/* Copyright (C) 1999-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Jes Sorensen, <Jes.Sorensen@cern.ch>, April 1999.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
#include <asm/fpu.h>
/*
* Arguments for __libc_start_main:
* out0: main
* out1: argc
* out2: argv
* out3: init
* out4: fini
* out5: rtld_fini
* out6: stack_end
*/
.align 32
.global _start
.proc _start
.type _start,@function
_start:
.prologue
.save rp, r0
.body
.prologue
{ .mlx
alloc r2 = ar.pfs,0,0,7,0
movl r3 = FPSR_DEFAULT
}
{ .mlx
adds out2 = 16, sp /* get address of argc value */
movl gp = @gprel(0f)
;;
}
0: { .mmi
ld8 out1 = [out2], 8 /* load argc and move out2 to become argv */
mov.m r10 = ar.bsp /* fetch rbs base address */
mov r9 = ip
;;
}
{ .mii
mov ar.fpsr = r3
sub gp = r9, gp /* back-compute gp value */
adds out6 = 16, sp /* highest non-environment stack address */
;;
}
{
addl r11 = @ltoff(__libc_ia64_register_backing_store_base), gp
addl out0 = @ltoff(@fptr(main)), gp
addl out3 = @ltoff(@fptr(__libc_csu_init)), gp
;;
}
{ .mmi
ld8 r3 = [r11] /* pointer to __libc_ia64_register_backing_store_base */
ld8 out0 = [out0] /* pointer to `main' function descriptor */
addl out4 = @ltoff(@fptr(__libc_csu_fini)), gp
;;
}
{ .mmi
ld8 out3 = [out3] /* pointer to `init' function descriptor */
ld8 out4 = [out4] /* pointer to `fini' function descriptor */
nop 0
}
.body
{ .mib
st8 [r3] = r10
mov out5 = ret0 /* dynamic linker destructor */
br.call.sptk.few rp = __libc_start_main
}
{ .mib
break 0 /* break miserably if we ever return */
}
.endp _start
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.long 0
.weak data_start
data_start = __data_start
.common __libc_ia64_register_backing_store_base, 8, 8

120
lib/libc/glibc/sysdeps/m68k/start-2.33.S vendored Normal file
View File

@@ -0,0 +1,120 @@
/* Startup code compliant to the ELF m68k ABI.
Copyright (C) 1996-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
/* This is the canonical entry point, usually the first thing in the text
segment. The SVR4/m68k ABI says that when the entry point runs,
most registers' values are unspecified, except for:
%a1 Contains a function pointer to be registered with `atexit'.
This is how the dynamic linker arranges to have DT_FINI
functions called for shared libraries that have been loaded
before this code runs.
%sp The stack contains the arguments and environment:
0(%sp) argc
4(%sp) argv[0]
...
(4*argc)(%sp) NULL
(4*(argc+1))(%sp) envp[0]
...
NULL
*/
#include <sysdep.h>
.text
.globl _start
.type _start,@function
_start:
/* Clear the frame pointer. The ABI suggests this be done, to mark
the outermost frame obviously. */
sub.l %fp, %fp
/* Extract the arguments as encoded on the stack and set up the
arguments for `main': argc, argv. envp will be determined
later in __libc_start_main. */
move.l (%sp)+, %d0 /* Pop the argument count. */
move.l %sp, %a0 /* The argument vector starts just at the
current stack top. */
/* Provide the highest stack address to the user code (for stacks
which grow downward). */
pea (%sp)
pea (%a1) /* Push address of the shared library
termination function. */
#ifdef PIC
/* Load PIC register. */
LOAD_GOT (%a5)
/* Push the address of our own entry points to `.fini' and
`.init'. */
move.l __libc_csu_fini@GOT(%a5), -(%sp)
move.l __libc_csu_init@GOT(%a5), -(%sp)
pea (%a0) /* Push second argument: argv. */
move.l %d0, -(%sp) /* Push first argument: argc. */
move.l main@GOT(%a5), -(%sp)
/* Call the user's main function, and exit with its value. But
let the libc call main. */
jbsr __libc_start_main@PLTPC
#else
/* Push the address of our own entry points to `.fini' and
`.init'. */
pea __libc_csu_fini
pea __libc_csu_init
pea (%a0) /* Push second argument: argv. */
move.l %d0, -(%sp) /* Push first argument: argc. */
pea main
/* Call the user's main function, and exit with its value. But
let the libc call main. */
jbsr __libc_start_main
#endif
illegal /* Crash if somehow `exit' does return. */
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.long 0
.weak data_start
data_start = __data_start

View File

@@ -0,0 +1,84 @@
/* Copyright (C) 1995-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
.text
.globl _start
.type _start,@function
_start:
/* On entry the stack contains the following args:
r1+0 - argc
r1+4 - argv[0]
...
r1+4*(argc-1) - argv[argc-1]
r1+4*argc - NULL
r1+4*argc + 4 - envp[0]
...
NULL
*/
addk r3,r0,r0
addk r5,r1,r0
1:
addik r5,r5,4
lw r4,r5,r0
bneid r4,1b
addik r3,r3,1
addik r6,r3,-1
sw r6,r1,r0
addik r7,r1,4
addik r1,r1,-24
#ifdef SHARED
/* Setup PIC. */
mfs r20,rpc
addik r20,r20,_GLOBAL_OFFSET_TABLE_+8
lwi r5,r20,main@GOT
lwi r8,r20,__libc_csu_init@GOT
lwi r9,r20,__libc_csu_fini@GOT
brid __libc_start_main@PLT
addk r10,r0,r0
#else
addik r5,r0,main
addik r8,r0,__libc_csu_init
addik r9,r0,__libc_csu_fini
brid __libc_start_main
addk r10,r0,r0
#endif
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.long 0
.weak data_start
data_start = __data_start

185
lib/libc/glibc/sysdeps/mips/start-2.33.S vendored Normal file
View File

@@ -0,0 +1,185 @@
/* Startup code compliant to the ELF Mips ABI.
Copyright (C) 1995-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#define __ASSEMBLY__ 1
#include <entry.h>
#include <sgidefs.h>
#include <sys/asm.h>
#ifndef ENTRY_POINT
#error ENTRY_POINT needs to be defined for start.S on MIPS/ELF.
#endif
/* This is the canonical entry point, usually the first thing in the text
segment. The SVR4/Mips ABI (pages 3-31, 3-32) says that when the entry
point runs, most registers' values are unspecified, except for:
v0 ($2) Contains a function pointer to be registered with `atexit'.
This is how the dynamic linker arranges to have DT_FINI
functions called for shared libraries that have been loaded
before this code runs.
sp ($29) The stack contains the arguments and environment:
0(%esp) argc
4(%esp) argv[0]
...
(4*argc)(%esp) NULL
(4*(argc+1))(%esp) envp[0]
...
NULL
ra ($31) The return address register is set to zero so that programs
that search backword through stack frames recognize the last
stack frame.
*/
/* We need to call:
__libc_start_main (int (*main) (int, char **, char **), int argc,
char **argv, void (*init) (void), void (*fini) (void),
void (*rtld_fini) (void), void *stack_end)
*/
.text
.globl ENTRY_POINT
.type ENTRY_POINT,@function
#ifndef __mips16
ENTRY_POINT:
# ifdef __PIC__
SETUP_GPX($0)
SETUP_GPX64($25,$0)
# else
PTR_LA $28, _gp /* Setup GP correctly if we're non-PIC. */
move $31, $0
# endif
PTR_LA $4, main /* main */
PTR_L $5, 0($29) /* argc */
PTR_ADDIU $6, $29, PTRSIZE /* argv */
/* Allocate space on the stack for seven arguments (o32 only)
and make sure the stack is aligned to double words (8 bytes)
on o32 and quad words (16 bytes) on n32 and n64. */
and $29, -2 * SZREG
# if _MIPS_SIM == _ABIO32
PTR_SUBIU $29, 32
# endif
PTR_LA $7, __libc_csu_init /* init */
PTR_LA $8, __libc_csu_fini
# if _MIPS_SIM == _ABIO32
PTR_S $8, 16($29) /* fini */
PTR_S $2, 20($29) /* rtld_fini */
PTR_S $29, 24($29) /* stack_end */
# else
move $9, $2 /* rtld_fini */
move $10, $29 /* stack_end */
# endif
PTR_LA $25, __libc_start_main
jalr $25
hlt: b hlt /* Crash if somehow it does return. */
#elif _MIPS_SIM == _ABIO32 /* __mips16 */
/* MIPS16 entry point. */
.set mips16
ENTRY_POINT:
# ifdef __PIC__
li $3, %hi(_gp_disp)
addiu $4, $pc, %lo(_gp_disp)
sll $3, 16
addu $3, $4
move $gp, $3
# else
li $3, %hi(_gp)
sll $3, 16
addiu $3, %lo(_gp)
move $gp, $3
# endif
/* Tie end of stack frames. */
li $4, 0
move $31, $4
/* Create new SP value in $7, including alignment. */
li $4, 2 * SZREG
neg $4, $4
move $7, $sp
and $7, $4
addiu $7, -32
/* Load arguments with original SP. */
lw $5, 0($sp)
addiu $6, $sp, PTRSIZE
/* Update SP. */
move $sp, $7
/* Lay out last arguments, and call __libc_start_main(). */
# ifdef __PIC__
sw $7, 24($sp) /* stack_end */
lw $4, %got(__libc_csu_fini)($3)
lw $7, %got(__libc_csu_init)($3) /* init */
sw $4, 16($sp) /* fini */
lw $4, %got(main)($3) /* main */
lw $3, %call16(__libc_start_main)($3)
sw $2, 20($sp) /* rtld_fini */
move $25, $3
jalr $3
# else
lw $4, 1f
sw $7, 24($sp) /* stack_end */
lw $7, 2f /* init */
sw $4, 16($sp) /* fini */
lw $4, 3f /* main */
sw $2, 20($sp) /* rtld_fini */
/* Load and call __libc_start_main(). */
lw $3, 4f
jalr $3
# endif
hlt: b hlt /* Crash if somehow it does return. */
# ifndef __PIC__
.align 2
1: .word __libc_csu_fini
2: .word __libc_csu_init
3: .word main
4: .word __libc_start_main
# endif
#else /* __mips16 && _MIPS_SIM != _ABIO32 */
# error "MIPS16 support for N32/N64 not implemented"
#endif /* __mips16 */
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.long 0
.weak data_start
data_start = __data_start

View File

@@ -0,0 +1,95 @@
/* Startup code for programs linked with GNU libc.
Copyright (C) 1998-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
/* We do not want .eh_frame info for crt1.o since crt1.o is linked
before crtbegin.o, the file defining __EH_FRAME_BEGIN__. */
#undef cfi_startproc
#define cfi_startproc
#undef cfi_endproc
#define cfi_endproc
/* These are the various addresses we require. */
#ifdef PIC
.section ".data"
#else
.section ".rodata"
#endif
.align 2
L(start_addresses):
.long _SDA_BASE_
.long main
.long __libc_csu_init
.long __libc_csu_fini
ASM_SIZE_DIRECTIVE(L(start_addresses))
.section ".text"
ENTRY(_start)
/* Save the stack pointer, in case we're statically linked under Linux. */
mr r9,r1
/* Set up an initial stack frame, and clear the LR. */
clrrwi r1,r1,4
#ifdef PIC
SETUP_GOT_ACCESS(r13,got_label)
li r0,0
#else
li r0,0
#endif
stwu r1,-16(r1)
mtlr r0
stw r0,0(r1)
/* Set r13 to point at the 'small data area', and put the address of
start_addresses in r8. Also load the GOT pointer so that new PLT
calls work, like the one to __libc_start_main. */
#ifdef PIC
addis r30,r13,_GLOBAL_OFFSET_TABLE_-got_label@ha
addis r8,r13,L(start_addresses)-got_label@ha
addi r30,r30,_GLOBAL_OFFSET_TABLE_-got_label@l
lwzu r13, L(start_addresses)-got_label@l(r8)
#else
lis r8,L(start_addresses)@ha
lwzu r13,L(start_addresses)@l(r8)
#endif
/* and continue in libc-start, in glibc. */
b JUMPTARGET(__libc_start_main)
END(_start)
/* Define a symbol for the first piece of initialized data. */
.section ".data"
.globl __data_start
__data_start:
.long 0
weak_alias (__data_start, data_start)

View File

@@ -0,0 +1,92 @@
/* Startup code for programs linked with GNU libc. PowerPC64 version.
Copyright (C) 1998-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
/* We do not want .eh_frame info for crt1.o since crt1.o is linked
before crtbegin.o, the file defining __EH_FRAME_BEGIN__. */
#undef cfi_startproc
#define cfi_startproc
#undef cfi_endproc
#define cfi_endproc
/* These are the various addresses we require. */
#ifdef PIC
.section ".data.rel.ro.local","aw"
#else
.section ".rodata"
#endif
.align 3
L(start_addresses):
.quad 0 /* was _SDA_BASE_ but not in 64-bit ABI*/
/* function descriptors so don't need JUMPTARGET */
.quad main
.quad __libc_csu_init
.quad __libc_csu_fini
ASM_SIZE_DIRECTIVE(L(start_addresses))
.section ".toc","aw"
.L01:
.tc L(start_addresses)[TC],L(start_addresses)
.section ".text"
ENTRY (_start)
/* Save the stack pointer, in case we're statically linked under Linux. */
mr r9,r1
/* Set up an initial stack frame, and clear the LR. */
clrrdi r1,r1,4
li r0,0
stdu r1,-128(r1)
mtlr r0
std r0,0(r1)
/* put the address of start_addresses in r8... **
** PPC64 ABI uses R13 for thread local, so we leave it alone */
ld r8,.L01@toc(r2)
/* and continue in libc-start, in glibc. */
b JUMPTARGET(__libc_start_main)
/* Older versions of ld need this nop to recognize that it's OK to call via a
TOC adjusting stub. */
nop
END(_start)
/* Define a symbol for the first piece of initialized data. */
.section ".data"
.globl __data_start
__data_start:
.long 0
weak_alias (__data_start, data_start)

View File

@@ -0,0 +1,86 @@
/* Startup code compliant to the ELF RISC-V ABI.
Copyright (C) 1995-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
#define __ASSEMBLY__ 1
#include <entry.h>
#include <sysdep.h>
#include <sys/asm.h>
/* The entry point's job is to call __libc_start_main. Per the ABI,
a0 contains the address of a function to be passed to atexit.
__libc_start_main wants this in a5. */
ENTRY (ENTRY_POINT)
/* Terminate call stack by noting ra is undefined. Use a dummy
.cfi_label to force starting the FDE. */
.cfi_label .Ldummy
cfi_undefined (ra)
call load_gp
mv a5, a0 /* rtld_fini. */
/* main may be in a shared library. */
la a0, main
REG_L a1, 0(sp) /* argc. */
addi a2, sp, SZREG /* argv. */
andi sp, sp, ALMASK /* Align stack. */
lla a3, __libc_csu_init
lla a4, __libc_csu_fini
mv a6, sp /* stack_end. */
call __libc_start_main@plt
ebreak
END (ENTRY_POINT)
/* Dynamic links need the global pointer to be initialized prior to calling
any shared library's initializers, so we use preinit_array to load it.
This doesn't cut it for static links, though, since the global pointer
needs to be initialized before calling __libc_start_main in that case.
So we redundantly initialize it at the beginning of _start. */
load_gp:
.option push
.option norelax
lla gp, __global_pointer$
.option pop
ret
.section .preinit_array,"aw"
.dc.a load_gp
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.weak data_start
data_start = __data_start

View File

@@ -0,0 +1,218 @@
/* Startup code compliant to the ELF s390 ABI.
Copyright (C) 2000-2020 Free Software Foundation, Inc.
Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
/*
This is the canonical entry point, usually the first thing in the text
segment. Most registers' values are unspecified, except for:
%r14 Contains a function pointer to be registered with `atexit'.
This is how the dynamic linker arranges to have DT_FINI
functions called for shared libraries that have been loaded
before this code runs.
%r15 The stack contains the arguments and environment:
0(%r15) argc
4(%r15) argv[0]
...
(4*argc)(%r15) NULL
(4*(argc+1))(%r15) envp[0]
...
NULL
*/
.text
.globl _start
.type _start,@function
_start:
cfi_startproc
/* Mark r14 as undefined in order to stop unwinding here! */
cfi_undefined (r14)
/* Check if the kernel provides highgprs facility if needed by
the binary. */
lr %r6,%r15
la %r6,4(%r6) /* Skip the argument counter. */
.L11: l %r5,0(%r6) /* Skip the argument vector. */
la %r6,4(%r6)
ltr %r5,%r5
jne .L11
.L12: l %r5,0(%r6) /* Skip the environment vector. */
la %r6,4(%r6)
ltr %r5,%r5
jne .L12
/* Usually the auxiliary vector can be expected directly after
the environment variables. But we have to skip extra zeros
because the loader might have removed unsecure variables for
setuid programs. */
.L26: l %r5,0(%r6)
la %r6,4(%r6)
ltr %r5,%r5
jz .L26
ahi %r6,-4
/* Obtain the needed values from the auxiliary vector. */
lhi %r7,16 /* AT_HWCAP */
lhi %r8,3 /* AT_PHDR */
lhi %r9,5 /* AT_PHNUM */
lhi %r2,4 /* AT_PHENT */
.L13: l %r5,0(%r6)
clr %r5,%r7
jne .L15
l %r10,4(%r6) /* r10 = AT_HWCAP value. */
.L15: clr %r5,%r8
jne .L16
l %r11,4(%r6) /* r11 = AT_PHDR value. */
.L16: clr %r5,%r9
jne .L17
l %r12,4(%r6) /* r12 = AT_PHNUM value. */
.L17: clr %r5,%r2
jne .L18
l %r0,4(%r6) /* r0 = AT_PHENT value. */
.L18: ltr %r5,%r5
la %r6,8(%r6)
jnz .L13
/* Locate the ELF header by looking for the first PT_LOAD
segment with a p_offset of zero. */
lr %r4,%r11 /* Backup AT_PHDR. */
lhi %r7,1 /* PT_LOAD id */
lhi %r8,0
.L19: cl %r7,0(%r4) /* p_type == PT_LOAD? */
jne .L20
cl %r8,4(%r4) /* p_offset == 0? */
jne .L20
l %r9,8(%r4) /* r9 = PT_LOAD.p_vaddr <- ELF header address */
j .L24
.L20: alr %r4,%r0 /* r4 += AT_PHENT value */
brct %r12,.L19
j .+2 /* Trap, there must be such a phdr. */
.L24: lr %r4,%r11 /* Backup AT_PHDR. */
lhi %r2,6 /* PT_PHDR id */
.L23: cl %r2,0(%r4)
jne .L22
l %r3,8(%r4) /* r3 = PT_PHDR p_vaddr */
j .L25
.L22: alr %r4,%r0 /* r4 += AT_PHENT value */
brct %r12,.L23
j .L14 /* No PT_PHDR found - skip checking. */
.L25: slr %r11,%r3 /* AT_PHDR - PT_PHDR.p_vaddr (relocation offset)*/
alr %r9,%r11 /* PT_LOAD.p_vaddr += relocation offset */
l %r5,36(%r9) /* Load the e_flags field. */
tml %r5,1
jz .L14 /* Binary does not require highgprs facility. */
tml %r10,512 /* Check the AT_HWCAP value. */
jz 2 /* Trap if no highgprs facility available. */
.L14:
/* Setup pointer to literal pool of _start */
basr %r13,0
.L0: ahi %r13,.Llit-.L0
/* load argc and argv from stack */
la %r4,4(%r15) # get argv
l %r3,0(%r15) # get argc
/* align the stack to a double word boundary */
lhi %r0,-8
nr %r15,%r0
/* Setup a stack frame and a parameter area */
ahi %r15,-104 # make room on stack
xc 0(4,%r15),0(%r15) # clear back-chain
/* set up arguments for __libc_start_main:
main, argc, argv, envp, _init, _fini, rtld_fini, stack_end
Note that envp will be determined later in __libc_start_main
*/
stm %r14,%r15,96(%r15) # store rtld_fini/stack_end to parameter area
la %r7,96(%r15)
l %r6,.L2-.Llit(%r13) # load pointer to __libc_csu_fini
l %r5,.L1-.Llit(%r13) # load pointer to __libc_csu_init
l %r2,.L3-.Llit(%r13) # load pointer to main
l %r1,.L4-.Llit(%r13) # load pointer to __libc_start_main
#ifdef PIC
l %r12,.L5-.Llit(%r13) # load .got pointer
la %r6,0(%r13,%r6)
la %r5,0(%r13,%r5)
la %r12,0(%r13,%r12)
l %r2,0(%r12,%r2)
la %r1,0(%r13,%r1)
#endif
/* ok, now branch to the libc main routine */
basr %r14,%r1
/* crash if __libc_start_main returns */
.word 0
cfi_endproc
.Llit:
#ifndef PIC
.L1: .long __libc_csu_init
.L2: .long __libc_csu_fini
.L3: .long main
.L4: .long __libc_start_main
#else
.L1: .long __libc_csu_init-.Llit
.L2: .long __libc_csu_fini-.Llit
.L3: .long main@GOT
.L4: .long __libc_start_main@plt-.Llit
.L5: .long _GLOBAL_OFFSET_TABLE_-.Llit
#endif
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.long 0
.weak data_start
data_start = __data_start

View File

@@ -0,0 +1,107 @@
/* Startup code compliant to the 64 bit S/390 ELF ABI.
Copyright (C) 2001-2020 Free Software Foundation, Inc.
Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
/*
This is the canonical entry point, usually the first thing in the text
segment. Most registers' values are unspecified, except for:
%r14 Contains a function pointer to be registered with `atexit'.
This is how the dynamic linker arranges to have DT_FINI
functions called for shared libraries that have been loaded
before this code runs.
%r15 The stack contains the arguments and environment:
0(%r15) argc
8(%r15) argv[0]
...
(8*argc)(%r15) NULL
(8*(argc+1))(%r15) envp[0]
...
NULL
*/
.text
.globl _start
.type _start,@function
_start:
cfi_startproc
/* Mark r14 as undefined in order to stop unwinding here! */
cfi_undefined (r14)
/* Load argc and argv from stack. */
la %r4,8(%r15) # get argv
lg %r3,0(%r15) # get argc
/* Align the stack to a double word boundary. */
lghi %r0,-16
ngr %r15,%r0
/* Setup a stack frame and a parameter area. */
aghi %r15,-176 # make room on stack
xc 0(8,%r15),0(%r15) # clear back-chain
/* Set up arguments for __libc_start_main:
main, argc, argv, envp, _init, _fini, rtld_fini, stack_end
Note that envp will be determined later in __libc_start_main.
*/
stmg %r14,%r15,160(%r15) # store rtld_fini/stack_end to parameter area
la %r7,160(%r15)
larl %r6,__libc_csu_fini # load pointer to __libc_csu_fini
larl %r5,__libc_csu_init # load pointer to __libc_csu_init
/* Ok, now branch to the libc main routine. */
#ifdef PIC
larl %r2,main@GOTENT # load pointer to main
lg %r2,0(%r2)
brasl %r14,__libc_start_main@plt
#else
larl %r2,main # load pointer to main
brasl %r14,__libc_start_main
#endif
/* Crash if __libc_start_main returns. */
.word 0
cfi_endproc
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.long 0
.weak data_start
data_start = __data_start

111
lib/libc/glibc/sysdeps/sh/start-2.33.S vendored Normal file
View File

@@ -0,0 +1,111 @@
/* Startup code for SH & ELF.
Copyright (C) 1999-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
/* This is the canonical entry point, usually the first thing in the text
segment.
Note that the code in the .init section has already been run.
This includes _init and _libc_init
At this entry point, most registers' values are unspecified, except:
r4 Contains a function pointer to be registered with `atexit'.
This is how the dynamic linker arranges to have DT_FINI
functions called for shared libraries that have been loaded
before this code runs.
sp The stack contains the arguments and environment:
0(sp) argc
4(sp) argv[0]
...
(4*argc)(sp) NULL
(4*(argc+1))(sp) envp[0]
...
NULL
*/
.text
.globl _start
.type _start,@function
_start:
/* Clear the frame pointer since this is the outermost frame. */
mov #0, r14
/* Pop argc off the stack and save a pointer to argv */
mov.l @r15+,r5
mov r15, r6
/* Push the last arguments to main() onto the stack */
mov.l r4,@-r15
mov.l L_fini,r0
mov.l r0,@-r15
/* Set up the other arguments for main() that go in registers */
mov.l L_main,r4
mov.l L_init,r7
/* __libc_start_main (main, argc, argv, init, fini, rtld_fini) */
/* Let the libc call main and exit with its return code. */
mov.l L_libc_start_main,r1
jsr @r1
nop
/* should never get here....*/
mov.l L_abort,r1
jsr @r1
nop
.align 2
L_main:
.long main
L_init:
.long __libc_csu_init
L_fini:
.long __libc_csu_fini
L_libc_start_main:
.long __libc_start_main
L_abort:
.long abort
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.long 0
.weak data_start
data_start = __data_start
.global __fpscr_values
__fpscr_values:
.long 0
.long 0x80000

View File

@@ -0,0 +1,99 @@
/* Startup code for elf32-sparc
Copyright (C) 1997-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson <richard@gnu.ai.mit.edu>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
.section ".text"
.align 4
.global _start
.type _start,#function
_start:
#ifdef PIC
SETUP_PIC_REG(l7)
#endif
/* Terminate the stack frame, and reserve space for functions to
drop their arguments. */
mov %g0, %fp
sub %sp, 6*4, %sp
/* Extract the arguments and environment as encoded on the stack. The
argument info starts after one register window (16 words) past the SP. */
ld [%sp+22*4], %o1
add %sp, 23*4, %o2
/* Load the addresses of the user entry points. */
#ifndef PIC
sethi %hi(main), %o0
sethi %hi(__libc_csu_init), %o3
sethi %hi(__libc_csu_fini), %o4
or %o0, %lo(main), %o0
or %o3, %lo(__libc_csu_init), %o3
or %o4, %lo(__libc_csu_fini), %o4
#else
sethi %gdop_hix22(main), %o0
sethi %gdop_hix22(__libc_csu_init), %o3
sethi %gdop_hix22(__libc_csu_fini), %o4
xor %o0, %gdop_lox10(main), %o0
xor %o3, %gdop_lox10(__libc_csu_init), %o3
xor %o4, %gdop_lox10(__libc_csu_fini), %o4
ld [%l7 + %o0], %o0, %gdop(main)
ld [%l7 + %o3], %o3, %gdop(__libc_csu_init)
ld [%l7 + %o4], %o4, %gdop(__libc_csu_fini)
#endif
/* When starting a binary via the dynamic linker, %g1 contains the
address of the shared library termination function, which will be
registered with atexit(). If we are statically linked, this will
be NULL. */
mov %g1, %o5
/* Let libc do the rest of the initialization, and call main. */
call __libc_start_main
nop
/* Die very horribly if exit returns. */
unimp
.size _start, .-_start
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.long 0
weak_alias (__data_start, data_start)

View File

@@ -0,0 +1,100 @@
/* Startup code for elf64-sparc
Copyright (C) 1997-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Richard Henderson <richard@gnu.ai.mit.edu>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <sysdep.h>
.section ".text"
.align 4
.global _start
.type _start,#function
_start:
#ifdef PIC
SETUP_PIC_REG(l7)
#endif
/* Terminate the stack frame, and reserve space for functions to
drop their arguments. */
mov %g0, %fp
sub %sp, 6*8, %sp
/* Extract the arguments and environment as encoded on the stack. The
argument info starts after one register window (16 words) past the SP,
plus the bias we added, plus the magic v9 STACK_BIAS. */
ldx [%sp+STACK_BIAS+22*8], %o1
add %sp, STACK_BIAS+23*8, %o2
/* Load the addresses of the user entry points. */
#ifndef PIC
sethi %hi(main), %o0
sethi %hi(__libc_csu_init), %o3
sethi %hi(__libc_csu_fini), %o4
or %o0, %lo(main), %o0
or %o3, %lo(__libc_csu_init), %o3
or %o4, %lo(__libc_csu_fini), %o4
#else
sethi %gdop_hix22(main), %o0
sethi %gdop_hix22(__libc_csu_init), %o3
sethi %gdop_hix22(__libc_csu_fini), %o4
xor %o0, %gdop_lox10(main), %o0
xor %o3, %gdop_lox10(__libc_csu_init), %o3
xor %o4, %gdop_lox10(__libc_csu_fini), %o4
ldx [%l7 + %o0], %o0, %gdop(main)
ldx [%l7 + %o3], %o3, %gdop(__libc_csu_init)
ldx [%l7 + %o4], %o4, %gdop(__libc_csu_fini)
#endif
/* When starting a binary via the dynamic linker, %g1 contains the
address of the shared library termination function, which will be
registered with atexit(). If we are statically linked, this will
be NULL. */
mov %g1, %o5
/* Let libc do the rest of the initialization, and call main. */
call __libc_start_main
nop
/* Die very horribly if exit returns. */
illtrap 0
.size _start, .-_start
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.long 0
weak_alias (__data_start, data_start)

View File

@@ -0,0 +1,131 @@
/* Startup code compliant to the ELF x86-64 ABI.
Copyright (C) 2001-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Andreas Jaeger <aj@suse.de>, 2001.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
/* This is the canonical entry point, usually the first thing in the text
segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
point runs, most registers' values are unspecified, except for:
%rdx Contains a function pointer to be registered with `atexit'.
This is how the dynamic linker arranges to have DT_FINI
functions called for shared libraries that have been loaded
before this code runs.
%rsp The stack contains the arguments and environment:
0(%rsp) argc
LP_SIZE(%rsp) argv[0]
...
(LP_SIZE*argc)(%rsp) NULL
(LP_SIZE*(argc+1))(%rsp) envp[0]
...
NULL
*/
#include <sysdep.h>
ENTRY (_start)
/* Clearing frame pointer is insufficient, use CFI. */
cfi_undefined (rip)
/* Clear the frame pointer. The ABI suggests this be done, to mark
the outermost frame obviously. */
xorl %ebp, %ebp
/* Extract the arguments as encoded on the stack and set up
the arguments for __libc_start_main (int (*main) (int, char **, char **),
int argc, char *argv,
void (*init) (void), void (*fini) (void),
void (*rtld_fini) (void), void *stack_end).
The arguments are passed via registers and on the stack:
main: %rdi
argc: %rsi
argv: %rdx
init: %rcx
fini: %r8
rtld_fini: %r9
stack_end: stack. */
mov %RDX_LP, %R9_LP /* Address of the shared library termination
function. */
#ifdef __ILP32__
mov (%rsp), %esi /* Simulate popping 4-byte argument count. */
add $4, %esp
#else
popq %rsi /* Pop the argument count. */
#endif
/* argv starts just at the current stack top. */
mov %RSP_LP, %RDX_LP
/* Align the stack to a 16 byte boundary to follow the ABI. */
and $~15, %RSP_LP
/* Push garbage because we push 8 more bytes. */
pushq %rax
/* Provide the highest stack address to the user code (for stacks
which grow downwards). */
pushq %rsp
#ifdef PIC
/* Pass address of our own entry points to .fini and .init. */
mov __libc_csu_fini@GOTPCREL(%rip), %R8_LP
mov __libc_csu_init@GOTPCREL(%rip), %RCX_LP
mov main@GOTPCREL(%rip), %RDI_LP
#else
/* Pass address of our own entry points to .fini and .init. */
mov $__libc_csu_fini, %R8_LP
mov $__libc_csu_init, %RCX_LP
mov $main, %RDI_LP
#endif
/* Call the user's main function, and exit with its value.
But let the libc call main. Since __libc_start_main in
libc.so is called very early, lazy binding isn't relevant
here. Use indirect branch via GOT to avoid extra branch
to PLT slot. In case of static executable, ld in binutils
2.26 or above can convert indirect branch into direct
branch. */
call *__libc_start_main@GOTPCREL(%rip)
hlt /* Crash if somehow `exit' does return. */
END (_start)
/* Define a symbol for the first piece of initialized data. */
.data
.globl __data_start
__data_start:
.long 0
.weak data_start
data_start = __data_start

View File

@@ -29,7 +29,7 @@
#define POLLRDHUP 0x2000 #define POLLRDHUP 0x2000
#endif #endif
#define POLLFREE (__poll_t)0x4000 /* currently only for epoll */ #define POLLFREE (__poll_t)0x4000
#define POLL_BUSY_LOOP (__poll_t)0x8000 #define POLL_BUSY_LOOP (__poll_t)0x8000

View File

@@ -196,6 +196,13 @@ struct drm_virtgpu_context_init {
__u64 ctx_set_params; __u64 ctx_set_params;
}; };
/*
* Event code that's given when VIRTGPU_CONTEXT_PARAM_POLL_RINGS_MASK is in
* effect. The event size is sizeof(drm_event), since there is no additional
* payload.
*/
#define VIRTGPU_EVENT_FENCE_SIGNALED 0x90000000
#define DRM_IOCTL_VIRTGPU_MAP \ #define DRM_IOCTL_VIRTGPU_MAP \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_MAP, struct drm_virtgpu_map) DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_MAP, struct drm_virtgpu_map)

View File

@@ -9,6 +9,7 @@
#define __BIG_ENDIAN_BITFIELD #define __BIG_ENDIAN_BITFIELD
#endif #endif
#include <linux/stddef.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/swab.h> #include <linux/swab.h>

View File

@@ -9,6 +9,7 @@
#define __LITTLE_ENDIAN_BITFIELD #define __LITTLE_ENDIAN_BITFIELD
#endif #endif
#include <linux/stddef.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/swab.h> #include <linux/swab.h>

View File

@@ -117,7 +117,7 @@
#define ETH_P_IFE 0xED3E /* ForCES inter-FE LFB type */ #define ETH_P_IFE 0xED3E /* ForCES inter-FE LFB type */
#define ETH_P_AF_IUCV 0xFBFB /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */ #define ETH_P_AF_IUCV 0xFBFB /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */
#define ETH_P_802_3_MIN 0x0600 /* If the value in the ethernet type is less than this value #define ETH_P_802_3_MIN 0x0600 /* If the value in the ethernet type is more than this value
* then the frame is Ethernet II. Else it is 802.3 */ * then the frame is Ethernet II. Else it is 802.3 */
/* /*

View File

@@ -134,19 +134,21 @@ struct mptcp_info {
* MPTCP_EVENT_REMOVED: token, rem_id * MPTCP_EVENT_REMOVED: token, rem_id
* An address has been lost by the peer. * An address has been lost by the peer.
* *
* MPTCP_EVENT_SUB_ESTABLISHED: token, family, saddr4 | saddr6, * MPTCP_EVENT_SUB_ESTABLISHED: token, family, loc_id, rem_id,
* daddr4 | daddr6, sport, dport, backup, * saddr4 | saddr6, daddr4 | daddr6, sport,
* if_idx [, error] * dport, backup, if_idx [, error]
* A new subflow has been established. 'error' should not be set. * A new subflow has been established. 'error' should not be set.
* *
* MPTCP_EVENT_SUB_CLOSED: token, family, saddr4 | saddr6, daddr4 | daddr6, * MPTCP_EVENT_SUB_CLOSED: token, family, loc_id, rem_id, saddr4 | saddr6,
* sport, dport, backup, if_idx [, error] * daddr4 | daddr6, sport, dport, backup, if_idx
* [, error]
* A subflow has been closed. An error (copy of sk_err) could be set if an * A subflow has been closed. An error (copy of sk_err) could be set if an
* error has been detected for this subflow. * error has been detected for this subflow.
* *
* MPTCP_EVENT_SUB_PRIORITY: token, family, saddr4 | saddr6, daddr4 | daddr6, * MPTCP_EVENT_SUB_PRIORITY: token, family, loc_id, rem_id, saddr4 | saddr6,
* sport, dport, backup, if_idx [, error] * daddr4 | daddr6, sport, dport, backup, if_idx
* The priority of a subflow has changed. 'error' should not be set. * [, error]
* The priority of a subflow has changed. 'error' should not be set.
*/ */
enum mptcp_event_type { enum mptcp_event_type {
MPTCP_EVENT_UNSPEC = 0, MPTCP_EVENT_UNSPEC = 0,

View File

@@ -263,7 +263,7 @@ enum nfc_sdp_attr {
#define NFC_SE_ENABLED 0x1 #define NFC_SE_ENABLED 0x1
struct sockaddr_nfc { struct sockaddr_nfc {
sa_family_t sa_family; __kernel_sa_family_t sa_family;
__u32 dev_idx; __u32 dev_idx;
__u32 target_idx; __u32 target_idx;
__u32 nfc_protocol; __u32 nfc_protocol;
@@ -271,14 +271,14 @@ struct sockaddr_nfc {
#define NFC_LLCP_MAX_SERVICE_NAME 63 #define NFC_LLCP_MAX_SERVICE_NAME 63
struct sockaddr_nfc_llcp { struct sockaddr_nfc_llcp {
sa_family_t sa_family; __kernel_sa_family_t sa_family;
__u32 dev_idx; __u32 dev_idx;
__u32 target_idx; __u32 target_idx;
__u32 nfc_protocol; __u32 nfc_protocol;
__u8 dsap; /* Destination SAP, if known */ __u8 dsap; /* Destination SAP, if known */
__u8 ssap; /* Source SAP to be bound to */ __u8 ssap; /* Source SAP to be bound to */
char service_name[NFC_LLCP_MAX_SERVICE_NAME]; /* Service name URI */; char service_name[NFC_LLCP_MAX_SERVICE_NAME]; /* Service name URI */;
size_t service_name_len; __kernel_size_t service_name_len;
}; };
/* NFC socket protocols */ /* NFC socket protocols */

View File

@@ -66,10 +66,17 @@ struct rlimit64 {
#define _STK_LIM (8*1024*1024) #define _STK_LIM (8*1024*1024)
/* /*
* GPG2 wants 64kB of mlocked memory, to make sure pass phrases * Limit the amount of locked memory by some sane default:
* and other sensitive information are never written to disk. * root can always increase this limit if needed.
*
* The main use-cases are (1) preventing sensitive memory
* from being swapped; (2) real-time operations; (3) via
* IOURING_REGISTER_BUFFERS.
*
* The first two don't need much. The latter will take as
* much as it can get. 8MB is a reasonably sane default.
*/ */
#define MLOCK_LIMIT ((PAGE_SIZE > 64*1024) ? PAGE_SIZE : 64*1024) #define MLOCK_LIMIT (8*1024*1024)
/* /*
* Due to binary compatibility, the actual resource numbers * Due to binary compatibility, the actual resource numbers

View File

@@ -1,5 +1,5 @@
#define LINUX_VERSION_CODE 331776 #define LINUX_VERSION_CODE 331778
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c))) #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c)))
#define LINUX_VERSION_MAJOR 5 #define LINUX_VERSION_MAJOR 5
#define LINUX_VERSION_PATCHLEVEL 16 #define LINUX_VERSION_PATCHLEVEL 16
#define LINUX_VERSION_SUBLEVEL 0 #define LINUX_VERSION_SUBLEVEL 2

View File

@@ -220,8 +220,12 @@
# define _DEFAULT_SOURCE 1 # define _DEFAULT_SOURCE 1
# undef _ATFILE_SOURCE # undef _ATFILE_SOURCE
# define _ATFILE_SOURCE 1 # define _ATFILE_SOURCE 1
# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 34) || __GLIBC__ > 2
# undef _DYNAMIC_STACK_SIZE_SOURCE # undef _DYNAMIC_STACK_SIZE_SOURCE
# define _DYNAMIC_STACK_SIZE_SOURCE 1 # define _DYNAMIC_STACK_SIZE_SOURCE 1
# endif
#endif #endif
/* If nothing (other than _GNU_SOURCE and _DEFAULT_SOURCE) is defined, /* If nothing (other than _GNU_SOURCE and _DEFAULT_SOURCE) is defined,
@@ -477,7 +481,7 @@
/* Major and minor version number of the GNU C library package. Use /* Major and minor version number of the GNU C library package. Use
these macros to test for features in specific releases. */ these macros to test for features in specific releases. */
#define __GLIBC__ 2 #define __GLIBC__ 2
#define __GLIBC_MINOR__ 34 /* Zig patch: we pass `-D__GLIBC_MINOR__=XX` depending on the target. */
#define __GLIBC_PREREQ(maj, min) \ #define __GLIBC_PREREQ(maj, min) \
((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min)) ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min))
@@ -512,4 +516,4 @@
#include <gnu/stubs.h> #include <gnu/stubs.h>
#endif /* features.h */ #endif /* features.h */

View File

@@ -16,6 +16,7 @@ pub const StaticResetEvent = @import("Thread/StaticResetEvent.zig");
pub const Mutex = @import("Thread/Mutex.zig"); pub const Mutex = @import("Thread/Mutex.zig");
pub const Semaphore = @import("Thread/Semaphore.zig"); pub const Semaphore = @import("Thread/Semaphore.zig");
pub const Condition = @import("Thread/Condition.zig"); pub const Condition = @import("Thread/Condition.zig");
pub const RwLock = @import("Thread/RwLock.zig");
pub const use_pthreads = target.os.tag != .windows and target.os.tag != .wasi and builtin.link_libc; pub const use_pthreads = target.os.tag != .windows and target.os.tag != .wasi and builtin.link_libc;
const is_gnu = target.abi.isGnu(); const is_gnu = target.abi.isGnu();
@@ -1151,3 +1152,27 @@ test "Thread.detach" {
event.wait(); event.wait();
try std.testing.expectEqual(value, 1); try std.testing.expectEqual(value, 1);
} }
fn testWaitForSignal(mutex: *Mutex, cond: *Condition) void {
mutex.lock();
defer mutex.unlock();
cond.signal();
cond.wait(mutex);
}
test "Condition.signal" {
if (builtin.single_threaded) return error.SkipZigTest;
var mutex = Mutex{};
var cond = Condition{};
var thread: Thread = undefined;
{
mutex.lock();
defer mutex.unlock();
thread = try Thread.spawn(.{}, testWaitForSignal, .{ &mutex, &cond });
cond.wait(&mutex);
cond.signal();
}
thread.join();
}

View File

@@ -106,7 +106,7 @@ pub const AtomicCondition = struct {
.linux => { .linux => {
switch (linux.getErrno(linux.futex_wait( switch (linux.getErrno(linux.futex_wait(
&cond.futex, &cond.futex,
linux.FUTEX_PRIVATE_FLAG | linux.FUTEX_WAIT, linux.FUTEX.PRIVATE_FLAG | linux.FUTEX.WAIT,
0, 0,
null, null,
))) { ))) {
@@ -128,7 +128,7 @@ pub const AtomicCondition = struct {
.linux => { .linux => {
switch (linux.getErrno(linux.futex_wake( switch (linux.getErrno(linux.futex_wake(
&cond.futex, &cond.futex,
linux.FUTEX_PRIVATE_FLAG | linux.FUTEX_WAKE, linux.FUTEX.PRIVATE_FLAG | linux.FUTEX.WAKE,
1, 1,
))) { ))) {
.SUCCESS => {}, .SUCCESS => {},

View File

@@ -3,15 +3,12 @@
//! This API requires being initialized at runtime, and initialization //! This API requires being initialized at runtime, and initialization
//! can fail. Once initialized, the core operations cannot fail. //! can fail. Once initialized, the core operations cannot fail.
impl: Impl, impl: Impl = .{},
const RwLock = @This(); const RwLock = @This();
const std = @import("../std.zig"); const std = @import("../std.zig");
const builtin = @import("builtin"); const builtin = @import("builtin");
const assert = std.debug.assert; const assert = std.debug.assert;
const Mutex = std.Thread.Mutex;
const Semaphore = std.Semaphore;
const CondVar = std.CondVar;
pub const Impl = if (builtin.single_threaded) pub const Impl = if (builtin.single_threaded)
SingleThreadedRwLock SingleThreadedRwLock
@@ -20,14 +17,6 @@ else if (std.Thread.use_pthreads)
else else
DefaultRwLock; DefaultRwLock;
pub fn init(rwl: *RwLock) void {
return rwl.impl.init();
}
pub fn deinit(rwl: *RwLock) void {
return rwl.impl.deinit();
}
/// Attempts to obtain exclusive lock ownership. /// Attempts to obtain exclusive lock ownership.
/// Returns `true` if the lock is obtained, `false` otherwise. /// Returns `true` if the lock is obtained, `false` otherwise.
pub fn tryLock(rwl: *RwLock) bool { pub fn tryLock(rwl: *RwLock) bool {
@@ -64,20 +53,8 @@ pub fn unlockShared(rwl: *RwLock) void {
/// Single-threaded applications use this for deadlock checks in /// Single-threaded applications use this for deadlock checks in
/// debug mode, and no-ops in release modes. /// debug mode, and no-ops in release modes.
pub const SingleThreadedRwLock = struct { pub const SingleThreadedRwLock = struct {
state: enum { unlocked, locked_exclusive, locked_shared }, state: enum { unlocked, locked_exclusive, locked_shared } = .unlocked,
shared_count: usize, shared_count: usize = 0,
pub fn init(rwl: *SingleThreadedRwLock) void {
rwl.* = .{
.state = .unlocked,
.shared_count = 0,
};
}
pub fn deinit(rwl: *SingleThreadedRwLock) void {
assert(rwl.state == .unlocked);
assert(rwl.shared_count == 0);
}
/// Attempts to obtain exclusive lock ownership. /// Attempts to obtain exclusive lock ownership.
/// Returns `true` if the lock is obtained, `false` otherwise. /// Returns `true` if the lock is obtained, `false` otherwise.
@@ -152,55 +129,41 @@ pub const SingleThreadedRwLock = struct {
}; };
pub const PthreadRwLock = struct { pub const PthreadRwLock = struct {
rwlock: pthread_rwlock_t, rwlock: std.c.pthread_rwlock_t = .{},
pub fn init(rwl: *PthreadRwLock) void {
rwl.* = .{ .rwlock = .{} };
}
pub fn deinit(rwl: *PthreadRwLock) void {
const safe_rc: std.os.E = switch (builtin.os.tag) {
.dragonfly, .netbsd => .AGAIN,
else => .SUCCESS,
};
const rc = std.c.pthread_rwlock_destroy(&rwl.rwlock);
assert(rc == .SUCCESS or rc == safe_rc);
rwl.* = undefined;
}
pub fn tryLock(rwl: *PthreadRwLock) bool { pub fn tryLock(rwl: *PthreadRwLock) bool {
return pthread_rwlock_trywrlock(&rwl.rwlock) == .SUCCESS; return std.c.pthread_rwlock_trywrlock(&rwl.rwlock) == .SUCCESS;
} }
pub fn lock(rwl: *PthreadRwLock) void { pub fn lock(rwl: *PthreadRwLock) void {
const rc = pthread_rwlock_wrlock(&rwl.rwlock); const rc = std.c.pthread_rwlock_wrlock(&rwl.rwlock);
assert(rc == .SUCCESS); assert(rc == .SUCCESS);
} }
pub fn unlock(rwl: *PthreadRwLock) void { pub fn unlock(rwl: *PthreadRwLock) void {
const rc = pthread_rwlock_unlock(&rwl.rwlock); const rc = std.c.pthread_rwlock_unlock(&rwl.rwlock);
assert(rc == .SUCCESS); assert(rc == .SUCCESS);
} }
pub fn tryLockShared(rwl: *PthreadRwLock) bool { pub fn tryLockShared(rwl: *PthreadRwLock) bool {
return pthread_rwlock_tryrdlock(&rwl.rwlock) == .SUCCESS; return std.c.pthread_rwlock_tryrdlock(&rwl.rwlock) == .SUCCESS;
} }
pub fn lockShared(rwl: *PthreadRwLock) void { pub fn lockShared(rwl: *PthreadRwLock) void {
const rc = pthread_rwlock_rdlock(&rwl.rwlock); const rc = std.c.pthread_rwlock_rdlock(&rwl.rwlock);
assert(rc == .SUCCESS); assert(rc == .SUCCESS);
} }
pub fn unlockShared(rwl: *PthreadRwLock) void { pub fn unlockShared(rwl: *PthreadRwLock) void {
const rc = pthread_rwlock_unlock(&rwl.rwlock); const rc = std.c.pthread_rwlock_unlock(&rwl.rwlock);
assert(rc == .SUCCESS); assert(rc == .SUCCESS);
} }
}; };
pub const DefaultRwLock = struct { pub const DefaultRwLock = struct {
state: usize, state: usize = 0,
mutex: Mutex, mutex: std.Thread.Mutex = .{},
semaphore: Semaphore, semaphore: std.Thread.Semaphore = .{},
const IS_WRITING: usize = 1; const IS_WRITING: usize = 1;
const WRITER: usize = 1 << 1; const WRITER: usize = 1 << 1;
@@ -209,20 +172,6 @@ pub const DefaultRwLock = struct {
const READER_MASK: usize = std.math.maxInt(Count) << @ctz(usize, READER); const READER_MASK: usize = std.math.maxInt(Count) << @ctz(usize, READER);
const Count = std.meta.Int(.unsigned, @divFloor(std.meta.bitCount(usize) - 1, 2)); const Count = std.meta.Int(.unsigned, @divFloor(std.meta.bitCount(usize) - 1, 2));
pub fn init(rwl: *DefaultRwLock) void {
rwl.* = .{
.state = 0,
.mutex = Mutex.init(),
.semaphore = Semaphore.init(0),
};
}
pub fn deinit(rwl: *DefaultRwLock) void {
rwl.semaphore.deinit();
rwl.mutex.deinit();
rwl.* = undefined;
}
pub fn tryLock(rwl: *DefaultRwLock) bool { pub fn tryLock(rwl: *DefaultRwLock) bool {
if (rwl.mutex.tryLock()) { if (rwl.mutex.tryLock()) {
const state = @atomicLoad(usize, &rwl.state, .SeqCst); const state = @atomicLoad(usize, &rwl.state, .SeqCst);

View File

@@ -1552,6 +1552,8 @@ pub const LibExeObjStep = struct {
subsystem: ?std.Target.SubSystem = null, subsystem: ?std.Target.SubSystem = null,
entry_symbol_name: ?[]const u8 = null,
/// Overrides the default stack size /// Overrides the default stack size
stack_size: ?u64 = null, stack_size: ?u64 = null,
@@ -2253,6 +2255,11 @@ pub const LibExeObjStep = struct {
try zig_args.append(@tagName(builder.color)); try zig_args.append(@tagName(builder.color));
} }
if (self.entry_symbol_name) |entry| {
try zig_args.append("--entry");
try zig_args.append(entry);
}
if (self.stack_size) |stack_size| { if (self.stack_size) |stack_size| {
try zig_args.append("--stack"); try zig_args.append("--stack");
try zig_args.append(try std.fmt.allocPrint(builder.allocator, "{}", .{stack_size})); try zig_args.append(try std.fmt.allocPrint(builder.allocator, "{}", .{stack_size}));
@@ -2651,6 +2658,8 @@ pub const LibExeObjStep = struct {
try zig_args.append(bin_name); try zig_args.append(bin_name);
try zig_args.append("--test-cmd"); try zig_args.append("--test-cmd");
try zig_args.append("--dir=."); try zig_args.append("--dir=.");
try zig_args.append("--test-cmd");
try zig_args.append("--allow-unknown-exports"); // TODO: Remove when stage2 is default compiler
try zig_args.append("--test-cmd-bin"); try zig_args.append("--test-cmd-bin");
} else { } else {
try zig_args.append("--test-no-exec"); try zig_args.append("--test-no-exec");

View File

@@ -357,6 +357,8 @@ pub extern "c" fn openlog(ident: [*:0]const u8, logopt: c_int, facility: c_int)
pub extern "c" fn closelog() void; pub extern "c" fn closelog() void;
pub extern "c" fn setlogmask(maskpri: c_int) c_int; pub extern "c" fn setlogmask(maskpri: c_int) c_int;
pub extern "c" fn if_nametoindex([*:0]const u8) c_int;
pub const max_align_t = if (builtin.abi == .msvc) pub const max_align_t = if (builtin.abi == .msvc)
f64 f64
else if (builtin.target.isDarwin()) else if (builtin.target.isDarwin())

View File

@@ -6,6 +6,26 @@ const native_arch = builtin.target.cpu.arch;
const maxInt = std.math.maxInt; const maxInt = std.math.maxInt;
const iovec_const = std.os.iovec_const; const iovec_const = std.os.iovec_const;
const arch_bits = switch (native_arch) {
.aarch64 => @import("darwin/aarch64.zig"),
.x86_64 => @import("darwin/x86_64.zig"),
else => struct {},
};
pub const ucontext_t = extern struct {
onstack: c_int,
sigmask: sigset_t,
stack: stack_t,
link: ?*ucontext_t,
mcsize: u64,
mcontext: *mcontext_t,
};
pub const mcontext_t = extern struct {
es: arch_bits.exception_state,
ss: arch_bits.thread_state,
};
extern "c" fn __error() *c_int; extern "c" fn __error() *c_int;
pub extern "c" fn NSVersionOfRunTimeLibrary(library_name: [*:0]const u8) u32; pub extern "c" fn NSVersionOfRunTimeLibrary(library_name: [*:0]const u8) u32;
pub extern "c" fn _NSGetExecutablePath(buf: [*:0]u8, bufsize: *u32) c_int; pub extern "c" fn _NSGetExecutablePath(buf: [*:0]u8, bufsize: *u32) c_int;
@@ -108,6 +128,8 @@ pub fn sigaddset(set: *sigset_t, signo: u5) void {
pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
pub const IFNAMESIZE = 16;
pub const AI = struct { pub const AI = struct {
/// get address to use bind() /// get address to use bind()
pub const PASSIVE = 0x00000001; pub const PASSIVE = 0x00000001;

View File

@@ -0,0 +1,18 @@
// See C headers in
// lib/libc/include/aarch64-macos.12-gnu/mach/arm/_structs.h
pub const exception_state = extern struct {
far: u64, // Virtual Fault Address
esr: u32, // Exception syndrome
exception: u32, // Number of arm exception taken
};
pub const thread_state = extern struct {
regs: [29]u64, // General purpose registers
fp: u64, // Frame pointer x29
lr: u64, // Link register x30
sp: u64, // Stack pointer x31
pc: u64, // Program counter
cpsr: u32, // Current program status register
__pad: u32,
};

View File

@@ -0,0 +1,30 @@
pub const exception_state = extern struct {
trapno: u16,
cpu: u16,
err: u32,
faultvaddr: u64,
};
pub const thread_state = extern struct {
rax: u64,
rbx: u64,
rcx: u64,
rdx: u64,
rdi: u64,
rsi: u64,
rbp: u64,
rsp: u64,
r8: u64,
r9: u64,
r10: u64,
r11: u64,
r12: u64,
r13: u64,
r14: u64,
r15: u64,
rip: u64,
rflags: u64,
cs: u64,
fs: u64,
gs: u64,
};

View File

@@ -56,6 +56,7 @@ pub const STDOUT_FILENO = linux.STDOUT_FILENO;
pub const SYS = linux.SYS; pub const SYS = linux.SYS;
pub const Sigaction = linux.Sigaction; pub const Sigaction = linux.Sigaction;
pub const TCP = linux.TCP; pub const TCP = linux.TCP;
pub const TCSA = linux.TCSA;
pub const VDSO = linux.VDSO; pub const VDSO = linux.VDSO;
pub const W = linux.W; pub const W = linux.W;
pub const W_OK = linux.W_OK; pub const W_OK = linux.W_OK;
@@ -85,11 +86,13 @@ pub const pollfd = linux.pollfd;
pub const rlim_t = linux.rlim_t; pub const rlim_t = linux.rlim_t;
pub const rlimit = linux.rlimit; pub const rlimit = linux.rlimit;
pub const rlimit_resource = linux.rlimit_resource; pub const rlimit_resource = linux.rlimit_resource;
pub const rusage = linux.rusage;
pub const siginfo_t = linux.siginfo_t; pub const siginfo_t = linux.siginfo_t;
pub const sigset_t = linux.sigset_t; pub const sigset_t = linux.sigset_t;
pub const sockaddr = linux.sockaddr; pub const sockaddr = linux.sockaddr;
pub const socklen_t = linux.socklen_t; pub const socklen_t = linux.socklen_t;
pub const stack_t = linux.stack_t; pub const stack_t = linux.stack_t;
pub const tcflag_t = linux.tcflag_t;
pub const termios = linux.termios; pub const termios = linux.termios;
pub const time_t = linux.time_t; pub const time_t = linux.time_t;
pub const timespec = linux.timespec; pub const timespec = linux.timespec;

View File

@@ -703,8 +703,48 @@ pub const T = struct {
pub const IOCXMTFRAME = 0x80087444; pub const IOCXMTFRAME = 0x80087444;
}; };
// BSD Authentication
pub const auth_item_t = c_int;
pub const AUTHV = struct {
pub const ALL: auth_item_t = 0;
pub const CHALLENGE: auth_item_t = 1;
pub const CLASS: auth_item_t = 2;
pub const NAME: auth_item_t = 3;
pub const SERVICE: auth_item_t = 4;
pub const STYLE: auth_item_t = 5;
pub const INTERACTIVE: auth_item_t = 6;
};
pub const BI = struct {
pub const AUTH = "authorize"; // Accepted authentication
pub const REJECT = "reject"; // Rejected authentication
pub const CHALLENGE = "reject challenge"; // Reject with a challenge
pub const SILENT = "reject silent"; // Reject silently
pub const REMOVE = "remove"; // remove file on error
pub const ROOTOKAY = "authorize root"; // root authenticated
pub const SECURE = "authorize secure"; // okay on non-secure line
pub const SETENV = "setenv"; // set environment variable
pub const UNSETENV = "unsetenv"; // unset environment variable
pub const VALUE = "value"; // set local variable
pub const EXPIRED = "reject expired"; // account expired
pub const PWEXPIRED = "reject pwexpired"; // password expired
pub const FDPASS = "fd"; // child is passing an fd
};
pub const AUTH = struct {
pub const OKAY: c_int = 0x01; // user authenticated
pub const ROOTOKAY: c_int = 0x02; // authenticated as root
pub const SECURE: c_int = 0x04; // secure login
pub const SILENT: c_int = 0x08; // silent rejection
pub const CHALLENGE: c_int = 0x10; // a challenge was given
pub const EXPIRED: c_int = 0x20; // account expired
pub const PWEXPIRED: c_int = 0x40; // password expired
pub const ALLOW: c_int = (OKAY | ROOTOKAY | SECURE);
};
// Term // Term
const V = struct { pub const V = struct {
pub const EOF = 0; // ICANON pub const EOF = 0; // ICANON
pub const EOL = 1; // ICANON pub const EOL = 1; // ICANON
pub const EOL2 = 2; // ICANON pub const EOL2 = 2; // ICANON
@@ -942,7 +982,7 @@ comptime {
std.debug.assert(@sizeOf(siginfo_t) == 136); std.debug.assert(@sizeOf(siginfo_t) == 136);
} }
const arch_bits = switch (builtin.cpu.arch) { pub usingnamespace switch (builtin.cpu.arch) {
.x86_64 => struct { .x86_64 => struct {
pub const ucontext_t = extern struct { pub const ucontext_t = extern struct {
sc_rdi: c_long, sc_rdi: c_long,
@@ -972,7 +1012,7 @@ const arch_bits = switch (builtin.cpu.arch) {
sc_rsp: c_long, sc_rsp: c_long,
sc_ss: c_long, sc_ss: c_long,
sc_fpstate: arch_bits.fxsave64, sc_fpstate: fxsave64,
__sc_unused: c_int, __sc_unused: c_int,
sc_mask: c_int, sc_mask: c_int,
sc_cookie: c_long, sc_cookie: c_long,
@@ -995,8 +1035,6 @@ const arch_bits = switch (builtin.cpu.arch) {
}, },
else => struct {}, else => struct {},
}; };
pub const ucontext_t = arch_bits.ucontext_t;
pub const fxsave64 = arch_bits.fxsave64;
pub const sigset_t = c_uint; pub const sigset_t = c_uint;
pub const empty_sigset: sigset_t = 0; pub const empty_sigset: sigset_t = 0;

View File

@@ -252,6 +252,35 @@ pub const ChildProcess = struct {
} }
} }
const WindowsAsyncReadResult = enum {
pending,
closed,
full,
};
fn windowsAsyncRead(
handle: windows.HANDLE,
overlapped: *windows.OVERLAPPED,
buf: *std.ArrayList(u8),
bump_amt: usize,
max_output_bytes: usize,
) !WindowsAsyncReadResult {
while (true) {
const new_capacity = std.math.min(buf.items.len + bump_amt, max_output_bytes);
try buf.ensureTotalCapacity(new_capacity);
const next_buf = buf.unusedCapacitySlice();
if (next_buf.len == 0) return .full;
var read_bytes: u32 = undefined;
const read_result = windows.kernel32.ReadFile(handle, next_buf.ptr, math.cast(u32, next_buf.len) catch maxInt(u32), &read_bytes, overlapped);
if (read_result == 0) return switch (windows.kernel32.GetLastError()) {
.IO_PENDING => .pending,
.BROKEN_PIPE => .closed,
else => |err| windows.unexpectedError(err),
};
buf.items.len += read_bytes;
}
}
fn collectOutputWindows(child: *const ChildProcess, outs: [2]*std.ArrayList(u8), max_output_bytes: usize) !void { fn collectOutputWindows(child: *const ChildProcess, outs: [2]*std.ArrayList(u8), max_output_bytes: usize) !void {
const bump_amt = 512; const bump_amt = 512;
const handles = [_]windows.HANDLE{ const handles = [_]windows.HANDLE{
@@ -274,15 +303,17 @@ pub const ChildProcess = struct {
// Windows Async IO requires an initial call to ReadFile before waiting on the handle // Windows Async IO requires an initial call to ReadFile before waiting on the handle
for ([_]u1{ 0, 1 }) |i| { for ([_]u1{ 0, 1 }) |i| {
const new_capacity = std.math.min(outs[i].items.len + bump_amt, max_output_bytes); switch (try windowsAsyncRead(handles[i], &overlapped[i], outs[i], bump_amt, max_output_bytes)) {
try outs[i].ensureTotalCapacity(new_capacity); .pending => {
const buf = outs[i].unusedCapacitySlice(); wait_objects[wait_object_count] = handles[i];
_ = windows.kernel32.ReadFile(handles[i], buf.ptr, math.cast(u32, buf.len) catch maxInt(u32), null, &overlapped[i]); wait_object_count += 1;
wait_objects[wait_object_count] = handles[i]; },
wait_object_count += 1; .closed => {}, // don't add to the wait_objects list
.full => return if (i == 0) error.StdoutStreamTooLong else error.StderrStreamTooLong,
}
} }
while (true) { while (wait_object_count > 0) {
const status = windows.kernel32.WaitForMultipleObjects(wait_object_count, &wait_objects, 0, windows.INFINITE); const status = windows.kernel32.WaitForMultipleObjects(wait_object_count, &wait_objects, 0, windows.INFINITE);
if (status == windows.WAIT_FAILED) { if (status == windows.WAIT_FAILED) {
switch (windows.kernel32.GetLastError()) { switch (windows.kernel32.GetLastError()) {
@@ -306,23 +337,21 @@ pub const ChildProcess = struct {
var read_bytes: u32 = undefined; var read_bytes: u32 = undefined;
if (windows.kernel32.GetOverlappedResult(handles[i], &overlapped[i], &read_bytes, 0) == 0) { if (windows.kernel32.GetOverlappedResult(handles[i], &overlapped[i], &read_bytes, 0) == 0) {
switch (windows.kernel32.GetLastError()) { switch (windows.kernel32.GetLastError()) {
.BROKEN_PIPE => { .BROKEN_PIPE => continue,
if (wait_object_count == 0)
break;
continue;
},
else => |err| return windows.unexpectedError(err), else => |err| return windows.unexpectedError(err),
} }
} }
outs[i].items.len += read_bytes; outs[i].items.len += read_bytes;
const new_capacity = std.math.min(outs[i].items.len + bump_amt, max_output_bytes);
try outs[i].ensureTotalCapacity(new_capacity); switch (try windowsAsyncRead(handles[i], &overlapped[i], outs[i], bump_amt, max_output_bytes)) {
const buf = outs[i].unusedCapacitySlice(); .pending => {
if (buf.len == 0) return if (i == 0) error.StdoutStreamTooLong else error.StderrStreamTooLong; wait_objects[wait_object_count] = handles[i];
_ = windows.kernel32.ReadFile(handles[i], buf.ptr, math.cast(u32, buf.len) catch maxInt(u32), null, &overlapped[i]); wait_object_count += 1;
wait_objects[wait_object_count] = handles[i]; },
wait_object_count += 1; .closed => {}, // don't add to the wait_objects list
.full => return if (i == 0) error.StdoutStreamTooLong else error.StderrStreamTooLong,
}
} }
} }

View File

@@ -158,7 +158,7 @@ pub const nacl = struct {
pub const utils = @import("crypto/utils.zig"); pub const utils = @import("crypto/utils.zig");
/// This is a thread-local, cryptographically secure pseudo random number generator. /// This is a thread-local, cryptographically secure pseudo random number generator.
pub const random = &@import("crypto/tlcsprng.zig").interface; pub const random = @import("crypto/tlcsprng.zig").interface;
const std = @import("std.zig"); const std = @import("std.zig");

View File

@@ -126,12 +126,29 @@ test "expand 128-bit key" {
} }
test "expand 256-bit key" { test "expand 256-bit key" {
const key = [_]u8{ 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 }; const key = [_]u8{
0x60, 0x3d, 0xeb, 0x10,
0x15, 0xca, 0x71, 0xbe,
0x2b, 0x73, 0xae, 0xf0,
0x85, 0x7d, 0x77, 0x81,
0x1f, 0x35, 0x2c, 0x07,
0x3b, 0x61, 0x08, 0xd7,
0x2d, 0x98, 0x10, 0xa3,
0x09, 0x14, 0xdf, 0xf4,
};
const exp_enc = [_]*const [32:0]u8{ const exp_enc = [_]*const [32:0]u8{
"603deb1015ca71be2b73aef0857d7781", "1f352c073b6108d72d9810a30914dff4", "9ba354118e6925afa51a8b5f2067fcde", "a8b09c1a93d194cdbe49846eb75d5b9a", "d59aecb85bf3c917fee94248de8ebe96", "b5a9328a2678a647983122292f6c79b3", "812c81addadf48ba24360af2fab8b464", "98c5bfc9bebd198e268c3ba709e04214", "68007bacb2df331696e939e46c518d80", "c814e20476a9fb8a5025c02d59c58239", "de1369676ccc5a71fa2563959674ee15", "5886ca5d2e2f31d77e0af1fa27cf73c3", "749c47ab18501ddae2757e4f7401905a", "cafaaae3e4d59b349adf6acebd10190d", "fe4890d1e6188d0b046df344706c631e", "603deb1015ca71be2b73aef0857d7781", "1f352c073b6108d72d9810a30914dff4", "9ba354118e6925afa51a8b5f2067fcde",
"a8b09c1a93d194cdbe49846eb75d5b9a", "d59aecb85bf3c917fee94248de8ebe96", "b5a9328a2678a647983122292f6c79b3",
"812c81addadf48ba24360af2fab8b464", "98c5bfc9bebd198e268c3ba709e04214", "68007bacb2df331696e939e46c518d80",
"c814e20476a9fb8a5025c02d59c58239", "de1369676ccc5a71fa2563959674ee15", "5886ca5d2e2f31d77e0af1fa27cf73c3",
"749c47ab18501ddae2757e4f7401905a", "cafaaae3e4d59b349adf6acebd10190d", "fe4890d1e6188d0b046df344706c631e",
}; };
const exp_dec = [_]*const [32:0]u8{ const exp_dec = [_]*const [32:0]u8{
"fe4890d1e6188d0b046df344706c631e", "ada23f4963e23b2455427c8a5c709104", "57c96cf6074f07c0706abb07137f9241", "b668b621ce40046d36a047ae0932ed8e", "34ad1e4450866b367725bcc763152946", "32526c367828b24cf8e043c33f92aa20", "c440b289642b757227a3d7f114309581", "d669a7334a7ade7a80c8f18fc772e9e3", "25ba3c22a06bc7fb4388a28333934270", "54fb808b9c137949cab22ff547ba186c", "6c3d632985d1fbd9e3e36578701be0f3", "4a7459f9c8e8f9c256a156bc8d083799", "42107758e9ec98f066329ea193f8858b", "8ec6bff6829ca03b9e49af7edba96125", "603deb1015ca71be2b73aef0857d7781", "fe4890d1e6188d0b046df344706c631e", "ada23f4963e23b2455427c8a5c709104", "57c96cf6074f07c0706abb07137f9241",
"b668b621ce40046d36a047ae0932ed8e", "34ad1e4450866b367725bcc763152946", "32526c367828b24cf8e043c33f92aa20",
"c440b289642b757227a3d7f114309581", "d669a7334a7ade7a80c8f18fc772e9e3", "25ba3c22a06bc7fb4388a28333934270",
"54fb808b9c137949cab22ff547ba186c", "6c3d632985d1fbd9e3e36578701be0f3", "4a7459f9c8e8f9c256a156bc8d083799",
"42107758e9ec98f066329ea193f8858b", "8ec6bff6829ca03b9e49af7edba96125", "603deb1015ca71be2b73aef0857d7781",
}; };
const enc = Aes256.initEnc(key); const enc = Aes256.initEnc(key);
const dec = Aes256.initDec(key); const dec = Aes256.initDec(key);

View File

@@ -26,12 +26,279 @@ pub const hash_length: usize = 60;
const State = struct { const State = struct {
sboxes: [4][256]u32 = [4][256]u32{ sboxes: [4][256]u32 = [4][256]u32{
.{ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a }, .{
.{ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 }, 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
.{ 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 }, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
.{ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 }, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
},
.{
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
},
.{
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
},
.{
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
},
},
subkeys: [18]u32 = [18]u32{
0x243f6a88, 0x85a308d3, 0x13198a2e,
0x03707344, 0xa4093822, 0x299f31d0,
0x082efa98, 0xec4e6c89, 0x452821e6,
0x38d01377, 0xbe5466cf, 0x34e90c6c,
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5,
0xb5470917, 0x9216d5d9, 0x8979fb1b,
}, },
subkeys: [18]u32 = [18]u32{ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b },
fn toWord(data: []const u8, current: *usize) u32 { fn toWord(data: []const u8, current: *usize) u32 {
var t: u32 = 0; var t: u32 = 0;

View File

@@ -13,7 +13,38 @@
// //
// Computed values: // Computed values:
// eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) // eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192)
// bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) // bytes_eval z = z[0]
// + (z[1] << 8)
// + (z[2] << 16)
// + (z[3] << 24)
// + (z[4] << 32)
// + (z[5] << 40)
// + (z[6] << 48)
// + (z[7] << 56)
// + (z[8] << 64)
// + (z[9] << 72)
// + (z[10] << 80)
// + (z[11] << 88)
// + (z[12] << 96)
// + (z[13] << 104)
// + (z[14] << 112)
// + (z[15] << 120)
// + (z[16] << 128)
// + (z[17] << 136)
// + (z[18] << 144)
// + (z[19] << 152)
// + (z[20] << 160)
// + (z[21] << 168)
// + (z[22] << 176)
// + (z[23] << 184)
// + (z[24] << 192)
// + (z[25] << 200)
// + (z[26] << 208)
// + (z[27] << 216)
// + (z[28] << 224)
// + (z[29] << 232)
// + (z[30] << 240)
// + (z[31] << 248)
// twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in // twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in
// if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256 // if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256

View File

@@ -13,7 +13,38 @@
// //
// Computed values: // Computed values:
// eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) // eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192)
// bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) // bytes_eval z = z[0]
// + (z[1] << 8)
// + (z[2] << 16)
// + (z[3] << 24)
// + (z[4] << 32)
// + (z[5] << 40)
// + (z[6] << 48)
// + (z[7] << 56)
// + (z[8] << 64)
// + (z[9] << 72)
// + (z[10] << 80)
// + (z[11] << 88)
// + (z[12] << 96)
// + (z[13] << 104)
// + (z[14] << 112)
// + (z[15] << 120)
// + (z[16] << 128)
// + (z[17] << 136)
// + (z[18] << 144)
// + (z[19] << 152)
// + (z[20] << 160)
// + (z[21] << 168)
// + (z[22] << 176)
// + (z[23] << 184)
// + (z[24] << 192)
// + (z[25] << 200)
// + (z[26] << 208)
// + (z[27] << 216)
// + (z[28] << 224)
// + (z[29] << 232)
// + (z[30] << 240)
// + (z[31] << 248)
// twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in // twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in
// if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256 // if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256

View File

@@ -6,6 +6,7 @@ const io = std.io;
const os = std.os; const os = std.os;
const fs = std.fs; const fs = std.fs;
const process = std.process; const process = std.process;
const testing = std.testing;
const elf = std.elf; const elf = std.elf;
const DW = std.dwarf; const DW = std.dwarf;
const macho = std.macho; const macho = std.macho;
@@ -559,7 +560,7 @@ pub const TTY = struct {
fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const MachoSymbol { fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const MachoSymbol {
var min: usize = 0; var min: usize = 0;
var max: usize = symbols.len; var max: usize = symbols.len - 1;
while (min < max) { while (min < max) {
const mid = min + (max - min) / 2; const mid = min + (max - min) / 2;
const curr = &symbols[mid]; const curr = &symbols[mid];
@@ -572,9 +573,36 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach
return curr; return curr;
} }
} }
const max_sym = &symbols[symbols.len - 1];
if (address >= max_sym.address())
return max_sym;
return null; return null;
} }
test "machoSearchSymbols" {
const symbols = [_]MachoSymbol{
.{ .addr = 100, .strx = undefined, .size = undefined, .ofile = undefined },
.{ .addr = 200, .strx = undefined, .size = undefined, .ofile = undefined },
.{ .addr = 300, .strx = undefined, .size = undefined, .ofile = undefined },
};
try testing.expectEqual(@as(?*const MachoSymbol, null), machoSearchSymbols(&symbols, 0));
try testing.expectEqual(@as(?*const MachoSymbol, null), machoSearchSymbols(&symbols, 99));
try testing.expectEqual(&symbols[0], machoSearchSymbols(&symbols, 100).?);
try testing.expectEqual(&symbols[0], machoSearchSymbols(&symbols, 150).?);
try testing.expectEqual(&symbols[0], machoSearchSymbols(&symbols, 199).?);
try testing.expectEqual(&symbols[1], machoSearchSymbols(&symbols, 200).?);
try testing.expectEqual(&symbols[1], machoSearchSymbols(&symbols, 250).?);
try testing.expectEqual(&symbols[1], machoSearchSymbols(&symbols, 299).?);
try testing.expectEqual(&symbols[2], machoSearchSymbols(&symbols, 300).?);
try testing.expectEqual(&symbols[2], machoSearchSymbols(&symbols, 301).?);
try testing.expectEqual(&symbols[2], machoSearchSymbols(&symbols, 5000).?);
}
/// TODO resources https://github.com/ziglang/zig/issues/4353 /// TODO resources https://github.com/ziglang/zig/issues/4353
pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: anytype, address: usize, tty_config: TTY.Config) !void { pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: anytype, address: usize, tty_config: TTY.Config) !void {
const module = debug_info.getModuleForAddress(address) catch |err| switch (err) { const module = debug_info.getModuleForAddress(address) catch |err| switch (err) {
@@ -1573,8 +1601,13 @@ fn getDebugInfoAllocator() mem.Allocator {
/// Whether or not the current target can print useful debug information when a segfault occurs. /// Whether or not the current target can print useful debug information when a segfault occurs.
pub const have_segfault_handling_support = switch (native_os) { pub const have_segfault_handling_support = switch (native_os) {
.linux, .netbsd, .solaris => true, .linux,
.windows => true, .macos,
.netbsd,
.solaris,
.windows,
=> true,
.freebsd, .openbsd => @hasDecl(os.system, "ucontext_t"), .freebsd, .openbsd => @hasDecl(os.system, "ucontext_t"),
else => false, else => false,
}; };
@@ -1601,7 +1634,7 @@ pub fn attachSegfaultHandler() void {
return; return;
} }
var act = os.Sigaction{ var act = os.Sigaction{
.handler = .{ .sigaction = handleSegfaultLinux }, .handler = .{ .sigaction = handleSegfaultPosix },
.mask = os.empty_sigset, .mask = os.empty_sigset,
.flags = (os.SA.SIGINFO | os.SA.RESTART | os.SA.RESETHAND), .flags = (os.SA.SIGINFO | os.SA.RESTART | os.SA.RESETHAND),
}; };
@@ -1629,7 +1662,7 @@ fn resetSegfaultHandler() void {
os.sigaction(os.SIG.BUS, &act, null); os.sigaction(os.SIG.BUS, &act, null);
} }
fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn { fn handleSegfaultPosix(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn {
// Reset to the default handler so that if a segfault happens in this handler it will crash // Reset to the default handler so that if a segfault happens in this handler it will crash
// the process. Also when this handler returns, the original instruction will be repeated // the process. Also when this handler returns, the original instruction will be repeated
// and the resulting segfault will crash the process rather than continually dump stack traces. // and the resulting segfault will crash the process rather than continually dump stack traces.
@@ -1637,7 +1670,7 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const any
const addr = switch (native_os) { const addr = switch (native_os) {
.linux => @ptrToInt(info.fields.sigfault.addr), .linux => @ptrToInt(info.fields.sigfault.addr),
.freebsd => @ptrToInt(info.addr), .freebsd, .macos => @ptrToInt(info.addr),
.netbsd => @ptrToInt(info.info.reason.fault.addr), .netbsd => @ptrToInt(info.info.reason.fault.addr),
.openbsd => @ptrToInt(info.data.fault.addr), .openbsd => @ptrToInt(info.data.fault.addr),
.solaris => @ptrToInt(info.reason.fault.addr), .solaris => @ptrToInt(info.reason.fault.addr),
@@ -1668,12 +1701,14 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const any
.linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RIP]), .linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RIP]),
.freebsd => @intCast(usize, ctx.mcontext.rip), .freebsd => @intCast(usize, ctx.mcontext.rip),
.openbsd => @intCast(usize, ctx.sc_rip), .openbsd => @intCast(usize, ctx.sc_rip),
.macos => @intCast(usize, ctx.mcontext.ss.rip),
else => unreachable, else => unreachable,
}; };
const bp = switch (native_os) { const bp = switch (native_os) {
.linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RBP]), .linux, .netbsd, .solaris => @intCast(usize, ctx.mcontext.gregs[os.REG.RBP]),
.openbsd => @intCast(usize, ctx.sc_rbp), .openbsd => @intCast(usize, ctx.sc_rbp),
.freebsd => @intCast(usize, ctx.mcontext.rbp), .freebsd => @intCast(usize, ctx.mcontext.rbp),
.macos => @intCast(usize, ctx.mcontext.ss.rbp),
else => unreachable, else => unreachable,
}; };
dumpStackTraceFromBase(bp, ip); dumpStackTraceFromBase(bp, ip);
@@ -1686,9 +1721,15 @@ fn handleSegfaultLinux(sig: i32, info: *const os.siginfo_t, ctx_ptr: ?*const any
}, },
.aarch64 => { .aarch64 => {
const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr)); const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr));
const ip = @intCast(usize, ctx.mcontext.pc); const ip = switch (native_os) {
.macos => @intCast(usize, ctx.mcontext.ss.pc),
else => @intCast(usize, ctx.mcontext.pc),
};
// x29 is the ABI-designated frame pointer // x29 is the ABI-designated frame pointer
const bp = @intCast(usize, ctx.mcontext.regs[29]); const bp = switch (native_os) {
.macos => @intCast(usize, ctx.mcontext.ss.fp),
else => @intCast(usize, ctx.mcontext.regs[29]),
};
dumpStackTraceFromBase(bp, ip); dumpStackTraceFromBase(bp, ip);
}, },
else => {}, else => {},

View File

@@ -943,7 +943,7 @@ pub const Half = switch (@sizeOf(usize)) {
/// Machine architectures /// Machine architectures
/// See current registered ELF machine architectures at: /// See current registered ELF machine architectures at:
/// http://www.uxsglobal.com/developers/gabi/latest/ch4.eheader.html /// http://www.sco.com/developers/gabi/latest/ch4.eheader.html
/// The underscore prefix is because many of these start with numbers. /// The underscore prefix is because many of these start with numbers.
pub const EM = enum(u16) { pub const EM = enum(u16) {
/// No machine /// No machine

View File

@@ -75,111 +75,20 @@ pub fn format(
comptime fmt: []const u8, comptime fmt: []const u8,
args: anytype, args: anytype,
) !void { ) !void {
const ArgSetType = u32;
const ArgsType = @TypeOf(args); const ArgsType = @TypeOf(args);
const args_type_info = @typeInfo(ArgsType);
// XXX: meta.trait.is(.Struct)(ArgsType) doesn't seem to work... // XXX: meta.trait.is(.Struct)(ArgsType) doesn't seem to work...
if (@typeInfo(ArgsType) != .Struct) { if (args_type_info != .Struct) {
@compileError("Expected tuple or struct argument, found " ++ @typeName(ArgsType)); @compileError("Expected tuple or struct argument, found " ++ @typeName(ArgsType));
} }
const fields_info = meta.fields(ArgsType); const fields_info = args_type_info.Struct.fields;
if (fields_info.len > @typeInfo(ArgSetType).Int.bits) { if (fields_info.len > max_format_args) {
@compileError("32 arguments max are supported per format call"); @compileError("32 arguments max are supported per format call");
} }
comptime var arg_state: struct {
next_arg: usize = 0,
used_args: usize = 0,
args_len: usize = fields_info.len,
fn hasUnusedArgs(comptime self: *@This()) bool {
return @popCount(ArgSetType, self.used_args) != self.args_len;
}
fn nextArg(comptime self: *@This(), comptime arg_index: ?usize) comptime_int {
const next_index = arg_index orelse init: {
const arg = self.next_arg;
self.next_arg += 1;
break :init arg;
};
if (next_index >= self.args_len) {
@compileError("Too few arguments");
}
// Mark this argument as used
self.used_args |= 1 << next_index;
return next_index;
}
} = .{};
comptime var parser: struct {
buf: []const u8 = undefined,
pos: comptime_int = 0,
// Returns a decimal number or null if the current character is not a
// digit
fn number(comptime self: *@This()) ?usize {
var r: ?usize = null;
while (self.pos < self.buf.len) : (self.pos += 1) {
switch (self.buf[self.pos]) {
'0'...'9' => {
if (r == null) r = 0;
r.? *= 10;
r.? += self.buf[self.pos] - '0';
},
else => break,
}
}
return r;
}
// Returns a substring of the input starting from the current position
// and ending where `ch` is found or until the end if not found
fn until(comptime self: *@This(), comptime ch: u8) []const u8 {
const start = self.pos;
if (start >= self.buf.len)
return &[_]u8{};
while (self.pos < self.buf.len) : (self.pos += 1) {
if (self.buf[self.pos] == ch) break;
}
return self.buf[start..self.pos];
}
// Returns one character, if available
fn char(comptime self: *@This()) ?u8 {
if (self.pos < self.buf.len) {
const ch = self.buf[self.pos];
self.pos += 1;
return ch;
}
return null;
}
fn maybe(comptime self: *@This(), comptime val: u8) bool {
if (self.pos < self.buf.len and self.buf[self.pos] == val) {
self.pos += 1;
return true;
}
return false;
}
// Returns the n-th next character or null if that's past the end
fn peek(comptime self: *@This(), comptime n: usize) ?u8 {
return if (self.pos + n < self.buf.len) self.buf[self.pos + n] else null;
}
} = .{};
var options: FormatOptions = .{};
@setEvalBranchQuota(2000000); @setEvalBranchQuota(2000000);
comptime var arg_state: ArgState = .{ .args_len = fields_info.len };
comptime var i = 0; comptime var i = 0;
inline while (i < fmt.len) { inline while (i < fmt.len) {
const start_index = i; const start_index = i;
@@ -234,120 +143,48 @@ pub fn format(
comptime assert(fmt[i] == '}'); comptime assert(fmt[i] == '}');
i += 1; i += 1;
options = .{}; const placeholder = comptime parsePlaceholder(fmt[fmt_begin..fmt_end].*);
const arg_pos = comptime switch (placeholder.arg) {
// Parse the format fragment between braces .none => null,
parser.buf = fmt[fmt_begin..fmt_end]; .number => |pos| pos,
parser.pos = 0; .named => |arg_name| meta.fieldIndex(ArgsType, arg_name) orelse
@compileError("No argument with name '" ++ arg_name ++ "'"),
// Parse the positional argument number
const opt_pos_arg = comptime init: {
if (parser.maybe('[')) {
const arg_name = parser.until(']');
if (!parser.maybe(']')) {
@compileError("Expected closing ]");
}
break :init meta.fieldIndex(ArgsType, arg_name) orelse
@compileError("No argument with name '" ++ arg_name ++ "'");
} else {
break :init parser.number();
}
}; };
// Parse the format specifier const width = switch (placeholder.width) {
const specifier_arg = comptime parser.until(':'); .none => null,
.number => |v| v,
// Skip the colon, if present .named => |arg_name| blk: {
if (comptime parser.char()) |ch| { const arg_i = comptime meta.fieldIndex(ArgsType, arg_name) orelse
if (ch != ':') {
@compileError("Expected : or }, found '" ++ [1]u8{ch} ++ "'");
}
}
// Parse the fill character
// The fill parameter requires the alignment parameter to be specified
// too
if (comptime parser.peek(1)) |ch| {
if (comptime mem.indexOfScalar(u8, "<^>", ch) != null) {
options.fill = comptime parser.char().?;
}
}
// Parse the alignment parameter
if (comptime parser.peek(0)) |ch| {
switch (ch) {
'<' => {
options.alignment = .Left;
_ = comptime parser.char();
},
'^' => {
options.alignment = .Center;
_ = comptime parser.char();
},
'>' => {
options.alignment = .Right;
_ = comptime parser.char();
},
else => {},
}
}
// Parse the width parameter
options.width = comptime init: {
if (parser.maybe('[')) {
const arg_name = parser.until(']');
if (!parser.maybe(']')) {
@compileError("Expected closing ]");
}
const index = meta.fieldIndex(ArgsType, arg_name) orelse
@compileError("No argument with name '" ++ arg_name ++ "'"); @compileError("No argument with name '" ++ arg_name ++ "'");
const arg_index = arg_state.nextArg(index); _ = comptime arg_state.nextArg(arg_i) orelse @compileError("Too few arguments");
break :blk @field(args, arg_name);
break :init @field(args, fields_info[arg_index].name); },
} else {
break :init parser.number();
}
}; };
// Skip the dot, if present const precision = switch (placeholder.precision) {
if (comptime parser.char()) |ch| { .none => null,
if (ch != '.') { .number => |v| v,
@compileError("Expected . or }, found '" ++ [1]u8{ch} ++ "'"); .named => |arg_name| blk: {
} const arg_i = comptime meta.fieldIndex(ArgsType, arg_name) orelse
}
// Parse the precision parameter
options.precision = comptime init: {
if (parser.maybe('[')) {
const arg_name = parser.until(']');
if (!parser.maybe(']')) {
@compileError("Expected closing ]");
}
const arg_i = meta.fieldIndex(ArgsType, arg_name) orelse
@compileError("No argument with name '" ++ arg_name ++ "'"); @compileError("No argument with name '" ++ arg_name ++ "'");
const arg_to_use = arg_state.nextArg(arg_i); _ = comptime arg_state.nextArg(arg_i) orelse @compileError("Too few arguments");
break :blk @field(args, arg_name);
break :init @field(args, fields_info[arg_to_use].name); },
} else {
break :init parser.number();
}
}; };
if (comptime parser.char()) |ch| { const arg_to_print = comptime arg_state.nextArg(arg_pos) orelse
@compileError("Extraneous trailing character '" ++ [1]u8{ch} ++ "'"); @compileError("Too few arguments");
}
const arg_to_print = comptime arg_state.nextArg(opt_pos_arg);
try formatType( try formatType(
@field(args, fields_info[arg_to_print].name), @field(args, fields_info[arg_to_print].name),
specifier_arg, placeholder.specifier_arg,
options, FormatOptions{
.fill = placeholder.fill,
.alignment = placeholder.alignment,
.width = width,
.precision = precision,
},
writer, writer,
default_max_depth, default_max_depth,
); );
@@ -363,6 +200,202 @@ pub fn format(
} }
} }
fn parsePlaceholder(comptime str: anytype) Placeholder {
comptime var parser = Parser{ .buf = &str };
// Parse the positional argument number
const arg = comptime parser.specifier() catch |err|
@compileError(@errorName(err));
// Parse the format specifier
const specifier_arg = comptime parser.until(':');
// Skip the colon, if present
if (comptime parser.char()) |ch| {
if (ch != ':') {
@compileError("Expected : or }, found '" ++ [1]u8{ch} ++ "'");
}
}
// Parse the fill character
// The fill parameter requires the alignment parameter to be specified
// too
const fill = comptime if (parser.peek(1)) |ch|
switch (ch) {
'<', '^', '>' => parser.char().?,
else => ' ',
}
else
' ';
// Parse the alignment parameter
const alignment: Alignment = comptime if (parser.peek(0)) |ch| init: {
switch (ch) {
'<', '^', '>' => _ = parser.char(),
else => {},
}
break :init switch (ch) {
'<' => .Left,
'^' => .Center,
else => .Right,
};
} else .Right;
// Parse the width parameter
const width = comptime parser.specifier() catch |err|
@compileError(@errorName(err));
// Skip the dot, if present
if (comptime parser.char()) |ch| {
if (ch != '.') {
@compileError("Expected . or }, found '" ++ [1]u8{ch} ++ "'");
}
}
// Parse the precision parameter
const precision = comptime parser.specifier() catch |err|
@compileError(@errorName(err));
if (comptime parser.char()) |ch| {
@compileError("Extraneous trailing character '" ++ [1]u8{ch} ++ "'");
}
return Placeholder{
.specifier_arg = cacheString(specifier_arg[0..specifier_arg.len].*),
.fill = fill,
.alignment = alignment,
.arg = arg,
.width = width,
.precision = precision,
};
}
fn cacheString(str: anytype) []const u8 {
return &str;
}
const Placeholder = struct {
specifier_arg: []const u8,
fill: u8,
alignment: Alignment,
arg: Specifier,
width: Specifier,
precision: Specifier,
};
const Specifier = union(enum) {
none,
number: usize,
named: []const u8,
};
const Parser = struct {
buf: []const u8,
pos: usize = 0,
// Returns a decimal number or null if the current character is not a
// digit
fn number(self: *@This()) ?usize {
var r: ?usize = null;
while (self.pos < self.buf.len) : (self.pos += 1) {
switch (self.buf[self.pos]) {
'0'...'9' => {
if (r == null) r = 0;
r.? *= 10;
r.? += self.buf[self.pos] - '0';
},
else => break,
}
}
return r;
}
// Returns a substring of the input starting from the current position
// and ending where `ch` is found or until the end if not found
fn until(self: *@This(), ch: u8) []const u8 {
const start = self.pos;
if (start >= self.buf.len)
return &[_]u8{};
while (self.pos < self.buf.len) : (self.pos += 1) {
if (self.buf[self.pos] == ch) break;
}
return self.buf[start..self.pos];
}
// Returns one character, if available
fn char(self: *@This()) ?u8 {
if (self.pos < self.buf.len) {
const ch = self.buf[self.pos];
self.pos += 1;
return ch;
}
return null;
}
fn maybe(self: *@This(), val: u8) bool {
if (self.pos < self.buf.len and self.buf[self.pos] == val) {
self.pos += 1;
return true;
}
return false;
}
// Returns a decimal number or null if the current character is not a
// digit
fn specifier(self: *@This()) !Specifier {
if (self.maybe('[')) {
const arg_name = self.until(']');
if (!self.maybe(']'))
return @field(anyerror, "Expected closing ]");
return Specifier{ .named = arg_name };
}
if (self.number()) |i|
return Specifier{ .number = i };
return Specifier{ .none = {} };
}
// Returns the n-th next character or null if that's past the end
fn peek(self: *@This(), n: usize) ?u8 {
return if (self.pos + n < self.buf.len) self.buf[self.pos + n] else null;
}
};
const ArgSetType = u32;
const max_format_args = @typeInfo(ArgSetType).Int.bits;
const ArgState = struct {
next_arg: usize = 0,
used_args: ArgSetType = 0,
args_len: usize,
fn hasUnusedArgs(self: *@This()) bool {
return @popCount(ArgSetType, self.used_args) != self.args_len;
}
fn nextArg(self: *@This(), arg_index: ?usize) ?usize {
const next_index = arg_index orelse init: {
const arg = self.next_arg;
self.next_arg += 1;
break :init arg;
};
if (next_index >= self.args_len) {
return null;
}
// Mark this argument as used
self.used_args |= @as(ArgSetType, 1) << @intCast(u5, next_index);
return next_index;
}
};
pub fn formatAddress(value: anytype, options: FormatOptions, writer: anytype) @TypeOf(writer).Error!void { pub fn formatAddress(value: anytype, options: FormatOptions, writer: anytype) @TypeOf(writer).Error!void {
_ = options; _ = options;
const T = @TypeOf(value); const T = @TypeOf(value);
@@ -535,14 +568,19 @@ pub fn formatType(
if (actual_fmt.len == 0) if (actual_fmt.len == 0)
@compileError("cannot format array ref without a specifier (i.e. {s} or {*})"); @compileError("cannot format array ref without a specifier (i.e. {s} or {*})");
if (info.child == u8) { if (info.child == u8) {
if (comptime mem.indexOfScalar(u8, "sxXeE", actual_fmt[0]) != null) { switch (actual_fmt[0]) {
return formatText(value, actual_fmt, options, writer); 's', 'x', 'X', 'e', 'E' => {
comptime checkTextFmt(actual_fmt);
return formatBuf(value, options, writer);
},
else => {},
} }
} }
if (comptime std.meta.trait.isZigString(info.child)) { if (comptime std.meta.trait.isZigString(info.child)) {
for (value) |item, i| { for (value) |item, i| {
if (i != 0) try formatText(", ", actual_fmt, options, writer); comptime checkTextFmt(actual_fmt);
try formatText(item, actual_fmt, options, writer); if (i != 0) try formatBuf(", ", options, writer);
try formatBuf(item, options, writer);
} }
return; return;
} }
@@ -560,8 +598,12 @@ pub fn formatType(
return formatType(mem.span(value), actual_fmt, options, writer, max_depth); return formatType(mem.span(value), actual_fmt, options, writer, max_depth);
} }
if (ptr_info.child == u8) { if (ptr_info.child == u8) {
if (comptime mem.indexOfScalar(u8, "sxXeE", actual_fmt[0]) != null) { switch (actual_fmt[0]) {
return formatText(mem.span(value), actual_fmt, options, writer); 's', 'x', 'X', 'e', 'E' => {
comptime checkTextFmt(actual_fmt);
return formatBuf(mem.span(value), options, writer);
},
else => {},
} }
} }
@compileError("Unknown format string: '" ++ actual_fmt ++ "' for type '" ++ @typeName(T) ++ "'"); @compileError("Unknown format string: '" ++ actual_fmt ++ "' for type '" ++ @typeName(T) ++ "'");
@@ -573,8 +615,12 @@ pub fn formatType(
return writer.writeAll("{ ... }"); return writer.writeAll("{ ... }");
} }
if (ptr_info.child == u8) { if (ptr_info.child == u8) {
if (comptime mem.indexOfScalar(u8, "sxXeE", actual_fmt[0]) != null) { switch (actual_fmt[0]) {
return formatText(value, actual_fmt, options, writer); 's', 'x', 'X', 'e', 'E' => {
comptime checkTextFmt(actual_fmt);
return formatBuf(value, options, writer);
},
else => {},
} }
} }
try writer.writeAll("{ "); try writer.writeAll("{ ");
@@ -594,8 +640,12 @@ pub fn formatType(
return writer.writeAll("{ ... }"); return writer.writeAll("{ ... }");
} }
if (info.child == u8) { if (info.child == u8) {
if (comptime mem.indexOfScalar(u8, "sxXeE", actual_fmt[0]) != null) { switch (actual_fmt[0]) {
return formatText(&value, actual_fmt, options, writer); 's', 'x', 'X', 'e', 'E' => {
comptime checkTextFmt(actual_fmt);
return formatBuf(&value, options, writer);
},
else => {},
} }
} }
try writer.writeAll("{ "); try writer.writeAll("{ ");
@@ -673,7 +723,7 @@ pub fn formatIntValue(
if (@typeInfo(@TypeOf(int_value)).Int.bits <= 8) { if (@typeInfo(@TypeOf(int_value)).Int.bits <= 8) {
return formatAsciiChar(@as(u8, int_value), options, writer); return formatAsciiChar(@as(u8, int_value), options, writer);
} else { } else {
@compileError("Cannot print integer that is larger than 8 bits as a ascii"); @compileError("Cannot print integer that is larger than 8 bits as an ASCII character");
} }
} else if (comptime std.mem.eql(u8, fmt, "u")) { } else if (comptime std.mem.eql(u8, fmt, "u")) {
if (@typeInfo(@TypeOf(int_value)).Int.bits <= 21) { if (@typeInfo(@TypeOf(int_value)).Int.bits <= 21) {
@@ -881,29 +931,28 @@ pub fn fmtIntSizeBin(value: u64) std.fmt.Formatter(formatSizeBin) {
return .{ .data = value }; return .{ .data = value };
} }
fn checkTextFmt(comptime fmt: []const u8) void {
if (fmt.len != 1)
@compileError("Unsupported format string '" ++ fmt ++ "' when formatting text");
switch (fmt[0]) {
'x' => @compileError("specifier 'x' has been deprecated, wrap your argument in std.fmt.fmtSliceHexLower instead"),
'X' => @compileError("specifier 'X' has been deprecated, wrap your argument in std.fmt.fmtSliceHexUpper instead"),
'e' => @compileError("specifier 'e' has been deprecated, wrap your argument in std.fmt.fmtSliceEscapeLower instead"),
'E' => @compileError("specifier 'E' has been deprecated, wrap your argument in std.fmt.fmtSliceEscapeUpper instead"),
'z' => @compileError("specifier 'z' has been deprecated, wrap your argument in std.zig.fmtId instead"),
'Z' => @compileError("specifier 'Z' has been deprecated, wrap your argument in std.zig.fmtEscapes instead"),
else => {},
}
}
pub fn formatText( pub fn formatText(
bytes: []const u8, bytes: []const u8,
comptime fmt: []const u8, comptime fmt: []const u8,
options: FormatOptions, options: FormatOptions,
writer: anytype, writer: anytype,
) !void { ) !void {
if (comptime std.mem.eql(u8, fmt, "s")) { comptime checkTextFmt(fmt);
return formatBuf(bytes, options, writer); return formatBuf(bytes, options, writer);
} else if (comptime (std.mem.eql(u8, fmt, "x"))) {
@compileError("specifier 'x' has been deprecated, wrap your argument in std.fmt.fmtSliceHexLower instead");
} else if (comptime (std.mem.eql(u8, fmt, "X"))) {
@compileError("specifier 'X' has been deprecated, wrap your argument in std.fmt.fmtSliceHexUpper instead");
} else if (comptime (std.mem.eql(u8, fmt, "e"))) {
@compileError("specifier 'e' has been deprecated, wrap your argument in std.fmt.fmtSliceEscapeLower instead");
} else if (comptime (std.mem.eql(u8, fmt, "E"))) {
@compileError("specifier 'X' has been deprecated, wrap your argument in std.fmt.fmtSliceEscapeUpper instead");
} else if (comptime std.mem.eql(u8, fmt, "z")) {
@compileError("specifier 'z' has been deprecated, wrap your argument in std.zig.fmtId instead");
} else if (comptime std.mem.eql(u8, fmt, "Z")) {
@compileError("specifier 'Z' has been deprecated, wrap your argument in std.zig.fmtEscapes instead");
} else {
@compileError("Unsupported format string '" ++ fmt ++ "' when formatting text");
}
} }
pub fn formatAsciiChar( pub fn formatAsciiChar(
@@ -2210,6 +2259,7 @@ test "float.decimal" {
try expectFmt("f64: 0.00030000", "f64: {d:.8}", .{@as(f64, 0.0003)}); try expectFmt("f64: 0.00030000", "f64: {d:.8}", .{@as(f64, 0.0003)});
try expectFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 1.40130e-45)}); try expectFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 1.40130e-45)});
try expectFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)}); try expectFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)});
try expectFmt("f64: 10000000000000.00", "f64: {d:.2}", .{@as(f64, 9999999999999.999)});
} }
test "float.libc.sanity" { test "float.libc.sanity" {

View File

@@ -92,7 +92,10 @@ pub fn errol3(value: f64, buffer: []u8) FloatDecimal {
}; };
} }
return errol3u(value, buffer); // We generate digits starting at index 1. If rounding a buffer later then it may be
// required to generate a preceding digit in some cases (9.999) in which case we use
// the 0-index for this extra digit.
return errol3u(value, buffer[1..]);
} }
/// Uncorrected Errol3 double to ASCII conversion. /// Uncorrected Errol3 double to ASCII conversion.
@@ -162,11 +165,7 @@ fn errol3u(val: f64, buffer: []u8) FloatDecimal {
} }
// digit generation // digit generation
var buf_index: usize = 0;
// We generate digits starting at index 1. If rounding a buffer later then it may be
// required to generate a preceding digit in some cases (9.999) in which case we use
// the 0-index for this extra digit.
var buf_index: usize = 1;
while (true) { while (true) {
var hdig = @floatToInt(u8, math.floor(high.val)); var hdig = @floatToInt(u8, math.floor(high.val));
if ((high.val == @intToFloat(f64, hdig)) and (high.off < 0)) hdig -= 1; if ((high.val == @intToFloat(f64, hdig)) and (high.off < 0)) hdig -= 1;
@@ -192,7 +191,7 @@ fn errol3u(val: f64, buffer: []u8) FloatDecimal {
buf_index += 1; buf_index += 1;
return FloatDecimal{ return FloatDecimal{
.digits = buffer[1..buf_index], .digits = buffer[0..buf_index],
.exp = exp, .exp = exp,
}; };
} }

View File

@@ -202,18 +202,19 @@ pub fn parseHexFloat(comptime T: type, s: []const u8) !T {
exponent += 1; exponent += 1;
} }
// There are two cases to handle: // Whenever the guard bit is one (G=1) and:
// - We've truncated more than 0.5ULP (R=S=1), increase the mantissa. // - we've truncated more than 0.5ULP (R=S=1)
// - We've truncated exactly 0.5ULP (R=1 S=0), increase the mantissa if the // - we've truncated exactly 0.5ULP (R=1 S=0)
// result is odd (G=1). // Were are going to increase the mantissa (round up)
// The two checks can be neatly folded as follows. const guard_bit_and_half_or_more = (mantissa & 0b110) == 0b110;
mantissa |= @boolToInt(mantissa & 0b100 != 0);
mantissa += 1;
mantissa >>= 2; mantissa >>= 2;
exponent += 2; exponent += 2;
if (mantissa & (1 << (mantissa_bits + 1)) != 0) { if (guard_bit_and_half_or_more) {
mantissa += 1;
}
if (mantissa == (1 << (mantissa_bits + 1))) {
// Renormalize, if the exponent overflows we'll catch that below. // Renormalize, if the exponent overflows we'll catch that below.
mantissa >>= 1; mantissa >>= 1;
exponent += 1; exponent += 1;
@@ -338,6 +339,7 @@ test "f128" {
// // Min denormalized value. // // Min denormalized value.
.{ .s = "0x1p-16494", .v = math.f128_true_min }, .{ .s = "0x1p-16494", .v = math.f128_true_min },
.{ .s = "-0x1p-16494", .v = -math.f128_true_min }, .{ .s = "-0x1p-16494", .v = -math.f128_true_min },
.{ .s = "0x1.edcb34a235253948765432134674fp-1", .v = 0x1.edcb34a235253948765432134674fp-1 },
}; };
for (cases) |case| { for (cases) |case| {

View File

@@ -300,6 +300,7 @@ pub const Dir = struct {
buf: [8192]u8, // TODO align(@alignOf(os.system.dirent)), buf: [8192]u8, // TODO align(@alignOf(os.system.dirent)),
index: usize, index: usize,
end_index: usize, end_index: usize,
first_iter: bool,
const Self = @This(); const Self = @This();
@@ -319,6 +320,10 @@ pub const Dir = struct {
fn nextDarwin(self: *Self) !?Entry { fn nextDarwin(self: *Self) !?Entry {
start_over: while (true) { start_over: while (true) {
if (self.index >= self.end_index) { if (self.index >= self.end_index) {
if (self.first_iter) {
std.os.lseek_SET(self.dir.fd, 0) catch unreachable; // EBADF here likely means that the Dir was not opened with iteration permissions
self.first_iter = false;
}
const rc = os.system.__getdirentries64( const rc = os.system.__getdirentries64(
self.dir.fd, self.dir.fd,
&self.buf, &self.buf,
@@ -369,6 +374,10 @@ pub const Dir = struct {
fn nextSolaris(self: *Self) !?Entry { fn nextSolaris(self: *Self) !?Entry {
start_over: while (true) { start_over: while (true) {
if (self.index >= self.end_index) { if (self.index >= self.end_index) {
if (self.first_iter) {
std.os.lseek_SET(self.dir.fd, 0) catch unreachable; // EBADF here likely means that the Dir was not opened with iteration permissions
self.first_iter = false;
}
const rc = os.system.getdents(self.dir.fd, &self.buf, self.buf.len); const rc = os.system.getdents(self.dir.fd, &self.buf, self.buf.len);
switch (os.errno(rc)) { switch (os.errno(rc)) {
.SUCCESS => {}, .SUCCESS => {},
@@ -423,6 +432,10 @@ pub const Dir = struct {
fn nextBsd(self: *Self) !?Entry { fn nextBsd(self: *Self) !?Entry {
start_over: while (true) { start_over: while (true) {
if (self.index >= self.end_index) { if (self.index >= self.end_index) {
if (self.first_iter) {
std.os.lseek_SET(self.dir.fd, 0) catch unreachable; // EBADF here likely means that the Dir was not opened with iteration permissions
self.first_iter = false;
}
const rc = if (builtin.os.tag == .netbsd) const rc = if (builtin.os.tag == .netbsd)
os.system.__getdents30(self.dir.fd, &self.buf, self.buf.len) os.system.__getdents30(self.dir.fd, &self.buf, self.buf.len)
else else
@@ -479,6 +492,7 @@ pub const Dir = struct {
buf: [8192]u8, // TODO align(@alignOf(os.dirent64)), buf: [8192]u8, // TODO align(@alignOf(os.dirent64)),
index: usize, index: usize,
end_index: usize, end_index: usize,
first_iter: bool,
const Self = @This(); const Self = @This();
@@ -491,6 +505,10 @@ pub const Dir = struct {
// TODO: find a better max // TODO: find a better max
const HAIKU_MAX_COUNT = 10000; const HAIKU_MAX_COUNT = 10000;
if (self.index >= self.end_index) { if (self.index >= self.end_index) {
if (self.first_iter) {
std.os.lseek_SET(self.dir.fd, 0) catch unreachable; // EBADF here likely means that the Dir was not opened with iteration permissions
self.first_iter = false;
}
const rc = os.system._kern_read_dir( const rc = os.system._kern_read_dir(
self.dir.fd, self.dir.fd,
&self.buf, &self.buf,
@@ -563,6 +581,7 @@ pub const Dir = struct {
buf: [8192]u8 align(if (builtin.os.tag != .linux) 1 else @alignOf(linux.dirent64)), buf: [8192]u8 align(if (builtin.os.tag != .linux) 1 else @alignOf(linux.dirent64)),
index: usize, index: usize,
end_index: usize, end_index: usize,
first_iter: bool,
const Self = @This(); const Self = @This();
const linux = os.linux; const linux = os.linux;
@@ -574,6 +593,10 @@ pub const Dir = struct {
pub fn next(self: *Self) Error!?Entry { pub fn next(self: *Self) Error!?Entry {
start_over: while (true) { start_over: while (true) {
if (self.index >= self.end_index) { if (self.index >= self.end_index) {
if (self.first_iter) {
std.os.lseek_SET(self.dir.fd, 0) catch unreachable; // EBADF here likely means that the Dir was not opened with iteration permissions
self.first_iter = false;
}
const rc = linux.getdents64(self.dir.fd, &self.buf, self.buf.len); const rc = linux.getdents64(self.dir.fd, &self.buf, self.buf.len);
switch (linux.getErrno(rc)) { switch (linux.getErrno(rc)) {
.SUCCESS => {}, .SUCCESS => {},
@@ -620,7 +643,7 @@ pub const Dir = struct {
buf: [8192]u8 align(@alignOf(os.windows.FILE_BOTH_DIR_INFORMATION)), buf: [8192]u8 align(@alignOf(os.windows.FILE_BOTH_DIR_INFORMATION)),
index: usize, index: usize,
end_index: usize, end_index: usize,
first: bool, first_iter: bool,
name_data: [256]u8, name_data: [256]u8,
const Self = @This(); const Self = @This();
@@ -645,9 +668,9 @@ pub const Dir = struct {
.FileBothDirectoryInformation, .FileBothDirectoryInformation,
w.FALSE, w.FALSE,
null, null,
if (self.first) @as(w.BOOLEAN, w.TRUE) else @as(w.BOOLEAN, w.FALSE), if (self.first_iter) @as(w.BOOLEAN, w.TRUE) else @as(w.BOOLEAN, w.FALSE),
); );
self.first = false; self.first_iter = false;
if (io.Information == 0) return null; if (io.Information == 0) return null;
self.index = 0; self.index = 0;
self.end_index = io.Information; self.end_index = io.Information;
@@ -769,18 +792,20 @@ pub const Dir = struct {
.index = 0, .index = 0,
.end_index = 0, .end_index = 0,
.buf = undefined, .buf = undefined,
.first_iter = true,
}, },
.linux, .haiku => return Iterator{ .linux, .haiku => return Iterator{
.dir = self, .dir = self,
.index = 0, .index = 0,
.end_index = 0, .end_index = 0,
.buf = undefined, .buf = undefined,
.first_iter = true,
}, },
.windows => return Iterator{ .windows => return Iterator{
.dir = self, .dir = self,
.index = 0, .index = 0,
.end_index = 0, .end_index = 0,
.first = true, .first_iter = true,
.buf = undefined, .buf = undefined,
.name_data = undefined, .name_data = undefined,
}, },

View File

@@ -45,6 +45,10 @@ pub fn getAppDataDir(allocator: mem.Allocator, appname: []const u8) GetAppDataDi
return fs.path.join(allocator, &[_][]const u8{ home_dir, "Library", "Application Support", appname }); return fs.path.join(allocator, &[_][]const u8{ home_dir, "Library", "Application Support", appname });
}, },
.linux, .freebsd, .netbsd, .dragonfly, .openbsd, .solaris => { .linux, .freebsd, .netbsd, .dragonfly, .openbsd, .solaris => {
if (os.getenv("XDG_DATA_HOME")) |xdg| {
return fs.path.join(allocator, &[_][]const u8{ xdg, appname });
}
const home_dir = os.getenv("HOME") orelse { const home_dir = os.getenv("HOME") orelse {
// TODO look in /etc/passwd // TODO look in /etc/passwd
return error.AppDataDirUnavailable; return error.AppDataDirUnavailable;

View File

@@ -14,11 +14,17 @@ const native_os = builtin.target.os.tag;
pub const sep_windows = '\\'; pub const sep_windows = '\\';
pub const sep_posix = '/'; pub const sep_posix = '/';
pub const sep = if (native_os == .windows) sep_windows else sep_posix; pub const sep = switch (native_os) {
.windows, .uefi => sep_windows,
else => sep_posix,
};
pub const sep_str_windows = "\\"; pub const sep_str_windows = "\\";
pub const sep_str_posix = "/"; pub const sep_str_posix = "/";
pub const sep_str = if (native_os == .windows) sep_str_windows else sep_str_posix; pub const sep_str = switch (native_os) {
.windows, .uefi => sep_str_windows,
else => sep_str_posix,
};
pub const delimiter_windows = ';'; pub const delimiter_windows = ';';
pub const delimiter_posix = ':'; pub const delimiter_posix = ':';
@@ -26,11 +32,11 @@ pub const delimiter = if (native_os == .windows) delimiter_windows else delimite
/// Returns if the given byte is a valid path separator /// Returns if the given byte is a valid path separator
pub fn isSep(byte: u8) bool { pub fn isSep(byte: u8) bool {
if (native_os == .windows) { return switch (native_os) {
return byte == '/' or byte == '\\'; .windows => byte == '/' or byte == '\\',
} else { .uefi => byte == '\\',
return byte == '/'; else => byte == '/',
} };
} }
/// This is different from mem.join in that the separator will not be repeated if /// This is different from mem.join in that the separator will not be repeated if
@@ -110,6 +116,17 @@ pub fn joinZ(allocator: Allocator, paths: []const []const u8) ![:0]u8 {
return out[0 .. out.len - 1 :0]; return out[0 .. out.len - 1 :0];
} }
fn testJoinMaybeZUefi(paths: []const []const u8, expected: []const u8, zero: bool) !void {
const uefiIsSep = struct {
fn isSep(byte: u8) bool {
return byte == '\\';
}
}.isSep;
const actual = try joinSepMaybeZ(testing.allocator, sep_windows, uefiIsSep, paths, zero);
defer testing.allocator.free(actual);
try testing.expectEqualSlices(u8, expected, if (zero) actual[0 .. actual.len - 1 :0] else actual);
}
fn testJoinMaybeZWindows(paths: []const []const u8, expected: []const u8, zero: bool) !void { fn testJoinMaybeZWindows(paths: []const []const u8, expected: []const u8, zero: bool) !void {
const windowsIsSep = struct { const windowsIsSep = struct {
fn isSep(byte: u8) bool { fn isSep(byte: u8) bool {
@@ -158,6 +175,11 @@ test "join" {
zero, zero,
); );
try testJoinMaybeZUefi(&[_][]const u8{ "EFI", "Boot", "bootx64.efi" }, "EFI\\Boot\\bootx64.efi", zero);
try testJoinMaybeZUefi(&[_][]const u8{ "EFI\\Boot", "bootx64.efi" }, "EFI\\Boot\\bootx64.efi", zero);
try testJoinMaybeZUefi(&[_][]const u8{ "EFI\\", "\\Boot", "bootx64.efi" }, "EFI\\Boot\\bootx64.efi", zero);
try testJoinMaybeZUefi(&[_][]const u8{ "EFI\\", "\\Boot\\", "\\bootx64.efi" }, "EFI\\Boot\\bootx64.efi", zero);
try testJoinMaybeZWindows(&[_][]const u8{ "c:\\", "a", "b/", "c" }, "c:\\a\\b/c", zero); try testJoinMaybeZWindows(&[_][]const u8{ "c:\\", "a", "b/", "c" }, "c:\\a\\b/c", zero);
try testJoinMaybeZWindows(&[_][]const u8{ "c:\\a/", "b\\", "/c" }, "c:\\a/b\\c", zero); try testJoinMaybeZWindows(&[_][]const u8{ "c:\\a/", "b\\", "/c" }, "c:\\a/b\\c", zero);

View File

@@ -180,6 +180,39 @@ test "Dir.Iterator" {
try testing.expect(contains(&entries, Dir.Entry{ .name = "some_dir", .kind = Dir.Entry.Kind.Directory })); try testing.expect(contains(&entries, Dir.Entry{ .name = "some_dir", .kind = Dir.Entry.Kind.Directory }));
} }
test "Dir.Iterator twice" {
var tmp_dir = tmpDir(.{ .iterate = true });
defer tmp_dir.cleanup();
// First, create a couple of entries to iterate over.
const file = try tmp_dir.dir.createFile("some_file", .{});
file.close();
try tmp_dir.dir.makeDir("some_dir");
var arena = ArenaAllocator.init(testing.allocator);
defer arena.deinit();
const allocator = arena.allocator();
var i: u8 = 0;
while (i < 2) : (i += 1) {
var entries = std.ArrayList(Dir.Entry).init(allocator);
// Create iterator.
var iter = tmp_dir.dir.iterate();
while (try iter.next()) |entry| {
// We cannot just store `entry` as on Windows, we're re-using the name buffer
// which means we'll actually share the `name` pointer between entries!
const name = try allocator.dupe(u8, entry.name);
try entries.append(Dir.Entry{ .name = name, .kind = entry.kind });
}
try testing.expect(entries.items.len == 2); // note that the Iterator skips '.' and '..'
try testing.expect(contains(&entries, Dir.Entry{ .name = "some_file", .kind = Dir.Entry.Kind.File }));
try testing.expect(contains(&entries, Dir.Entry{ .name = "some_dir", .kind = Dir.Entry.Kind.Directory }));
}
}
fn entryEql(lhs: Dir.Entry, rhs: Dir.Entry) bool { fn entryEql(lhs: Dir.Entry, rhs: Dir.Entry) bool {
return mem.eql(u8, lhs.name, rhs.name) and lhs.kind == rhs.kind; return mem.eql(u8, lhs.name, rhs.name) and lhs.kind == rhs.kind;
} }

View File

@@ -750,12 +750,19 @@ pub fn HashMapUnmanaged(
fingerprint: FingerPrint = free, fingerprint: FingerPrint = free,
used: u1 = 0, used: u1 = 0,
const slot_free = @bitCast(u8, Metadata{ .fingerprint = free });
const slot_tombstone = @bitCast(u8, Metadata{ .fingerprint = tombstone });
pub fn isUsed(self: Metadata) bool { pub fn isUsed(self: Metadata) bool {
return self.used == 1; return self.used == 1;
} }
pub fn isTombstone(self: Metadata) bool { pub fn isTombstone(self: Metadata) bool {
return !self.isUsed() and self.fingerprint == tombstone; return @bitCast(u8, self) == slot_tombstone;
}
pub fn isFree(self: Metadata) bool {
return @bitCast(u8, self) == slot_free;
} }
pub fn takeFingerprint(hash: Hash) FingerPrint { pub fn takeFingerprint(hash: Hash) FingerPrint {
@@ -1115,7 +1122,7 @@ pub fn HashMapUnmanaged(
var idx = @truncate(usize, hash & mask); var idx = @truncate(usize, hash & mask);
var metadata = self.metadata.? + idx; var metadata = self.metadata.? + idx;
while ((metadata[0].isUsed() or metadata[0].isTombstone()) and limit != 0) { while (!metadata[0].isFree() and limit != 0) {
if (metadata[0].isUsed() and metadata[0].fingerprint == fingerprint) { if (metadata[0].isUsed() and metadata[0].fingerprint == fingerprint) {
const test_key = &self.keys()[idx]; const test_key = &self.keys()[idx];
// If you get a compile error on this line, it means that your generic eql // If you get a compile error on this line, it means that your generic eql
@@ -1294,7 +1301,7 @@ pub fn HashMapUnmanaged(
var first_tombstone_idx: usize = self.capacity(); // invalid index var first_tombstone_idx: usize = self.capacity(); // invalid index
var metadata = self.metadata.? + idx; var metadata = self.metadata.? + idx;
while ((metadata[0].isUsed() or metadata[0].isTombstone()) and limit != 0) { while (!metadata[0].isFree() and limit != 0) {
if (metadata[0].isUsed() and metadata[0].fingerprint == fingerprint) { if (metadata[0].isUsed() and metadata[0].fingerprint == fingerprint) {
const test_key = &self.keys()[idx]; const test_key = &self.keys()[idx];
// If you get a compile error on this line, it means that your generic eql // If you get a compile error on this line, it means that your generic eql

View File

@@ -107,16 +107,16 @@ pub fn Reader(
) !void { ) !void {
array_list.shrinkRetainingCapacity(0); array_list.shrinkRetainingCapacity(0);
while (true) { while (true) {
if (array_list.items.len == max_size) {
return error.StreamTooLong;
}
var byte: u8 = try self.readByte(); var byte: u8 = try self.readByte();
if (byte == delimiter) { if (byte == delimiter) {
return; return;
} }
if (array_list.items.len == max_size) {
return error.StreamTooLong;
}
try array_list.append(byte); try array_list.append(byte);
} }
} }
@@ -139,17 +139,20 @@ pub fn Reader(
/// Reads from the stream until specified byte is found. If the buffer is not /// Reads from the stream until specified byte is found. If the buffer is not
/// large enough to hold the entire contents, `error.StreamTooLong` is returned. /// large enough to hold the entire contents, `error.StreamTooLong` is returned.
/// If end-of-stream is found, `error.EndOfStream` is returned.
/// Returns a slice of the stream data, with ptr equal to `buf.ptr`. The /// Returns a slice of the stream data, with ptr equal to `buf.ptr`. The
/// delimiter byte is not included in the returned slice. /// delimiter byte is written to the output buffer but is not included
/// in the returned slice.
pub fn readUntilDelimiter(self: Self, buf: []u8, delimiter: u8) ![]u8 { pub fn readUntilDelimiter(self: Self, buf: []u8, delimiter: u8) ![]u8 {
var index: usize = 0; var index: usize = 0;
while (true) { while (true) {
const byte = try self.readByte();
if (byte == delimiter) return buf[0..index];
if (index >= buf.len) return error.StreamTooLong; if (index >= buf.len) return error.StreamTooLong;
const byte = try self.readByte();
buf[index] = byte; buf[index] = byte;
if (byte == delimiter) return buf[0..index];
index += 1; index += 1;
} }
} }
@@ -185,10 +188,13 @@ pub fn Reader(
/// If end-of-stream is found, returns the rest of the stream. If this /// If end-of-stream is found, returns the rest of the stream. If this
/// function is called again after that, returns null. /// function is called again after that, returns null.
/// Returns a slice of the stream data, with ptr equal to `buf.ptr`. The /// Returns a slice of the stream data, with ptr equal to `buf.ptr`. The
/// delimiter byte is not included in the returned slice. /// delimiter byte is written to the output buffer but is not included
/// in the returned slice.
pub fn readUntilDelimiterOrEof(self: Self, buf: []u8, delimiter: u8) !?[]u8 { pub fn readUntilDelimiterOrEof(self: Self, buf: []u8, delimiter: u8) !?[]u8 {
var index: usize = 0; var index: usize = 0;
while (true) { while (true) {
if (index >= buf.len) return error.StreamTooLong;
const byte = self.readByte() catch |err| switch (err) { const byte = self.readByte() catch |err| switch (err) {
error.EndOfStream => { error.EndOfStream => {
if (index == 0) { if (index == 0) {
@@ -199,11 +205,10 @@ pub fn Reader(
}, },
else => |e| return e, else => |e| return e,
}; };
buf[index] = byte;
if (byte == delimiter) return buf[0..index]; if (byte == delimiter) return buf[0..index];
if (index >= buf.len) return error.StreamTooLong;
buf[index] = byte;
index += 1; index += 1;
} }
} }
@@ -363,3 +368,272 @@ test "Reader.skipBytes" {
try reader.skipBytes(0, .{}); try reader.skipBytes(0, .{});
try testing.expectError(error.EndOfStream, reader.skipBytes(1, .{})); try testing.expectError(error.EndOfStream, reader.skipBytes(1, .{}));
} }
test "Reader.readUntilDelimiterArrayList returns ArrayLists with bytes read until the delimiter, then EndOfStream" {
const a = std.testing.allocator;
var list = std.ArrayList(u8).init(a);
defer list.deinit();
const reader = std.io.fixedBufferStream("0000\n1234\n").reader();
try reader.readUntilDelimiterArrayList(&list, '\n', 5);
try std.testing.expectEqualStrings("0000", list.items);
try reader.readUntilDelimiterArrayList(&list, '\n', 5);
try std.testing.expectEqualStrings("1234", list.items);
try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterArrayList(&list, '\n', 5));
}
test "Reader.readUntilDelimiterArrayList returns an empty ArrayList" {
const a = std.testing.allocator;
var list = std.ArrayList(u8).init(a);
defer list.deinit();
const reader = std.io.fixedBufferStream("\n").reader();
try reader.readUntilDelimiterArrayList(&list, '\n', 5);
try std.testing.expectEqualStrings("", list.items);
}
test "Reader.readUntilDelimiterArrayList returns StreamTooLong, then an ArrayList with bytes read until the delimiter" {
const a = std.testing.allocator;
var list = std.ArrayList(u8).init(a);
defer list.deinit();
const reader = std.io.fixedBufferStream("1234567\n").reader();
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterArrayList(&list, '\n', 5));
try std.testing.expectEqualStrings("12345", list.items);
try reader.readUntilDelimiterArrayList(&list, '\n', 5);
try std.testing.expectEqualStrings("67", list.items);
}
test "Reader.readUntilDelimiterArrayList returns EndOfStream" {
const a = std.testing.allocator;
var list = std.ArrayList(u8).init(a);
defer list.deinit();
const reader = std.io.fixedBufferStream("1234").reader();
try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterArrayList(&list, '\n', 5));
try std.testing.expectEqualStrings("1234", list.items);
}
test "Reader.readUntilDelimiterAlloc returns ArrayLists with bytes read until the delimiter, then EndOfStream" {
const a = std.testing.allocator;
const reader = std.io.fixedBufferStream("0000\n1234\n").reader();
{
var result = try reader.readUntilDelimiterAlloc(a, '\n', 5);
defer a.free(result);
try std.testing.expectEqualStrings("0000", result);
}
{
var result = try reader.readUntilDelimiterAlloc(a, '\n', 5);
defer a.free(result);
try std.testing.expectEqualStrings("1234", result);
}
try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterAlloc(a, '\n', 5));
}
test "Reader.readUntilDelimiterAlloc returns an empty ArrayList" {
const a = std.testing.allocator;
const reader = std.io.fixedBufferStream("\n").reader();
{
var result = try reader.readUntilDelimiterAlloc(a, '\n', 5);
defer a.free(result);
try std.testing.expectEqualStrings("", result);
}
}
test "Reader.readUntilDelimiterAlloc returns StreamTooLong, then an ArrayList with bytes read until the delimiter" {
const a = std.testing.allocator;
const reader = std.io.fixedBufferStream("1234567\n").reader();
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterAlloc(a, '\n', 5));
var result = try reader.readUntilDelimiterAlloc(a, '\n', 5);
defer a.free(result);
try std.testing.expectEqualStrings("67", result);
}
test "Reader.readUntilDelimiterAlloc returns EndOfStream" {
const a = std.testing.allocator;
const reader = std.io.fixedBufferStream("1234").reader();
try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterAlloc(a, '\n', 5));
}
test "Reader.readUntilDelimiter returns bytes read until the delimiter" {
var buf: [5]u8 = undefined;
const reader = std.io.fixedBufferStream("0000\n1234\n").reader();
try std.testing.expectEqualStrings("0000", try reader.readUntilDelimiter(&buf, '\n'));
try std.testing.expectEqualStrings("1234", try reader.readUntilDelimiter(&buf, '\n'));
}
test "Reader.readUntilDelimiter returns an empty string" {
var buf: [5]u8 = undefined;
const reader = std.io.fixedBufferStream("\n").reader();
try std.testing.expectEqualStrings("", try reader.readUntilDelimiter(&buf, '\n'));
}
test "Reader.readUntilDelimiter returns StreamTooLong, then an empty string" {
var buf: [5]u8 = undefined;
const reader = std.io.fixedBufferStream("12345\n").reader();
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n'));
try std.testing.expectEqualStrings("", try reader.readUntilDelimiter(&buf, '\n'));
}
test "Reader.readUntilDelimiter returns StreamTooLong, then bytes read until the delimiter" {
var buf: [5]u8 = undefined;
const reader = std.io.fixedBufferStream("1234567\n").reader();
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n'));
try std.testing.expectEqualStrings("67", try reader.readUntilDelimiter(&buf, '\n'));
}
test "Reader.readUntilDelimiter returns EndOfStream" {
var buf: [5]u8 = undefined;
const reader = std.io.fixedBufferStream("").reader();
try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n'));
}
test "Reader.readUntilDelimiter returns bytes read until delimiter, then EndOfStream" {
var buf: [5]u8 = undefined;
const reader = std.io.fixedBufferStream("1234\n").reader();
try std.testing.expectEqualStrings("1234", try reader.readUntilDelimiter(&buf, '\n'));
try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n'));
}
test "Reader.readUntilDelimiter returns EndOfStream" {
var buf: [5]u8 = undefined;
const reader = std.io.fixedBufferStream("1234").reader();
try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n'));
}
test "Reader.readUntilDelimiter returns StreamTooLong, then EndOfStream" {
var buf: [5]u8 = undefined;
const reader = std.io.fixedBufferStream("12345").reader();
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n'));
try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n'));
}
test "Reader.readUntilDelimiter writes all bytes read to the output buffer" {
var buf: [5]u8 = undefined;
const reader = std.io.fixedBufferStream("0000\n12345").reader();
_ = try reader.readUntilDelimiter(&buf, '\n');
try std.testing.expectEqualStrings("0000\n", &buf);
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n'));
try std.testing.expectEqualStrings("12345", &buf);
}
test "Reader.readUntilDelimiterOrEofAlloc returns ArrayLists with bytes read until the delimiter, then EndOfStream" {
const a = std.testing.allocator;
const reader = std.io.fixedBufferStream("0000\n1234\n").reader();
{
var result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?;
defer a.free(result);
try std.testing.expectEqualStrings("0000", result);
}
{
var result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?;
defer a.free(result);
try std.testing.expectEqualStrings("1234", result);
}
try std.testing.expect((try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)) == null);
}
test "Reader.readUntilDelimiterOrEofAlloc returns an empty ArrayList" {
const a = std.testing.allocator;
const reader = std.io.fixedBufferStream("\n").reader();
{
var result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?;
defer a.free(result);
try std.testing.expectEqualStrings("", result);
}
}
test "Reader.readUntilDelimiterOrEofAlloc returns StreamTooLong, then an ArrayList with bytes read until the delimiter" {
const a = std.testing.allocator;
const reader = std.io.fixedBufferStream("1234567\n").reader();
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEofAlloc(a, '\n', 5));
var result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?;
defer a.free(result);
try std.testing.expectEqualStrings("67", result);
}
test "Reader.readUntilDelimiterOrEof returns bytes read until the delimiter" {
var buf: [5]u8 = undefined;
const reader = std.io.fixedBufferStream("0000\n1234\n").reader();
try std.testing.expectEqualStrings("0000", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
try std.testing.expectEqualStrings("1234", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
}
test "Reader.readUntilDelimiterOrEof returns an empty string" {
var buf: [5]u8 = undefined;
const reader = std.io.fixedBufferStream("\n").reader();
try std.testing.expectEqualStrings("", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
}
test "Reader.readUntilDelimiterOrEof returns StreamTooLong, then an empty string" {
var buf: [5]u8 = undefined;
const reader = std.io.fixedBufferStream("12345\n").reader();
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n'));
try std.testing.expectEqualStrings("", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
}
test "Reader.readUntilDelimiterOrEof returns StreamTooLong, then bytes read until the delimiter" {
var buf: [5]u8 = undefined;
const reader = std.io.fixedBufferStream("1234567\n").reader();
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n'));
try std.testing.expectEqualStrings("67", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
}
test "Reader.readUntilDelimiterOrEof returns null" {
var buf: [5]u8 = undefined;
const reader = std.io.fixedBufferStream("").reader();
try std.testing.expect((try reader.readUntilDelimiterOrEof(&buf, '\n')) == null);
}
test "Reader.readUntilDelimiterOrEof returns bytes read until delimiter, then null" {
var buf: [5]u8 = undefined;
const reader = std.io.fixedBufferStream("1234\n").reader();
try std.testing.expectEqualStrings("1234", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
try std.testing.expect((try reader.readUntilDelimiterOrEof(&buf, '\n')) == null);
}
test "Reader.readUntilDelimiterOrEof returns bytes read until end-of-stream" {
var buf: [5]u8 = undefined;
const reader = std.io.fixedBufferStream("1234").reader();
try std.testing.expectEqualStrings("1234", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
}
test "Reader.readUntilDelimiterOrEof returns StreamTooLong, then bytes read until end-of-stream" {
var buf: [5]u8 = undefined;
const reader = std.io.fixedBufferStream("1234567").reader();
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n'));
try std.testing.expectEqualStrings("67", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?);
}
test "Reader.readUntilDelimiterOrEof writes all bytes read to the output buffer" {
var buf: [5]u8 = undefined;
const reader = std.io.fixedBufferStream("0000\n12345").reader();
_ = try reader.readUntilDelimiterOrEof(&buf, '\n');
try std.testing.expectEqualStrings("0000\n", &buf);
try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n'));
try std.testing.expectEqualStrings("12345", &buf);
}

View File

@@ -9,19 +9,19 @@ pub fn isNormal(x: anytype) bool {
switch (T) { switch (T) {
f16 => { f16 => {
const bits = @bitCast(u16, x); const bits = @bitCast(u16, x);
return (bits + (1 << 10)) & (maxInt(u16) >> 1) >= (1 << 11); return (bits +% (1 << 10)) & (maxInt(u16) >> 1) >= (1 << 11);
}, },
f32 => { f32 => {
const bits = @bitCast(u32, x); const bits = @bitCast(u32, x);
return (bits + (1 << 23)) & (maxInt(u32) >> 1) >= (1 << 24); return (bits +% (1 << 23)) & (maxInt(u32) >> 1) >= (1 << 24);
}, },
f64 => { f64 => {
const bits = @bitCast(u64, x); const bits = @bitCast(u64, x);
return (bits + (1 << 52)) & (maxInt(u64) >> 1) >= (1 << 53); return (bits +% (1 << 52)) & (maxInt(u64) >> 1) >= (1 << 53);
}, },
f128 => { f128 => {
const bits = @bitCast(u128, x); const bits = @bitCast(u128, x);
return (bits + (1 << 112)) & (maxInt(u128) >> 1) >= (1 << 113); return (bits +% (1 << 112)) & (maxInt(u128) >> 1) >= (1 << 113);
}, },
else => { else => {
@compileError("isNormal not implemented for " ++ @typeName(T)); @compileError("isNormal not implemented for " ++ @typeName(T));
@@ -34,6 +34,18 @@ test "math.isNormal" {
try expect(!isNormal(math.nan(f32))); try expect(!isNormal(math.nan(f32)));
try expect(!isNormal(math.nan(f64))); try expect(!isNormal(math.nan(f64)));
try expect(!isNormal(math.nan(f128))); try expect(!isNormal(math.nan(f128)));
try expect(!isNormal(-math.nan(f16)));
try expect(!isNormal(-math.nan(f32)));
try expect(!isNormal(-math.nan(f64)));
try expect(!isNormal(-math.nan(f128)));
try expect(!isNormal(math.inf(f16)));
try expect(!isNormal(math.inf(f32)));
try expect(!isNormal(math.inf(f64)));
try expect(!isNormal(math.inf(f128)));
try expect(!isNormal(-math.inf(f16)));
try expect(!isNormal(-math.inf(f32)));
try expect(!isNormal(-math.inf(f64)));
try expect(!isNormal(-math.inf(f128)));
try expect(!isNormal(@as(f16, 0))); try expect(!isNormal(@as(f16, 0)));
try expect(!isNormal(@as(f32, 0))); try expect(!isNormal(@as(f32, 0)));
try expect(!isNormal(@as(f64, 0))); try expect(!isNormal(@as(f64, 0)));

View File

@@ -275,7 +275,9 @@ pub fn zeroes(comptime T: type) T {
} else { } else {
var structure: T = undefined; var structure: T = undefined;
inline for (struct_info.fields) |field| { inline for (struct_info.fields) |field| {
@field(structure, field.name) = zeroes(@TypeOf(@field(structure, field.name))); if (!field.is_comptime) {
@field(structure, field.name) = zeroes(@TypeOf(@field(structure, field.name)));
}
} }
return structure; return structure;
} }
@@ -306,9 +308,7 @@ pub fn zeroes(comptime T: type) T {
if (comptime meta.containerLayout(T) == .Extern) { if (comptime meta.containerLayout(T) == .Extern) {
// The C language specification states that (global) unions // The C language specification states that (global) unions
// should be zero initialized to the first named member. // should be zero initialized to the first named member.
var item: T = undefined; return @unionInit(T, info.fields[0].name, zeroes(info.fields[0].field_type));
@field(item, info.fields[0].name) = zeroes(@TypeOf(@field(item, info.fields[0].name)));
return item;
} }
@compileError("Can't set a " ++ @typeName(T) ++ " to zero."); @compileError("Can't set a " ++ @typeName(T) ++ " to zero.");
@@ -342,6 +342,8 @@ test "mem.zeroes" {
try testing.expect(a.y == 10); try testing.expect(a.y == 10);
const ZigStruct = struct { const ZigStruct = struct {
comptime comptime_field: u8 = 5,
integral_types: struct { integral_types: struct {
integer_0: i0, integer_0: i0,
integer_8: i8, integer_8: i8,
@@ -376,6 +378,7 @@ test "mem.zeroes" {
}; };
const b = zeroes(ZigStruct); const b = zeroes(ZigStruct);
try testing.expectEqual(@as(u8, 5), b.comptime_field);
try testing.expectEqual(@as(i8, 0), b.integral_types.integer_0); try testing.expectEqual(@as(i8, 0), b.integral_types.integer_0);
try testing.expectEqual(@as(i8, 0), b.integral_types.integer_8); try testing.expectEqual(@as(i8, 0), b.integral_types.integer_8);
try testing.expectEqual(@as(i16, 0), b.integral_types.integer_16); try testing.expectEqual(@as(i16, 0), b.integral_types.integer_16);
@@ -411,6 +414,9 @@ test "mem.zeroes" {
var c = zeroes(C_union); var c = zeroes(C_union);
try testing.expectEqual(@as(u8, 0), c.a); try testing.expectEqual(@as(u8, 0), c.a);
comptime var comptime_union = zeroes(C_union);
try testing.expectEqual(@as(u8, 0), comptime_union.a);
} }
/// Initializes all fields of the struct with their default value, or zero values if no default value is present. /// Initializes all fields of the struct with their default value, or zero values if no default value is present.
@@ -715,7 +721,7 @@ fn SliceTo(comptime T: type, comptime end: meta.Elem(T)) type {
@compileError("invalid type given to std.mem.sliceTo: " ++ @typeName(T)); @compileError("invalid type given to std.mem.sliceTo: " ++ @typeName(T));
} }
/// Takes a pointer to an array, an array, a sentinel-terminated pointer, or a slice and /// Takes an array, a pointer to an array, a sentinel-terminated pointer, or a slice and
/// iterates searching for the first occurrence of `end`, returning the scanned slice. /// iterates searching for the first occurrence of `end`, returning the scanned slice.
/// If `end` is not found, the full length of the array/slice/sentinel terminated pointer is returned. /// If `end` is not found, the full length of the array/slice/sentinel terminated pointer is returned.
/// If the pointer type is sentinel terminated and `end` matches that terminator, the /// If the pointer type is sentinel terminated and `end` matches that terminator, the

View File

@@ -188,7 +188,7 @@ pub fn MultiArrayList(comptime S: type) type {
/// after and including the specified index back by one and /// after and including the specified index back by one and
/// sets the given index to the specified element. May reallocate /// sets the given index to the specified element. May reallocate
/// and invalidate iterators. /// and invalidate iterators.
pub fn insert(self: *Self, gpa: Allocator, index: usize, elem: S) void { pub fn insert(self: *Self, gpa: Allocator, index: usize, elem: S) !void {
try self.ensureUnusedCapacity(gpa, 1); try self.ensureUnusedCapacity(gpa, 1);
self.insertAssumeCapacity(index, elem); self.insertAssumeCapacity(index, elem);
} }
@@ -602,3 +602,22 @@ test "ensure capacity on empty list" {
try testing.expectEqualSlices(u32, &[_]u32{ 9, 11 }, list.items(.a)); try testing.expectEqualSlices(u32, &[_]u32{ 9, 11 }, list.items(.a));
try testing.expectEqualSlices(u8, &[_]u8{ 10, 12 }, list.items(.b)); try testing.expectEqualSlices(u8, &[_]u8{ 10, 12 }, list.items(.b));
} }
test "insert elements" {
const ally = testing.allocator;
const Foo = struct {
a: u8,
b: u32,
};
var list = MultiArrayList(Foo){};
defer list.deinit(ally);
try list.insert(ally, 0, .{ .a = 1, .b = 2 });
try list.ensureUnusedCapacity(ally, 1);
list.insertAssumeCapacity(1, .{ .a = 2, .b = 3 });
try testing.expectEqualSlices(u8, &[_]u8{ 1, 2 }, list.items(.a));
try testing.expectEqualSlices(u32, &[_]u32{ 2, 3 }, list.items(.b));
}

View File

@@ -636,17 +636,35 @@ pub fn connectUnixSocket(path: []const u8) !Stream {
} }
fn if_nametoindex(name: []const u8) !u32 { fn if_nametoindex(name: []const u8) !u32 {
var ifr: os.ifreq = undefined; if (builtin.target.os.tag == .linux) {
var sockfd = try os.socket(os.AF.UNIX, os.SOCK.DGRAM | os.SOCK.CLOEXEC, 0); var ifr: os.ifreq = undefined;
defer os.closeSocket(sockfd); var sockfd = try os.socket(os.AF.UNIX, os.SOCK.DGRAM | os.SOCK.CLOEXEC, 0);
defer os.closeSocket(sockfd);
std.mem.copy(u8, &ifr.ifrn.name, name); std.mem.copy(u8, &ifr.ifrn.name, name);
ifr.ifrn.name[name.len] = 0; ifr.ifrn.name[name.len] = 0;
// TODO investigate if this needs to be integrated with evented I/O. // TODO investigate if this needs to be integrated with evented I/O.
try os.ioctl_SIOCGIFINDEX(sockfd, &ifr); try os.ioctl_SIOCGIFINDEX(sockfd, &ifr);
return @bitCast(u32, ifr.ifru.ivalue); return @bitCast(u32, ifr.ifru.ivalue);
}
if (comptime builtin.target.os.tag.isDarwin()) {
if (name.len >= os.IFNAMESIZE)
return error.NameTooLong;
var if_name: [os.IFNAMESIZE:0]u8 = undefined;
std.mem.copy(u8, &if_name, name);
if_name[name.len] = 0;
const if_slice = if_name[0..name.len :0];
const index = os.system.if_nametoindex(if_slice);
if (index == 0)
return error.InterfaceNotFound;
return @bitCast(u32, index);
}
@compileError("std.net.if_nametoindex unimplemented for this OS");
} }
pub const AddressList = struct { pub const AddressList = struct {

View File

@@ -49,7 +49,7 @@ test "parse and render IPv6 addresses" {
try testing.expectError(error.Incomplete, net.Address.parseIp6("FF01:", 0)); try testing.expectError(error.Incomplete, net.Address.parseIp6("FF01:", 0));
try testing.expectError(error.InvalidIpv4Mapping, net.Address.parseIp6("::123.123.123.123", 0)); try testing.expectError(error.InvalidIpv4Mapping, net.Address.parseIp6("::123.123.123.123", 0));
// TODO Make this test pass on other operating systems. // TODO Make this test pass on other operating systems.
if (builtin.os.tag == .linux) { if (builtin.os.tag == .linux or comptime builtin.os.tag.isDarwin()) {
try testing.expectError(error.Incomplete, net.Address.resolveIp6("ff01::fb%", 0)); try testing.expectError(error.Incomplete, net.Address.resolveIp6("ff01::fb%", 0));
try testing.expectError(error.Overflow, net.Address.resolveIp6("ff01::fb%wlp3s0s0s0s0s0s0s0s0", 0)); try testing.expectError(error.Overflow, net.Address.resolveIp6("ff01::fb%wlp3s0s0s0s0s0s0s0s0", 0));
try testing.expectError(error.Overflow, net.Address.resolveIp6("ff01::fb%12345678901234", 0)); try testing.expectError(error.Overflow, net.Address.resolveIp6("ff01::fb%12345678901234", 0));
@@ -57,7 +57,7 @@ test "parse and render IPv6 addresses" {
} }
test "invalid but parseable IPv6 scope ids" { test "invalid but parseable IPv6 scope ids" {
if (builtin.os.tag != .linux) { if (builtin.os.tag != .linux or comptime !builtin.os.tag.isDarwin()) {
// Currently, resolveIp6 with alphanumerical scope IDs only works on Linux. // Currently, resolveIp6 with alphanumerical scope IDs only works on Linux.
// TODO Make this test pass on other operating systems. // TODO Make this test pass on other operating systems.
return error.SkipZigTest; return error.SkipZigTest;

View File

@@ -163,6 +163,7 @@ pub const sigset_t = system.sigset_t;
pub const sockaddr = system.sockaddr; pub const sockaddr = system.sockaddr;
pub const socklen_t = system.socklen_t; pub const socklen_t = system.socklen_t;
pub const stack_t = system.stack_t; pub const stack_t = system.stack_t;
pub const tcflag_t = system.tcflag_t;
pub const termios = system.termios; pub const termios = system.termios;
pub const time_t = system.time_t; pub const time_t = system.time_t;
pub const timespec = system.timespec; pub const timespec = system.timespec;
@@ -992,7 +993,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {
/// transfer further bytes or may result in an error (e.g., if the disk is now full). /// transfer further bytes or may result in an error (e.g., if the disk is now full).
/// ///
/// For POSIX systems, if `fd` is opened in non blocking mode, the function will /// For POSIX systems, if `fd` is opened in non blocking mode, the function will
/// return error.WouldBlock when EAGAIN is received.k`. /// return error.WouldBlock when EAGAIN is received.
/// On Windows, if the application has a global event loop enabled, I/O Completion Ports are /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are
/// used to perform the I/O. `error.WouldBlock` is not possible on Windows. /// used to perform the I/O. `error.WouldBlock` is not possible on Windows.
/// ///

View File

@@ -440,26 +440,30 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
} }
pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: i64) usize { pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: i64) usize {
const offset_halves = splitValueLE64(offset); const offset_u = @bitCast(u64, offset);
return syscall5( return syscall5(
.preadv, .preadv,
@bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, fd)),
@ptrToInt(iov), @ptrToInt(iov),
count, count,
offset_halves[0], // Kernel expects the offset is splitted into largest natural word-size.
offset_halves[1], // See following link for detail:
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=601cc11d054ae4b5e9b5babec3d8e4667a2cb9b5
@truncate(usize, offset_u),
if (usize_bits < 64) @truncate(usize, offset_u >> 32) else 0,
); );
} }
pub fn preadv2(fd: i32, iov: [*]const iovec, count: usize, offset: i64, flags: kernel_rwf) usize { pub fn preadv2(fd: i32, iov: [*]const iovec, count: usize, offset: i64, flags: kernel_rwf) usize {
const offset_halves = splitValue64(offset); const offset_u = @bitCast(u64, offset);
return syscall6( return syscall6(
.preadv2, .preadv2,
@bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, fd)),
@ptrToInt(iov), @ptrToInt(iov),
count, count,
offset_halves[0], // See comments in preadv
offset_halves[1], @truncate(usize, offset_u),
if (usize_bits < 64) @truncate(usize, offset_u >> 32) else 0,
flags, flags,
); );
} }
@@ -473,26 +477,28 @@ pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize {
} }
pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: i64) usize { pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: i64) usize {
const offset_halves = splitValueLE64(offset); const offset_u = @bitCast(u64, offset);
return syscall5( return syscall5(
.pwritev, .pwritev,
@bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, fd)),
@ptrToInt(iov), @ptrToInt(iov),
count, count,
offset_halves[0], // See comments in preadv
offset_halves[1], @truncate(usize, offset_u),
if (usize_bits < 64) @truncate(usize, offset_u >> 32) else 0,
); );
} }
pub fn pwritev2(fd: i32, iov: [*]const iovec_const, count: usize, offset: i64, flags: kernel_rwf) usize { pub fn pwritev2(fd: i32, iov: [*]const iovec_const, count: usize, offset: i64, flags: kernel_rwf) usize {
const offset_halves = splitValue64(offset); const offset_u = @bitCast(u64, offset);
return syscall6( return syscall6(
.pwritev2, .pwritev2,
@bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, fd)),
@ptrToInt(iov), @ptrToInt(iov),
count, count,
offset_halves[0], // See comments in preadv
offset_halves[1], @truncate(usize, offset_u),
if (usize_bits < 64) @truncate(usize, offset_u >> 32) else 0,
flags, flags,
); );
} }
@@ -738,7 +744,11 @@ pub fn fchmod(fd: i32, mode: mode_t) usize {
} }
pub fn fchown(fd: i32, owner: uid_t, group: gid_t) usize { pub fn fchown(fd: i32, owner: uid_t, group: gid_t) usize {
return syscall3(.fchown, @bitCast(usize, @as(isize, fd)), owner, group); if (@hasField(SYS, "fchown32")) {
return syscall3(.fchown32, @bitCast(usize, @as(isize, fd)), owner, group);
} else {
return syscall3(.fchown, @bitCast(usize, @as(isize, fd)), owner, group);
}
} }
/// Can only be called on 32 bit systems. For 64 bit see `lseek`. /// Can only be called on 32 bit systems. For 64 bit see `lseek`.

View File

@@ -300,9 +300,10 @@ pub const IO_Uring = struct {
/// A convenience method for `copy_cqes()` for when you don't need to batch or peek. /// A convenience method for `copy_cqes()` for when you don't need to batch or peek.
pub fn copy_cqe(ring: *IO_Uring) !io_uring_cqe { pub fn copy_cqe(ring: *IO_Uring) !io_uring_cqe {
var cqes: [1]io_uring_cqe = undefined; var cqes: [1]io_uring_cqe = undefined;
const count = try ring.copy_cqes(&cqes, 1); while (true) {
assert(count == 1); const count = try ring.copy_cqes(&cqes, 1);
return cqes[0]; if (count > 0) return cqes[0];
}
} }
/// Matches the implementation of cq_ring_needs_flush() in liburing. /// Matches the implementation of cq_ring_needs_flush() in liburing.
@@ -2471,7 +2472,7 @@ test "renameat" {
switch (cqe.err()) { switch (cqe.err()) {
.SUCCESS => {}, .SUCCESS => {},
// This kernel's io_uring does not yet implement renameat (kernel version < 5.11) // This kernel's io_uring does not yet implement renameat (kernel version < 5.11)
.INVAL => return error.SkipZigTest, .BADF, .INVAL => return error.SkipZigTest,
else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), else => |errno| std.debug.panic("unhandled errno: {}", .{errno}),
} }
try testing.expectEqual(linux.io_uring_cqe{ try testing.expectEqual(linux.io_uring_cqe{
@@ -2533,7 +2534,7 @@ test "unlinkat" {
switch (cqe.err()) { switch (cqe.err()) {
.SUCCESS => {}, .SUCCESS => {},
// This kernel's io_uring does not yet implement unlinkat (kernel version < 5.11) // This kernel's io_uring does not yet implement unlinkat (kernel version < 5.11)
.INVAL => return error.SkipZigTest, .BADF, .INVAL => return error.SkipZigTest,
else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), else => |errno| std.debug.panic("unhandled errno: {}", .{errno}),
} }
try testing.expectEqual(linux.io_uring_cqe{ try testing.expectEqual(linux.io_uring_cqe{
@@ -2579,7 +2580,7 @@ test "mkdirat" {
switch (cqe.err()) { switch (cqe.err()) {
.SUCCESS => {}, .SUCCESS => {},
// This kernel's io_uring does not yet implement mkdirat (kernel version < 5.15) // This kernel's io_uring does not yet implement mkdirat (kernel version < 5.15)
.INVAL => return error.SkipZigTest, .BADF, .INVAL => return error.SkipZigTest,
else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), else => |errno| std.debug.panic("unhandled errno: {}", .{errno}),
} }
try testing.expectEqual(linux.io_uring_cqe{ try testing.expectEqual(linux.io_uring_cqe{
@@ -2628,7 +2629,7 @@ test "symlinkat" {
switch (cqe.err()) { switch (cqe.err()) {
.SUCCESS => {}, .SUCCESS => {},
// This kernel's io_uring does not yet implement symlinkat (kernel version < 5.15) // This kernel's io_uring does not yet implement symlinkat (kernel version < 5.15)
.INVAL => return error.SkipZigTest, .BADF, .INVAL => return error.SkipZigTest,
else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), else => |errno| std.debug.panic("unhandled errno: {}", .{errno}),
} }
try testing.expectEqual(linux.io_uring_cqe{ try testing.expectEqual(linux.io_uring_cqe{
@@ -2683,7 +2684,7 @@ test "linkat" {
switch (cqe.err()) { switch (cqe.err()) {
.SUCCESS => {}, .SUCCESS => {},
// This kernel's io_uring does not yet implement linkat (kernel version < 5.15) // This kernel's io_uring does not yet implement linkat (kernel version < 5.15)
.INVAL => return error.SkipZigTest, .BADF, .INVAL => return error.SkipZigTest,
else => |errno| std.debug.panic("unhandled errno: {}", .{errno}), else => |errno| std.debug.panic("unhandled errno: {}", .{errno}),
} }
try testing.expectEqual(linux.io_uring_cqe{ try testing.expectEqual(linux.io_uring_cqe{

View File

@@ -7,6 +7,13 @@ pub const protocols = @import("uefi/protocols.zig");
pub const Status = @import("uefi/status.zig").Status; pub const Status = @import("uefi/status.zig").Status;
pub const tables = @import("uefi/tables.zig"); pub const tables = @import("uefi/tables.zig");
/// The memory type to allocate when using the pool
/// Defaults to .LoaderData, the default data allocation type
/// used by UEFI applications to allocate pool memory.
pub var efi_pool_memory_type: tables.MemoryType = .LoaderData;
pub const pool_allocator = @import("uefi/pool_allocator.zig").pool_allocator;
pub const raw_pool_allocator = @import("uefi/pool_allocator.zig").raw_pool_allocator;
/// The EFI image's handle that is passed to its entry point. /// The EFI image's handle that is passed to its entry point.
pub var handle: Handle = undefined; pub var handle: Handle = undefined;

View File

@@ -0,0 +1,153 @@
const std = @import("std");
const mem = std.mem;
const uefi = std.os.uefi;
const assert = std.debug.assert;
const Allocator = mem.Allocator;
const UefiPoolAllocator = struct {
fn getHeader(ptr: [*]u8) *[*]align(8) u8 {
return @intToPtr(*[*]align(8) u8, @ptrToInt(ptr) - @sizeOf(usize));
}
fn alignedAlloc(len: usize, alignment: usize) ?[*]u8 {
var unaligned_ptr: [*]align(8) u8 = undefined;
if (uefi.system_table.boot_services.?.allocatePool(uefi.efi_pool_memory_type, len, &unaligned_ptr) != .Success)
return null;
const unaligned_addr = @ptrToInt(unaligned_ptr);
const aligned_addr = mem.alignForward(unaligned_addr + @sizeOf(usize), alignment);
var aligned_ptr = unaligned_ptr + (aligned_addr - unaligned_addr);
getHeader(aligned_ptr).* = unaligned_ptr;
return aligned_ptr;
}
fn alignedFree(ptr: [*]u8) void {
_ = uefi.system_table.boot_services.?.freePool(getHeader(ptr).*);
}
fn alloc(
_: *anyopaque,
len: usize,
ptr_align: u29,
len_align: u29,
ret_addr: usize,
) Allocator.Error![]u8 {
_ = ret_addr;
assert(len > 0);
assert(std.math.isPowerOfTwo(ptr_align));
var ptr = alignedAlloc(len, ptr_align) orelse return error.OutOfMemory;
if (len_align == 0)
return ptr[0..len];
return ptr[0..mem.alignBackwardAnyAlign(len, len_align)];
}
fn resize(
_: *anyopaque,
buf: []u8,
buf_align: u29,
new_len: usize,
len_align: u29,
ret_addr: usize,
) ?usize {
_ = buf_align;
_ = ret_addr;
return if (new_len <= buf.len) mem.alignAllocLen(buf.len, new_len, len_align) else null;
}
fn free(
_: *anyopaque,
buf: []u8,
buf_align: u29,
ret_addr: usize,
) void {
_ = buf_align;
_ = ret_addr;
alignedFree(buf.ptr);
}
};
/// Supports the full Allocator interface, including alignment.
/// For a direct call of `allocatePool`, see `raw_pool_allocator`.
pub const pool_allocator = Allocator{
.ptr = undefined,
.vtable = &pool_allocator_vtable,
};
const pool_allocator_vtable = Allocator.VTable{
.alloc = UefiPoolAllocator.alloc,
.resize = UefiPoolAllocator.resize,
.free = UefiPoolAllocator.free,
};
/// Asserts allocations are 8 byte aligned and calls `boot_services.allocatePool`.
pub const raw_pool_allocator = Allocator{
.ptr = undefined,
.vtable = &raw_pool_allocator_table,
};
const raw_pool_allocator_table = Allocator.VTable{
.alloc = uefi_alloc,
.resize = uefi_resize,
.free = uefi_free,
};
fn uefi_alloc(
_: *anyopaque,
len: usize,
ptr_align: u29,
len_align: u29,
ret_addr: usize,
) Allocator.Error![]u8 {
_ = len_align;
_ = ret_addr;
std.debug.assert(ptr_align <= 8);
var ptr: [*]align(8) u8 = undefined;
if (uefi.system_table.boot_services.?.allocatePool(uefi.efi_pool_memory_type, len, &ptr) != .Success) {
return error.OutOfMemory;
}
return ptr[0..len];
}
fn uefi_resize(
_: *anyopaque,
buf: []u8,
old_align: u29,
new_len: usize,
len_align: u29,
ret_addr: usize,
) ?usize {
_ = old_align;
_ = ret_addr;
if (new_len <= buf.len) {
return mem.alignAllocLen(buf.len, new_len, len_align);
}
return null;
}
fn uefi_free(
_: *anyopaque,
buf: []u8,
buf_align: u29,
ret_addr: usize,
) void {
_ = buf_align;
_ = ret_addr;
_ = uefi.system_table.boot_services.?.freePool(@alignCast(8, buf.ptr));
}

View File

@@ -14,6 +14,7 @@ pub const MessagingDevicePath = @import("protocols/device_path_protocol.zig").Me
pub const SimpleFileSystemProtocol = @import("protocols/simple_file_system_protocol.zig").SimpleFileSystemProtocol; pub const SimpleFileSystemProtocol = @import("protocols/simple_file_system_protocol.zig").SimpleFileSystemProtocol;
pub const FileProtocol = @import("protocols/file_protocol.zig").FileProtocol; pub const FileProtocol = @import("protocols/file_protocol.zig").FileProtocol;
pub const FileInfo = @import("protocols/file_protocol.zig").FileInfo; pub const FileInfo = @import("protocols/file_protocol.zig").FileInfo;
pub const FileSystemInfo = @import("protocols/file_protocol.zig").FileSystemInfo;
pub const InputKey = @import("protocols/simple_text_input_ex_protocol.zig").InputKey; pub const InputKey = @import("protocols/simple_text_input_ex_protocol.zig").InputKey;
pub const KeyData = @import("protocols/simple_text_input_ex_protocol.zig").KeyData; pub const KeyData = @import("protocols/simple_text_input_ex_protocol.zig").KeyData;

View File

@@ -1,4 +1,7 @@
const uefi = @import("std").os.uefi; const std = @import("std");
const mem = std.mem;
const uefi = std.os.uefi;
const Allocator = mem.Allocator;
const Guid = uefi.Guid; const Guid = uefi.Guid;
pub const DevicePathProtocol = packed struct { pub const DevicePathProtocol = packed struct {
@@ -15,6 +18,59 @@ pub const DevicePathProtocol = packed struct {
.node = [_]u8{ 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b }, .node = [_]u8{ 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b },
}; };
/// Returns the next DevicePathProtocol node in the sequence, if any.
pub fn next(self: *DevicePathProtocol) ?*DevicePathProtocol {
if (self.type == .End and @intToEnum(EndDevicePath.Subtype, self.subtype) == .EndEntire)
return null;
return @ptrCast(*DevicePathProtocol, @ptrCast([*]u8, self) + self.length);
}
/// Calculates the total length of the device path structure in bytes, including the end of device path node.
pub fn size(self: *DevicePathProtocol) usize {
var node = self;
while (node.next()) |next_node| {
node = next_node;
}
return (@ptrToInt(node) + node.length) - @ptrToInt(self);
}
/// Creates a file device path from the existing device path and a file path.
pub fn create_file_device_path(self: *DevicePathProtocol, allocator: Allocator, path: [:0]const u16) !*DevicePathProtocol {
var path_size = self.size();
// 2 * (path.len + 1) for the path and its null terminator, which are u16s
// DevicePathProtocol for the extra node before the end
var buf = try allocator.alloc(u8, path_size + 2 * (path.len + 1) + @sizeOf(DevicePathProtocol));
mem.copy(u8, buf, @ptrCast([*]const u8, self)[0..path_size]);
// Pointer to the copy of the end node of the current chain, which is - 4 from the buffer
// as the end node itself is 4 bytes (type: u8 + subtype: u8 + length: u16).
var new = @ptrCast(*MediaDevicePath.FilePathDevicePath, buf.ptr + path_size - 4);
new.type = .Media;
new.subtype = .FilePath;
new.length = @sizeOf(MediaDevicePath.FilePathDevicePath) + 2 * (@intCast(u16, path.len) + 1);
// The same as new.getPath(), but not const as we're filling it in.
var ptr = @ptrCast([*:0]u16, @alignCast(2, @ptrCast([*]u8, new)) + @sizeOf(MediaDevicePath.FilePathDevicePath));
for (path) |s, i|
ptr[i] = s;
ptr[path.len] = 0;
var end = @ptrCast(*EndDevicePath.EndEntireDevicePath, @ptrCast(*DevicePathProtocol, new).next().?);
end.type = .End;
end.subtype = .EndEntire;
end.length = @sizeOf(EndDevicePath.EndEntireDevicePath);
return @ptrCast(*DevicePathProtocol, buf.ptr);
}
pub fn getDevicePath(self: *const DevicePathProtocol) ?DevicePath { pub fn getDevicePath(self: *const DevicePathProtocol) ?DevicePath {
return switch (self.type) { return switch (self.type) {
.Hardware => blk: { .Hardware => blk: {

View File

@@ -127,15 +127,6 @@ pub const FileProtocol = extern struct {
return self._flush(self); return self._flush(self);
} }
pub const guid align(8) = Guid{
.time_low = 0x09576e92,
.time_mid = 0x6d3f,
.time_high_and_version = 0x11d2,
.clock_seq_high_and_reserved = 0x8e,
.clock_seq_low = 0x39,
.node = [_]u8{ 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b },
};
pub const efi_file_mode_read: u64 = 0x0000000000000001; pub const efi_file_mode_read: u64 = 0x0000000000000001;
pub const efi_file_mode_write: u64 = 0x0000000000000002; pub const efi_file_mode_write: u64 = 0x0000000000000002;
pub const efi_file_mode_create: u64 = 0x8000000000000000; pub const efi_file_mode_create: u64 = 0x8000000000000000;
@@ -171,4 +162,35 @@ pub const FileInfo = extern struct {
pub const efi_file_directory: u64 = 0x0000000000000010; pub const efi_file_directory: u64 = 0x0000000000000010;
pub const efi_file_archive: u64 = 0x0000000000000020; pub const efi_file_archive: u64 = 0x0000000000000020;
pub const efi_file_valid_attr: u64 = 0x0000000000000037; pub const efi_file_valid_attr: u64 = 0x0000000000000037;
pub const guid align(8) = Guid{
.time_low = 0x09576e92,
.time_mid = 0x6d3f,
.time_high_and_version = 0x11d2,
.clock_seq_high_and_reserved = 0x8e,
.clock_seq_low = 0x39,
.node = [_]u8{ 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b },
};
};
pub const FileSystemInfo = extern struct {
size: u64,
read_only: bool,
volume_size: u64,
free_space: u64,
block_size: u32,
_volume_label: u16,
pub fn getVolumeLabel(self: *const FileSystemInfo) [*:0]const u16 {
return @ptrCast([*:0]const u16, &self._volume_label);
}
pub const guid align(8) = Guid{
.time_low = 0x09576e93,
.time_mid = 0x6d3f,
.time_high_and_version = 0x11d2,
.clock_seq_high_and_reserved = 0x8e,
.clock_seq_low = 0x39,
.node = [_]u8{ 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b },
};
}; };

View File

@@ -900,6 +900,7 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil
.FILE_IS_A_DIRECTORY => return error.IsDir, .FILE_IS_A_DIRECTORY => return error.IsDir,
.NOT_A_DIRECTORY => return error.NotDir, .NOT_A_DIRECTORY => return error.NotDir,
.SHARING_VIOLATION => return error.FileBusy, .SHARING_VIOLATION => return error.FileBusy,
.CANNOT_DELETE => return error.AccessDenied,
else => return unexpectedStatus(rc), else => return unexpectedStatus(rc),
} }
} }

View File

@@ -868,7 +868,8 @@ const Msf = struct {
return error.InvalidDebugInfo; return error.InvalidDebugInfo;
if (superblock.FreeBlockMapBlock != 1 and superblock.FreeBlockMapBlock != 2) if (superblock.FreeBlockMapBlock != 1 and superblock.FreeBlockMapBlock != 2)
return error.InvalidDebugInfo; return error.InvalidDebugInfo;
if (superblock.NumBlocks * superblock.BlockSize != try file.getEndPos()) const file_len = try file.getEndPos();
if (superblock.NumBlocks * superblock.BlockSize != file_len)
return error.InvalidDebugInfo; return error.InvalidDebugInfo;
switch (superblock.BlockSize) { switch (superblock.BlockSize) {
// llvm only supports 4096 but we can handle any of these values // llvm only supports 4096 but we can handle any of these values
@@ -919,7 +920,7 @@ const Msf = struct {
const block_id = try directory.reader().readIntLittle(u32); const block_id = try directory.reader().readIntLittle(u32);
const n = (block_id % superblock.BlockSize); const n = (block_id % superblock.BlockSize);
// 0 is for SuperBlock, 1 and 2 for FPMs. // 0 is for SuperBlock, 1 and 2 for FPMs.
if (block_id == 0 or n == 1 or n == 2 or block_id * superblock.BlockSize > try file.getEndPos()) if (block_id == 0 or n == 1 or n == 2 or block_id * superblock.BlockSize > file_len)
return error.InvalidBlockIndex; return error.InvalidBlockIndex;
blocks[j] = block_id; blocks[j] = block_id;
} }

View File

@@ -559,9 +559,8 @@ pub fn argsAlloc(allocator: mem.Allocator) ![][:0]u8 {
const contents_slice = contents.items; const contents_slice = contents.items;
const slice_sizes = slice_list.items; const slice_sizes = slice_list.items;
const contents_size_bytes = try math.add(usize, contents_slice.len, slice_sizes.len);
const slice_list_bytes = try math.mul(usize, @sizeOf([]u8), slice_sizes.len); const slice_list_bytes = try math.mul(usize, @sizeOf([]u8), slice_sizes.len);
const total_bytes = try math.add(usize, slice_list_bytes, contents_size_bytes); const total_bytes = try math.add(usize, slice_list_bytes, contents_slice.len);
const buf = try allocator.alignedAlloc(u8, @alignOf([]u8), total_bytes); const buf = try allocator.alignedAlloc(u8, @alignOf([]u8), total_bytes);
errdefer allocator.free(buf); errdefer allocator.free(buf);

View File

@@ -324,7 +324,7 @@ fn _start() callconv(.Naked) noreturn {
fn WinStartup() callconv(std.os.windows.WINAPI) noreturn { fn WinStartup() callconv(std.os.windows.WINAPI) noreturn {
@setAlignStack(16); @setAlignStack(16);
if (!builtin.single_threaded) { if (!builtin.single_threaded and !builtin.link_libc) {
_ = @import("start_windows_tls.zig"); _ = @import("start_windows_tls.zig");
} }
@@ -335,7 +335,7 @@ fn WinStartup() callconv(std.os.windows.WINAPI) noreturn {
fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn { fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn {
@setAlignStack(16); @setAlignStack(16);
if (!builtin.single_threaded) { if (!builtin.single_threaded and !builtin.link_libc) {
_ = @import("start_windows_tls.zig"); _ = @import("start_windows_tls.zig");
} }
@@ -511,9 +511,9 @@ inline fn initEventLoopAndCallWinMain() std.os.windows.INT {
}; };
defer loop.deinit(); defer loop.deinit();
var result: u8 = undefined; var result: std.os.windows.INT = undefined;
var frame: @Frame(callMainAsync) = undefined; var frame: @Frame(callWinMainAsync) = undefined;
_ = @asyncCall(&frame, &result, callMainAsync, .{loop}); _ = @asyncCall(&frame, &result, callWinMainAsync, .{loop});
loop.run(); loop.run();
return result; return result;
} }
@@ -532,6 +532,14 @@ fn callMainAsync(loop: *std.event.Loop) callconv(.Async) u8 {
return callMain(); return callMain();
} }
fn callWinMainAsync(loop: *std.event.Loop) callconv(.Async) std.os.windows.INT {
// This prevents the event loop from terminating at least until main() has returned.
// TODO This shouldn't be needed here; it should be in the event loop code.
loop.beginOneEvent();
defer loop.finishOneEvent();
return call_wWinMain();
}
// This is not marked inline because it is called with @asyncCall when // This is not marked inline because it is called with @asyncCall when
// there is an event loop. // there is an event loop.
pub fn callMain() u8 { pub fn callMain() u8 {

Some files were not shown because too many files have changed in this diff Show More