zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 03cc81665bb28eb35c8c6d4be17b5a56fa66261f (tree)
parent 86d9563d1539cd7581dc120023bb830fae77ba0f
Author: Vexu <15308111+Vexu@users.noreply.github.com>
Date:   Sat, 23 Nov 2019 19:13:48 +0200

Merge branch 'master' into modernize-stage2

Diffstat:
MREADME.md | 4++--
Mbuild.zig | 2+-
Mci/azure/pipelines.yml | 4++--
Mci/drone/drone.yml | 2++
Mdoc/docgen.zig | 5+++--
Mdoc/langref.html.in | 307+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Mlib/std/array_list.zig | 16++++++++--------
Mlib/std/ascii.zig | 22+++++++++++-----------
Mlib/std/atomic/queue.zig | 6+++---
Mlib/std/atomic/stack.zig | 8++++----
Mlib/std/bloom_filter.zig | 22+++++++++++-----------
Mlib/std/build.zig | 83++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mlib/std/builtin.zig | 33++-------------------------------
Mlib/std/c.zig | 24+++++++++++++++++++++++-
Mlib/std/c/darwin.zig | 18+++++++++++++++++-
Mlib/std/c/dragonfly.zig | 13++++++++++++-
Alib/std/c/emscripten.zig | 8++++++++
Mlib/std/c/freebsd.zig | 12++++++++++++
Alib/std/c/fuchsia.zig | 8++++++++
Alib/std/c/haiku.zig | 14++++++++++++++
Alib/std/c/hermit.zig | 6++++++
Mlib/std/c/linux.zig | 23+++++++++++++++++++++++
Alib/std/c/minix.zig | 18++++++++++++++++++
Mlib/std/c/netbsd.zig | 29+++++++++++++++++++++++++++++
Alib/std/c/openbsd.zig | 6++++++
Alib/std/c/solaris.zig | 15+++++++++++++++
Mlib/std/child_process.zig | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Mlib/std/coff.zig | 2+-
Mlib/std/crypto/aes.zig | 20++++++++++----------
Mlib/std/crypto/benchmark.zig | 4+---
Mlib/std/crypto/blake2.zig | 16++++++++--------
Mlib/std/crypto/chacha20.zig | 8++++----
Mlib/std/crypto/gimli.zig | 8++++----
Mlib/std/crypto/md5.zig | 8++++----
Mlib/std/crypto/poly1305.zig | 12++++++------
Mlib/std/crypto/sha1.zig | 30+++++++++++++++---------------
Mlib/std/crypto/sha2.zig | 38++++++++++++++++++++------------------
Mlib/std/crypto/sha3.zig | 2+-
Mlib/std/crypto/x25519.zig | 66+++++++++++++++++++++++++++++++++---------------------------------
Mlib/std/debug.zig | 49+++++++++++++++++++++++++++++++------------------
Mlib/std/debug/leb128.zig | 6+++---
Mlib/std/dynamic_library.zig | 4++--
Mlib/std/elf.zig | 24++++++++++++------------
Mlib/std/event/channel.zig | 4++--
Mlib/std/event/fs.zig | 13++++++++-----
Mlib/std/event/future.zig | 25+++++++++++++------------
Mlib/std/event/group.zig | 41++++++++++++++++++++++++++++++++++-------
Mlib/std/event/lock.zig | 10+++++-----
Mlib/std/event/loop.zig | 52+++++++++++++++-------------------------------------
Mlib/std/event/rwlock.zig | 44++++++++++++++++++++++----------------------
Mlib/std/fifo.zig | 26+++++++++++++-------------
Mlib/std/fmt.zig | 130+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Mlib/std/fmt/errol.zig | 4++--
Mlib/std/fmt/parse_float.zig | 20++++++++++----------
Mlib/std/fs.zig | 115+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Mlib/std/fs/file.zig | 56++++++++++++++++++++++++--------------------------------
Mlib/std/fs/path.zig | 2+-
Mlib/std/hash/auto_hash.zig | 14+++++++-------
Mlib/std/hash/cityhash.zig | 8++++----
Mlib/std/hash/crc.zig | 8++++----
Mlib/std/hash/murmur.zig | 2+-
Mlib/std/hash/siphash.zig | 14+++++++-------
Mlib/std/hash_map.zig | 2+-
Mlib/std/heap.zig | 12+++++-------
Mlib/std/http/headers.zig | 10+++++-----
Mlib/std/io.zig | 74++++++++++++++++++++++++++------------------------------------------------
Mlib/std/io/out_stream.zig | 4++--
Mlib/std/io/test.zig | 64++++++++++++++++++++++++++++++++--------------------------------
Mlib/std/json.zig | 130++++++++++++++++----------------------------------------------------------------
Mlib/std/json/write_stream.zig | 6+++++-
Mlib/std/lazy_init.zig | 26++++++++++++++------------
Mlib/std/math.zig | 163++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mlib/std/math/acos.zig | 4++--
Mlib/std/math/acosh.zig | 4++--
Mlib/std/math/asin.zig | 4++--
Mlib/std/math/asinh.zig | 4++--
Mlib/std/math/atan.zig | 4++--
Mlib/std/math/atanh.zig | 4++--
Mlib/std/math/big/int.zig | 22+++++++++++-----------
Mlib/std/math/cbrt.zig | 10+++++-----
Mlib/std/math/ceil.zig | 6+++---
Mlib/std/math/complex.zig | 8++++----
Mlib/std/math/complex/acos.zig | 2+-
Mlib/std/math/complex/ldexp.zig | 4++--
Mlib/std/math/complex/sqrt.zig | 4++--
Mlib/std/math/complex/tanh.zig | 2+-
Mlib/std/math/copysign.zig | 6+++---
Mlib/std/math/cos.zig | 4++--
Mlib/std/math/cosh.zig | 4++--
Mlib/std/math/exp.zig | 6+++---
Mlib/std/math/exp2.zig | 6+++---
Mlib/std/math/expm1.zig | 4++--
Mlib/std/math/expo2.zig | 2+-
Mlib/std/math/fabs.zig | 8++++----
Mlib/std/math/floor.zig | 10+++++-----
Mlib/std/math/fma.zig | 2+-
Mlib/std/math/frexp.zig | 4++--
Mlib/std/math/hypot.zig | 2+-
Mlib/std/math/ilogb.zig | 6+++---
Mlib/std/math/isfinite.zig | 12++++++------
Mlib/std/math/isinf.zig | 48++++++++++++++++++++++++------------------------
Mlib/std/math/isnan.zig | 8++++----
Mlib/std/math/isnormal.zig | 12++++++------
Mlib/std/math/ln.zig | 10+++++-----
Mlib/std/math/log.zig | 14+++++++-------
Mlib/std/math/log10.zig | 10+++++-----
Mlib/std/math/log1p.zig | 6+++---
Mlib/std/math/log2.zig | 8++++----
Mlib/std/math/modf.zig | 8++++----
Mlib/std/math/round.zig | 4++--
Mlib/std/math/scalbn.zig | 4++--
Mlib/std/math/signbit.zig | 6+++---
Mlib/std/math/sin.zig | 6+++---
Mlib/std/math/sinh.zig | 4++--
Mlib/std/math/sqrt.zig | 10+++++-----
Mlib/std/math/tan.zig | 4++--
Mlib/std/math/tanh.zig | 4++--
Mlib/std/math/trunc.zig | 8++++----
Mlib/std/mem.zig | 26+++++++++++++-------------
Mlib/std/meta.zig | 4++--
Mlib/std/meta/trait.zig | 4++--
Mlib/std/mutex.zig | 133++++++++++++++++++++++++++++++++++++++-----------------------------------------
Mlib/std/net.zig | 186++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Mlib/std/net/test.zig | 38+++++++++++++++++++-------------------
Mlib/std/os.zig | 33++++++++++++++++++++++++++-------
Mlib/std/os/bits.zig | 3---
Mlib/std/os/bits/darwin.zig | 6------
Mlib/std/os/bits/dragonfly.zig | 14++++----------
Mlib/std/os/bits/freebsd.zig | 6------
Mlib/std/os/bits/linux.zig | 15+++++----------
Mlib/std/os/bits/netbsd.zig | 7-------
Mlib/std/os/bits/windows.zig | 19+++++++++++++++++++
Mlib/std/os/linux.zig | 194++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mlib/std/os/linux/arm-eabi.zig | 4++--
Mlib/std/os/linux/arm64.zig | 2+-
Mlib/std/os/linux/mipsel.zig | 6+++---
Mlib/std/os/linux/riscv64.zig | 2+-
Mlib/std/os/linux/test.zig | 6+++---
Mlib/std/os/linux/vdso.zig | 4++--
Mlib/std/os/linux/x86_64.zig | 2+-
Mlib/std/os/test.zig | 2+-
Mlib/std/os/uefi/protocols.zig | 44++++++++++++++++++++++++++++++++++++++++++++
Alib/std/os/uefi/protocols/device_path_protocol.zig | 17+++++++++++++++++
Alib/std/os/uefi/protocols/ip6_config_protocol.zig | 45+++++++++++++++++++++++++++++++++++++++++++++
Alib/std/os/uefi/protocols/ip6_protocol.zig | 143+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/std/os/uefi/protocols/ip6_service_binding_protocol.zig | 25+++++++++++++++++++++++++
Alib/std/os/uefi/protocols/loaded_image_protocol.zig | 36++++++++++++++++++++++++++++++++++++
Alib/std/os/uefi/protocols/managed_network_protocol.zig | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/std/os/uefi/protocols/managed_network_service_binding_protocol.zig | 25+++++++++++++++++++++++++
Alib/std/os/uefi/protocols/simple_network_protocol.zig | 172+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/std/os/uefi/protocols/udp6_protocol.zig | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/std/os/uefi/protocols/udp6_service_binding_protocol.zig | 25+++++++++++++++++++++++++
Mlib/std/os/uefi/tables.zig | 3+++
Mlib/std/os/uefi/tables/boot_services.zig | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Mlib/std/os/uefi/tables/runtime_services.zig | 8++++++++
Mlib/std/os/uefi/tables/system_table.zig | 1+
Mlib/std/os/windows.zig | 132+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mlib/std/os/windows/bits.zig | 132+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Mlib/std/os/windows/kernel32.zig | 13+++++++++++++
Mlib/std/os/windows/ntdll.zig | 30++++++++++++++++++++++++++++++
Mlib/std/os/windows/status.zig | 1654++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Alib/std/os/windows/ws2_32.zig | 257+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlib/std/os/zen.zig | 4++--
Mlib/std/packed_int_array.zig | 36++++++++++++++++++------------------
Alib/std/parker.zig | 180+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlib/std/pdb.zig | 2+-
Mlib/std/priority_queue.zig | 60++++++++++++++++++++++++++++++------------------------------
Mlib/std/progress.zig | 7++-----
Mlib/std/rand.zig | 16++++++++--------
Mlib/std/rand/ziggurat.zig | 2+-
Mlib/std/segmented_list.zig | 10+++++-----
Mlib/std/sort.zig | 8++++----
Mlib/std/special/build_runner.zig | 35++++++++++++-----------------------
Mlib/std/special/c.zig | 6+++---
Mlib/std/special/compiler_rt.zig | 34+++++++++++++++++-----------------
Mlib/std/special/compiler_rt/addXf3.zig | 26+++++++++++++-------------
Mlib/std/special/compiler_rt/addXf3_test.zig | 8++++----
Mlib/std/special/compiler_rt/comparedf2.zig | 20++++++++++----------
Mlib/std/special/compiler_rt/comparesf2.zig | 20++++++++++----------
Mlib/std/special/compiler_rt/comparetf2.zig | 20++++++++++----------
Mlib/std/special/compiler_rt/divdf3.zig | 66+++++++++++++++++++++++++++++++++---------------------------------
Mlib/std/special/compiler_rt/divsf3.zig | 22+++++++++++-----------
Mlib/std/special/compiler_rt/divti3_test.zig | 8++++----
Mlib/std/special/compiler_rt/extendXfYf2.zig | 14+++++++-------
Mlib/std/special/compiler_rt/extendXfYf2_test.zig | 8++++----
Mlib/std/special/compiler_rt/fixdfdi_test.zig | 2+-
Mlib/std/special/compiler_rt/fixdfsi_test.zig | 2+-
Mlib/std/special/compiler_rt/fixdfti_test.zig | 2+-
Mlib/std/special/compiler_rt/fixint.zig | 6+++---
Mlib/std/special/compiler_rt/fixint_test.zig | 26+++++++++++++-------------
Mlib/std/special/compiler_rt/fixsfdi_test.zig | 2+-
Mlib/std/special/compiler_rt/fixsfsi_test.zig | 2+-
Mlib/std/special/compiler_rt/fixsfti_test.zig | 2+-
Mlib/std/special/compiler_rt/fixtfdi_test.zig | 2+-
Mlib/std/special/compiler_rt/fixtfsi_test.zig | 2+-
Mlib/std/special/compiler_rt/fixtfti_test.zig | 2+-
Mlib/std/special/compiler_rt/fixuint.zig | 8++++----
Mlib/std/special/compiler_rt/fixunstfsi_test.zig | 2+-
Mlib/std/special/compiler_rt/fixunstfti_test.zig | 2+-
Mlib/std/special/compiler_rt/floatsiXf.zig | 10+++++-----
Mlib/std/special/compiler_rt/floattidf.zig | 2+-
Mlib/std/special/compiler_rt/floattisf.zig | 2+-
Mlib/std/special/compiler_rt/floattitf.zig | 2+-
Mlib/std/special/compiler_rt/floatunsidf.zig | 6+++---
Mlib/std/special/compiler_rt/floatuntidf.zig | 4++--
Mlib/std/special/compiler_rt/floatuntisf.zig | 4++--
Mlib/std/special/compiler_rt/floatuntitf.zig | 4++--
Mlib/std/special/compiler_rt/mulXf3.zig | 50+++++++++++++++++++++++++-------------------------
Mlib/std/special/compiler_rt/mulXf3_test.zig | 18+++++++++---------
Mlib/std/special/compiler_rt/muldi3.zig | 2+-
Mlib/std/special/compiler_rt/mulodi4.zig | 2+-
Mlib/std/special/compiler_rt/mulodi4_test.zig | 48++++++++++++++++++++++++------------------------
Mlib/std/special/compiler_rt/muloti4.zig | 2+-
Mlib/std/special/compiler_rt/muloti4_test.zig | 62+++++++++++++++++++++++++++++++-------------------------------
Mlib/std/special/compiler_rt/multi3.zig | 2+-
Mlib/std/special/compiler_rt/negXf2.zig | 2+-
Mlib/std/special/compiler_rt/popcountdi2_test.zig | 6+++---
Mlib/std/special/compiler_rt/truncXfYf2.zig | 2+-
Mlib/std/special/compiler_rt/truncXfYf2_test.zig | 20++++++++++----------
Mlib/std/special/compiler_rt/udivmod.zig | 6+++---
Mlib/std/special/docs/index.html | 2+-
Mlib/std/special/docs/main.js | 31+++++++++++++++++++------------
Mlib/std/special/start.zig | 2+-
Mlib/std/spinlock.zig | 45+++++++++++++++++++++++++++++++++++++++++----
Dlib/std/statically_initialized_mutex.zig | 105-------------------------------------------------------------------------------
Mlib/std/std.zig | 2+-
Mlib/std/target.zig | 38++++++++++++++++++++++++++++++++++++--
Mlib/std/testing.zig | 2+-
Mlib/std/thread.zig | 2+-
Mlib/std/time.zig | 8++++----
Mlib/std/unicode.zig | 26+++++++++++++-------------
Mlib/std/unicode/throughput_test.zig | 4+---
Mlib/std/valgrind.zig | 80++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Mlib/std/valgrind/callgrind.zig | 14+++++++-------
Mlib/std/valgrind/memcheck.zig | 81++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
Mlib/std/zig/ast.zig | 23+++++++++++++++++------
Mlib/std/zig/parse.zig | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Mlib/std/zig/parse_string_literal.zig | 2+-
Mlib/std/zig/parser_test.zig | 98++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Mlib/std/zig/render.zig | 78+++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
Mlib/std/zig/tokenizer.zig | 56++++++++++++++++++++++++++++++++------------------------
Msrc-self-hosted/clang.zig | 4++++
Msrc-self-hosted/main.zig | 11++++-------
Msrc-self-hosted/stage1.zig | 14+++++---------
Msrc-self-hosted/test.zig | 6+++---
Msrc-self-hosted/translate_c.zig | 19+++++++++++--------
Msrc/all_types.hpp | 63++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Msrc/analyze.cpp | 288++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Msrc/analyze.hpp | 9++++++++-
Msrc/ast_render.cpp | 22+++++++++++++++++-----
Msrc/codegen.cpp | 184++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Msrc/dump_analysis.cpp | 7++++---
Msrc/ir.cpp | 1603+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Msrc/ir_print.cpp | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Msrc/ir_print.hpp | 1+
Msrc/parser.cpp | 60++++++++++++++++++++++++++++++++++++++++++++++++------------
Msrc/range_set.cpp | 3+++
Msrc/tokenizer.cpp | 33++++++++++++++++++++++++++++++++-
Msrc/tokenizer.hpp | 1+
Msrc/translate_c.cpp | 35++++++++++++++++++++---------------
Msrc/zig_clang.cpp | 5+++++
Msrc/zig_clang.h | 3+++
Mtest/compare_output.zig | 122++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mtest/compile_errors.zig | 270+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Mtest/stage1/behavior.zig | 2++
Mtest/stage1/behavior/align.zig | 4++--
Mtest/stage1/behavior/array.zig | 39+++++++++++++++++++++++++++++++++++++--
Mtest/stage1/behavior/asm.zig | 16++++++++--------
Mtest/stage1/behavior/async_fn.zig | 14+++++++-------
Mtest/stage1/behavior/atomics.zig | 44+++++++++++++++++++++++++++++++++++++++++---
Mtest/stage1/behavior/bitreverse.zig | 28++++++++++++++--------------
Mtest/stage1/behavior/bool.zig | 8++++----
Mtest/stage1/behavior/bugs/1322.zig | 4++--
Mtest/stage1/behavior/bugs/1421.zig | 2+-
Mtest/stage1/behavior/bugs/2114.zig | 8++++----
Atest/stage1/behavior/bugs/2889.zig | 31+++++++++++++++++++++++++++++++
Atest/stage1/behavior/bugs/3007.zig | 23+++++++++++++++++++++++
Mtest/stage1/behavior/bugs/3046.zig | 2+-
Mtest/stage1/behavior/byteswap.zig | 24++++++++++++------------
Mtest/stage1/behavior/cast.zig | 49++++++++++++++++++++++++++++++++++++++-----------
Mtest/stage1/behavior/defer.zig | 2+-
Mtest/stage1/behavior/enum.zig | 4++--
Mtest/stage1/behavior/error.zig | 8++++++--
Mtest/stage1/behavior/eval.zig | 36++++++++++++++++++------------------
Mtest/stage1/behavior/floatop.zig | 4++--
Mtest/stage1/behavior/fn.zig | 20++++++++++++++++++--
Mtest/stage1/behavior/if.zig | 4++--
Mtest/stage1/behavior/import.zig | 4++--
Mtest/stage1/behavior/math.zig | 24++++++++++++------------
Mtest/stage1/behavior/misc.zig | 16++++++++--------
Mtest/stage1/behavior/popcount.zig | 2+-
Mtest/stage1/behavior/pub_enum.zig | 2+-
Mtest/stage1/behavior/shuffle.zig | 26+++++++++++++-------------
Mtest/stage1/behavior/slicetobytes.zig | 2+-
Mtest/stage1/behavior/struct.zig | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Mtest/stage1/behavior/switch.zig | 8++++----
Mtest/stage1/behavior/try.zig | 6+++---
Mtest/stage1/behavior/type_info.zig | 46+++++++++++++++++++++++-----------------------
Mtest/stage1/behavior/union.zig | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Mtest/stage1/behavior/var_args.zig | 10+++++-----
Mtest/stage1/behavior/vector.zig | 50+++++++++++++++++++++++++-------------------------
Mtest/stage1/behavior/void.zig | 2+-
Mtest/stage1/behavior/while.zig | 16++++++++--------
Mtest/standalone/brace_expansion/main.zig | 4++--
Mtest/standalone/cat/main.zig | 14++++++--------
Mtest/standalone/guess_number/main.zig | 3+--
Mtest/standalone/hello_world/hello.zig | 3+--
Mtest/tests.zig | 4++--
Mtest/translate_c.zig | 123++++++++++++++++++++++++++++++++++++++++++-------------------------------------
309 files changed, 8519 insertions(+), 3249 deletions(-)

diff --git a/README.md b/README.md @@ -1,7 +1,7 @@ ![ZIG](https://ziglang.org/zig-logo.svg) -A general-purpose programming language designed for **robustness**, -**optimality**, and **maintainability**. +A general-purpose programming language for maintaining **robust**, **optimal**, +and **reusable** code. ## Resources diff --git a/build.zig b/build.zig @@ -155,7 +155,7 @@ fn dependOnLib(b: *Builder, lib_exe_obj: var, dep: LibraryDep) void { ) catch unreachable; for (dep.system_libs.toSliceConst()) |lib| { const static_bare_name = if (mem.eql(u8, lib, "curses")) - ([]const u8)("libncurses.a") + @as([]const u8, "libncurses.a") else b.fmt("lib{}.a", lib); const static_lib_name = fs.path.join( diff --git a/ci/azure/pipelines.yml b/ci/azure/pipelines.yml @@ -14,7 +14,7 @@ jobs: displayName: 'Build and test' - job: BuildLinux pool: - vmImage: 'ubuntu-16.04' + vmImage: 'ubuntu-18.04' timeoutInMinutes: 360 @@ -53,7 +53,7 @@ jobs: strategy: maxParallel: 1 pool: - vmImage: 'ubuntu-16.04' + vmImage: 'ubuntu-18.04' variables: version: $[ dependencies.BuildLinux.outputs['main.version'] ] steps: diff --git a/ci/drone/drone.yml b/ci/drone/drone.yml @@ -9,6 +9,8 @@ steps: - name: build-and-test image: ziglang/static-base:llvm9-1 environment: + SRHT_OAUTH_TOKEN: + from_secret: SRHT_OAUTH_TOKEN AWS_ACCESS_KEY_ID: from_secret: AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY: diff --git a/doc/docgen.zig b/doc/docgen.zig @@ -10,8 +10,8 @@ const testing = std.testing; const max_doc_file_size = 10 * 1024 * 1024; -const exe_ext = std.build.Target(std.build.Target.Native).exeFileExt(); -const obj_ext = std.build.Target(std.build.Target.Native).oFileExt(); +const exe_ext = @as(std.build.Target, std.build.Target.Native).exeFileExt(); +const obj_ext = @as(std.build.Target, std.build.Target.Native).oFileExt(); const tmp_dir_name = "docgen_tmp"; const test_out_path = tmp_dir_name ++ fs.path.sep_str ++ "test" ++ exe_ext; @@ -856,6 +856,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok .LineComment, .DocComment, + .ContainerDocComment, .ShebangLine, => { try out.write("<span class=\"tok-comment\">"); diff --git a/doc/langref.html.in b/doc/langref.html.in @@ -164,15 +164,17 @@ <div id="contents"> {#header_open|Introduction#} <p> - Zig is a general-purpose programming language designed for <strong>robustness</strong>, - <strong>optimality</strong>, and <strong>maintainability</strong>. + Zig is a general-purpose programming language for maintaining <strong>robust</strong>, + <strong>optimal</strong>, and <strong>reusable</strong> code. </p> <ul> <li><strong>Robust</strong> - behavior is correct even for edge cases such as out of memory.</li> <li><strong>Optimal</strong> - write programs the best way they can behave and perform.</li> - <li><strong>Maintainable</strong> - precisely communicate intent to the compiler and other programmers. - The language imposes a low overhead to reading code and is resilient to changing requirements - and environments.</li> + <li><strong>Reusable</strong> - the same code works in many environments which have different + constraints.</li> + <li><strong>Maintainable</strong> - precisely communicate intent to the compiler and + other programmers. The language imposes a low overhead to reading code and is + resilient to changing requirements and environments.</li> </ul> <p> Often the most efficient way to learn something new is to see examples, so @@ -202,11 +204,8 @@ const std = @import("std"); pub fn main() !void { - // If this program is run without stdout attached, exit with an error. - const stdout_file = try std.io.getStdOut(); - // If this program encounters pipe failure when printing to stdout, exit - // with an error. - try stdout_file.write("Hello, world!\n"); + const stdout = &std.io.getStdOut().outStream().stream; + try stdout.print("Hello, {}!\n", "world"); } {#code_end#} <p> @@ -712,7 +711,7 @@ test "init with undefined" { } {#code_end#} <p> - {#syntax#}undefined{#endsyntax#} can be {#link|implicitly cast|Implicit Casts#} to any type. + {#syntax#}undefined{#endsyntax#} can be {#link|coerced|Type Coercion#} to any type. Once this happens, it is no longer possible to detect that the value is {#syntax#}undefined{#endsyntax#}. {#syntax#}undefined{#endsyntax#} means the value could be anything, even something that is nonsense according to the type. Translated into English, {#syntax#}undefined{#endsyntax#} means "Not a meaningful @@ -920,7 +919,7 @@ fn divide(a: i32, b: i32) i32 { {#syntax#}f128{#endsyntax#}. </p> <p> - Float literals {#link|implicitly cast|Implicit Casts#} to any floating point type, + Float literals {#link|coerce|Type Coercion#} to any floating point type, and to any {#link|integer|Integers#} type when there is no fractional component. </p> {#code_begin|syntax#} @@ -950,7 +949,7 @@ const nan = std.math.nan(f128); {#code_begin|obj|foo#} {#code_release_fast#} const builtin = @import("builtin"); -const big = f64(1 << 40); +const big = @as(f64, 1 << 40); export fn foo_strict(x: f64) f64 { return x + big - big; @@ -1652,7 +1651,7 @@ test "iterate over an array" { for (message) |byte| { sum += byte; } - assert(sum == usize('h') + usize('e') + usize('l') * 2 + usize('o')); + assert(sum == 'h' + 'e' + 'l' * 2 + 'o'); } // modifiable array @@ -1734,6 +1733,43 @@ test "array initialization with function calls" { {#code_end#} {#see_also|for|Slices#} + {#header_open|Anonymous List Literals#} + <p>Similar to {#link|Enum Literals#} and {#link|Anonymous Struct Literals#} + the type can be omitted from array literals:</p> + {#code_begin|test|anon_list#} +const std = @import("std"); +const assert = std.debug.assert; + +test "anonymous list literal syntax" { + var array: [4]u8 = .{11, 22, 33, 44}; + assert(array[0] == 11); + assert(array[1] == 22); + assert(array[2] == 33); + assert(array[3] == 44); +} + {#code_end#} + <p> + If there is no type in the result location then an anonymous list literal actually + turns into a {#link|struct#} with numbered field names: + </p> + {#code_begin|test|infer_list_literal#} +const std = @import("std"); +const assert = std.debug.assert; + +test "fully anonymous list literal" { + dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi"}); +} + +fn dump(args: var) void { + assert(args.@"0" == 1234); + assert(args.@"1" == 12.34); + assert(args.@"2"); + assert(args.@"3"[0] == 'h'); + assert(args.@"3"[1] == 'i'); +} + {#code_end#} + {#header_close#} + {#header_open|Multidimensional Arrays#} <p> Mutlidimensional arrays can be created by nesting arrays: @@ -2003,7 +2039,7 @@ test "variable alignment" { } } {#code_end#} - <p>In the same way that a {#syntax#}*i32{#endsyntax#} can be {#link|implicitly cast|Implicit Casts#} to a + <p>In the same way that a {#syntax#}*i32{#endsyntax#} can be {#link|coerced|Type Coercion#} to a {#syntax#}*const i32{#endsyntax#}, a pointer with a larger alignment can be implicitly cast to a pointer with a smaller alignment, but not vice versa. </p> @@ -2019,7 +2055,7 @@ var foo: u8 align(4) = 100; test "global variable alignment" { assert(@typeOf(&foo).alignment == 4); assert(@typeOf(&foo) == *align(4) u8); - const slice = (*[1]u8)(&foo)[0..]; + const slice = @as(*[1]u8, &foo)[0..]; assert(@typeOf(slice) == []align(4) u8); } @@ -2114,7 +2150,7 @@ const fmt = @import("std").fmt; test "using slices for strings" { // Zig has no concept of strings. String literals are arrays of u8, and // in general the string type is []u8 (slice of u8). - // Here we implicitly cast [5]u8 to []const u8 + // Here we coerce [5]u8 to []const u8 const hello: []const u8 = "hello"; const world: []const u8 = "世界"; @@ -2526,7 +2562,8 @@ test "overaligned pointer to packed struct" { Don't worry, there will be a good solution for this use case in zig. </p> {#header_close#} - {#header_open|struct Naming#} + + {#header_open|Struct Naming#} <p>Since all structs are anonymous, Zig infers the type name based on a few rules.</p> <ul> <li>If the struct is in the initialization expression of a variable, it gets named after @@ -2552,6 +2589,53 @@ fn List(comptime T: type) type { } {#code_end#} {#header_close#} + + {#header_open|Anonymous Struct Literals#} + <p> + Zig allows omitting the struct type of a literal. When the result is {#link|coerced|Type Coercion#}, + the struct literal will directly instantiate the result location, with no copy: + </p> + {#code_begin|test|struct_result#} +const std = @import("std"); +const assert = std.debug.assert; + +const Point = struct {x: i32, y: i32}; + +test "anonymous struct literal" { + var pt: Point = .{ + .x = 13, + .y = 67, + }; + assert(pt.x == 13); + assert(pt.y == 67); +} + {#code_end#} + <p> + The struct type can be inferred. Here the result location does not include a type, and + so Zig infers the type: + </p> + {#code_begin|test|struct_anon#} +const std = @import("std"); +const assert = std.debug.assert; + +test "fully anonymous struct" { + dump(.{ + .int = @as(u32, 1234), + .float = @as(f64, 12.34), + .b = true, + .s = "hi", + }); +} + +fn dump(args: var) void { + assert(args.int == 1234); + assert(args.float == 12.34); + assert(args.b); + assert(args.s[0] == 'h'); + assert(args.s[1] == 'i'); +} + {#code_end#} + {#header_close#} {#see_also|comptime|@fieldParentPtr#} {#header_close#} {#header_open|enum#} @@ -2778,7 +2862,7 @@ test "simple union" { This turns the union into a <em>tagged</em> union, which makes it eligible to use with {#link|switch#} expressions. One can use {#link|@TagType#} to obtain the enum type from the union type. - Tagged unions implicitly cast to their enum {#link|Implicit Cast: unions and enums#} + Tagged unions coerce to their enum {#link|Type Coercion: unions and enums#} </p> {#code_begin|test#} const std = @import("std"); @@ -2795,7 +2879,7 @@ const ComplexType = union(ComplexTypeTag) { test "switch on tagged union" { const c = ComplexType{ .Ok = 42 }; - assert(ComplexTypeTag(c) == ComplexTypeTag.Ok); + assert(@as(ComplexTypeTag, c) == ComplexTypeTag.Ok); switch (c) { ComplexTypeTag.Ok => |value| assert(value == 42), @@ -2807,7 +2891,7 @@ test "@TagType" { assert(@TagType(ComplexType) == ComplexTypeTag); } -test "implicit cast to enum" { +test "coerce to enum" { const c1 = ComplexType{ .Ok = 42 }; const c2 = ComplexType.NotOk; @@ -2833,7 +2917,7 @@ const ComplexType = union(ComplexTypeTag) { test "modify tagged union in switch" { var c = ComplexType{ .Ok = 42 }; - assert(ComplexTypeTag(c) == ComplexTypeTag.Ok); + assert(@as(ComplexTypeTag, c) == ComplexTypeTag.Ok); switch (c) { ComplexTypeTag.Ok => |*value| value.* += 1, @@ -2906,6 +2990,32 @@ test "@tagName" { <p>A {#syntax#}packed union{#endsyntax#} has well-defined in-memory layout and is eligible to be in a {#link|packed struct#}. {#header_close#} + + {#header_open|Anonymous Union Literals#} + <p>{#link|Anonymous Struct Literals#} syntax can be used to initialize unions without specifying + the type:</p> + {#code_begin|test|anon_union#} +const std = @import("std"); +const assert = std.debug.assert; + +const Number = union { + int: i32, + float: f64, +}; + +test "anonymous union literal syntax" { + var i: Number = .{.int = 42}; + var f = makeNumber(); + assert(i.int == 42); + assert(f.float == 12.34); +} + +fn makeNumber() Number { + return .{.float = 12.34}; +} + {#code_end#} + {#header_close#} + {#header_close#} {#header_open|blocks#} @@ -3943,7 +4053,7 @@ test "fn reflection" { However right now it is hard coded to be a {#syntax#}u16{#endsyntax#}. See <a href="https://github.com/ziglang/zig/issues/786">#768</a>. </p> <p> - You can {#link|implicitly cast|Implicit Casts#} an error from a subset to a superset: + You can {#link|coerce|Type Coercion#} an error from a subset to a superset: </p> {#code_begin|test#} const std = @import("std"); @@ -3958,7 +4068,7 @@ const AllocationError = error { OutOfMemory, }; -test "implicit cast subset to superset" { +test "coerce subset to superset" { const err = foo(AllocationError.OutOfMemory); std.debug.assert(err == FileOpenError.OutOfMemory); } @@ -3968,7 +4078,7 @@ fn foo(err: AllocationError) FileOpenError { } {#code_end#} <p> - But you cannot implicitly cast an error from a superset to a subset: + But you cannot {#link|coerce|Type Coercion#} an error from a superset to a subset: </p> {#code_begin|test_err|not a member of destination error set#} const FileOpenError = error { @@ -3981,7 +4091,7 @@ const AllocationError = error { OutOfMemory, }; -test "implicit cast superset to subset" { +test "coerce superset to subset" { foo(FileOpenError.OutOfMemory) catch {}; } @@ -4008,7 +4118,7 @@ const err = (error {FileNotFound}).FileNotFound; It is a superset of all other error sets and a subset of none of them. </p> <p> - You can implicitly cast any error set to the global one, and you can explicitly + You can {#link|coerce|Type Coercion#} any error set to the global one, and you can explicitly cast an error of the global error set to a non-global one. This inserts a language-level assert to make sure the error value is in fact in the destination error set. </p> @@ -4079,7 +4189,7 @@ test "parse u64" { <p> Within the function definition, you can see some return statements that return an error, and at the bottom a return statement that returns a {#syntax#}u64{#endsyntax#}. - Both types {#link|implicitly cast|Implicit Casts#} to {#syntax#}anyerror!u64{#endsyntax#}. + Both types {#link|coerce|Type Coercion#} to {#syntax#}anyerror!u64{#endsyntax#}. </p> <p> What it looks like to use this function varies depending on what you're @@ -4218,10 +4328,10 @@ const assert = @import("std").debug.assert; test "error union" { var foo: anyerror!i32 = undefined; - // Implicitly cast from child type of an error union: + // Coerce from child type of an error union: foo = 1234; - // Implicitly cast from an error set: + // Coerce from an error set: foo = error.SomeError; // Use compile-time reflection to access the payload type of an error union: @@ -4598,10 +4708,10 @@ fn doAThing(optional_foo: ?*Foo) void { const assert = @import("std").debug.assert; test "optional type" { - // Declare an optional and implicitly cast from null: + // Declare an optional and coerce from null: var foo: ?i32 = null; - // Implicitly cast from child type of an optional + // Coerce from child type of an optional foo = 1234; // Use compile-time reflection to access the child type of the optional: @@ -4644,38 +4754,38 @@ test "optional pointers" { {#header_open|Casting#} <p> A <strong>type cast</strong> converts a value of one type to another. - Zig has {#link|Implicit Casts#} for conversions that are known to be completely safe and unambiguous, + Zig has {#link|Type Coercion#} for conversions that are known to be completely safe and unambiguous, and {#link|Explicit Casts#} for conversions that one would not want to happen on accident. There is also a third kind of type conversion called {#link|Peer Type Resolution#} for the case when a result type must be decided given multiple operand types. </p> - {#header_open|Implicit Casts#} + {#header_open|Type Coercion#} <p> - An implicit cast occurs when one type is expected, but different type is provided: + Type coercion occurs when one type is expected, but different type is provided: </p> {#code_begin|test#} -test "implicit cast - variable declaration" { +test "type coercion - variable declaration" { var a: u8 = 1; var b: u16 = a; } -test "implicit cast - function call" { +test "type coercion - function call" { var a: u8 = 1; foo(a); } fn foo(b: u16) void {} -test "implicit cast - invoke a type as a function" { +test "type coercion - @as builtin" { var a: u8 = 1; - var b = u16(a); + var b = @as(u16, a); } {#code_end#} <p> - Implicit casts are only allowed when it is completely unambiguous how to get from one type to another, + Type coercions are only allowed when it is completely unambiguous how to get from one type to another, and the transformation is guaranteed to be safe. There is one exception, which is {#link|C Pointers#}. </p> - {#header_open|Implicit Cast: Stricter Qualification#} + {#header_open|Type Coercion: Stricter Qualification#} <p> Values which have the same representation at runtime can be cast to increase the strictness of the qualifiers, no matter how nested the qualifiers are: @@ -4690,7 +4800,7 @@ test "implicit cast - invoke a type as a function" { These casts are no-ops at runtime since the value representation does not change. </p> {#code_begin|test#} -test "implicit cast - const qualification" { +test "type coercion - const qualification" { var a: i32 = 1; var b: *i32 = &a; foo(b); @@ -4699,7 +4809,7 @@ test "implicit cast - const qualification" { fn foo(a: *const i32) void {} {#code_end#} <p> - In addition, pointers implicitly cast to const optional pointers: + In addition, pointers coerce to const optional pointers: </p> {#code_begin|test#} const std = @import("std"); @@ -4713,10 +4823,10 @@ test "cast *[1][*]const u8 to [*]const ?[*]const u8" { } {#code_end#} {#header_close#} - {#header_open|Implicit Cast: Integer and Float Widening#} + {#header_open|Type Coercion: Integer and Float Widening#} <p> - {#link|Integers#} implicitly cast to integer types which can represent every value of the old type, and likewise - {#link|Floats#} implicitly cast to float types which can represent every value of the old type. + {#link|Integers#} coerce to integer types which can represent every value of the old type, and likewise + {#link|Floats#} coerce to float types which can represent every value of the old type. </p> {#code_begin|test#} const std = @import("std"); @@ -4748,7 +4858,7 @@ test "float widening" { } {#code_end#} {#header_close#} - {#header_open|Implicit Cast: Arrays and Pointers#} + {#header_open|Type Coercion: Arrays and Pointers#} {#code_begin|test#} const std = @import("std"); const assert = std.debug.assert; @@ -4797,7 +4907,7 @@ test "*[N]T to []T" { assert(std.mem.eql(f32, x2, [2]f32{ 1.2, 3.4 })); } -// Single-item pointers to arrays can be implicitly casted to +// Single-item pointers to arrays can be coerced to // unknown length pointers. test "*[N]T to [*]T" { var buf: [5]u8 = "hello"; @@ -4823,15 +4933,15 @@ test "*T to *[1]T" { {#code_end#} {#see_also|C Pointers#} {#header_close#} - {#header_open|Implicit Cast: Optionals#} + {#header_open|Type Coercion: Optionals#} <p> - The payload type of {#link|Optionals#}, as well as {#link|null#}, implicitly cast to the optional type. + The payload type of {#link|Optionals#}, as well as {#link|null#}, coerce to the optional type. </p> {#code_begin|test#} const std = @import("std"); const assert = std.debug.assert; -test "implicit casting to optionals" { +test "coerce to optionals" { const x: ?i32 = 1234; const y: ?i32 = null; @@ -4844,7 +4954,7 @@ test "implicit casting to optionals" { const std = @import("std"); const assert = std.debug.assert; -test "implicit casting to optionals wrapped in error union" { +test "coerce to optionals wrapped in error union" { const x: anyerror!?i32 = 1234; const y: anyerror!?i32 = null; @@ -4853,15 +4963,15 @@ test "implicit casting to optionals wrapped in error union" { } {#code_end#} {#header_close#} - {#header_open|Implicit Cast: Error Unions#} + {#header_open|Type Coercion: Error Unions#} <p>The payload type of an {#link|Error Union Type#} as well as the {#link|Error Set Type#} - implicitly cast to the error union type: + coerce to the error union type: </p> {#code_begin|test#} const std = @import("std"); const assert = std.debug.assert; -test "implicit casting to error unions" { +test "coercion to error unions" { const x: anyerror!i32 = 1234; const y: anyerror!i32 = error.Failure; @@ -4870,23 +4980,23 @@ test "implicit casting to error unions" { } {#code_end#} {#header_close#} - {#header_open|Implicit Cast: Compile-Time Known Numbers#} + {#header_open|Type Coercion: Compile-Time Known Numbers#} <p>When a number is {#link|comptime#}-known to be representable in the destination type, - it may be implicitly casted: + it may be coerced: </p> {#code_begin|test#} const std = @import("std"); const assert = std.debug.assert; -test "implicit casting large integer type to smaller one when value is comptime known to fit" { +test "coercing large integer type to smaller one when value is comptime known to fit" { const x: u64 = 255; const y: u8 = x; assert(y == 255); } {#code_end#} {#header_close#} - {#header_open|Implicit Cast: unions and enums#} - <p>Tagged unions can be implicitly cast to enums, and enums can be implicitly casted to tagged unions + {#header_open|Type Coercion: unions and enums#} + <p>Tagged unions can be coerced to enums, and enums can be coerced to tagged unions when they are {#link|comptime#}-known to be a field of the union that has only one possible value, such as {#link|void#}: </p> @@ -4906,7 +5016,7 @@ const U = union(E) { Three, }; -test "implicit casting between unions and enums" { +test "coercion between unions and enums" { var u = U{ .Two = 12.34 }; var e: E = u; assert(e == E.Two); @@ -4918,20 +5028,20 @@ test "implicit casting between unions and enums" { {#code_end#} {#see_also|union|enum#} {#header_close#} - {#header_open|Implicit Cast: Zero Bit Types#} - <p>{#link|Zero Bit Types#} may be implicitly casted to single-item {#link|Pointers#}, + {#header_open|Type Coercion: Zero Bit Types#} + <p>{#link|Zero Bit Types#} may be coerced to single-item {#link|Pointers#}, regardless of const.</p> <p>TODO document the reasoning for this</p> <p>TODO document whether vice versa should work and why</p> {#code_begin|test#} -test "implicit casting of zero bit types" { +test "coercion of zero bit types" { var x: void = {}; var y: *void = x; //var z: void = y; // TODO } {#code_end#} {#header_close#} - {#header_open|Implicit Cast: undefined#} + {#header_open|Type Coercion: undefined#} <p>{#link|undefined#} can be cast to any type.</p> {#header_close#} {#header_close#} @@ -4976,7 +5086,7 @@ test "implicit casting of zero bit types" { <li>Some {#link|binary operations|Table of Operators#}</li> </ul> <p> - This kind of type resolution chooses a type that all peer types can implicitly cast into. Here are + This kind of type resolution chooses a type that all peer types can coerce into. Here are some examples: </p> {#code_begin|test#} @@ -5007,8 +5117,8 @@ test "peer resolve array and const slice" { comptime testPeerResolveArrayConstSlice(true); } fn testPeerResolveArrayConstSlice(b: bool) void { - const value1 = if (b) "aoeu" else ([]const u8)("zz"); - const value2 = if (b) ([]const u8)("zz") else "aoeu"; + const value1 = if (b) "aoeu" else @as([]const u8, "zz"); + const value2 = if (b) @as([]const u8, "zz") else "aoeu"; assert(mem.eql(u8, value1, "aoeu")); assert(mem.eql(u8, value2, "zz")); } @@ -5023,10 +5133,10 @@ test "peer type resolution: ?T and T" { } fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize { if (c) { - return if (b) null else usize(0); + return if (b) null else @as(usize, 0); } - return usize(3); + return @as(usize, 3); } test "peer type resolution: [0]u8 and []const u8" { @@ -5293,7 +5403,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 { <p> For example, if we were to introduce another function to the above snippet: </p> - {#code_begin|test_err|cannot store runtime value in type 'type'#} + {#code_begin|test_err|values of type 'type' must be comptime known#} fn max(comptime T: type, a: T, b: T) T { return if (a > b) a else b; } @@ -5815,7 +5925,7 @@ test "printf too many arguments" { </p> <p> Zig doesn't care whether the format argument is a string literal, - only that it is a compile-time known value that is implicitly castable to a {#syntax#}[]const u8{#endsyntax#}: + only that it is a compile-time known value that can be coerced to a {#syntax#}[]const u8{#endsyntax#}: </p> {#code_begin|exe|printf#} const warn = @import("std").debug.warn; @@ -6185,7 +6295,7 @@ fn func() void { </p> <p> {#syntax#}await{#endsyntax#} is a suspend point, and takes as an operand anything that - implicitly casts to {#syntax#}anyframe->T{#endsyntax#}. + coerces to {#syntax#}anyframe->T{#endsyntax#}. </p> <p> There is a common misconception that {#syntax#}await{#endsyntax#} resumes the target function. @@ -6445,6 +6555,14 @@ comptime { </p> {#header_close#} + {#header_open|@as#} + <pre>{#syntax#}@as(comptime T: type, expression) T{#endsyntax#}</pre> + <p> + Performs {#link|Type Coercion#}. This cast is allowed when the conversion is unambiguous and safe, + and is the preferred way to convert between types, whenever possible. + </p> + {#header_close#} + {#header_open|@asyncCall#} <pre>{#syntax#}@asyncCall(frame_buffer: []align(@alignOf(@Frame(anyAsyncFunction))) u8, result_ptr, function_ptr, args: ...) anyframe->T{#endsyntax#}</pre> <p> @@ -6493,14 +6611,14 @@ async fn func(y: *i32) void { This builtin function atomically dereferences a pointer and returns the value. </p> <p> - {#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#}, - or an integer whose bit count meets these requirements: + {#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#} + an integer whose bit count meets these requirements: </p> <ul> <li>At least 8</li> <li>At most the same as usize</li> <li>Power of 2</li> - </ul> + </ul> or an enum with a valid integer tag type. <p> TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe we can remove this restriction @@ -6541,6 +6659,25 @@ async fn func(y: *i32) void { <li>{#syntax#}.Min{#endsyntax#} - stores the operand if it is smaller. Supports integers and floats.</li> </ul> {#header_close#} + {#header_open|@atomicStore#} + <pre>{#syntax#}@atomicStore(comptime T: type, ptr: *T, value: T, comptime ordering: builtin.AtomicOrder) void{#endsyntax#}</pre> + <p> + This builtin function atomically stores a value. + </p> + <p> + {#syntax#}T{#endsyntax#} must be a pointer type, a {#syntax#}bool{#endsyntax#} + an integer whose bit count meets these requirements: + </p> + <ul> + <li>At least 8</li> + <li>At most the same as usize</li> + <li>Power of 2</li> + </ul> or an enum with a valid integer tag type. + <p> + TODO right now bool is not accepted. Also I think we could make non powers of 2 work fine, maybe + we can remove this restriction + </p> + {#header_close#} {#header_open|@bitCast#} <pre>{#syntax#}@bitCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre> <p> @@ -7108,7 +7245,7 @@ test "field access by string" { <pre>{#syntax#}@frame() *@Frame(func){#endsyntax#}</pre> <p> This function returns a pointer to the frame for a given function. This type - can be {#link|implicitly cast|Implicit Casts#} to {#syntax#}anyframe->T{#endsyntax#} and + can be {#link|coerced|Type Coercion#} to {#syntax#}anyframe->T{#endsyntax#} and to {#syntax#}anyframe{#endsyntax#}, where {#syntax#}T{#endsyntax#} is the return type of the function in scope. </p> @@ -7827,7 +7964,7 @@ test "vector @splat" { const scalar: u32 = 5; const result = @splat(4, scalar); comptime assert(@typeOf(result) == @Vector(4, u32)); - assert(std.mem.eql(u32, ([4]u32)(result), [_]u32{ 5, 5, 5, 5 })); + assert(std.mem.eql(u32, @as([4]u32, result), [_]u32{ 5, 5, 5, 5 })); } {#code_end#} <p> @@ -8025,7 +8162,7 @@ test "integer truncation" { </p> <p> If {#syntax#}T{#endsyntax#} is {#syntax#}comptime_int{#endsyntax#}, - then this is semantically equivalent to an {#link|implicit cast|Implicit Casts#}. + then this is semantically equivalent to {#link|Type Coercion#}. </p> {#header_close#} @@ -8529,7 +8666,7 @@ pub fn main() void { {#header_close#} {#header_open|Cast Truncates Data#} <p>At compile-time:</p> - {#code_begin|test_err|integer value 300 cannot be implicitly casted to type 'u8'#} + {#code_begin|test_err|integer value 300 cannot be coerced to type 'u8'#} comptime { const spartan_count: u16 = 300; const byte = @intCast(u8, spartan_count); @@ -8665,7 +8802,7 @@ test "wraparound addition and subtraction" { <p>At compile-time:</p> {#code_begin|test_err|operation caused overflow#} comptime { - const x = @shlExact(u8(0b01010101), 2); + const x = @shlExact(@as(u8, 0b01010101), 2); } {#code_end#} <p>At runtime:</p> @@ -8683,7 +8820,7 @@ pub fn main() void { <p>At compile-time:</p> {#code_begin|test_err|exact shift shifted out 1 bits#} comptime { - const x = @shrExact(u8(0b10101010), 2); + const x = @shrExact(@as(u8, 0b10101010), 2); } {#code_end#} <p>At runtime:</p> @@ -9535,8 +9672,8 @@ const c = @cImport({ <p>{#syntax#}[*c]T{#endsyntax#} - C pointer.</p> <ul> <li>Supports all the syntax of the other two pointer types.</li> - <li>Implicitly casts to other pointer types, as well as {#link|Optional Pointers#}. - When a C pointer is implicitly casted to a non-optional pointer, safety-checked + <li>Coerces to other pointer types, as well as {#link|Optional Pointers#}. + When a C pointer is coerced to a non-optional pointer, safety-checked {#link|Undefined Behavior#} occurs if the address is 0. </li> <li>Allows address 0. On non-freestanding targets, dereferencing address 0 is safety-checked @@ -9544,7 +9681,7 @@ const c = @cImport({ null, just like {#syntax#}?usize{#endsyntax#}. Note that creating an optional C pointer is unnecessary as one can use normal {#link|Optional Pointers#}. </li> - <li>Supports {#link|implicit casting|Implicit Casts#} to and from integers.</li> + <li>Supports {#link|Type Coercion#} to and from integers.</li> <li>Supports comparison with integers.</li> <li>Does not support Zig-only pointer attributes such as alignment. Use normal {#link|Pointers#} please!</li> diff --git a/lib/std/array_list.zig b/lib/std/array_list.zig @@ -344,18 +344,18 @@ test "std.ArrayList.orderedRemove" { try list.append(7); //remove from middle - testing.expectEqual(i32(4), list.orderedRemove(3)); - testing.expectEqual(i32(5), list.at(3)); - testing.expectEqual(usize(6), list.len); + testing.expectEqual(@as(i32, 4), list.orderedRemove(3)); + testing.expectEqual(@as(i32, 5), list.at(3)); + testing.expectEqual(@as(usize, 6), list.len); //remove from end - testing.expectEqual(i32(7), list.orderedRemove(5)); - testing.expectEqual(usize(5), list.len); + testing.expectEqual(@as(i32, 7), list.orderedRemove(5)); + testing.expectEqual(@as(usize, 5), list.len); //remove from front - testing.expectEqual(i32(1), list.orderedRemove(0)); - testing.expectEqual(i32(2), list.at(0)); - testing.expectEqual(usize(4), list.len); + testing.expectEqual(@as(i32, 1), list.orderedRemove(0)); + testing.expectEqual(@as(i32, 2), list.at(0)); + testing.expectEqual(@as(usize, 4), list.len); } test "std.ArrayList.swapRemove" { diff --git a/lib/std/ascii.zig b/lib/std/ascii.zig @@ -129,26 +129,26 @@ const combinedTable = init: { comptime var i = 0; inline while (i < 128) : (i += 1) { table[i] = - u8(alpha[i]) << @enumToInt(tIndex.Alpha) | - u8(hex[i]) << @enumToInt(tIndex.Hex) | - u8(space[i]) << @enumToInt(tIndex.Space) | - u8(digit[i]) << @enumToInt(tIndex.Digit) | - u8(lower[i]) << @enumToInt(tIndex.Lower) | - u8(upper[i]) << @enumToInt(tIndex.Upper) | - u8(punct[i]) << @enumToInt(tIndex.Punct) | - u8(graph[i]) << @enumToInt(tIndex.Graph); + @as(u8, alpha[i]) << @enumToInt(tIndex.Alpha) | + @as(u8, hex[i]) << @enumToInt(tIndex.Hex) | + @as(u8, space[i]) << @enumToInt(tIndex.Space) | + @as(u8, digit[i]) << @enumToInt(tIndex.Digit) | + @as(u8, lower[i]) << @enumToInt(tIndex.Lower) | + @as(u8, upper[i]) << @enumToInt(tIndex.Upper) | + @as(u8, punct[i]) << @enumToInt(tIndex.Punct) | + @as(u8, graph[i]) << @enumToInt(tIndex.Graph); } mem.set(u8, table[128..256], 0); break :init table; }; fn inTable(c: u8, t: tIndex) bool { - return (combinedTable[c] & (u8(1) << @enumToInt(t))) != 0; + return (combinedTable[c] & (@as(u8, 1) << @enumToInt(t))) != 0; } pub fn isAlNum(c: u8) bool { - return (combinedTable[c] & ((u8(1) << @enumToInt(tIndex.Alpha)) | - u8(1) << @enumToInt(tIndex.Digit))) != 0; + return (combinedTable[c] & ((@as(u8, 1) << @enumToInt(tIndex.Alpha)) | + @as(u8, 1) << @enumToInt(tIndex.Digit))) != 0; } pub fn isAlpha(c: u8) bool { diff --git a/lib/std/atomic/queue.zig b/lib/std/atomic/queue.zig @@ -199,7 +199,7 @@ test "std.atomic.Queue" { for (putters) |t| t.wait(); - _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst); + @atomicStore(u8, &context.puts_done, 1, AtomicOrder.SeqCst); for (getters) |t| t.wait(); @@ -214,8 +214,8 @@ test "std.atomic.Queue" { std.debug.panic( "failure\nget_count:{} != puts_per_thread:{} * put_thread_count:{}", context.get_count, - u32(puts_per_thread), - u32(put_thread_count), + @as(u32, puts_per_thread), + @as(u32, put_thread_count), ); } } diff --git a/lib/std/atomic/stack.zig b/lib/std/atomic/stack.zig @@ -11,7 +11,7 @@ pub fn Stack(comptime T: type) type { root: ?*Node, lock: @typeOf(lock_init), - const lock_init = if (builtin.single_threaded) {} else u8(0); + const lock_init = if (builtin.single_threaded) {} else @as(u8, 0); pub const Self = @This(); @@ -128,7 +128,7 @@ test "std.atomic.stack" { for (putters) |t| t.wait(); - _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst); + @atomicStore(u8, &context.puts_done, 1, AtomicOrder.SeqCst); for (getters) |t| t.wait(); } @@ -141,8 +141,8 @@ test "std.atomic.stack" { std.debug.panic( "failure\nget_count:{} != puts_per_thread:{} * put_thread_count:{}", context.get_count, - u32(puts_per_thread), - u32(put_thread_count), + @as(u32, puts_per_thread), + @as(u32, put_thread_count), ); } } diff --git a/lib/std/bloom_filter.zig b/lib/std/bloom_filter.zig @@ -28,7 +28,7 @@ pub fn BloomFilter( assert(n_items > 0); assert(math.isPowerOfTwo(n_items)); assert(K > 0); - const cellEmpty = if (Cell == bool) false else Cell(0); + const cellEmpty = if (Cell == bool) false else @as(Cell, 0); const cellMax = if (Cell == bool) true else math.maxInt(Cell); const n_bytes = (n_items * comptime std.meta.bitCount(Cell)) / 8; assert(n_bytes > 0); @@ -137,7 +137,7 @@ pub fn BloomFilter( var i: usize = 0; while (i < n_items) : (i += 1) { const cell = self.getCell(@intCast(Index, i)); - n += if (if (Cell == bool) cell else cell > 0) Index(1) else Index(0); + n += if (if (Cell == bool) cell else cell > 0) @as(Index, 1) else @as(Index, 0); } } return n; @@ -161,7 +161,7 @@ fn hashFunc(out: []u8, Ki: usize, in: []const u8) void { test "std.BloomFilter" { inline for ([_]type{ bool, u1, u2, u3, u4 }) |Cell| { - const emptyCell = if (Cell == bool) false else Cell(0); + const emptyCell = if (Cell == bool) false else @as(Cell, 0); const BF = BloomFilter(128 * 8, 8, Cell, builtin.endian, hashFunc); var bf = BF{}; var i: usize = undefined; @@ -170,8 +170,8 @@ test "std.BloomFilter" { while (i < BF.items) : (i += 1) { testing.expectEqual(emptyCell, bf.getCell(@intCast(BF.Index, i))); } - testing.expectEqual(BF.Index(0), bf.popCount()); - testing.expectEqual(f64(0), bf.estimateItems()); + testing.expectEqual(@as(BF.Index, 0), bf.popCount()); + testing.expectEqual(@as(f64, 0), bf.estimateItems()); // fill in a few items bf.incrementCell(42); bf.incrementCell(255); @@ -196,8 +196,8 @@ test "std.BloomFilter" { while (i < BF.items) : (i += 1) { testing.expectEqual(emptyCell, bf.getCell(@intCast(BF.Index, i))); } - testing.expectEqual(BF.Index(0), bf.popCount()); - testing.expectEqual(f64(0), bf.estimateItems()); + testing.expectEqual(@as(BF.Index, 0), bf.popCount()); + testing.expectEqual(@as(f64, 0), bf.estimateItems()); // Lets add a string bf.add("foo"); @@ -218,8 +218,8 @@ test "std.BloomFilter" { while (i < BF.items) : (i += 1) { testing.expectEqual(emptyCell, bf.getCell(@intCast(BF.Index, i))); } - testing.expectEqual(BF.Index(0), bf.popCount()); - testing.expectEqual(f64(0), bf.estimateItems()); + testing.expectEqual(@as(BF.Index, 0), bf.popCount()); + testing.expectEqual(@as(f64, 0), bf.estimateItems()); comptime var teststrings = [_][]const u8{ "foo", @@ -246,12 +246,12 @@ test "std.BloomFilter" { inline for (teststrings) |str| { testing.expectEqual(true, larger_bf.contains(str)); } - testing.expectEqual(u12(bf.popCount()) * (4096 / 1024), larger_bf.popCount()); + testing.expectEqual(@as(u12, bf.popCount()) * (4096 / 1024), larger_bf.popCount()); const smaller_bf = bf.resize(64); inline for (teststrings) |str| { testing.expectEqual(true, smaller_bf.contains(str)); } - testing.expect(bf.popCount() <= u10(smaller_bf.popCount()) * (1024 / 64)); + testing.expect(bf.popCount() <= @as(u10, smaller_bf.popCount()) * (1024 / 64)); } } diff --git a/lib/std/build.zig b/lib/std/build.zig @@ -53,7 +53,7 @@ pub const Builder = struct { release_mode: ?builtin.Mode, is_release: bool, override_lib_dir: ?[]const u8, - + vcpkg_root: VcpkgRoot, pkg_config_pkg_list: ?(PkgConfigError![]const PkgConfigPkg) = null, const PkgConfigError = error{ @@ -159,6 +159,7 @@ pub const Builder = struct { .is_release = false, .override_lib_dir = null, .install_path = undefined, + .vcpkg_root = VcpkgRoot{ .Unattempted = {} }, }; try self.top_level_steps.append(&self.install_tls); try self.top_level_steps.append(&self.uninstall_tls); @@ -957,6 +958,7 @@ pub const Builder = struct { error.ProcessTerminated => error.PkgConfigCrashed, error.ExitCodeFailure => error.PkgConfigFailed, error.FileNotFound => error.PkgConfigNotInstalled, + error.InvalidName => error.PkgConfigNotInstalled, error.PkgConfigInvalidOutput => error.PkgConfigInvalidOutput, else => return err, }; @@ -1046,6 +1048,7 @@ pub const LibExeObjStep = struct { output_dir: ?[]const u8, need_system_paths: bool, is_linking_libc: bool = false, + vcpkg_bin_path: ?[]const u8 = null, installed_path: ?[]const u8, install_step: ?*InstallArtifactStep, @@ -1264,6 +1267,11 @@ pub const LibExeObjStep = struct { // option is supplied. const run_step = RunStep.create(exe.builder, exe.builder.fmt("run {}", exe.step.name)); run_step.addArtifactArg(exe); + + if (exe.vcpkg_bin_path) |path| { + run_step.addPathDir(path); + } + return run_step; } @@ -1569,6 +1577,43 @@ pub const LibExeObjStep = struct { }) catch unreachable; } + /// If Vcpkg was found on the system, it will be added to include and lib + /// paths for the specified target. + pub fn addVcpkgPaths(self: *LibExeObjStep, linkage: VcpkgLinkage) !void { + // Ideally in the Unattempted case we would call the function recursively + // after findVcpkgRoot and have only one switch statement, but the compiler + // cannot resolve the error set. + switch (self.builder.vcpkg_root) { + .Unattempted => { + self.builder.vcpkg_root = if (try findVcpkgRoot(self.builder.allocator)) |root| + VcpkgRoot{ .Found = root } + else + .NotFound; + }, + .NotFound => return error.VcpkgNotFound, + .Found => {}, + } + + switch (self.builder.vcpkg_root) { + .Unattempted => unreachable, + .NotFound => return error.VcpkgNotFound, + .Found => |root| { + const allocator = self.builder.allocator; + const triplet = try Target.vcpkgTriplet(allocator, self.target, linkage); + defer self.builder.allocator.free(triplet); + + const include_path = try fs.path.join(allocator, [_][]const u8{ root, "installed", triplet, "include" }); + errdefer allocator.free(include_path); + try self.include_dirs.append(IncludeDir{ .RawPath = include_path }); + + const lib_path = try fs.path.join(allocator, [_][]const u8{ root, "installed", triplet, "lib" }); + try self.lib_paths.append(lib_path); + + self.vcpkg_bin_path = try fs.path.join(allocator, [_][]const u8{ root, "installed", triplet, "bin" }); + }, + } + } + pub fn setExecCmd(self: *LibExeObjStep, args: []const ?[]const u8) void { assert(self.kind == Kind.Test); self.exec_cmd_args = args; @@ -2341,6 +2386,42 @@ fn doAtomicSymLinks(allocator: *Allocator, output_path: []const u8, filename_maj }; } +/// Returned slice must be freed by the caller. +fn findVcpkgRoot(allocator: *Allocator) !?[]const u8 { + const appdata_path = try fs.getAppDataDir(allocator, "vcpkg"); + defer allocator.free(appdata_path); + + const path_file = try fs.path.join(allocator, [_][]const u8{ appdata_path, "vcpkg.path.txt" }); + defer allocator.free(path_file); + + const file = fs.File.openRead(path_file) catch return null; + defer file.close(); + + const size = @intCast(usize, try file.getEndPos()); + const vcpkg_path = try allocator.alloc(u8, size); + const size_read = try file.read(vcpkg_path); + std.debug.assert(size == size_read); + + return vcpkg_path; +} + +const VcpkgRoot = union(VcpkgRootStatus) { + Unattempted: void, + NotFound: void, + Found: []const u8, +}; + +const VcpkgRootStatus = enum { + Unattempted, + NotFound, + Found, +}; + +pub const VcpkgLinkage = enum { + Static, + Dynamic, +}; + pub const InstallDir = enum { Prefix, Lib, diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig @@ -90,40 +90,11 @@ pub const Mode = enum { ReleaseSmall, }; -/// This data structure is used by the Zig language code generation and -/// therefore must be kept in sync with the compiler implementation. -pub const TypeId = enum { - Type, - Void, - Bool, - NoReturn, - Int, - Float, - Pointer, - Array, - Struct, - ComptimeFloat, - ComptimeInt, - Undefined, - Null, - Optional, - ErrorUnion, - ErrorSet, - Enum, - Union, - Fn, - BoundFn, - ArgTuple, - Opaque, - Frame, - AnyFrame, - Vector, - EnumLiteral, -}; +pub const TypeId = @TagType(TypeInfo); /// This data structure is used by the Zig language code generation and /// therefore must be kept in sync with the compiler implementation. -pub const TypeInfo = union(TypeId) { +pub const TypeInfo = union(enum) { Type: void, Void: void, Bool: void, diff --git a/lib/std/c.zig b/lib/std/c.zig @@ -8,9 +8,16 @@ pub usingnamespace switch (builtin.os) { .linux => @import("c/linux.zig"), .windows => @import("c/windows.zig"), .macosx, .ios, .tvos, .watchos => @import("c/darwin.zig"), - .freebsd => @import("c/freebsd.zig"), + .freebsd, .kfreebsd => @import("c/freebsd.zig"), .netbsd => @import("c/netbsd.zig"), .dragonfly => @import("c/dragonfly.zig"), + .openbsd => @import("c/openbsd.zig"), + .haiku => @import("c/haiku.zig"), + .hermit => @import("c/hermit.zig"), + .solaris => @import("c/solaris.zig"), + .fuchsia => @import("c/fuchsia.zig"), + .minix => @import("c/minix.zig"), + .emscripten => @import("c/emscripten.zig"), else => struct {}, }; @@ -203,3 +210,18 @@ pub extern "c" fn dn_expand( exp_dn: [*]u8, length: c_int, ) c_int; + +pub extern "c" fn sched_yield() c_int; + +pub const PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t{}; +pub extern "c" fn pthread_mutex_lock(mutex: *pthread_mutex_t) c_int; +pub extern "c" fn pthread_mutex_unlock(mutex: *pthread_mutex_t) c_int; +pub extern "c" fn pthread_mutex_destroy(mutex: *pthread_mutex_t) c_int; + +pub const PTHREAD_COND_INITIALIZER = pthread_cond_t{}; +pub extern "c" fn pthread_cond_wait(noalias cond: *pthread_cond_t, noalias mutex: *pthread_mutex_t) c_int; +pub extern "c" fn pthread_cond_signal(cond: *pthread_cond_t) c_int; +pub extern "c" fn pthread_cond_destroy(cond: *pthread_cond_t) c_int; + +pub const pthread_t = *@OpaqueType(); +pub const FILE = @OpaqueType(); diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig @@ -53,7 +53,7 @@ pub extern "c" fn host_get_clock_service(host: host_t, clock_id: clock_id_t, clo pub extern "c" fn mach_port_deallocate(task: ipc_space_t, name: mach_port_name_t) kern_return_t; pub fn sigaddset(set: *sigset_t, signo: u5) void { - set.* |= u32(1) << (signo - 1); + set.* |= @as(u32, 1) << (signo - 1); } pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; @@ -112,3 +112,19 @@ pub const EAI_PROTOCOL = 13; /// argument buffer overflow pub const EAI_OVERFLOW = 14; pub const EAI_MAX = 15; + +pub const pthread_mutex_t = extern struct { + __sig: c_long = 0x32AAABA7, + __opaque: [__PTHREAD_MUTEX_SIZE__]u8 = [_]u8{0} ** __PTHREAD_MUTEX_SIZE__, +}; +pub const pthread_cond_t = extern struct { + __sig: c_long = 0x3CB0B1BB, + __opaque: [__PTHREAD_COND_SIZE__]u8 = [_]u8{0} ** __PTHREAD_COND_SIZE__, +}; +const __PTHREAD_MUTEX_SIZE__ = if (@sizeOf(usize) == 8) 56 else 40; +const __PTHREAD_COND_SIZE__ = if (@sizeOf(usize) == 8) 40 else 24; + +pub const pthread_attr_t = extern struct { + __sig: c_long, + __opaque: [56]u8, +}; diff --git a/lib/std/c/dragonfly.zig b/lib/std/c/dragonfly.zig @@ -1,6 +1,5 @@ const std = @import("../std.zig"); usingnamespace std.c; - extern "c" threadlocal var errno: c_int; pub fn _errno() *c_int { return &errno; @@ -12,3 +11,15 @@ pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize pub const dl_iterate_phdr_callback = extern fn (info: *dl_phdr_info, size: usize, data: ?*c_void) c_int; pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int; + +pub const pthread_mutex_t = extern struct { + inner: ?*c_void = null, +}; +pub const pthread_cond_t = extern struct { + inner: ?*c_void = null, +}; + +pub const pthread_attr_t = extern struct { // copied from freebsd + __size: [56]u8, + __align: c_long, +}; diff --git a/lib/std/c/emscripten.zig b/lib/std/c/emscripten.zig @@ -0,0 +1,8 @@ +pub const pthread_mutex_t = extern struct { + size: [__SIZEOF_PTHREAD_MUTEX_T]u8 align(4) = [_]u8{0} ** __SIZEOF_PTHREAD_MUTEX_T, +}; +pub const pthread_cond_t = extern struct { + size: [__SIZEOF_PTHREAD_COND_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_COND_T, +}; +const __SIZEOF_PTHREAD_COND_T = 48; +const __SIZEOF_PTHREAD_MUTEX_T = 28; diff --git a/lib/std/c/freebsd.zig b/lib/std/c/freebsd.zig @@ -10,3 +10,15 @@ pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize pub const dl_iterate_phdr_callback = extern fn (info: *dl_phdr_info, size: usize, data: ?*c_void) c_int; pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int; + +pub const pthread_mutex_t = extern struct { + inner: ?*c_void = null, +}; +pub const pthread_cond_t = extern struct { + inner: ?*c_void = null, +}; + +pub const pthread_attr_t = extern struct { + __size: [56]u8, + __align: c_long, +}; diff --git a/lib/std/c/fuchsia.zig b/lib/std/c/fuchsia.zig @@ -0,0 +1,8 @@ +pub const pthread_mutex_t = extern struct { + size: [__SIZEOF_PTHREAD_MUTEX_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_MUTEX_T, +}; +pub const pthread_cond_t = extern struct { + size: [__SIZEOF_PTHREAD_COND_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_COND_T, +}; +const __SIZEOF_PTHREAD_COND_T = 48; +const __SIZEOF_PTHREAD_MUTEX_T = 40; diff --git a/lib/std/c/haiku.zig b/lib/std/c/haiku.zig @@ -0,0 +1,14 @@ +pub const pthread_mutex_t = extern struct { + flags: u32 = 0, + lock: i32 = 0, + unused: i32 = -42, + owner: i32 = -1, + owner_count: i32 = 0, +}; +pub const pthread_cond_t = extern struct { + flags: u32 = 0, + unused: i32 = -42, + mutex: ?*c_void = null, + waiter_count: i32 = 0, + lock: i32 = 0, +}; diff --git a/lib/std/c/hermit.zig b/lib/std/c/hermit.zig @@ -0,0 +1,6 @@ +pub const pthread_mutex_t = extern struct { + inner: usize = ~usize(0), +}; +pub const pthread_cond_t = extern struct { + inner: usize = ~usize(0), +}; diff --git a/lib/std/c/linux.zig b/lib/std/c/linux.zig @@ -75,3 +75,26 @@ pub const dl_iterate_phdr_callback = extern fn (info: *dl_phdr_info, size: usize pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int; pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; + +pub const pthread_attr_t = extern struct { + __size: [56]u8, + __align: c_long, +}; + +pub const pthread_mutex_t = extern struct { + size: [__SIZEOF_PTHREAD_MUTEX_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_MUTEX_T, +}; +pub const pthread_cond_t = extern struct { + size: [__SIZEOF_PTHREAD_COND_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_COND_T, +}; +const __SIZEOF_PTHREAD_COND_T = 48; +const __SIZEOF_PTHREAD_MUTEX_T = if (builtin.os == .fuchsia) 40 else switch (builtin.abi) { + .musl, .musleabi, .musleabihf => if (@sizeOf(usize) == 8) 40 else 24, + .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => switch (builtin.arch) { + .aarch64 => 48, + .x86_64 => if (builtin.abi == .gnux32) 40 else 32, + .mips64, .powerpc64, .powerpc64le, .sparcv9 => 40, + else => if (@sizeOf(usize) == 8) 40 else 24, + }, + else => unreachable, +}; diff --git a/lib/std/c/minix.zig b/lib/std/c/minix.zig @@ -0,0 +1,18 @@ +const builtin = @import("builtin"); +pub const pthread_mutex_t = extern struct { + size: [__SIZEOF_PTHREAD_MUTEX_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_MUTEX_T, +}; +pub const pthread_cond_t = extern struct { + size: [__SIZEOF_PTHREAD_COND_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_COND_T, +}; +const __SIZEOF_PTHREAD_COND_T = 48; +const __SIZEOF_PTHREAD_MUTEX_T = switch (builtin.abi) { + .musl, .musleabi, .musleabihf => if (@sizeOf(usize) == 8) 40 else 24, + .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => switch (builtin.arch) { + .aarch64 => 48, + .x86_64 => if (builtin.abi == .gnux32) 40 else 32, + .mips64, .powerpc64, .powerpc64le, .sparcv9 => 40, + else => if (@sizeOf(usize) == 8) 40 else 24, + }, + else => unreachable, +}; diff --git a/lib/std/c/netbsd.zig b/lib/std/c/netbsd.zig @@ -6,3 +6,32 @@ pub const _errno = __errno; pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) usize; pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; + +pub const pthread_mutex_t = extern struct { + ptm_magic: c_uint = 0x33330003, + ptm_errorcheck: padded_spin_t = 0, + ptm_unused: padded_spin_t = 0, + ptm_owner: usize = 0, + ptm_waiters: ?*u8 = null, + ptm_recursed: c_uint = 0, + ptm_spare2: ?*c_void = null, +}; +pub const pthread_cond_t = extern struct { + ptc_magic: c_uint = 0x55550005, + ptc_lock: pthread_spin_t = 0, + ptc_waiters_first: ?*u8 = null, + ptc_waiters_last: ?*u8 = null, + ptc_mutex: ?*pthread_mutex_t = null, + ptc_private: ?*c_void = null, +}; +const pthread_spin_t = if (builtin.arch == .arm or .arch == .powerpc) c_int else u8; +const padded_spin_t = switch (builtin.arch) { + .sparc, .sparcel, .sparcv9, .i386, .x86_64, .le64 => u32, + else => spin_t, +}; + +pub const pthread_attr_t = extern struct { + pta_magic: u32, + pta_flags: c_int, + pta_private: *c_void, +}; diff --git a/lib/std/c/openbsd.zig b/lib/std/c/openbsd.zig @@ -0,0 +1,6 @@ +pub const pthread_mutex_t = extern struct { + inner: ?*c_void = null, +}; +pub const pthread_cond_t = extern struct { + inner: ?*c_void = null, +}; diff --git a/lib/std/c/solaris.zig b/lib/std/c/solaris.zig @@ -0,0 +1,15 @@ +pub const pthread_mutex_t = extern struct { + __pthread_mutex_flag1: u16 = 0, + __pthread_mutex_flag2: u8 = 0, + __pthread_mutex_ceiling: u8 = 0, + __pthread_mutex_type: u16 = 0, + __pthread_mutex_magic: u16 = 0x4d58, + __pthread_mutex_lock: u64 = 0, + __pthread_mutex_data: u64 = 0, +}; +pub const pthread_cond_t = extern struct { + __pthread_cond_flag: u32 = 0, + __pthread_cond_type: u16 = 0, + __pthread_cond_magic: u16 = 0x4356, + __pthread_cond_data: u64 = 0, +}; diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig @@ -50,8 +50,20 @@ pub const ChildProcess = struct { err_pipe: if (builtin.os == .windows) void else [2]os.fd_t, llnode: if (builtin.os == .windows) void else TailQueue(*ChildProcess).Node, - pub const SpawnError = error{OutOfMemory} || os.ExecveError || os.SetIdError || - os.ChangeCurDirError || windows.CreateProcessError; + pub const SpawnError = error{ + OutOfMemory, + + /// POSIX-only. `StdIo.Ignore` was selected and opening `/dev/null` returned ENODEV. + NoDevice, + + /// Windows-only. One of: + /// * `cwd` was provided and it could not be re-encoded into UTF16LE, or + /// * The `PATH` or `PATHEXT` environment variable contained invalid UTF-8. + InvalidUtf8, + + /// Windows-only. `cwd` was provided, but the path did not exist when spawning the child process. + CurrentWorkingDirectoryUnlinked, + } || os.ExecveError || os.SetIdError || os.ChangeCurDirError || windows.CreateProcessError || windows.WaitForSingleObjectError; pub const Term = union(enum) { Exited: u32, @@ -102,7 +114,7 @@ pub const ChildProcess = struct { } /// On success must call `kill` or `wait`. - pub fn spawn(self: *ChildProcess) !void { + pub fn spawn(self: *ChildProcess) SpawnError!void { if (builtin.os == .windows) { return self.spawnWindows(); } else { @@ -110,7 +122,7 @@ pub const ChildProcess = struct { } } - pub fn spawnAndWait(self: *ChildProcess) !Term { + pub fn spawnAndWait(self: *ChildProcess) SpawnError!Term { try self.spawn(); return self.wait(); } @@ -162,7 +174,13 @@ pub const ChildProcess = struct { /// Spawns a child process, waits for it, collecting stdout and stderr, and then returns. /// If it succeeds, the caller owns result.stdout and result.stderr memory. - pub fn exec(allocator: *mem.Allocator, argv: []const []const u8, cwd: ?[]const u8, env_map: ?*const BufMap, max_output_size: usize) !ExecResult { + pub fn exec( + allocator: *mem.Allocator, + argv: []const []const u8, + cwd: ?[]const u8, + env_map: ?*const BufMap, + max_output_size: usize, + ) !ExecResult { const child = try ChildProcess.init(argv, allocator); defer child.deinit(); @@ -219,7 +237,7 @@ pub const ChildProcess = struct { fn waitUnwrappedWindows(self: *ChildProcess) !void { const result = windows.WaitForSingleObject(self.handle, windows.INFINITE); - self.term = (SpawnError!Term)(x: { + self.term = @as(SpawnError!Term, x: { var exit_code: windows.DWORD = undefined; if (windows.kernel32.GetExitCodeProcess(self.handle, &exit_code) == 0) { break :x Term{ .Unknown = 0 }; @@ -292,7 +310,7 @@ pub const ChildProcess = struct { Term{ .Unknown = status }; } - fn spawnPosix(self: *ChildProcess) !void { + fn spawnPosix(self: *ChildProcess) SpawnError!void { const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try os.pipe() else undefined; errdefer if (self.stdin_behavior == StdIo.Pipe) { destroyPipe(stdin_pipe); @@ -309,7 +327,16 @@ pub const ChildProcess = struct { }; const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore); - const dev_null_fd = if (any_ignore) try os.openC(c"/dev/null", os.O_RDWR, 0) else undefined; + const dev_null_fd = if (any_ignore) + os.openC(c"/dev/null", os.O_RDWR, 0) catch |err| switch (err) { + error.PathAlreadyExists => unreachable, + error.NoSpaceLeft => unreachable, + error.FileTooBig => unreachable, + error.DeviceBusy => unreachable, + else => |e| return e, + } + else + undefined; defer { if (any_ignore) os.close(dev_null_fd); } @@ -403,7 +430,7 @@ pub const ChildProcess = struct { } } - fn spawnWindows(self: *ChildProcess) !void { + fn spawnWindows(self: *ChildProcess) SpawnError!void { const saAttr = windows.SECURITY_ATTRIBUTES{ .nLength = @sizeOf(windows.SECURITY_ATTRIBUTES), .bInheritHandle = windows.TRUE, @@ -412,11 +439,28 @@ pub const ChildProcess = struct { const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore); - const nul_handle = if (any_ignore) blk: { - break :blk try windows.CreateFile("NUL", windows.GENERIC_READ, windows.FILE_SHARE_READ, null, windows.OPEN_EXISTING, windows.FILE_ATTRIBUTE_NORMAL, null); - } else blk: { - break :blk undefined; - }; + const nul_handle = if (any_ignore) + windows.CreateFile( + "NUL", + windows.GENERIC_READ, + windows.FILE_SHARE_READ, + null, + windows.OPEN_EXISTING, + windows.FILE_ATTRIBUTE_NORMAL, + null, + ) catch |err| switch (err) { + error.SharingViolation => unreachable, // not possible for "NUL" + error.PathAlreadyExists => unreachable, // not possible for "NUL" + error.PipeBusy => unreachable, // not possible for "NUL" + error.InvalidUtf8 => unreachable, // not possible for "NUL" + error.BadPathName => unreachable, // not possible for "NUL" + error.FileNotFound => unreachable, // not possible for "NUL" + error.AccessDenied => unreachable, // not possible for "NUL" + error.NameTooLong => unreachable, // not possible for "NUL" + else => |e| return e, + } + else + undefined; defer { if (any_ignore) os.close(nul_handle); } @@ -542,10 +586,25 @@ pub const ChildProcess = struct { windowsCreateProcess(app_name_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_w_ptr, &siStartInfo, &piProcInfo) catch |no_path_err| { if (no_path_err != error.FileNotFound) return no_path_err; - const PATH = try process.getEnvVarOwned(self.allocator, "PATH"); - defer self.allocator.free(PATH); - const PATHEXT = try process.getEnvVarOwned(self.allocator, "PATHEXT"); - defer self.allocator.free(PATHEXT); + var free_path = true; + const PATH = process.getEnvVarOwned(self.allocator, "PATH") catch |err| switch (err) { + error.EnvironmentVariableNotFound => blk: { + free_path = false; + break :blk ""; + }, + else => |e| return e, + }; + defer if (free_path) self.allocator.free(PATH); + + var free_path_ext = true; + const PATHEXT = process.getEnvVarOwned(self.allocator, "PATHEXT") catch |err| switch (err) { + error.EnvironmentVariableNotFound => blk: { + free_path_ext = false; + break :blk ""; + }, + else => |e| return e, + }; + defer if (free_path_ext) self.allocator.free(PATHEXT); var it = mem.tokenize(PATH, ";"); retry: while (it.next()) |search_path| { @@ -717,7 +776,7 @@ fn destroyPipe(pipe: [2]os.fd_t) void { // Child of fork calls this to report an error to the fork parent. // Then the child exits. fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn { - writeIntFd(fd, ErrInt(@errorToInt(err))) catch {}; + writeIntFd(fd, @as(ErrInt, @errorToInt(err))) catch {}; os.exit(1); } diff --git a/lib/std/coff.zig b/lib/std/coff.zig @@ -179,7 +179,7 @@ pub const Coff = struct { if (byte != 0 and i == buffer.len) return error.NameTooLong; - return i; + return @as(usize, i); } pub fn loadSections(self: *Coff) !void { diff --git a/lib/std/crypto/aes.zig b/lib/std/crypto/aes.zig @@ -6,7 +6,7 @@ const testing = std.testing; // Apply sbox0 to each byte in w. fn subw(w: u32) u32 { - return u32(sbox0[w >> 24]) << 24 | u32(sbox0[w >> 16 & 0xff]) << 16 | u32(sbox0[w >> 8 & 0xff]) << 8 | u32(sbox0[w & 0xff]); + return @as(u32, sbox0[w >> 24]) << 24 | @as(u32, sbox0[w >> 16 & 0xff]) << 16 | @as(u32, sbox0[w >> 8 & 0xff]) << 8 | @as(u32, sbox0[w & 0xff]); } fn rotw(w: u32) u32 { @@ -48,10 +48,10 @@ fn encryptBlock(xk: []const u32, dst: []u8, src: []const u8) void { } // Last round uses s-box directly and XORs to produce output. - s0 = u32(sbox0[t0 >> 24]) << 24 | u32(sbox0[t1 >> 16 & 0xff]) << 16 | u32(sbox0[t2 >> 8 & 0xff]) << 8 | u32(sbox0[t3 & 0xff]); - s1 = u32(sbox0[t1 >> 24]) << 24 | u32(sbox0[t2 >> 16 & 0xff]) << 16 | u32(sbox0[t3 >> 8 & 0xff]) << 8 | u32(sbox0[t0 & 0xff]); - s2 = u32(sbox0[t2 >> 24]) << 24 | u32(sbox0[t3 >> 16 & 0xff]) << 16 | u32(sbox0[t0 >> 8 & 0xff]) << 8 | u32(sbox0[t1 & 0xff]); - s3 = u32(sbox0[t3 >> 24]) << 24 | u32(sbox0[t0 >> 16 & 0xff]) << 16 | u32(sbox0[t1 >> 8 & 0xff]) << 8 | u32(sbox0[t2 & 0xff]); + s0 = @as(u32, sbox0[t0 >> 24]) << 24 | @as(u32, sbox0[t1 >> 16 & 0xff]) << 16 | @as(u32, sbox0[t2 >> 8 & 0xff]) << 8 | @as(u32, sbox0[t3 & 0xff]); + s1 = @as(u32, sbox0[t1 >> 24]) << 24 | @as(u32, sbox0[t2 >> 16 & 0xff]) << 16 | @as(u32, sbox0[t3 >> 8 & 0xff]) << 8 | @as(u32, sbox0[t0 & 0xff]); + s2 = @as(u32, sbox0[t2 >> 24]) << 24 | @as(u32, sbox0[t3 >> 16 & 0xff]) << 16 | @as(u32, sbox0[t0 >> 8 & 0xff]) << 8 | @as(u32, sbox0[t1 & 0xff]); + s3 = @as(u32, sbox0[t3 >> 24]) << 24 | @as(u32, sbox0[t0 >> 16 & 0xff]) << 16 | @as(u32, sbox0[t1 >> 8 & 0xff]) << 8 | @as(u32, sbox0[t2 & 0xff]); s0 ^= xk[k + 0]; s1 ^= xk[k + 1]; @@ -99,10 +99,10 @@ pub fn decryptBlock(xk: []const u32, dst: []u8, src: []const u8) void { } // Last round uses s-box directly and XORs to produce output. - s0 = u32(sbox1[t0 >> 24]) << 24 | u32(sbox1[t3 >> 16 & 0xff]) << 16 | u32(sbox1[t2 >> 8 & 0xff]) << 8 | u32(sbox1[t1 & 0xff]); - s1 = u32(sbox1[t1 >> 24]) << 24 | u32(sbox1[t0 >> 16 & 0xff]) << 16 | u32(sbox1[t3 >> 8 & 0xff]) << 8 | u32(sbox1[t2 & 0xff]); - s2 = u32(sbox1[t2 >> 24]) << 24 | u32(sbox1[t1 >> 16 & 0xff]) << 16 | u32(sbox1[t0 >> 8 & 0xff]) << 8 | u32(sbox1[t3 & 0xff]); - s3 = u32(sbox1[t3 >> 24]) << 24 | u32(sbox1[t2 >> 16 & 0xff]) << 16 | u32(sbox1[t1 >> 8 & 0xff]) << 8 | u32(sbox1[t0 & 0xff]); + s0 = @as(u32, sbox1[t0 >> 24]) << 24 | @as(u32, sbox1[t3 >> 16 & 0xff]) << 16 | @as(u32, sbox1[t2 >> 8 & 0xff]) << 8 | @as(u32, sbox1[t1 & 0xff]); + s1 = @as(u32, sbox1[t1 >> 24]) << 24 | @as(u32, sbox1[t0 >> 16 & 0xff]) << 16 | @as(u32, sbox1[t3 >> 8 & 0xff]) << 8 | @as(u32, sbox1[t2 & 0xff]); + s2 = @as(u32, sbox1[t2 >> 24]) << 24 | @as(u32, sbox1[t1 >> 16 & 0xff]) << 16 | @as(u32, sbox1[t0 >> 8 & 0xff]) << 8 | @as(u32, sbox1[t3 & 0xff]); + s3 = @as(u32, sbox1[t3 >> 24]) << 24 | @as(u32, sbox1[t2 >> 16 & 0xff]) << 16 | @as(u32, sbox1[t1 >> 8 & 0xff]) << 8 | @as(u32, sbox1[t0 & 0xff]); s0 ^= xk[k + 0]; s1 ^= xk[k + 1]; @@ -256,7 +256,7 @@ fn expandKey(key: []const u8, enc: []u32, dec: []u32) void { while (i < enc.len) : (i += 1) { var t = enc[i - 1]; if (i % nk == 0) { - t = subw(rotw(t)) ^ (u32(powx[i / nk - 1]) << 24); + t = subw(rotw(t)) ^ (@as(u32, powx[i / nk - 1]) << 24); } else if (nk > 6 and i % nk == 4) { t = subw(t); } diff --git a/lib/std/crypto/benchmark.zig b/lib/std/crypto/benchmark.zig @@ -131,9 +131,7 @@ fn printPad(stdout: var, s: []const u8) !void { } pub fn main() !void { - var stdout_file = try std.io.getStdOut(); - var stdout_out_stream = stdout_file.outStream(); - const stdout = &stdout_out_stream.stream; + const stdout = &std.io.getStdOut().outStream().stream; var buffer: [1024]u8 = undefined; var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]); diff --git a/lib/std/crypto/blake2.zig b/lib/std/crypto/blake2.zig @@ -164,13 +164,13 @@ fn Blake2s(comptime out_len: usize) type { inline while (j < 10) : (j += 1) { inline for (rounds) |r| { v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]]; - v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(16)); + v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], @as(usize, 16)); v[r.c] = v[r.c] +% v[r.d]; - v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(12)); + v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], @as(usize, 12)); v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]]; - v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], usize(8)); + v[r.d] = math.rotr(u32, v[r.d] ^ v[r.a], @as(usize, 8)); v[r.c] = v[r.c] +% v[r.d]; - v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], usize(7)); + v[r.b] = math.rotr(u32, v[r.b] ^ v[r.c], @as(usize, 7)); } } @@ -398,13 +398,13 @@ fn Blake2b(comptime out_len: usize) type { inline while (j < 12) : (j += 1) { inline for (rounds) |r| { v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.x]]; - v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(32)); + v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], @as(usize, 32)); v[r.c] = v[r.c] +% v[r.d]; - v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(24)); + v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], @as(usize, 24)); v[r.a] = v[r.a] +% v[r.b] +% m[sigma[j][r.y]]; - v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], usize(16)); + v[r.d] = math.rotr(u64, v[r.d] ^ v[r.a], @as(usize, 16)); v[r.c] = v[r.c] +% v[r.d]; - v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], usize(63)); + v[r.b] = math.rotr(u64, v[r.b] ^ v[r.c], @as(usize, 63)); } } diff --git a/lib/std/crypto/chacha20.zig b/lib/std/crypto/chacha20.zig @@ -49,13 +49,13 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void { // two-round cycles inline for (rounds) |r| { x[r.a] +%= x[r.b]; - x[r.d] = std.math.rotl(u32, x[r.d] ^ x[r.a], u32(16)); + x[r.d] = std.math.rotl(u32, x[r.d] ^ x[r.a], @as(u32, 16)); x[r.c] +%= x[r.d]; - x[r.b] = std.math.rotl(u32, x[r.b] ^ x[r.c], u32(12)); + x[r.b] = std.math.rotl(u32, x[r.b] ^ x[r.c], @as(u32, 12)); x[r.a] +%= x[r.b]; - x[r.d] = std.math.rotl(u32, x[r.d] ^ x[r.a], u32(8)); + x[r.d] = std.math.rotl(u32, x[r.d] ^ x[r.a], @as(u32, 8)); x[r.c] +%= x[r.d]; - x[r.b] = std.math.rotl(u32, x[r.b] ^ x[r.c], u32(7)); + x[r.b] = std.math.rotl(u32, x[r.b] ^ x[r.c], @as(u32, 7)); } } diff --git a/lib/std/crypto/gimli.zig b/lib/std/crypto/gimli.zig @@ -34,9 +34,9 @@ pub const State = struct { pub fn permute(self: *Self) void { const state = &self.data; - var round = u32(24); + var round = @as(u32, 24); while (round > 0) : (round -= 1) { - var column = usize(0); + var column = @as(usize, 0); while (column < 4) : (column += 1) { const x = math.rotl(u32, state[column], 24); const y = math.rotl(u32, state[4 + column], 9); @@ -61,7 +61,7 @@ pub const State = struct { } pub fn squeeze(self: *Self, out: []u8) void { - var i = usize(0); + var i = @as(usize, 0); while (i + RATE <= out.len) : (i += RATE) { self.permute(); mem.copy(u8, out[i..], self.toSliceConst()[0..RATE]); @@ -79,7 +79,7 @@ test "permute" { var state = State{ .data = blk: { var input: [12]u32 = undefined; - var i = u32(0); + var i = @as(u32, 0); while (i < 12) : (i += 1) { input[i] = i * i * i + i *% 0x9e3779b9; } diff --git a/lib/std/crypto/md5.zig b/lib/std/crypto/md5.zig @@ -126,10 +126,10 @@ pub const Md5 = struct { while (i < 16) : (i += 1) { // NOTE: Performing or's separately improves perf by ~10% s[i] = 0; - s[i] |= u32(b[i * 4 + 0]); - s[i] |= u32(b[i * 4 + 1]) << 8; - s[i] |= u32(b[i * 4 + 2]) << 16; - s[i] |= u32(b[i * 4 + 3]) << 24; + s[i] |= @as(u32, b[i * 4 + 0]); + s[i] |= @as(u32, b[i * 4 + 1]) << 8; + s[i] |= @as(u32, b[i * 4 + 2]) << 16; + s[i] |= @as(u32, b[i * 4 + 3]) << 24; } var v: [4]u32 = [_]u32{ diff --git a/lib/std/crypto/poly1305.zig b/lib/std/crypto/poly1305.zig @@ -87,11 +87,11 @@ pub const Poly1305 = struct { // ctx->h <= 4_ffffffff_ffffffff_ffffffff_ffffffff fn polyBlock(ctx: *Self) void { // s = h + c, without carry propagation - const s0 = u64(ctx.h[0]) + ctx.c[0]; // s0 <= 1_fffffffe - const s1 = u64(ctx.h[1]) + ctx.c[1]; // s1 <= 1_fffffffe - const s2 = u64(ctx.h[2]) + ctx.c[2]; // s2 <= 1_fffffffe - const s3 = u64(ctx.h[3]) + ctx.c[3]; // s3 <= 1_fffffffe - const s4 = u64(ctx.h[4]) + ctx.c[4]; // s4 <= 5 + const s0 = @as(u64, ctx.h[0]) + ctx.c[0]; // s0 <= 1_fffffffe + const s1 = @as(u64, ctx.h[1]) + ctx.c[1]; // s1 <= 1_fffffffe + const s2 = @as(u64, ctx.h[2]) + ctx.c[2]; // s2 <= 1_fffffffe + const s3 = @as(u64, ctx.h[3]) + ctx.c[3]; // s3 <= 1_fffffffe + const s4 = @as(u64, ctx.h[4]) + ctx.c[4]; // s4 <= 5 // Local all the things! const r0 = ctx.r[0]; // r0 <= 0fffffff @@ -197,7 +197,7 @@ pub const Poly1305 = struct { // check if we should subtract 2^130-5 by performing the // corresponding carry propagation. - const _u0 = u64(5) + ctx.h[0]; // <= 1_00000004 + const _u0 = @as(u64, 5) + ctx.h[0]; // <= 1_00000004 const _u1 = (_u0 >> 32) + ctx.h[1]; // <= 1_00000000 const _u2 = (_u1 >> 32) + ctx.h[2]; // <= 1_00000000 const _u3 = (_u2 >> 32) + ctx.h[3]; // <= 1_00000000 diff --git a/lib/std/crypto/sha1.zig b/lib/std/crypto/sha1.zig @@ -146,10 +146,10 @@ pub const Sha1 = struct { Rp(0, 1, 2, 3, 4, 15), }; inline for (round0a) |r| { - s[r.i] = (u32(b[r.i * 4 + 0]) << 24) | (u32(b[r.i * 4 + 1]) << 16) | (u32(b[r.i * 4 + 2]) << 8) | (u32(b[r.i * 4 + 3]) << 0); + s[r.i] = (@as(u32, b[r.i * 4 + 0]) << 24) | (@as(u32, b[r.i * 4 + 1]) << 16) | (@as(u32, b[r.i * 4 + 2]) << 8) | (@as(u32, b[r.i * 4 + 3]) << 0); - v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x5A827999 +% s[r.i & 0xf] +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d])); - v[r.b] = math.rotl(u32, v[r.b], u32(30)); + v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], @as(u32, 5)) +% 0x5A827999 +% s[r.i & 0xf] +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d])); + v[r.b] = math.rotl(u32, v[r.b], @as(u32, 30)); } const round0b = comptime [_]RoundParam{ @@ -160,10 +160,10 @@ pub const Sha1 = struct { }; inline for (round0b) |r| { const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf]; - s[r.i & 0xf] = math.rotl(u32, t, u32(1)); + s[r.i & 0xf] = math.rotl(u32, t, @as(u32, 1)); - v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x5A827999 +% s[r.i & 0xf] +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d])); - v[r.b] = math.rotl(u32, v[r.b], u32(30)); + v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], @as(u32, 5)) +% 0x5A827999 +% s[r.i & 0xf] +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d])); + v[r.b] = math.rotl(u32, v[r.b], @as(u32, 30)); } const round1 = comptime [_]RoundParam{ @@ -190,10 +190,10 @@ pub const Sha1 = struct { }; inline for (round1) |r| { const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf]; - s[r.i & 0xf] = math.rotl(u32, t, u32(1)); + s[r.i & 0xf] = math.rotl(u32, t, @as(u32, 1)); - v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x6ED9EBA1 +% s[r.i & 0xf] +% (v[r.b] ^ v[r.c] ^ v[r.d]); - v[r.b] = math.rotl(u32, v[r.b], u32(30)); + v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], @as(u32, 5)) +% 0x6ED9EBA1 +% s[r.i & 0xf] +% (v[r.b] ^ v[r.c] ^ v[r.d]); + v[r.b] = math.rotl(u32, v[r.b], @as(u32, 30)); } const round2 = comptime [_]RoundParam{ @@ -220,10 +220,10 @@ pub const Sha1 = struct { }; inline for (round2) |r| { const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf]; - s[r.i & 0xf] = math.rotl(u32, t, u32(1)); + s[r.i & 0xf] = math.rotl(u32, t, @as(u32, 1)); - v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0x8F1BBCDC +% s[r.i & 0xf] +% ((v[r.b] & v[r.c]) ^ (v[r.b] & v[r.d]) ^ (v[r.c] & v[r.d])); - v[r.b] = math.rotl(u32, v[r.b], u32(30)); + v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], @as(u32, 5)) +% 0x8F1BBCDC +% s[r.i & 0xf] +% ((v[r.b] & v[r.c]) ^ (v[r.b] & v[r.d]) ^ (v[r.c] & v[r.d])); + v[r.b] = math.rotl(u32, v[r.b], @as(u32, 30)); } const round3 = comptime [_]RoundParam{ @@ -250,10 +250,10 @@ pub const Sha1 = struct { }; inline for (round3) |r| { const t = s[(r.i - 3) & 0xf] ^ s[(r.i - 8) & 0xf] ^ s[(r.i - 14) & 0xf] ^ s[(r.i - 16) & 0xf]; - s[r.i & 0xf] = math.rotl(u32, t, u32(1)); + s[r.i & 0xf] = math.rotl(u32, t, @as(u32, 1)); - v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], u32(5)) +% 0xCA62C1D6 +% s[r.i & 0xf] +% (v[r.b] ^ v[r.c] ^ v[r.d]); - v[r.b] = math.rotl(u32, v[r.b], u32(30)); + v[r.e] = v[r.e] +% math.rotl(u32, v[r.a], @as(u32, 5)) +% 0xCA62C1D6 +% s[r.i & 0xf] +% (v[r.b] ^ v[r.c] ^ v[r.d]); + v[r.b] = math.rotl(u32, v[r.b], @as(u32, 30)); } d.s[0] +%= v[0]; diff --git a/lib/std/crypto/sha2.zig b/lib/std/crypto/sha2.zig @@ -180,13 +180,13 @@ fn Sha2_32(comptime params: Sha2Params32) type { var i: usize = 0; while (i < 16) : (i += 1) { s[i] = 0; - s[i] |= u32(b[i * 4 + 0]) << 24; - s[i] |= u32(b[i * 4 + 1]) << 16; - s[i] |= u32(b[i * 4 + 2]) << 8; - s[i] |= u32(b[i * 4 + 3]) << 0; + s[i] |= @as(u32, b[i * 4 + 0]) << 24; + s[i] |= @as(u32, b[i * 4 + 1]) << 16; + s[i] |= @as(u32, b[i * 4 + 2]) << 8; + s[i] |= @as(u32, b[i * 4 + 3]) << 0; } while (i < 64) : (i += 1) { - s[i] = s[i - 16] +% s[i - 7] +% (math.rotr(u32, s[i - 15], u32(7)) ^ math.rotr(u32, s[i - 15], u32(18)) ^ (s[i - 15] >> 3)) +% (math.rotr(u32, s[i - 2], u32(17)) ^ math.rotr(u32, s[i - 2], u32(19)) ^ (s[i - 2] >> 10)); + s[i] = s[i - 16] +% s[i - 7] +% (math.rotr(u32, s[i - 15], @as(u32, 7)) ^ math.rotr(u32, s[i - 15], @as(u32, 18)) ^ (s[i - 15] >> 3)) +% (math.rotr(u32, s[i - 2], @as(u32, 17)) ^ math.rotr(u32, s[i - 2], @as(u32, 19)) ^ (s[i - 2] >> 10)); } var v: [8]u32 = [_]u32{ @@ -267,11 +267,11 @@ fn Sha2_32(comptime params: Sha2Params32) type { Rp256(1, 2, 3, 4, 5, 6, 7, 0, 63, 0xC67178F2), }; inline for (round0) |r| { - v[r.h] = v[r.h] +% (math.rotr(u32, v[r.e], u32(6)) ^ math.rotr(u32, v[r.e], u32(11)) ^ math.rotr(u32, v[r.e], u32(25))) +% (v[r.g] ^ (v[r.e] & (v[r.f] ^ v[r.g]))) +% r.k +% s[r.i]; + v[r.h] = v[r.h] +% (math.rotr(u32, v[r.e], @as(u32, 6)) ^ math.rotr(u32, v[r.e], @as(u32, 11)) ^ math.rotr(u32, v[r.e], @as(u32, 25))) +% (v[r.g] ^ (v[r.e] & (v[r.f] ^ v[r.g]))) +% r.k +% s[r.i]; v[r.d] = v[r.d] +% v[r.h]; - v[r.h] = v[r.h] +% (math.rotr(u32, v[r.a], u32(2)) ^ math.rotr(u32, v[r.a], u32(13)) ^ math.rotr(u32, v[r.a], u32(22))) +% ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c])); + v[r.h] = v[r.h] +% (math.rotr(u32, v[r.a], @as(u32, 2)) ^ math.rotr(u32, v[r.a], @as(u32, 13)) ^ math.rotr(u32, v[r.a], @as(u32, 22))) +% ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c])); } d.s[0] +%= v[0]; @@ -522,17 +522,19 @@ fn Sha2_64(comptime params: Sha2Params64) type { var i: usize = 0; while (i < 16) : (i += 1) { s[i] = 0; - s[i] |= u64(b[i * 8 + 0]) << 56; - s[i] |= u64(b[i * 8 + 1]) << 48; - s[i] |= u64(b[i * 8 + 2]) << 40; - s[i] |= u64(b[i * 8 + 3]) << 32; - s[i] |= u64(b[i * 8 + 4]) << 24; - s[i] |= u64(b[i * 8 + 5]) << 16; - s[i] |= u64(b[i * 8 + 6]) << 8; - s[i] |= u64(b[i * 8 + 7]) << 0; + s[i] |= @as(u64, b[i * 8 + 0]) << 56; + s[i] |= @as(u64, b[i * 8 + 1]) << 48; + s[i] |= @as(u64, b[i * 8 + 2]) << 40; + s[i] |= @as(u64, b[i * 8 + 3]) << 32; + s[i] |= @as(u64, b[i * 8 + 4]) << 24; + s[i] |= @as(u64, b[i * 8 + 5]) << 16; + s[i] |= @as(u64, b[i * 8 + 6]) << 8; + s[i] |= @as(u64, b[i * 8 + 7]) << 0; } while (i < 80) : (i += 1) { - s[i] = s[i - 16] +% s[i - 7] +% (math.rotr(u64, s[i - 15], u64(1)) ^ math.rotr(u64, s[i - 15], u64(8)) ^ (s[i - 15] >> 7)) +% (math.rotr(u64, s[i - 2], u64(19)) ^ math.rotr(u64, s[i - 2], u64(61)) ^ (s[i - 2] >> 6)); + s[i] = s[i - 16] +% s[i - 7] +% + (math.rotr(u64, s[i - 15], @as(u64, 1)) ^ math.rotr(u64, s[i - 15], @as(u64, 8)) ^ (s[i - 15] >> 7)) +% + (math.rotr(u64, s[i - 2], @as(u64, 19)) ^ math.rotr(u64, s[i - 2], @as(u64, 61)) ^ (s[i - 2] >> 6)); } var v: [8]u64 = [_]u64{ @@ -629,11 +631,11 @@ fn Sha2_64(comptime params: Sha2Params64) type { Rp512(1, 2, 3, 4, 5, 6, 7, 0, 79, 0x6C44198C4A475817), }; inline for (round0) |r| { - v[r.h] = v[r.h] +% (math.rotr(u64, v[r.e], u64(14)) ^ math.rotr(u64, v[r.e], u64(18)) ^ math.rotr(u64, v[r.e], u64(41))) +% (v[r.g] ^ (v[r.e] & (v[r.f] ^ v[r.g]))) +% r.k +% s[r.i]; + v[r.h] = v[r.h] +% (math.rotr(u64, v[r.e], @as(u64, 14)) ^ math.rotr(u64, v[r.e], @as(u64, 18)) ^ math.rotr(u64, v[r.e], @as(u64, 41))) +% (v[r.g] ^ (v[r.e] & (v[r.f] ^ v[r.g]))) +% r.k +% s[r.i]; v[r.d] = v[r.d] +% v[r.h]; - v[r.h] = v[r.h] +% (math.rotr(u64, v[r.a], u64(28)) ^ math.rotr(u64, v[r.a], u64(34)) ^ math.rotr(u64, v[r.a], u64(39))) +% ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c])); + v[r.h] = v[r.h] +% (math.rotr(u64, v[r.a], @as(u64, 28)) ^ math.rotr(u64, v[r.a], @as(u64, 34)) ^ math.rotr(u64, v[r.a], @as(u64, 39))) +% ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c])); } d.s[0] +%= v[0]; diff --git a/lib/std/crypto/sha3.zig b/lib/std/crypto/sha3.zig @@ -133,7 +133,7 @@ fn keccak_f(comptime F: usize, d: []u8) void { } x = 0; inline while (x < 5) : (x += 1) { - t[0] = c[M5[x + 4]] ^ math.rotl(u64, c[M5[x + 1]], usize(1)); + t[0] = c[M5[x + 4]] ^ math.rotl(u64, c[M5[x + 1]], @as(usize, 1)); y = 0; inline while (y < 5) : (y += 1) { s[x + y * 5] ^= t[0]; diff --git a/lib/std/crypto/x25519.zig b/lib/std/crypto/x25519.zig @@ -199,9 +199,9 @@ const Fe = struct { inline fn carryRound(c: []i64, t: []i64, comptime i: comptime_int, comptime shift: comptime_int, comptime mult: comptime_int) void { const j = (i + 1) % 10; - c[i] = (t[i] + (i64(1) << shift)) >> (shift + 1); + c[i] = (t[i] + (@as(i64, 1) << shift)) >> (shift + 1); t[j] += c[i] * mult; - t[i] -= c[i] * (i64(1) << (shift + 1)); + t[i] -= c[i] * (@as(i64, 1) << (shift + 1)); } fn carry1(h: *Fe, t: []i64) void { @@ -256,15 +256,15 @@ const Fe = struct { var t: [10]i64 = undefined; t[0] = readIntSliceLittle(u32, s[0..4]); - t[1] = u32(readIntSliceLittle(u24, s[4..7])) << 6; - t[2] = u32(readIntSliceLittle(u24, s[7..10])) << 5; - t[3] = u32(readIntSliceLittle(u24, s[10..13])) << 3; - t[4] = u32(readIntSliceLittle(u24, s[13..16])) << 2; + t[1] = @as(u32, readIntSliceLittle(u24, s[4..7])) << 6; + t[2] = @as(u32, readIntSliceLittle(u24, s[7..10])) << 5; + t[3] = @as(u32, readIntSliceLittle(u24, s[10..13])) << 3; + t[4] = @as(u32, readIntSliceLittle(u24, s[13..16])) << 2; t[5] = readIntSliceLittle(u32, s[16..20]); - t[6] = u32(readIntSliceLittle(u24, s[20..23])) << 7; - t[7] = u32(readIntSliceLittle(u24, s[23..26])) << 5; - t[8] = u32(readIntSliceLittle(u24, s[26..29])) << 4; - t[9] = (u32(readIntSliceLittle(u24, s[29..32])) & 0x7fffff) << 2; + t[6] = @as(u32, readIntSliceLittle(u24, s[20..23])) << 7; + t[7] = @as(u32, readIntSliceLittle(u24, s[23..26])) << 5; + t[8] = @as(u32, readIntSliceLittle(u24, s[26..29])) << 4; + t[9] = (@as(u32, readIntSliceLittle(u24, s[29..32])) & 0x7fffff) << 2; carry1(h, t[0..]); } @@ -273,7 +273,7 @@ const Fe = struct { var t: [10]i64 = undefined; for (t[0..]) |_, i| { - t[i] = i64(f.b[i]) * g; + t[i] = @as(i64, f.b[i]) * g; } carry1(h, t[0..]); @@ -305,16 +305,16 @@ const Fe = struct { // t's become h var t: [10]i64 = undefined; - t[0] = f[0] * i64(g[0]) + F[1] * i64(G[9]) + f[2] * i64(G[8]) + F[3] * i64(G[7]) + f[4] * i64(G[6]) + F[5] * i64(G[5]) + f[6] * i64(G[4]) + F[7] * i64(G[3]) + f[8] * i64(G[2]) + F[9] * i64(G[1]); - t[1] = f[0] * i64(g[1]) + f[1] * i64(g[0]) + f[2] * i64(G[9]) + f[3] * i64(G[8]) + f[4] * i64(G[7]) + f[5] * i64(G[6]) + f[6] * i64(G[5]) + f[7] * i64(G[4]) + f[8] * i64(G[3]) + f[9] * i64(G[2]); - t[2] = f[0] * i64(g[2]) + F[1] * i64(g[1]) + f[2] * i64(g[0]) + F[3] * i64(G[9]) + f[4] * i64(G[8]) + F[5] * i64(G[7]) + f[6] * i64(G[6]) + F[7] * i64(G[5]) + f[8] * i64(G[4]) + F[9] * i64(G[3]); - t[3] = f[0] * i64(g[3]) + f[1] * i64(g[2]) + f[2] * i64(g[1]) + f[3] * i64(g[0]) + f[4] * i64(G[9]) + f[5] * i64(G[8]) + f[6] * i64(G[7]) + f[7] * i64(G[6]) + f[8] * i64(G[5]) + f[9] * i64(G[4]); - t[4] = f[0] * i64(g[4]) + F[1] * i64(g[3]) + f[2] * i64(g[2]) + F[3] * i64(g[1]) + f[4] * i64(g[0]) + F[5] * i64(G[9]) + f[6] * i64(G[8]) + F[7] * i64(G[7]) + f[8] * i64(G[6]) + F[9] * i64(G[5]); - t[5] = f[0] * i64(g[5]) + f[1] * i64(g[4]) + f[2] * i64(g[3]) + f[3] * i64(g[2]) + f[4] * i64(g[1]) + f[5] * i64(g[0]) + f[6] * i64(G[9]) + f[7] * i64(G[8]) + f[8] * i64(G[7]) + f[9] * i64(G[6]); - t[6] = f[0] * i64(g[6]) + F[1] * i64(g[5]) + f[2] * i64(g[4]) + F[3] * i64(g[3]) + f[4] * i64(g[2]) + F[5] * i64(g[1]) + f[6] * i64(g[0]) + F[7] * i64(G[9]) + f[8] * i64(G[8]) + F[9] * i64(G[7]); - t[7] = f[0] * i64(g[7]) + f[1] * i64(g[6]) + f[2] * i64(g[5]) + f[3] * i64(g[4]) + f[4] * i64(g[3]) + f[5] * i64(g[2]) + f[6] * i64(g[1]) + f[7] * i64(g[0]) + f[8] * i64(G[9]) + f[9] * i64(G[8]); - t[8] = f[0] * i64(g[8]) + F[1] * i64(g[7]) + f[2] * i64(g[6]) + F[3] * i64(g[5]) + f[4] * i64(g[4]) + F[5] * i64(g[3]) + f[6] * i64(g[2]) + F[7] * i64(g[1]) + f[8] * i64(g[0]) + F[9] * i64(G[9]); - t[9] = f[0] * i64(g[9]) + f[1] * i64(g[8]) + f[2] * i64(g[7]) + f[3] * i64(g[6]) + f[4] * i64(g[5]) + f[5] * i64(g[4]) + f[6] * i64(g[3]) + f[7] * i64(g[2]) + f[8] * i64(g[1]) + f[9] * i64(g[0]); + t[0] = f[0] * @as(i64, g[0]) + F[1] * @as(i64, G[9]) + f[2] * @as(i64, G[8]) + F[3] * @as(i64, G[7]) + f[4] * @as(i64, G[6]) + F[5] * @as(i64, G[5]) + f[6] * @as(i64, G[4]) + F[7] * @as(i64, G[3]) + f[8] * @as(i64, G[2]) + F[9] * @as(i64, G[1]); + t[1] = f[0] * @as(i64, g[1]) + f[1] * @as(i64, g[0]) + f[2] * @as(i64, G[9]) + f[3] * @as(i64, G[8]) + f[4] * @as(i64, G[7]) + f[5] * @as(i64, G[6]) + f[6] * @as(i64, G[5]) + f[7] * @as(i64, G[4]) + f[8] * @as(i64, G[3]) + f[9] * @as(i64, G[2]); + t[2] = f[0] * @as(i64, g[2]) + F[1] * @as(i64, g[1]) + f[2] * @as(i64, g[0]) + F[3] * @as(i64, G[9]) + f[4] * @as(i64, G[8]) + F[5] * @as(i64, G[7]) + f[6] * @as(i64, G[6]) + F[7] * @as(i64, G[5]) + f[8] * @as(i64, G[4]) + F[9] * @as(i64, G[3]); + t[3] = f[0] * @as(i64, g[3]) + f[1] * @as(i64, g[2]) + f[2] * @as(i64, g[1]) + f[3] * @as(i64, g[0]) + f[4] * @as(i64, G[9]) + f[5] * @as(i64, G[8]) + f[6] * @as(i64, G[7]) + f[7] * @as(i64, G[6]) + f[8] * @as(i64, G[5]) + f[9] * @as(i64, G[4]); + t[4] = f[0] * @as(i64, g[4]) + F[1] * @as(i64, g[3]) + f[2] * @as(i64, g[2]) + F[3] * @as(i64, g[1]) + f[4] * @as(i64, g[0]) + F[5] * @as(i64, G[9]) + f[6] * @as(i64, G[8]) + F[7] * @as(i64, G[7]) + f[8] * @as(i64, G[6]) + F[9] * @as(i64, G[5]); + t[5] = f[0] * @as(i64, g[5]) + f[1] * @as(i64, g[4]) + f[2] * @as(i64, g[3]) + f[3] * @as(i64, g[2]) + f[4] * @as(i64, g[1]) + f[5] * @as(i64, g[0]) + f[6] * @as(i64, G[9]) + f[7] * @as(i64, G[8]) + f[8] * @as(i64, G[7]) + f[9] * @as(i64, G[6]); + t[6] = f[0] * @as(i64, g[6]) + F[1] * @as(i64, g[5]) + f[2] * @as(i64, g[4]) + F[3] * @as(i64, g[3]) + f[4] * @as(i64, g[2]) + F[5] * @as(i64, g[1]) + f[6] * @as(i64, g[0]) + F[7] * @as(i64, G[9]) + f[8] * @as(i64, G[8]) + F[9] * @as(i64, G[7]); + t[7] = f[0] * @as(i64, g[7]) + f[1] * @as(i64, g[6]) + f[2] * @as(i64, g[5]) + f[3] * @as(i64, g[4]) + f[4] * @as(i64, g[3]) + f[5] * @as(i64, g[2]) + f[6] * @as(i64, g[1]) + f[7] * @as(i64, g[0]) + f[8] * @as(i64, G[9]) + f[9] * @as(i64, G[8]); + t[8] = f[0] * @as(i64, g[8]) + F[1] * @as(i64, g[7]) + f[2] * @as(i64, g[6]) + F[3] * @as(i64, g[5]) + f[4] * @as(i64, g[4]) + F[5] * @as(i64, g[3]) + f[6] * @as(i64, g[2]) + F[7] * @as(i64, g[1]) + f[8] * @as(i64, g[0]) + F[9] * @as(i64, G[9]); + t[9] = f[0] * @as(i64, g[9]) + f[1] * @as(i64, g[8]) + f[2] * @as(i64, g[7]) + f[3] * @as(i64, g[6]) + f[4] * @as(i64, g[5]) + f[5] * @as(i64, g[4]) + f[6] * @as(i64, g[3]) + f[7] * @as(i64, g[2]) + f[8] * @as(i64, g[1]) + f[9] * @as(i64, g[0]); carry2(h, t[0..]); } @@ -348,16 +348,16 @@ const Fe = struct { var t: [10]i64 = undefined; - t[0] = f0 * i64(f0) + f1_2 * i64(f9_38) + f2_2 * i64(f8_19) + f3_2 * i64(f7_38) + f4_2 * i64(f6_19) + f5 * i64(f5_38); - t[1] = f0_2 * i64(f1) + f2 * i64(f9_38) + f3_2 * i64(f8_19) + f4 * i64(f7_38) + f5_2 * i64(f6_19); - t[2] = f0_2 * i64(f2) + f1_2 * i64(f1) + f3_2 * i64(f9_38) + f4_2 * i64(f8_19) + f5_2 * i64(f7_38) + f6 * i64(f6_19); - t[3] = f0_2 * i64(f3) + f1_2 * i64(f2) + f4 * i64(f9_38) + f5_2 * i64(f8_19) + f6 * i64(f7_38); - t[4] = f0_2 * i64(f4) + f1_2 * i64(f3_2) + f2 * i64(f2) + f5_2 * i64(f9_38) + f6_2 * i64(f8_19) + f7 * i64(f7_38); - t[5] = f0_2 * i64(f5) + f1_2 * i64(f4) + f2_2 * i64(f3) + f6 * i64(f9_38) + f7_2 * i64(f8_19); - t[6] = f0_2 * i64(f6) + f1_2 * i64(f5_2) + f2_2 * i64(f4) + f3_2 * i64(f3) + f7_2 * i64(f9_38) + f8 * i64(f8_19); - t[7] = f0_2 * i64(f7) + f1_2 * i64(f6) + f2_2 * i64(f5) + f3_2 * i64(f4) + f8 * i64(f9_38); - t[8] = f0_2 * i64(f8) + f1_2 * i64(f7_2) + f2_2 * i64(f6) + f3_2 * i64(f5_2) + f4 * i64(f4) + f9 * i64(f9_38); - t[9] = f0_2 * i64(f9) + f1_2 * i64(f8) + f2_2 * i64(f7) + f3_2 * i64(f6) + f4 * i64(f5_2); + t[0] = f0 * @as(i64, f0) + f1_2 * @as(i64, f9_38) + f2_2 * @as(i64, f8_19) + f3_2 * @as(i64, f7_38) + f4_2 * @as(i64, f6_19) + f5 * @as(i64, f5_38); + t[1] = f0_2 * @as(i64, f1) + f2 * @as(i64, f9_38) + f3_2 * @as(i64, f8_19) + f4 * @as(i64, f7_38) + f5_2 * @as(i64, f6_19); + t[2] = f0_2 * @as(i64, f2) + f1_2 * @as(i64, f1) + f3_2 * @as(i64, f9_38) + f4_2 * @as(i64, f8_19) + f5_2 * @as(i64, f7_38) + f6 * @as(i64, f6_19); + t[3] = f0_2 * @as(i64, f3) + f1_2 * @as(i64, f2) + f4 * @as(i64, f9_38) + f5_2 * @as(i64, f8_19) + f6 * @as(i64, f7_38); + t[4] = f0_2 * @as(i64, f4) + f1_2 * @as(i64, f3_2) + f2 * @as(i64, f2) + f5_2 * @as(i64, f9_38) + f6_2 * @as(i64, f8_19) + f7 * @as(i64, f7_38); + t[5] = f0_2 * @as(i64, f5) + f1_2 * @as(i64, f4) + f2_2 * @as(i64, f3) + f6 * @as(i64, f9_38) + f7_2 * @as(i64, f8_19); + t[6] = f0_2 * @as(i64, f6) + f1_2 * @as(i64, f5_2) + f2_2 * @as(i64, f4) + f3_2 * @as(i64, f3) + f7_2 * @as(i64, f9_38) + f8 * @as(i64, f8_19); + t[7] = f0_2 * @as(i64, f7) + f1_2 * @as(i64, f6) + f2_2 * @as(i64, f5) + f3_2 * @as(i64, f4) + f8 * @as(i64, f9_38); + t[8] = f0_2 * @as(i64, f8) + f1_2 * @as(i64, f7_2) + f2_2 * @as(i64, f6) + f3_2 * @as(i64, f5_2) + f4 * @as(i64, f4) + f9 * @as(i64, f9_38); + t[9] = f0_2 * @as(i64, f9) + f1_2 * @as(i64, f8) + f2_2 * @as(i64, f7) + f3_2 * @as(i64, f6) + f4 * @as(i64, f5_2); carry2(h, t[0..]); } @@ -500,7 +500,7 @@ const Fe = struct { if (i + 1 < 10) { t[i + 1] += c[i]; } - t[i] -= c[i] * (i32(1) << shift); + t[i] -= c[i] * (@as(i32, 1) << shift); } fn toBytes(s: []u8, h: *const Fe) void { @@ -511,7 +511,7 @@ const Fe = struct { t[i] = h.b[i]; } - var q = (19 * t[9] + ((i32(1) << 24))) >> 25; + var q = (19 * t[9] + ((@as(i32, 1) << 24))) >> 25; { var i: usize = 0; while (i < 5) : (i += 1) { diff --git a/lib/std/debug.zig b/lib/std/debug.zig @@ -45,18 +45,19 @@ var stderr_file_out_stream: File.OutStream = undefined; var stderr_stream: ?*io.OutStream(File.WriteError) = null; var stderr_mutex = std.Mutex.init(); + pub fn warn(comptime fmt: []const u8, args: ...) void { const held = stderr_mutex.acquire(); defer held.release(); - const stderr = getStderrStream() catch return; + const stderr = getStderrStream(); stderr.print(fmt, args) catch return; } -pub fn getStderrStream() !*io.OutStream(File.WriteError) { +pub fn getStderrStream() *io.OutStream(File.WriteError) { if (stderr_stream) |st| { return st; } else { - stderr_file = try io.getStdErr(); + stderr_file = io.getStdErr(); stderr_file_out_stream = stderr_file.outStream(); const st = &stderr_file_out_stream.stream; stderr_stream = st; @@ -64,6 +65,10 @@ pub fn getStderrStream() !*io.OutStream(File.WriteError) { } } +pub fn getStderrMutex() *std.Mutex { + return &stderr_mutex; +} + /// TODO multithreaded awareness var self_debug_info: ?DebugInfo = null; @@ -85,7 +90,7 @@ fn wantTtyColor() bool { /// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned. /// TODO multithreaded awareness pub fn dumpCurrentStackTrace(start_addr: ?usize) void { - const stderr = getStderrStream() catch return; + const stderr = getStderrStream(); if (builtin.strip_debug_info) { stderr.print("Unable to dump stack trace: debug info stripped\n") catch return; return; @@ -104,7 +109,7 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void { /// unbuffered, and ignores any error returned. /// TODO multithreaded awareness pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void { - const stderr = getStderrStream() catch return; + const stderr = getStderrStream(); if (builtin.strip_debug_info) { stderr.print("Unable to dump stack trace: debug info stripped\n") catch return; return; @@ -177,7 +182,7 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *builtin.StackTrace /// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned. /// TODO multithreaded awareness pub fn dumpStackTrace(stack_trace: builtin.StackTrace) void { - const stderr = getStderrStream() catch return; + const stderr = getStderrStream(); if (builtin.strip_debug_info) { stderr.print("Unable to dump stack trace: debug info stripped\n") catch return; return; @@ -232,7 +237,7 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c // which first called panic can finish printing a stack trace. os.abort(); } - const stderr = getStderrStream() catch os.abort(); + const stderr = getStderrStream(); stderr.print(format ++ "\n", args) catch os.abort(); if (trace) |t| { dumpStackTrace(t.*); @@ -1003,7 +1008,7 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize { const word = try stream.readIntLittle(u32); var bit_i: u5 = 0; while (true) : (bit_i += 1) { - if (word & (u32(1) << bit_i) != 0) { + if (word & (@as(u32, 1) << bit_i) != 0) { try list.append(word_i * 32 + bit_i); } if (bit_i == maxInt(u5)) break; @@ -1551,13 +1556,14 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo // TODO the noasyncs here are workarounds fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 { - return if (is_64) try noasync in_stream.readIntLittle(u64) else u64(try noasync in_stream.readIntLittle(u32)); + return if (is_64) try noasync in_stream.readIntLittle(u64) else @as(u64, try noasync in_stream.readIntLittle(u32)); } // TODO the noasyncs here are workarounds fn parseFormValueTargetAddrSize(in_stream: var) !u64 { if (@sizeOf(usize) == 4) { - return u64(try noasync in_stream.readIntLittle(u32)); + // TODO this cast should not be needed + return @as(u64, try noasync in_stream.readIntLittle(u32)); } else if (@sizeOf(usize) == 8) { return noasync in_stream.readIntLittle(u64); } else { @@ -1705,7 +1711,12 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u const ofile_path = mem.toSliceConst(u8, di.strings.ptr + ofile.n_strx); gop.kv.value = MachOFile{ - .bytes = try std.io.readFileAllocAligned(di.ofiles.allocator, ofile_path, @alignOf(macho.mach_header_64)), + .bytes = try std.fs.Dir.cwd().readFileAllocAligned( + di.ofiles.allocator, + ofile_path, + maxInt(usize), + @alignOf(macho.mach_header_64), + ), .sect_debug_info = null, .sect_debug_line = null, }; @@ -1841,7 +1852,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u // special opcodes const adjusted_opcode = opcode - opcode_base; const inc_addr = minimum_instruction_length * (adjusted_opcode / line_range); - const inc_line = i32(line_base) + i32(adjusted_opcode % line_range); + const inc_line = @as(i32, line_base) + @as(i32, adjusted_opcode % line_range); prog.line += inc_line; prog.address += inc_addr; if (try prog.checkLineMatch()) |info| return info; @@ -1908,7 +1919,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr if (unit_length == 0) { return error.MissingDebugInfo; } - const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); + const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4)); const version = try di.dwarf_in_stream.readInt(u16, di.endian); // TODO support 3 and 5 @@ -2007,7 +2018,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr // special opcodes const adjusted_opcode = opcode - opcode_base; const inc_addr = minimum_instruction_length * (adjusted_opcode / line_range); - const inc_line = i32(line_base) + i32(adjusted_opcode % line_range); + const inc_line = @as(i32, line_base) + @as(i32, adjusted_opcode % line_range); prog.line += inc_line; prog.address += inc_addr; if (try prog.checkLineMatch()) |info| return info; @@ -2088,7 +2099,7 @@ fn scanAllFunctions(di: *DwarfInfo) !void { var is_64: bool = undefined; const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64); if (unit_length == 0) return; - const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); + const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4)); const version = try di.dwarf_in_stream.readInt(u16, di.endian); if (version < 2 or version > 5) return error.InvalidDebugInfo; @@ -2190,7 +2201,7 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void { var is_64: bool = undefined; const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64); if (unit_length == 0) return; - const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); + const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4)); const version = try di.dwarf_in_stream.readInt(u16, di.endian); if (version < 2 or version > 5) return error.InvalidDebugInfo; @@ -2307,7 +2318,8 @@ fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 { } else { if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo; ptr.* += 4; - return u64(first_32_bits); + // TODO this cast should not be needed + return @as(u64, first_32_bits); } } @@ -2324,7 +2336,8 @@ fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) return in_stream.readIntLittle(u64); } else { if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo; - return u64(first_32_bits); + // TODO this cast should not be needed + return @as(u64, first_32_bits); } } diff --git a/lib/std/debug/leb128.zig b/lib/std/debug/leb128.zig @@ -62,13 +62,13 @@ pub fn readILEB128(comptime T: type, in_stream: var) !T { var shift: usize = 0; while (true) { - const byte = u8(try in_stream.readByte()); + const byte: u8 = try in_stream.readByte(); if (shift > T.bit_count) return error.Overflow; var operand: UT = undefined; - if (@shlWithOverflow(UT, UT(byte & 0x7f), @intCast(ShiftT, shift), &operand)) { + if (@shlWithOverflow(UT, @as(UT, byte & 0x7f), @intCast(ShiftT, shift), &operand)) { if (byte != 0x7f) return error.Overflow; } @@ -101,7 +101,7 @@ pub fn readILEB128Mem(comptime T: type, ptr: *[*]const u8) !T { return error.Overflow; var operand: UT = undefined; - if (@shlWithOverflow(UT, UT(byte & 0x7f), @intCast(ShiftT, shift), &operand)) { + if (@shlWithOverflow(UT, @as(UT, byte & 0x7f), @intCast(ShiftT, shift), &operand)) { if (byte != 0x7f) return error.Overflow; } diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig @@ -215,8 +215,8 @@ pub const ElfLib = struct { var i: usize = 0; while (i < self.hashtab[1]) : (i += 1) { - if (0 == (u32(1) << @intCast(u5, self.syms[i].st_info & 0xf) & OK_TYPES)) continue; - if (0 == (u32(1) << @intCast(u5, self.syms[i].st_info >> 4) & OK_BINDS)) continue; + if (0 == (@as(u32, 1) << @intCast(u5, self.syms[i].st_info & 0xf) & OK_TYPES)) continue; + if (0 == (@as(u32, 1) << @intCast(u5, self.syms[i].st_info >> 4) & OK_BINDS)) continue; if (0 == self.syms[i].st_shndx) continue; if (!mem.eql(u8, name, mem.toSliceConst(u8, self.strings + self.syms[i].st_name))) continue; if (maybe_versym) |versym| { diff --git a/lib/std/elf.zig b/lib/std/elf.zig @@ -441,9 +441,9 @@ pub const Elf = struct { elf.program_header_offset = try in.readInt(u64, elf.endian); elf.section_header_offset = try in.readInt(u64, elf.endian); } else { - elf.entry_addr = u64(try in.readInt(u32, elf.endian)); - elf.program_header_offset = u64(try in.readInt(u32, elf.endian)); - elf.section_header_offset = u64(try in.readInt(u32, elf.endian)); + elf.entry_addr = @as(u64, try in.readInt(u32, elf.endian)); + elf.program_header_offset = @as(u64, try in.readInt(u32, elf.endian)); + elf.section_header_offset = @as(u64, try in.readInt(u32, elf.endian)); } // skip over flags @@ -458,13 +458,13 @@ pub const Elf = struct { const ph_entry_count = try in.readInt(u16, elf.endian); const sh_entry_size = try in.readInt(u16, elf.endian); const sh_entry_count = try in.readInt(u16, elf.endian); - elf.string_section_index = usize(try in.readInt(u16, elf.endian)); + elf.string_section_index = @as(usize, try in.readInt(u16, elf.endian)); if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat; - const sh_byte_count = u64(sh_entry_size) * u64(sh_entry_count); + const sh_byte_count = @as(u64, sh_entry_size) * @as(u64, sh_entry_count); const end_sh = try math.add(u64, elf.section_header_offset, sh_byte_count); - const ph_byte_count = u64(ph_entry_size) * u64(ph_entry_count); + const ph_byte_count = @as(u64, ph_entry_size) * @as(u64, ph_entry_count); const end_ph = try math.add(u64, elf.program_header_offset, ph_byte_count); const stream_end = try seekable_stream.getEndPos(); @@ -499,14 +499,14 @@ pub const Elf = struct { // TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ? elf_section.name = try in.readInt(u32, elf.endian); elf_section.sh_type = try in.readInt(u32, elf.endian); - elf_section.flags = u64(try in.readInt(u32, elf.endian)); - elf_section.addr = u64(try in.readInt(u32, elf.endian)); - elf_section.offset = u64(try in.readInt(u32, elf.endian)); - elf_section.size = u64(try in.readInt(u32, elf.endian)); + elf_section.flags = @as(u64, try in.readInt(u32, elf.endian)); + elf_section.addr = @as(u64, try in.readInt(u32, elf.endian)); + elf_section.offset = @as(u64, try in.readInt(u32, elf.endian)); + elf_section.size = @as(u64, try in.readInt(u32, elf.endian)); elf_section.link = try in.readInt(u32, elf.endian); elf_section.info = try in.readInt(u32, elf.endian); - elf_section.addr_align = u64(try in.readInt(u32, elf.endian)); - elf_section.ent_size = u64(try in.readInt(u32, elf.endian)); + elf_section.addr_align = @as(u64, try in.readInt(u32, elf.endian)); + elf_section.ent_size = @as(u64, try in.readInt(u32, elf.endian)); } } diff --git a/lib/std/event/channel.zig b/lib/std/event/channel.zig @@ -161,7 +161,7 @@ pub fn Channel(comptime T: type) type { fn dispatch(self: *SelfChannel) void { // set the "need dispatch" flag - _ = @atomicRmw(u8, &self.need_dispatch, .Xchg, 1, .SeqCst); + @atomicStore(u8, &self.need_dispatch, 1, .SeqCst); lock: while (true) { // set the lock flag @@ -169,7 +169,7 @@ pub fn Channel(comptime T: type) type { if (prev_lock != 0) return; // clear the need_dispatch flag since we're about to do it - _ = @atomicRmw(u8, &self.need_dispatch, .Xchg, 0, .SeqCst); + @atomicStore(u8, &self.need_dispatch, 0, .SeqCst); while (true) { one_dispatch: { diff --git a/lib/std/event/fs.zig b/lib/std/event/fs.zig @@ -328,11 +328,11 @@ pub fn preadWindows(loop: *Loop, fd: fd_t, data: []u8, offset: u64) !usize { windows.ERROR.IO_PENDING => unreachable, windows.ERROR.OPERATION_ABORTED => return error.OperationAborted, windows.ERROR.BROKEN_PIPE => return error.BrokenPipe, - windows.ERROR.HANDLE_EOF => return usize(bytes_transferred), + windows.ERROR.HANDLE_EOF => return @as(usize, bytes_transferred), else => |err| return windows.unexpectedError(err), } } - return usize(bytes_transferred); + return @as(usize, bytes_transferred); } /// iovecs must live until preadv frame completes @@ -415,7 +415,8 @@ pub fn openPosix( pub fn openRead(loop: *Loop, path: []const u8) File.OpenError!fd_t { switch (builtin.os) { .macosx, .linux, .freebsd, .netbsd, .dragonfly => { - const flags = os.O_LARGEFILE | os.O_RDONLY | os.O_CLOEXEC; + const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0; + const flags = O_LARGEFILE | os.O_RDONLY | os.O_CLOEXEC; return openPosix(loop, path, flags, File.default_mode); }, @@ -448,7 +449,8 @@ pub fn openWriteMode(loop: *Loop, path: []const u8, mode: File.Mode) File.OpenEr .netbsd, .dragonfly, => { - const flags = os.O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_TRUNC; + const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0; + const flags = O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_TRUNC; return openPosix(loop, path, flags, File.default_mode); }, .windows => return windows.CreateFile( @@ -472,7 +474,8 @@ pub fn openReadWrite( ) File.OpenError!fd_t { switch (builtin.os) { .macosx, .linux, .freebsd, .netbsd, .dragonfly => { - const flags = os.O_LARGEFILE | os.O_RDWR | os.O_CREAT | os.O_CLOEXEC; + const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0; + const flags = O_LARGEFILE | os.O_RDWR | os.O_CREAT | os.O_CLOEXEC; return openPosix(loop, path, flags, mode); }, diff --git a/lib/std/event/future.zig b/lib/std/event/future.zig @@ -12,12 +12,13 @@ pub fn Future(comptime T: type) type { return struct { lock: Lock, data: T, + available: Available, - /// TODO make this an enum - /// 0 - not started - /// 1 - started - /// 2 - finished - available: u8, + const Available = enum(u8) { + NotStarted, + Started, + Finished, + }; const Self = @This(); const Queue = std.atomic.Queue(anyframe); @@ -34,7 +35,7 @@ pub fn Future(comptime T: type) type { /// available. /// Thread-safe. pub async fn get(self: *Self) *T { - if (@atomicLoad(u8, &self.available, .SeqCst) == 2) { + if (@atomicLoad(Available, &self.available, .SeqCst) == .Finished) { return &self.data; } const held = self.lock.acquire(); @@ -46,7 +47,7 @@ pub fn Future(comptime T: type) type { /// Gets the data without waiting for it. If it's available, a pointer is /// returned. Otherwise, null is returned. pub fn getOrNull(self: *Self) ?*T { - if (@atomicLoad(u8, &self.available, .SeqCst) == 2) { + if (@atomicLoad(Available, &self.available, .SeqCst) == .Finished) { return &self.data; } else { return null; @@ -59,14 +60,14 @@ pub fn Future(comptime T: type) type { /// It's not required to call start() before resolve() but it can be useful since /// this method is thread-safe. pub async fn start(self: *Self) ?*T { - const state = @cmpxchgStrong(u8, &self.available, 0, 1, .SeqCst, .SeqCst) orelse return null; + const state = @cmpxchgStrong(Available, &self.available, .NotStarted, .Started, .SeqCst, .SeqCst) orelse return null; switch (state) { - 1 => { + .Started => { const held = self.lock.acquire(); held.release(); return &self.data; }, - 2 => return &self.data, + .Finished => return &self.data, else => unreachable, } } @@ -74,8 +75,8 @@ pub fn Future(comptime T: type) type { /// Make the data become available. May be called only once. /// Before calling this, modify the `data` property. pub fn resolve(self: *Self) void { - const prev = @atomicRmw(u8, &self.available, .Xchg, 2, .SeqCst); - assert(prev == 0 or prev == 1); // resolve() called twice + const prev = @atomicRmw(Available, &self.available, .Xchg, .Finished, .SeqCst); + assert(prev != .Finished); // resolve() called twice Lock.Held.release(Lock.Held{ .lock = &self.lock }); } }; diff --git a/lib/std/event/group.zig b/lib/std/event/group.zig @@ -8,7 +8,7 @@ const Allocator = std.mem.Allocator; pub fn Group(comptime ReturnType: type) type { return struct { frame_stack: Stack, - alloc_stack: Stack, + alloc_stack: AllocStack, lock: Lock, allocator: *Allocator, @@ -19,11 +19,17 @@ pub fn Group(comptime ReturnType: type) type { else => void, }; const Stack = std.atomic.Stack(anyframe->ReturnType); + const AllocStack = std.atomic.Stack(Node); + + pub const Node = struct { + bytes: []const u8 = [0]u8{}, + handle: anyframe->ReturnType, + }; pub fn init(allocator: *Allocator) Self { return Self{ .frame_stack = Stack.init(), - .alloc_stack = Stack.init(), + .alloc_stack = AllocStack.init(), .lock = Lock.init(), .allocator = allocator, }; @@ -31,10 +37,12 @@ pub fn Group(comptime ReturnType: type) type { /// Add a frame to the group. Thread-safe. pub fn add(self: *Self, handle: anyframe->ReturnType) (error{OutOfMemory}!void) { - const node = try self.allocator.create(Stack.Node); - node.* = Stack.Node{ + const node = try self.allocator.create(AllocStack.Node); + node.* = AllocStack.Node{ .next = undefined, - .data = handle, + .data = Node{ + .handle = handle, + }, }; self.alloc_stack.push(node); } @@ -48,6 +56,24 @@ pub fn Group(comptime ReturnType: type) type { self.frame_stack.push(node); } + /// This is equivalent to adding a frame to the group but the memory of its frame is + /// allocated by the group and freed by `wait`. + /// `func` must be async and have return type `ReturnType`. + /// Thread-safe. + pub fn call(self: *Self, comptime func: var, args: ...) error{OutOfMemory}!void { + var frame = try self.allocator.create(@Frame(func)); + const node = try self.allocator.create(AllocStack.Node); + node.* = AllocStack.Node{ + .next = undefined, + .data = Node{ + .handle = frame, + .bytes = @sliceToBytes((*[1]@Frame(func))(frame)[0..]), + }, + }; + frame.* = async func(args); + self.alloc_stack.push(node); + } + /// Wait for all the calls and promises of the group to complete. /// Thread-safe. /// Safe to call any number of times. @@ -67,8 +93,7 @@ pub fn Group(comptime ReturnType: type) type { } } while (self.alloc_stack.pop()) |node| { - const handle = node.data; - self.allocator.destroy(node); + const handle = node.data.handle; if (Error == void) { await handle; } else { @@ -76,6 +101,8 @@ pub fn Group(comptime ReturnType: type) type { result = err; }; } + self.allocator.free(node.data.bytes); + self.allocator.destroy(node); } return result; } diff --git a/lib/std/event/lock.zig b/lib/std/event/lock.zig @@ -31,8 +31,8 @@ pub const Lock = struct { } // We need to release the lock. - _ = @atomicRmw(u8, &self.lock.queue_empty_bit, .Xchg, 1, .SeqCst); - _ = @atomicRmw(u8, &self.lock.shared_bit, .Xchg, 0, .SeqCst); + @atomicStore(u8, &self.lock.queue_empty_bit, 1, .SeqCst); + @atomicStore(u8, &self.lock.shared_bit, 0, .SeqCst); // There might be a queue item. If we know the queue is empty, we can be done, // because the other actor will try to obtain the lock. @@ -56,8 +56,8 @@ pub const Lock = struct { } // Release the lock again. - _ = @atomicRmw(u8, &self.lock.queue_empty_bit, .Xchg, 1, .SeqCst); - _ = @atomicRmw(u8, &self.lock.shared_bit, .Xchg, 0, .SeqCst); + @atomicStore(u8, &self.lock.queue_empty_bit, 1, .SeqCst); + @atomicStore(u8, &self.lock.shared_bit, 0, .SeqCst); // Find out if we can be done. if (@atomicLoad(u8, &self.lock.queue_empty_bit, .SeqCst) == 1) { @@ -101,7 +101,7 @@ pub const Lock = struct { // We set this bit so that later we can rely on the fact, that if queue_empty_bit is 1, some actor // will attempt to grab the lock. - _ = @atomicRmw(u8, &self.queue_empty_bit, .Xchg, 0, .SeqCst); + @atomicStore(u8, &self.queue_empty_bit, 0, .SeqCst); const old_bit = @atomicRmw(u8, &self.shared_bit, .Xchg, 1, .SeqCst); if (old_bit == 0) { diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig @@ -266,7 +266,7 @@ pub const Loop = struct { }, }; - const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; + const empty_kevs = &[0]os.Kevent{}; for (self.eventfd_resume_nodes) |*eventfd_node, i| { eventfd_node.* = std.atomic.Stack(ResumeNode.EventFd).Node{ @@ -289,7 +289,7 @@ pub const Loop = struct { .next = undefined, }; self.available_eventfd_resume_nodes.push(eventfd_node); - const kevent_array = (*const [1]os.Kevent)(&eventfd_node.data.kevent); + const kevent_array = @as(*const [1]os.Kevent, &eventfd_node.data.kevent); _ = try os.kevent(self.os_data.kqfd, kevent_array, empty_kevs, null); eventfd_node.data.kevent.flags = os.EV_CLEAR | os.EV_ENABLE; eventfd_node.data.kevent.fflags = os.NOTE_TRIGGER; @@ -305,7 +305,7 @@ pub const Loop = struct { .data = 0, .udata = @ptrToInt(&self.final_resume_node), }; - const final_kev_arr = (*const [1]os.Kevent)(&self.os_data.final_kevent); + const final_kev_arr = @as(*const [1]os.Kevent, &self.os_data.final_kevent); _ = try os.kevent(self.os_data.kqfd, final_kev_arr, empty_kevs, null); self.os_data.final_kevent.flags = os.EV_ENABLE; self.os_data.final_kevent.fflags = os.NOTE_TRIGGER; @@ -572,8 +572,8 @@ pub const Loop = struct { eventfd_node.base.handle = next_tick_node.data; switch (builtin.os) { .macosx, .freebsd, .netbsd, .dragonfly => { - const kevent_array = (*const [1]os.Kevent)(&eventfd_node.kevent); - const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; + const kevent_array = @as(*const [1]os.Kevent, &eventfd_node.kevent); + const empty_kevs = &[0]os.Kevent{}; _ = os.kevent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch { self.next_tick_queue.unget(next_tick_node); self.available_eventfd_resume_nodes.push(resume_stack_node); @@ -645,12 +645,6 @@ pub const Loop = struct { } } - /// This is equivalent to function call, except it calls `startCpuBoundOperation` first. - pub fn call(comptime func: var, args: ...) @typeOf(func).ReturnType { - startCpuBoundOperation(); - return func(args); - } - /// Yielding lets the event loop run, starting any unstarted async operations. /// Note that async operations automatically start when a function yields for any other reason, /// for example, when async I/O is performed. This function is intended to be used only when @@ -695,8 +689,8 @@ pub const Loop = struct { }, .macosx, .freebsd, .netbsd, .dragonfly => { self.posixFsRequest(&self.os_data.fs_end_request); - const final_kevent = (*const [1]os.Kevent)(&self.os_data.final_kevent); - const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; + const final_kevent = @as(*const [1]os.Kevent, &self.os_data.final_kevent); + const empty_kevs = &[0]os.Kevent{}; // cannot fail because we already added it and this just enables it _ = os.kevent(self.os_data.kqfd, final_kevent, empty_kevs, null) catch unreachable; return; @@ -753,7 +747,7 @@ pub const Loop = struct { }, .macosx, .freebsd, .netbsd, .dragonfly => { var eventlist: [1]os.Kevent = undefined; - const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; + const empty_kevs = &[0]os.Kevent{}; const count = os.kevent(self.os_data.kqfd, empty_kevs, eventlist[0..], null) catch unreachable; for (eventlist[0..count]) |ev| { const resume_node = @intToPtr(*ResumeNode, ev.udata); @@ -815,12 +809,12 @@ pub const Loop = struct { self.os_data.fs_queue.put(request_node); switch (builtin.os) { .macosx, .freebsd, .netbsd, .dragonfly => { - const fs_kevs = (*const [1]os.Kevent)(&self.os_data.fs_kevent_wake); - const empty_kevs = ([*]os.Kevent)(undefined)[0..0]; + const fs_kevs = @as(*const [1]os.Kevent, &self.os_data.fs_kevent_wake); + const empty_kevs = &[0]os.Kevent{}; _ = os.kevent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable; }, .linux => { - _ = @atomicRmw(i32, &self.os_data.fs_queue_item, AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst); + @atomicStore(i32, &self.os_data.fs_queue_item, 1, AtomicOrder.SeqCst); const rc = os.linux.futex_wake(&self.os_data.fs_queue_item, os.linux.FUTEX_WAKE, 1); switch (os.linux.getErrno(rc)) { 0 => {}, @@ -843,7 +837,7 @@ pub const Loop = struct { fn posixFsRun(self: *Loop) void { while (true) { if (builtin.os == .linux) { - _ = @atomicRmw(i32, &self.os_data.fs_queue_item, .Xchg, 0, .SeqCst); + @atomicStore(i32, &self.os_data.fs_queue_item, 0, .SeqCst); } while (self.os_data.fs_queue.get()) |node| { switch (node.data.msg) { @@ -862,7 +856,8 @@ pub const Loop = struct { }, .Close => |*msg| noasync os.close(msg.fd), .WriteFile => |*msg| blk: { - const flags = os.O_LARGEFILE | os.O_WRONLY | os.O_CREAT | + const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0; + const flags = O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_TRUNC; const fd = noasync os.openC(msg.path.ptr, flags, msg.mode) catch |err| { msg.result = err; @@ -890,7 +885,7 @@ pub const Loop = struct { } }, .macosx, .freebsd, .netbsd, .dragonfly => { - const fs_kevs = (*const [1]os.Kevent)(&self.os_data.fs_kevent_wait); + const fs_kevs = @as(*const [1]os.Kevent, &self.os_data.fs_kevent_wait); var out_kevs: [1]os.Kevent = undefined; _ = os.kevent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable; }, @@ -942,23 +937,6 @@ test "std.event.Loop - basic" { loop.run(); } -test "std.event.Loop - call" { - // https://github.com/ziglang/zig/issues/1908 - if (builtin.single_threaded) return error.SkipZigTest; - - var loop: Loop = undefined; - try loop.initMultiThreaded(); - defer loop.deinit(); - - var did_it = false; - var handle = async Loop.call(testEventLoop); - var handle2 = async Loop.call(testEventLoop2, &handle, &did_it); - - loop.run(); - - testing.expect(did_it); -} - async fn testEventLoop() i32 { return 1234; } diff --git a/lib/std/event/rwlock.zig b/lib/std/event/rwlock.zig @@ -13,17 +13,17 @@ const Loop = std.event.Loop; /// When a write lock is held, it will not be released until the writer queue is empty. /// TODO: make this API also work in blocking I/O mode pub const RwLock = struct { - shared_state: u8, // TODO make this an enum + shared_state: State, writer_queue: Queue, reader_queue: Queue, writer_queue_empty_bit: u8, // TODO make this a bool reader_queue_empty_bit: u8, // TODO make this a bool reader_lock_count: usize, - const State = struct { - const Unlocked = 0; - const WriteLock = 1; - const ReadLock = 2; + const State = enum(u8) { + Unlocked, + WriteLock, + ReadLock, }; const Queue = std.atomic.Queue(anyframe); @@ -40,8 +40,8 @@ pub const RwLock = struct { return; } - _ = @atomicRmw(u8, &self.lock.reader_queue_empty_bit, .Xchg, 1, .SeqCst); - if (@cmpxchgStrong(u8, &self.lock.shared_state, State.ReadLock, State.Unlocked, .SeqCst, .SeqCst) != null) { + @atomicStore(u8, &self.lock.reader_queue_empty_bit, 1, .SeqCst); + if (@cmpxchgStrong(State, &self.lock.shared_state, .ReadLock, .Unlocked, .SeqCst, .SeqCst) != null) { // Didn't unlock. Someone else's problem. return; } @@ -64,15 +64,15 @@ pub const RwLock = struct { // We need to release the write lock. Check if any readers are waiting to grab the lock. if (@atomicLoad(u8, &self.lock.reader_queue_empty_bit, .SeqCst) == 0) { // Switch to a read lock. - _ = @atomicRmw(u8, &self.lock.shared_state, .Xchg, State.ReadLock, .SeqCst); + @atomicStore(State, &self.lock.shared_state, .ReadLock, .SeqCst); while (self.lock.reader_queue.get()) |node| { global_event_loop.onNextTick(node); } return; } - _ = @atomicRmw(u8, &self.lock.writer_queue_empty_bit, .Xchg, 1, .SeqCst); - _ = @atomicRmw(u8, &self.lock.shared_state, .Xchg, State.Unlocked, .SeqCst); + @atomicStore(u8, &self.lock.writer_queue_empty_bit, 1, .SeqCst); + @atomicStore(State, &self.lock.shared_state, .Unlocked, .SeqCst); self.lock.commonPostUnlock(); } @@ -80,7 +80,7 @@ pub const RwLock = struct { pub fn init() RwLock { return RwLock{ - .shared_state = State.Unlocked, + .shared_state = .Unlocked, .writer_queue = Queue.init(), .writer_queue_empty_bit = 1, .reader_queue = Queue.init(), @@ -92,7 +92,7 @@ pub const RwLock = struct { /// Must be called when not locked. Not thread safe. /// All calls to acquire() and release() must complete before calling deinit(). pub fn deinit(self: *RwLock) void { - assert(self.shared_state == State.Unlocked); + assert(self.shared_state == .Unlocked); while (self.writer_queue.get()) |node| resume node.data; while (self.reader_queue.get()) |node| resume node.data; } @@ -113,10 +113,10 @@ pub const RwLock = struct { // We set this bit so that later we can rely on the fact, that if reader_queue_empty_bit is 1, // some actor will attempt to grab the lock. - _ = @atomicRmw(u8, &self.reader_queue_empty_bit, .Xchg, 0, .SeqCst); + @atomicStore(u8, &self.reader_queue_empty_bit, 0, .SeqCst); // Here we don't care if we are the one to do the locking or if it was already locked for reading. - const have_read_lock = if (@cmpxchgStrong(u8, &self.shared_state, State.Unlocked, State.ReadLock, .SeqCst, .SeqCst)) |old_state| old_state == State.ReadLock else true; + const have_read_lock = if (@cmpxchgStrong(State, &self.shared_state, .Unlocked, .ReadLock, .SeqCst, .SeqCst)) |old_state| old_state == .ReadLock else true; if (have_read_lock) { // Give out all the read locks. if (self.reader_queue.get()) |first_node| { @@ -144,10 +144,10 @@ pub const RwLock = struct { // We set this bit so that later we can rely on the fact, that if writer_queue_empty_bit is 1, // some actor will attempt to grab the lock. - _ = @atomicRmw(u8, &self.writer_queue_empty_bit, .Xchg, 0, .SeqCst); + @atomicStore(u8, &self.writer_queue_empty_bit, 0, .SeqCst); // Here we must be the one to acquire the write lock. It cannot already be locked. - if (@cmpxchgStrong(u8, &self.shared_state, State.Unlocked, State.WriteLock, .SeqCst, .SeqCst) == null) { + if (@cmpxchgStrong(State, &self.shared_state, .Unlocked, .WriteLock, .SeqCst, .SeqCst) == null) { // We now have a write lock. if (self.writer_queue.get()) |node| { // Whether this node is us or someone else, we tail resume it. @@ -166,7 +166,7 @@ pub const RwLock = struct { // But if there's a writer_queue item or a reader_queue item, // we are the actor which must loop and attempt to grab the lock again. if (@atomicLoad(u8, &self.writer_queue_empty_bit, .SeqCst) == 0) { - if (@cmpxchgStrong(u8, &self.shared_state, State.Unlocked, State.WriteLock, .SeqCst, .SeqCst) != null) { + if (@cmpxchgStrong(State, &self.shared_state, .Unlocked, .WriteLock, .SeqCst, .SeqCst) != null) { // We did not obtain the lock. Great, the queues are someone else's problem. return; } @@ -176,13 +176,13 @@ pub const RwLock = struct { return; } // Release the lock again. - _ = @atomicRmw(u8, &self.writer_queue_empty_bit, .Xchg, 1, .SeqCst); - _ = @atomicRmw(u8, &self.shared_state, .Xchg, State.Unlocked, .SeqCst); + @atomicStore(u8, &self.writer_queue_empty_bit, 1, .SeqCst); + @atomicStore(State, &self.shared_state, .Unlocked, .SeqCst); continue; } if (@atomicLoad(u8, &self.reader_queue_empty_bit, .SeqCst) == 0) { - if (@cmpxchgStrong(u8, &self.shared_state, State.Unlocked, State.ReadLock, .SeqCst, .SeqCst) != null) { + if (@cmpxchgStrong(State, &self.shared_state, .Unlocked, .ReadLock, .SeqCst, .SeqCst) != null) { // We did not obtain the lock. Great, the queues are someone else's problem. return; } @@ -195,8 +195,8 @@ pub const RwLock = struct { return; } // Release the lock again. - _ = @atomicRmw(u8, &self.reader_queue_empty_bit, .Xchg, 1, .SeqCst); - if (@cmpxchgStrong(u8, &self.shared_state, State.ReadLock, State.Unlocked, .SeqCst, .SeqCst) != null) { + @atomicStore(u8, &self.reader_queue_empty_bit, 1, .SeqCst); + if (@cmpxchgStrong(State, &self.shared_state, .ReadLock, .Unlocked, .SeqCst, .SeqCst) != null) { // Didn't unlock. Someone else's problem. return; } diff --git a/lib/std/fifo.zig b/lib/std/fifo.zig @@ -257,7 +257,7 @@ test "ByteFifo" { defer fifo.deinit(); try fifo.write("HELLO"); - testing.expectEqual(usize(5), fifo.readableLength()); + testing.expectEqual(@as(usize, 5), fifo.readableLength()); testing.expectEqualSlices(u8, "HELLO", fifo.readableSlice(0)); { @@ -265,34 +265,34 @@ test "ByteFifo" { while (i < 5) : (i += 1) { try fifo.write([_]u8{try fifo.peekItem(i)}); } - testing.expectEqual(usize(10), fifo.readableLength()); + testing.expectEqual(@as(usize, 10), fifo.readableLength()); testing.expectEqualSlices(u8, "HELLOHELLO", fifo.readableSlice(0)); } { - testing.expectEqual(u8('H'), try fifo.readItem()); - testing.expectEqual(u8('E'), try fifo.readItem()); - testing.expectEqual(u8('L'), try fifo.readItem()); - testing.expectEqual(u8('L'), try fifo.readItem()); - testing.expectEqual(u8('O'), try fifo.readItem()); + testing.expectEqual(@as(u8, 'H'), try fifo.readItem()); + testing.expectEqual(@as(u8, 'E'), try fifo.readItem()); + testing.expectEqual(@as(u8, 'L'), try fifo.readItem()); + testing.expectEqual(@as(u8, 'L'), try fifo.readItem()); + testing.expectEqual(@as(u8, 'O'), try fifo.readItem()); } - testing.expectEqual(usize(5), fifo.readableLength()); + testing.expectEqual(@as(usize, 5), fifo.readableLength()); { // Writes that wrap around - testing.expectEqual(usize(11), fifo.writableLength()); - testing.expectEqual(usize(6), fifo.writableSlice(0).len); + testing.expectEqual(@as(usize, 11), fifo.writableLength()); + testing.expectEqual(@as(usize, 6), fifo.writableSlice(0).len); fifo.writeAssumeCapacity("6<chars<11"); testing.expectEqualSlices(u8, "HELLO6<char", fifo.readableSlice(0)); testing.expectEqualSlices(u8, "s<11", fifo.readableSlice(11)); fifo.discard(11); testing.expectEqualSlices(u8, "s<11", fifo.readableSlice(0)); fifo.discard(4); - testing.expectEqual(usize(0), fifo.readableLength()); + testing.expectEqual(@as(usize, 0), fifo.readableLength()); } { const buf = try fifo.writeableWithSize(12); - testing.expectEqual(usize(12), buf.len); + testing.expectEqual(@as(usize, 12), buf.len); var i: u8 = 0; while (i < 10) : (i += 1) { buf[i] = i + 'a'; @@ -313,6 +313,6 @@ test "ByteFifo" { try fifo.print("{}, {}!", "Hello", "World"); var result: [30]u8 = undefined; testing.expectEqualSlices(u8, "Hello, World!", fifo.read(&result)); - testing.expectEqual(usize(0), fifo.readableLength()); + testing.expectEqual(@as(usize, 0), fifo.readableLength()); } } diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig @@ -167,6 +167,10 @@ pub fn format( '}' => { const arg_to_print = comptime nextArg(&used_pos_args, maybe_pos_arg, &next_arg); + if (arg_to_print >= args.len) { + @compileError("Too few arguments"); + } + try formatType( args[arg_to_print], fmt[0..0], @@ -378,10 +382,10 @@ pub fn formatType( const info = @typeInfo(T).Union; if (info.tag_type) |UnionTagType| { try output(context, "{ ."); - try output(context, @tagName(UnionTagType(value))); + try output(context, @tagName(@as(UnionTagType, value))); try output(context, " = "); inline for (info.fields) |u_field| { - if (@enumToInt(UnionTagType(value)) == u_field.enum_field.?.value) { + if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) { try formatType(@field(value, u_field.name), "", options, context, Errors, output, max_depth - 1); } } @@ -499,7 +503,7 @@ pub fn formatIntValue( const int_value = if (@typeOf(value) == comptime_int) blk: { const Int = math.IntFittingRange(value, value); - break :blk Int(value); + break :blk @as(Int, value); } else value; @@ -508,7 +512,7 @@ pub fn formatIntValue( uppercase = false; } else if (comptime std.mem.eql(u8, fmt, "c")) { if (@typeOf(int_value).bit_count <= 8) { - return formatAsciiChar(u8(int_value), options, context, Errors, output); + return formatAsciiChar(@as(u8, int_value), options, context, Errors, output); } else { @compileError("Cannot print integer that is larger than 8 bits as a ascii"); } @@ -574,7 +578,7 @@ pub fn formatAsciiChar( comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void, ) Errors!void { - return output(context, (*const [1]u8)(&c)[0..]); + return output(context, @as(*const [1]u8, &c)[0..]); } pub fn formatBuf( @@ -590,7 +594,7 @@ pub fn formatBuf( var leftover_padding = if (width > buf.len) (width - buf.len) else return; const pad_byte: u8 = options.fill; while (leftover_padding > 0) : (leftover_padding -= 1) { - try output(context, (*const [1]u8)(&pad_byte)[0..1]); + try output(context, @as(*const [1]u8, &pad_byte)[0..1]); } } @@ -664,7 +668,7 @@ pub fn formatFloatScientific( try output(context, float_decimal.digits[0..1]); try output(context, "."); if (float_decimal.digits.len > 1) { - const num_digits = if (@typeOf(value) == f32) math.min(usize(9), float_decimal.digits.len) else float_decimal.digits.len; + const num_digits = if (@typeOf(value) == f32) math.min(@as(usize, 9), float_decimal.digits.len) else float_decimal.digits.len; try output(context, float_decimal.digits[1..num_digits]); } else { @@ -699,7 +703,7 @@ pub fn formatFloatDecimal( comptime Errors: type, output: fn (@typeOf(context), []const u8) Errors!void, ) Errors!void { - var x = f64(value); + var x = @as(f64, value); // Errol doesn't handle these special cases. if (math.signbit(x)) { @@ -888,7 +892,7 @@ pub fn formatInt( ) Errors!void { const int_value = if (@typeOf(value) == comptime_int) blk: { const Int = math.IntFittingRange(value, value); - break :blk Int(value); + break :blk @as(Int, value); } else value; @@ -917,14 +921,14 @@ fn formatIntSigned( const uint = @IntType(false, @typeOf(value).bit_count); if (value < 0) { const minus_sign: u8 = '-'; - try output(context, (*const [1]u8)(&minus_sign)[0..]); + try output(context, @as(*const [1]u8, &minus_sign)[0..]); const new_value = @intCast(uint, -(value + 1)) + 1; return formatIntUnsigned(new_value, base, uppercase, new_options, context, Errors, output); } else if (options.width == null or options.width.? == 0) { return formatIntUnsigned(@intCast(uint, value), base, uppercase, options, context, Errors, output); } else { const plus_sign: u8 = '+'; - try output(context, (*const [1]u8)(&plus_sign)[0..]); + try output(context, @as(*const [1]u8, &plus_sign)[0..]); const new_value = @intCast(uint, value); return formatIntUnsigned(new_value, base, uppercase, new_options, context, Errors, output); } @@ -962,7 +966,7 @@ fn formatIntUnsigned( const zero_byte: u8 = options.fill; var leftover_padding = padding - index; while (true) { - try output(context, (*const [1]u8)(&zero_byte)[0..]); + try output(context, @as(*const [1]u8, &zero_byte)[0..]); leftover_padding -= 1; if (leftover_padding == 0) break; } @@ -994,7 +998,7 @@ fn formatIntCallback(context: *FormatIntBuf, bytes: []const u8) (error{}!void) { pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T { if (!T.is_signed) return parseUnsigned(T, buf, radix); - if (buf.len == 0) return T(0); + if (buf.len == 0) return @as(T, 0); if (buf[0] == '-') { return math.negate(try parseUnsigned(T, buf[1..], radix)); } else if (buf[0] == '+') { @@ -1084,7 +1088,7 @@ pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) { fn digitToChar(digit: u8, uppercase: bool) u8 { return switch (digit) { 0...9 => digit + '0', - 10...35 => digit + ((if (uppercase) u8('A') else u8('a')) - 10), + 10...35 => digit + ((if (uppercase) @as(u8, 'A') else @as(u8, 'a')) - 10), else => unreachable, }; } @@ -1130,19 +1134,19 @@ fn countSize(size: *usize, bytes: []const u8) (error{}!void) { test "bufPrintInt" { var buffer: [100]u8 = undefined; const buf = buffer[0..]; - testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 2, false, FormatOptions{}), "-101111000110000101001110")); - testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 10, false, FormatOptions{}), "-12345678")); - testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, false, FormatOptions{}), "-bc614e")); - testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, true, FormatOptions{}), "-BC614E")); + testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 2, false, FormatOptions{}), "-101111000110000101001110")); + testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 10, false, FormatOptions{}), "-12345678")); + testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 16, false, FormatOptions{}), "-bc614e")); + testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 16, true, FormatOptions{}), "-BC614E")); - testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(12345678), 10, true, FormatOptions{}), "12345678")); + testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 12345678), 10, true, FormatOptions{}), "12345678")); - testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(666), 10, false, FormatOptions{ .width = 6 }), " 666")); - testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, FormatOptions{ .width = 6 }), " 1234")); - testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, FormatOptions{ .width = 1 }), "1234")); + testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 666), 10, false, FormatOptions{ .width = 6 }), " 666")); + testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, false, FormatOptions{ .width = 6 }), " 1234")); + testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, false, FormatOptions{ .width = 1 }), "1234")); - testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(42), 10, false, FormatOptions{ .width = 3 }), "+42")); - testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-42), 10, false, FormatOptions{ .width = 3 }), "-42")); + testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, 42), 10, false, FormatOptions{ .width = 3 }), "+42")); + testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -42), 10, false, FormatOptions{ .width = 3 }), "-42")); } fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) []u8 { @@ -1204,8 +1208,8 @@ test "int.specifier" { } test "int.padded" { - try testFmt("u8: ' 1'", "u8: '{:4}'", u8(1)); - try testFmt("u8: 'xxx1'", "u8: '{:x<4}'", u8(1)); + try testFmt("u8: ' 1'", "u8: '{:4}'", @as(u8, 1)); + try testFmt("u8: 'xxx1'", "u8: '{:x<4}'", @as(u8, 1)); } test "buffer" { @@ -1283,8 +1287,8 @@ test "filesize" { // TODO https://github.com/ziglang/zig/issues/3289 return error.SkipZigTest; } - try testFmt("file size: 63MiB\n", "file size: {Bi}\n", usize(63 * 1024 * 1024)); - try testFmt("file size: 66.06MB\n", "file size: {B:.2}\n", usize(63 * 1024 * 1024)); + try testFmt("file size: 63MiB\n", "file size: {Bi}\n", @as(usize, 63 * 1024 * 1024)); + try testFmt("file size: 66.06MB\n", "file size: {B:.2}\n", @as(usize, 63 * 1024 * 1024)); } test "struct" { @@ -1321,10 +1325,10 @@ test "float.scientific" { // TODO https://github.com/ziglang/zig/issues/3289 return error.SkipZigTest; } - try testFmt("f32: 1.34000003e+00", "f32: {e}", f32(1.34)); - try testFmt("f32: 1.23400001e+01", "f32: {e}", f32(12.34)); - try testFmt("f64: -1.234e+11", "f64: {e}", f64(-12.34e10)); - try testFmt("f64: 9.99996e-40", "f64: {e}", f64(9.999960e-40)); + try testFmt("f32: 1.34000003e+00", "f32: {e}", @as(f32, 1.34)); + try testFmt("f32: 1.23400001e+01", "f32: {e}", @as(f32, 12.34)); + try testFmt("f64: -1.234e+11", "f64: {e}", @as(f64, -12.34e10)); + try testFmt("f64: 9.99996e-40", "f64: {e}", @as(f64, 9.999960e-40)); } test "float.scientific.precision" { @@ -1332,12 +1336,12 @@ test "float.scientific.precision" { // TODO https://github.com/ziglang/zig/issues/3289 return error.SkipZigTest; } - try testFmt("f64: 1.40971e-42", "f64: {e:.5}", f64(1.409706e-42)); - try testFmt("f64: 1.00000e-09", "f64: {e:.5}", f64(@bitCast(f32, u32(814313563)))); - try testFmt("f64: 7.81250e-03", "f64: {e:.5}", f64(@bitCast(f32, u32(1006632960)))); + try testFmt("f64: 1.40971e-42", "f64: {e:.5}", @as(f64, 1.409706e-42)); + try testFmt("f64: 1.00000e-09", "f64: {e:.5}", @as(f64, @bitCast(f32, @as(u32, 814313563)))); + try testFmt("f64: 7.81250e-03", "f64: {e:.5}", @as(f64, @bitCast(f32, @as(u32, 1006632960)))); // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05. // In fact, libc doesn't round a lot of 5 cases up when one past the precision point. - try testFmt("f64: 1.00001e+05", "f64: {e:.5}", f64(@bitCast(f32, u32(1203982400)))); + try testFmt("f64: 1.00001e+05", "f64: {e:.5}", @as(f64, @bitCast(f32, @as(u32, 1203982400)))); } test "float.special" { @@ -1360,21 +1364,21 @@ test "float.decimal" { // TODO https://github.com/ziglang/zig/issues/3289 return error.SkipZigTest; } - try testFmt("f64: 152314000000000000000000000000", "f64: {d}", f64(1.52314e+29)); - try testFmt("f32: 1.1", "f32: {d:.1}", f32(1.1234)); - try testFmt("f32: 1234.57", "f32: {d:.2}", f32(1234.567)); + try testFmt("f64: 152314000000000000000000000000", "f64: {d}", @as(f64, 1.52314e+29)); + try testFmt("f32: 1.1", "f32: {d:.1}", @as(f32, 1.1234)); + try testFmt("f32: 1234.57", "f32: {d:.2}", @as(f32, 1234.567)); // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64). // -11.12339... is rounded back up to -11.1234 - try testFmt("f32: -11.1234", "f32: {d:.4}", f32(-11.1234)); - try testFmt("f32: 91.12345", "f32: {d:.5}", f32(91.12345)); - try testFmt("f64: 91.1234567890", "f64: {d:.10}", f64(91.12345678901235)); - try testFmt("f64: 0.00000", "f64: {d:.5}", f64(0.0)); - try testFmt("f64: 6", "f64: {d:.0}", f64(5.700)); - try testFmt("f64: 10.0", "f64: {d:.1}", f64(9.999)); - try testFmt("f64: 1.000", "f64: {d:.3}", f64(1.0)); - try testFmt("f64: 0.00030000", "f64: {d:.8}", f64(0.0003)); - try testFmt("f64: 0.00000", "f64: {d:.5}", f64(1.40130e-45)); - try testFmt("f64: 0.00000", "f64: {d:.5}", f64(9.999960e-40)); + try testFmt("f32: -11.1234", "f32: {d:.4}", @as(f32, -11.1234)); + try testFmt("f32: 91.12345", "f32: {d:.5}", @as(f32, 91.12345)); + try testFmt("f64: 91.1234567890", "f64: {d:.10}", @as(f64, 91.12345678901235)); + try testFmt("f64: 0.00000", "f64: {d:.5}", @as(f64, 0.0)); + try testFmt("f64: 6", "f64: {d:.0}", @as(f64, 5.700)); + try testFmt("f64: 10.0", "f64: {d:.1}", @as(f64, 9.999)); + try testFmt("f64: 1.000", "f64: {d:.3}", @as(f64, 1.0)); + try testFmt("f64: 0.00030000", "f64: {d:.8}", @as(f64, 0.0003)); + try testFmt("f64: 0.00000", "f64: {d:.5}", @as(f64, 1.40130e-45)); + try testFmt("f64: 0.00000", "f64: {d:.5}", @as(f64, 9.999960e-40)); } test "float.libc.sanity" { @@ -1382,22 +1386,22 @@ test "float.libc.sanity" { // TODO https://github.com/ziglang/zig/issues/3289 return error.SkipZigTest; } - try testFmt("f64: 0.00001", "f64: {d:.5}", f64(@bitCast(f32, u32(916964781)))); - try testFmt("f64: 0.00001", "f64: {d:.5}", f64(@bitCast(f32, u32(925353389)))); - try testFmt("f64: 0.10000", "f64: {d:.5}", f64(@bitCast(f32, u32(1036831278)))); - try testFmt("f64: 1.00000", "f64: {d:.5}", f64(@bitCast(f32, u32(1065353133)))); - try testFmt("f64: 10.00000", "f64: {d:.5}", f64(@bitCast(f32, u32(1092616192)))); + try testFmt("f64: 0.00001", "f64: {d:.5}", @as(f64, @bitCast(f32, @as(u32, 916964781)))); + try testFmt("f64: 0.00001", "f64: {d:.5}", @as(f64, @bitCast(f32, @as(u32, 925353389)))); + try testFmt("f64: 0.10000", "f64: {d:.5}", @as(f64, @bitCast(f32, @as(u32, 1036831278)))); + try testFmt("f64: 1.00000", "f64: {d:.5}", @as(f64, @bitCast(f32, @as(u32, 1065353133)))); + try testFmt("f64: 10.00000", "f64: {d:.5}", @as(f64, @bitCast(f32, @as(u32, 1092616192)))); // libc differences // // This is 0.015625 exactly according to gdb. We thus round down, // however glibc rounds up for some reason. This occurs for all // floats of the form x.yyyy25 on a precision point. - try testFmt("f64: 0.01563", "f64: {d:.5}", f64(@bitCast(f32, u32(1015021568)))); + try testFmt("f64: 0.01563", "f64: {d:.5}", @as(f64, @bitCast(f32, @as(u32, 1015021568)))); // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3 // also rounds to 630 so I'm inclined to believe libc is not // optimal here. - try testFmt("f64: 18014400656965630.00000", "f64: {d:.5}", f64(@bitCast(f32, u32(1518338049)))); + try testFmt("f64: 18014400656965630.00000", "f64: {d:.5}", @as(f64, @bitCast(f32, @as(u32, 1518338049)))); } test "custom" { @@ -1673,17 +1677,17 @@ test "formatType max_depth" { } test "positional" { - try testFmt("2 1 0", "{2} {1} {0}", usize(0), usize(1), usize(2)); - try testFmt("2 1 0", "{2} {1} {}", usize(0), usize(1), usize(2)); - try testFmt("0 0", "{0} {0}", usize(0)); - try testFmt("0 1", "{} {1}", usize(0), usize(1)); - try testFmt("1 0 0 1", "{1} {} {0} {}", usize(0), usize(1)); + try testFmt("2 1 0", "{2} {1} {0}", @as(usize, 0), @as(usize, 1), @as(usize, 2)); + try testFmt("2 1 0", "{2} {1} {}", @as(usize, 0), @as(usize, 1), @as(usize, 2)); + try testFmt("0 0", "{0} {0}", @as(usize, 0)); + try testFmt("0 1", "{} {1}", @as(usize, 0), @as(usize, 1)); + try testFmt("1 0 0 1", "{1} {} {0} {}", @as(usize, 0), @as(usize, 1)); } test "positional with specifier" { - try testFmt("10.0", "{0d:.1}", f64(9.999)); + try testFmt("10.0", "{0d:.1}", @as(f64, 9.999)); } test "positional/alignment/width/precision" { - try testFmt("10.0", "{0d: >3.1}", f64(9.999)); + try testFmt("10.0", "{0d: >3.1}", @as(f64, 9.999)); } diff --git a/lib/std/fmt/errol.zig b/lib/std/fmt/errol.zig @@ -296,7 +296,7 @@ fn hpMul10(hp: *HP) void { /// @buf: The output buffer. /// &return: The exponent. fn errolInt(val: f64, buffer: []u8) FloatDecimal { - const pow19 = u128(1e19); + const pow19 = @as(u128, 1e19); assert((val > 9.007199254740992e15) and val < (3.40282366920938e38)); @@ -670,7 +670,7 @@ fn fpeint(from: f64) u128 { const bits = @bitCast(u64, from); assert((bits & ((1 << 52) - 1)) == 0); - return u128(1) << @truncate(u7, (bits >> 52) -% 1023); + return @as(u128, 1) << @truncate(u7, (bits >> 52) -% 1023); } /// Given two different integers with the same length in terms of the number diff --git a/lib/std/fmt/parse_float.zig b/lib/std/fmt/parse_float.zig @@ -59,29 +59,29 @@ const Z96 = struct { // d += s inline fn add(d: *Z96, s: Z96) void { - var w = u64(d.d0) + u64(s.d0); + var w = @as(u64, d.d0) + @as(u64, s.d0); d.d0 = @truncate(u32, w); w >>= 32; - w += u64(d.d1) + u64(s.d1); + w += @as(u64, d.d1) + @as(u64, s.d1); d.d1 = @truncate(u32, w); w >>= 32; - w += u64(d.d2) + u64(s.d2); + w += @as(u64, d.d2) + @as(u64, s.d2); d.d2 = @truncate(u32, w); } // d -= s inline fn sub(d: *Z96, s: Z96) void { - var w = u64(d.d0) -% u64(s.d0); + var w = @as(u64, d.d0) -% @as(u64, s.d0); d.d0 = @truncate(u32, w); w >>= 32; - w += u64(d.d1) -% u64(s.d1); + w += @as(u64, d.d1) -% @as(u64, s.d1); d.d1 = @truncate(u32, w); w >>= 32; - w += u64(d.d2) -% u64(s.d2); + w += @as(u64, d.d2) -% @as(u64, s.d2); d.d2 = @truncate(u32, w); } }; @@ -160,7 +160,7 @@ fn convertRepr(comptime T: type, n: FloatRepr) T { break :blk if (n.negative) f64_minus_zero else f64_plus_zero; } else if (s.d2 != 0) { const binexs2 = @intCast(u64, binary_exponent) << 52; - const rr = (u64(s.d2 & ~mask28) << 24) | ((u64(s.d1) + 128) >> 8) | binexs2; + const rr = (@as(u64, s.d2 & ~mask28) << 24) | ((@as(u64, s.d1) + 128) >> 8) | binexs2; break :blk if (n.negative) rr | (1 << 63) else rr; } else { break :blk 0; @@ -375,7 +375,7 @@ pub fn parseFloat(comptime T: type, s: []const u8) !T { return switch (try parseRepr(s, &r)) { ParseResult.Ok => convertRepr(T, r), ParseResult.PlusZero => 0.0, - ParseResult.MinusZero => -T(0.0), + ParseResult.MinusZero => -@as(T, 0.0), ParseResult.PlusInf => std.math.inf(T), ParseResult.MinusInf => -std.math.inf(T), }; @@ -426,8 +426,8 @@ test "fmt.parseFloat" { expect(approxEq(T, try parseFloat(T, "1234e-2"), 12.34, epsilon)); expect(approxEq(T, try parseFloat(T, "123142.1"), 123142.1, epsilon)); - expect(approxEq(T, try parseFloat(T, "-123142.1124"), T(-123142.1124), epsilon)); - expect(approxEq(T, try parseFloat(T, "0.7062146892655368"), T(0.7062146892655368), epsilon)); + expect(approxEq(T, try parseFloat(T, "-123142.1124"), @as(T, -123142.1124), epsilon)); + expect(approxEq(T, try parseFloat(T, "0.7062146892655368"), @as(T, 0.7062146892655368), epsilon)); } } } diff --git a/lib/std/fs.zig b/lib/std/fs.zig @@ -6,6 +6,7 @@ const base64 = std.base64; const crypto = std.crypto; const Allocator = std.mem.Allocator; const assert = std.debug.assert; +const math = std.math; pub const path = @import("fs/path.zig"); pub const File = @import("fs/file.zig").File; @@ -584,7 +585,7 @@ pub const Dir = struct { .FileBothDirectoryInformation, w.FALSE, null, - if (self.first) w.BOOLEAN(w.TRUE) else w.BOOLEAN(w.FALSE), + if (self.first) @as(w.BOOLEAN, w.TRUE) else @as(w.BOOLEAN, w.FALSE), ); self.first = false; if (io.Information == 0) return null; @@ -698,17 +699,81 @@ pub const Dir = struct { /// Call `File.close` on the result when done. pub fn openRead(self: Dir, sub_path: []const u8) File.OpenError!File { + if (builtin.os == .windows) { + const path_w = try os.windows.sliceToPrefixedFileW(sub_path); + return self.openReadW(&path_w); + } const path_c = try os.toPosixPath(sub_path); return self.openReadC(&path_c); } /// Call `File.close` on the result when done. pub fn openReadC(self: Dir, sub_path: [*]const u8) File.OpenError!File { - const flags = os.O_LARGEFILE | os.O_RDONLY | os.O_CLOEXEC; + if (builtin.os == .windows) { + const path_w = try os.windows.cStrToPrefixedFileW(sub_path); + return self.openReadW(&path_w); + } + const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0; + const flags = O_LARGEFILE | os.O_RDONLY | os.O_CLOEXEC; const fd = try os.openatC(self.fd, sub_path, flags, 0); return File.openHandle(fd); } + pub fn openReadW(self: Dir, sub_path_w: [*]const u16) File.OpenError!File { + const w = os.windows; + + var result = File{ .handle = undefined }; + + const path_len_bytes = math.cast(u16, mem.toSliceConst(u16, sub_path_w).len * 2) catch |err| switch (err) { + error.Overflow => return error.NameTooLong, + }; + var nt_name = w.UNICODE_STRING{ + .Length = path_len_bytes, + .MaximumLength = path_len_bytes, + .Buffer = @intToPtr([*]u16, @ptrToInt(sub_path_w)), + }; + var attr = w.OBJECT_ATTRIBUTES{ + .Length = @sizeOf(w.OBJECT_ATTRIBUTES), + .RootDirectory = if (path.isAbsoluteW(sub_path_w)) null else self.fd, + .Attributes = 0, // Note we do not use OBJ_CASE_INSENSITIVE here. + .ObjectName = &nt_name, + .SecurityDescriptor = null, + .SecurityQualityOfService = null, + }; + if (sub_path_w[0] == '.' and sub_path_w[1] == 0) { + return error.IsDir; + } + if (sub_path_w[0] == '.' and sub_path_w[1] == '.' and sub_path_w[2] == 0) { + return error.IsDir; + } + var io: w.IO_STATUS_BLOCK = undefined; + const rc = w.ntdll.NtCreateFile( + &result.handle, + w.GENERIC_READ | w.SYNCHRONIZE, + &attr, + &io, + null, + w.FILE_ATTRIBUTE_NORMAL, + w.FILE_SHARE_READ, + w.FILE_OPEN, + w.FILE_NON_DIRECTORY_FILE | w.FILE_SYNCHRONOUS_IO_NONALERT, + null, + 0, + ); + switch (rc) { + w.STATUS.SUCCESS => return result, + w.STATUS.OBJECT_NAME_INVALID => unreachable, + w.STATUS.OBJECT_NAME_NOT_FOUND => return error.FileNotFound, + w.STATUS.OBJECT_PATH_NOT_FOUND => return error.FileNotFound, + w.STATUS.INVALID_PARAMETER => unreachable, + w.STATUS.SHARING_VIOLATION => return error.SharingViolation, + w.STATUS.ACCESS_DENIED => return error.AccessDenied, + w.STATUS.PIPE_BUSY => return error.PipeBusy, + w.STATUS.OBJECT_PATH_SYNTAX_BAD => unreachable, + else => return w.unexpectedStatus(rc), + } + } + /// Call `close` on the result when done. pub fn openDir(self: Dir, sub_path: []const u8) OpenError!Dir { if (builtin.os == .windows) { @@ -866,6 +931,34 @@ pub const Dir = struct { return os.readlinkatC(self.fd, sub_path_c, buffer); } + /// On success, caller owns returned buffer. + /// If the file is larger than `max_bytes`, returns `error.FileTooBig`. + pub fn readFileAlloc(self: Dir, allocator: *mem.Allocator, file_path: []const u8, max_bytes: usize) ![]u8 { + return self.readFileAllocAligned(allocator, file_path, max_bytes, @alignOf(u8)); + } + + /// On success, caller owns returned buffer. + /// If the file is larger than `max_bytes`, returns `error.FileTooBig`. + pub fn readFileAllocAligned( + self: Dir, + allocator: *mem.Allocator, + file_path: []const u8, + max_bytes: usize, + comptime A: u29, + ) ![]align(A) u8 { + var file = try self.openRead(file_path); + defer file.close(); + + const size = math.cast(usize, try file.getEndPos()) catch math.maxInt(usize); + if (size > max_bytes) return error.FileTooBig; + + const buf = try allocator.alignedAlloc(u8, A, size); + errdefer allocator.free(buf); + + try file.inStream().stream.readNoEof(buf); + return buf; + } + pub const DeleteTreeError = error{ AccessDenied, FileTooBig, @@ -1100,7 +1193,7 @@ pub const Walker = struct { } pub fn deinit(self: *Walker) void { - while (self.stack.popOrNull()) |*item| item.dir_it.close(); + while (self.stack.popOrNull()) |*item| item.dir_it.dir.close(); self.stack.deinit(); self.name_buffer.deinit(); } @@ -1150,9 +1243,9 @@ pub fn openSelfExe() OpenSelfExeError!File { return File.openReadC(c"/proc/self/exe"); } if (builtin.os == .windows) { - var buf: [os.windows.PATH_MAX_WIDE]u16 = undefined; - const wide_slice = try selfExePathW(&buf); - return File.openReadW(wide_slice.ptr); + const wide_slice = selfExePathW(); + const prefixed_path_w = try os.windows.wToPrefixedFileW(wide_slice); + return Dir.cwd().openReadW(&prefixed_path_w); } var buf: [MAX_PATH_BYTES]u8 = undefined; const self_exe_path = try selfExePath(&buf); @@ -1203,8 +1296,7 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 { return mem.toSlice(u8, out_buffer); }, .windows => { - var utf16le_buf: [os.windows.PATH_MAX_WIDE]u16 = undefined; - const utf16le_slice = try selfExePathW(&utf16le_buf); + const utf16le_slice = selfExePathW(); // Trust that Windows gives us valid UTF-16LE. const end_index = std.unicode.utf16leToUtf8(out_buffer, utf16le_slice) catch unreachable; return out_buffer[0..end_index]; @@ -1213,9 +1305,10 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 { } } -/// Same as `selfExePath` except the result is UTF16LE-encoded. -pub fn selfExePathW(out_buffer: *[os.windows.PATH_MAX_WIDE]u16) SelfExePathError![]u16 { - return os.windows.GetModuleFileNameW(null, out_buffer, out_buffer.len); +/// The result is UTF16LE-encoded. +pub fn selfExePathW() []const u16 { + const image_path_name = &os.windows.peb().ProcessParameters.ImagePathName; + return mem.toSliceConst(u16, image_path_name.Buffer); } /// `selfExeDirPath` except allocates the result on the heap. diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig @@ -25,42 +25,23 @@ pub const File = struct { pub const OpenError = windows.CreateFileError || os.OpenError; - /// Call close to clean up. + /// Deprecated; call `std.fs.Dir.openRead` directly. pub fn openRead(path: []const u8) OpenError!File { - if (builtin.os == .windows) { - const path_w = try windows.sliceToPrefixedFileW(path); - return openReadW(&path_w); - } - const path_c = try os.toPosixPath(path); - return openReadC(&path_c); + return std.fs.Dir.cwd().openRead(path); } - /// `openRead` except with a null terminated path - pub fn openReadC(path: [*]const u8) OpenError!File { - if (builtin.os == .windows) { - const path_w = try windows.cStrToPrefixedFileW(path); - return openReadW(&path_w); - } - const flags = os.O_LARGEFILE | os.O_RDONLY | os.O_CLOEXEC; - const fd = try os.openC(path, flags, 0); - return openHandle(fd); + /// Deprecated; call `std.fs.Dir.openReadC` directly. + pub fn openReadC(path_c: [*]const u8) OpenError!File { + return std.fs.Dir.cwd().openReadC(path_c); } - /// `openRead` except with a null terminated UTF16LE encoded path + /// Deprecated; call `std.fs.Dir.openReadW` directly. pub fn openReadW(path_w: [*]const u16) OpenError!File { - const handle = try windows.CreateFileW( - path_w, - windows.GENERIC_READ, - windows.FILE_SHARE_READ, - null, - windows.OPEN_EXISTING, - windows.FILE_ATTRIBUTE_NORMAL, - null, - ); - return openHandle(handle); + return std.fs.Dir.cwd().openReadW(path_w); } /// Calls `openWriteMode` with `default_mode` for the mode. + /// TODO: deprecate this and move it to `std.fs.Dir`. pub fn openWrite(path: []const u8) OpenError!File { return openWriteMode(path, default_mode); } @@ -68,6 +49,7 @@ pub const File = struct { /// If the path does not exist it will be created. /// If a file already exists in the destination it will be truncated. /// Call close to clean up. + /// TODO: deprecate this and move it to `std.fs.Dir`. pub fn openWriteMode(path: []const u8, file_mode: Mode) OpenError!File { if (builtin.os == .windows) { const path_w = try windows.sliceToPrefixedFileW(path); @@ -78,17 +60,20 @@ pub const File = struct { } /// Same as `openWriteMode` except `path` is null-terminated. + /// TODO: deprecate this and move it to `std.fs.Dir`. pub fn openWriteModeC(path: [*]const u8, file_mode: Mode) OpenError!File { if (builtin.os == .windows) { const path_w = try windows.cStrToPrefixedFileW(path); return openWriteModeW(&path_w, file_mode); } - const flags = os.O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_TRUNC; + const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0; + const flags = O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_TRUNC; const fd = try os.openC(path, flags, file_mode); return openHandle(fd); } /// Same as `openWriteMode` except `path` is null-terminated and UTF16LE encoded + /// TODO: deprecate this and move it to `std.fs.Dir`. pub fn openWriteModeW(path_w: [*]const u16, file_mode: Mode) OpenError!File { const handle = try windows.CreateFileW( path_w, @@ -105,6 +90,7 @@ pub const File = struct { /// If the path does not exist it will be created. /// If a file already exists in the destination this returns OpenError.PathAlreadyExists /// Call close to clean up. + /// TODO: deprecate this and move it to `std.fs.Dir`. pub fn openWriteNoClobber(path: []const u8, file_mode: Mode) OpenError!File { if (builtin.os == .windows) { const path_w = try windows.sliceToPrefixedFileW(path); @@ -114,16 +100,19 @@ pub const File = struct { return openWriteNoClobberC(&path_c, file_mode); } + /// TODO: deprecate this and move it to `std.fs.Dir`. pub fn openWriteNoClobberC(path: [*]const u8, file_mode: Mode) OpenError!File { if (builtin.os == .windows) { const path_w = try windows.cStrToPrefixedFileW(path); return openWriteNoClobberW(&path_w, file_mode); } - const flags = os.O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_EXCL; + const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0; + const flags = O_LARGEFILE | os.O_WRONLY | os.O_CREAT | os.O_CLOEXEC | os.O_EXCL; const fd = try os.openC(path, flags, file_mode); return openHandle(fd); } + /// TODO: deprecate this and move it to `std.fs.Dir`. pub fn openWriteNoClobberW(path_w: [*]const u16, file_mode: Mode) OpenError!File { const handle = try windows.CreateFileW( path_w, @@ -146,16 +135,19 @@ pub const File = struct { /// In general it is recommended to avoid this function. For example, /// instead of testing if a file exists and then opening it, just /// open it and handle the error for file not found. + /// TODO: deprecate this and move it to `std.fs.Dir`. pub fn access(path: []const u8) !void { return os.access(path, os.F_OK); } /// Same as `access` except the parameter is null-terminated. + /// TODO: deprecate this and move it to `std.fs.Dir`. pub fn accessC(path: [*]const u8) !void { return os.accessC(path, os.F_OK); } /// Same as `access` except the parameter is null-terminated UTF16LE-encoded. + /// TODO: deprecate this and move it to `std.fs.Dir`. pub fn accessW(path: [*]const u16) !void { return os.accessW(path, os.F_OK); } @@ -272,9 +264,9 @@ pub const File = struct { return Stat{ .size = @bitCast(u64, st.size), .mode = st.mode, - .atime = i64(atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec, - .mtime = i64(mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec, - .ctime = i64(ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec, + .atime = @as(i64, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec, + .mtime = @as(i64, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec, + .ctime = @as(i64, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec, }; } diff --git a/lib/std/fs/path.zig b/lib/std/fs/path.zig @@ -32,7 +32,7 @@ pub fn isSep(byte: u8) bool { /// This is different from mem.join in that the separator will not be repeated if /// it is found at the end or beginning of a pair of consecutive paths. fn joinSep(allocator: *Allocator, separator: u8, paths: []const []const u8) ![]u8 { - if (paths.len == 0) return (([*]u8)(undefined))[0..0]; + if (paths.len == 0) return &[0]u8{}; const total_len = blk: { var sum: usize = paths[0].len; diff --git a/lib/std/hash/auto_hash.zig b/lib/std/hash/auto_hash.zig @@ -306,7 +306,7 @@ test "hash struct deep" { test "testHash optional" { const a: ?u32 = 123; const b: ?u32 = null; - testing.expectEqual(testHash(a), testHash(u32(123))); + testing.expectEqual(testHash(a), testHash(@as(u32, 123))); testing.expect(testHash(a) != testHash(b)); testing.expectEqual(testHash(b), 0); } @@ -315,9 +315,9 @@ test "testHash array" { const a = [_]u32{ 1, 2, 3 }; const h = testHash(a); var hasher = Wyhash.init(0); - autoHash(&hasher, u32(1)); - autoHash(&hasher, u32(2)); - autoHash(&hasher, u32(3)); + autoHash(&hasher, @as(u32, 1)); + autoHash(&hasher, @as(u32, 2)); + autoHash(&hasher, @as(u32, 3)); testing.expectEqual(h, hasher.final()); } @@ -330,9 +330,9 @@ test "testHash struct" { const f = Foo{}; const h = testHash(f); var hasher = Wyhash.init(0); - autoHash(&hasher, u32(1)); - autoHash(&hasher, u32(2)); - autoHash(&hasher, u32(3)); + autoHash(&hasher, @as(u32, 1)); + autoHash(&hasher, @as(u32, 2)); + autoHash(&hasher, @as(u32, 3)); testing.expectEqual(h, hasher.final()); } diff --git a/lib/std/hash/cityhash.zig b/lib/std/hash/cityhash.zig @@ -214,7 +214,7 @@ pub const CityHash64 = struct { } fn hashLen0To16(str: []const u8) u64 { - const len: u64 = u64(str.len); + const len: u64 = @as(u64, str.len); if (len >= 8) { const mul: u64 = k2 +% len *% 2; const a: u64 = fetch64(str.ptr) +% k2; @@ -240,7 +240,7 @@ pub const CityHash64 = struct { } fn hashLen17To32(str: []const u8) u64 { - const len: u64 = u64(str.len); + const len: u64 = @as(u64, str.len); const mul: u64 = k2 +% len *% 2; const a: u64 = fetch64(str.ptr) *% k1; const b: u64 = fetch64(str.ptr + 8); @@ -251,7 +251,7 @@ pub const CityHash64 = struct { } fn hashLen33To64(str: []const u8) u64 { - const len: u64 = u64(str.len); + const len: u64 = @as(u64, str.len); const mul: u64 = k2 +% len *% 2; const a: u64 = fetch64(str.ptr) *% k2; const b: u64 = fetch64(str.ptr + 8); @@ -305,7 +305,7 @@ pub const CityHash64 = struct { return hashLen33To64(str); } - var len: u64 = u64(str.len); + var len: u64 = @as(u64, str.len); var x: u64 = fetch64(str.ptr + str.len - 40); var y: u64 = fetch64(str.ptr + str.len - 16) +% fetch64(str.ptr + str.len - 56); diff --git a/lib/std/hash/crc.zig b/lib/std/hash/crc.zig @@ -65,10 +65,10 @@ pub fn Crc32WithPoly(comptime poly: u32) type { const p = input[i .. i + 8]; // Unrolling this way gives ~50Mb/s increase - self.crc ^= (u32(p[0]) << 0); - self.crc ^= (u32(p[1]) << 8); - self.crc ^= (u32(p[2]) << 16); - self.crc ^= (u32(p[3]) << 24); + self.crc ^= (@as(u32, p[0]) << 0); + self.crc ^= (@as(u32, p[1]) << 8); + self.crc ^= (@as(u32, p[2]) << 16); + self.crc ^= (@as(u32, p[3]) << 24); self.crc = lookup_tables[0][p[7]] ^ diff --git a/lib/std/hash/murmur.zig b/lib/std/hash/murmur.zig @@ -98,7 +98,7 @@ pub const Murmur2_64 = struct { pub fn hashWithSeed(str: []const u8, seed: u64) u64 { const m: u64 = 0xc6a4a7935bd1e995; - const len = u64(str.len); + const len = @as(u64, str.len); var h1: u64 = seed ^ (len *% m); for (@ptrCast([*]allowzero align(1) const u64, str.ptr)[0..@intCast(usize, len >> 3)]) |v| { var k1: u64 = v; diff --git a/lib/std/hash/siphash.zig b/lib/std/hash/siphash.zig @@ -102,7 +102,7 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round } const b2 = self.v0 ^ self.v1 ^ self.v2 ^ self.v3; - return (u128(b2) << 64) | b1; + return (@as(u128, b2) << 64) | b1; } fn round(self: *Self, b: []const u8) void { @@ -121,19 +121,19 @@ fn SipHashStateless(comptime T: type, comptime c_rounds: usize, comptime d_round fn sipRound(d: *Self) void { d.v0 +%= d.v1; - d.v1 = math.rotl(u64, d.v1, u64(13)); + d.v1 = math.rotl(u64, d.v1, @as(u64, 13)); d.v1 ^= d.v0; - d.v0 = math.rotl(u64, d.v0, u64(32)); + d.v0 = math.rotl(u64, d.v0, @as(u64, 32)); d.v2 +%= d.v3; - d.v3 = math.rotl(u64, d.v3, u64(16)); + d.v3 = math.rotl(u64, d.v3, @as(u64, 16)); d.v3 ^= d.v2; d.v0 +%= d.v3; - d.v3 = math.rotl(u64, d.v3, u64(21)); + d.v3 = math.rotl(u64, d.v3, @as(u64, 21)); d.v3 ^= d.v0; d.v2 +%= d.v1; - d.v1 = math.rotl(u64, d.v1, u64(17)); + d.v1 = math.rotl(u64, d.v1, @as(u64, 17)); d.v1 ^= d.v2; - d.v2 = math.rotl(u64, d.v2, u64(32)); + d.v2 = math.rotl(u64, d.v2, @as(u64, 32)); } pub fn hash(key: []const u8, input: []const u8) T { diff --git a/lib/std/hash_map.zig b/lib/std/hash_map.zig @@ -402,7 +402,7 @@ pub fn HashMap(comptime K: type, comptime V: type, comptime hash: fn (key: K) u3 } fn keyToIndex(hm: Self, key: K) usize { - return hm.constrainIndex(usize(hash(key))); + return hm.constrainIndex(@as(usize, hash(key))); } fn constrainIndex(hm: Self, i: usize) usize { diff --git a/lib/std/heap.zig b/lib/std/heap.zig @@ -41,8 +41,7 @@ var direct_allocator_state = Allocator{ const DirectAllocator = struct { fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 { - if (n == 0) - return (([*]u8)(undefined))[0..0]; + if (n == 0) return &[0]u8{}; if (builtin.os == .windows) { const w = os.windows; @@ -261,8 +260,7 @@ pub const HeapAllocator = switch (builtin.os) { fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 { const self = @fieldParentPtr(HeapAllocator, "allocator", allocator); - if (n == 0) - return (([*]u8)(undefined))[0..0]; + if (n == 0) return &[0]u8{}; const amt = n + alignment + @sizeOf(usize); const optional_heap_handle = @atomicLoad(?HeapHandle, &self.heap_handle, builtin.AtomicOrder.SeqCst); @@ -677,7 +675,7 @@ pub fn StackFallbackAllocator(comptime size: usize) type { ) catch { const result = try self.fallback_allocator.reallocFn( self.fallback_allocator, - ([*]u8)(undefined)[0..0], + &[0]u8{}, undefined, new_size, new_align, @@ -895,10 +893,10 @@ fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!vo if (mem.page_size << 2 > maxInt(usize)) return; const USizeShift = @IntType(false, std.math.log2(usize.bit_count)); - const large_align = u29(mem.page_size << 2); + const large_align = @as(u29, mem.page_size << 2); var align_mask: usize = undefined; - _ = @shlWithOverflow(usize, ~usize(0), USizeShift(@ctz(u29, large_align)), &align_mask); + _ = @shlWithOverflow(usize, ~@as(usize, 0), @as(USizeShift, @ctz(u29, large_align)), &align_mask); var slice = try allocator.alignedAlloc(u8, large_align, 500); testing.expect(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); diff --git a/lib/std/http/headers.zig b/lib/std/http/headers.zig @@ -399,7 +399,7 @@ test "Headers.iterator" { } count += 1; } - testing.expectEqual(i32(2), count); + testing.expectEqual(@as(i32, 2), count); } test "Headers.contains" { @@ -420,10 +420,10 @@ test "Headers.delete" { try h.append("cookie", "somevalue", null); testing.expectEqual(false, h.delete("not-present")); - testing.expectEqual(usize(3), h.count()); + testing.expectEqual(@as(usize, 3), h.count()); testing.expectEqual(true, h.delete("foo")); - testing.expectEqual(usize(2), h.count()); + testing.expectEqual(@as(usize, 2), h.count()); { const e = h.at(0); testing.expectEqualSlices(u8, "baz", e.name); @@ -448,7 +448,7 @@ test "Headers.orderedRemove" { try h.append("cookie", "somevalue", null); h.orderedRemove(0); - testing.expectEqual(usize(2), h.count()); + testing.expectEqual(@as(usize, 2), h.count()); { const e = h.at(0); testing.expectEqualSlices(u8, "baz", e.name); @@ -471,7 +471,7 @@ test "Headers.swapRemove" { try h.append("cookie", "somevalue", null); h.swapRemove(0); - testing.expectEqual(usize(2), h.count()); + testing.expectEqual(@as(usize, 2), h.count()); { const e = h.at(0); testing.expectEqualSlices(u8, "cookie", e.name); diff --git a/lib/std/io.zig b/lib/std/io.zig @@ -34,28 +34,23 @@ else Mode.blocking; pub const is_async = mode != .blocking; -pub const GetStdIoError = os.windows.GetStdHandleError; - -pub fn getStdOut() GetStdIoError!File { +pub fn getStdOut() File { if (builtin.os == .windows) { - const handle = try os.windows.GetStdHandle(os.windows.STD_OUTPUT_HANDLE); - return File.openHandle(handle); + return File.openHandle(os.windows.peb().ProcessParameters.hStdOutput); } return File.openHandle(os.STDOUT_FILENO); } -pub fn getStdErr() GetStdIoError!File { +pub fn getStdErr() File { if (builtin.os == .windows) { - const handle = try os.windows.GetStdHandle(os.windows.STD_ERROR_HANDLE); - return File.openHandle(handle); + return File.openHandle(os.windows.peb().ProcessParameters.hStdError); } return File.openHandle(os.STDERR_FILENO); } -pub fn getStdIn() GetStdIoError!File { +pub fn getStdIn() File { if (builtin.os == .windows) { - const handle = try os.windows.GetStdHandle(os.windows.STD_INPUT_HANDLE); - return File.openHandle(handle); + return File.openHandle(os.windows.peb().ProcessParameters.hStdInput); } return File.openHandle(os.STDIN_FILENO); } @@ -74,24 +69,9 @@ pub fn writeFile(path: []const u8, data: []const u8) !void { } /// On success, caller owns returned buffer. -/// TODO move this to `std.fs` and add a version to `std.fs.Dir`. +/// This function is deprecated; use `std.fs.Dir.readFileAlloc`. pub fn readFileAlloc(allocator: *mem.Allocator, path: []const u8) ![]u8 { - return readFileAllocAligned(allocator, path, @alignOf(u8)); -} - -/// On success, caller owns returned buffer. -/// TODO move this to `std.fs` and add a version to `std.fs.Dir`. -pub fn readFileAllocAligned(allocator: *mem.Allocator, path: []const u8, comptime A: u29) ![]align(A) u8 { - var file = try File.openRead(path); - defer file.close(); - - const size = try math.cast(usize, try file.getEndPos()); - const buf = try allocator.alignedAlloc(u8, A, size); - errdefer allocator.free(buf); - - var adapter = file.inStream(); - try adapter.stream.readNoEof(buf[0..size]); - return buf; + return fs.Dir.cwd().readFileAlloc(allocator, path, math.maxInt(usize)); } pub fn BufferedInStream(comptime Error: type) type { @@ -353,21 +333,21 @@ pub fn BitInStream(endian: builtin.Endian, comptime Error: type) type { const Buf = @IntType(false, buf_bit_count); const BufShift = math.Log2Int(Buf); - out_bits.* = usize(0); + out_bits.* = @as(usize, 0); if (U == u0 or bits == 0) return 0; - var out_buffer = Buf(0); + var out_buffer = @as(Buf, 0); if (self.bit_count > 0) { const n = if (self.bit_count >= bits) @intCast(u3, bits) else self.bit_count; const shift = u7_bit_count - n; switch (endian) { builtin.Endian.Big => { - out_buffer = Buf(self.bit_buffer >> shift); + out_buffer = @as(Buf, self.bit_buffer >> shift); self.bit_buffer <<= n; }, builtin.Endian.Little => { const value = (self.bit_buffer << shift) >> shift; - out_buffer = Buf(value); + out_buffer = @as(Buf, value); self.bit_buffer >>= n; }, } @@ -393,28 +373,28 @@ pub fn BitInStream(endian: builtin.Endian, comptime Error: type) type { if (n >= u8_bit_count) { out_buffer <<= @intCast(u3, u8_bit_count - 1); out_buffer <<= 1; - out_buffer |= Buf(next_byte); + out_buffer |= @as(Buf, next_byte); out_bits.* += u8_bit_count; continue; } const shift = @intCast(u3, u8_bit_count - n); out_buffer <<= @intCast(BufShift, n); - out_buffer |= Buf(next_byte >> shift); + out_buffer |= @as(Buf, next_byte >> shift); out_bits.* += n; self.bit_buffer = @truncate(u7, next_byte << @intCast(u3, n - 1)); self.bit_count = shift; }, builtin.Endian.Little => { if (n >= u8_bit_count) { - out_buffer |= Buf(next_byte) << @intCast(BufShift, out_bits.*); + out_buffer |= @as(Buf, next_byte) << @intCast(BufShift, out_bits.*); out_bits.* += u8_bit_count; continue; } const shift = @intCast(u3, u8_bit_count - n); const value = (next_byte << shift) >> shift; - out_buffer |= Buf(value) << @intCast(BufShift, out_bits.*); + out_buffer |= @as(Buf, value) << @intCast(BufShift, out_bits.*); out_bits.* += n; self.bit_buffer = @truncate(u7, next_byte >> @intCast(u3, n)); self.bit_count = shift; @@ -434,7 +414,7 @@ pub fn BitInStream(endian: builtin.Endian, comptime Error: type) type { var self = @fieldParentPtr(Self, "stream", self_stream); var out_bits: usize = undefined; - var out_bits_total = usize(0); + var out_bits_total = @as(usize, 0); //@NOTE: I'm not sure this is a good idea, maybe alignToByte should be forced if (self.bit_count > 0) { for (buffer) |*b, i| { @@ -598,7 +578,7 @@ pub fn BufferedOutStreamCustom(comptime buffer_size: usize, comptime OutStreamEr self.index = 0; } - fn writeFn(out_stream: *Stream, bytes: []const u8) !void { + fn writeFn(out_stream: *Stream, bytes: []const u8) Error!void { const self = @fieldParentPtr(Self, "stream", out_stream); if (bytes.len >= self.buffer.len) { @@ -814,8 +794,7 @@ pub const BufferedAtomicFile = struct { }; pub fn readLine(buf: *std.Buffer) ![]u8 { - var stdin = try getStdIn(); - var stdin_stream = stdin.inStream(); + var stdin_stream = getStdIn().inStream(); return readLineFrom(&stdin_stream.stream, buf); } @@ -856,8 +835,7 @@ test "io.readLineFrom" { } pub fn readLineSlice(slice: []u8) ![]u8 { - var stdin = try getStdIn(); - var stdin_stream = stdin.inStream(); + var stdin_stream = getStdIn().inStream(); return readLineSliceFrom(&stdin_stream.stream, slice); } @@ -949,14 +927,14 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing, return @truncate(T, @bitCast(PossiblySignedByte, buffer[0])); } - var result = U(0); + var result = @as(U, 0); for (buffer) |byte, i| { switch (endian) { builtin.Endian.Big => { result = (result << u8_bit_count) | byte; }, builtin.Endian.Little => { - result |= U(byte) << @intCast(Log2U, u8_bit_count * i); + result |= @as(U, byte) << @intCast(Log2U, u8_bit_count * i); }, } } @@ -1050,7 +1028,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing, return; } - ptr.* = OC(undefined); //make it non-null so the following .? is guaranteed safe + ptr.* = @as(OC, undefined); //make it non-null so the following .? is guaranteed safe const val_ptr = &ptr.*.?; try self.deserializeInto(val_ptr); }, @@ -1154,7 +1132,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co switch (@typeId(T)) { builtin.TypeId.Void => return, - builtin.TypeId.Bool => try self.serializeInt(u1(@boolToInt(value))), + builtin.TypeId.Bool => try self.serializeInt(@as(u1, @boolToInt(value))), builtin.TypeId.Float, builtin.TypeId.Int => try self.serializeInt(value), builtin.TypeId.Struct => { const info = @typeInfo(T); @@ -1197,10 +1175,10 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co }, builtin.TypeId.Optional => { if (value == null) { - try self.serializeInt(u1(@boolToInt(false))); + try self.serializeInt(@as(u1, @boolToInt(false))); return; } - try self.serializeInt(u1(@boolToInt(true))); + try self.serializeInt(@as(u1, @boolToInt(true))); const OC = comptime meta.Child(T); const val_ptr = &value.?; diff --git a/lib/std/io/out_stream.zig b/lib/std/io/out_stream.zig @@ -40,12 +40,12 @@ pub fn OutStream(comptime WriteError: type) type { } pub fn writeByte(self: *Self, byte: u8) Error!void { - const slice = (*const [1]u8)(&byte)[0..]; + const slice = @as(*const [1]u8, &byte)[0..]; return self.writeFn(self, slice); } pub fn writeByteNTimes(self: *Self, byte: u8, n: usize) Error!void { - const slice = (*const [1]u8)(&byte)[0..]; + const slice = @as(*const [1]u8, &byte)[0..]; var i: usize = 0; while (i < n) : (i += 1) { try self.writeFn(self, slice); diff --git a/lib/std/io/test.zig b/lib/std/io/test.zig @@ -226,49 +226,49 @@ test "BitOutStream" { const OutError = io.SliceOutStream.Error; var bit_stream_be = io.BitOutStream(builtin.Endian.Big, OutError).init(&mem_out_be.stream); - try bit_stream_be.writeBits(u2(1), 1); - try bit_stream_be.writeBits(u5(2), 2); - try bit_stream_be.writeBits(u128(3), 3); - try bit_stream_be.writeBits(u8(4), 4); - try bit_stream_be.writeBits(u9(5), 5); - try bit_stream_be.writeBits(u1(1), 1); + try bit_stream_be.writeBits(@as(u2, 1), 1); + try bit_stream_be.writeBits(@as(u5, 2), 2); + try bit_stream_be.writeBits(@as(u128, 3), 3); + try bit_stream_be.writeBits(@as(u8, 4), 4); + try bit_stream_be.writeBits(@as(u9, 5), 5); + try bit_stream_be.writeBits(@as(u1, 1), 1); expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001011); mem_out_be.pos = 0; - try bit_stream_be.writeBits(u15(0b110011010000101), 15); + try bit_stream_be.writeBits(@as(u15, 0b110011010000101), 15); try bit_stream_be.flushBits(); expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001010); mem_out_be.pos = 0; - try bit_stream_be.writeBits(u32(0b110011010000101), 16); + try bit_stream_be.writeBits(@as(u32, 0b110011010000101), 16); expect(mem_be[0] == 0b01100110 and mem_be[1] == 0b10000101); - try bit_stream_be.writeBits(u0(0), 0); + try bit_stream_be.writeBits(@as(u0, 0), 0); var mem_out_le = io.SliceOutStream.init(mem_le[0..]); var bit_stream_le = io.BitOutStream(builtin.Endian.Little, OutError).init(&mem_out_le.stream); - try bit_stream_le.writeBits(u2(1), 1); - try bit_stream_le.writeBits(u5(2), 2); - try bit_stream_le.writeBits(u128(3), 3); - try bit_stream_le.writeBits(u8(4), 4); - try bit_stream_le.writeBits(u9(5), 5); - try bit_stream_le.writeBits(u1(1), 1); + try bit_stream_le.writeBits(@as(u2, 1), 1); + try bit_stream_le.writeBits(@as(u5, 2), 2); + try bit_stream_le.writeBits(@as(u128, 3), 3); + try bit_stream_le.writeBits(@as(u8, 4), 4); + try bit_stream_le.writeBits(@as(u9, 5), 5); + try bit_stream_le.writeBits(@as(u1, 1), 1); expect(mem_le[0] == 0b00011101 and mem_le[1] == 0b10010101); mem_out_le.pos = 0; - try bit_stream_le.writeBits(u15(0b110011010000101), 15); + try bit_stream_le.writeBits(@as(u15, 0b110011010000101), 15); try bit_stream_le.flushBits(); expect(mem_le[0] == 0b10000101 and mem_le[1] == 0b01100110); mem_out_le.pos = 0; - try bit_stream_le.writeBits(u32(0b1100110100001011), 16); + try bit_stream_le.writeBits(@as(u32, 0b1100110100001011), 16); expect(mem_le[0] == 0b00001011 and mem_le[1] == 0b11001101); - try bit_stream_le.writeBits(u0(0), 0); + try bit_stream_le.writeBits(@as(u0, 0), 0); } test "BitStreams with File Stream" { @@ -282,12 +282,12 @@ test "BitStreams with File Stream" { const OutError = File.WriteError; var bit_stream = io.BitOutStream(builtin.endian, OutError).init(file_out_stream); - try bit_stream.writeBits(u2(1), 1); - try bit_stream.writeBits(u5(2), 2); - try bit_stream.writeBits(u128(3), 3); - try bit_stream.writeBits(u8(4), 4); - try bit_stream.writeBits(u9(5), 5); - try bit_stream.writeBits(u1(1), 1); + try bit_stream.writeBits(@as(u2, 1), 1); + try bit_stream.writeBits(@as(u5, 2), 2); + try bit_stream.writeBits(@as(u128, 3), 3); + try bit_stream.writeBits(@as(u8, 4), 4); + try bit_stream.writeBits(@as(u9, 5), 5); + try bit_stream.writeBits(@as(u1, 1), 1); try bit_stream.flushBits(); } { @@ -345,8 +345,8 @@ fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime packi inline while (i <= max_test_bitsize) : (i += 1) { const U = @IntType(false, i); const S = @IntType(true, i); - try serializer.serializeInt(U(i)); - if (i != 0) try serializer.serializeInt(S(-1)) else try serializer.serialize(S(0)); + try serializer.serializeInt(@as(U, i)); + if (i != 0) try serializer.serializeInt(@as(S, -1)) else try serializer.serialize(@as(S, 0)); } try serializer.flush(); @@ -356,8 +356,8 @@ fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime packi const S = @IntType(true, i); const x = try deserializer.deserializeInt(U); const y = try deserializer.deserializeInt(S); - expect(x == U(i)); - if (i != 0) expect(y == S(-1)) else expect(y == 0); + expect(x == @as(U, i)); + if (i != 0) expect(y == @as(S, -1)) else expect(y == 0); } const u8_bit_count = comptime meta.bitCount(u8); @@ -577,11 +577,11 @@ fn testBadData(comptime endian: builtin.Endian, comptime packing: io.Packing) !v var in_stream = &in.stream; var deserializer = io.Deserializer(endian, packing, InError).init(in_stream); - try serializer.serialize(u14(3)); + try serializer.serialize(@as(u14, 3)); expectError(error.InvalidEnumTag, deserializer.deserialize(A)); out.pos = 0; - try serializer.serialize(u14(3)); - try serializer.serialize(u14(88)); + try serializer.serialize(@as(u14, 3)); + try serializer.serialize(@as(u14, 88)); expectError(error.InvalidEnumTag, deserializer.deserialize(C)); } @@ -603,7 +603,7 @@ test "c out stream" { } const out_stream = &io.COutStream.init(out_file).stream; - try out_stream.print("hi: {}\n", i32(123)); + try out_stream.print("hi: {}\n", @as(i32, 123)); } test "File seek ops" { diff --git a/lib/std/json.zig b/lib/std/json.zig @@ -1012,119 +1012,39 @@ pub const Value = union(enum) { Object: ObjectMap, pub fn dump(self: Value) void { - switch (self) { - Value.Null => { - debug.warn("null"); - }, - Value.Bool => |inner| { - debug.warn("{}", inner); - }, - Value.Integer => |inner| { - debug.warn("{}", inner); - }, - Value.Float => |inner| { - debug.warn("{:.5}", inner); - }, - Value.String => |inner| { - debug.warn("\"{}\"", inner); - }, - Value.Array => |inner| { - var not_first = false; - debug.warn("["); - for (inner.toSliceConst()) |value| { - if (not_first) { - debug.warn(","); - } - not_first = true; - value.dump(); - } - debug.warn("]"); - }, - Value.Object => |inner| { - var not_first = false; - debug.warn("{{"); - var it = inner.iterator(); - - while (it.next()) |entry| { - if (not_first) { - debug.warn(","); - } - not_first = true; - debug.warn("\"{}\":", entry.key); - entry.value.dump(); - } - debug.warn("}}"); - }, - } + var held = std.debug.getStderrMutex().acquire(); + defer held.release(); + + const stderr = std.debug.getStderrStream(); + self.dumpStream(stderr, 1024) catch return; } - pub fn dumpIndent(self: Value, indent: usize) void { + pub fn dumpIndent(self: Value, comptime indent: usize) void { if (indent == 0) { self.dump(); } else { - self.dumpIndentLevel(indent, 0); + var held = std.debug.getStderrMutex().acquire(); + defer held.release(); + + const stderr = std.debug.getStderrStream(); + self.dumpStreamIndent(indent, stderr, 1024) catch return; } } - fn dumpIndentLevel(self: Value, indent: usize, level: usize) void { - switch (self) { - Value.Null => { - debug.warn("null"); - }, - Value.Bool => |inner| { - debug.warn("{}", inner); - }, - Value.Integer => |inner| { - debug.warn("{}", inner); - }, - Value.Float => |inner| { - debug.warn("{:.5}", inner); - }, - Value.String => |inner| { - debug.warn("\"{}\"", inner); - }, - Value.Array => |inner| { - var not_first = false; - debug.warn("[\n"); - - for (inner.toSliceConst()) |value| { - if (not_first) { - debug.warn(",\n"); - } - not_first = true; - padSpace(level + indent); - value.dumpIndentLevel(indent, level + indent); - } - debug.warn("\n"); - padSpace(level); - debug.warn("]"); - }, - Value.Object => |inner| { - var not_first = false; - debug.warn("{{\n"); - var it = inner.iterator(); - - while (it.next()) |entry| { - if (not_first) { - debug.warn(",\n"); - } - not_first = true; - padSpace(level + indent); - debug.warn("\"{}\": ", entry.key); - entry.value.dumpIndentLevel(indent, level + indent); - } - debug.warn("\n"); - padSpace(level); - debug.warn("}}"); - }, - } + pub fn dumpStream(self: @This(), stream: var, comptime max_depth: usize) !void { + var w = std.json.WriteStream(@typeOf(stream).Child, max_depth).init(stream); + w.newline = ""; + w.one_indent = ""; + w.space = ""; + try w.emitJson(self); } - fn padSpace(indent: usize) void { - var i: usize = 0; - while (i < indent) : (i += 1) { - debug.warn(" "); - } + pub fn dumpStreamIndent(self: @This(), comptime indent: usize, stream: var, comptime max_depth: usize) !void { + var one_indent = " " ** indent; + + var w = std.json.WriteStream(@typeOf(stream).Child, max_depth).init(stream); + w.one_indent = one_indent; + try w.emitJson(self); } }; @@ -1423,7 +1343,7 @@ test "write json then parse it" { try jw.emitBool(true); try jw.objectField("int"); - try jw.emitNumber(i32(1234)); + try jw.emitNumber(@as(i32, 1234)); try jw.objectField("array"); try jw.beginArray(); @@ -1432,7 +1352,7 @@ test "write json then parse it" { try jw.emitNull(); try jw.arrayElem(); - try jw.emitNumber(f64(12.34)); + try jw.emitNumber(@as(f64, 12.34)); try jw.endArray(); diff --git a/lib/std/json/write_stream.zig b/lib/std/json/write_stream.zig @@ -27,6 +27,9 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type { /// The string used as a newline character. newline: []const u8 = "\n", + /// The string used as spacing. + space: []const u8 = " ", + stream: *OutStream, state_index: usize, state: [max_depth]State, @@ -87,7 +90,8 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type { self.pushState(.Value); try self.indent(); try self.writeEscapedString(name); - try self.stream.write(": "); + try self.stream.write(":"); + try self.stream.write(self.space); }, } } diff --git a/lib/std/lazy_init.zig b/lib/std/lazy_init.zig @@ -1,24 +1,26 @@ const std = @import("std.zig"); -const builtin = @import("builtin"); const assert = std.debug.assert; const testing = std.testing; -const AtomicRmwOp = builtin.AtomicRmwOp; -const AtomicOrder = builtin.AtomicOrder; /// Thread-safe initialization of global data. /// TODO use a mutex instead of a spinlock pub fn lazyInit(comptime T: type) LazyInit(T) { return LazyInit(T){ .data = undefined, - .state = 0, }; } fn LazyInit(comptime T: type) type { return struct { - state: u8, // TODO make this an enum + state: State = .NotResolved, data: Data, + const State = enum(u8) { + NotResolved, + Resolving, + Resolved, + }; + const Self = @This(); // TODO this isn't working for void, investigate and then remove this special case @@ -30,16 +32,16 @@ fn LazyInit(comptime T: type) type { /// perform the initialization and then call resolve(). pub fn get(self: *Self) ?Ptr { while (true) { - var state = @cmpxchgWeak(u8, &self.state, 0, 1, AtomicOrder.SeqCst, AtomicOrder.SeqCst) orelse return null; + var state = @cmpxchgWeak(State, &self.state, .NotResolved, .Resolving, .SeqCst, .SeqCst) orelse return null; switch (state) { - 0 => continue, - 1 => { + .NotResolved => continue, + .Resolving => { // TODO mutex instead of a spinlock continue; }, - 2 => { + .Resolved => { if (@sizeOf(T) == 0) { - return T(undefined); + return @as(T, undefined); } else { return &self.data; } @@ -50,8 +52,8 @@ fn LazyInit(comptime T: type) type { } pub fn resolve(self: *Self) void { - const prev = @atomicRmw(u8, &self.state, AtomicRmwOp.Xchg, 2, AtomicOrder.SeqCst); - assert(prev == 1); // resolve() called twice + const prev = @atomicRmw(State, &self.state, .Xchg, .Resolved, .SeqCst); + assert(prev != .Resolved); // resolve() called twice } }; } diff --git a/lib/std/math.zig b/lib/std/math.zig @@ -10,6 +10,9 @@ pub const e = 2.71828182845904523536028747135266249775724709369995; /// Archimedes' constant (π) pub const pi = 3.14159265358979323846264338327950288419716939937510; +/// Circle constant (τ) +pub const tau = 2 * pi; + /// log2(e) pub const log2e = 1.442695040888963407359924681001892137; @@ -44,10 +47,10 @@ pub const sqrt2 = 1.414213562373095048801688724209698079; pub const sqrt1_2 = 0.707106781186547524400844362104849039; // From a small c++ [program using boost float128](https://github.com/winksaville/cpp_boost_float128) -pub const f128_true_min = @bitCast(f128, u128(0x00000000000000000000000000000001)); -pub const f128_min = @bitCast(f128, u128(0x00010000000000000000000000000000)); -pub const f128_max = @bitCast(f128, u128(0x7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFF)); -pub const f128_epsilon = @bitCast(f128, u128(0x3F8F0000000000000000000000000000)); +pub const f128_true_min = @bitCast(f128, @as(u128, 0x00000000000000000000000000000001)); +pub const f128_min = @bitCast(f128, @as(u128, 0x00010000000000000000000000000000)); +pub const f128_max = @bitCast(f128, @as(u128, 0x7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFF)); +pub const f128_epsilon = @bitCast(f128, @as(u128, 0x3F8F0000000000000000000000000000)); pub const f128_toint = 1.0 / f128_epsilon; // float.h details @@ -69,28 +72,28 @@ pub const f16_max = 65504; pub const f16_epsilon = 0.0009765625; // 2**-10 pub const f16_toint = 1.0 / f16_epsilon; -pub const nan_u16 = u16(0x7C01); +pub const nan_u16 = @as(u16, 0x7C01); pub const nan_f16 = @bitCast(f16, nan_u16); -pub const inf_u16 = u16(0x7C00); +pub const inf_u16 = @as(u16, 0x7C00); pub const inf_f16 = @bitCast(f16, inf_u16); -pub const nan_u32 = u32(0x7F800001); +pub const nan_u32 = @as(u32, 0x7F800001); pub const nan_f32 = @bitCast(f32, nan_u32); -pub const inf_u32 = u32(0x7F800000); +pub const inf_u32 = @as(u32, 0x7F800000); pub const inf_f32 = @bitCast(f32, inf_u32); -pub const nan_u64 = u64(0x7FF << 52) | 1; +pub const nan_u64 = @as(u64, 0x7FF << 52) | 1; pub const nan_f64 = @bitCast(f64, nan_u64); -pub const inf_u64 = u64(0x7FF << 52); +pub const inf_u64 = @as(u64, 0x7FF << 52); pub const inf_f64 = @bitCast(f64, inf_u64); -pub const nan_u128 = u128(0x7fff0000000000000000000000000001); +pub const nan_u128 = @as(u128, 0x7fff0000000000000000000000000001); pub const nan_f128 = @bitCast(f128, nan_u128); -pub const inf_u128 = u128(0x7fff0000000000000000000000000000); +pub const inf_u128 = @as(u128, 0x7fff0000000000000000000000000000); pub const inf_f128 = @bitCast(f128, inf_u128); pub const nan = @import("math/nan.zig").nan; @@ -248,7 +251,7 @@ pub fn Min(comptime A: type, comptime B: type) type { }, else => {}, } - return @typeOf(A(0) + B(0)); + return @typeOf(@as(A, 0) + @as(B, 0)); } /// Returns the smaller number. When one of the parameter's type's full range fits in the other, @@ -273,7 +276,7 @@ pub fn min(x: var, y: var) Min(@typeOf(x), @typeOf(y)) { } test "math.min" { - testing.expect(min(i32(-1), i32(2)) == -1); + testing.expect(min(@as(i32, -1), @as(i32, 2)) == -1); { var a: u16 = 999; var b: u32 = 10; @@ -309,7 +312,7 @@ pub fn max(x: var, y: var) @typeOf(x + y) { } test "math.max" { - testing.expect(max(i32(-1), i32(2)) == 2); + testing.expect(max(@as(i32, -1), @as(i32, 2)) == 2); } pub fn mul(comptime T: type, a: T, b: T) (error{Overflow}!T) { @@ -352,10 +355,10 @@ pub fn shl(comptime T: type, a: T, shift_amt: var) T { } test "math.shl" { - testing.expect(shl(u8, 0b11111111, usize(3)) == 0b11111000); - testing.expect(shl(u8, 0b11111111, usize(8)) == 0); - testing.expect(shl(u8, 0b11111111, usize(9)) == 0); - testing.expect(shl(u8, 0b11111111, isize(-2)) == 0b00111111); + testing.expect(shl(u8, 0b11111111, @as(usize, 3)) == 0b11111000); + testing.expect(shl(u8, 0b11111111, @as(usize, 8)) == 0); + testing.expect(shl(u8, 0b11111111, @as(usize, 9)) == 0); + testing.expect(shl(u8, 0b11111111, @as(isize, -2)) == 0b00111111); testing.expect(shl(u8, 0b11111111, 3) == 0b11111000); testing.expect(shl(u8, 0b11111111, 8) == 0); testing.expect(shl(u8, 0b11111111, 9) == 0); @@ -380,10 +383,10 @@ pub fn shr(comptime T: type, a: T, shift_amt: var) T { } test "math.shr" { - testing.expect(shr(u8, 0b11111111, usize(3)) == 0b00011111); - testing.expect(shr(u8, 0b11111111, usize(8)) == 0); - testing.expect(shr(u8, 0b11111111, usize(9)) == 0); - testing.expect(shr(u8, 0b11111111, isize(-2)) == 0b11111100); + testing.expect(shr(u8, 0b11111111, @as(usize, 3)) == 0b00011111); + testing.expect(shr(u8, 0b11111111, @as(usize, 8)) == 0); + testing.expect(shr(u8, 0b11111111, @as(usize, 9)) == 0); + testing.expect(shr(u8, 0b11111111, @as(isize, -2)) == 0b11111100); testing.expect(shr(u8, 0b11111111, 3) == 0b00011111); testing.expect(shr(u8, 0b11111111, 8) == 0); testing.expect(shr(u8, 0b11111111, 9) == 0); @@ -402,11 +405,11 @@ pub fn rotr(comptime T: type, x: T, r: var) T { } test "math.rotr" { - testing.expect(rotr(u8, 0b00000001, usize(0)) == 0b00000001); - testing.expect(rotr(u8, 0b00000001, usize(9)) == 0b10000000); - testing.expect(rotr(u8, 0b00000001, usize(8)) == 0b00000001); - testing.expect(rotr(u8, 0b00000001, usize(4)) == 0b00010000); - testing.expect(rotr(u8, 0b00000001, isize(-1)) == 0b00000010); + testing.expect(rotr(u8, 0b00000001, @as(usize, 0)) == 0b00000001); + testing.expect(rotr(u8, 0b00000001, @as(usize, 9)) == 0b10000000); + testing.expect(rotr(u8, 0b00000001, @as(usize, 8)) == 0b00000001); + testing.expect(rotr(u8, 0b00000001, @as(usize, 4)) == 0b00010000); + testing.expect(rotr(u8, 0b00000001, @as(isize, -1)) == 0b00000010); } /// Rotates left. Only unsigned values can be rotated. @@ -421,11 +424,11 @@ pub fn rotl(comptime T: type, x: T, r: var) T { } test "math.rotl" { - testing.expect(rotl(u8, 0b00000001, usize(0)) == 0b00000001); - testing.expect(rotl(u8, 0b00000001, usize(9)) == 0b00000010); - testing.expect(rotl(u8, 0b00000001, usize(8)) == 0b00000001); - testing.expect(rotl(u8, 0b00000001, usize(4)) == 0b00010000); - testing.expect(rotl(u8, 0b00000001, isize(-1)) == 0b10000000); + testing.expect(rotl(u8, 0b00000001, @as(usize, 0)) == 0b00000001); + testing.expect(rotl(u8, 0b00000001, @as(usize, 9)) == 0b00000010); + testing.expect(rotl(u8, 0b00000001, @as(usize, 8)) == 0b00000001); + testing.expect(rotl(u8, 0b00000001, @as(usize, 4)) == 0b00010000); + testing.expect(rotl(u8, 0b00000001, @as(isize, -1)) == 0b10000000); } pub fn Log2Int(comptime T: type) type { @@ -532,8 +535,8 @@ test "math.absInt" { comptime testAbsInt(); } fn testAbsInt() void { - testing.expect((absInt(i32(-10)) catch unreachable) == 10); - testing.expect((absInt(i32(10)) catch unreachable) == 10); + testing.expect((absInt(@as(i32, -10)) catch unreachable) == 10); + testing.expect((absInt(@as(i32, 10)) catch unreachable) == 10); } pub const absFloat = fabs; @@ -543,8 +546,8 @@ test "math.absFloat" { comptime testAbsFloat(); } fn testAbsFloat() void { - testing.expect(absFloat(f32(-10.05)) == 10.05); - testing.expect(absFloat(f32(10.05)) == 10.05); + testing.expect(absFloat(@as(f32, -10.05)) == 10.05); + testing.expect(absFloat(@as(f32, 10.05)) == 10.05); } pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T { @@ -679,14 +682,14 @@ pub fn absCast(x: var) t: { } test "math.absCast" { - testing.expect(absCast(i32(-999)) == 999); - testing.expect(@typeOf(absCast(i32(-999))) == u32); + testing.expect(absCast(@as(i32, -999)) == 999); + testing.expect(@typeOf(absCast(@as(i32, -999))) == u32); - testing.expect(absCast(i32(999)) == 999); - testing.expect(@typeOf(absCast(i32(999))) == u32); + testing.expect(absCast(@as(i32, 999)) == 999); + testing.expect(@typeOf(absCast(@as(i32, 999))) == u32); - testing.expect(absCast(i32(minInt(i32))) == -minInt(i32)); - testing.expect(@typeOf(absCast(i32(minInt(i32)))) == u32); + testing.expect(absCast(@as(i32, minInt(i32))) == -minInt(i32)); + testing.expect(@typeOf(absCast(@as(i32, minInt(i32)))) == u32); testing.expect(absCast(-999) == 999); } @@ -705,13 +708,13 @@ pub fn negateCast(x: var) !@IntType(true, @typeOf(x).bit_count) { } test "math.negateCast" { - testing.expect((negateCast(u32(999)) catch unreachable) == -999); - testing.expect(@typeOf(negateCast(u32(999)) catch unreachable) == i32); + testing.expect((negateCast(@as(u32, 999)) catch unreachable) == -999); + testing.expect(@typeOf(negateCast(@as(u32, 999)) catch unreachable) == i32); - testing.expect((negateCast(u32(-minInt(i32))) catch unreachable) == minInt(i32)); - testing.expect(@typeOf(negateCast(u32(-minInt(i32))) catch unreachable) == i32); + testing.expect((negateCast(@as(u32, -minInt(i32))) catch unreachable) == minInt(i32)); + testing.expect(@typeOf(negateCast(@as(u32, -minInt(i32))) catch unreachable) == i32); - testing.expectError(error.Overflow, negateCast(u32(maxInt(i32) + 10))); + testing.expectError(error.Overflow, negateCast(@as(u32, maxInt(i32) + 10))); } /// Cast an integer to a different integer type. If the value doesn't fit, @@ -729,13 +732,13 @@ pub fn cast(comptime T: type, x: var) (error{Overflow}!T) { } test "math.cast" { - testing.expectError(error.Overflow, cast(u8, u32(300))); - testing.expectError(error.Overflow, cast(i8, i32(-200))); - testing.expectError(error.Overflow, cast(u8, i8(-1))); - testing.expectError(error.Overflow, cast(u64, i8(-1))); + testing.expectError(error.Overflow, cast(u8, @as(u32, 300))); + testing.expectError(error.Overflow, cast(i8, @as(i32, -200))); + testing.expectError(error.Overflow, cast(u8, @as(i8, -1))); + testing.expectError(error.Overflow, cast(u64, @as(i8, -1))); - testing.expect((try cast(u8, u32(255))) == u8(255)); - testing.expect(@typeOf(try cast(u8, u32(255))) == u8); + testing.expect((try cast(u8, @as(u32, 255))) == @as(u8, 255)); + testing.expect(@typeOf(try cast(u8, @as(u32, 255))) == u8); } pub const AlignCastError = error{UnalignedMemory}; @@ -786,9 +789,9 @@ pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) @IntType(T.is_signed, T comptime assert(@typeId(T) == builtin.TypeId.Int); comptime assert(!T.is_signed); assert(value != 0); - comptime const promotedType = @IntType(T.is_signed, T.bit_count + 1); - comptime const shiftType = std.math.Log2Int(promotedType); - return promotedType(1) << @intCast(shiftType, T.bit_count - @clz(T, value - 1)); + comptime const PromotedType = @IntType(T.is_signed, T.bit_count + 1); + comptime const shiftType = std.math.Log2Int(PromotedType); + return @as(PromotedType, 1) << @intCast(shiftType, T.bit_count - @clz(T, value - 1)); } /// Returns the next power of two (if the value is not already a power of two). @@ -797,8 +800,8 @@ pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) @IntType(T.is_signed, T pub fn ceilPowerOfTwo(comptime T: type, value: T) (error{Overflow}!T) { comptime assert(@typeId(T) == builtin.TypeId.Int); comptime assert(!T.is_signed); - comptime const promotedType = @IntType(T.is_signed, T.bit_count + 1); - comptime const overflowBit = promotedType(1) << T.bit_count; + comptime const PromotedType = @IntType(T.is_signed, T.bit_count + 1); + comptime const overflowBit = @as(PromotedType, 1) << T.bit_count; var x = ceilPowerOfTwoPromote(T, value); if (overflowBit & x != 0) { return error.Overflow; @@ -812,15 +815,15 @@ test "math.ceilPowerOfTwoPromote" { } fn testCeilPowerOfTwoPromote() void { - testing.expectEqual(u33(1), ceilPowerOfTwoPromote(u32, 1)); - testing.expectEqual(u33(2), ceilPowerOfTwoPromote(u32, 2)); - testing.expectEqual(u33(64), ceilPowerOfTwoPromote(u32, 63)); - testing.expectEqual(u33(64), ceilPowerOfTwoPromote(u32, 64)); - testing.expectEqual(u33(128), ceilPowerOfTwoPromote(u32, 65)); - testing.expectEqual(u6(8), ceilPowerOfTwoPromote(u5, 7)); - testing.expectEqual(u6(8), ceilPowerOfTwoPromote(u5, 8)); - testing.expectEqual(u6(16), ceilPowerOfTwoPromote(u5, 9)); - testing.expectEqual(u5(16), ceilPowerOfTwoPromote(u4, 9)); + testing.expectEqual(@as(u33, 1), ceilPowerOfTwoPromote(u32, 1)); + testing.expectEqual(@as(u33, 2), ceilPowerOfTwoPromote(u32, 2)); + testing.expectEqual(@as(u33, 64), ceilPowerOfTwoPromote(u32, 63)); + testing.expectEqual(@as(u33, 64), ceilPowerOfTwoPromote(u32, 64)); + testing.expectEqual(@as(u33, 128), ceilPowerOfTwoPromote(u32, 65)); + testing.expectEqual(@as(u6, 8), ceilPowerOfTwoPromote(u5, 7)); + testing.expectEqual(@as(u6, 8), ceilPowerOfTwoPromote(u5, 8)); + testing.expectEqual(@as(u6, 16), ceilPowerOfTwoPromote(u5, 9)); + testing.expectEqual(@as(u5, 16), ceilPowerOfTwoPromote(u4, 9)); } test "math.ceilPowerOfTwo" { @@ -829,14 +832,14 @@ test "math.ceilPowerOfTwo" { } fn testCeilPowerOfTwo() !void { - testing.expectEqual(u32(1), try ceilPowerOfTwo(u32, 1)); - testing.expectEqual(u32(2), try ceilPowerOfTwo(u32, 2)); - testing.expectEqual(u32(64), try ceilPowerOfTwo(u32, 63)); - testing.expectEqual(u32(64), try ceilPowerOfTwo(u32, 64)); - testing.expectEqual(u32(128), try ceilPowerOfTwo(u32, 65)); - testing.expectEqual(u5(8), try ceilPowerOfTwo(u5, 7)); - testing.expectEqual(u5(8), try ceilPowerOfTwo(u5, 8)); - testing.expectEqual(u5(16), try ceilPowerOfTwo(u5, 9)); + testing.expectEqual(@as(u32, 1), try ceilPowerOfTwo(u32, 1)); + testing.expectEqual(@as(u32, 2), try ceilPowerOfTwo(u32, 2)); + testing.expectEqual(@as(u32, 64), try ceilPowerOfTwo(u32, 63)); + testing.expectEqual(@as(u32, 64), try ceilPowerOfTwo(u32, 64)); + testing.expectEqual(@as(u32, 128), try ceilPowerOfTwo(u32, 65)); + testing.expectEqual(@as(u5, 8), try ceilPowerOfTwo(u5, 7)); + testing.expectEqual(@as(u5, 8), try ceilPowerOfTwo(u5, 8)); + testing.expectEqual(@as(u5, 16), try ceilPowerOfTwo(u5, 9)); testing.expectError(error.Overflow, ceilPowerOfTwo(u4, 9)); } @@ -848,7 +851,7 @@ pub fn log2_int(comptime T: type, x: T) Log2Int(T) { pub fn log2_int_ceil(comptime T: type, x: T) Log2Int(T) { assert(x != 0); const log2_val = log2_int(T, x); - if (T(1) << log2_val == x) + if (@as(T, 1) << log2_val == x) return log2_val; return log2_val + 1; } @@ -870,8 +873,8 @@ pub fn lossyCast(comptime T: type, value: var) T { switch (@typeInfo(@typeOf(value))) { builtin.TypeId.Int => return @intToFloat(T, value), builtin.TypeId.Float => return @floatCast(T, value), - builtin.TypeId.ComptimeInt => return T(value), - builtin.TypeId.ComptimeFloat => return T(value), + builtin.TypeId.ComptimeInt => return @as(T, value), + builtin.TypeId.ComptimeFloat => return @as(T, value), else => @compileError("bad type"), } } @@ -944,7 +947,7 @@ test "max value type" { pub fn mulWide(comptime T: type, a: T, b: T) @IntType(T.is_signed, T.bit_count * 2) { const ResultInt = @IntType(T.is_signed, T.bit_count * 2); - return ResultInt(a) * ResultInt(b); + return @as(ResultInt, a) * @as(ResultInt, b); } test "math.mulWide" { diff --git a/lib/std/math/acos.zig b/lib/std/math/acos.zig @@ -149,8 +149,8 @@ fn acos64(x: f64) f64 { } test "math.acos" { - expect(acos(f32(0.0)) == acos32(0.0)); - expect(acos(f64(0.0)) == acos64(0.0)); + expect(acos(@as(f32, 0.0)) == acos32(0.0)); + expect(acos(@as(f64, 0.0)) == acos64(0.0)); } test "math.acos32" { diff --git a/lib/std/math/acosh.zig b/lib/std/math/acosh.zig @@ -61,8 +61,8 @@ fn acosh64(x: f64) f64 { } test "math.acosh" { - expect(acosh(f32(1.5)) == acosh32(1.5)); - expect(acosh(f64(1.5)) == acosh64(1.5)); + expect(acosh(@as(f32, 1.5)) == acosh32(1.5)); + expect(acosh(@as(f64, 1.5)) == acosh64(1.5)); } test "math.acosh32" { diff --git a/lib/std/math/asin.zig b/lib/std/math/asin.zig @@ -142,8 +142,8 @@ fn asin64(x: f64) f64 { } test "math.asin" { - expect(asin(f32(0.0)) == asin32(0.0)); - expect(asin(f64(0.0)) == asin64(0.0)); + expect(asin(@as(f32, 0.0)) == asin32(0.0)); + expect(asin(@as(f64, 0.0)) == asin64(0.0)); } test "math.asin32" { diff --git a/lib/std/math/asinh.zig b/lib/std/math/asinh.zig @@ -89,8 +89,8 @@ fn asinh64(x: f64) f64 { } test "math.asinh" { - expect(asinh(f32(0.0)) == asinh32(0.0)); - expect(asinh(f64(0.0)) == asinh64(0.0)); + expect(asinh(@as(f32, 0.0)) == asinh32(0.0)); + expect(asinh(@as(f64, 0.0)) == asinh64(0.0)); } test "math.asinh32" { diff --git a/lib/std/math/atan.zig b/lib/std/math/atan.zig @@ -212,8 +212,8 @@ fn atan64(x_: f64) f64 { } test "math.atan" { - expect(@bitCast(u32, atan(f32(0.2))) == @bitCast(u32, atan32(0.2))); - expect(atan(f64(0.2)) == atan64(0.2)); + expect(@bitCast(u32, atan(@as(f32, 0.2))) == @bitCast(u32, atan32(0.2))); + expect(atan(@as(f64, 0.2)) == atan64(0.2)); } test "math.atan32" { diff --git a/lib/std/math/atanh.zig b/lib/std/math/atanh.zig @@ -84,8 +84,8 @@ fn atanh_64(x: f64) f64 { } test "math.atanh" { - expect(atanh(f32(0.0)) == atanh_32(0.0)); - expect(atanh(f64(0.0)) == atanh_64(0.0)); + expect(atanh(@as(f32, 0.0)) == atanh_32(0.0)); + expect(atanh(@as(f64, 0.0)) == atanh_64(0.0)); } test "math.atanh_32" { diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig @@ -261,7 +261,7 @@ pub const Int = struct { /// the minus sign. This is used for determining the number of characters needed to print the /// value. It is inexact and may exceed the given value by ~1-2 bytes. pub fn sizeInBase(self: Int, base: usize) usize { - const bit_count = usize(@boolToInt(!self.isPositive())) + self.bitCountAbs(); + const bit_count = @as(usize, @boolToInt(!self.isPositive())) + self.bitCountAbs(); return (bit_count / math.log2(base)) + 1; } @@ -281,7 +281,7 @@ pub const Int = struct { var w_value: UT = if (value < 0) @intCast(UT, -value) else @intCast(UT, value); if (info.bits <= Limb.bit_count) { - self.limbs[0] = Limb(w_value); + self.limbs[0] = @as(Limb, w_value); self.metadata += 1; } else { var i: usize = 0; @@ -453,7 +453,7 @@ pub const Int = struct { for (self.limbs[0..self.len()]) |limb| { var shift: usize = 0; while (shift < Limb.bit_count) : (shift += base_shift) { - const r = @intCast(u8, (limb >> @intCast(Log2Limb, shift)) & Limb(base - 1)); + const r = @intCast(u8, (limb >> @intCast(Log2Limb, shift)) & @as(Limb, base - 1)); const ch = try digitToChar(r, base); try digits.append(ch); } @@ -560,7 +560,7 @@ pub const Int = struct { /// Returns -1, 0, 1 if a < b, a == b or a > b respectively. pub fn cmp(a: Int, b: Int) i8 { if (a.isPositive() != b.isPositive()) { - return if (a.isPositive()) i8(1) else -1; + return if (a.isPositive()) @as(i8, 1) else -1; } else { const r = cmpAbs(a, b); return if (a.isPositive()) r else -r; @@ -785,7 +785,7 @@ pub const Int = struct { const c1: Limb = @boolToInt(@addWithOverflow(Limb, a, carry.*, &r1)); // r2 = b * c - const bc = DoubleLimb(math.mulWide(Limb, b, c)); + const bc = @as(DoubleLimb, math.mulWide(Limb, b, c)); const r2 = @truncate(Limb, bc); const c2 = @truncate(Limb, bc >> Limb.bit_count); @@ -1084,7 +1084,7 @@ pub const Int = struct { rem.* = 0; for (a) |_, ri| { const i = a.len - ri - 1; - const pdiv = ((DoubleLimb(rem.*) << Limb.bit_count) | a[i]); + const pdiv = ((@as(DoubleLimb, rem.*) << Limb.bit_count) | a[i]); if (pdiv == 0) { quo[i] = 0; @@ -1143,9 +1143,9 @@ pub const Int = struct { if (x.limbs[i] == y.limbs[t]) { q.limbs[i - t - 1] = maxInt(Limb); } else { - const num = (DoubleLimb(x.limbs[i]) << Limb.bit_count) | DoubleLimb(x.limbs[i - 1]); - const z = @intCast(Limb, num / DoubleLimb(y.limbs[t])); - q.limbs[i - t - 1] = if (z > maxInt(Limb)) maxInt(Limb) else Limb(z); + const num = (@as(DoubleLimb, x.limbs[i]) << Limb.bit_count) | @as(DoubleLimb, x.limbs[i - 1]); + const z = @intCast(Limb, num / @as(DoubleLimb, y.limbs[t])); + q.limbs[i - t - 1] = if (z > maxInt(Limb)) maxInt(Limb) else @as(Limb, z); } // 3.2 @@ -1362,7 +1362,7 @@ test "big.int comptime_int set" { comptime var i: usize = 0; inline while (i < s_limb_count) : (i += 1) { - const result = Limb(s & maxInt(Limb)); + const result = @as(Limb, s & maxInt(Limb)); s >>= Limb.bit_count / 2; s >>= Limb.bit_count / 2; testing.expect(a.limbs[i] == result); @@ -1377,7 +1377,7 @@ test "big.int comptime_int set negative" { } test "big.int int set unaligned small" { - var a = try Int.initSet(al, u7(45)); + var a = try Int.initSet(al, @as(u7, 45)); testing.expect(a.limbs[0] == 45); testing.expect(a.isPositive() == true); diff --git a/lib/std/math/cbrt.zig b/lib/std/math/cbrt.zig @@ -54,11 +54,11 @@ fn cbrt32(x: f32) f32 { // first step newton to 16 bits var t: f64 = @bitCast(f32, u); var r: f64 = t * t * t; - t = t * (f64(x) + x + r) / (x + r + r); + t = t * (@as(f64, x) + x + r) / (x + r + r); // second step newton to 47 bits r = t * t * t; - t = t * (f64(x) + x + r) / (x + r + r); + t = t * (@as(f64, x) + x + r) / (x + r + r); return @floatCast(f32, t); } @@ -97,7 +97,7 @@ fn cbrt64(x: f64) f64 { } u &= 1 << 63; - u |= u64(hx) << 32; + u |= @as(u64, hx) << 32; var t = @bitCast(f64, u); // cbrt to 23 bits @@ -120,8 +120,8 @@ fn cbrt64(x: f64) f64 { } test "math.cbrt" { - expect(cbrt(f32(0.0)) == cbrt32(0.0)); - expect(cbrt(f64(0.0)) == cbrt64(0.0)); + expect(cbrt(@as(f32, 0.0)) == cbrt32(0.0)); + expect(cbrt(@as(f64, 0.0)) == cbrt64(0.0)); } test "math.cbrt32" { diff --git a/lib/std/math/ceil.zig b/lib/std/math/ceil.zig @@ -37,7 +37,7 @@ fn ceil32(x: f32) f32 { if (e >= 23) { return x; } else if (e >= 0) { - m = u32(0x007FFFFF) >> @intCast(u5, e); + m = @as(u32, 0x007FFFFF) >> @intCast(u5, e); if (u & m == 0) { return x; } @@ -87,8 +87,8 @@ fn ceil64(x: f64) f64 { } test "math.ceil" { - expect(ceil(f32(0.0)) == ceil32(0.0)); - expect(ceil(f64(0.0)) == ceil64(0.0)); + expect(ceil(@as(f32, 0.0)) == ceil32(0.0)); + expect(ceil(@as(f64, 0.0)) == ceil64(0.0)); } test "math.ceil32" { diff --git a/lib/std/math/complex.zig b/lib/std/math/complex.zig @@ -133,8 +133,8 @@ test "complex.div" { const b = Complex(f32).new(2, 7); const c = a.div(b); - testing.expect(math.approxEq(f32, c.re, f32(31) / 53, epsilon) and - math.approxEq(f32, c.im, f32(-29) / 53, epsilon)); + testing.expect(math.approxEq(f32, c.re, @as(f32, 31) / 53, epsilon) and + math.approxEq(f32, c.im, @as(f32, -29) / 53, epsilon)); } test "complex.conjugate" { @@ -148,8 +148,8 @@ test "complex.reciprocal" { const a = Complex(f32).new(5, 3); const c = a.reciprocal(); - testing.expect(math.approxEq(f32, c.re, f32(5) / 34, epsilon) and - math.approxEq(f32, c.im, f32(-3) / 34, epsilon)); + testing.expect(math.approxEq(f32, c.re, @as(f32, 5) / 34, epsilon) and + math.approxEq(f32, c.im, @as(f32, -3) / 34, epsilon)); } test "complex.magnitude" { diff --git a/lib/std/math/complex/acos.zig b/lib/std/math/complex/acos.zig @@ -8,7 +8,7 @@ const Complex = cmath.Complex; pub fn acos(z: var) Complex(@typeOf(z.re)) { const T = @typeOf(z.re); const q = cmath.asin(z); - return Complex(T).new(T(math.pi) / 2 - q.re, -q.im); + return Complex(T).new(@as(T, math.pi) / 2 - q.re, -q.im); } const epsilon = 0.0001; diff --git a/lib/std/math/complex/ldexp.zig b/lib/std/math/complex/ldexp.zig @@ -59,13 +59,13 @@ fn frexp_exp64(x: f64, expt: *i32) f64 { expt.* = @intCast(i32, hx >> 20) - (0x3ff + 1023) + k; const high_word = (hx & 0xfffff) | ((0x3ff + 1023) << 20); - return @bitCast(f64, (u64(high_word) << 32) | lx); + return @bitCast(f64, (@as(u64, high_word) << 32) | lx); } fn ldexp_cexp64(z: Complex(f64), expt: i32) Complex(f64) { var ex_expt: i32 = undefined; const exp_x = frexp_exp64(z.re, &ex_expt); - const exptf = i64(expt + ex_expt); + const exptf = @as(i64, expt + ex_expt); const half_expt1 = @divTrunc(exptf, 2); const scale1 = @bitCast(f64, (0x3ff + half_expt1) << 20); diff --git a/lib/std/math/complex/sqrt.zig b/lib/std/math/complex/sqrt.zig @@ -52,8 +52,8 @@ fn sqrt32(z: Complex(f32)) Complex(f32) { // y = nan special case is handled fine below // double-precision avoids overflow with correct rounding. - const dx = f64(x); - const dy = f64(y); + const dx = @as(f64, x); + const dy = @as(f64, y); if (dx >= 0) { const t = math.sqrt((dx + math.hypot(f64, dx, dy)) * 0.5); diff --git a/lib/std/math/complex/tanh.zig b/lib/std/math/complex/tanh.zig @@ -76,7 +76,7 @@ fn tanh64(z: Complex(f64)) Complex(f64) { return Complex(f64).new(x, r); } - const xx = @bitCast(f64, (u64(hx - 0x40000000) << 32) | lx); + const xx = @bitCast(f64, (@as(u64, hx - 0x40000000) << 32) | lx); const r = if (math.isInf(y)) y else math.sin(y) * math.cos(y); return Complex(f64).new(xx, math.copysign(f64, 0, r)); } diff --git a/lib/std/math/copysign.zig b/lib/std/math/copysign.zig @@ -24,7 +24,7 @@ fn copysign16(x: f16, y: f16) f16 { const uy = @bitCast(u16, y); const h1 = ux & (maxInt(u16) / 2); - const h2 = uy & (u16(1) << 15); + const h2 = uy & (@as(u16, 1) << 15); return @bitCast(f16, h1 | h2); } @@ -33,7 +33,7 @@ fn copysign32(x: f32, y: f32) f32 { const uy = @bitCast(u32, y); const h1 = ux & (maxInt(u32) / 2); - const h2 = uy & (u32(1) << 31); + const h2 = uy & (@as(u32, 1) << 31); return @bitCast(f32, h1 | h2); } @@ -42,7 +42,7 @@ fn copysign64(x: f64, y: f64) f64 { const uy = @bitCast(u64, y); const h1 = ux & (maxInt(u64) / 2); - const h2 = uy & (u64(1) << 63); + const h2 = uy & (@as(u64, 1) << 63); return @bitCast(f64, h1 | h2); } diff --git a/lib/std/math/cos.zig b/lib/std/math/cos.zig @@ -83,8 +83,8 @@ fn cos_(comptime T: type, x_: T) T { } test "math.cos" { - expect(cos(f32(0.0)) == cos_(f32, 0.0)); - expect(cos(f64(0.0)) == cos_(f64, 0.0)); + expect(cos(@as(f32, 0.0)) == cos_(f32, 0.0)); + expect(cos(@as(f64, 0.0)) == cos_(f64, 0.0)); } test "math.cos32" { diff --git a/lib/std/math/cosh.zig b/lib/std/math/cosh.zig @@ -88,8 +88,8 @@ fn cosh64(x: f64) f64 { } test "math.cosh" { - expect(cosh(f32(1.5)) == cosh32(1.5)); - expect(cosh(f64(1.5)) == cosh64(1.5)); + expect(cosh(@as(f32, 1.5)) == cosh32(1.5)); + expect(cosh(@as(f64, 1.5)) == cosh64(1.5)); } test "math.cosh32" { diff --git a/lib/std/math/exp.zig b/lib/std/math/exp.zig @@ -134,7 +134,7 @@ fn exp64(x_: f64) f64 { } if (x < -708.39641853226410622) { // underflow if x != -inf - // math.forceEval(f32(-0x1.0p-149 / x)); + // math.forceEval(@as(f32, -0x1.0p-149 / x)); if (x < -745.13321910194110842) { return 0; } @@ -183,8 +183,8 @@ fn exp64(x_: f64) f64 { } test "math.exp" { - assert(exp(f32(0.0)) == exp32(0.0)); - assert(exp(f64(0.0)) == exp64(0.0)); + assert(exp(@as(f32, 0.0)) == exp32(0.0)); + assert(exp(@as(f64, 0.0)) == exp64(0.0)); } test "math.exp32" { diff --git a/lib/std/math/exp2.zig b/lib/std/math/exp2.zig @@ -85,7 +85,7 @@ fn exp2_32(x: f32) f32 { const k = i_0 / tblsiz; // NOTE: musl relies on undefined overflow shift behaviour. Appears that this produces the // intended result but should confirm how GCC/Clang handle this to ensure. - const uk = @bitCast(f64, u64(0x3FF + k) << 52); + const uk = @bitCast(f64, @as(u64, 0x3FF + k) << 52); i_0 &= tblsiz - 1; uf -= redux; @@ -421,8 +421,8 @@ fn exp2_64(x: f64) f64 { } test "math.exp2" { - expect(exp2(f32(0.8923)) == exp2_32(0.8923)); - expect(exp2(f64(0.8923)) == exp2_64(0.8923)); + expect(exp2(@as(f32, 0.8923)) == exp2_32(0.8923)); + expect(exp2(@as(f64, 0.8923)) == exp2_64(0.8923)); } test "math.exp2_32" { diff --git a/lib/std/math/expm1.zig b/lib/std/math/expm1.zig @@ -287,8 +287,8 @@ fn expm1_64(x_: f64) f64 { } test "math.exp1m" { - expect(expm1(f32(0.0)) == expm1_32(0.0)); - expect(expm1(f64(0.0)) == expm1_64(0.0)); + expect(expm1(@as(f32, 0.0)) == expm1_32(0.0)); + expect(expm1(@as(f64, 0.0)) == expm1_64(0.0)); } test "math.expm1_32" { diff --git a/lib/std/math/expo2.zig b/lib/std/math/expo2.zig @@ -30,6 +30,6 @@ fn expo2d(x: f64) f64 { const kln2 = 0x1.62066151ADD8BP+10; const u = (0x3FF + k / 2) << 20; - const scale = @bitCast(f64, u64(u) << 32); + const scale = @bitCast(f64, @as(u64, u) << 32); return math.exp(x - kln2) * scale * scale; } diff --git a/lib/std/math/fabs.zig b/lib/std/math/fabs.zig @@ -50,10 +50,10 @@ fn fabs128(x: f128) f128 { } test "math.fabs" { - expect(fabs(f16(1.0)) == fabs16(1.0)); - expect(fabs(f32(1.0)) == fabs32(1.0)); - expect(fabs(f64(1.0)) == fabs64(1.0)); - expect(fabs(f128(1.0)) == fabs128(1.0)); + expect(fabs(@as(f16, 1.0)) == fabs16(1.0)); + expect(fabs(@as(f32, 1.0)) == fabs32(1.0)); + expect(fabs(@as(f64, 1.0)) == fabs64(1.0)); + expect(fabs(@as(f128, 1.0)) == fabs128(1.0)); } test "math.fabs16" { diff --git a/lib/std/math/floor.zig b/lib/std/math/floor.zig @@ -40,7 +40,7 @@ fn floor16(x: f16) f16 { } if (e >= 0) { - m = u16(1023) >> @intCast(u4, e); + m = @as(u16, 1023) >> @intCast(u4, e); if (u & m == 0) { return x; } @@ -74,7 +74,7 @@ fn floor32(x: f32) f32 { } if (e >= 0) { - m = u32(0x007FFFFF) >> @intCast(u5, e); + m = @as(u32, 0x007FFFFF) >> @intCast(u5, e); if (u & m == 0) { return x; } @@ -123,9 +123,9 @@ fn floor64(x: f64) f64 { } test "math.floor" { - expect(floor(f16(1.3)) == floor16(1.3)); - expect(floor(f32(1.3)) == floor32(1.3)); - expect(floor(f64(1.3)) == floor64(1.3)); + expect(floor(@as(f16, 1.3)) == floor16(1.3)); + expect(floor(@as(f32, 1.3)) == floor32(1.3)); + expect(floor(@as(f64, 1.3)) == floor64(1.3)); } test "math.floor16" { diff --git a/lib/std/math/fma.zig b/lib/std/math/fma.zig @@ -18,7 +18,7 @@ pub fn fma(comptime T: type, x: T, y: T, z: T) T { } fn fma32(x: f32, y: f32, z: f32) f32 { - const xy = f64(x) * y; + const xy = @as(f64, x) * y; const xy_z = xy + z; const u = @bitCast(u64, xy_z); const e = (u >> 52) & 0x7FF; diff --git a/lib/std/math/frexp.zig b/lib/std/math/frexp.zig @@ -108,11 +108,11 @@ fn frexp64(x: f64) frexp64_result { } test "math.frexp" { - const a = frexp(f32(1.3)); + const a = frexp(@as(f32, 1.3)); const b = frexp32(1.3); expect(a.significand == b.significand and a.exponent == b.exponent); - const c = frexp(f64(1.3)); + const c = frexp(@as(f64, 1.3)); const d = frexp64(1.3); expect(c.significand == d.significand and c.exponent == d.exponent); } diff --git a/lib/std/math/hypot.zig b/lib/std/math/hypot.zig @@ -56,7 +56,7 @@ fn hypot32(x: f32, y: f32) f32 { yy *= 0x1.0p-90; } - return z * math.sqrt(@floatCast(f32, f64(x) * x + f64(y) * y)); + return z * math.sqrt(@floatCast(f32, @as(f64, x) * x + @as(f64, y) * y)); } fn sq(hi: *f64, lo: *f64, x: f64) void { diff --git a/lib/std/math/ilogb.zig b/lib/std/math/ilogb.zig @@ -26,7 +26,7 @@ pub fn ilogb(x: var) i32 { } // NOTE: Should these be exposed publicly? -const fp_ilogbnan = -1 - i32(maxInt(u32) >> 1); +const fp_ilogbnan = -1 - @as(i32, maxInt(u32) >> 1); const fp_ilogb0 = fp_ilogbnan; fn ilogb32(x: f32) i32 { @@ -101,8 +101,8 @@ fn ilogb64(x: f64) i32 { } test "math.ilogb" { - expect(ilogb(f32(0.2)) == ilogb32(0.2)); - expect(ilogb(f64(0.2)) == ilogb64(0.2)); + expect(ilogb(@as(f32, 0.2)) == ilogb32(0.2)); + expect(ilogb(@as(f64, 0.2)) == ilogb64(0.2)); } test "math.ilogb32" { diff --git a/lib/std/math/isfinite.zig b/lib/std/math/isfinite.zig @@ -26,12 +26,12 @@ pub fn isFinite(x: var) bool { } test "math.isFinite" { - expect(isFinite(f16(0.0))); - expect(isFinite(f16(-0.0))); - expect(isFinite(f32(0.0))); - expect(isFinite(f32(-0.0))); - expect(isFinite(f64(0.0))); - expect(isFinite(f64(-0.0))); + expect(isFinite(@as(f16, 0.0))); + expect(isFinite(@as(f16, -0.0))); + expect(isFinite(@as(f32, 0.0))); + expect(isFinite(@as(f32, -0.0))); + expect(isFinite(@as(f64, 0.0))); + expect(isFinite(@as(f64, -0.0))); expect(!isFinite(math.inf(f16))); expect(!isFinite(-math.inf(f16))); expect(!isFinite(math.inf(f32))); diff --git a/lib/std/math/isinf.zig b/lib/std/math/isinf.zig @@ -74,14 +74,14 @@ pub fn isNegativeInf(x: var) bool { } test "math.isInf" { - expect(!isInf(f16(0.0))); - expect(!isInf(f16(-0.0))); - expect(!isInf(f32(0.0))); - expect(!isInf(f32(-0.0))); - expect(!isInf(f64(0.0))); - expect(!isInf(f64(-0.0))); - expect(!isInf(f128(0.0))); - expect(!isInf(f128(-0.0))); + expect(!isInf(@as(f16, 0.0))); + expect(!isInf(@as(f16, -0.0))); + expect(!isInf(@as(f32, 0.0))); + expect(!isInf(@as(f32, -0.0))); + expect(!isInf(@as(f64, 0.0))); + expect(!isInf(@as(f64, -0.0))); + expect(!isInf(@as(f128, 0.0))); + expect(!isInf(@as(f128, -0.0))); expect(isInf(math.inf(f16))); expect(isInf(-math.inf(f16))); expect(isInf(math.inf(f32))); @@ -93,14 +93,14 @@ test "math.isInf" { } test "math.isPositiveInf" { - expect(!isPositiveInf(f16(0.0))); - expect(!isPositiveInf(f16(-0.0))); - expect(!isPositiveInf(f32(0.0))); - expect(!isPositiveInf(f32(-0.0))); - expect(!isPositiveInf(f64(0.0))); - expect(!isPositiveInf(f64(-0.0))); - expect(!isPositiveInf(f128(0.0))); - expect(!isPositiveInf(f128(-0.0))); + expect(!isPositiveInf(@as(f16, 0.0))); + expect(!isPositiveInf(@as(f16, -0.0))); + expect(!isPositiveInf(@as(f32, 0.0))); + expect(!isPositiveInf(@as(f32, -0.0))); + expect(!isPositiveInf(@as(f64, 0.0))); + expect(!isPositiveInf(@as(f64, -0.0))); + expect(!isPositiveInf(@as(f128, 0.0))); + expect(!isPositiveInf(@as(f128, -0.0))); expect(isPositiveInf(math.inf(f16))); expect(!isPositiveInf(-math.inf(f16))); expect(isPositiveInf(math.inf(f32))); @@ -112,14 +112,14 @@ test "math.isPositiveInf" { } test "math.isNegativeInf" { - expect(!isNegativeInf(f16(0.0))); - expect(!isNegativeInf(f16(-0.0))); - expect(!isNegativeInf(f32(0.0))); - expect(!isNegativeInf(f32(-0.0))); - expect(!isNegativeInf(f64(0.0))); - expect(!isNegativeInf(f64(-0.0))); - expect(!isNegativeInf(f128(0.0))); - expect(!isNegativeInf(f128(-0.0))); + expect(!isNegativeInf(@as(f16, 0.0))); + expect(!isNegativeInf(@as(f16, -0.0))); + expect(!isNegativeInf(@as(f32, 0.0))); + expect(!isNegativeInf(@as(f32, -0.0))); + expect(!isNegativeInf(@as(f64, 0.0))); + expect(!isNegativeInf(@as(f64, -0.0))); + expect(!isNegativeInf(@as(f128, 0.0))); + expect(!isNegativeInf(@as(f128, -0.0))); expect(!isNegativeInf(math.inf(f16))); expect(isNegativeInf(-math.inf(f16))); expect(!isNegativeInf(math.inf(f32))); diff --git a/lib/std/math/isnan.zig b/lib/std/math/isnan.zig @@ -20,8 +20,8 @@ test "math.isNan" { expect(isNan(math.nan(f32))); expect(isNan(math.nan(f64))); expect(isNan(math.nan(f128))); - expect(!isNan(f16(1.0))); - expect(!isNan(f32(1.0))); - expect(!isNan(f64(1.0))); - expect(!isNan(f128(1.0))); + expect(!isNan(@as(f16, 1.0))); + expect(!isNan(@as(f32, 1.0))); + expect(!isNan(@as(f64, 1.0))); + expect(!isNan(@as(f128, 1.0))); } diff --git a/lib/std/math/isnormal.zig b/lib/std/math/isnormal.zig @@ -29,10 +29,10 @@ test "math.isNormal" { expect(!isNormal(math.nan(f16))); expect(!isNormal(math.nan(f32))); expect(!isNormal(math.nan(f64))); - expect(!isNormal(f16(0))); - expect(!isNormal(f32(0))); - expect(!isNormal(f64(0))); - expect(isNormal(f16(1.0))); - expect(isNormal(f32(1.0))); - expect(isNormal(f64(1.0))); + expect(!isNormal(@as(f16, 0))); + expect(!isNormal(@as(f32, 0))); + expect(!isNormal(@as(f64, 0))); + expect(isNormal(@as(f16, 1.0))); + expect(isNormal(@as(f32, 1.0))); + expect(isNormal(@as(f64, 1.0))); } diff --git a/lib/std/math/ln.zig b/lib/std/math/ln.zig @@ -31,10 +31,10 @@ pub fn ln(x: var) @typeOf(x) { }; }, TypeId.ComptimeInt => { - return @typeOf(1)(math.floor(ln_64(f64(x)))); + return @typeOf(1)(math.floor(ln_64(@as(f64, x)))); }, TypeId.Int => { - return T(math.floor(ln_64(f64(x)))); + return @as(T, math.floor(ln_64(@as(f64, x)))); }, else => @compileError("ln not implemented for " ++ @typeName(T)), } @@ -132,7 +132,7 @@ pub fn ln_64(x_: f64) f64 { hx += 0x3FF00000 - 0x3FE6A09E; k += @intCast(i32, hx >> 20) - 0x3FF; hx = (hx & 0x000FFFFF) + 0x3FE6A09E; - ix = (u64(hx) << 32) | (ix & 0xFFFFFFFF); + ix = (@as(u64, hx) << 32) | (ix & 0xFFFFFFFF); x = @bitCast(f64, ix); const f = x - 1.0; @@ -149,8 +149,8 @@ pub fn ln_64(x_: f64) f64 { } test "math.ln" { - expect(ln(f32(0.2)) == ln_32(0.2)); - expect(ln(f64(0.2)) == ln_64(0.2)); + expect(ln(@as(f32, 0.2)) == ln_32(0.2)); + expect(ln(@as(f64, 0.2)) == ln_64(0.2)); } test "math.ln32" { diff --git a/lib/std/math/log.zig b/lib/std/math/log.zig @@ -23,10 +23,10 @@ pub fn log(comptime T: type, base: T, x: T) T { const float_base = math.lossyCast(f64, base); switch (@typeId(T)) { TypeId.ComptimeFloat => { - return @typeOf(1.0)(math.ln(f64(x)) / math.ln(float_base)); + return @typeOf(1.0)(math.ln(@as(f64, x)) / math.ln(float_base)); }, TypeId.ComptimeInt => { - return @typeOf(1)(math.floor(math.ln(f64(x)) / math.ln(float_base))); + return @typeOf(1)(math.floor(math.ln(@as(f64, x)) / math.ln(float_base))); }, builtin.TypeId.Int => { // TODO implement integer log without using float math @@ -35,7 +35,7 @@ pub fn log(comptime T: type, base: T, x: T) T { builtin.TypeId.Float => { switch (T) { - f32 => return @floatCast(f32, math.ln(f64(x)) / math.ln(float_base)), + f32 => return @floatCast(f32, math.ln(@as(f64, x)) / math.ln(float_base)), f64 => return math.ln(x) / math.ln(float_base), else => @compileError("log not implemented for " ++ @typeName(T)), } @@ -64,9 +64,9 @@ test "math.log float" { } test "math.log float_special" { - expect(log(f32, 2, 0.2301974) == math.log2(f32(0.2301974))); - expect(log(f32, 10, 0.2301974) == math.log10(f32(0.2301974))); + expect(log(f32, 2, 0.2301974) == math.log2(@as(f32, 0.2301974))); + expect(log(f32, 10, 0.2301974) == math.log10(@as(f32, 0.2301974))); - expect(log(f64, 2, 213.23019799993) == math.log2(f64(213.23019799993))); - expect(log(f64, 10, 213.23019799993) == math.log10(f64(213.23019799993))); + expect(log(f64, 2, 213.23019799993) == math.log2(@as(f64, 213.23019799993))); + expect(log(f64, 10, 213.23019799993) == math.log10(@as(f64, 213.23019799993))); } diff --git a/lib/std/math/log10.zig b/lib/std/math/log10.zig @@ -32,7 +32,7 @@ pub fn log10(x: var) @typeOf(x) { }; }, TypeId.ComptimeInt => { - return @typeOf(1)(math.floor(log10_64(f64(x)))); + return @typeOf(1)(math.floor(log10_64(@as(f64, x)))); }, TypeId.Int => { return @floatToInt(T, math.floor(log10_64(@intToFloat(f64, x)))); @@ -143,7 +143,7 @@ pub fn log10_64(x_: f64) f64 { hx += 0x3FF00000 - 0x3FE6A09E; k += @intCast(i32, hx >> 20) - 0x3FF; hx = (hx & 0x000FFFFF) + 0x3FE6A09E; - ix = (u64(hx) << 32) | (ix & 0xFFFFFFFF); + ix = (@as(u64, hx) << 32) | (ix & 0xFFFFFFFF); x = @bitCast(f64, ix); const f = x - 1.0; @@ -158,7 +158,7 @@ pub fn log10_64(x_: f64) f64 { // hi + lo = f - hfsq + s * (hfsq + R) ~ log(1 + f) var hi = f - hfsq; var hii = @bitCast(u64, hi); - hii &= u64(maxInt(u64)) << 32; + hii &= @as(u64, maxInt(u64)) << 32; hi = @bitCast(f64, hii); const lo = f - hi - hfsq + s * (hfsq + R); @@ -177,8 +177,8 @@ pub fn log10_64(x_: f64) f64 { } test "math.log10" { - testing.expect(log10(f32(0.2)) == log10_32(0.2)); - testing.expect(log10(f64(0.2)) == log10_64(0.2)); + testing.expect(log10(@as(f32, 0.2)) == log10_32(0.2)); + testing.expect(log10(@as(f64, 0.2)) == log10_64(0.2)); } test "math.log10_32" { diff --git a/lib/std/math/log1p.zig b/lib/std/math/log1p.zig @@ -166,7 +166,7 @@ fn log1p_64(x: f64) f64 { // u into [sqrt(2)/2, sqrt(2)] iu = (iu & 0x000FFFFF) + 0x3FE6A09E; - const iq = (u64(iu) << 32) | (hu & 0xFFFFFFFF); + const iq = (@as(u64, iu) << 32) | (hu & 0xFFFFFFFF); f = @bitCast(f64, iq) - 1; } @@ -183,8 +183,8 @@ fn log1p_64(x: f64) f64 { } test "math.log1p" { - expect(log1p(f32(0.0)) == log1p_32(0.0)); - expect(log1p(f64(0.0)) == log1p_64(0.0)); + expect(log1p(@as(f32, 0.0)) == log1p_32(0.0)); + expect(log1p(@as(f64, 0.0)) == log1p_64(0.0)); } test "math.log1p_32" { diff --git a/lib/std/math/log2.zig b/lib/std/math/log2.zig @@ -143,7 +143,7 @@ pub fn log2_64(x_: f64) f64 { hx += 0x3FF00000 - 0x3FE6A09E; k += @intCast(i32, hx >> 20) - 0x3FF; hx = (hx & 0x000FFFFF) + 0x3FE6A09E; - ix = (u64(hx) << 32) | (ix & 0xFFFFFFFF); + ix = (@as(u64, hx) << 32) | (ix & 0xFFFFFFFF); x = @bitCast(f64, ix); const f = x - 1.0; @@ -158,7 +158,7 @@ pub fn log2_64(x_: f64) f64 { // hi + lo = f - hfsq + s * (hfsq + R) ~ log(1 + f) var hi = f - hfsq; var hii = @bitCast(u64, hi); - hii &= u64(maxInt(u64)) << 32; + hii &= @as(u64, maxInt(u64)) << 32; hi = @bitCast(f64, hii); const lo = f - hi - hfsq + s * (hfsq + R); @@ -175,8 +175,8 @@ pub fn log2_64(x_: f64) f64 { } test "math.log2" { - expect(log2(f32(0.2)) == log2_32(0.2)); - expect(log2(f64(0.2)) == log2_64(0.2)); + expect(log2(@as(f32, 0.2)) == log2_32(0.2)); + expect(log2(@as(f64, 0.2)) == log2_64(0.2)); } test "math.log2_32" { diff --git a/lib/std/math/modf.zig b/lib/std/math/modf.zig @@ -65,7 +65,7 @@ fn modf32(x: f32) modf32_result { return result; } - const mask = u32(0x007FFFFF) >> @intCast(u5, e); + const mask = @as(u32, 0x007FFFFF) >> @intCast(u5, e); if (u & mask == 0) { result.ipart = x; result.fpart = @bitCast(f32, us); @@ -109,7 +109,7 @@ fn modf64(x: f64) modf64_result { return result; } - const mask = u64(maxInt(u64) >> 12) >> @intCast(u6, e); + const mask = @as(u64, maxInt(u64) >> 12) >> @intCast(u6, e); if (u & mask == 0) { result.ipart = x; result.fpart = @bitCast(f64, us); @@ -123,12 +123,12 @@ fn modf64(x: f64) modf64_result { } test "math.modf" { - const a = modf(f32(1.0)); + const a = modf(@as(f32, 1.0)); const b = modf32(1.0); // NOTE: No struct comparison on generic return type function? non-named, makes sense, but still. expect(a.ipart == b.ipart and a.fpart == b.fpart); - const c = modf(f64(1.0)); + const c = modf(@as(f64, 1.0)); const d = modf64(1.0); expect(a.ipart == b.ipart and a.fpart == b.fpart); } diff --git a/lib/std/math/round.zig b/lib/std/math/round.zig @@ -91,8 +91,8 @@ fn round64(x_: f64) f64 { } test "math.round" { - expect(round(f32(1.3)) == round32(1.3)); - expect(round(f64(1.3)) == round64(1.3)); + expect(round(@as(f32, 1.3)) == round32(1.3)); + expect(round(@as(f64, 1.3)) == round64(1.3)); } test "math.round32" { diff --git a/lib/std/math/scalbn.zig b/lib/std/math/scalbn.zig @@ -79,8 +79,8 @@ fn scalbn64(x: f64, n_: i32) f64 { } test "math.scalbn" { - expect(scalbn(f32(1.5), 4) == scalbn32(1.5, 4)); - expect(scalbn(f64(1.5), 4) == scalbn64(1.5, 4)); + expect(scalbn(@as(f32, 1.5), 4) == scalbn32(1.5, 4)); + expect(scalbn(@as(f64, 1.5), 4) == scalbn64(1.5, 4)); } test "math.scalbn32" { diff --git a/lib/std/math/signbit.zig b/lib/std/math/signbit.zig @@ -29,9 +29,9 @@ fn signbit64(x: f64) bool { } test "math.signbit" { - expect(signbit(f16(4.0)) == signbit16(4.0)); - expect(signbit(f32(4.0)) == signbit32(4.0)); - expect(signbit(f64(4.0)) == signbit64(4.0)); + expect(signbit(@as(f16, 4.0)) == signbit16(4.0)); + expect(signbit(@as(f32, 4.0)) == signbit32(4.0)); + expect(signbit(@as(f64, 4.0)) == signbit64(4.0)); } test "math.signbit16" { diff --git a/lib/std/math/sin.zig b/lib/std/math/sin.zig @@ -88,9 +88,9 @@ test "math.sin" { // TODO https://github.com/ziglang/zig/issues/3289 return error.SkipZigTest; } - expect(sin(f32(0.0)) == sin_(f32, 0.0)); - expect(sin(f64(0.0)) == sin_(f64, 0.0)); - expect(comptime (math.sin(f64(2))) == math.sin(f64(2))); + expect(sin(@as(f32, 0.0)) == sin_(f32, 0.0)); + expect(sin(@as(f64, 0.0)) == sin_(f64, 0.0)); + expect(comptime (math.sin(@as(f64, 2))) == math.sin(@as(f64, 2))); } test "math.sin32" { diff --git a/lib/std/math/sinh.zig b/lib/std/math/sinh.zig @@ -93,8 +93,8 @@ fn sinh64(x: f64) f64 { } test "math.sinh" { - expect(sinh(f32(1.5)) == sinh32(1.5)); - expect(sinh(f64(1.5)) == sinh64(1.5)); + expect(sinh(@as(f32, 1.5)) == sinh32(1.5)); + expect(sinh(@as(f64, 1.5)) == sinh64(1.5)); } test "math.sinh32" { diff --git a/lib/std/math/sqrt.zig b/lib/std/math/sqrt.zig @@ -15,7 +15,7 @@ const maxInt = std.math.maxInt; pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typeOf(x).bit_count / 2) else @typeOf(x)) { const T = @typeOf(x); switch (@typeId(T)) { - TypeId.ComptimeFloat => return T(@sqrt(f64, x)), // TODO upgrade to f128 + TypeId.ComptimeFloat => return @as(T, @sqrt(f64, x)), // TODO upgrade to f128 TypeId.Float => return @sqrt(T, x), TypeId.ComptimeInt => comptime { if (x > maxInt(u128)) { @@ -24,7 +24,7 @@ pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typ if (x < 0) { @compileError("sqrt on negative number"); } - return T(sqrt_int(u128, x)); + return @as(T, sqrt_int(u128, x)); }, TypeId.Int => return sqrt_int(T, x), else => @compileError("sqrt not implemented for " ++ @typeName(T)), @@ -32,9 +32,9 @@ pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typ } test "math.sqrt" { - expect(sqrt(f16(0.0)) == @sqrt(f16, 0.0)); - expect(sqrt(f32(0.0)) == @sqrt(f32, 0.0)); - expect(sqrt(f64(0.0)) == @sqrt(f64, 0.0)); + expect(sqrt(@as(f16, 0.0)) == @sqrt(f16, 0.0)); + expect(sqrt(@as(f32, 0.0)) == @sqrt(f32, 0.0)); + expect(sqrt(@as(f64, 0.0)) == @sqrt(f64, 0.0)); } test "math.sqrt16" { diff --git a/lib/std/math/tan.zig b/lib/std/math/tan.zig @@ -75,8 +75,8 @@ fn tan_(comptime T: type, x_: T) T { } test "math.tan" { - expect(tan(f32(0.0)) == tan_(f32, 0.0)); - expect(tan(f64(0.0)) == tan_(f64, 0.0)); + expect(tan(@as(f32, 0.0)) == tan_(f32, 0.0)); + expect(tan(@as(f64, 0.0)) == tan_(f64, 0.0)); } test "math.tan32" { diff --git a/lib/std/math/tanh.zig b/lib/std/math/tanh.zig @@ -119,8 +119,8 @@ fn tanh64(x: f64) f64 { } test "math.tanh" { - expect(tanh(f32(1.5)) == tanh32(1.5)); - expect(tanh(f64(1.5)) == tanh64(1.5)); + expect(tanh(@as(f32, 1.5)) == tanh32(1.5)); + expect(tanh(@as(f64, 1.5)) == tanh64(1.5)); } test "math.tanh32" { diff --git a/lib/std/math/trunc.zig b/lib/std/math/trunc.zig @@ -36,7 +36,7 @@ fn trunc32(x: f32) f32 { e = 1; } - m = u32(maxInt(u32)) >> @intCast(u5, e); + m = @as(u32, maxInt(u32)) >> @intCast(u5, e); if (u & m == 0) { return x; } else { @@ -57,7 +57,7 @@ fn trunc64(x: f64) f64 { e = 1; } - m = u64(maxInt(u64)) >> @intCast(u6, e); + m = @as(u64, maxInt(u64)) >> @intCast(u6, e); if (u & m == 0) { return x; } else { @@ -67,8 +67,8 @@ fn trunc64(x: f64) f64 { } test "math.trunc" { - expect(trunc(f32(1.3)) == trunc32(1.3)); - expect(trunc(f64(1.3)) == trunc64(1.3)); + expect(trunc(@as(f32, 1.3)) == trunc32(1.3)); + expect(trunc(@as(f64, 1.3)) == trunc64(1.3)); } test "math.trunc32" { diff --git a/lib/std/mem.zig b/lib/std/mem.zig @@ -118,11 +118,11 @@ pub const Allocator = struct { } else @alignOf(T); if (n == 0) { - return ([*]align(a) T)(undefined)[0..0]; + return @as([*]align(a) T, undefined)[0..0]; } const byte_count = math.mul(usize, @sizeOf(T), n) catch return Error.OutOfMemory; - const byte_slice = try self.reallocFn(self, ([*]u8)(undefined)[0..0], undefined, byte_count, a); + const byte_slice = try self.reallocFn(self, &[0]u8{}, undefined, byte_count, a); assert(byte_slice.len == byte_count); @memset(byte_slice.ptr, undefined, byte_slice.len); if (alignment == null) { @@ -170,7 +170,7 @@ pub const Allocator = struct { } if (new_n == 0) { self.free(old_mem); - return ([*]align(new_alignment) T)(undefined)[0..0]; + return @as([*]align(new_alignment) T, undefined)[0..0]; } const old_byte_slice = @sliceToBytes(old_mem); @@ -523,7 +523,7 @@ pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: builtin. builtin.Endian.Little => { const ShiftType = math.Log2Int(ReturnType); for (bytes) |b, index| { - result = result | (ReturnType(b) << @intCast(ShiftType, index * 8)); + result = result | (@as(ReturnType, b) << @intCast(ShiftType, index * 8)); } }, } @@ -976,7 +976,7 @@ pub const SplitIterator = struct { /// Naively combines a series of slices with a separator. /// Allocates memory for the result, which must be freed by the caller. pub fn join(allocator: *Allocator, separator: []const u8, slices: []const []const u8) ![]u8 { - if (slices.len == 0) return (([*]u8)(undefined))[0..0]; + if (slices.len == 0) return &[0]u8{}; const total_len = blk: { var sum: usize = separator.len * (slices.len - 1); @@ -1011,7 +1011,7 @@ test "mem.join" { /// Copies each T from slices into a new slice that exactly holds all the elements. pub fn concat(allocator: *Allocator, comptime T: type, slices: []const []const T) ![]T { - if (slices.len == 0) return (([*]T)(undefined))[0..0]; + if (slices.len == 0) return &[0]T{}; const total_len = blk: { var sum: usize = 0; @@ -1332,7 +1332,7 @@ fn AsBytesReturnType(comptime P: type) type { if (comptime !trait.isSingleItemPtr(P)) @compileError("expected single item " ++ "pointer, passed " ++ @typeName(P)); - const size = usize(@sizeOf(meta.Child(P))); + const size = @as(usize, @sizeOf(meta.Child(P))); const alignment = comptime meta.alignment(P); if (alignment == 0) { @@ -1353,7 +1353,7 @@ pub fn asBytes(ptr: var) AsBytesReturnType(@typeOf(ptr)) { } test "asBytes" { - const deadbeef = u32(0xDEADBEEF); + const deadbeef = @as(u32, 0xDEADBEEF); const deadbeef_bytes = switch (builtin.endian) { builtin.Endian.Big => "\xDE\xAD\xBE\xEF", builtin.Endian.Little => "\xEF\xBE\xAD\xDE", @@ -1361,7 +1361,7 @@ test "asBytes" { testing.expect(eql(u8, asBytes(&deadbeef), deadbeef_bytes)); - var codeface = u32(0xC0DEFACE); + var codeface = @as(u32, 0xC0DEFACE); for (asBytes(&codeface).*) |*b| b.* = 0; testing.expect(codeface == 0); @@ -1392,7 +1392,7 @@ pub fn toBytes(value: var) [@sizeOf(@typeOf(value))]u8 { } test "toBytes" { - var my_bytes = toBytes(u32(0x12345678)); + var my_bytes = toBytes(@as(u32, 0x12345678)); switch (builtin.endian) { builtin.Endian.Big => testing.expect(eql(u8, my_bytes, "\x12\x34\x56\x78")), builtin.Endian.Little => testing.expect(eql(u8, my_bytes, "\x78\x56\x34\x12")), @@ -1406,7 +1406,7 @@ test "toBytes" { } fn BytesAsValueReturnType(comptime T: type, comptime B: type) type { - const size = usize(@sizeOf(T)); + const size = @as(usize, @sizeOf(T)); if (comptime !trait.is(builtin.TypeId.Pointer)(B) or meta.Child(B) != [size]u8) { @compileError("expected *[N]u8 " ++ ", passed " ++ @typeName(B)); @@ -1424,7 +1424,7 @@ pub fn bytesAsValue(comptime T: type, bytes: var) BytesAsValueReturnType(T, @typ } test "bytesAsValue" { - const deadbeef = u32(0xDEADBEEF); + const deadbeef = @as(u32, 0xDEADBEEF); const deadbeef_bytes = switch (builtin.endian) { builtin.Endian.Big => "\xDE\xAD\xBE\xEF", builtin.Endian.Little => "\xEF\xBE\xAD\xDE", @@ -1472,7 +1472,7 @@ test "bytesToValue" { }; const deadbeef = bytesToValue(u32, deadbeef_bytes); - testing.expect(deadbeef == u32(0xDEADBEEF)); + testing.expect(deadbeef == @as(u32, 0xDEADBEEF)); } fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type { diff --git a/lib/std/meta.zig b/lib/std/meta.zig @@ -341,7 +341,7 @@ test "std.meta.TagType" { ///Returns the active tag of a tagged union pub fn activeTag(u: var) @TagType(@typeOf(u)) { const T = @typeOf(u); - return @TagType(T)(u); + return @as(@TagType(T), u); } test "std.meta.activeTag" { @@ -505,7 +505,7 @@ test "std.meta.eql" { const EU = struct { fn tst(err: bool) !u8 { if (err) return error.Error; - return u8(5); + return @as(u8, 5); } }; diff --git a/lib/std/meta/trait.zig b/lib/std/meta/trait.zig @@ -327,8 +327,8 @@ pub fn isConstPtr(comptime T: type) bool { } test "std.meta.trait.isConstPtr" { - var t = u8(0); - const c = u8(0); + var t = @as(u8, 0); + const c = @as(u8, 0); testing.expect(isConstPtr(*const @typeOf(t))); testing.expect(isConstPtr(@typeOf(&c))); testing.expect(!isConstPtr(*@typeOf(t))); diff --git a/lib/std/mutex.zig b/lib/std/mutex.zig @@ -1,19 +1,13 @@ const std = @import("std.zig"); const builtin = @import("builtin"); -const AtomicOrder = builtin.AtomicOrder; -const AtomicRmwOp = builtin.AtomicRmwOp; const testing = std.testing; const SpinLock = std.SpinLock; -const linux = std.os.linux; -const windows = std.os.windows; +const ThreadParker = std.ThreadParker; /// Lock may be held only once. If the same thread /// tries to acquire the same mutex twice, it deadlocks. -/// This type must be initialized at runtime, and then deinitialized when no -/// longer needed, to free resources. -/// If you need static initialization, use std.StaticallyInitializedMutex. -/// The Linux implementation is based on mutex3 from -/// https://www.akkadia.org/drepper/futex.pdf +/// This type supports static initialization and is based off of Golang 1.13 runtime.lock_futex: +/// https://github.com/golang/go/blob/master/src/runtime/lock_futex.go /// When an application is built in single threaded release mode, all the functions are /// no-ops. In single threaded debug mode, there is deadlock detection. pub const Mutex = if (builtin.single_threaded) @@ -43,84 +37,85 @@ pub const Mutex = if (builtin.single_threaded) return Held{ .mutex = self }; } } -else switch (builtin.os) { - builtin.Os.linux => struct { - /// 0: unlocked - /// 1: locked, no waiters - /// 2: locked, one or more waiters - lock: i32, - - pub const Held = struct { - mutex: *Mutex, +else + struct { + state: State, // TODO: make this an enum + parker: ThreadParker, - pub fn release(self: Held) void { - const c = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Sub, 1, AtomicOrder.Release); - if (c != 1) { - _ = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release); - const rc = linux.futex_wake(&self.mutex.lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1); - switch (linux.getErrno(rc)) { - 0 => {}, - linux.EINVAL => unreachable, - else => unreachable, - } - } - } + const State = enum(u32) { + Unlocked, + Sleeping, + Locked, }; + /// number of iterations to spin yielding the cpu + const SPIN_CPU = 4; + + /// number of iterations to perform in the cpu yield loop + const SPIN_CPU_COUNT = 30; + + /// number of iterations to spin yielding the thread + const SPIN_THREAD = 1; + pub fn init() Mutex { - return Mutex{ .lock = 0 }; + return Mutex{ + .state = .Unlocked, + .parker = ThreadParker.init(), + }; } - pub fn deinit(self: *Mutex) void {} - - pub fn acquire(self: *Mutex) Held { - var c = @cmpxchgWeak(i32, &self.lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse - return Held{ .mutex = self }; - if (c != 2) - c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire); - while (c != 0) { - const rc = linux.futex_wait(&self.lock, linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG, 2, null); - switch (linux.getErrno(rc)) { - 0, linux.EINTR, linux.EAGAIN => {}, - linux.EINVAL => unreachable, - else => unreachable, - } - c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire); - } - return Held{ .mutex = self }; + pub fn deinit(self: *Mutex) void { + self.parker.deinit(); } - }, - // TODO once https://github.com/ziglang/zig/issues/287 (copy elision) is solved, we can make a - // better implementation of this. The problem is we need the init() function to have access to - // the address of the CRITICAL_SECTION, and then have it not move. - builtin.Os.windows => std.StaticallyInitializedMutex, - else => struct { - /// TODO better implementation than spin lock. - /// When changing this, one must also change the corresponding - /// std.StaticallyInitializedMutex code, since it aliases this type, - /// under the assumption that it works both statically and at runtime. - lock: SpinLock, pub const Held = struct { mutex: *Mutex, pub fn release(self: Held) void { - SpinLock.Held.release(SpinLock.Held{ .spinlock = &self.mutex.lock }); + switch (@atomicRmw(State, &self.mutex.state, .Xchg, .Unlocked, .Release)) { + .Locked => {}, + .Sleeping => self.mutex.parker.unpark(@ptrCast(*const u32, &self.mutex.state)), + .Unlocked => unreachable, // unlocking an unlocked mutex + else => unreachable, // should never be anything else + } } }; - pub fn init() Mutex { - return Mutex{ .lock = SpinLock.init() }; - } + pub fn acquire(self: *Mutex) Held { + // Try and speculatively grab the lock. + // If it fails, the state is either Locked or Sleeping + // depending on if theres a thread stuck sleeping below. + var state = @atomicRmw(State, &self.state, .Xchg, .Locked, .Acquire); + if (state == .Unlocked) + return Held{ .mutex = self }; - pub fn deinit(self: *Mutex) void {} + while (true) { + // try and acquire the lock using cpu spinning on failure + var spin: usize = 0; + while (spin < SPIN_CPU) : (spin += 1) { + var value = @atomicLoad(State, &self.state, .Monotonic); + while (value == .Unlocked) + value = @cmpxchgWeak(State, &self.state, .Unlocked, state, .Acquire, .Monotonic) orelse return Held{ .mutex = self }; + SpinLock.yield(SPIN_CPU_COUNT); + } - pub fn acquire(self: *Mutex) Held { - _ = self.lock.acquire(); - return Held{ .mutex = self }; + // try and acquire the lock using thread rescheduling on failure + spin = 0; + while (spin < SPIN_THREAD) : (spin += 1) { + var value = @atomicLoad(State, &self.state, .Monotonic); + while (value == .Unlocked) + value = @cmpxchgWeak(State, &self.state, .Unlocked, state, .Acquire, .Monotonic) orelse return Held{ .mutex = self }; + std.os.sched_yield() catch std.time.sleep(1); + } + + // failed to acquire the lock, go to sleep until woken up by `Held.release()` + if (@atomicRmw(State, &self.state, .Xchg, .Sleeping, .Acquire) == .Unlocked) + return Held{ .mutex = self }; + state = .Sleeping; + self.parker.park(@ptrCast(*const u32, &self.state), @enumToInt(State.Sleeping)); + } } - }, -}; + }; const TestContext = struct { mutex: *Mutex, diff --git a/lib/std/net.zig b/lib/std/net.zig @@ -10,15 +10,18 @@ test "" { _ = @import("net/test.zig"); } -pub const IpAddress = extern union { +const has_unix_sockets = @hasDecl(os, "sockaddr_un"); + +pub const Address = extern union { any: os.sockaddr, in: os.sockaddr_in, in6: os.sockaddr_in6, + un: if (has_unix_sockets) os.sockaddr_un else void, // TODO this crashed the compiler //pub const localhost = initIp4(parseIp4("127.0.0.1") catch unreachable, 0); - pub fn parse(name: []const u8, port: u16) !IpAddress { + pub fn parseIp(name: []const u8, port: u16) !Address { if (parseIp4(name, port)) |ip4| return ip4 else |err| switch (err) { error.Overflow, error.InvalidEnd, @@ -39,17 +42,17 @@ pub const IpAddress = extern union { return error.InvalidIPAddressFormat; } - pub fn parseExpectingFamily(name: []const u8, family: os.sa_family_t, port: u16) !IpAddress { + pub fn parseExpectingFamily(name: []const u8, family: os.sa_family_t, port: u16) !Address { switch (family) { os.AF_INET => return parseIp4(name, port), os.AF_INET6 => return parseIp6(name, port), - os.AF_UNSPEC => return parse(name, port), + os.AF_UNSPEC => return parseIp(name, port), else => unreachable, } } - pub fn parseIp6(buf: []const u8, port: u16) !IpAddress { - var result = IpAddress{ + pub fn parseIp6(buf: []const u8, port: u16) !Address { + var result = Address{ .in6 = os.sockaddr_in6{ .scope_id = 0, .port = mem.nativeToBig(u16, port), @@ -117,7 +120,7 @@ pub const IpAddress = extern union { ip_slice[10] = 0xff; ip_slice[11] = 0xff; - const ptr = @sliceToBytes((*const [1]u32)(&addr)[0..]); + const ptr = @sliceToBytes(@as(*const [1]u32, &addr)[0..]); ip_slice[12] = ptr[0]; ip_slice[13] = ptr[1]; @@ -154,14 +157,14 @@ pub const IpAddress = extern union { } } - pub fn parseIp4(buf: []const u8, port: u16) !IpAddress { - var result = IpAddress{ + pub fn parseIp4(buf: []const u8, port: u16) !Address { + var result = Address{ .in = os.sockaddr_in{ .port = mem.nativeToBig(u16, port), .addr = undefined, }, }; - const out_ptr = @sliceToBytes((*[1]u32)(&result.in.addr)[0..]); + const out_ptr = @sliceToBytes(@as(*[1]u32, &result.in.addr)[0..]); var x: u8 = 0; var index: u8 = 0; @@ -194,8 +197,8 @@ pub const IpAddress = extern union { return error.Incomplete; } - pub fn initIp4(addr: [4]u8, port: u16) IpAddress { - return IpAddress{ + pub fn initIp4(addr: [4]u8, port: u16) Address { + return Address{ .in = os.sockaddr_in{ .port = mem.nativeToBig(u16, port), .addr = @ptrCast(*align(1) const u32, &addr).*, @@ -203,8 +206,8 @@ pub const IpAddress = extern union { }; } - pub fn initIp6(addr: [16]u8, port: u16, flowinfo: u32, scope_id: u32) IpAddress { - return IpAddress{ + pub fn initIp6(addr: [16]u8, port: u16, flowinfo: u32, scope_id: u32) Address { + return Address{ .in6 = os.sockaddr_in6{ .addr = addr, .port = mem.nativeToBig(u16, port), @@ -214,8 +217,24 @@ pub const IpAddress = extern union { }; } + pub fn initUnix(path: []const u8) !Address { + var sock_addr = os.sockaddr_un{ + .family = os.AF_UNIX, + .path = undefined, + }; + + // this enables us to have the proper length of the socket in getOsSockLen + mem.set(u8, &sock_addr.path, 0); + + if (path.len > sock_addr.path.len) return error.NameTooLong; + mem.copy(u8, &sock_addr.path, path); + + return Address{ .un = sock_addr }; + } + /// Returns the port in native endian. - pub fn getPort(self: IpAddress) u16 { + /// Asserts that the address is ip4 or ip6. + pub fn getPort(self: Address) u16 { const big_endian_port = switch (self.any.family) { os.AF_INET => self.in.port, os.AF_INET6 => self.in6.port, @@ -225,7 +244,8 @@ pub const IpAddress = extern union { } /// `port` is native-endian. - pub fn setPort(self: *IpAddress, port: u16) void { + /// Asserts that the address is ip4 or ip6. + pub fn setPort(self: *Address, port: u16) void { const ptr = switch (self.any.family) { os.AF_INET => &self.in.port, os.AF_INET6 => &self.in6.port, @@ -237,16 +257,16 @@ pub const IpAddress = extern union { /// Asserts that `addr` is an IP address. /// This function will read past the end of the pointer, with a size depending /// on the address family. - pub fn initPosix(addr: *align(4) const os.sockaddr) IpAddress { + pub fn initPosix(addr: *align(4) const os.sockaddr) Address { switch (addr.family) { - os.AF_INET => return IpAddress{ .in = @ptrCast(*const os.sockaddr_in, addr).* }, - os.AF_INET6 => return IpAddress{ .in6 = @ptrCast(*const os.sockaddr_in6, addr).* }, + os.AF_INET => return Address{ .in = @ptrCast(*const os.sockaddr_in, addr).* }, + os.AF_INET6 => return Address{ .in6 = @ptrCast(*const os.sockaddr_in6, addr).* }, else => unreachable, } } pub fn format( - self: IpAddress, + self: Address, comptime fmt: []const u8, options: std.fmt.FormatOptions, context: var, @@ -271,7 +291,7 @@ pub const IpAddress = extern union { }, os.AF_INET6 => { const port = mem.bigToNative(u16, self.in6.port); - if (mem.eql(u8, self.in6.addr[0..12], [_]u8{0,0,0,0,0,0,0,0,0,0,0xff,0xff})) { + if (mem.eql(u8, self.in6.addr[0..12], [_]u8{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff })) { try std.fmt.format( context, Errors, @@ -314,20 +334,35 @@ pub const IpAddress = extern union { } try std.fmt.format(context, Errors, output, "]:{}", port); }, + os.AF_UNIX => { + if (!has_unix_sockets) { + unreachable; + } + + try std.fmt.format(context, Errors, output, "{}", self.un.path); + }, else => unreachable, } } - pub fn eql(a: IpAddress, b: IpAddress) bool { + pub fn eql(a: Address, b: Address) bool { const a_bytes = @ptrCast([*]const u8, &a.any)[0..a.getOsSockLen()]; const b_bytes = @ptrCast([*]const u8, &b.any)[0..b.getOsSockLen()]; return mem.eql(u8, a_bytes, b_bytes); } - fn getOsSockLen(self: IpAddress) os.socklen_t { + fn getOsSockLen(self: Address) os.socklen_t { switch (self.any.family) { os.AF_INET => return @sizeOf(os.sockaddr_in), os.AF_INET6 => return @sizeOf(os.sockaddr_in6), + os.AF_UNIX => { + if (!has_unix_sockets) { + unreachable; + } + + const path_len = std.mem.len(u8, &self.un.path); + return @intCast(os.socklen_t, @sizeOf(os.sockaddr_un) - self.un.path.len + path_len); + }, else => unreachable, } } @@ -342,23 +377,20 @@ pub fn connectUnixSocket(path: []const u8) !fs.File { ); errdefer os.close(sockfd); - var sock_addr = os.sockaddr_un{ - .family = os.AF_UNIX, - .path = undefined, - }; - - if (path.len > sock_addr.path.len) return error.NameTooLong; - mem.copy(u8, &sock_addr.path, path); + var addr = try std.net.Address.initUnix(path); - const size = @intCast(u32, @sizeOf(os.sockaddr_un) - sock_addr.path.len + path.len); - try os.connect(sockfd, &sock_addr, size); + try os.connect( + sockfd, + &addr.any, + addr.getOsSockLen(), + ); return fs.File.openHandle(sockfd); } pub const AddressList = struct { arena: std.heap.ArenaAllocator, - addrs: []IpAddress, + addrs: []Address, canon_name: ?[]u8, fn deinit(self: *AddressList) void { @@ -381,7 +413,7 @@ pub fn tcpConnectToHost(allocator: *mem.Allocator, name: []const u8, port: u16) return tcpConnectToAddress(addrs[0], port); } -pub fn tcpConnectToAddress(address: IpAddress) !fs.File { +pub fn tcpConnectToAddress(address: Address) !fs.File { const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0; const sock_flags = os.SOCK_STREAM | os.SOCK_CLOEXEC | nonblock; const sockfd = try os.socket(address.any.family, sock_flags, os.IPPROTO_TCP); @@ -456,13 +488,13 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !* } break :blk count; }; - result.addrs = try arena.alloc(IpAddress, addr_count); + result.addrs = try arena.alloc(Address, addr_count); var it: ?*os.addrinfo = res; var i: usize = 0; while (it) |info| : (it = info.next) { const addr = info.addr orelse continue; - result.addrs[i] = IpAddress.initPosix(@alignCast(4, addr)); + result.addrs[i] = Address.initPosix(@alignCast(4, addr)); if (info.canonname) |n| { if (result.canon_name == null) { @@ -485,7 +517,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !* try linuxLookupName(&lookup_addrs, &canon, name, family, flags, port); - result.addrs = try arena.alloc(IpAddress, lookup_addrs.len); + result.addrs = try arena.alloc(Address, lookup_addrs.len); if (!canon.isNull()) { result.canon_name = canon.toOwnedSlice(); } @@ -501,7 +533,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !* } const LookupAddr = struct { - addr: IpAddress, + addr: Address, sortkey: i32 = 0, }; @@ -524,7 +556,7 @@ fn linuxLookupName( if (opt_name) |name| { // reject empty name and check len so it fits into temp bufs try canon.replaceContents(name); - if (IpAddress.parseExpectingFamily(name, family, port)) |addr| { + if (Address.parseExpectingFamily(name, family, port)) |addr| { try addrs.append(LookupAddr{ .addr = addr }); } else |name_err| if ((flags & std.c.AI_NUMERICHOST) != 0) { return name_err; @@ -611,7 +643,7 @@ fn linuxLookupName( // TODO sa6.addr[12..16] should return *[4]u8, making this cast unnecessary. mem.writeIntNative(u32, @ptrCast(*[4]u8, &sa6.addr[12]), sa4.addr); } - if (dscope == i32(scopeOf(sa6.addr))) key |= DAS_MATCHINGSCOPE; + if (dscope == @as(i32, scopeOf(sa6.addr))) key |= DAS_MATCHINGSCOPE; if (dlabel == labelOf(sa6.addr)) key |= DAS_MATCHINGLABEL; prefixlen = prefixMatch(sa6.addr, da6.addr); } else |_| {} @@ -710,7 +742,7 @@ fn prefixMatch(s: [16]u8, d: [16]u8) u8 { // address. However the definition of the source prefix length is // not clear and thus this limiting is not yet implemented. var i: u8 = 0; - while (i < 128 and ((s[i / 8] ^ d[i / 8]) & (u8(128) >> @intCast(u3, i % 8))) == 0) : (i += 1) {} + while (i < 128 and ((s[i / 8] ^ d[i / 8]) & (@as(u8, 128) >> @intCast(u3, i % 8))) == 0) : (i += 1) {} return i; } @@ -751,23 +783,23 @@ fn linuxLookupNameFromNull( if ((flags & std.c.AI_PASSIVE) != 0) { if (family != os.AF_INET6) { (try addrs.addOne()).* = LookupAddr{ - .addr = IpAddress.initIp4([1]u8{0} ** 4, port), + .addr = Address.initIp4([1]u8{0} ** 4, port), }; } if (family != os.AF_INET) { (try addrs.addOne()).* = LookupAddr{ - .addr = IpAddress.initIp6([1]u8{0} ** 16, port, 0, 0), + .addr = Address.initIp6([1]u8{0} ** 16, port, 0, 0), }; } } else { if (family != os.AF_INET6) { (try addrs.addOne()).* = LookupAddr{ - .addr = IpAddress.initIp4([4]u8{ 127, 0, 0, 1 }, port), + .addr = Address.initIp4([4]u8{ 127, 0, 0, 1 }, port), }; } if (family != os.AF_INET) { (try addrs.addOne()).* = LookupAddr{ - .addr = IpAddress.initIp6(([1]u8{0} ** 15) ++ [1]u8{1}, port, 0, 0), + .addr = Address.initIp6(([1]u8{0} ** 15) ++ [1]u8{1}, port, 0, 0), }; } } @@ -812,7 +844,7 @@ fn linuxLookupNameFromHosts( } } else continue; - const addr = IpAddress.parseExpectingFamily(ip_text, family, port) catch |err| switch (err) { + const addr = Address.parseExpectingFamily(ip_text, family, port) catch |err| switch (err) { error.Overflow, error.InvalidEnd, error.InvalidCharacter, @@ -1033,7 +1065,7 @@ fn linuxLookupNameFromNumericUnspec( name: []const u8, port: u16, ) !void { - const addr = try IpAddress.parse(name, port); + const addr = try Address.parseIp(name, port); (try addrs.addOne()).* = LookupAddr{ .addr = addr }; } @@ -1049,7 +1081,7 @@ fn resMSendRc( var sl: os.socklen_t = @sizeOf(os.sockaddr_in); var family: os.sa_family_t = os.AF_INET; - var ns_list = std.ArrayList(IpAddress).init(rc.ns.allocator); + var ns_list = std.ArrayList(Address).init(rc.ns.allocator); defer ns_list.deinit(); try ns_list.resize(rc.ns.len); @@ -1065,8 +1097,8 @@ fn resMSendRc( } // Get local address and open/bind a socket - var sa: IpAddress = undefined; - @memset(@ptrCast([*]u8, &sa), 0, @sizeOf(IpAddress)); + var sa: Address = undefined; + @memset(@ptrCast([*]u8, &sa), 0, @sizeOf(Address)); sa.any.family = family; const flags = os.SOCK_DGRAM | os.SOCK_CLOEXEC | os.SOCK_NONBLOCK; const fd = os.socket(family, flags, 0) catch |err| switch (err) { @@ -1133,7 +1165,7 @@ fn resMSendRc( } // Wait for a response, or until time to retry - const clamped_timeout = std.math.min(u31(std.math.maxInt(u31)), t1 + retry_interval - t2); + const clamped_timeout = std.math.min(@as(u31, std.math.maxInt(u31)), t1 + retry_interval - t2); const nevents = os.poll(&pfd, clamped_timeout) catch 0; if (nevents == 0) continue; @@ -1194,23 +1226,23 @@ fn dnsParse( if (r.len < 12) return error.InvalidDnsPacket; if ((r[3] & 15) != 0) return; var p = r.ptr + 12; - var qdcount = r[4] * usize(256) + r[5]; - var ancount = r[6] * usize(256) + r[7]; + var qdcount = r[4] * @as(usize, 256) + r[5]; + var ancount = r[6] * @as(usize, 256) + r[7]; if (qdcount + ancount > 64) return error.InvalidDnsPacket; while (qdcount != 0) { qdcount -= 1; while (@ptrToInt(p) - @ptrToInt(r.ptr) < r.len and p[0] -% 1 < 127) p += 1; if (p[0] > 193 or (p[0] == 193 and p[1] > 254) or @ptrToInt(p) > @ptrToInt(r.ptr) + r.len - 6) return error.InvalidDnsPacket; - p += usize(5) + @boolToInt(p[0] != 0); + p += @as(usize, 5) + @boolToInt(p[0] != 0); } while (ancount != 0) { ancount -= 1; while (@ptrToInt(p) - @ptrToInt(r.ptr) < r.len and p[0] -% 1 < 127) p += 1; if (p[0] > 193 or (p[0] == 193 and p[1] > 254) or @ptrToInt(p) > @ptrToInt(r.ptr) + r.len - 6) return error.InvalidDnsPacket; - p += usize(1) + @boolToInt(p[0] != 0); - const len = p[8] * usize(256) + p[9]; + p += @as(usize, 1) + @boolToInt(p[0] != 0); + const len = p[8] * @as(usize, 256) + p[9]; if (@ptrToInt(p) + len > @ptrToInt(r.ptr) + r.len) return error.InvalidDnsPacket; try callback(ctx, p[1], p[10 .. 10 + len], r); p += 10 + len; @@ -1224,7 +1256,7 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8) const new_addr = try ctx.addrs.addOne(); new_addr.* = LookupAddr{ // TODO slice [0..4] to make this *[4]u8 without @ptrCast - .addr = IpAddress.initIp4(@ptrCast(*const [4]u8, data.ptr).*, ctx.port), + .addr = Address.initIp4(@ptrCast(*const [4]u8, data.ptr).*, ctx.port), }; }, os.RR_AAAA => { @@ -1232,7 +1264,7 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8) const new_addr = try ctx.addrs.addOne(); new_addr.* = LookupAddr{ // TODO slice [0..16] to make this *[16]u8 without @ptrCast - .addr = IpAddress.initIp6(@ptrCast(*const [16]u8, data.ptr).*, ctx.port, 0, 0), + .addr = Address.initIp6(@ptrCast(*const [16]u8, data.ptr).*, ctx.port, 0, 0), }; }, os.RR_CNAME => { @@ -1248,12 +1280,12 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8) } } -pub const TcpServer = struct { +pub const StreamServer = struct { /// Copied from `Options` on `init`. kernel_backlog: u32, /// `undefined` until `listen` returns successfully. - listen_address: IpAddress, + listen_address: Address, sockfd: ?os.fd_t, @@ -1266,24 +1298,26 @@ pub const TcpServer = struct { /// After this call succeeds, resources have been acquired and must /// be released with `deinit`. - pub fn init(options: Options) TcpServer { - return TcpServer{ + pub fn init(options: Options) StreamServer { + return StreamServer{ .sockfd = null, .kernel_backlog = options.kernel_backlog, .listen_address = undefined, }; } - /// Release all resources. The `TcpServer` memory becomes `undefined`. - pub fn deinit(self: *TcpServer) void { + /// Release all resources. The `StreamServer` memory becomes `undefined`. + pub fn deinit(self: *StreamServer) void { self.close(); self.* = undefined; } - pub fn listen(self: *TcpServer, address: IpAddress) !void { + pub fn listen(self: *StreamServer, address: Address) !void { const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0; const sock_flags = os.SOCK_STREAM | os.SOCK_CLOEXEC | nonblock; - const sockfd = try os.socket(os.AF_INET, sock_flags, os.IPPROTO_TCP); + const proto = if (address.any.family == os.AF_UNIX) @as(u32, 0) else os.IPPROTO_TCP; + + const sockfd = try os.socket(address.any.family, sock_flags, proto); self.sockfd = sockfd; errdefer { os.close(sockfd); @@ -1299,7 +1333,7 @@ pub const TcpServer = struct { /// Stop listening. It is still necessary to call `deinit` after stopping listening. /// Calling `deinit` will automatically call `close`. It is safe to call `close` when /// not listening. - pub fn close(self: *TcpServer) void { + pub fn close(self: *StreamServer) void { if (self.sockfd) |fd| { os.close(fd); self.sockfd = null; @@ -1326,14 +1360,22 @@ pub const TcpServer = struct { BlockedByFirewall, } || os.UnexpectedError; - /// If this function succeeds, the returned `fs.File` is a caller-managed resource. - pub fn accept(self: *TcpServer) AcceptError!fs.File { + pub const Connection = struct { + file: fs.File, + address: Address + }; + + /// If this function succeeds, the returned `Connection` is a caller-managed resource. + pub fn accept(self: *StreamServer) AcceptError!Connection { const nonblock = if (std.io.is_async) os.SOCK_NONBLOCK else 0; const accept_flags = nonblock | os.SOCK_CLOEXEC; - var accepted_addr: IpAddress = undefined; - var adr_len: os.socklen_t = @sizeOf(IpAddress); + var accepted_addr: Address = undefined; + var adr_len: os.socklen_t = @sizeOf(Address); if (os.accept4(self.sockfd.?, &accepted_addr.any, &adr_len, accept_flags)) |fd| { - return fs.File.openHandle(fd); + return Connection{ + .file = fs.File.openHandle(fd), + .address = accepted_addr, + }; } else |err| switch (err) { // We only give SOCK_NONBLOCK when I/O mode is async, in which case this error // is handled by os.accept4. diff --git a/lib/std/net/test.zig b/lib/std/net/test.zig @@ -28,17 +28,17 @@ test "parse and render IPv6 addresses" { "::ffff:123.5.123.5", }; for (ips) |ip, i| { - var addr = net.IpAddress.parseIp6(ip, 0) catch unreachable; + var addr = net.Address.parseIp6(ip, 0) catch unreachable; var newIp = std.fmt.bufPrint(buffer[0..], "{}", addr) catch unreachable; std.testing.expect(std.mem.eql(u8, printed[i], newIp[1 .. newIp.len - 3])); } - testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp6(":::", 0)); - testing.expectError(error.Overflow, net.IpAddress.parseIp6("FF001::FB", 0)); - testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp6("FF01::Fb:zig", 0)); - testing.expectError(error.InvalidEnd, net.IpAddress.parseIp6("FF01:0:0:0:0:0:0:FB:", 0)); - testing.expectError(error.Incomplete, net.IpAddress.parseIp6("FF01:", 0)); - testing.expectError(error.InvalidIpv4Mapping, net.IpAddress.parseIp6("::123.123.123.123", 0)); + testing.expectError(error.InvalidCharacter, net.Address.parseIp6(":::", 0)); + testing.expectError(error.Overflow, net.Address.parseIp6("FF001::FB", 0)); + testing.expectError(error.InvalidCharacter, net.Address.parseIp6("FF01::Fb:zig", 0)); + testing.expectError(error.InvalidEnd, net.Address.parseIp6("FF01:0:0:0:0:0:0:FB:", 0)); + testing.expectError(error.Incomplete, net.Address.parseIp6("FF01:", 0)); + testing.expectError(error.InvalidIpv4Mapping, net.Address.parseIp6("::123.123.123.123", 0)); } test "parse and render IPv4 addresses" { @@ -50,16 +50,16 @@ test "parse and render IPv4 addresses" { "123.255.0.91", "127.0.0.1", }) |ip| { - var addr = net.IpAddress.parseIp4(ip, 0) catch unreachable; + var addr = net.Address.parseIp4(ip, 0) catch unreachable; var newIp = std.fmt.bufPrint(buffer[0..], "{}", addr) catch unreachable; std.testing.expect(std.mem.eql(u8, ip, newIp[0 .. newIp.len - 2])); } - testing.expectError(error.Overflow, net.IpAddress.parseIp4("256.0.0.1", 0)); - testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp4("x.0.0.1", 0)); - testing.expectError(error.InvalidEnd, net.IpAddress.parseIp4("127.0.0.1.1", 0)); - testing.expectError(error.Incomplete, net.IpAddress.parseIp4("127.0.0.", 0)); - testing.expectError(error.InvalidCharacter, net.IpAddress.parseIp4("100..0.1", 0)); + testing.expectError(error.Overflow, net.Address.parseIp4("256.0.0.1", 0)); + testing.expectError(error.InvalidCharacter, net.Address.parseIp4("x.0.0.1", 0)); + testing.expectError(error.InvalidEnd, net.Address.parseIp4("127.0.0.1.1", 0)); + testing.expectError(error.Incomplete, net.Address.parseIp4("127.0.0.", 0)); + testing.expectError(error.InvalidCharacter, net.Address.parseIp4("100..0.1", 0)); } test "resolve DNS" { @@ -91,9 +91,9 @@ test "listen on a port, send bytes, receive bytes" { } // TODO doing this at comptime crashed the compiler - const localhost = net.IpAddress.parse("127.0.0.1", 0); + const localhost = net.Address.parseIp("127.0.0.1", 0); - var server = net.TcpServer.init(net.TcpServer.Options{}); + var server = net.StreamServer.init(net.StreamServer.Options{}); defer server.deinit(); try server.listen(localhost); @@ -104,7 +104,7 @@ test "listen on a port, send bytes, receive bytes" { try await client_frame; } -fn testClient(addr: net.IpAddress) anyerror!void { +fn testClient(addr: net.Address) anyerror!void { const socket_file = try net.tcpConnectToAddress(addr); defer socket_file.close(); @@ -114,9 +114,9 @@ fn testClient(addr: net.IpAddress) anyerror!void { testing.expect(mem.eql(u8, msg, "hello from server\n")); } -fn testServer(server: *net.TcpServer) anyerror!void { - var client_file = try server.accept(); +fn testServer(server: *net.StreamServer) anyerror!void { + var client = try server.accept(); - const stream = &client_file.outStream().stream; + const stream = &client.file.outStream().stream; try stream.print("hello from server\n"); } diff --git a/lib/std/os.zig b/lib/std/os.zig @@ -472,7 +472,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!void { var index: usize = 0; while (index < bytes.len) { - const amt_to_write = math.min(bytes.len - index, usize(max_bytes_len)); + const amt_to_write = math.min(bytes.len - index, @as(usize, max_bytes_len)); const rc = system.write(fd, bytes.ptr + index, amt_to_write); switch (errno(rc)) { 0 => { @@ -1126,9 +1126,9 @@ pub fn unlinkatW(dirfd: fd_t, sub_path_w: [*]const u16, flags: u32) UnlinkatErro const want_rmdir_behavior = (flags & AT_REMOVEDIR) != 0; const create_options_flags = if (want_rmdir_behavior) - w.ULONG(w.FILE_DELETE_ON_CLOSE) + @as(w.ULONG, w.FILE_DELETE_ON_CLOSE) else - w.ULONG(w.FILE_DELETE_ON_CLOSE | w.FILE_NON_DIRECTORY_FILE); + @as(w.ULONG, w.FILE_DELETE_ON_CLOSE | w.FILE_NON_DIRECTORY_FILE); const path_len_bytes = @intCast(u16, mem.toSliceConst(u16, sub_path_w).len * 2); var nt_name = w.UNICODE_STRING{ @@ -1526,7 +1526,7 @@ pub fn isatty(handle: fd_t) bool { } if (builtin.os == .linux) { var wsz: linux.winsize = undefined; - return linux.syscall3(linux.SYS_ioctl, @bitCast(usize, isize(handle)), linux.TIOCGWINSZ, @ptrToInt(&wsz)) == 0; + return linux.syscall3(linux.SYS_ioctl, @bitCast(usize, @as(isize, handle)), linux.TIOCGWINSZ, @ptrToInt(&wsz)) == 0; } unreachable; } @@ -1547,7 +1547,7 @@ pub fn isCygwinPty(handle: fd_t) bool { } const name_info = @ptrCast(*const windows.FILE_NAME_INFO, &name_info_bytes[0]); - const name_bytes = name_info_bytes[size .. size + usize(name_info.FileNameLength)]; + const name_bytes = name_info_bytes[size .. size + @as(usize, name_info.FileNameLength)]; const name_wide = @bytesToSlice(u16, name_bytes); return mem.indexOf(u16, name_wide, [_]u16{ 'm', 's', 'y', 's', '-' }) != null or mem.indexOf(u16, name_wide, [_]u16{ '-', 'p', 't', 'y' }) != null; @@ -2897,7 +2897,7 @@ pub fn res_mkquery( // Construct query template - ID will be filled later var q: [280]u8 = undefined; @memset(&q, 0, n); - q[2] = u8(op) * 8 + 1; + q[2] = @as(u8, op) * 8 + 1; q[5] = 1; mem.copy(u8, q[13..], name); var i: usize = 13; @@ -3143,7 +3143,7 @@ pub fn dn_expand( // loop invariants: p<end, dest<dend if ((p[0] & 0xc0) != 0) { if (p + 1 == end) return error.InvalidDnsPacket; - var j = ((p[0] & usize(0x3f)) << 8) | p[1]; + var j = ((p[0] & @as(usize, 0x3f)) << 8) | p[1]; if (len == std.math.maxInt(usize)) len = @ptrToInt(p) + 2 - @ptrToInt(comp_dn.ptr); if (j >= msg.len) return error.InvalidDnsPacket; p = msg.ptr + j; @@ -3171,3 +3171,22 @@ pub fn dn_expand( } return error.InvalidDnsPacket; } + +pub const SchedYieldError = error{ + /// The system is not configured to allow yielding + SystemCannotYield, +}; + +pub fn sched_yield() SchedYieldError!void { + if (builtin.os == .windows) { + // The return value has to do with how many other threads there are; it is not + // an error condition on Windows. + _ = windows.kernel32.SwitchToThread(); + return; + } + switch (errno(system.sched_yield())) { + 0 => return, + ENOSYS => return error.SystemCannotYield, + else => return error.SystemCannotYield, + } +} diff --git a/lib/std/os/bits.zig b/lib/std/os/bits.zig @@ -14,9 +14,6 @@ pub usingnamespace switch (builtin.os) { else => struct {}, }; -pub const pthread_t = *@OpaqueType(); -pub const FILE = @OpaqueType(); - pub const iovec = extern struct { iov_base: [*]u8, iov_len: usize, diff --git a/lib/std/os/bits/darwin.zig b/lib/std/os/bits/darwin.zig @@ -133,11 +133,6 @@ pub const dirent = extern struct { } }; -pub const pthread_attr_t = extern struct { - __sig: c_long, - __opaque: [56]u8, -}; - /// Renamed from `kevent` to `Kevent` to avoid conflict with function name. pub const Kevent = extern struct { ident: usize, @@ -272,7 +267,6 @@ pub const SA_USERTRAMP = 0x0100; /// signal handler with SA_SIGINFO args with 64bit regs information pub const SA_64REGSET = 0x0200; -pub const O_LARGEFILE = 0x0000; pub const O_PATH = 0x0000; pub const F_OK = 0; diff --git a/lib/std/os/bits/dragonfly.zig b/lib/std/os/bits/dragonfly.zig @@ -241,7 +241,6 @@ pub const KERN_MAXID = 37; pub const HOST_NAME_MAX = 255; -pub const O_LARGEFILE = 0; // faked support pub const O_RDONLY = 0; pub const O_NDELAY = O_NONBLOCK; pub const O_WRONLY = 1; @@ -315,7 +314,7 @@ pub const dirent = extern struct { d_name: [256]u8, pub fn reclen(self: dirent) u16 { - return (@byteOffsetOf(dirent, "d_name") + self.d_namlen + 1 + 7) & ~u16(7); + return (@byteOffsetOf(dirent, "d_name") + self.d_namlen + 1 + 7) & ~@as(u16, 7); } }; @@ -360,11 +359,6 @@ pub const Kevent = extern struct { udata: usize, }; -pub const pthread_attr_t = extern struct { // copied from freebsd - __size: [56]u8, - __align: c_long, -}; - pub const EVFILT_FS = -10; pub const EVFILT_USER = -9; pub const EVFILT_EXCEPT = -8; @@ -515,13 +509,13 @@ pub const sigset_t = extern struct { pub const sig_atomic_t = c_int; pub const Sigaction = extern struct { __sigaction_u: extern union { - __sa_handler: ?extern fn(c_int) void, - __sa_sigaction: ?extern fn(c_int, [*c]siginfo_t, ?*c_void) void, + __sa_handler: ?extern fn (c_int) void, + __sa_sigaction: ?extern fn (c_int, [*c]siginfo_t, ?*c_void) void, }, sa_flags: c_int, sa_mask: sigset_t, }; -pub const sig_t = [*c]extern fn(c_int) void; +pub const sig_t = [*c]extern fn (c_int) void; pub const sigvec = extern struct { sv_handler: [*c]__sighandler_t, diff --git a/lib/std/os/bits/freebsd.zig b/lib/std/os/bits/freebsd.zig @@ -15,11 +15,6 @@ pub const Kevent = extern struct { // TODO ext }; -pub const pthread_attr_t = extern struct { - __size: [56]u8, - __align: c_long, -}; - pub const dl_phdr_info = extern struct { dlpi_addr: usize, dlpi_name: ?[*]const u8, @@ -305,7 +300,6 @@ pub const O_CLOEXEC = 0x00100000; pub const O_ASYNC = 0x0040; pub const O_DIRECT = 0x00010000; -pub const O_LARGEFILE = 0; pub const O_NOATIME = 0o1000000; pub const O_PATH = 0o10000000; pub const O_TMPFILE = 0o20200000; diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig @@ -559,10 +559,10 @@ pub const EPOLLMSG = 0x400; pub const EPOLLERR = 0x008; pub const EPOLLHUP = 0x010; pub const EPOLLRDHUP = 0x2000; -pub const EPOLLEXCLUSIVE = (u32(1) << 28); -pub const EPOLLWAKEUP = (u32(1) << 29); -pub const EPOLLONESHOT = (u32(1) << 30); -pub const EPOLLET = (u32(1) << 31); +pub const EPOLLEXCLUSIVE = (@as(u32, 1) << 28); +pub const EPOLLWAKEUP = (@as(u32, 1) << 29); +pub const EPOLLONESHOT = (@as(u32, 1) << 30); +pub const EPOLLET = (@as(u32, 1) << 31); pub const CLOCK_REALTIME = 0; pub const CLOCK_MONOTONIC = 1; @@ -950,7 +950,7 @@ pub fn cap_valid(u8: x) bool { } pub fn CAP_TO_MASK(cap: u8) u32 { - return u32(1) << u5(cap & 31); + return @as(u32, 1) << u5(cap & 31); } pub fn CAP_TO_INDEX(cap: u8) u8 { @@ -1000,11 +1000,6 @@ pub const dl_phdr_info = extern struct { dlpi_phnum: u16, }; -pub const pthread_attr_t = extern struct { - __size: [56]u8, - __align: c_long, -}; - pub const CPU_SETSIZE = 128; pub const cpu_set_t = [CPU_SETSIZE / @sizeOf(usize)]usize; pub const cpu_count_t = @IntType(false, std.math.log2(CPU_SETSIZE * 8)); diff --git a/lib/std/os/bits/netbsd.zig b/lib/std/os/bits/netbsd.zig @@ -14,12 +14,6 @@ pub const Kevent = extern struct { udata: usize, }; -pub const pthread_attr_t = extern struct { - pta_magic: u32, - pta_flags: c_int, - pta_private: *c_void, -}; - pub const dl_phdr_info = extern struct { dlpi_addr: usize, dlpi_name: ?[*]const u8, @@ -298,7 +292,6 @@ pub const O_CLOEXEC = 0x00400000; pub const O_ASYNC = 0x0040; pub const O_DIRECT = 0x00080000; -pub const O_LARGEFILE = 0; pub const O_NOATIME = 0; pub const O_PATH = 0; pub const O_TMPFILE = 0; diff --git a/lib/std/os/bits/windows.zig b/lib/std/os/bits/windows.zig @@ -186,6 +186,11 @@ pub const sockaddr_in6 = extern struct { pub const in6_addr = [16]u8; pub const in_addr = u32; +pub const sockaddr_un = extern struct { + family: sa_family_t = AF_UNIX, + path: [108]u8, +}; + pub const AF_UNSPEC = 0; pub const AF_UNIX = 1; pub const AF_INET = 2; @@ -221,3 +226,17 @@ pub const AF_TCNMESSAGE = 30; pub const AF_ICLFXBM = 31; pub const AF_BTH = 32; pub const AF_MAX = 33; + +pub const SOCK_STREAM = 1; +pub const SOCK_DGRAM = 2; +pub const SOCK_RAW = 3; +pub const SOCK_RDM = 4; +pub const SOCK_SEQPACKET = 5; + +pub const IPPROTO_ICMP = 1; +pub const IPPROTO_IGMP = 2; +pub const BTHPROTO_RFCOMM = 3; +pub const IPPROTO_TCP = 6; +pub const IPPROTO_UDP = 17; +pub const IPPROTO_ICMPV6 = 58; +pub const IPPROTO_RM = 113; diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig @@ -46,22 +46,22 @@ pub fn getErrno(r: usize) u12 { pub fn dup2(old: i32, new: i32) usize { if (@hasDecl(@This(), "SYS_dup2")) { - return syscall2(SYS_dup2, @bitCast(usize, isize(old)), @bitCast(usize, isize(new))); + return syscall2(SYS_dup2, @bitCast(usize, @as(isize, old)), @bitCast(usize, @as(isize, new))); } else { if (old == new) { if (std.debug.runtime_safety) { - const rc = syscall2(SYS_fcntl, @bitCast(usize, isize(old)), F_GETFD); + const rc = syscall2(SYS_fcntl, @bitCast(usize, @as(isize, old)), F_GETFD); if (@bitCast(isize, rc) < 0) return rc; } return @intCast(usize, old); } else { - return syscall3(SYS_dup3, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)), 0); + return syscall3(SYS_dup3, @bitCast(usize, @as(isize, old)), @bitCast(usize, @as(isize, new)), 0); } } } pub fn dup3(old: i32, new: i32, flags: u32) usize { - return syscall3(SYS_dup3, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)), flags); + return syscall3(SYS_dup3, @bitCast(usize, @as(isize, old)), @bitCast(usize, @as(isize, new)), flags); } // TODO https://github.com/ziglang/zig/issues/265 @@ -102,7 +102,7 @@ pub fn futimens(fd: i32, times: *const [2]timespec) usize { // TODO https://github.com/ziglang/zig/issues/265 pub fn utimensat(dirfd: i32, path: ?[*]const u8, times: *const [2]timespec, flags: u32) usize { - return syscall4(SYS_utimensat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(times), flags); + return syscall4(SYS_utimensat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), @ptrToInt(times), flags); } pub fn futex_wait(uaddr: *const i32, futex_op: u32, val: i32, timeout: ?*timespec) usize { @@ -120,7 +120,7 @@ pub fn getcwd(buf: [*]u8, size: usize) usize { pub fn getdents(fd: i32, dirp: [*]u8, len: usize) usize { return syscall3( SYS_getdents, - @bitCast(usize, isize(fd)), + @bitCast(usize, @as(isize, fd)), @ptrToInt(dirp), std.math.min(len, maxInt(c_int)), ); @@ -129,7 +129,7 @@ pub fn getdents(fd: i32, dirp: [*]u8, len: usize) usize { pub fn getdents64(fd: i32, dirp: [*]u8, len: usize) usize { return syscall3( SYS_getdents64, - @bitCast(usize, isize(fd)), + @bitCast(usize, @as(isize, fd)), @ptrToInt(dirp), std.math.min(len, maxInt(c_int)), ); @@ -140,11 +140,11 @@ pub fn inotify_init1(flags: u32) usize { } pub fn inotify_add_watch(fd: i32, pathname: [*]const u8, mask: u32) usize { - return syscall3(SYS_inotify_add_watch, @bitCast(usize, isize(fd)), @ptrToInt(pathname), mask); + return syscall3(SYS_inotify_add_watch, @bitCast(usize, @as(isize, fd)), @ptrToInt(pathname), mask); } pub fn inotify_rm_watch(fd: i32, wd: i32) usize { - return syscall2(SYS_inotify_rm_watch, @bitCast(usize, isize(fd)), @bitCast(usize, isize(wd))); + return syscall2(SYS_inotify_rm_watch, @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, wd))); } // TODO https://github.com/ziglang/zig/issues/265 @@ -152,13 +152,13 @@ pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usiz if (@hasDecl(@This(), "SYS_readlink")) { return syscall3(SYS_readlink, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len); } else { - return syscall4(SYS_readlinkat, @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len); + return syscall4(SYS_readlinkat, @bitCast(usize, @as(isize, AT_FDCWD)), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len); } } // TODO https://github.com/ziglang/zig/issues/265 pub fn readlinkat(dirfd: i32, noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize { - return syscall4(SYS_readlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len); + return syscall4(SYS_readlinkat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len); } // TODO https://github.com/ziglang/zig/issues/265 @@ -166,13 +166,13 @@ pub fn mkdir(path: [*]const u8, mode: u32) usize { if (@hasDecl(@This(), "SYS_mkdir")) { return syscall2(SYS_mkdir, @ptrToInt(path), mode); } else { - return syscall3(SYS_mkdirat, @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(path), mode); + return syscall3(SYS_mkdirat, @bitCast(usize, @as(isize, AT_FDCWD)), @ptrToInt(path), mode); } } // TODO https://github.com/ziglang/zig/issues/265 pub fn mkdirat(dirfd: i32, path: [*]const u8, mode: u32) usize { - return syscall3(SYS_mkdirat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode); + return syscall3(SYS_mkdirat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), mode); } // TODO https://github.com/ziglang/zig/issues/265 @@ -194,7 +194,7 @@ pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, of if (@hasDecl(@This(), "SYS_mmap2")) { // Make sure the offset is also specified in multiples of page size if ((offset & (MMAP2_UNIT - 1)) != 0) - return @bitCast(usize, isize(-EINVAL)); + return @bitCast(usize, @as(isize, -EINVAL)); return syscall6( SYS_mmap2, @@ -202,7 +202,7 @@ pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, of length, prot, flags, - @bitCast(usize, isize(fd)), + @bitCast(usize, @as(isize, fd)), @truncate(usize, offset / MMAP2_UNIT), ); } else { @@ -212,7 +212,7 @@ pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, of length, prot, flags, - @bitCast(usize, isize(fd)), + @bitCast(usize, @as(isize, fd)), offset, ); } @@ -249,13 +249,13 @@ pub fn poll(fds: [*]pollfd, n: nfds_t, timeout: i32) usize { } pub fn read(fd: i32, buf: [*]u8, count: usize) usize { - return syscall3(SYS_read, @bitCast(usize, isize(fd)), @ptrToInt(buf), count); + return syscall3(SYS_read, @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), count); } pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize { return syscall5( SYS_preadv, - @bitCast(usize, isize(fd)), + @bitCast(usize, @as(isize, fd)), @ptrToInt(iov), count, @truncate(usize, offset), @@ -266,7 +266,7 @@ pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize { pub fn preadv2(fd: i32, iov: [*]const iovec, count: usize, offset: u64, flags: kernel_rwf) usize { return syscall6( SYS_preadv2, - @bitCast(usize, isize(fd)), + @bitCast(usize, @as(isize, fd)), @ptrToInt(iov), count, @truncate(usize, offset), @@ -276,17 +276,17 @@ pub fn preadv2(fd: i32, iov: [*]const iovec, count: usize, offset: u64, flags: k } pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize { - return syscall3(SYS_readv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count); + return syscall3(SYS_readv, @bitCast(usize, @as(isize, fd)), @ptrToInt(iov), count); } pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize { - return syscall3(SYS_writev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count); + return syscall3(SYS_writev, @bitCast(usize, @as(isize, fd)), @ptrToInt(iov), count); } pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) usize { return syscall5( SYS_pwritev, - @bitCast(usize, isize(fd)), + @bitCast(usize, @as(isize, fd)), @ptrToInt(iov), count, @truncate(usize, offset), @@ -297,7 +297,7 @@ pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) us pub fn pwritev2(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64, flags: kernel_rwf) usize { return syscall6( SYS_pwritev2, - @bitCast(usize, isize(fd)), + @bitCast(usize, @as(isize, fd)), @ptrToInt(iov), count, @truncate(usize, offset), @@ -311,7 +311,7 @@ pub fn rmdir(path: [*]const u8) usize { if (@hasDecl(@This(), "SYS_rmdir")) { return syscall1(SYS_rmdir, @ptrToInt(path)); } else { - return syscall3(SYS_unlinkat, @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(path), AT_REMOVEDIR); + return syscall3(SYS_unlinkat, @bitCast(usize, @as(isize, AT_FDCWD)), @ptrToInt(path), AT_REMOVEDIR); } } @@ -320,18 +320,18 @@ pub fn symlink(existing: [*]const u8, new: [*]const u8) usize { if (@hasDecl(@This(), "SYS_symlink")) { return syscall2(SYS_symlink, @ptrToInt(existing), @ptrToInt(new)); } else { - return syscall3(SYS_symlinkat, @ptrToInt(existing), @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(new)); + return syscall3(SYS_symlinkat, @ptrToInt(existing), @bitCast(usize, @as(isize, AT_FDCWD)), @ptrToInt(new)); } } // TODO https://github.com/ziglang/zig/issues/265 pub fn symlinkat(existing: [*]const u8, newfd: i32, newpath: [*]const u8) usize { - return syscall3(SYS_symlinkat, @ptrToInt(existing), @bitCast(usize, isize(newfd)), @ptrToInt(newpath)); + return syscall3(SYS_symlinkat, @ptrToInt(existing), @bitCast(usize, @as(isize, newfd)), @ptrToInt(newpath)); } // TODO https://github.com/ziglang/zig/issues/265 pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize { - return syscall4(SYS_pread, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset); + return syscall4(SYS_pread, @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), count, offset); } // TODO https://github.com/ziglang/zig/issues/265 @@ -339,13 +339,13 @@ pub fn access(path: [*]const u8, mode: u32) usize { if (@hasDecl(@This(), "SYS_access")) { return syscall2(SYS_access, @ptrToInt(path), mode); } else { - return syscall4(SYS_faccessat, @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(path), mode, 0); + return syscall4(SYS_faccessat, @bitCast(usize, @as(isize, AT_FDCWD)), @ptrToInt(path), mode, 0); } } // TODO https://github.com/ziglang/zig/issues/265 pub fn faccessat(dirfd: i32, path: [*]const u8, mode: u32, flags: u32) usize { - return syscall4(SYS_faccessat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode, flags); + return syscall4(SYS_faccessat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), mode, flags); } pub fn pipe(fd: *[2]i32) usize { @@ -363,11 +363,11 @@ pub fn pipe2(fd: *[2]i32, flags: u32) usize { } pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { - return syscall3(SYS_write, @bitCast(usize, isize(fd)), @ptrToInt(buf), count); + return syscall3(SYS_write, @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), count); } pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize { - return syscall4(SYS_pwrite, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset); + return syscall4(SYS_pwrite, @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), count, offset); } // TODO https://github.com/ziglang/zig/issues/265 @@ -375,9 +375,9 @@ pub fn rename(old: [*]const u8, new: [*]const u8) usize { if (@hasDecl(@This(), "SYS_rename")) { return syscall2(SYS_rename, @ptrToInt(old), @ptrToInt(new)); } else if (@hasDecl(@This(), "SYS_renameat")) { - return syscall4(SYS_renameat, @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(old), @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(new)); + return syscall4(SYS_renameat, @bitCast(usize, @as(isize, AT_FDCWD)), @ptrToInt(old), @bitCast(usize, @as(isize, AT_FDCWD)), @ptrToInt(new)); } else { - return syscall5(SYS_renameat2, @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(old), @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(new), 0); + return syscall5(SYS_renameat2, @bitCast(usize, @as(isize, AT_FDCWD)), @ptrToInt(old), @bitCast(usize, @as(isize, AT_FDCWD)), @ptrToInt(new), 0); } } @@ -385,17 +385,17 @@ pub fn renameat(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const if (@hasDecl(@This(), "SYS_renameat")) { return syscall4( SYS_renameat, - @bitCast(usize, isize(oldfd)), + @bitCast(usize, @as(isize, oldfd)), @ptrToInt(old), - @bitCast(usize, isize(newfd)), + @bitCast(usize, @as(isize, newfd)), @ptrToInt(new), ); } else { return syscall5( SYS_renameat2, - @bitCast(usize, isize(oldfd)), + @bitCast(usize, @as(isize, oldfd)), @ptrToInt(old), - @bitCast(usize, isize(newfd)), + @bitCast(usize, @as(isize, newfd)), @ptrToInt(new), 0, ); @@ -406,9 +406,9 @@ pub fn renameat(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const pub fn renameat2(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const u8, flags: u32) usize { return syscall5( SYS_renameat2, - @bitCast(usize, isize(oldfd)), + @bitCast(usize, @as(isize, oldfd)), @ptrToInt(oldpath), - @bitCast(usize, isize(newfd)), + @bitCast(usize, @as(isize, newfd)), @ptrToInt(newpath), flags, ); @@ -421,7 +421,7 @@ pub fn open(path: [*]const u8, flags: u32, perm: usize) usize { } else { return syscall4( SYS_openat, - @bitCast(usize, isize(AT_FDCWD)), + @bitCast(usize, @as(isize, AT_FDCWD)), @ptrToInt(path), flags, perm, @@ -437,7 +437,7 @@ pub fn create(path: [*]const u8, perm: usize) usize { // TODO https://github.com/ziglang/zig/issues/265 pub fn openat(dirfd: i32, path: [*]const u8, flags: u32, mode: usize) usize { // dirfd could be negative, for example AT_FDCWD is -100 - return syscall4(SYS_openat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags, mode); + return syscall4(SYS_openat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), flags, mode); } /// See also `clone` (from the arch-specific include) @@ -451,14 +451,14 @@ pub fn clone2(flags: u32, child_stack_ptr: usize) usize { } pub fn close(fd: i32) usize { - return syscall1(SYS_close, @bitCast(usize, isize(fd))); + return syscall1(SYS_close, @bitCast(usize, @as(isize, fd))); } /// Can only be called on 32 bit systems. For 64 bit see `lseek`. pub fn llseek(fd: i32, offset: u64, result: ?*u64, whence: usize) usize { return syscall5( SYS__llseek, - @bitCast(usize, isize(fd)), + @bitCast(usize, @as(isize, fd)), @truncate(usize, offset >> 32), @truncate(usize, offset), @ptrToInt(result), @@ -468,16 +468,16 @@ pub fn llseek(fd: i32, offset: u64, result: ?*u64, whence: usize) usize { /// Can only be called on 64 bit systems. For 32 bit see `llseek`. pub fn lseek(fd: i32, offset: i64, whence: usize) usize { - return syscall3(SYS_lseek, @bitCast(usize, isize(fd)), @bitCast(usize, offset), whence); + return syscall3(SYS_lseek, @bitCast(usize, @as(isize, fd)), @bitCast(usize, offset), whence); } pub fn exit(status: i32) noreturn { - _ = syscall1(SYS_exit, @bitCast(usize, isize(status))); + _ = syscall1(SYS_exit, @bitCast(usize, @as(isize, status))); unreachable; } pub fn exit_group(status: i32) noreturn { - _ = syscall1(SYS_exit_group, @bitCast(usize, isize(status))); + _ = syscall1(SYS_exit_group, @bitCast(usize, @as(isize, status))); unreachable; } @@ -486,7 +486,7 @@ pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize { } pub fn kill(pid: i32, sig: i32) usize { - return syscall2(SYS_kill, @bitCast(usize, isize(pid)), @bitCast(usize, isize(sig))); + return syscall2(SYS_kill, @bitCast(usize, @as(isize, pid)), @bitCast(usize, @as(isize, sig))); } // TODO https://github.com/ziglang/zig/issues/265 @@ -494,17 +494,17 @@ pub fn unlink(path: [*]const u8) usize { if (@hasDecl(@This(), "SYS_unlink")) { return syscall1(SYS_unlink, @ptrToInt(path)); } else { - return syscall3(SYS_unlinkat, @bitCast(usize, isize(AT_FDCWD)), @ptrToInt(path), 0); + return syscall3(SYS_unlinkat, @bitCast(usize, @as(isize, AT_FDCWD)), @ptrToInt(path), 0); } } // TODO https://github.com/ziglang/zig/issues/265 pub fn unlinkat(dirfd: i32, path: [*]const u8, flags: u32) usize { - return syscall3(SYS_unlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags); + return syscall3(SYS_unlinkat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), flags); } pub fn waitpid(pid: i32, status: *u32, flags: u32) usize { - return syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), flags, 0); + return syscall4(SYS_wait4, @bitCast(usize, @as(isize, pid)), @ptrToInt(status), flags, 0); } var vdso_clock_gettime = @ptrCast(?*const c_void, init_vdso_clock_gettime); @@ -519,33 +519,33 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) usize { const f = @ptrCast(vdso_clock_gettime_ty, fn_ptr); const rc = f(clk_id, tp); switch (rc) { - 0, @bitCast(usize, isize(-EINVAL)) => return rc, + 0, @bitCast(usize, @as(isize, -EINVAL)) => return rc, else => {}, } } } - return syscall2(SYS_clock_gettime, @bitCast(usize, isize(clk_id)), @ptrToInt(tp)); + return syscall2(SYS_clock_gettime, @bitCast(usize, @as(isize, clk_id)), @ptrToInt(tp)); } extern fn init_vdso_clock_gettime(clk: i32, ts: *timespec) usize { const ptr = @intToPtr(?*const c_void, vdso.lookup(VDSO_CGT_VER, VDSO_CGT_SYM)); // Note that we may not have a VDSO at all, update the stub address anyway // so that clock_gettime will fall back on the good old (and slow) syscall - _ = @cmpxchgStrong(?*const c_void, &vdso_clock_gettime, &init_vdso_clock_gettime, ptr, .Monotonic, .Monotonic); + @atomicStore(?*const c_void, &vdso_clock_gettime, ptr, .Monotonic); // Call into the VDSO if available if (ptr) |fn_ptr| { const f = @ptrCast(vdso_clock_gettime_ty, fn_ptr); return f(clk, ts); } - return @bitCast(usize, isize(-ENOSYS)); + return @bitCast(usize, @as(isize, -ENOSYS)); } pub fn clock_getres(clk_id: i32, tp: *timespec) usize { - return syscall2(SYS_clock_getres, @bitCast(usize, isize(clk_id)), @ptrToInt(tp)); + return syscall2(SYS_clock_getres, @bitCast(usize, @as(isize, clk_id)), @ptrToInt(tp)); } pub fn clock_settime(clk_id: i32, tp: *const timespec) usize { - return syscall2(SYS_clock_settime, @bitCast(usize, isize(clk_id)), @ptrToInt(tp)); + return syscall2(SYS_clock_settime, @bitCast(usize, @as(isize, clk_id)), @ptrToInt(tp)); } pub fn gettimeofday(tv: *timeval, tz: *timezone) usize { @@ -594,33 +594,33 @@ pub fn setregid(rgid: u32, egid: u32) usize { pub fn getuid() u32 { if (@hasDecl(@This(), "SYS_getuid32")) { - return u32(syscall0(SYS_getuid32)); + return @as(u32, syscall0(SYS_getuid32)); } else { - return u32(syscall0(SYS_getuid)); + return @as(u32, syscall0(SYS_getuid)); } } pub fn getgid() u32 { if (@hasDecl(@This(), "SYS_getgid32")) { - return u32(syscall0(SYS_getgid32)); + return @as(u32, syscall0(SYS_getgid32)); } else { - return u32(syscall0(SYS_getgid)); + return @as(u32, syscall0(SYS_getgid)); } } pub fn geteuid() u32 { if (@hasDecl(@This(), "SYS_geteuid32")) { - return u32(syscall0(SYS_geteuid32)); + return @as(u32, syscall0(SYS_geteuid32)); } else { - return u32(syscall0(SYS_geteuid)); + return @as(u32, syscall0(SYS_geteuid)); } } pub fn getegid() u32 { if (@hasDecl(@This(), "SYS_getegid32")) { - return u32(syscall0(SYS_getegid32)); + return @as(u32, syscall0(SYS_getegid32)); } else { - return u32(syscall0(SYS_getegid)); + return @as(u32, syscall0(SYS_getegid)); } } @@ -743,11 +743,11 @@ pub fn sigismember(set: *const sigset_t, sig: u6) bool { } pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { - return syscall3(SYS_getsockname, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len)); + return syscall3(SYS_getsockname, @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @ptrToInt(len)); } pub fn getpeername(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { - return syscall3(SYS_getpeername, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len)); + return syscall3(SYS_getpeername, @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @ptrToInt(len)); } pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize { @@ -755,15 +755,15 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize { } pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: [*]const u8, optlen: socklen_t) usize { - return syscall5(SYS_setsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @intCast(usize, optlen)); + return syscall5(SYS_setsockopt, @bitCast(usize, @as(isize, fd)), level, optname, @ptrToInt(optval), @intCast(usize, optlen)); } pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noalias optlen: *socklen_t) usize { - return syscall5(SYS_getsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen)); + return syscall5(SYS_getsockopt, @bitCast(usize, @as(isize, fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen)); } pub fn sendmsg(fd: i32, msg: *msghdr_const, flags: u32) usize { - return syscall3(SYS_sendmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags); + return syscall3(SYS_sendmsg, @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags); } pub fn sendmmsg(fd: i32, msgvec: [*]mmsghdr_const, vlen: u32, flags: u32) usize { @@ -781,7 +781,7 @@ pub fn sendmmsg(fd: i32, msgvec: [*]mmsghdr_const, vlen: u32, flags: u32) usize // batch-send all messages up to the current message if (next_unsent < i) { const batch_size = i - next_unsent; - const r = syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(&msgvec[next_unsent]), batch_size, flags); + const r = syscall4(SYS_sendmmsg, @bitCast(usize, @as(isize, fd)), @ptrToInt(&msgvec[next_unsent]), batch_size, flags); if (getErrno(r) != 0) return next_unsent; if (r < batch_size) return next_unsent + r; } @@ -797,41 +797,41 @@ pub fn sendmmsg(fd: i32, msgvec: [*]mmsghdr_const, vlen: u32, flags: u32) usize } if (next_unsent < kvlen or next_unsent == 0) { // want to make sure at least one syscall occurs (e.g. to trigger MSG_EOR) const batch_size = kvlen - next_unsent; - const r = syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(&msgvec[next_unsent]), batch_size, flags); + const r = syscall4(SYS_sendmmsg, @bitCast(usize, @as(isize, fd)), @ptrToInt(&msgvec[next_unsent]), batch_size, flags); if (getErrno(r) != 0) return r; return next_unsent + r; } return kvlen; } - return syscall4(SYS_sendmmsg, @bitCast(usize, isize(fd)), @ptrToInt(msgvec), vlen, flags); + return syscall4(SYS_sendmmsg, @bitCast(usize, @as(isize, fd)), @ptrToInt(msgvec), vlen, flags); } pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize { - return syscall3(SYS_connect, @bitCast(usize, isize(fd)), @ptrToInt(addr), len); + return syscall3(SYS_connect, @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), len); } pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize { - return syscall3(SYS_recvmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags); + return syscall3(SYS_recvmsg, @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags); } pub fn recvfrom(fd: i32, noalias buf: [*]u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t) usize { - return syscall6(SYS_recvfrom, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen)); + return syscall6(SYS_recvfrom, @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen)); } pub fn shutdown(fd: i32, how: i32) usize { - return syscall2(SYS_shutdown, @bitCast(usize, isize(fd)), @bitCast(usize, isize(how))); + return syscall2(SYS_shutdown, @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, how))); } pub fn bind(fd: i32, addr: *const sockaddr, len: socklen_t) usize { - return syscall3(SYS_bind, @bitCast(usize, isize(fd)), @ptrToInt(addr), @intCast(usize, len)); + return syscall3(SYS_bind, @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @intCast(usize, len)); } pub fn listen(fd: i32, backlog: u32) usize { - return syscall2(SYS_listen, @bitCast(usize, isize(fd)), backlog); + return syscall2(SYS_listen, @bitCast(usize, @as(isize, fd)), backlog); } pub fn sendto(fd: i32, buf: [*]const u8, len: usize, flags: u32, addr: ?*const sockaddr, alen: socklen_t) usize { - return syscall6(SYS_sendto, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen)); + return syscall6(SYS_sendto, @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen)); } pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) usize { @@ -843,14 +843,14 @@ pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { } pub fn accept4(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t, flags: u32) usize { - return syscall4(SYS_accept4, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len), flags); + return syscall4(SYS_accept4, @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @ptrToInt(len), flags); } pub fn fstat(fd: i32, stat_buf: *Stat) usize { if (@hasDecl(@This(), "SYS_fstat64")) { - return syscall2(SYS_fstat64, @bitCast(usize, isize(fd)), @ptrToInt(stat_buf)); + return syscall2(SYS_fstat64, @bitCast(usize, @as(isize, fd)), @ptrToInt(stat_buf)); } else { - return syscall2(SYS_fstat, @bitCast(usize, isize(fd)), @ptrToInt(stat_buf)); + return syscall2(SYS_fstat, @bitCast(usize, @as(isize, fd)), @ptrToInt(stat_buf)); } } @@ -875,9 +875,9 @@ pub fn lstat(pathname: [*]const u8, statbuf: *Stat) usize { // TODO https://github.com/ziglang/zig/issues/265 pub fn fstatat(dirfd: i32, path: [*]const u8, stat_buf: *Stat, flags: u32) usize { if (@hasDecl(@This(), "SYS_fstatat64")) { - return syscall4(SYS_fstatat64, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags); + return syscall4(SYS_fstatat64, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags); } else { - return syscall4(SYS_fstatat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags); + return syscall4(SYS_fstatat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags); } } @@ -885,14 +885,14 @@ pub fn statx(dirfd: i32, path: [*]const u8, flags: u32, mask: u32, statx_buf: *S if (@hasDecl(@This(), "SYS_statx")) { return syscall5( SYS_statx, - @bitCast(usize, isize(dirfd)), + @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), flags, mask, @ptrToInt(statx_buf), ); } - return @bitCast(usize, isize(-ENOSYS)); + return @bitCast(usize, @as(isize, -ENOSYS)); } // TODO https://github.com/ziglang/zig/issues/265 @@ -954,8 +954,12 @@ pub fn fremovexattr(fd: usize, name: [*]const u8) usize { return syscall2(SYS_fremovexattr, fd, @ptrToInt(name)); } +pub fn sched_yield() usize { + return syscall0(SYS_sched_yield); +} + pub fn sched_getaffinity(pid: i32, size: usize, set: *cpu_set_t) usize { - const rc = syscall3(SYS_sched_getaffinity, @bitCast(usize, isize(pid)), size, @ptrToInt(set)); + const rc = syscall3(SYS_sched_getaffinity, @bitCast(usize, @as(isize, pid)), size, @ptrToInt(set)); if (@bitCast(isize, rc) < 0) return rc; if (rc < size) @memset(@ptrCast([*]u8, set) + rc, 0, size - rc); return 0; @@ -970,7 +974,7 @@ pub fn epoll_create1(flags: usize) usize { } pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: ?*epoll_event) usize { - return syscall4(SYS_epoll_ctl, @bitCast(usize, isize(epoll_fd)), @intCast(usize, op), @bitCast(usize, isize(fd)), @ptrToInt(ev)); + return syscall4(SYS_epoll_ctl, @bitCast(usize, @as(isize, epoll_fd)), @intCast(usize, op), @bitCast(usize, @as(isize, fd)), @ptrToInt(ev)); } pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize { @@ -980,10 +984,10 @@ pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout pub fn epoll_pwait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32, sigmask: ?*sigset_t) usize { return syscall6( SYS_epoll_pwait, - @bitCast(usize, isize(epoll_fd)), + @bitCast(usize, @as(isize, epoll_fd)), @ptrToInt(events), @intCast(usize, maxevents), - @bitCast(usize, isize(timeout)), + @bitCast(usize, @as(isize, timeout)), @ptrToInt(sigmask), @sizeOf(sigset_t), ); @@ -994,7 +998,7 @@ pub fn eventfd(count: u32, flags: u32) usize { } pub fn timerfd_create(clockid: i32, flags: u32) usize { - return syscall2(SYS_timerfd_create, @bitCast(usize, isize(clockid)), flags); + return syscall2(SYS_timerfd_create, @bitCast(usize, @as(isize, clockid)), flags); } pub const itimerspec = extern struct { @@ -1003,11 +1007,11 @@ pub const itimerspec = extern struct { }; pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize { - return syscall2(SYS_timerfd_gettime, @bitCast(usize, isize(fd)), @ptrToInt(curr_value)); + return syscall2(SYS_timerfd_gettime, @bitCast(usize, @as(isize, fd)), @ptrToInt(curr_value)); } pub fn timerfd_settime(fd: i32, flags: u32, new_value: *const itimerspec, old_value: ?*itimerspec) usize { - return syscall4(SYS_timerfd_settime, @bitCast(usize, isize(fd)), flags, @ptrToInt(new_value), @ptrToInt(old_value)); + return syscall4(SYS_timerfd_settime, @bitCast(usize, @as(isize, fd)), flags, @ptrToInt(new_value), @ptrToInt(old_value)); } pub fn unshare(flags: usize) usize { @@ -1092,11 +1096,11 @@ pub fn io_uring_setup(entries: u32, p: *io_uring_params) usize { } pub fn io_uring_enter(fd: i32, to_submit: u32, min_complete: u32, flags: u32, sig: ?*sigset_t) usize { - return syscall6(SYS_io_uring_enter, @bitCast(usize, isize(fd)), to_submit, min_complete, flags, @ptrToInt(sig), NSIG / 8); + return syscall6(SYS_io_uring_enter, @bitCast(usize, @as(isize, fd)), to_submit, min_complete, flags, @ptrToInt(sig), NSIG / 8); } pub fn io_uring_register(fd: i32, opcode: u32, arg: ?*const c_void, nr_args: u32) usize { - return syscall4(SYS_io_uring_register, @bitCast(usize, isize(fd)), opcode, @ptrToInt(arg), nr_args); + return syscall4(SYS_io_uring_register, @bitCast(usize, @as(isize, fd)), opcode, @ptrToInt(arg), nr_args); } test "" { diff --git a/lib/std/os/linux/arm-eabi.zig b/lib/std/os/linux/arm-eabi.zig @@ -100,7 +100,7 @@ pub extern fn getThreadPointer() usize { pub nakedcc fn restore() void { return asm volatile ("svc #0" : - : [number] "{r7}" (usize(SYS_sigreturn)) + : [number] "{r7}" (@as(usize, SYS_sigreturn)) : "memory" ); } @@ -108,7 +108,7 @@ pub nakedcc fn restore() void { pub nakedcc fn restore_rt() void { return asm volatile ("svc #0" : - : [number] "{r7}" (usize(SYS_rt_sigreturn)) + : [number] "{r7}" (@as(usize, SYS_rt_sigreturn)) : "memory" ); } diff --git a/lib/std/os/linux/arm64.zig b/lib/std/os/linux/arm64.zig @@ -93,7 +93,7 @@ pub const restore = restore_rt; pub nakedcc fn restore_rt() void { return asm volatile ("svc #0" : - : [number] "{x8}" (usize(SYS_rt_sigreturn)) + : [number] "{x8}" (@as(usize, SYS_rt_sigreturn)) : "memory", "cc" ); } diff --git a/lib/std/os/linux/mipsel.zig b/lib/std/os/linux/mipsel.zig @@ -26,7 +26,7 @@ pub fn syscall_pipe(fd: *[2]i32) usize { \\ sw $3, 4($4) \\ 2: : [ret] "={$2}" (-> usize) - : [number] "{$2}" (usize(SYS_pipe)) + : [number] "{$2}" (@as(usize, SYS_pipe)) : "memory", "cc", "$7" ); } @@ -147,7 +147,7 @@ pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, a pub nakedcc fn restore() void { return asm volatile ("syscall" : - : [number] "{$2}" (usize(SYS_sigreturn)) + : [number] "{$2}" (@as(usize, SYS_sigreturn)) : "memory", "cc", "$7" ); } @@ -155,7 +155,7 @@ pub nakedcc fn restore() void { pub nakedcc fn restore_rt() void { return asm volatile ("syscall" : - : [number] "{$2}" (usize(SYS_rt_sigreturn)) + : [number] "{$2}" (@as(usize, SYS_rt_sigreturn)) : "memory", "cc", "$7" ); } diff --git a/lib/std/os/linux/riscv64.zig b/lib/std/os/linux/riscv64.zig @@ -92,7 +92,7 @@ pub const restore = restore_rt; pub nakedcc fn restore_rt() void { return asm volatile ("ecall" : - : [number] "{x17}" (usize(SYS_rt_sigreturn)) + : [number] "{x17}" (@as(usize, SYS_rt_sigreturn)) : "memory" ); } diff --git a/lib/std/os/linux/test.zig b/lib/std/os/linux/test.zig @@ -72,7 +72,7 @@ test "statx" { expect(stat_buf.mode == statx_buf.mode); expect(@bitCast(u32, stat_buf.uid) == statx_buf.uid); expect(@bitCast(u32, stat_buf.gid) == statx_buf.gid); - expect(@bitCast(u64, i64(stat_buf.size)) == statx_buf.size); - expect(@bitCast(u64, i64(stat_buf.blksize)) == statx_buf.blksize); - expect(@bitCast(u64, i64(stat_buf.blocks)) == statx_buf.blocks); + expect(@bitCast(u64, @as(i64, stat_buf.size)) == statx_buf.size); + expect(@bitCast(u64, @as(i64, stat_buf.blksize)) == statx_buf.blksize); + expect(@bitCast(u64, @as(i64, stat_buf.blocks)) == statx_buf.blocks); } diff --git a/lib/std/os/linux/vdso.zig b/lib/std/os/linux/vdso.zig @@ -62,8 +62,8 @@ pub fn lookup(vername: []const u8, name: []const u8) usize { var i: usize = 0; while (i < hashtab[1]) : (i += 1) { - if (0 == (u32(1) << @intCast(u5, syms[i].st_info & 0xf) & OK_TYPES)) continue; - if (0 == (u32(1) << @intCast(u5, syms[i].st_info >> 4) & OK_BINDS)) continue; + if (0 == (@as(u32, 1) << @intCast(u5, syms[i].st_info & 0xf) & OK_TYPES)) continue; + if (0 == (@as(u32, 1) << @intCast(u5, syms[i].st_info >> 4) & OK_BINDS)) continue; if (0 == syms[i].st_shndx) continue; if (!mem.eql(u8, name, mem.toSliceConst(u8, strings + syms[i].st_name))) continue; if (maybe_versym) |versym| { diff --git a/lib/std/os/linux/x86_64.zig b/lib/std/os/linux/x86_64.zig @@ -93,7 +93,7 @@ pub const restore = restore_rt; pub nakedcc fn restore_rt() void { return asm volatile ("syscall" : - : [number] "{rax}" (usize(SYS_rt_sigreturn)) + : [number] "{rax}" (@as(usize, SYS_rt_sigreturn)) : "rcx", "r11", "memory" ); } diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig @@ -172,7 +172,7 @@ export fn iter_fn(info: *dl_phdr_info, size: usize, data: ?*usize) i32 { var counter = data.?; // Count how many libraries are loaded - counter.* += usize(1); + counter.* += @as(usize, 1); // The image should contain at least a PT_LOAD segment if (info.dlpi_phnum < 1) return -1; diff --git a/lib/std/os/uefi/protocols.zig b/lib/std/os/uefi/protocols.zig @@ -1,3 +1,7 @@ +pub const LoadedImageProtocol = @import("protocols/loaded_image_protocol.zig").LoadedImageProtocol; + +pub const DevicePathProtocol = @import("protocols/device_path_protocol.zig").DevicePathProtocol; + 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 KeyState = @import("protocols/simple_text_input_ex_protocol.zig").KeyState; @@ -29,6 +33,46 @@ pub const EdidActiveProtocol = @import("protocols/edid_active_protocol.zig").Edi pub const EdidOverrideProtocol = @import("protocols/edid_override_protocol.zig").EdidOverrideProtocol; pub const EdidOverrideProtocolAttributes = @import("protocols/edid_override_protocol.zig").EdidOverrideProtocolAttributes; +pub const SimpleNetworkProtocol = @import("protocols/simple_network_protocol.zig").SimpleNetworkProtocol; +pub const MacAddress = @import("protocols/simple_network_protocol.zig").MacAddress; +pub const SimpleNetworkMode = @import("protocols/simple_network_protocol.zig").SimpleNetworkMode; +pub const SimpleNetworkReceiveFilter = @import("protocols/simple_network_protocol.zig").SimpleNetworkReceiveFilter; +pub const SimpleNetworkState = @import("protocols/simple_network_protocol.zig").SimpleNetworkState; +pub const NetworkStatistics = @import("protocols/simple_network_protocol.zig").NetworkStatistics; +pub const SimpleNetworkInterruptStatus = @import("protocols/simple_network_protocol.zig").SimpleNetworkInterruptStatus; + +pub const ManagedNetworkServiceBindingProtocol = @import("protocols/managed_network_service_binding_protocol.zig").ManagedNetworkServiceBindingProtocol; +pub const ManagedNetworkProtocol = @import("protocols/managed_network_protocol.zig").ManagedNetworkProtocol; +pub const ManagedNetworkConfigData = @import("protocols/managed_network_protocol.zig").ManagedNetworkConfigData; +pub const ManagedNetworkCompletionToken = @import("protocols/managed_network_protocol.zig").ManagedNetworkCompletionToken; +pub const ManagedNetworkReceiveData = @import("protocols/managed_network_protocol.zig").ManagedNetworkReceiveData; +pub const ManagedNetworkTransmitData = @import("protocols/managed_network_protocol.zig").ManagedNetworkTransmitData; +pub const ManagedNetworkFragmentData = @import("protocols/managed_network_protocol.zig").ManagedNetworkFragmentData; + +pub const Ip6ServiceBindingProtocol = @import("protocols/ip6_service_binding_protocol.zig").Ip6ServiceBindingProtocol; +pub const Ip6Protocol = @import("protocols/ip6_protocol.zig").Ip6Protocol; +pub const Ip6ModeData = @import("protocols/ip6_protocol.zig").Ip6ModeData; +pub const Ip6ConfigData = @import("protocols/ip6_protocol.zig").Ip6ConfigData; +pub const Ip6Address = @import("protocols/ip6_protocol.zig").Ip6Address; +pub const Ip6AddressInfo = @import("protocols/ip6_protocol.zig").Ip6AddressInfo; +pub const Ip6RouteTable = @import("protocols/ip6_protocol.zig").Ip6RouteTable; +pub const Ip6NeighborState = @import("protocols/ip6_protocol.zig").Ip6NeighborState; +pub const Ip6NeighborCache = @import("protocols/ip6_protocol.zig").Ip6NeighborCache; +pub const Ip6IcmpType = @import("protocols/ip6_protocol.zig").Ip6IcmpType; +pub const Ip6CompletionToken = @import("protocols/ip6_protocol.zig").Ip6CompletionToken; + +pub const Ip6ConfigProtocol = @import("protocols/ip6_config_protocol.zig").Ip6ConfigProtocol; +pub const Ip6ConfigDataType = @import("protocols/ip6_config_protocol.zig").Ip6ConfigDataType; + +pub const Udp6ServiceBindingProtocol = @import("protocols/udp6_service_binding_protocol.zig").Udp6ServiceBindingProtocol; +pub const Udp6Protocol = @import("protocols/udp6_protocol.zig").Udp6Protocol; +pub const Udp6ConfigData = @import("protocols/udp6_protocol.zig").Udp6ConfigData; +pub const Udp6CompletionToken = @import("protocols/udp6_protocol.zig").Udp6CompletionToken; +pub const Udp6ReceiveData = @import("protocols/udp6_protocol.zig").Udp6ReceiveData; +pub const Udp6TransmitData = @import("protocols/udp6_protocol.zig").Udp6TransmitData; +pub const Udp6SessionData = @import("protocols/udp6_protocol.zig").Udp6SessionData; +pub const Udp6FragmentData = @import("protocols/udp6_protocol.zig").Udp6FragmentData; + pub const hii = @import("protocols/hii.zig"); pub const HIIDatabaseProtocol = @import("protocols/hii_database_protocol.zig").HIIDatabaseProtocol; pub const HIIPopupProtocol = @import("protocols/hii_popup_protocol.zig").HIIPopupProtocol; diff --git a/lib/std/os/uefi/protocols/device_path_protocol.zig b/lib/std/os/uefi/protocols/device_path_protocol.zig @@ -0,0 +1,17 @@ +const uefi = @import("std").os.uefi; +const Guid = uefi.Guid; + +pub const DevicePathProtocol = extern struct { + type: u8, + subtype: u8, + length: u16, + + pub const guid align(8) = Guid{ + .time_low = 0x09576e91, + .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 }, + }; +}; diff --git a/lib/std/os/uefi/protocols/ip6_config_protocol.zig b/lib/std/os/uefi/protocols/ip6_config_protocol.zig @@ -0,0 +1,45 @@ +const uefi = @import("std").os.uefi; +const Guid = uefi.Guid; +const Event = uefi.Event; + +pub const Ip6ConfigProtocol = extern struct { + _set_data: extern fn (*const Ip6ConfigProtocol, Ip6ConfigDataType, usize, *const c_void) usize, + _get_data: extern fn (*const Ip6ConfigProtocol, Ip6ConfigDataType, *usize, ?*const c_void) usize, + _register_data_notify: extern fn (*const Ip6ConfigProtocol, Ip6ConfigDataType, Event) usize, + _unregister_data_notify: extern fn (*const Ip6ConfigProtocol, Ip6ConfigDataType, Event) usize, + + pub fn setData(self: *const Ip6ConfigProtocol, data_type: Ip6ConfigDataType, data_size: usize, data: *const c_void) usize { + return self._set_data(self, data_type, data_size, data); + } + + pub fn getData(self: *const Ip6ConfigProtocol, data_type: Ip6ConfigDataType, data_size: *usize, data: ?*const c_void) usize { + return self._get_data(self, data_type, data_size, data); + } + + pub fn registerDataNotify(self: *const Ip6ConfigProtocol, data_type: Ip6ConfigDataType, event: Event) usize { + return self._register_data_notify(self, data_type, event); + } + + pub fn unregisterDataNotify(self: *const Ip6ConfigProtocol, data_type: Ip6ConfigDataType, event: Event) usize { + return self._unregister_data_notify(self, data_type, event); + } + + pub const guid align(8) = Guid{ + .time_low = 0x937fe521, + .time_mid = 0x95ae, + .time_high_and_version = 0x4d1a, + .clock_seq_high_and_reserved = 0x89, + .clock_seq_low = 0x29, + .node = [_]u8{ 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a }, + }; +}; + +pub const Ip6ConfigDataType = extern enum(u32) { + InterfaceInfo, + AltInterfaceId, + Policy, + DupAddrDetectTransmits, + ManualAddress, + Gateway, + DnsServer, +}; diff --git a/lib/std/os/uefi/protocols/ip6_protocol.zig b/lib/std/os/uefi/protocols/ip6_protocol.zig @@ -0,0 +1,143 @@ +const uefi = @import("std").os.uefi; +const Guid = uefi.Guid; +const Event = uefi.Event; +const MacAddress = uefi.protocols.MacAddress; +const ManagedNetworkConfigData = uefi.protocols.ManagedNetworkConfigData; +const SimpleNetworkMode = uefi.protocols.SimpleNetworkMode; + +pub const Ip6Protocol = extern struct { + _get_mode_data: extern fn (*const Ip6Protocol, ?*Ip6ModeData, ?*ManagedNetworkConfigData, ?*SimpleNetworkMode) usize, + _configure: extern fn (*const Ip6Protocol, ?*const Ip6ConfigData) usize, + _groups: extern fn (*const Ip6Protocol, bool, ?*const Ip6Address) usize, + _routes: extern fn (*const Ip6Protocol, bool, ?*const Ip6Address, u8, ?*const Ip6Address) usize, + _neighbors: extern fn (*const Ip6Protocol, bool, *const Ip6Address, ?*const MacAddress, u32, bool) usize, + _transmit: extern fn (*const Ip6Protocol, *Ip6CompletionToken) usize, + _receive: extern fn (*const Ip6Protocol, *Ip6CompletionToken) usize, + _cancel: extern fn (*const Ip6Protocol, ?*Ip6CompletionToken) usize, + _poll: extern fn (*const Ip6Protocol) usize, + + /// Gets the current operational settings for this instance of the EFI IPv6 Protocol driver. + pub fn getModeData(self: *const Ip6Protocol, ip6_mode_data: ?*Ip6ModeData, mnp_config_data: ?*ManagedNetworkConfigData, snp_mode_data: ?*SimpleNetworkMode) usize { + return self._get_mode_data(self, ip6_mode_data, mnp_config_data, snp_mode_data); + } + + /// Assign IPv6 address and other configuration parameter to this EFI IPv6 Protocol driver instance. + pub fn configure(self: *const Ip6Protocol, ip6_config_data: ?*const Ip6ConfigData) usize { + return self._configure(self, ip6_config_data); + } + + /// Joins and leaves multicast groups. + pub fn groups(self: *const Ip6Protocol, join_flag: bool, group_address: ?*const Ip6Address) usize { + return self._groups(self, join_flag, group_address); + } + + /// Adds and deletes routing table entries. + pub fn routes(self: *const Ip6Protocol, delete_route: bool, destination: ?*const Ip6Address, prefix_length: u8, gateway_address: ?*const Ip6Address) usize { + return self._routes(self, delete_route, destination, prefix_length, gateway_address); + } + + /// Add or delete Neighbor cache entries. + pub fn neighbors(self: *const Ip6Protocol, delete_flag: bool, target_ip6_address: *const Ip6Address, target_link_address: ?*const MacAddress, timeout: u32, override: bool) usize { + return self._neighbors(self, delete_flag, target_ip6_address, target_link_address, timeout, override); + } + + /// Places outgoing data packets into the transmit queue. + pub fn transmit(self: *const Ip6Protocol, token: *Ip6CompletionToken) usize { + return self._transmit(self, token); + } + + /// Places a receiving request into the receiving queue. + pub fn receive(self: *const Ip6Protocol, token: *Ip6CompletionToken) usize { + return self._receive(self, token); + } + + /// Abort an asynchronous transmits or receive request. + pub fn cancel(self: *const Ip6Protocol, token: ?*Ip6CompletionToken) usize { + return self._cancel(self, token); + } + + /// Polls for incoming data packets and processes outgoing data packets. + pub fn poll(self: *const Ip6Protocol) usize { + return self._poll(self); + } + + pub const guid align(8) = Guid{ + .time_low = 0x2c8759d5, + .time_mid = 0x5c2d, + .time_high_and_version = 0x66ef, + .clock_seq_high_and_reserved = 0x92, + .clock_seq_low = 0x5f, + .node = [_]u8{ 0xb6, 0x6c, 0x10, 0x19, 0x57, 0xe2 }, + }; +}; + +pub const Ip6ModeData = extern struct { + is_started: bool, + max_packet_size: u32, + config_data: Ip6ConfigData, + is_configured: bool, + address_count: u32, + address_list: [*]Ip6AddressInfo, + group_count: u32, + group_table: [*]Ip6Address, + route_count: u32, + route_table: [*]Ip6RouteTable, + neighbor_count: u32, + neighbor_cache: [*]Ip6NeighborCache, + prefix_count: u32, + prefix_table: [*]Ip6AddressInfo, + icmp_type_count: u32, + icmp_type_list: [*]Ip6IcmpType, +}; + +pub const Ip6ConfigData = extern struct { + default_protocol: u8, + accept_any_protocol: bool, + accept_icmp_errors: bool, + accept_promiscuous: bool, + destination_address: Ip6Address, + station_address: Ip6Address, + traffic_class: u8, + hop_limit: u8, + flow_label: u32, + receive_timeout: u32, + transmit_timeout: u32, +}; + +pub const Ip6Address = [16]u8; + +pub const Ip6AddressInfo = extern struct { + address: Ip6Address, + prefix_length: u8, +}; + +pub const Ip6RouteTable = extern struct { + gateway: Ip6Address, + destination: Ip6Address, + prefix_length: u8, +}; + +pub const Ip6NeighborState = extern enum(u32) { + Incomplete, + Reachable, + Stale, + Delay, + Probe, +}; + +pub const Ip6NeighborCache = extern struct { + neighbor: Ip6Address, + link_address: MacAddress, + state: Ip6NeighborState, +}; + +pub const Ip6IcmpType = extern struct { + type: u8, + code: u8, +}; + +pub const Ip6CompletionToken = extern struct { + event: Event, + status: usize, + packet: *c_void, // union TODO +}; diff --git a/lib/std/os/uefi/protocols/ip6_service_binding_protocol.zig b/lib/std/os/uefi/protocols/ip6_service_binding_protocol.zig @@ -0,0 +1,25 @@ +const uefi = @import("std").os.uefi; +const Handle = uefi.Handle; +const Guid = uefi.Guid; + +pub const Ip6ServiceBindingProtocol = extern struct { + _create_child: extern fn (*const Ip6ServiceBindingProtocol, *?Handle) usize, + _destroy_child: extern fn (*const Ip6ServiceBindingProtocol, Handle) usize, + + pub fn createChild(self: *const Ip6ServiceBindingProtocol, handle: *?Handle) usize { + return self._create_child(self, handle); + } + + pub fn destroyChild(self: *const Ip6ServiceBindingProtocol, handle: Handle) usize { + return self._destroy_child(self, handle); + } + + pub const guid align(8) = Guid{ + .time_low = 0xec835dd3, + .time_mid = 0xfe0f, + .time_high_and_version = 0x617b, + .clock_seq_high_and_reserved = 0xa6, + .clock_seq_low = 0x21, + .node = [_]u8{ 0xb3, 0x50, 0xc3, 0xe1, 0x33, 0x88 }, + }; +}; diff --git a/lib/std/os/uefi/protocols/loaded_image_protocol.zig b/lib/std/os/uefi/protocols/loaded_image_protocol.zig @@ -0,0 +1,36 @@ +const uefi = @import("std").os.uefi; +const Guid = uefi.Guid; +const Handle = uefi.Handle; +const SystemTable = uefi.tables.SystemTable; +const MemoryType = uefi.tables.MemoryType; +const DevicePathProtocol = uefi.protocols.DevicePathProtocol; + +pub const LoadedImageProtocol = extern struct { + revision: u32, + parent_handle: Handle, + system_table: *SystemTable, + device_handle: ?Handle, + file_path: *DevicePathProtocol, + reserved: *c_void, + load_options_size: u32, + load_options: *c_void, + image_base: [*]u8, + image_size: u64, + image_code_type: MemoryType, + image_data_type: MemoryType, + _unload: extern fn (*const LoadedImageProtocol, Handle) usize, + + /// Unloads an image from memory. + pub fn unload(self: *const LoadedImageProtocol, handle: Handle) usize { + return self._unload(self, handle); + } + + pub const guid align(8) = Guid{ + .time_low = 0x5b1b31a1, + .time_mid = 0x9562, + .time_high_and_version = 0x11d2, + .clock_seq_high_and_reserved = 0x8e, + .clock_seq_low = 0x3f, + .node = [_]u8{ 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b }, + }; +}; diff --git a/lib/std/os/uefi/protocols/managed_network_protocol.zig b/lib/std/os/uefi/protocols/managed_network_protocol.zig @@ -0,0 +1,126 @@ +const uefi = @import("std").os.uefi; +const Guid = uefi.Guid; +const Event = uefi.Event; +const Time = uefi.Time; +const SimpleNetworkMode = uefi.protocols.SimpleNetworkMode; +const MacAddress = uefi.protocols.MacAddress; + +pub const ManagedNetworkProtocol = extern struct { + _get_mode_data: extern fn (*const ManagedNetworkProtocol, ?*ManagedNetworkConfigData, ?*SimpleNetworkMode) usize, + _configure: extern fn (*const ManagedNetworkProtocol, ?*const ManagedNetworkConfigData) usize, + _mcast_ip_to_mac: extern fn (*const ManagedNetworkProtocol, bool, *const c_void, *MacAddress) usize, + _groups: extern fn (*const ManagedNetworkProtocol, bool, ?*const MacAddress) usize, + _transmit: extern fn (*const ManagedNetworkProtocol, *const ManagedNetworkCompletionToken) usize, + _receive: extern fn (*const ManagedNetworkProtocol, *const ManagedNetworkCompletionToken) usize, + _cancel: extern fn (*const ManagedNetworkProtocol, ?*const ManagedNetworkCompletionToken) usize, + _poll: extern fn (*const ManagedNetworkProtocol) usize, + + /// Returns the operational parameters for the current MNP child driver. + /// May also support returning the underlying SNP driver mode data. + pub fn getModeData(self: *const ManagedNetworkProtocol, mnp_config_data: ?*ManagedNetworkConfigData, snp_mode_data: ?*SimpleNetworkMode) usize { + return self._get_mode_data(self, mnp_config_data, snp_mode_data); + } + + /// Sets or clears the operational parameters for the MNP child driver. + pub fn configure(self: *const ManagedNetworkProtocol, mnp_config_data: ?*const ManagedNetworkConfigData) usize { + return self._configure(self, mnp_config_data); + } + + /// Translates an IP multicast address to a hardware (MAC) multicast address. + /// This function may be unsupported in some MNP implementations. + pub fn mcastIpToMac(self: *const ManagedNetworkProtocol, ipv6flag: bool, ipaddress: *const c_void, mac_address: *MacAddress) usize { + return self._mcast_ip_to_mac(self, ipv6flag, ipaddress); + } + + /// Enables and disables receive filters for multicast address. + /// This function may be unsupported in some MNP implementations. + pub fn groups(self: *const ManagedNetworkProtocol, join_flag: bool, mac_address: ?*const MacAddress) usiz { + return self._groups(self, join_flag, mac_address); + } + + /// Places asynchronous outgoing data packets into the transmit queue. + pub fn transmit(self: *const ManagedNetworkProtocol, token: *const ManagedNetworkCompletionToken) usize { + return self._transmit(self, token); + } + + /// Places an asynchronous receiving request into the receiving queue. + pub fn receive(self: *const ManagedNetworkProtocol, token: *const ManagedNetworkCompletionToken) usize { + return self._receive(self, token); + } + + /// Aborts an asynchronous transmit or receive request. + pub fn cancel(self: *const ManagedNetworkProtocol, token: ?*const ManagedNetworkCompletionToken) usize { + return self._cancel(self, token); + } + + /// Polls for incoming data packets and processes outgoing data packets. + pub fn poll(self: *const ManagedNetworkProtocol) usize { + return self._poll(self); + } + + pub const guid align(8) = Guid{ + .time_low = 0x7ab33a91, + .time_mid = 0xace5, + .time_high_and_version = 0x4326, + .clock_seq_high_and_reserved = 0xb5, + .clock_seq_low = 0x72, + .node = [_]u8{ 0xe7, 0xee, 0x33, 0xd3, 0x9f, 0x16 }, + }; +}; + +pub const ManagedNetworkConfigData = extern struct { + received_queue_timeout_value: u32, + transmit_queue_timeout_value: u32, + protocol_type_filter: u16, + enable_unicast_receive: bool, + enable_multicast_receive: bool, + enable_broadcast_receive: bool, + enable_promiscuous_receive: bool, + flush_queues_on_reset: bool, + enable_receive_timestamps: bool, + disable_background_polling: bool, +}; + +pub const ManagedNetworkCompletionToken = extern struct { + event: Event, + status: usize, + packet: extern union { + RxData: *ManagedNetworkReceiveData, + TxData: *ManagedNetworkTransmitData, + }, +}; + +pub const ManagedNetworkReceiveData = extern struct { + timestamp: Time, + recycle_event: Event, + packet_length: u32, + header_length: u32, + address_length: u32, + data_length: u32, + broadcast_flag: bool, + multicast_flag: bool, + promiscuous_flag: bool, + protocol_type: u16, + destination_address: [*]u8, + source_address: [*]u8, + media_header: [*]u8, + packet_data: [*]u8, +}; + +pub const ManagedNetworkTransmitData = extern struct { + destination_address: ?*MacAddress, + source_address: ?*MacAddress, + protocol_type: u16, + data_length: u32, + header_length: u16, + fragment_count: u16, + + pub fn getFragments(self: *ManagedNetworkTransmitData) []ManagedNetworkFragmentData { + return @ptrCast([*]ManagedNetworkFragmentData, @ptrCast([*]u8, self) + @sizeOf(ManagedNetworkTransmitData))[0..self.fragment_count]; + } +}; + +pub const ManagedNetworkFragmentData = extern struct { + fragment_length: u32, + fragment_buffer: [*]u8, +}; diff --git a/lib/std/os/uefi/protocols/managed_network_service_binding_protocol.zig b/lib/std/os/uefi/protocols/managed_network_service_binding_protocol.zig @@ -0,0 +1,25 @@ +const uefi = @import("std").os.uefi; +const Handle = uefi.Handle; +const Guid = uefi.Guid; + +pub const ManagedNetworkServiceBindingProtocol = extern struct { + _create_child: extern fn (*const ManagedNetworkServiceBindingProtocol, *?Handle) usize, + _destroy_child: extern fn (*const ManagedNetworkServiceBindingProtocol, Handle) usize, + + pub fn createChild(self: *const ManagedNetworkServiceBindingProtocol, handle: *?Handle) usize { + return self._create_child(self, handle); + } + + pub fn destroyChild(self: *const ManagedNetworkServiceBindingProtocol, handle: Handle) usize { + return self._destroy_child(self, handle); + } + + pub const guid align(8) = Guid{ + .time_low = 0xf36ff770, + .time_mid = 0xa7e1, + .time_high_and_version = 0x42cf, + .clock_seq_high_and_reserved = 0x9e, + .clock_seq_low = 0xd2, + .node = [_]u8{ 0x56, 0xf0, 0xf2, 0x71, 0xf4, 0x4c }, + }; +}; diff --git a/lib/std/os/uefi/protocols/simple_network_protocol.zig b/lib/std/os/uefi/protocols/simple_network_protocol.zig @@ -0,0 +1,172 @@ +const uefi = @import("std").os.uefi; +const Event = uefi.Event; +const Guid = uefi.Guid; + +pub const SimpleNetworkProtocol = extern struct { + revision: u64, + _start: extern fn (*const SimpleNetworkProtocol) usize, + _stop: extern fn (*const SimpleNetworkProtocol) usize, + _initialize: extern fn (*const SimpleNetworkProtocol, usize, usize) usize, + _reset: extern fn (*const SimpleNetworkProtocol, bool) usize, + _shutdown: extern fn (*const SimpleNetworkProtocol) usize, + _receive_filters: extern fn (*const SimpleNetworkProtocol, SimpleNetworkReceiveFilter, SimpleNetworkReceiveFilter, bool, usize, ?[*]const MacAddress) usize, + _station_address: extern fn (*const SimpleNetworkProtocol, bool, ?*const MacAddress) usize, + _statistics: extern fn (*const SimpleNetworkProtocol, bool, ?*usize, ?*NetworkStatistics) usize, + _mcast_ip_to_mac: extern fn (*const SimpleNetworkProtocol, bool, *const c_void, *MacAddress) usize, + _nvdata: extern fn (*const SimpleNetworkProtocol, bool, usize, usize, [*]u8) usize, + _get_status: extern fn (*const SimpleNetworkProtocol, *SimpleNetworkInterruptStatus, ?*?[*]u8) usize, + _transmit: extern fn (*const SimpleNetworkProtocol, usize, usize, [*]const u8, ?*const MacAddress, ?*const MacAddress, ?*const u16) usize, + _receive: extern fn (*const SimpleNetworkProtocol, ?*usize, *usize, [*]u8, ?*MacAddress, ?*MacAddress, ?*u16) usize, + wait_for_packet: Event, + mode: *SimpleNetworkMode, + + /// Changes the state of a network interface from "stopped" to "started". + pub fn start(self: *const SimpleNetworkProtocol) usize { + return self._start(self); + } + + /// Changes the state of a network interface from "started" to "stopped". + pub fn stop(self: *const SimpleNetworkProtocol) usize { + return self._stop(self); + } + + /// Resets a network adapter and allocates the transmit and receive buffers required by the network interface. + pub fn initialize(self: *const SimpleNetworkProtocol, extra_rx_buffer_size: usize, extra_tx_buffer_size: usize) usize { + return self._initialize(self, extra_rx_buffer_size, extra_tx_buffer_size); + } + + /// Resets a network adapter and reinitializes it with the parameters that were provided in the previous call to initialize(). + pub fn reset(self: *const SimpleNetworkProtocol, extended_verification: bool) usize { + return self._reset(self, extended_verification); + } + + /// Resets a network adapter and leaves it in a state that is safe for another driver to initialize. + pub fn shutdown(self: *const SimpleNetworkProtocol) usize { + return self._shutdown(self); + } + + /// Manages the multicast receive filters of a network interface. + pub fn receiveFilters(self: *const SimpleNetworkProtocol, enable: SimpleNetworkReceiveFilter, disable: SimpleNetworkReceiveFilter, reset_mcast_filter: bool, mcast_filter_cnt: usize, mcast_filter: ?[*]const MacAddress) usize { + return self._receive_filters(self, enable, disable, reset_mcast_filter, mcast_filter_cnt, mcast_filter); + } + + /// Modifies or resets the current station address, if supported. + pub fn stationAddress(self: *const SimpleNetworkProtocol, reset: bool, new: ?*const MacAddress) usize { + return self._station_address(self, reset, new); + } + + /// Resets or collects the statistics on a network interface. + pub fn statistics(self: *const SimpleNetworkProtocol, reset_: bool, statistics_size: ?*usize, statistics_table: ?*NetworkStatistics) usize { + return self._statistics(self, reset_, statistics_size, statistics_table); + } + + /// Converts a multicast IP address to a multicast HW MAC address. + pub fn mcastIpToMac(self: *const SimpleNetworkProtocol, ipv6: bool, ip: *const c_void, mac: *MacAddress) usize { + return self._mcast_ip_to_mac(self, ipv6, ip, mac); + } + + /// Performs read and write operations on the NVRAM device attached to a network interface. + pub fn nvdata(self: *const SimpleNetworkProtocol, read_write: bool, offset: usize, buffer_size: usize, buffer: [*]u8) usize { + return self._nvdata(self, read_write, offset, buffer_size, buffer); + } + + /// Reads the current interrupt status and recycled transmit buffer status from a network interface. + pub fn getStatus(self: *const SimpleNetworkProtocol, interrupt_status: *SimpleNetworkInterruptStatus, tx_buf: ?*?[*]u8) usize { + return self._get_status(self, interrupt_status, tx_buf); + } + + /// Places a packet in the transmit queue of a network interface. + pub fn transmit(self: *const SimpleNetworkProtocol, header_size: usize, buffer_size: usize, buffer: [*]const u8, src_addr: ?*const MacAddress, dest_addr: ?*const MacAddress, protocol: ?*const u16) usize { + return self._transmit(self, header_size, buffer_size, buffer, src_addr, dest_addr, protocol); + } + + /// Receives a packet from a network interface. + pub fn receive(self: *const SimpleNetworkProtocol, header_size: ?*usize, buffer_size: *usize, buffer: [*]u8, src_addr: ?*MacAddress, dest_addr: ?*MacAddress, protocol: ?*u16) usize { + return self._receive(self, header_size, buffer_size, buffer, src_addr, dest_addr, protocol); + } + + pub const guid align(8) = Guid{ + .time_low = 0xa19832b9, + .time_mid = 0xac25, + .time_high_and_version = 0x11d3, + .clock_seq_high_and_reserved = 0x9a, + .clock_seq_low = 0x2d, + .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d }, + }; +}; + +pub const MacAddress = [32]u8; + +pub const SimpleNetworkMode = extern struct { + state: SimpleNetworkState, + hw_address_size: u32, + media_header_size: u32, + max_packet_size: u32, + nvram_size: u32, + nvram_access_size: u32, + receive_filter_mask: SimpleNetworkReceiveFilter, + receive_filter_setting: SimpleNetworkReceiveFilter, + max_mcast_filter_count: u32, + mcast_filter_count: u32, + mcast_filter: [16]MacAddress, + current_address: MacAddress, + broadcast_address: MacAddress, + permanent_address: MacAddress, + if_type: u8, + mac_address_changeable: bool, + multiple_tx_supported: bool, + media_present_supported: bool, + media_present: bool, +}; + +pub const SimpleNetworkReceiveFilter = packed struct { + receive_unicast: bool, + receive_multicast: bool, + receive_broadcast: bool, + receive_promiscuous: bool, + receive_promiscuous_multicast: bool, + _pad: u27 = undefined, +}; + +pub const SimpleNetworkState = extern enum(u32) { + Stopped, + Started, + Initialized, +}; + +pub const NetworkStatistics = extern struct { + rx_total_frames: u64, + rx_good_frames: u64, + rx_undersize_frames: u64, + rx_oversize_frames: u64, + rx_dropped_frames: u64, + rx_unicast_frames: u64, + rx_broadcast_frames: u64, + rx_multicast_frames: u64, + rx_crc_error_frames: u64, + rx_total_bytes: u64, + tx_total_frames: u64, + tx_good_frames: u64, + tx_undersize_frames: u64, + tx_oversize_frames: u64, + tx_dropped_frames: u64, + tx_unicast_frames: u64, + tx_broadcast_frames: u64, + tx_multicast_frames: u64, + tx_crc_error_frames: u64, + tx_total_bytes: u64, + collisions: u64, + unsupported_protocol: u64, + rx_duplicated_frames: u64, + rx_decryptError_frames: u64, + tx_error_frames: u64, + tx_retry_frames: u64, +}; + +pub const SimpleNetworkInterruptStatus = packed struct { + receive_interrupt: bool, + transmit_interrupt: bool, + command_interrupt: bool, + software_interrupt: bool, + _pad: u28, +}; diff --git a/lib/std/os/uefi/protocols/udp6_protocol.zig b/lib/std/os/uefi/protocols/udp6_protocol.zig @@ -0,0 +1,112 @@ +const uefi = @import("std").os.uefi; +const Guid = uefi.Guid; +const Event = uefi.Event; +const Time = uefi.Time; +const Ip6ModeData = uefi.protocols.Ip6ModeData; +const Ip6Address = uefi.protocols.Ip6Address; +const ManagedNetworkConfigData = uefi.protocols.ManagedNetworkConfigData; +const SimpleNetworkMode = uefi.protocols.SimpleNetworkMode; + +pub const Udp6Protocol = extern struct { + _get_mode_data: extern fn (*const Udp6Protocol, ?*Udp6ConfigData, ?*Ip6ModeData, ?*ManagedNetworkConfigData, ?*SimpleNetworkMode) usize, + _configure: extern fn (*const Udp6Protocol, ?*const Udp6ConfigData) usize, + _groups: extern fn (*const Udp6Protocol, bool, ?*const Ip6Address) usize, + _transmit: extern fn (*const Udp6Protocol, *Udp6CompletionToken) usize, + _receive: extern fn (*const Udp6Protocol, *Udp6CompletionToken) usize, + _cancel: extern fn (*const Udp6Protocol, ?*Udp6CompletionToken) usize, + _poll: extern fn (*const Udp6Protocol) usize, + + pub fn getModeData(self: *const Udp6Protocol, udp6_config_data: ?*Udp6ConfigData, ip6_mode_data: ?*Ip6ModeData, mnp_config_data: ?*ManagedNetworkConfigData, snp_mode_data: ?*SimpleNetworkMode) usize { + return self._get_mode_data(self, udp6_config_data, ip6_mode_data, mnp_config_data, snp_mode_data); + } + + pub fn configure(self: *const Udp6Protocol, udp6_config_data: ?*const Udp6ConfigData) usize { + return self._configure(self, udp6_config_data); + } + + pub fn groups(self: *const Udp6Protocol, join_flag: bool, multicast_address: ?*const Ip6Address) usize { + return self._groups(self, join_flag, multicast_address); + } + + pub fn transmit(self: *const Udp6Protocol, token: *Udp6CompletionToken) usize { + return self._transmit(self, token); + } + + pub fn receive(self: *const Udp6Protocol, token: *Udp6CompletionToken) usize { + return self._receive(self, token); + } + + pub fn cancel(self: *const Udp6Protocol, token: ?*Udp6CompletionToken) usize { + return self._cancel(self, token); + } + + pub fn poll(self: *const Udp6Protocol) usize { + return self._poll(self); + } + + pub const guid align(8) = uefi.Guid{ + .time_low = 0x4f948815, + .time_mid = 0xb4b9, + .time_high_and_version = 0x43cb, + .clock_seq_high_and_reserved = 0x8a, + .clock_seq_low = 0x33, + .node = [_]u8{ 0x90, 0xe0, 0x60, 0xb3, 0x49, 0x55 }, + }; +}; + +pub const Udp6ConfigData = extern struct { + accept_promiscuous: bool, + accept_any_port: bool, + allow_duplicate_port: bool, + traffic_class: u8, + hop_limit: u8, + receive_timeout: u32, + transmit_timeout: u32, + station_address: Ip6Address, + station_port: u16, + remote_address: Ip6Address, + remote_port: u16, +}; + +pub const Udp6CompletionToken = extern struct { + event: Event, + status: usize, + packet: extern union { + RxData: *Udp6ReceiveData, + TxData: *Udp6TransmitData, + }, +}; + +pub const Udp6ReceiveData = extern struct { + timestamp: Time, + recycle_signal: Event, + udp6_session: Udp6SessionData, + data_length: u32, + fragment_count: u32, + + pub fn getFragments(self: *Udp6ReceiveData) []Udp6FragmentData { + return @ptrCast([*]Udp6FragmentData, @ptrCast([*]u8, self) + @sizeOf(Udp6ReceiveData))[0..self.fragment_count]; + } +}; + +pub const Udp6TransmitData = extern struct { + udp6_session_data: ?*Udp6SessionData, + data_length: u32, + fragment_count: u32, + + pub fn getFragments(self: *Udp6TransmitData) []Udp6FragmentData { + return @ptrCast([*]Udp6FragmentData, @ptrCast([*]u8, self) + @sizeOf(Udp6TransmitData))[0..self.fragment_count]; + } +}; + +pub const Udp6SessionData = extern struct { + source_address: Ip6Address, + source_port: u16, + destination_address: Ip6Address, + destination_port: u16, +}; + +pub const Udp6FragmentData = extern struct { + fragment_length: u32, + fragment_buffer: [*]u8, +}; diff --git a/lib/std/os/uefi/protocols/udp6_service_binding_protocol.zig b/lib/std/os/uefi/protocols/udp6_service_binding_protocol.zig @@ -0,0 +1,25 @@ +const uefi = @import("std").os.uefi; +const Handle = uefi.Handle; +const Guid = uefi.Guid; + +pub const Udp6ServiceBindingProtocol = extern struct { + _create_child: extern fn (*const Udp6ServiceBindingProtocol, *?Handle) usize, + _destroy_child: extern fn (*const Udp6ServiceBindingProtocol, Handle) usize, + + pub fn createChild(self: *const Udp6ServiceBindingProtocol, handle: *?Handle) usize { + return self._create_child(self, handle); + } + + pub fn destroyChild(self: *const Udp6ServiceBindingProtocol, handle: Handle) usize { + return self._destroy_child(self, handle); + } + + pub const guid align(8) = Guid{ + .time_low = 0x66ed4721, + .time_mid = 0x3c98, + .time_high_and_version = 0x4d3e, + .clock_seq_high_and_reserved = 0x81, + .clock_seq_low = 0xe3, + .node = [_]u8{ 0xd0, 0x3d, 0xd3, 0x9a, 0x72, 0x54 }, + }; +}; diff --git a/lib/std/os/uefi/tables.zig b/lib/std/os/uefi/tables.zig @@ -1,8 +1,11 @@ pub const BootServices = @import("tables/boot_services.zig").BootServices; pub const ConfigurationTable = @import("tables/configuration_table.zig").ConfigurationTable; pub const global_variable align(8) = @import("tables/runtime_services.zig").global_variable; +pub const LocateSearchType = @import("tables/boot_services.zig").LocateSearchType; pub const MemoryDescriptor = @import("tables/boot_services.zig").MemoryDescriptor; pub const MemoryType = @import("tables/boot_services.zig").MemoryType; +pub const OpenProtocolAttributes = @import("tables/boot_services.zig").OpenProtocolAttributes; +pub const ProtocolInformationEntry = @import("tables/boot_services.zig").ProtocolInformationEntry; pub const ResetType = @import("tables/runtime_services.zig").ResetType; pub const RuntimeServices = @import("tables/runtime_services.zig").RuntimeServices; pub const SystemTable = @import("tables/system_table.zig").SystemTable; diff --git a/lib/std/os/uefi/tables/boot_services.zig b/lib/std/os/uefi/tables/boot_services.zig @@ -3,6 +3,7 @@ const Event = uefi.Event; const Guid = uefi.Guid; const Handle = uefi.Handle; const TableHeader = uefi.tables.TableHeader; +const DevicePathProtocol = uefi.protocols.DevicePathProtocol; /// Boot services are services provided by the system's firmware until the operating system takes /// over control over the hardware by calling exitBootServices. @@ -17,56 +18,96 @@ const TableHeader = uefi.tables.TableHeader; /// As the boot_services table may grow with new UEFI versions, it is important to check hdr.header_size. pub const BootServices = extern struct { hdr: TableHeader, + raiseTpl: usize, // TODO restoreTpl: usize, // TODO allocatePages: usize, // TODO freePages: usize, // TODO + /// Returns the current memory map. getMemoryMap: extern fn (*usize, [*]MemoryDescriptor, *usize, *usize, *u32) usize, + /// Allocates pool memory. allocatePool: extern fn (MemoryType, usize, *align(8) [*]u8) usize, - freePool: usize, // TODO + + /// Returns pool memory to the system. + freePool: extern fn ([*]align(8) u8) usize, + /// Creates an event. - createEvent: extern fn (u32, usize, ?extern fn (Event, ?*const c_void) void, ?*const c_void, *Event) usize, + createEvent: extern fn (u32, usize, ?extern fn (Event, ?*c_void) void, ?*const c_void, *Event) usize, + /// Sets the type of timer and the trigger time for a timer event. setTimer: extern fn (Event, TimerDelay, u64) usize, + /// Stops execution until an event is signaled. waitForEvent: extern fn (usize, [*]const Event, *usize) usize, + /// Signals an event. signalEvent: extern fn (Event) usize, + /// Closes an event. closeEvent: extern fn (Event) usize, - checkEvent: usize, // TODO + + /// Checks whether an event is in the signaled state. + checkEvent: extern fn (Event) usize, + installProtocolInterface: usize, // TODO reinstallProtocolInterface: usize, // TODO uninstallProtocolInterface: usize, // TODO - handleProtocol: usize, // TODO + + /// Queries a handle to determine if it supports a specified protocol. + handleProtocol: extern fn (Handle, *align(8) const Guid, *?*c_void) usize, + reserved: *c_void, + registerProtocolNotify: usize, // TODO locateHandle: usize, // TODO locateDevicePath: usize, // TODO installConfigurationTable: usize, // TODO - imageLoad: usize, // TODO - imageStart: usize, // TODO + + /// Loads an EFI image into memory. + loadImage: extern fn (bool, Handle, ?*const DevicePathProtocol, ?[*]const u8, usize, *?Handle) usize, + + /// Transfers control to a loaded image's entry point. + startImage: extern fn (Handle, ?*usize, ?*[*]u16) usize, + /// Terminates a loaded EFI image and returns control to boot services. exit: extern fn (Handle, usize, usize, ?*const c_void) usize, - imageUnload: usize, // TODO + + /// Unloads an image. + unloadImage: extern fn (Handle) usize, + /// Terminates all boot services. exitBootServices: extern fn (Handle, usize) usize, + getNextMonotonicCount: usize, // TODO + /// Induces a fine-grained stall. stall: extern fn (usize) usize, + /// Sets the system's watchdog timer. setWatchdogTimer: extern fn (usize, u64, usize, ?[*]const u16) usize, + connectController: usize, // TODO disconnectController: usize, // TODO - openProtocol: usize, // TODO - closeProtocol: usize, // TODO - openProtocolInformation: usize, // TODO + + /// Queries a handle to determine if it supports a specified protocol. + openProtocol: extern fn (Handle, *align(8) const Guid, *?*c_void, ?Handle, ?Handle, OpenProtocolAttributes) usize, + + /// Closes a protocol on a handle that was opened using openProtocol(). + closeProtocol: extern fn (Handle, *align(8) const Guid, Handle, ?Handle) usize, + + /// Retrieves the list of agents that currently have a protocol interface opened. + openProtocolInformation: extern fn (Handle, *align(8) const Guid, *[*]ProtocolInformationEntry, *usize) usize, + protocolsPerHandle: usize, // TODO - locateHandleBuffer: usize, // TODO + + /// Returns an array of handles that support the requested protocol in a buffer allocated from pool. + locateHandleBuffer: extern fn (LocateSearchType, ?*align(8) const Guid, ?*const c_void, *usize, *[*]Handle) usize, + /// Returns the first protocol instance that matches the given protocol. locateProtocol: extern fn (*align(8) const Guid, ?*const c_void, *?*c_void) usize, + installMultipleProtocolInterfaces: usize, // TODO uninstallMultipleProtocolInterfaces: usize, // TODO calculateCrc32: usize, // TODO @@ -138,3 +179,26 @@ pub const MemoryDescriptor = extern struct { memory_runtime: bool, }, }; + +pub const LocateSearchType = extern enum(u32) { + AllHandles, + ByRegisterNotify, + ByProtocol, +}; + +pub const OpenProtocolAttributes = packed struct { + by_handle_protocol: bool, + get_protocol: bool, + test_protocol: bool, + by_child_controller: bool, + by_driver: bool, + exclusive: bool, + _pad: u26, +}; + +pub const ProtocolInformationEntry = extern struct { + agent_handle: ?Handle, + controller_handle: ?Handle, + attributes: OpenProtocolAttributes, + open_count: u32, +}; diff --git a/lib/std/os/uefi/tables/runtime_services.zig b/lib/std/os/uefi/tables/runtime_services.zig @@ -14,22 +14,30 @@ const TimeCapabilities = uefi.TimeCapabilities; /// Some functions may not be called while other functions are running. pub const RuntimeServices = extern struct { hdr: TableHeader, + /// Returns the current time and date information, and the time-keeping capabilities of the hardware platform. getTime: extern fn (*uefi.Time, ?*TimeCapabilities) usize, + setTime: usize, // TODO getWakeupTime: usize, // TODO setWakeupTime: usize, // TODO setVirtualAddressMap: usize, // TODO convertPointer: usize, // TODO + /// Returns the value of a variable. getVariable: extern fn ([*]const u16, *align(8) const Guid, ?*u32, *usize, ?*c_void) usize, + /// Enumerates the current variable names. getNextVariableName: extern fn (*usize, [*]u16, *align(8) Guid) usize, + /// Sets the value of a variable. setVariable: extern fn ([*]const u16, *align(8) const Guid, u32, usize, *c_void) usize, + getNextHighMonotonicCount: usize, // TODO + /// Resets the entire platform. resetSystem: extern fn (ResetType, usize, usize, ?*const c_void) noreturn, + updateCapsule: usize, // TODO queryCapsuleCapabilities: usize, // TODO queryVariableInfo: usize, // TODO diff --git a/lib/std/os/uefi/tables/system_table.zig b/lib/std/os/uefi/tables/system_table.zig @@ -17,6 +17,7 @@ const TableHeader = uefi.tables.TableHeader; /// hdr.crc32 must be recomputed. pub const SystemTable = extern struct { hdr: TableHeader, + /// A null-terminated string that identifies the vendor that produces the system firmware of the platform. firmware_vendor: [*]u16, firmware_revision: u32, diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig @@ -16,6 +16,7 @@ pub const kernel32 = @import("windows/kernel32.zig"); pub const ntdll = @import("windows/ntdll.zig"); pub const ole32 = @import("windows/ole32.zig"); pub const shell32 = @import("windows/shell32.zig"); +pub const ws2_32 = @import("windows/ws2_32.zig"); pub usingnamespace @import("windows/bits.zig"); @@ -96,6 +97,42 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C } } +pub fn DeviceIoControl( + h: HANDLE, + ioControlCode: DWORD, + in: ?[]const u8, + out: ?[]u8, + overlapped: ?*OVERLAPPED, +) !DWORD { + var bytes: DWORD = undefined; + if (kernel32.DeviceIoControl( + h, + ioControlCode, + if (in) |i| i.ptr else null, + if (in) |i| @intCast(u32, i.len) else 0, + if (out) |o| o.ptr else null, + if (out) |o| @intCast(u32, o.len) else 0, + &bytes, + overlapped, + ) == 0) { + switch (kernel32.GetLastError()) { + else => |err| return unexpectedError(err), + } + } + return bytes; +} + +pub fn GetOverlappedResult(h: HANDLE, overlapped: *OVERLAPPED, wait: bool) !DWORD { + var bytes: DWORD = undefined; + if (kernel32.GetOverlappedResult(h, overlapped, &bytes, wait) == 0) { + switch (kernel32.GetLastError()) { + ERROR_IO_INCOMPLETE => if (!wait) return error.WouldBlock else unreachable, + else => |err| return unexpectedError(err), + } + } + return bytes; +} + pub const SetHandleInformationError = error{Unexpected}; pub fn SetHandleInformation(h: HANDLE, mask: DWORD, flags: DWORD) SetHandleInformationError!void { @@ -262,7 +299,7 @@ pub const ReadFileError = error{Unexpected}; pub fn ReadFile(in_hFile: HANDLE, buffer: []u8) ReadFileError!usize { var index: usize = 0; while (index < buffer.len) { - const want_read_count = @intCast(DWORD, math.min(DWORD(maxInt(DWORD)), buffer.len - index)); + const want_read_count = @intCast(DWORD, math.min(@as(DWORD, maxInt(DWORD)), buffer.len - index)); var amt_read: DWORD = undefined; if (kernel32.ReadFile(in_hFile, buffer.ptr + index, want_read_count, &amt_read, null) == 0) { switch (kernel32.GetLastError()) { @@ -571,6 +608,74 @@ pub fn GetFileAttributesW(lpFileName: [*]const u16) GetFileAttributesError!DWORD return rc; } +pub fn WSAStartup(majorVersion: u8, minorVersion: u8) !ws2_32.WSADATA { + var wsadata: ws2_32.WSADATA = undefined; + return switch (ws2_32.WSAStartup((@as(WORD, minorVersion) << 8) | majorVersion, &wsadata)) { + 0 => wsadata, + else => |err| unexpectedWSAError(err), + }; +} + +pub fn WSACleanup() !void { + return switch (ws2_32.WSACleanup()) { + 0 => {}, + ws2_32.SOCKET_ERROR => switch (ws2_32.WSAGetLastError()) { + else => |err| return unexpectedWSAError(err), + }, + else => unreachable, + }; +} + +pub fn WSASocketW( + af: i32, + socket_type: i32, + protocol: i32, + protocolInfo: ?*ws2_32.WSAPROTOCOL_INFOW, + g: ws2_32.GROUP, + dwFlags: DWORD, +) !ws2_32.SOCKET { + const rc = ws2_32.WSASocketW(af, socket_type, protocol, protocolInfo, g, dwFlags); + if (rc == ws2_32.INVALID_SOCKET) { + switch (ws2_32.WSAGetLastError()) { + ws2_32.WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, + ws2_32.WSAEMFILE => return error.ProcessFdQuotaExceeded, + ws2_32.WSAENOBUFS => return error.SystemResources, + ws2_32.WSAEPROTONOSUPPORT => return error.ProtocolNotSupported, + else => |err| return unexpectedWSAError(err), + } + } + return rc; +} + +pub fn WSAIoctl( + s: ws2_32.SOCKET, + dwIoControlCode: DWORD, + inBuffer: ?[]const u8, + outBuffer: []u8, + overlapped: ?*ws2_32.WSAOVERLAPPED, + completionRoutine: ?*ws2_32.WSAOVERLAPPED_COMPLETION_ROUTINE, +) !DWORD { + var bytes: DWORD = undefined; + switch (ws2_32.WSAIoctl( + s, + dwIoControlCode, + if (inBuffer) |i| i.ptr else null, + if (inBuffer) |i| @intCast(DWORD, i.len) else 0, + outBuffer.ptr, + @intCast(DWORD, outBuffer.len), + &bytes, + overlapped, + completionRoutine, + )) { + 0 => {}, + ws2_32.SOCKET_ERROR => switch (ws2_32.WSAGetLastError()) { + else => |err| return unexpectedWSAError(err), + }, + else => unreachable, + } + return bytes; +} + const GetModuleFileNameError = error{Unexpected}; pub fn GetModuleFileNameW(hModule: ?HMODULE, buf_ptr: [*]u16, buf_len: DWORD) GetModuleFileNameError![]u16 { @@ -801,7 +906,7 @@ pub fn toSysTime(ns: i64) i64 { } pub fn fileTimeToNanoSeconds(ft: FILETIME) i64 { - const hns = @bitCast(i64, (u64(ft.dwHighDateTime) << 32) | ft.dwLowDateTime); + const hns = @bitCast(i64, (@as(u64, ft.dwHighDateTime) << 32) | ft.dwLowDateTime); return fromSysTime(hns); } @@ -822,6 +927,24 @@ pub fn sliceToPrefixedFileW(s: []const u8) ![PATH_MAX_WIDE + 1]u16 { return sliceToPrefixedSuffixedFileW(s, [_]u16{0}); } +/// Assumes an absolute path. +pub fn wToPrefixedFileW(s: []const u16) ![PATH_MAX_WIDE + 1]u16 { + // TODO https://github.com/ziglang/zig/issues/2765 + var result: [PATH_MAX_WIDE + 1]u16 = undefined; + + const start_index = if (mem.startsWith(u16, s, [_]u16{'\\', '?'})) 0 else blk: { + const prefix = [_]u16{ '\\', '?', '?', '\\' }; + mem.copy(u16, result[0..], prefix); + break :blk prefix.len; + }; + const end_index = start_index + s.len; + if (end_index + 1 > result.len) return error.NameTooLong; + mem.copy(u16, result[start_index..], s); + result[end_index] = 0; + return result; + +} + pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) ![PATH_MAX_WIDE + suffix.len]u16 { // TODO https://github.com/ziglang/zig/issues/2765 var result: [PATH_MAX_WIDE + suffix.len]u16 = undefined; @@ -843,7 +966,6 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) break :blk prefix.len; }; const end_index = start_index + try std.unicode.utf8ToUtf16Le(result[start_index..], s); - assert(end_index <= result.len); if (end_index + suffix.len > result.len) return error.NameTooLong; mem.copy(u16, result[end_index..], suffix); return result; @@ -868,6 +990,10 @@ pub fn unexpectedError(err: DWORD) std.os.UnexpectedError { return error.Unexpected; } +pub fn unexpectedWSAError(err: c_int) std.os.UnexpectedError { + return unexpectedError(@intCast(DWORD, err)); +} + /// Call this when you made a windows NtDll call /// and you get an unexpected status. pub fn unexpectedStatus(status: NTSTATUS) std.os.UnexpectedError { diff --git a/lib/std/os/windows/bits.zig b/lib/std/os/windows/bits.zig @@ -67,9 +67,116 @@ pub const va_list = *@OpaqueType(); pub const TRUE = 1; pub const FALSE = 0; +pub const DEVICE_TYPE = ULONG; +pub const FILE_DEVICE_BEEP: DEVICE_TYPE = 0x0001; +pub const FILE_DEVICE_CD_ROM: DEVICE_TYPE = 0x0002; +pub const FILE_DEVICE_CD_ROM_FILE_SYSTEM: DEVICE_TYPE = 0x0003; +pub const FILE_DEVICE_CONTROLLER: DEVICE_TYPE = 0x0004; +pub const FILE_DEVICE_DATALINK: DEVICE_TYPE = 0x0005; +pub const FILE_DEVICE_DFS: DEVICE_TYPE = 0x0006; +pub const FILE_DEVICE_DISK: DEVICE_TYPE = 0x0007; +pub const FILE_DEVICE_DISK_FILE_SYSTEM: DEVICE_TYPE = 0x0008; +pub const FILE_DEVICE_FILE_SYSTEM: DEVICE_TYPE = 0x0009; +pub const FILE_DEVICE_INPORT_PORT: DEVICE_TYPE = 0x000a; +pub const FILE_DEVICE_KEYBOARD: DEVICE_TYPE = 0x000b; +pub const FILE_DEVICE_MAILSLOT: DEVICE_TYPE = 0x000c; +pub const FILE_DEVICE_MIDI_IN: DEVICE_TYPE = 0x000d; +pub const FILE_DEVICE_MIDI_OUT: DEVICE_TYPE = 0x000e; +pub const FILE_DEVICE_MOUSE: DEVICE_TYPE = 0x000f; +pub const FILE_DEVICE_MULTI_UNC_PROVIDER: DEVICE_TYPE = 0x0010; +pub const FILE_DEVICE_NAMED_PIPE: DEVICE_TYPE = 0x0011; +pub const FILE_DEVICE_NETWORK: DEVICE_TYPE = 0x0012; +pub const FILE_DEVICE_NETWORK_BROWSER: DEVICE_TYPE = 0x0013; +pub const FILE_DEVICE_NETWORK_FILE_SYSTEM: DEVICE_TYPE = 0x0014; +pub const FILE_DEVICE_NULL: DEVICE_TYPE = 0x0015; +pub const FILE_DEVICE_PARALLEL_PORT: DEVICE_TYPE = 0x0016; +pub const FILE_DEVICE_PHYSICAL_NETCARD: DEVICE_TYPE = 0x0017; +pub const FILE_DEVICE_PRINTER: DEVICE_TYPE = 0x0018; +pub const FILE_DEVICE_SCANNER: DEVICE_TYPE = 0x0019; +pub const FILE_DEVICE_SERIAL_MOUSE_PORT: DEVICE_TYPE = 0x001a; +pub const FILE_DEVICE_SERIAL_PORT: DEVICE_TYPE = 0x001b; +pub const FILE_DEVICE_SCREEN: DEVICE_TYPE = 0x001c; +pub const FILE_DEVICE_SOUND: DEVICE_TYPE = 0x001d; +pub const FILE_DEVICE_STREAMS: DEVICE_TYPE = 0x001e; +pub const FILE_DEVICE_TAPE: DEVICE_TYPE = 0x001f; +pub const FILE_DEVICE_TAPE_FILE_SYSTEM: DEVICE_TYPE = 0x0020; +pub const FILE_DEVICE_TRANSPORT: DEVICE_TYPE = 0x0021; +pub const FILE_DEVICE_UNKNOWN: DEVICE_TYPE = 0x0022; +pub const FILE_DEVICE_VIDEO: DEVICE_TYPE = 0x0023; +pub const FILE_DEVICE_VIRTUAL_DISK: DEVICE_TYPE = 0x0024; +pub const FILE_DEVICE_WAVE_IN: DEVICE_TYPE = 0x0025; +pub const FILE_DEVICE_WAVE_OUT: DEVICE_TYPE = 0x0026; +pub const FILE_DEVICE_8042_PORT: DEVICE_TYPE = 0x0027; +pub const FILE_DEVICE_NETWORK_REDIRECTOR: DEVICE_TYPE = 0x0028; +pub const FILE_DEVICE_BATTERY: DEVICE_TYPE = 0x0029; +pub const FILE_DEVICE_BUS_EXTENDER: DEVICE_TYPE = 0x002a; +pub const FILE_DEVICE_MODEM: DEVICE_TYPE = 0x002b; +pub const FILE_DEVICE_VDM: DEVICE_TYPE = 0x002c; +pub const FILE_DEVICE_MASS_STORAGE: DEVICE_TYPE = 0x002d; +pub const FILE_DEVICE_SMB: DEVICE_TYPE = 0x002e; +pub const FILE_DEVICE_KS: DEVICE_TYPE = 0x002f; +pub const FILE_DEVICE_CHANGER: DEVICE_TYPE = 0x0030; +pub const FILE_DEVICE_SMARTCARD: DEVICE_TYPE = 0x0031; +pub const FILE_DEVICE_ACPI: DEVICE_TYPE = 0x0032; +pub const FILE_DEVICE_DVD: DEVICE_TYPE = 0x0033; +pub const FILE_DEVICE_FULLSCREEN_VIDEO: DEVICE_TYPE = 0x0034; +pub const FILE_DEVICE_DFS_FILE_SYSTEM: DEVICE_TYPE = 0x0035; +pub const FILE_DEVICE_DFS_VOLUME: DEVICE_TYPE = 0x0036; +pub const FILE_DEVICE_SERENUM: DEVICE_TYPE = 0x0037; +pub const FILE_DEVICE_TERMSRV: DEVICE_TYPE = 0x0038; +pub const FILE_DEVICE_KSEC: DEVICE_TYPE = 0x0039; +pub const FILE_DEVICE_FIPS: DEVICE_TYPE = 0x003a; +pub const FILE_DEVICE_INFINIBAND: DEVICE_TYPE = 0x003b; +// TODO: missing values? +pub const FILE_DEVICE_VMBUS: DEVICE_TYPE = 0x003e; +pub const FILE_DEVICE_CRYPT_PROVIDER: DEVICE_TYPE = 0x003f; +pub const FILE_DEVICE_WPD: DEVICE_TYPE = 0x0040; +pub const FILE_DEVICE_BLUETOOTH: DEVICE_TYPE = 0x0041; +pub const FILE_DEVICE_MT_COMPOSITE: DEVICE_TYPE = 0x0042; +pub const FILE_DEVICE_MT_TRANSPORT: DEVICE_TYPE = 0x0043; +pub const FILE_DEVICE_BIOMETRIC: DEVICE_TYPE = 0x0044; +pub const FILE_DEVICE_PMI: DEVICE_TYPE = 0x0045; +pub const FILE_DEVICE_EHSTOR: DEVICE_TYPE = 0x0046; +pub const FILE_DEVICE_DEVAPI: DEVICE_TYPE = 0x0047; +pub const FILE_DEVICE_GPIO: DEVICE_TYPE = 0x0048; +pub const FILE_DEVICE_USBEX: DEVICE_TYPE = 0x0049; +pub const FILE_DEVICE_CONSOLE: DEVICE_TYPE = 0x0050; +pub const FILE_DEVICE_NFP: DEVICE_TYPE = 0x0051; +pub const FILE_DEVICE_SYSENV: DEVICE_TYPE = 0x0052; +pub const FILE_DEVICE_VIRTUAL_BLOCK: DEVICE_TYPE = 0x0053; +pub const FILE_DEVICE_POINT_OF_SERVICE: DEVICE_TYPE = 0x0054; +pub const FILE_DEVICE_STORAGE_REPLICATION: DEVICE_TYPE = 0x0055; +pub const FILE_DEVICE_TRUST_ENV: DEVICE_TYPE = 0x0056; +pub const FILE_DEVICE_UCM: DEVICE_TYPE = 0x0057; +pub const FILE_DEVICE_UCMTCPCI: DEVICE_TYPE = 0x0058; +pub const FILE_DEVICE_PERSISTENT_MEMORY: DEVICE_TYPE = 0x0059; +pub const FILE_DEVICE_NVDIMM: DEVICE_TYPE = 0x005a; +pub const FILE_DEVICE_HOLOGRAPHIC: DEVICE_TYPE = 0x005b; +pub const FILE_DEVICE_SDFXHCI: DEVICE_TYPE = 0x005c; + +/// https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/buffer-descriptions-for-i-o-control-codes +pub const TransferType = enum(u2) { + METHOD_BUFFERED = 0, + METHOD_IN_DIRECT = 1, + METHOD_OUT_DIRECT = 2, + METHOD_NEITHER = 3, +}; + +pub const FILE_ANY_ACCESS = 0; +pub const FILE_READ_ACCESS = 1; +pub const FILE_WRITE_ACCESS = 2; + +/// https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/defining-i-o-control-codes +pub fn CTL_CODE(deviceType: u16, function: u12, method: TransferType, access: u2) DWORD { + return (@as(DWORD, deviceType) << 16) | + (@as(DWORD, access) << 14) | + (@as(DWORD, function) << 2) | + @enumToInt(method); +} + pub const INVALID_HANDLE_VALUE = @intToPtr(HANDLE, maxInt(usize)); -pub const INVALID_FILE_ATTRIBUTES = DWORD(maxInt(DWORD)); +pub const INVALID_FILE_ATTRIBUTES = @as(DWORD, maxInt(DWORD)); pub const FILE_ALL_INFORMATION = extern struct { BasicInformation: FILE_BASIC_INFORMATION, @@ -571,16 +678,16 @@ pub const KF_FLAG_SIMPLE_IDLIST = 256; pub const KF_FLAG_ALIAS_ONLY = -2147483648; pub const S_OK = 0; -pub const E_NOTIMPL = @bitCast(c_long, c_ulong(0x80004001)); -pub const E_NOINTERFACE = @bitCast(c_long, c_ulong(0x80004002)); -pub const E_POINTER = @bitCast(c_long, c_ulong(0x80004003)); -pub const E_ABORT = @bitCast(c_long, c_ulong(0x80004004)); -pub const E_FAIL = @bitCast(c_long, c_ulong(0x80004005)); -pub const E_UNEXPECTED = @bitCast(c_long, c_ulong(0x8000FFFF)); -pub const E_ACCESSDENIED = @bitCast(c_long, c_ulong(0x80070005)); -pub const E_HANDLE = @bitCast(c_long, c_ulong(0x80070006)); -pub const E_OUTOFMEMORY = @bitCast(c_long, c_ulong(0x8007000E)); -pub const E_INVALIDARG = @bitCast(c_long, c_ulong(0x80070057)); +pub const E_NOTIMPL = @bitCast(c_long, @as(c_ulong, 0x80004001)); +pub const E_NOINTERFACE = @bitCast(c_long, @as(c_ulong, 0x80004002)); +pub const E_POINTER = @bitCast(c_long, @as(c_ulong, 0x80004003)); +pub const E_ABORT = @bitCast(c_long, @as(c_ulong, 0x80004004)); +pub const E_FAIL = @bitCast(c_long, @as(c_ulong, 0x80004005)); +pub const E_UNEXPECTED = @bitCast(c_long, @as(c_ulong, 0x8000FFFF)); +pub const E_ACCESSDENIED = @bitCast(c_long, @as(c_ulong, 0x80070005)); +pub const E_HANDLE = @bitCast(c_long, @as(c_ulong, 0x80070006)); +pub const E_OUTOFMEMORY = @bitCast(c_long, @as(c_ulong, 0x8007000E)); +pub const E_INVALIDARG = @bitCast(c_long, @as(c_ulong, 0x80070057)); pub const FILE_FLAG_BACKUP_SEMANTICS = 0x02000000; pub const FILE_FLAG_DELETE_ON_CLOSE = 0x04000000; @@ -873,4 +980,4 @@ pub const CURDIR = extern struct { Handle: HANDLE, }; -pub const DUPLICATE_SAME_ACCESS = 2; -\ No newline at end of file +pub const DUPLICATE_SAME_ACCESS = 2; diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig @@ -45,6 +45,17 @@ pub extern "kernel32" stdcallcc fn CreateIoCompletionPort(FileHandle: HANDLE, Ex pub extern "kernel32" stdcallcc fn CreateThread(lpThreadAttributes: ?LPSECURITY_ATTRIBUTES, dwStackSize: SIZE_T, lpStartAddress: LPTHREAD_START_ROUTINE, lpParameter: ?LPVOID, dwCreationFlags: DWORD, lpThreadId: ?LPDWORD) ?HANDLE; +pub extern "kernel32" stdcallcc fn DeviceIoControl( + h: HANDLE, + dwIoControlCode: DWORD, + lpInBuffer: ?*const c_void, + nInBufferSize: DWORD, + lpOutBuffer: ?LPVOID, + nOutBufferSize: DWORD, + lpBytesReturned: LPDWORD, + lpOverlapped: ?*OVERLAPPED, +) BOOL; + pub extern "kernel32" stdcallcc fn DeleteFileW(lpFileName: [*]const u16) BOOL; pub extern "kernel32" stdcallcc fn DuplicateHandle(hSourceProcessHandle: HANDLE, hSourceHandle: HANDLE, hTargetProcessHandle: HANDLE, lpTargetHandle: *HANDLE, dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwOptions: DWORD) BOOL; @@ -184,6 +195,8 @@ pub extern "kernel32" stdcallcc fn SetHandleInformation(hObject: HANDLE, dwMask: pub extern "kernel32" stdcallcc fn Sleep(dwMilliseconds: DWORD) void; +pub extern "kernel32" stdcallcc fn SwitchToThread() BOOL; + pub extern "kernel32" stdcallcc fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) BOOL; pub extern "kernel32" stdcallcc fn TlsAlloc() DWORD; diff --git a/lib/std/os/windows/ntdll.zig b/lib/std/os/windows/ntdll.zig @@ -21,6 +21,18 @@ pub extern "NtDll" stdcallcc fn NtCreateFile( EaBuffer: ?*c_void, EaLength: ULONG, ) NTSTATUS; +pub extern "NtDll" stdcallcc fn NtDeviceIoControlFile( + FileHandle: HANDLE, + Event: ?HANDLE, + ApcRoutine: ?*IO_APC_ROUTINE, + ApcContext: usize, + IoStatusBlock: *IO_STATUS_BLOCK, + IoControlCode: ULONG, + InputBuffer: ?*const c_void, + InputBufferLength: ULONG, + OutputBuffer: ?PVOID, + OutputBufferLength: ULONG, +) NTSTATUS; pub extern "NtDll" stdcallcc fn NtClose(Handle: HANDLE) NTSTATUS; pub extern "NtDll" stdcallcc fn RtlDosPathNameToNtPathName_U( DosPathName: [*]const u16, @@ -43,3 +55,21 @@ pub extern "NtDll" stdcallcc fn NtQueryDirectoryFile( FileName: ?*UNICODE_STRING, RestartScan: BOOLEAN, ) NTSTATUS; +pub extern "NtDll" stdcallcc fn NtCreateKeyedEvent( + KeyedEventHandle: *HANDLE, + DesiredAccess: ACCESS_MASK, + ObjectAttributes: ?PVOID, + Flags: ULONG, +) NTSTATUS; +pub extern "NtDll" stdcallcc fn NtReleaseKeyedEvent( + EventHandle: HANDLE, + Key: *const c_void, + Alertable: BOOLEAN, + Timeout: ?*LARGE_INTEGER, +) NTSTATUS; +pub extern "NtDll" stdcallcc fn NtWaitForKeyedEvent( + EventHandle: HANDLE, + Key: *const c_void, + Alertable: BOOLEAN, + Timeout: ?*LARGE_INTEGER, +) NTSTATUS; diff --git a/lib/std/os/windows/status.zig b/lib/std/os/windows/status.zig @@ -1,13 +1,1663 @@ /// The operation completed successfully. pub const SUCCESS = 0x00000000; -/// The data was too large to fit into the specified buffer. +pub const WAIT_0 = 0x00000000; +pub const WAIT_1 = 0x00000001; +pub const WAIT_2 = 0x00000002; +pub const WAIT_3 = 0x00000003; +pub const WAIT_63 = 0x0000003F; +pub const ABANDONED = 0x00000080; +pub const ABANDONED_WAIT_0 = 0x00000080; +pub const ABANDONED_WAIT_63 = 0x000000BF; +pub const USER_APC = 0x000000C0; +pub const ALERTED = 0x00000101; +pub const TIMEOUT = 0x00000102; +pub const PENDING = 0x00000103; +pub const REPARSE = 0x00000104; +pub const MORE_ENTRIES = 0x00000105; +pub const NOT_ALL_ASSIGNED = 0x00000106; +pub const SOME_NOT_MAPPED = 0x00000107; +pub const OPLOCK_BREAK_IN_PROGRESS = 0x00000108; +pub const VOLUME_MOUNTED = 0x00000109; +pub const RXACT_COMMITTED = 0x0000010A; +pub const NOTIFY_CLEANUP = 0x0000010B; +pub const NOTIFY_ENUM_DIR = 0x0000010C; +pub const NO_QUOTAS_FOR_ACCOUNT = 0x0000010D; +pub const PRIMARY_TRANSPORT_CONNECT_FAILED = 0x0000010E; +pub const PAGE_FAULT_TRANSITION = 0x00000110; +pub const PAGE_FAULT_DEMAND_ZERO = 0x00000111; +pub const PAGE_FAULT_COPY_ON_WRITE = 0x00000112; +pub const PAGE_FAULT_GUARD_PAGE = 0x00000113; +pub const PAGE_FAULT_PAGING_FILE = 0x00000114; +pub const CACHE_PAGE_LOCKED = 0x00000115; +pub const CRASH_DUMP = 0x00000116; +pub const BUFFER_ALL_ZEROS = 0x00000117; +pub const REPARSE_OBJECT = 0x00000118; +pub const RESOURCE_REQUIREMENTS_CHANGED = 0x00000119; +pub const TRANSLATION_COMPLETE = 0x00000120; +pub const DS_MEMBERSHIP_EVALUATED_LOCALLY = 0x00000121; +pub const NOTHING_TO_TERMINATE = 0x00000122; +pub const PROCESS_NOT_IN_JOB = 0x00000123; +pub const PROCESS_IN_JOB = 0x00000124; +pub const VOLSNAP_HIBERNATE_READY = 0x00000125; +pub const FSFILTER_OP_COMPLETED_SUCCESSFULLY = 0x00000126; +pub const INTERRUPT_VECTOR_ALREADY_CONNECTED = 0x00000127; +pub const INTERRUPT_STILL_CONNECTED = 0x00000128; +pub const PROCESS_CLONED = 0x00000129; +pub const FILE_LOCKED_WITH_ONLY_READERS = 0x0000012A; +pub const FILE_LOCKED_WITH_WRITERS = 0x0000012B; +pub const RESOURCEMANAGER_READ_ONLY = 0x00000202; +pub const WAIT_FOR_OPLOCK = 0x00000367; +pub const FLT_IO_COMPLETE = 0x001C0001; +pub const FILE_NOT_AVAILABLE = 0xC0000467; +pub const OBJECT_NAME_EXISTS = 0x40000000; +pub const THREAD_WAS_SUSPENDED = 0x40000001; +pub const WORKING_SET_LIMIT_RANGE = 0x40000002; +pub const IMAGE_NOT_AT_BASE = 0x40000003; +pub const RXACT_STATE_CREATED = 0x40000004; +pub const SEGMENT_NOTIFICATION = 0x40000005; +pub const LOCAL_USER_SESSION_KEY = 0x40000006; +pub const BAD_CURRENT_DIRECTORY = 0x40000007; +pub const SERIAL_MORE_WRITES = 0x40000008; +pub const REGISTRY_RECOVERED = 0x40000009; +pub const FT_READ_RECOVERY_FROM_BACKUP = 0x4000000A; +pub const FT_WRITE_RECOVERY = 0x4000000B; +pub const SERIAL_COUNTER_TIMEOUT = 0x4000000C; +pub const NULL_LM_PASSWORD = 0x4000000D; +pub const IMAGE_MACHINE_TYPE_MISMATCH = 0x4000000E; +pub const RECEIVE_PARTIAL = 0x4000000F; +pub const RECEIVE_EXPEDITED = 0x40000010; +pub const RECEIVE_PARTIAL_EXPEDITED = 0x40000011; +pub const EVENT_DONE = 0x40000012; +pub const EVENT_PENDING = 0x40000013; +pub const CHECKING_FILE_SYSTEM = 0x40000014; +pub const FATAL_APP_EXIT = 0x40000015; +pub const PREDEFINED_HANDLE = 0x40000016; +pub const WAS_UNLOCKED = 0x40000017; +pub const SERVICE_NOTIFICATION = 0x40000018; +pub const WAS_LOCKED = 0x40000019; +pub const LOG_HARD_ERROR = 0x4000001A; +pub const ALREADY_WIN32 = 0x4000001B; +pub const WX86_UNSIMULATE = 0x4000001C; +pub const WX86_CONTINUE = 0x4000001D; +pub const WX86_SINGLE_STEP = 0x4000001E; +pub const WX86_BREAKPOINT = 0x4000001F; +pub const WX86_EXCEPTION_CONTINUE = 0x40000020; +pub const WX86_EXCEPTION_LASTCHANCE = 0x40000021; +pub const WX86_EXCEPTION_CHAIN = 0x40000022; +pub const IMAGE_MACHINE_TYPE_MISMATCH_EXE = 0x40000023; +pub const NO_YIELD_PERFORMED = 0x40000024; +pub const TIMER_RESUME_IGNORED = 0x40000025; +pub const ARBITRATION_UNHANDLED = 0x40000026; +pub const CARDBUS_NOT_SUPPORTED = 0x40000027; +pub const WX86_CREATEWX86TIB = 0x40000028; +pub const MP_PROCESSOR_MISMATCH = 0x40000029; +pub const HIBERNATED = 0x4000002A; +pub const RESUME_HIBERNATION = 0x4000002B; +pub const FIRMWARE_UPDATED = 0x4000002C; +pub const DRIVERS_LEAKING_LOCKED_PAGES = 0x4000002D; +pub const MESSAGE_RETRIEVED = 0x4000002E; +pub const SYSTEM_POWERSTATE_TRANSITION = 0x4000002F; +pub const ALPC_CHECK_COMPLETION_LIST = 0x40000030; +pub const SYSTEM_POWERSTATE_COMPLEX_TRANSITION = 0x40000031; +pub const ACCESS_AUDIT_BY_POLICY = 0x40000032; +pub const ABANDON_HIBERFILE = 0x40000033; +pub const BIZRULES_NOT_ENABLED = 0x40000034; +pub const WAKE_SYSTEM = 0x40000294; +pub const DS_SHUTTING_DOWN = 0x40000370; +pub const CTX_CDM_CONNECT = 0x400A0004; +pub const CTX_CDM_DISCONNECT = 0x400A0005; +pub const SXS_RELEASE_ACTIVATION_CONTEXT = 0x4015000D; +pub const RECOVERY_NOT_NEEDED = 0x40190034; +pub const RM_ALREADY_STARTED = 0x40190035; +pub const LOG_NO_RESTART = 0x401A000C; +pub const VIDEO_DRIVER_DEBUG_REPORT_REQUEST = 0x401B00EC; +pub const GRAPHICS_PARTIAL_DATA_POPULATED = 0x401E000A; +pub const GRAPHICS_DRIVER_MISMATCH = 0x401E0117; +pub const GRAPHICS_MODE_NOT_PINNED = 0x401E0307; +pub const GRAPHICS_NO_PREFERRED_MODE = 0x401E031E; +pub const GRAPHICS_DATASET_IS_EMPTY = 0x401E034B; +pub const GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET = 0x401E034C; +pub const GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_PINNED = 0x401E0351; +pub const GRAPHICS_UNKNOWN_CHILD_STATUS = 0x401E042F; +pub const GRAPHICS_LEADLINK_START_DEFERRED = 0x401E0437; +pub const GRAPHICS_POLLING_TOO_FREQUENTLY = 0x401E0439; +pub const GRAPHICS_START_DEFERRED = 0x401E043A; +pub const NDIS_INDICATION_REQUIRED = 0x40230001; +pub const GUARD_PAGE_VIOLATION = 0x80000001; +pub const DATATYPE_MISALIGNMENT = 0x80000002; +pub const BREAKPOINT = 0x80000003; +pub const SINGLE_STEP = 0x80000004; pub const BUFFER_OVERFLOW = 0x80000005; - +pub const NO_MORE_FILES = 0x80000006; +pub const WAKE_SYSTEM_DEBUGGER = 0x80000007; +pub const HANDLES_CLOSED = 0x8000000A; +pub const NO_INHERITANCE = 0x8000000B; +pub const GUID_SUBSTITUTION_MADE = 0x8000000C; +pub const PARTIAL_COPY = 0x8000000D; +pub const DEVICE_PAPER_EMPTY = 0x8000000E; +pub const DEVICE_POWERED_OFF = 0x8000000F; +pub const DEVICE_OFF_LINE = 0x80000010; +pub const DEVICE_BUSY = 0x80000011; +pub const NO_MORE_EAS = 0x80000012; +pub const INVALID_EA_NAME = 0x80000013; +pub const EA_LIST_INCONSISTENT = 0x80000014; +pub const INVALID_EA_FLAG = 0x80000015; +pub const VERIFY_REQUIRED = 0x80000016; +pub const EXTRANEOUS_INFORMATION = 0x80000017; +pub const RXACT_COMMIT_NECESSARY = 0x80000018; +pub const NO_MORE_ENTRIES = 0x8000001A; +pub const FILEMARK_DETECTED = 0x8000001B; +pub const MEDIA_CHANGED = 0x8000001C; +pub const BUS_RESET = 0x8000001D; +pub const END_OF_MEDIA = 0x8000001E; +pub const BEGINNING_OF_MEDIA = 0x8000001F; +pub const MEDIA_CHECK = 0x80000020; +pub const SETMARK_DETECTED = 0x80000021; +pub const NO_DATA_DETECTED = 0x80000022; +pub const REDIRECTOR_HAS_OPEN_HANDLES = 0x80000023; +pub const SERVER_HAS_OPEN_HANDLES = 0x80000024; +pub const ALREADY_DISCONNECTED = 0x80000025; +pub const LONGJUMP = 0x80000026; +pub const CLEANER_CARTRIDGE_INSTALLED = 0x80000027; +pub const PLUGPLAY_QUERY_VETOED = 0x80000028; +pub const UNWIND_CONSOLIDATE = 0x80000029; +pub const REGISTRY_HIVE_RECOVERED = 0x8000002A; +pub const DLL_MIGHT_BE_INSECURE = 0x8000002B; +pub const DLL_MIGHT_BE_INCOMPATIBLE = 0x8000002C; +pub const STOPPED_ON_SYMLINK = 0x8000002D; +pub const DEVICE_REQUIRES_CLEANING = 0x80000288; +pub const DEVICE_DOOR_OPEN = 0x80000289; +pub const DATA_LOST_REPAIR = 0x80000803; +pub const CLUSTER_NODE_ALREADY_UP = 0x80130001; +pub const CLUSTER_NODE_ALREADY_DOWN = 0x80130002; +pub const CLUSTER_NETWORK_ALREADY_ONLINE = 0x80130003; +pub const CLUSTER_NETWORK_ALREADY_OFFLINE = 0x80130004; +pub const CLUSTER_NODE_ALREADY_MEMBER = 0x80130005; +pub const COULD_NOT_RESIZE_LOG = 0x80190009; +pub const NO_TXF_METADATA = 0x80190029; +pub const CANT_RECOVER_WITH_HANDLE_OPEN = 0x80190031; +pub const TXF_METADATA_ALREADY_PRESENT = 0x80190041; +pub const TRANSACTION_SCOPE_CALLBACKS_NOT_SET = 0x80190042; +pub const VIDEO_HUNG_DISPLAY_DRIVER_THREAD_RECOVERED = 0x801B00EB; +pub const FLT_BUFFER_TOO_SMALL = 0x801C0001; +pub const FVE_PARTIAL_METADATA = 0x80210001; +pub const FVE_TRANSIENT_STATE = 0x80210002; +pub const UNSUCCESSFUL = 0xC0000001; +pub const NOT_IMPLEMENTED = 0xC0000002; +pub const INVALID_INFO_CLASS = 0xC0000003; +pub const INFO_LENGTH_MISMATCH = 0xC0000004; +pub const ACCESS_VIOLATION = 0xC0000005; +pub const IN_PAGE_ERROR = 0xC0000006; +pub const PAGEFILE_QUOTA = 0xC0000007; +pub const INVALID_HANDLE = 0xC0000008; +pub const BAD_INITIAL_STACK = 0xC0000009; +pub const BAD_INITIAL_PC = 0xC000000A; +pub const INVALID_CID = 0xC000000B; +pub const TIMER_NOT_CANCELED = 0xC000000C; pub const INVALID_PARAMETER = 0xC000000D; +pub const NO_SUCH_DEVICE = 0xC000000E; +pub const NO_SUCH_FILE = 0xC000000F; +pub const INVALID_DEVICE_REQUEST = 0xC0000010; +pub const END_OF_FILE = 0xC0000011; +pub const WRONG_VOLUME = 0xC0000012; +pub const NO_MEDIA_IN_DEVICE = 0xC0000013; +pub const UNRECOGNIZED_MEDIA = 0xC0000014; +pub const NONEXISTENT_SECTOR = 0xC0000015; +pub const MORE_PROCESSING_REQUIRED = 0xC0000016; +pub const NO_MEMORY = 0xC0000017; +pub const CONFLICTING_ADDRESSES = 0xC0000018; +pub const NOT_MAPPED_VIEW = 0xC0000019; +pub const UNABLE_TO_FREE_VM = 0xC000001A; +pub const UNABLE_TO_DELETE_SECTION = 0xC000001B; +pub const INVALID_SYSTEM_SERVICE = 0xC000001C; +pub const ILLEGAL_INSTRUCTION = 0xC000001D; +pub const INVALID_LOCK_SEQUENCE = 0xC000001E; +pub const INVALID_VIEW_SIZE = 0xC000001F; +pub const INVALID_FILE_FOR_SECTION = 0xC0000020; +pub const ALREADY_COMMITTED = 0xC0000021; pub const ACCESS_DENIED = 0xC0000022; +pub const BUFFER_TOO_SMALL = 0xC0000023; +pub const OBJECT_TYPE_MISMATCH = 0xC0000024; +pub const NONCONTINUABLE_EXCEPTION = 0xC0000025; +pub const INVALID_DISPOSITION = 0xC0000026; +pub const UNWIND = 0xC0000027; +pub const BAD_STACK = 0xC0000028; +pub const INVALID_UNWIND_TARGET = 0xC0000029; +pub const NOT_LOCKED = 0xC000002A; +pub const PARITY_ERROR = 0xC000002B; +pub const UNABLE_TO_DECOMMIT_VM = 0xC000002C; +pub const NOT_COMMITTED = 0xC000002D; +pub const INVALID_PORT_ATTRIBUTES = 0xC000002E; +pub const PORT_MESSAGE_TOO_LONG = 0xC000002F; +pub const INVALID_PARAMETER_MIX = 0xC0000030; +pub const INVALID_QUOTA_LOWER = 0xC0000031; +pub const DISK_CORRUPT_ERROR = 0xC0000032; pub const OBJECT_NAME_INVALID = 0xC0000033; pub const OBJECT_NAME_NOT_FOUND = 0xC0000034; +pub const OBJECT_NAME_COLLISION = 0xC0000035; +pub const PORT_DISCONNECTED = 0xC0000037; +pub const DEVICE_ALREADY_ATTACHED = 0xC0000038; +pub const OBJECT_PATH_INVALID = 0xC0000039; pub const OBJECT_PATH_NOT_FOUND = 0xC000003A; pub const OBJECT_PATH_SYNTAX_BAD = 0xC000003B; +pub const DATA_OVERRUN = 0xC000003C; +pub const DATA_LATE_ERROR = 0xC000003D; +pub const DATA_ERROR = 0xC000003E; +pub const CRC_ERROR = 0xC000003F; +pub const SECTION_TOO_BIG = 0xC0000040; +pub const PORT_CONNECTION_REFUSED = 0xC0000041; +pub const INVALID_PORT_HANDLE = 0xC0000042; +pub const SHARING_VIOLATION = 0xC0000043; +pub const QUOTA_EXCEEDED = 0xC0000044; +pub const INVALID_PAGE_PROTECTION = 0xC0000045; +pub const MUTANT_NOT_OWNED = 0xC0000046; +pub const SEMAPHORE_LIMIT_EXCEEDED = 0xC0000047; +pub const PORT_ALREADY_SET = 0xC0000048; +pub const SECTION_NOT_IMAGE = 0xC0000049; +pub const SUSPEND_COUNT_EXCEEDED = 0xC000004A; +pub const THREAD_IS_TERMINATING = 0xC000004B; +pub const BAD_WORKING_SET_LIMIT = 0xC000004C; +pub const INCOMPATIBLE_FILE_MAP = 0xC000004D; +pub const SECTION_PROTECTION = 0xC000004E; +pub const EAS_NOT_SUPPORTED = 0xC000004F; +pub const EA_TOO_LARGE = 0xC0000050; +pub const NONEXISTENT_EA_ENTRY = 0xC0000051; +pub const NO_EAS_ON_FILE = 0xC0000052; +pub const EA_CORRUPT_ERROR = 0xC0000053; +pub const FILE_LOCK_CONFLICT = 0xC0000054; +pub const LOCK_NOT_GRANTED = 0xC0000055; +pub const DELETE_PENDING = 0xC0000056; +pub const CTL_FILE_NOT_SUPPORTED = 0xC0000057; +pub const UNKNOWN_REVISION = 0xC0000058; +pub const REVISION_MISMATCH = 0xC0000059; +pub const INVALID_OWNER = 0xC000005A; +pub const INVALID_PRIMARY_GROUP = 0xC000005B; +pub const NO_IMPERSONATION_TOKEN = 0xC000005C; +pub const CANT_DISABLE_MANDATORY = 0xC000005D; +pub const NO_LOGON_SERVERS = 0xC000005E; +pub const NO_SUCH_LOGON_SESSION = 0xC000005F; +pub const NO_SUCH_PRIVILEGE = 0xC0000060; +pub const PRIVILEGE_NOT_HELD = 0xC0000061; +pub const INVALID_ACCOUNT_NAME = 0xC0000062; +pub const USER_EXISTS = 0xC0000063; +pub const NO_SUCH_USER = 0xC0000064; +pub const GROUP_EXISTS = 0xC0000065; +pub const NO_SUCH_GROUP = 0xC0000066; +pub const MEMBER_IN_GROUP = 0xC0000067; +pub const MEMBER_NOT_IN_GROUP = 0xC0000068; +pub const LAST_ADMIN = 0xC0000069; +pub const WRONG_PASSWORD = 0xC000006A; +pub const ILL_FORMED_PASSWORD = 0xC000006B; +pub const PASSWORD_RESTRICTION = 0xC000006C; +pub const LOGON_FAILURE = 0xC000006D; +pub const ACCOUNT_RESTRICTION = 0xC000006E; +pub const INVALID_LOGON_HOURS = 0xC000006F; +pub const INVALID_WORKSTATION = 0xC0000070; +pub const PASSWORD_EXPIRED = 0xC0000071; +pub const ACCOUNT_DISABLED = 0xC0000072; +pub const NONE_MAPPED = 0xC0000073; +pub const TOO_MANY_LUIDS_REQUESTED = 0xC0000074; +pub const LUIDS_EXHAUSTED = 0xC0000075; +pub const INVALID_SUB_AUTHORITY = 0xC0000076; +pub const INVALID_ACL = 0xC0000077; +pub const INVALID_SID = 0xC0000078; +pub const INVALID_SECURITY_DESCR = 0xC0000079; +pub const PROCEDURE_NOT_FOUND = 0xC000007A; +pub const INVALID_IMAGE_FORMAT = 0xC000007B; +pub const NO_TOKEN = 0xC000007C; +pub const BAD_INHERITANCE_ACL = 0xC000007D; +pub const RANGE_NOT_LOCKED = 0xC000007E; +pub const DISK_FULL = 0xC000007F; +pub const SERVER_DISABLED = 0xC0000080; +pub const SERVER_NOT_DISABLED = 0xC0000081; +pub const TOO_MANY_GUIDS_REQUESTED = 0xC0000082; +pub const GUIDS_EXHAUSTED = 0xC0000083; +pub const INVALID_ID_AUTHORITY = 0xC0000084; +pub const AGENTS_EXHAUSTED = 0xC0000085; +pub const INVALID_VOLUME_LABEL = 0xC0000086; +pub const SECTION_NOT_EXTENDED = 0xC0000087; +pub const NOT_MAPPED_DATA = 0xC0000088; +pub const RESOURCE_DATA_NOT_FOUND = 0xC0000089; +pub const RESOURCE_TYPE_NOT_FOUND = 0xC000008A; +pub const RESOURCE_NAME_NOT_FOUND = 0xC000008B; +pub const ARRAY_BOUNDS_EXCEEDED = 0xC000008C; +pub const FLOAT_DENORMAL_OPERAND = 0xC000008D; +pub const FLOAT_DIVIDE_BY_ZERO = 0xC000008E; +pub const FLOAT_INEXACT_RESULT = 0xC000008F; +pub const FLOAT_INVALID_OPERATION = 0xC0000090; +pub const FLOAT_OVERFLOW = 0xC0000091; +pub const FLOAT_STACK_CHECK = 0xC0000092; +pub const FLOAT_UNDERFLOW = 0xC0000093; +pub const INTEGER_DIVIDE_BY_ZERO = 0xC0000094; +pub const INTEGER_OVERFLOW = 0xC0000095; +pub const PRIVILEGED_INSTRUCTION = 0xC0000096; +pub const TOO_MANY_PAGING_FILES = 0xC0000097; +pub const FILE_INVALID = 0xC0000098; +pub const ALLOTTED_SPACE_EXCEEDED = 0xC0000099; +pub const INSUFFICIENT_RESOURCES = 0xC000009A; +pub const DFS_EXIT_PATH_FOUND = 0xC000009B; +pub const DEVICE_DATA_ERROR = 0xC000009C; +pub const DEVICE_NOT_CONNECTED = 0xC000009D; +pub const FREE_VM_NOT_AT_BASE = 0xC000009F; +pub const MEMORY_NOT_ALLOCATED = 0xC00000A0; +pub const WORKING_SET_QUOTA = 0xC00000A1; +pub const MEDIA_WRITE_PROTECTED = 0xC00000A2; +pub const DEVICE_NOT_READY = 0xC00000A3; +pub const INVALID_GROUP_ATTRIBUTES = 0xC00000A4; +pub const BAD_IMPERSONATION_LEVEL = 0xC00000A5; +pub const CANT_OPEN_ANONYMOUS = 0xC00000A6; +pub const BAD_VALIDATION_CLASS = 0xC00000A7; +pub const BAD_TOKEN_TYPE = 0xC00000A8; +pub const BAD_MASTER_BOOT_RECORD = 0xC00000A9; +pub const INSTRUCTION_MISALIGNMENT = 0xC00000AA; +pub const INSTANCE_NOT_AVAILABLE = 0xC00000AB; +pub const PIPE_NOT_AVAILABLE = 0xC00000AC; +pub const INVALID_PIPE_STATE = 0xC00000AD; +pub const PIPE_BUSY = 0xC00000AE; +pub const ILLEGAL_FUNCTION = 0xC00000AF; +pub const PIPE_DISCONNECTED = 0xC00000B0; +pub const PIPE_CLOSING = 0xC00000B1; +pub const PIPE_CONNECTED = 0xC00000B2; +pub const PIPE_LISTENING = 0xC00000B3; +pub const INVALID_READ_MODE = 0xC00000B4; +pub const IO_TIMEOUT = 0xC00000B5; +pub const FILE_FORCED_CLOSED = 0xC00000B6; +pub const PROFILING_NOT_STARTED = 0xC00000B7; +pub const PROFILING_NOT_STOPPED = 0xC00000B8; +pub const COULD_NOT_INTERPRET = 0xC00000B9; pub const FILE_IS_A_DIRECTORY = 0xC00000BA; +pub const NOT_SUPPORTED = 0xC00000BB; +pub const REMOTE_NOT_LISTENING = 0xC00000BC; +pub const DUPLICATE_NAME = 0xC00000BD; +pub const BAD_NETWORK_PATH = 0xC00000BE; +pub const NETWORK_BUSY = 0xC00000BF; +pub const DEVICE_DOES_NOT_EXIST = 0xC00000C0; +pub const TOO_MANY_COMMANDS = 0xC00000C1; +pub const ADAPTER_HARDWARE_ERROR = 0xC00000C2; +pub const INVALID_NETWORK_RESPONSE = 0xC00000C3; +pub const UNEXPECTED_NETWORK_ERROR = 0xC00000C4; +pub const BAD_REMOTE_ADAPTER = 0xC00000C5; +pub const PRINT_QUEUE_FULL = 0xC00000C6; +pub const NO_SPOOL_SPACE = 0xC00000C7; +pub const PRINT_CANCELLED = 0xC00000C8; +pub const NETWORK_NAME_DELETED = 0xC00000C9; +pub const NETWORK_ACCESS_DENIED = 0xC00000CA; +pub const BAD_DEVICE_TYPE = 0xC00000CB; +pub const BAD_NETWORK_NAME = 0xC00000CC; +pub const TOO_MANY_NAMES = 0xC00000CD; +pub const TOO_MANY_SESSIONS = 0xC00000CE; +pub const SHARING_PAUSED = 0xC00000CF; +pub const REQUEST_NOT_ACCEPTED = 0xC00000D0; +pub const REDIRECTOR_PAUSED = 0xC00000D1; +pub const NET_WRITE_FAULT = 0xC00000D2; +pub const PROFILING_AT_LIMIT = 0xC00000D3; +pub const NOT_SAME_DEVICE = 0xC00000D4; +pub const FILE_RENAMED = 0xC00000D5; +pub const VIRTUAL_CIRCUIT_CLOSED = 0xC00000D6; +pub const NO_SECURITY_ON_OBJECT = 0xC00000D7; +pub const CANT_WAIT = 0xC00000D8; +pub const PIPE_EMPTY = 0xC00000D9; +pub const CANT_ACCESS_DOMAIN_INFO = 0xC00000DA; +pub const CANT_TERMINATE_SELF = 0xC00000DB; +pub const INVALID_SERVER_STATE = 0xC00000DC; +pub const INVALID_DOMAIN_STATE = 0xC00000DD; +pub const INVALID_DOMAIN_ROLE = 0xC00000DE; +pub const NO_SUCH_DOMAIN = 0xC00000DF; +pub const DOMAIN_EXISTS = 0xC00000E0; +pub const DOMAIN_LIMIT_EXCEEDED = 0xC00000E1; +pub const OPLOCK_NOT_GRANTED = 0xC00000E2; +pub const INVALID_OPLOCK_PROTOCOL = 0xC00000E3; +pub const INTERNAL_DB_CORRUPTION = 0xC00000E4; +pub const INTERNAL_ERROR = 0xC00000E5; +pub const GENERIC_NOT_MAPPED = 0xC00000E6; +pub const BAD_DESCRIPTOR_FORMAT = 0xC00000E7; +pub const INVALID_USER_BUFFER = 0xC00000E8; +pub const UNEXPECTED_IO_ERROR = 0xC00000E9; +pub const UNEXPECTED_MM_CREATE_ERR = 0xC00000EA; +pub const UNEXPECTED_MM_MAP_ERROR = 0xC00000EB; +pub const UNEXPECTED_MM_EXTEND_ERR = 0xC00000EC; +pub const NOT_LOGON_PROCESS = 0xC00000ED; +pub const LOGON_SESSION_EXISTS = 0xC00000EE; +pub const INVALID_PARAMETER_1 = 0xC00000EF; +pub const INVALID_PARAMETER_2 = 0xC00000F0; +pub const INVALID_PARAMETER_3 = 0xC00000F1; +pub const INVALID_PARAMETER_4 = 0xC00000F2; +pub const INVALID_PARAMETER_5 = 0xC00000F3; +pub const INVALID_PARAMETER_6 = 0xC00000F4; +pub const INVALID_PARAMETER_7 = 0xC00000F5; +pub const INVALID_PARAMETER_8 = 0xC00000F6; +pub const INVALID_PARAMETER_9 = 0xC00000F7; +pub const INVALID_PARAMETER_10 = 0xC00000F8; +pub const INVALID_PARAMETER_11 = 0xC00000F9; +pub const INVALID_PARAMETER_12 = 0xC00000FA; +pub const REDIRECTOR_NOT_STARTED = 0xC00000FB; +pub const REDIRECTOR_STARTED = 0xC00000FC; +pub const STACK_OVERFLOW = 0xC00000FD; +pub const NO_SUCH_PACKAGE = 0xC00000FE; +pub const BAD_FUNCTION_TABLE = 0xC00000FF; +pub const VARIABLE_NOT_FOUND = 0xC0000100; +pub const DIRECTORY_NOT_EMPTY = 0xC0000101; +pub const FILE_CORRUPT_ERROR = 0xC0000102; +pub const NOT_A_DIRECTORY = 0xC0000103; +pub const BAD_LOGON_SESSION_STATE = 0xC0000104; +pub const LOGON_SESSION_COLLISION = 0xC0000105; +pub const NAME_TOO_LONG = 0xC0000106; +pub const FILES_OPEN = 0xC0000107; +pub const CONNECTION_IN_USE = 0xC0000108; +pub const MESSAGE_NOT_FOUND = 0xC0000109; +pub const PROCESS_IS_TERMINATING = 0xC000010A; +pub const INVALID_LOGON_TYPE = 0xC000010B; +pub const NO_GUID_TRANSLATION = 0xC000010C; +pub const CANNOT_IMPERSONATE = 0xC000010D; +pub const IMAGE_ALREADY_LOADED = 0xC000010E; +pub const NO_LDT = 0xC0000117; +pub const INVALID_LDT_SIZE = 0xC0000118; +pub const INVALID_LDT_OFFSET = 0xC0000119; +pub const INVALID_LDT_DESCRIPTOR = 0xC000011A; +pub const INVALID_IMAGE_NE_FORMAT = 0xC000011B; +pub const RXACT_INVALID_STATE = 0xC000011C; +pub const RXACT_COMMIT_FAILURE = 0xC000011D; +pub const MAPPED_FILE_SIZE_ZERO = 0xC000011E; +pub const TOO_MANY_OPENED_FILES = 0xC000011F; +pub const CANCELLED = 0xC0000120; +pub const CANNOT_DELETE = 0xC0000121; +pub const INVALID_COMPUTER_NAME = 0xC0000122; +pub const FILE_DELETED = 0xC0000123; +pub const SPECIAL_ACCOUNT = 0xC0000124; +pub const SPECIAL_GROUP = 0xC0000125; +pub const SPECIAL_USER = 0xC0000126; +pub const MEMBERS_PRIMARY_GROUP = 0xC0000127; +pub const FILE_CLOSED = 0xC0000128; +pub const TOO_MANY_THREADS = 0xC0000129; +pub const THREAD_NOT_IN_PROCESS = 0xC000012A; +pub const TOKEN_ALREADY_IN_USE = 0xC000012B; +pub const PAGEFILE_QUOTA_EXCEEDED = 0xC000012C; +pub const COMMITMENT_LIMIT = 0xC000012D; +pub const INVALID_IMAGE_LE_FORMAT = 0xC000012E; +pub const INVALID_IMAGE_NOT_MZ = 0xC000012F; +pub const INVALID_IMAGE_PROTECT = 0xC0000130; +pub const INVALID_IMAGE_WIN_16 = 0xC0000131; +pub const LOGON_SERVER_CONFLICT = 0xC0000132; +pub const TIME_DIFFERENCE_AT_DC = 0xC0000133; +pub const SYNCHRONIZATION_REQUIRED = 0xC0000134; +pub const DLL_NOT_FOUND = 0xC0000135; +pub const OPEN_FAILED = 0xC0000136; +pub const IO_PRIVILEGE_FAILED = 0xC0000137; +pub const ORDINAL_NOT_FOUND = 0xC0000138; +pub const ENTRYPOINT_NOT_FOUND = 0xC0000139; +pub const CONTROL_C_EXIT = 0xC000013A; +pub const LOCAL_DISCONNECT = 0xC000013B; +pub const REMOTE_DISCONNECT = 0xC000013C; +pub const REMOTE_RESOURCES = 0xC000013D; +pub const LINK_FAILED = 0xC000013E; +pub const LINK_TIMEOUT = 0xC000013F; +pub const INVALID_CONNECTION = 0xC0000140; +pub const INVALID_ADDRESS = 0xC0000141; +pub const DLL_INIT_FAILED = 0xC0000142; +pub const MISSING_SYSTEMFILE = 0xC0000143; +pub const UNHANDLED_EXCEPTION = 0xC0000144; +pub const APP_INIT_FAILURE = 0xC0000145; +pub const PAGEFILE_CREATE_FAILED = 0xC0000146; +pub const NO_PAGEFILE = 0xC0000147; +pub const INVALID_LEVEL = 0xC0000148; +pub const WRONG_PASSWORD_CORE = 0xC0000149; +pub const ILLEGAL_FLOAT_CONTEXT = 0xC000014A; +pub const PIPE_BROKEN = 0xC000014B; +pub const REGISTRY_CORRUPT = 0xC000014C; +pub const REGISTRY_IO_FAILED = 0xC000014D; +pub const NO_EVENT_PAIR = 0xC000014E; +pub const UNRECOGNIZED_VOLUME = 0xC000014F; +pub const SERIAL_NO_DEVICE_INITED = 0xC0000150; +pub const NO_SUCH_ALIAS = 0xC0000151; +pub const MEMBER_NOT_IN_ALIAS = 0xC0000152; +pub const MEMBER_IN_ALIAS = 0xC0000153; +pub const ALIAS_EXISTS = 0xC0000154; +pub const LOGON_NOT_GRANTED = 0xC0000155; +pub const TOO_MANY_SECRETS = 0xC0000156; +pub const SECRET_TOO_LONG = 0xC0000157; +pub const INTERNAL_DB_ERROR = 0xC0000158; +pub const FULLSCREEN_MODE = 0xC0000159; +pub const TOO_MANY_CONTEXT_IDS = 0xC000015A; +pub const LOGON_TYPE_NOT_GRANTED = 0xC000015B; +pub const NOT_REGISTRY_FILE = 0xC000015C; +pub const NT_CROSS_ENCRYPTION_REQUIRED = 0xC000015D; +pub const DOMAIN_CTRLR_CONFIG_ERROR = 0xC000015E; +pub const FT_MISSING_MEMBER = 0xC000015F; +pub const ILL_FORMED_SERVICE_ENTRY = 0xC0000160; +pub const ILLEGAL_CHARACTER = 0xC0000161; +pub const UNMAPPABLE_CHARACTER = 0xC0000162; +pub const UNDEFINED_CHARACTER = 0xC0000163; +pub const FLOPPY_VOLUME = 0xC0000164; +pub const FLOPPY_ID_MARK_NOT_FOUND = 0xC0000165; +pub const FLOPPY_WRONG_CYLINDER = 0xC0000166; +pub const FLOPPY_UNKNOWN_ERROR = 0xC0000167; +pub const FLOPPY_BAD_REGISTERS = 0xC0000168; +pub const DISK_RECALIBRATE_FAILED = 0xC0000169; +pub const DISK_OPERATION_FAILED = 0xC000016A; +pub const DISK_RESET_FAILED = 0xC000016B; +pub const SHARED_IRQ_BUSY = 0xC000016C; +pub const FT_ORPHANING = 0xC000016D; +pub const BIOS_FAILED_TO_CONNECT_INTERRUPT = 0xC000016E; +pub const PARTITION_FAILURE = 0xC0000172; +pub const INVALID_BLOCK_LENGTH = 0xC0000173; +pub const DEVICE_NOT_PARTITIONED = 0xC0000174; +pub const UNABLE_TO_LOCK_MEDIA = 0xC0000175; +pub const UNABLE_TO_UNLOAD_MEDIA = 0xC0000176; +pub const EOM_OVERFLOW = 0xC0000177; +pub const NO_MEDIA = 0xC0000178; +pub const NO_SUCH_MEMBER = 0xC000017A; +pub const INVALID_MEMBER = 0xC000017B; +pub const KEY_DELETED = 0xC000017C; +pub const NO_LOG_SPACE = 0xC000017D; +pub const TOO_MANY_SIDS = 0xC000017E; +pub const LM_CROSS_ENCRYPTION_REQUIRED = 0xC000017F; +pub const KEY_HAS_CHILDREN = 0xC0000180; +pub const CHILD_MUST_BE_VOLATILE = 0xC0000181; +pub const DEVICE_CONFIGURATION_ERROR = 0xC0000182; +pub const DRIVER_INTERNAL_ERROR = 0xC0000183; +pub const INVALID_DEVICE_STATE = 0xC0000184; +pub const IO_DEVICE_ERROR = 0xC0000185; +pub const DEVICE_PROTOCOL_ERROR = 0xC0000186; +pub const BACKUP_CONTROLLER = 0xC0000187; +pub const LOG_FILE_FULL = 0xC0000188; +pub const TOO_LATE = 0xC0000189; +pub const NO_TRUST_LSA_SECRET = 0xC000018A; +pub const NO_TRUST_SAM_ACCOUNT = 0xC000018B; +pub const TRUSTED_DOMAIN_FAILURE = 0xC000018C; +pub const TRUSTED_RELATIONSHIP_FAILURE = 0xC000018D; +pub const EVENTLOG_FILE_CORRUPT = 0xC000018E; +pub const EVENTLOG_CANT_START = 0xC000018F; +pub const TRUST_FAILURE = 0xC0000190; +pub const MUTANT_LIMIT_EXCEEDED = 0xC0000191; +pub const NETLOGON_NOT_STARTED = 0xC0000192; +pub const ACCOUNT_EXPIRED = 0xC0000193; +pub const POSSIBLE_DEADLOCK = 0xC0000194; +pub const NETWORK_CREDENTIAL_CONFLICT = 0xC0000195; +pub const REMOTE_SESSION_LIMIT = 0xC0000196; +pub const EVENTLOG_FILE_CHANGED = 0xC0000197; +pub const NOLOGON_INTERDOMAIN_TRUST_ACCOUNT = 0xC0000198; +pub const NOLOGON_WORKSTATION_TRUST_ACCOUNT = 0xC0000199; +pub const NOLOGON_SERVER_TRUST_ACCOUNT = 0xC000019A; +pub const DOMAIN_TRUST_INCONSISTENT = 0xC000019B; +pub const FS_DRIVER_REQUIRED = 0xC000019C; +pub const IMAGE_ALREADY_LOADED_AS_DLL = 0xC000019D; +pub const INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING = 0xC000019E; +pub const SHORT_NAMES_NOT_ENABLED_ON_VOLUME = 0xC000019F; +pub const SECURITY_STREAM_IS_INCONSISTENT = 0xC00001A0; +pub const INVALID_LOCK_RANGE = 0xC00001A1; +pub const INVALID_ACE_CONDITION = 0xC00001A2; +pub const IMAGE_SUBSYSTEM_NOT_PRESENT = 0xC00001A3; +pub const NOTIFICATION_GUID_ALREADY_DEFINED = 0xC00001A4; +pub const NETWORK_OPEN_RESTRICTION = 0xC0000201; +pub const NO_USER_SESSION_KEY = 0xC0000202; +pub const USER_SESSION_DELETED = 0xC0000203; +pub const RESOURCE_LANG_NOT_FOUND = 0xC0000204; +pub const INSUFF_SERVER_RESOURCES = 0xC0000205; +pub const INVALID_BUFFER_SIZE = 0xC0000206; +pub const INVALID_ADDRESS_COMPONENT = 0xC0000207; +pub const INVALID_ADDRESS_WILDCARD = 0xC0000208; +pub const TOO_MANY_ADDRESSES = 0xC0000209; +pub const ADDRESS_ALREADY_EXISTS = 0xC000020A; +pub const ADDRESS_CLOSED = 0xC000020B; +pub const CONNECTION_DISCONNECTED = 0xC000020C; +pub const CONNECTION_RESET = 0xC000020D; +pub const TOO_MANY_NODES = 0xC000020E; +pub const TRANSACTION_ABORTED = 0xC000020F; +pub const TRANSACTION_TIMED_OUT = 0xC0000210; +pub const TRANSACTION_NO_RELEASE = 0xC0000211; +pub const TRANSACTION_NO_MATCH = 0xC0000212; +pub const TRANSACTION_RESPONDED = 0xC0000213; +pub const TRANSACTION_INVALID_ID = 0xC0000214; +pub const TRANSACTION_INVALID_TYPE = 0xC0000215; +pub const NOT_SERVER_SESSION = 0xC0000216; +pub const NOT_CLIENT_SESSION = 0xC0000217; +pub const CANNOT_LOAD_REGISTRY_FILE = 0xC0000218; +pub const DEBUG_ATTACH_FAILED = 0xC0000219; +pub const SYSTEM_PROCESS_TERMINATED = 0xC000021A; +pub const DATA_NOT_ACCEPTED = 0xC000021B; +pub const NO_BROWSER_SERVERS_FOUND = 0xC000021C; +pub const VDM_HARD_ERROR = 0xC000021D; +pub const DRIVER_CANCEL_TIMEOUT = 0xC000021E; +pub const REPLY_MESSAGE_MISMATCH = 0xC000021F; +pub const MAPPED_ALIGNMENT = 0xC0000220; +pub const IMAGE_CHECKSUM_MISMATCH = 0xC0000221; +pub const LOST_WRITEBEHIND_DATA = 0xC0000222; +pub const CLIENT_SERVER_PARAMETERS_INVALID = 0xC0000223; +pub const PASSWORD_MUST_CHANGE = 0xC0000224; +pub const NOT_FOUND = 0xC0000225; +pub const NOT_TINY_STREAM = 0xC0000226; +pub const RECOVERY_FAILURE = 0xC0000227; +pub const STACK_OVERFLOW_READ = 0xC0000228; +pub const FAIL_CHECK = 0xC0000229; +pub const DUPLICATE_OBJECTID = 0xC000022A; +pub const OBJECTID_EXISTS = 0xC000022B; +pub const CONVERT_TO_LARGE = 0xC000022C; +pub const RETRY = 0xC000022D; +pub const FOUND_OUT_OF_SCOPE = 0xC000022E; +pub const ALLOCATE_BUCKET = 0xC000022F; +pub const PROPSET_NOT_FOUND = 0xC0000230; +pub const MARSHALL_OVERFLOW = 0xC0000231; +pub const INVALID_VARIANT = 0xC0000232; +pub const DOMAIN_CONTROLLER_NOT_FOUND = 0xC0000233; +pub const ACCOUNT_LOCKED_OUT = 0xC0000234; +pub const HANDLE_NOT_CLOSABLE = 0xC0000235; +pub const CONNECTION_REFUSED = 0xC0000236; +pub const GRACEFUL_DISCONNECT = 0xC0000237; +pub const ADDRESS_ALREADY_ASSOCIATED = 0xC0000238; +pub const ADDRESS_NOT_ASSOCIATED = 0xC0000239; +pub const CONNECTION_INVALID = 0xC000023A; +pub const CONNECTION_ACTIVE = 0xC000023B; +pub const NETWORK_UNREACHABLE = 0xC000023C; +pub const HOST_UNREACHABLE = 0xC000023D; +pub const PROTOCOL_UNREACHABLE = 0xC000023E; +pub const PORT_UNREACHABLE = 0xC000023F; +pub const REQUEST_ABORTED = 0xC0000240; +pub const CONNECTION_ABORTED = 0xC0000241; +pub const BAD_COMPRESSION_BUFFER = 0xC0000242; +pub const USER_MAPPED_FILE = 0xC0000243; +pub const AUDIT_FAILED = 0xC0000244; +pub const TIMER_RESOLUTION_NOT_SET = 0xC0000245; +pub const CONNECTION_COUNT_LIMIT = 0xC0000246; +pub const LOGIN_TIME_RESTRICTION = 0xC0000247; +pub const LOGIN_WKSTA_RESTRICTION = 0xC0000248; +pub const IMAGE_MP_UP_MISMATCH = 0xC0000249; +pub const INSUFFICIENT_LOGON_INFO = 0xC0000250; +pub const BAD_DLL_ENTRYPOINT = 0xC0000251; +pub const BAD_SERVICE_ENTRYPOINT = 0xC0000252; +pub const LPC_REPLY_LOST = 0xC0000253; +pub const IP_ADDRESS_CONFLICT1 = 0xC0000254; +pub const IP_ADDRESS_CONFLICT2 = 0xC0000255; +pub const REGISTRY_QUOTA_LIMIT = 0xC0000256; +pub const PATH_NOT_COVERED = 0xC0000257; +pub const NO_CALLBACK_ACTIVE = 0xC0000258; +pub const LICENSE_QUOTA_EXCEEDED = 0xC0000259; +pub const PWD_TOO_SHORT = 0xC000025A; +pub const PWD_TOO_RECENT = 0xC000025B; +pub const PWD_HISTORY_CONFLICT = 0xC000025C; +pub const PLUGPLAY_NO_DEVICE = 0xC000025E; +pub const UNSUPPORTED_COMPRESSION = 0xC000025F; +pub const INVALID_HW_PROFILE = 0xC0000260; +pub const INVALID_PLUGPLAY_DEVICE_PATH = 0xC0000261; +pub const DRIVER_ORDINAL_NOT_FOUND = 0xC0000262; +pub const DRIVER_ENTRYPOINT_NOT_FOUND = 0xC0000263; +pub const RESOURCE_NOT_OWNED = 0xC0000264; +pub const TOO_MANY_LINKS = 0xC0000265; +pub const QUOTA_LIST_INCONSISTENT = 0xC0000266; +pub const FILE_IS_OFFLINE = 0xC0000267; +pub const EVALUATION_EXPIRATION = 0xC0000268; +pub const ILLEGAL_DLL_RELOCATION = 0xC0000269; +pub const LICENSE_VIOLATION = 0xC000026A; +pub const DLL_INIT_FAILED_LOGOFF = 0xC000026B; +pub const DRIVER_UNABLE_TO_LOAD = 0xC000026C; +pub const DFS_UNAVAILABLE = 0xC000026D; +pub const VOLUME_DISMOUNTED = 0xC000026E; +pub const WX86_INTERNAL_ERROR = 0xC000026F; +pub const WX86_FLOAT_STACK_CHECK = 0xC0000270; +pub const VALIDATE_CONTINUE = 0xC0000271; +pub const NO_MATCH = 0xC0000272; +pub const NO_MORE_MATCHES = 0xC0000273; +pub const NOT_A_REPARSE_POINT = 0xC0000275; +pub const IO_REPARSE_TAG_INVALID = 0xC0000276; +pub const IO_REPARSE_TAG_MISMATCH = 0xC0000277; +pub const IO_REPARSE_DATA_INVALID = 0xC0000278; +pub const IO_REPARSE_TAG_NOT_HANDLED = 0xC0000279; +pub const REPARSE_POINT_NOT_RESOLVED = 0xC0000280; +pub const DIRECTORY_IS_A_REPARSE_POINT = 0xC0000281; +pub const RANGE_LIST_CONFLICT = 0xC0000282; +pub const SOURCE_ELEMENT_EMPTY = 0xC0000283; +pub const DESTINATION_ELEMENT_FULL = 0xC0000284; +pub const ILLEGAL_ELEMENT_ADDRESS = 0xC0000285; +pub const MAGAZINE_NOT_PRESENT = 0xC0000286; +pub const REINITIALIZATION_NEEDED = 0xC0000287; +pub const ENCRYPTION_FAILED = 0xC000028A; +pub const DECRYPTION_FAILED = 0xC000028B; +pub const RANGE_NOT_FOUND = 0xC000028C; +pub const NO_RECOVERY_POLICY = 0xC000028D; +pub const NO_EFS = 0xC000028E; +pub const WRONG_EFS = 0xC000028F; +pub const NO_USER_KEYS = 0xC0000290; +pub const FILE_NOT_ENCRYPTED = 0xC0000291; +pub const NOT_EXPORT_FORMAT = 0xC0000292; +pub const FILE_ENCRYPTED = 0xC0000293; +pub const WMI_GUID_NOT_FOUND = 0xC0000295; +pub const WMI_INSTANCE_NOT_FOUND = 0xC0000296; +pub const WMI_ITEMID_NOT_FOUND = 0xC0000297; +pub const WMI_TRY_AGAIN = 0xC0000298; +pub const SHARED_POLICY = 0xC0000299; +pub const POLICY_OBJECT_NOT_FOUND = 0xC000029A; +pub const POLICY_ONLY_IN_DS = 0xC000029B; +pub const VOLUME_NOT_UPGRADED = 0xC000029C; +pub const REMOTE_STORAGE_NOT_ACTIVE = 0xC000029D; +pub const REMOTE_STORAGE_MEDIA_ERROR = 0xC000029E; +pub const NO_TRACKING_SERVICE = 0xC000029F; +pub const SERVER_SID_MISMATCH = 0xC00002A0; +pub const DS_NO_ATTRIBUTE_OR_VALUE = 0xC00002A1; +pub const DS_INVALID_ATTRIBUTE_SYNTAX = 0xC00002A2; +pub const DS_ATTRIBUTE_TYPE_UNDEFINED = 0xC00002A3; +pub const DS_ATTRIBUTE_OR_VALUE_EXISTS = 0xC00002A4; +pub const DS_BUSY = 0xC00002A5; +pub const DS_UNAVAILABLE = 0xC00002A6; +pub const DS_NO_RIDS_ALLOCATED = 0xC00002A7; +pub const DS_NO_MORE_RIDS = 0xC00002A8; +pub const DS_INCORRECT_ROLE_OWNER = 0xC00002A9; +pub const DS_RIDMGR_INIT_ERROR = 0xC00002AA; +pub const DS_OBJ_CLASS_VIOLATION = 0xC00002AB; +pub const DS_CANT_ON_NON_LEAF = 0xC00002AC; +pub const DS_CANT_ON_RDN = 0xC00002AD; +pub const DS_CANT_MOD_OBJ_CLASS = 0xC00002AE; +pub const DS_CROSS_DOM_MOVE_FAILED = 0xC00002AF; +pub const DS_GC_NOT_AVAILABLE = 0xC00002B0; +pub const DIRECTORY_SERVICE_REQUIRED = 0xC00002B1; +pub const REPARSE_ATTRIBUTE_CONFLICT = 0xC00002B2; +pub const CANT_ENABLE_DENY_ONLY = 0xC00002B3; +pub const FLOAT_MULTIPLE_FAULTS = 0xC00002B4; +pub const FLOAT_MULTIPLE_TRAPS = 0xC00002B5; +pub const DEVICE_REMOVED = 0xC00002B6; +pub const JOURNAL_DELETE_IN_PROGRESS = 0xC00002B7; +pub const JOURNAL_NOT_ACTIVE = 0xC00002B8; +pub const NOINTERFACE = 0xC00002B9; +pub const DS_ADMIN_LIMIT_EXCEEDED = 0xC00002C1; +pub const DRIVER_FAILED_SLEEP = 0xC00002C2; +pub const MUTUAL_AUTHENTICATION_FAILED = 0xC00002C3; +pub const CORRUPT_SYSTEM_FILE = 0xC00002C4; +pub const DATATYPE_MISALIGNMENT_ERROR = 0xC00002C5; +pub const WMI_READ_ONLY = 0xC00002C6; +pub const WMI_SET_FAILURE = 0xC00002C7; +pub const COMMITMENT_MINIMUM = 0xC00002C8; +pub const REG_NAT_CONSUMPTION = 0xC00002C9; +pub const TRANSPORT_FULL = 0xC00002CA; +pub const DS_SAM_INIT_FAILURE = 0xC00002CB; +pub const ONLY_IF_CONNECTED = 0xC00002CC; +pub const DS_SENSITIVE_GROUP_VIOLATION = 0xC00002CD; +pub const PNP_RESTART_ENUMERATION = 0xC00002CE; +pub const JOURNAL_ENTRY_DELETED = 0xC00002CF; +pub const DS_CANT_MOD_PRIMARYGROUPID = 0xC00002D0; +pub const SYSTEM_IMAGE_BAD_SIGNATURE = 0xC00002D1; +pub const PNP_REBOOT_REQUIRED = 0xC00002D2; +pub const POWER_STATE_INVALID = 0xC00002D3; +pub const DS_INVALID_GROUP_TYPE = 0xC00002D4; +pub const DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN = 0xC00002D5; +pub const DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN = 0xC00002D6; +pub const DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER = 0xC00002D7; +pub const DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER = 0xC00002D8; +pub const DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER = 0xC00002D9; +pub const DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER = 0xC00002DA; +pub const DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER = 0xC00002DB; +pub const DS_HAVE_PRIMARY_MEMBERS = 0xC00002DC; +pub const WMI_NOT_SUPPORTED = 0xC00002DD; +pub const INSUFFICIENT_POWER = 0xC00002DE; +pub const SAM_NEED_BOOTKEY_PASSWORD = 0xC00002DF; +pub const SAM_NEED_BOOTKEY_FLOPPY = 0xC00002E0; +pub const DS_CANT_START = 0xC00002E1; +pub const DS_INIT_FAILURE = 0xC00002E2; +pub const SAM_INIT_FAILURE = 0xC00002E3; +pub const DS_GC_REQUIRED = 0xC00002E4; +pub const DS_LOCAL_MEMBER_OF_LOCAL_ONLY = 0xC00002E5; +pub const DS_NO_FPO_IN_UNIVERSAL_GROUPS = 0xC00002E6; +pub const DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED = 0xC00002E7; +pub const CURRENT_DOMAIN_NOT_ALLOWED = 0xC00002E9; +pub const CANNOT_MAKE = 0xC00002EA; +pub const SYSTEM_SHUTDOWN = 0xC00002EB; +pub const DS_INIT_FAILURE_CONSOLE = 0xC00002EC; +pub const DS_SAM_INIT_FAILURE_CONSOLE = 0xC00002ED; +pub const UNFINISHED_CONTEXT_DELETED = 0xC00002EE; +pub const NO_TGT_REPLY = 0xC00002EF; +pub const OBJECTID_NOT_FOUND = 0xC00002F0; +pub const NO_IP_ADDRESSES = 0xC00002F1; +pub const WRONG_CREDENTIAL_HANDLE = 0xC00002F2; +pub const CRYPTO_SYSTEM_INVALID = 0xC00002F3; +pub const MAX_REFERRALS_EXCEEDED = 0xC00002F4; +pub const MUST_BE_KDC = 0xC00002F5; +pub const STRONG_CRYPTO_NOT_SUPPORTED = 0xC00002F6; +pub const TOO_MANY_PRINCIPALS = 0xC00002F7; +pub const NO_PA_DATA = 0xC00002F8; +pub const PKINIT_NAME_MISMATCH = 0xC00002F9; +pub const SMARTCARD_LOGON_REQUIRED = 0xC00002FA; +pub const KDC_INVALID_REQUEST = 0xC00002FB; +pub const KDC_UNABLE_TO_REFER = 0xC00002FC; +pub const KDC_UNKNOWN_ETYPE = 0xC00002FD; +pub const SHUTDOWN_IN_PROGRESS = 0xC00002FE; +pub const SERVER_SHUTDOWN_IN_PROGRESS = 0xC00002FF; +pub const NOT_SUPPORTED_ON_SBS = 0xC0000300; +pub const WMI_GUID_DISCONNECTED = 0xC0000301; +pub const WMI_ALREADY_DISABLED = 0xC0000302; +pub const WMI_ALREADY_ENABLED = 0xC0000303; +pub const MFT_TOO_FRAGMENTED = 0xC0000304; +pub const COPY_PROTECTION_FAILURE = 0xC0000305; +pub const CSS_AUTHENTICATION_FAILURE = 0xC0000306; +pub const CSS_KEY_NOT_PRESENT = 0xC0000307; +pub const CSS_KEY_NOT_ESTABLISHED = 0xC0000308; +pub const CSS_SCRAMBLED_SECTOR = 0xC0000309; +pub const CSS_REGION_MISMATCH = 0xC000030A; +pub const CSS_RESETS_EXHAUSTED = 0xC000030B; +pub const PKINIT_FAILURE = 0xC0000320; +pub const SMARTCARD_SUBSYSTEM_FAILURE = 0xC0000321; +pub const NO_KERB_KEY = 0xC0000322; +pub const HOST_DOWN = 0xC0000350; +pub const UNSUPPORTED_PREAUTH = 0xC0000351; +pub const EFS_ALG_BLOB_TOO_BIG = 0xC0000352; +pub const PORT_NOT_SET = 0xC0000353; +pub const DEBUGGER_INACTIVE = 0xC0000354; +pub const DS_VERSION_CHECK_FAILURE = 0xC0000355; +pub const AUDITING_DISABLED = 0xC0000356; +pub const PRENT4_MACHINE_ACCOUNT = 0xC0000357; +pub const DS_AG_CANT_HAVE_UNIVERSAL_MEMBER = 0xC0000358; +pub const INVALID_IMAGE_WIN_32 = 0xC0000359; +pub const INVALID_IMAGE_WIN_64 = 0xC000035A; +pub const BAD_BINDINGS = 0xC000035B; +pub const NETWORK_SESSION_EXPIRED = 0xC000035C; +pub const APPHELP_BLOCK = 0xC000035D; +pub const ALL_SIDS_FILTERED = 0xC000035E; +pub const NOT_SAFE_MODE_DRIVER = 0xC000035F; +pub const ACCESS_DISABLED_BY_POLICY_DEFAULT = 0xC0000361; +pub const ACCESS_DISABLED_BY_POLICY_PATH = 0xC0000362; +pub const ACCESS_DISABLED_BY_POLICY_PUBLISHER = 0xC0000363; +pub const ACCESS_DISABLED_BY_POLICY_OTHER = 0xC0000364; +pub const FAILED_DRIVER_ENTRY = 0xC0000365; +pub const DEVICE_ENUMERATION_ERROR = 0xC0000366; +pub const MOUNT_POINT_NOT_RESOLVED = 0xC0000368; +pub const INVALID_DEVICE_OBJECT_PARAMETER = 0xC0000369; +pub const MCA_OCCURED = 0xC000036A; +pub const DRIVER_BLOCKED_CRITICAL = 0xC000036B; +pub const DRIVER_BLOCKED = 0xC000036C; +pub const DRIVER_DATABASE_ERROR = 0xC000036D; +pub const SYSTEM_HIVE_TOO_LARGE = 0xC000036E; +pub const INVALID_IMPORT_OF_NON_DLL = 0xC000036F; +pub const NO_SECRETS = 0xC0000371; +pub const ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY = 0xC0000372; +pub const FAILED_STACK_SWITCH = 0xC0000373; +pub const HEAP_CORRUPTION = 0xC0000374; +pub const SMARTCARD_WRONG_PIN = 0xC0000380; +pub const SMARTCARD_CARD_BLOCKED = 0xC0000381; +pub const SMARTCARD_CARD_NOT_AUTHENTICATED = 0xC0000382; +pub const SMARTCARD_NO_CARD = 0xC0000383; +pub const SMARTCARD_NO_KEY_CONTAINER = 0xC0000384; +pub const SMARTCARD_NO_CERTIFICATE = 0xC0000385; +pub const SMARTCARD_NO_KEYSET = 0xC0000386; +pub const SMARTCARD_IO_ERROR = 0xC0000387; +pub const DOWNGRADE_DETECTED = 0xC0000388; +pub const SMARTCARD_CERT_REVOKED = 0xC0000389; +pub const ISSUING_CA_UNTRUSTED = 0xC000038A; +pub const REVOCATION_OFFLINE_C = 0xC000038B; +pub const PKINIT_CLIENT_FAILURE = 0xC000038C; +pub const SMARTCARD_CERT_EXPIRED = 0xC000038D; +pub const DRIVER_FAILED_PRIOR_UNLOAD = 0xC000038E; +pub const SMARTCARD_SILENT_CONTEXT = 0xC000038F; +pub const PER_USER_TRUST_QUOTA_EXCEEDED = 0xC0000401; +pub const ALL_USER_TRUST_QUOTA_EXCEEDED = 0xC0000402; +pub const USER_DELETE_TRUST_QUOTA_EXCEEDED = 0xC0000403; +pub const DS_NAME_NOT_UNIQUE = 0xC0000404; +pub const DS_DUPLICATE_ID_FOUND = 0xC0000405; +pub const DS_GROUP_CONVERSION_ERROR = 0xC0000406; +pub const VOLSNAP_PREPARE_HIBERNATE = 0xC0000407; +pub const USER2USER_REQUIRED = 0xC0000408; +pub const STACK_BUFFER_OVERRUN = 0xC0000409; +pub const NO_S4U_PROT_SUPPORT = 0xC000040A; +pub const CROSSREALM_DELEGATION_FAILURE = 0xC000040B; +pub const REVOCATION_OFFLINE_KDC = 0xC000040C; +pub const ISSUING_CA_UNTRUSTED_KDC = 0xC000040D; +pub const KDC_CERT_EXPIRED = 0xC000040E; +pub const KDC_CERT_REVOKED = 0xC000040F; +pub const PARAMETER_QUOTA_EXCEEDED = 0xC0000410; +pub const HIBERNATION_FAILURE = 0xC0000411; +pub const DELAY_LOAD_FAILED = 0xC0000412; +pub const AUTHENTICATION_FIREWALL_FAILED = 0xC0000413; +pub const VDM_DISALLOWED = 0xC0000414; +pub const HUNG_DISPLAY_DRIVER_THREAD = 0xC0000415; +pub const INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE = 0xC0000416; +pub const INVALID_CRUNTIME_PARAMETER = 0xC0000417; +pub const NTLM_BLOCKED = 0xC0000418; +pub const DS_SRC_SID_EXISTS_IN_FOREST = 0xC0000419; +pub const DS_DOMAIN_NAME_EXISTS_IN_FOREST = 0xC000041A; +pub const DS_FLAT_NAME_EXISTS_IN_FOREST = 0xC000041B; +pub const INVALID_USER_PRINCIPAL_NAME = 0xC000041C; +pub const ASSERTION_FAILURE = 0xC0000420; +pub const VERIFIER_STOP = 0xC0000421; +pub const CALLBACK_POP_STACK = 0xC0000423; +pub const INCOMPATIBLE_DRIVER_BLOCKED = 0xC0000424; +pub const HIVE_UNLOADED = 0xC0000425; +pub const COMPRESSION_DISABLED = 0xC0000426; +pub const FILE_SYSTEM_LIMITATION = 0xC0000427; +pub const INVALID_IMAGE_HASH = 0xC0000428; +pub const NOT_CAPABLE = 0xC0000429; +pub const REQUEST_OUT_OF_SEQUENCE = 0xC000042A; +pub const IMPLEMENTATION_LIMIT = 0xC000042B; +pub const ELEVATION_REQUIRED = 0xC000042C; +pub const NO_SECURITY_CONTEXT = 0xC000042D; +pub const PKU2U_CERT_FAILURE = 0xC000042E; +pub const BEYOND_VDL = 0xC0000432; +pub const ENCOUNTERED_WRITE_IN_PROGRESS = 0xC0000433; +pub const PTE_CHANGED = 0xC0000434; +pub const PURGE_FAILED = 0xC0000435; +pub const CRED_REQUIRES_CONFIRMATION = 0xC0000440; +pub const CS_ENCRYPTION_INVALID_SERVER_RESPONSE = 0xC0000441; +pub const CS_ENCRYPTION_UNSUPPORTED_SERVER = 0xC0000442; +pub const CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE = 0xC0000443; +pub const CS_ENCRYPTION_NEW_ENCRYPTED_FILE = 0xC0000444; +pub const CS_ENCRYPTION_FILE_NOT_CSE = 0xC0000445; +pub const INVALID_LABEL = 0xC0000446; +pub const DRIVER_PROCESS_TERMINATED = 0xC0000450; +pub const AMBIGUOUS_SYSTEM_DEVICE = 0xC0000451; +pub const SYSTEM_DEVICE_NOT_FOUND = 0xC0000452; +pub const RESTART_BOOT_APPLICATION = 0xC0000453; +pub const INSUFFICIENT_NVRAM_RESOURCES = 0xC0000454; +pub const INVALID_TASK_NAME = 0xC0000500; +pub const INVALID_TASK_INDEX = 0xC0000501; +pub const THREAD_ALREADY_IN_TASK = 0xC0000502; +pub const CALLBACK_BYPASS = 0xC0000503; +pub const FAIL_FAST_EXCEPTION = 0xC0000602; +pub const IMAGE_CERT_REVOKED = 0xC0000603; +pub const PORT_CLOSED = 0xC0000700; +pub const MESSAGE_LOST = 0xC0000701; +pub const INVALID_MESSAGE = 0xC0000702; +pub const REQUEST_CANCELED = 0xC0000703; +pub const RECURSIVE_DISPATCH = 0xC0000704; +pub const LPC_RECEIVE_BUFFER_EXPECTED = 0xC0000705; +pub const LPC_INVALID_CONNECTION_USAGE = 0xC0000706; +pub const LPC_REQUESTS_NOT_ALLOWED = 0xC0000707; +pub const RESOURCE_IN_USE = 0xC0000708; +pub const HARDWARE_MEMORY_ERROR = 0xC0000709; +pub const THREADPOOL_HANDLE_EXCEPTION = 0xC000070A; +pub const THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED = 0xC000070B; +pub const THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED = 0xC000070C; +pub const THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED = 0xC000070D; +pub const THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED = 0xC000070E; +pub const THREADPOOL_RELEASED_DURING_OPERATION = 0xC000070F; +pub const CALLBACK_RETURNED_WHILE_IMPERSONATING = 0xC0000710; +pub const APC_RETURNED_WHILE_IMPERSONATING = 0xC0000711; +pub const PROCESS_IS_PROTECTED = 0xC0000712; +pub const MCA_EXCEPTION = 0xC0000713; +pub const CERTIFICATE_MAPPING_NOT_UNIQUE = 0xC0000714; +pub const SYMLINK_CLASS_DISABLED = 0xC0000715; +pub const INVALID_IDN_NORMALIZATION = 0xC0000716; +pub const NO_UNICODE_TRANSLATION = 0xC0000717; +pub const ALREADY_REGISTERED = 0xC0000718; +pub const CONTEXT_MISMATCH = 0xC0000719; +pub const PORT_ALREADY_HAS_COMPLETION_LIST = 0xC000071A; +pub const CALLBACK_RETURNED_THREAD_PRIORITY = 0xC000071B; +pub const INVALID_THREAD = 0xC000071C; +pub const CALLBACK_RETURNED_TRANSACTION = 0xC000071D; +pub const CALLBACK_RETURNED_LDR_LOCK = 0xC000071E; +pub const CALLBACK_RETURNED_LANG = 0xC000071F; +pub const CALLBACK_RETURNED_PRI_BACK = 0xC0000720; +pub const DISK_REPAIR_DISABLED = 0xC0000800; +pub const DS_DOMAIN_RENAME_IN_PROGRESS = 0xC0000801; +pub const DISK_QUOTA_EXCEEDED = 0xC0000802; +pub const CONTENT_BLOCKED = 0xC0000804; +pub const BAD_CLUSTERS = 0xC0000805; +pub const VOLUME_DIRTY = 0xC0000806; +pub const FILE_CHECKED_OUT = 0xC0000901; +pub const CHECKOUT_REQUIRED = 0xC0000902; +pub const BAD_FILE_TYPE = 0xC0000903; +pub const FILE_TOO_LARGE = 0xC0000904; +pub const FORMS_AUTH_REQUIRED = 0xC0000905; +pub const VIRUS_INFECTED = 0xC0000906; +pub const VIRUS_DELETED = 0xC0000907; +pub const BAD_MCFG_TABLE = 0xC0000908; +pub const CANNOT_BREAK_OPLOCK = 0xC0000909; +pub const WOW_ASSERTION = 0xC0009898; +pub const INVALID_SIGNATURE = 0xC000A000; +pub const HMAC_NOT_SUPPORTED = 0xC000A001; +pub const IPSEC_QUEUE_OVERFLOW = 0xC000A010; +pub const ND_QUEUE_OVERFLOW = 0xC000A011; +pub const HOPLIMIT_EXCEEDED = 0xC000A012; +pub const PROTOCOL_NOT_SUPPORTED = 0xC000A013; +pub const LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED = 0xC000A080; +pub const LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR = 0xC000A081; +pub const LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR = 0xC000A082; +pub const XML_PARSE_ERROR = 0xC000A083; +pub const XMLDSIG_ERROR = 0xC000A084; +pub const WRONG_COMPARTMENT = 0xC000A085; +pub const AUTHIP_FAILURE = 0xC000A086; +pub const DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS = 0xC000A087; +pub const DS_OID_NOT_FOUND = 0xC000A088; +pub const HASH_NOT_SUPPORTED = 0xC000A100; +pub const HASH_NOT_PRESENT = 0xC000A101; +pub const PNP_BAD_MPS_TABLE = 0xC0040035; +pub const PNP_TRANSLATION_FAILED = 0xC0040036; +pub const PNP_IRQ_TRANSLATION_FAILED = 0xC0040037; +pub const PNP_INVALID_ID = 0xC0040038; +pub const IO_REISSUE_AS_CACHED = 0xC0040039; +pub const CTX_WINSTATION_NAME_INVALID = 0xC00A0001; +pub const CTX_INVALID_PD = 0xC00A0002; +pub const CTX_PD_NOT_FOUND = 0xC00A0003; +pub const CTX_CLOSE_PENDING = 0xC00A0006; +pub const CTX_NO_OUTBUF = 0xC00A0007; +pub const CTX_MODEM_INF_NOT_FOUND = 0xC00A0008; +pub const CTX_INVALID_MODEMNAME = 0xC00A0009; +pub const CTX_RESPONSE_ERROR = 0xC00A000A; +pub const CTX_MODEM_RESPONSE_TIMEOUT = 0xC00A000B; +pub const CTX_MODEM_RESPONSE_NO_CARRIER = 0xC00A000C; +pub const CTX_MODEM_RESPONSE_NO_DIALTONE = 0xC00A000D; +pub const CTX_MODEM_RESPONSE_BUSY = 0xC00A000E; +pub const CTX_MODEM_RESPONSE_VOICE = 0xC00A000F; +pub const CTX_TD_ERROR = 0xC00A0010; +pub const CTX_LICENSE_CLIENT_INVALID = 0xC00A0012; +pub const CTX_LICENSE_NOT_AVAILABLE = 0xC00A0013; +pub const CTX_LICENSE_EXPIRED = 0xC00A0014; +pub const CTX_WINSTATION_NOT_FOUND = 0xC00A0015; +pub const CTX_WINSTATION_NAME_COLLISION = 0xC00A0016; +pub const CTX_WINSTATION_BUSY = 0xC00A0017; +pub const CTX_BAD_VIDEO_MODE = 0xC00A0018; +pub const CTX_GRAPHICS_INVALID = 0xC00A0022; +pub const CTX_NOT_CONSOLE = 0xC00A0024; +pub const CTX_CLIENT_QUERY_TIMEOUT = 0xC00A0026; +pub const CTX_CONSOLE_DISCONNECT = 0xC00A0027; +pub const CTX_CONSOLE_CONNECT = 0xC00A0028; +pub const CTX_SHADOW_DENIED = 0xC00A002A; +pub const CTX_WINSTATION_ACCESS_DENIED = 0xC00A002B; +pub const CTX_INVALID_WD = 0xC00A002E; +pub const CTX_WD_NOT_FOUND = 0xC00A002F; +pub const CTX_SHADOW_INVALID = 0xC00A0030; +pub const CTX_SHADOW_DISABLED = 0xC00A0031; +pub const RDP_PROTOCOL_ERROR = 0xC00A0032; +pub const CTX_CLIENT_LICENSE_NOT_SET = 0xC00A0033; +pub const CTX_CLIENT_LICENSE_IN_USE = 0xC00A0034; +pub const CTX_SHADOW_ENDED_BY_MODE_CHANGE = 0xC00A0035; +pub const CTX_SHADOW_NOT_RUNNING = 0xC00A0036; +pub const CTX_LOGON_DISABLED = 0xC00A0037; +pub const CTX_SECURITY_LAYER_ERROR = 0xC00A0038; +pub const TS_INCOMPATIBLE_SESSIONS = 0xC00A0039; +pub const MUI_FILE_NOT_FOUND = 0xC00B0001; +pub const MUI_INVALID_FILE = 0xC00B0002; +pub const MUI_INVALID_RC_CONFIG = 0xC00B0003; +pub const MUI_INVALID_LOCALE_NAME = 0xC00B0004; +pub const MUI_INVALID_ULTIMATEFALLBACK_NAME = 0xC00B0005; +pub const MUI_FILE_NOT_LOADED = 0xC00B0006; +pub const RESOURCE_ENUM_USER_STOP = 0xC00B0007; +pub const CLUSTER_INVALID_NODE = 0xC0130001; +pub const CLUSTER_NODE_EXISTS = 0xC0130002; +pub const CLUSTER_JOIN_IN_PROGRESS = 0xC0130003; +pub const CLUSTER_NODE_NOT_FOUND = 0xC0130004; +pub const CLUSTER_LOCAL_NODE_NOT_FOUND = 0xC0130005; +pub const CLUSTER_NETWORK_EXISTS = 0xC0130006; +pub const CLUSTER_NETWORK_NOT_FOUND = 0xC0130007; +pub const CLUSTER_NETINTERFACE_EXISTS = 0xC0130008; +pub const CLUSTER_NETINTERFACE_NOT_FOUND = 0xC0130009; +pub const CLUSTER_INVALID_REQUEST = 0xC013000A; +pub const CLUSTER_INVALID_NETWORK_PROVIDER = 0xC013000B; +pub const CLUSTER_NODE_DOWN = 0xC013000C; +pub const CLUSTER_NODE_UNREACHABLE = 0xC013000D; +pub const CLUSTER_NODE_NOT_MEMBER = 0xC013000E; +pub const CLUSTER_JOIN_NOT_IN_PROGRESS = 0xC013000F; +pub const CLUSTER_INVALID_NETWORK = 0xC0130010; +pub const CLUSTER_NO_NET_ADAPTERS = 0xC0130011; +pub const CLUSTER_NODE_UP = 0xC0130012; +pub const CLUSTER_NODE_PAUSED = 0xC0130013; +pub const CLUSTER_NODE_NOT_PAUSED = 0xC0130014; +pub const CLUSTER_NO_SECURITY_CONTEXT = 0xC0130015; +pub const CLUSTER_NETWORK_NOT_INTERNAL = 0xC0130016; +pub const CLUSTER_POISONED = 0xC0130017; +pub const ACPI_INVALID_OPCODE = 0xC0140001; +pub const ACPI_STACK_OVERFLOW = 0xC0140002; +pub const ACPI_ASSERT_FAILED = 0xC0140003; +pub const ACPI_INVALID_INDEX = 0xC0140004; +pub const ACPI_INVALID_ARGUMENT = 0xC0140005; +pub const ACPI_FATAL = 0xC0140006; +pub const ACPI_INVALID_SUPERNAME = 0xC0140007; +pub const ACPI_INVALID_ARGTYPE = 0xC0140008; +pub const ACPI_INVALID_OBJTYPE = 0xC0140009; +pub const ACPI_INVALID_TARGETTYPE = 0xC014000A; +pub const ACPI_INCORRECT_ARGUMENT_COUNT = 0xC014000B; +pub const ACPI_ADDRESS_NOT_MAPPED = 0xC014000C; +pub const ACPI_INVALID_EVENTTYPE = 0xC014000D; +pub const ACPI_HANDLER_COLLISION = 0xC014000E; +pub const ACPI_INVALID_DATA = 0xC014000F; +pub const ACPI_INVALID_REGION = 0xC0140010; +pub const ACPI_INVALID_ACCESS_SIZE = 0xC0140011; +pub const ACPI_ACQUIRE_GLOBAL_LOCK = 0xC0140012; +pub const ACPI_ALREADY_INITIALIZED = 0xC0140013; +pub const ACPI_NOT_INITIALIZED = 0xC0140014; +pub const ACPI_INVALID_MUTEX_LEVEL = 0xC0140015; +pub const ACPI_MUTEX_NOT_OWNED = 0xC0140016; +pub const ACPI_MUTEX_NOT_OWNER = 0xC0140017; +pub const ACPI_RS_ACCESS = 0xC0140018; +pub const ACPI_INVALID_TABLE = 0xC0140019; +pub const ACPI_REG_HANDLER_FAILED = 0xC0140020; +pub const ACPI_POWER_REQUEST_FAILED = 0xC0140021; +pub const SXS_SECTION_NOT_FOUND = 0xC0150001; +pub const SXS_CANT_GEN_ACTCTX = 0xC0150002; +pub const SXS_INVALID_ACTCTXDATA_FORMAT = 0xC0150003; +pub const SXS_ASSEMBLY_NOT_FOUND = 0xC0150004; +pub const SXS_MANIFEST_FORMAT_ERROR = 0xC0150005; +pub const SXS_MANIFEST_PARSE_ERROR = 0xC0150006; +pub const SXS_ACTIVATION_CONTEXT_DISABLED = 0xC0150007; +pub const SXS_KEY_NOT_FOUND = 0xC0150008; +pub const SXS_VERSION_CONFLICT = 0xC0150009; +pub const SXS_WRONG_SECTION_TYPE = 0xC015000A; +pub const SXS_THREAD_QUERIES_DISABLED = 0xC015000B; +pub const SXS_ASSEMBLY_MISSING = 0xC015000C; +pub const SXS_PROCESS_DEFAULT_ALREADY_SET = 0xC015000E; +pub const SXS_EARLY_DEACTIVATION = 0xC015000F; +pub const SXS_INVALID_DEACTIVATION = 0xC0150010; +pub const SXS_MULTIPLE_DEACTIVATION = 0xC0150011; +pub const SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY = 0xC0150012; +pub const SXS_PROCESS_TERMINATION_REQUESTED = 0xC0150013; +pub const SXS_CORRUPT_ACTIVATION_STACK = 0xC0150014; +pub const SXS_CORRUPTION = 0xC0150015; +pub const SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE = 0xC0150016; +pub const SXS_INVALID_IDENTITY_ATTRIBUTE_NAME = 0xC0150017; +pub const SXS_IDENTITY_DUPLICATE_ATTRIBUTE = 0xC0150018; +pub const SXS_IDENTITY_PARSE_ERROR = 0xC0150019; +pub const SXS_COMPONENT_STORE_CORRUPT = 0xC015001A; +pub const SXS_FILE_HASH_MISMATCH = 0xC015001B; +pub const SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT = 0xC015001C; +pub const SXS_IDENTITIES_DIFFERENT = 0xC015001D; +pub const SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT = 0xC015001E; +pub const SXS_FILE_NOT_PART_OF_ASSEMBLY = 0xC015001F; +pub const ADVANCED_INSTALLER_FAILED = 0xC0150020; +pub const XML_ENCODING_MISMATCH = 0xC0150021; +pub const SXS_MANIFEST_TOO_BIG = 0xC0150022; +pub const SXS_SETTING_NOT_REGISTERED = 0xC0150023; +pub const SXS_TRANSACTION_CLOSURE_INCOMPLETE = 0xC0150024; +pub const SMI_PRIMITIVE_INSTALLER_FAILED = 0xC0150025; +pub const GENERIC_COMMAND_FAILED = 0xC0150026; +pub const SXS_FILE_HASH_MISSING = 0xC0150027; +pub const TRANSACTIONAL_CONFLICT = 0xC0190001; +pub const INVALID_TRANSACTION = 0xC0190002; +pub const TRANSACTION_NOT_ACTIVE = 0xC0190003; +pub const TM_INITIALIZATION_FAILED = 0xC0190004; +pub const RM_NOT_ACTIVE = 0xC0190005; +pub const RM_METADATA_CORRUPT = 0xC0190006; +pub const TRANSACTION_NOT_JOINED = 0xC0190007; +pub const DIRECTORY_NOT_RM = 0xC0190008; +pub const TRANSACTIONS_UNSUPPORTED_REMOTE = 0xC019000A; +pub const LOG_RESIZE_INVALID_SIZE = 0xC019000B; +pub const REMOTE_FILE_VERSION_MISMATCH = 0xC019000C; +pub const CRM_PROTOCOL_ALREADY_EXISTS = 0xC019000F; +pub const TRANSACTION_PROPAGATION_FAILED = 0xC0190010; +pub const CRM_PROTOCOL_NOT_FOUND = 0xC0190011; +pub const TRANSACTION_SUPERIOR_EXISTS = 0xC0190012; +pub const TRANSACTION_REQUEST_NOT_VALID = 0xC0190013; +pub const TRANSACTION_NOT_REQUESTED = 0xC0190014; +pub const TRANSACTION_ALREADY_ABORTED = 0xC0190015; +pub const TRANSACTION_ALREADY_COMMITTED = 0xC0190016; +pub const TRANSACTION_INVALID_MARSHALL_BUFFER = 0xC0190017; +pub const CURRENT_TRANSACTION_NOT_VALID = 0xC0190018; +pub const LOG_GROWTH_FAILED = 0xC0190019; +pub const OBJECT_NO_LONGER_EXISTS = 0xC0190021; +pub const STREAM_MINIVERSION_NOT_FOUND = 0xC0190022; +pub const STREAM_MINIVERSION_NOT_VALID = 0xC0190023; +pub const MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION = 0xC0190024; +pub const CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT = 0xC0190025; +pub const CANT_CREATE_MORE_STREAM_MINIVERSIONS = 0xC0190026; +pub const HANDLE_NO_LONGER_VALID = 0xC0190028; +pub const LOG_CORRUPTION_DETECTED = 0xC0190030; +pub const RM_DISCONNECTED = 0xC0190032; +pub const ENLISTMENT_NOT_SUPERIOR = 0xC0190033; +pub const FILE_IDENTITY_NOT_PERSISTENT = 0xC0190036; +pub const CANT_BREAK_TRANSACTIONAL_DEPENDENCY = 0xC0190037; +pub const CANT_CROSS_RM_BOUNDARY = 0xC0190038; +pub const TXF_DIR_NOT_EMPTY = 0xC0190039; +pub const INDOUBT_TRANSACTIONS_EXIST = 0xC019003A; +pub const TM_VOLATILE = 0xC019003B; +pub const ROLLBACK_TIMER_EXPIRED = 0xC019003C; +pub const TXF_ATTRIBUTE_CORRUPT = 0xC019003D; +pub const EFS_NOT_ALLOWED_IN_TRANSACTION = 0xC019003E; +pub const TRANSACTIONAL_OPEN_NOT_ALLOWED = 0xC019003F; +pub const TRANSACTED_MAPPING_UNSUPPORTED_REMOTE = 0xC0190040; +pub const TRANSACTION_REQUIRED_PROMOTION = 0xC0190043; +pub const CANNOT_EXECUTE_FILE_IN_TRANSACTION = 0xC0190044; +pub const TRANSACTIONS_NOT_FROZEN = 0xC0190045; +pub const TRANSACTION_FREEZE_IN_PROGRESS = 0xC0190046; +pub const NOT_SNAPSHOT_VOLUME = 0xC0190047; +pub const NO_SAVEPOINT_WITH_OPEN_FILES = 0xC0190048; +pub const SPARSE_NOT_ALLOWED_IN_TRANSACTION = 0xC0190049; +pub const TM_IDENTITY_MISMATCH = 0xC019004A; +pub const FLOATED_SECTION = 0xC019004B; +pub const CANNOT_ACCEPT_TRANSACTED_WORK = 0xC019004C; +pub const CANNOT_ABORT_TRANSACTIONS = 0xC019004D; +pub const TRANSACTION_NOT_FOUND = 0xC019004E; +pub const RESOURCEMANAGER_NOT_FOUND = 0xC019004F; +pub const ENLISTMENT_NOT_FOUND = 0xC0190050; +pub const TRANSACTIONMANAGER_NOT_FOUND = 0xC0190051; +pub const TRANSACTIONMANAGER_NOT_ONLINE = 0xC0190052; +pub const TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION = 0xC0190053; +pub const TRANSACTION_NOT_ROOT = 0xC0190054; +pub const TRANSACTION_OBJECT_EXPIRED = 0xC0190055; +pub const COMPRESSION_NOT_ALLOWED_IN_TRANSACTION = 0xC0190056; +pub const TRANSACTION_RESPONSE_NOT_ENLISTED = 0xC0190057; +pub const TRANSACTION_RECORD_TOO_LONG = 0xC0190058; +pub const NO_LINK_TRACKING_IN_TRANSACTION = 0xC0190059; +pub const OPERATION_NOT_SUPPORTED_IN_TRANSACTION = 0xC019005A; +pub const TRANSACTION_INTEGRITY_VIOLATED = 0xC019005B; +pub const EXPIRED_HANDLE = 0xC0190060; +pub const TRANSACTION_NOT_ENLISTED = 0xC0190061; +pub const LOG_SECTOR_INVALID = 0xC01A0001; +pub const LOG_SECTOR_PARITY_INVALID = 0xC01A0002; +pub const LOG_SECTOR_REMAPPED = 0xC01A0003; +pub const LOG_BLOCK_INCOMPLETE = 0xC01A0004; +pub const LOG_INVALID_RANGE = 0xC01A0005; +pub const LOG_BLOCKS_EXHAUSTED = 0xC01A0006; +pub const LOG_READ_CONTEXT_INVALID = 0xC01A0007; +pub const LOG_RESTART_INVALID = 0xC01A0008; +pub const LOG_BLOCK_VERSION = 0xC01A0009; +pub const LOG_BLOCK_INVALID = 0xC01A000A; +pub const LOG_READ_MODE_INVALID = 0xC01A000B; +pub const LOG_METADATA_CORRUPT = 0xC01A000D; +pub const LOG_METADATA_INVALID = 0xC01A000E; +pub const LOG_METADATA_INCONSISTENT = 0xC01A000F; +pub const LOG_RESERVATION_INVALID = 0xC01A0010; +pub const LOG_CANT_DELETE = 0xC01A0011; +pub const LOG_CONTAINER_LIMIT_EXCEEDED = 0xC01A0012; +pub const LOG_START_OF_LOG = 0xC01A0013; +pub const LOG_POLICY_ALREADY_INSTALLED = 0xC01A0014; +pub const LOG_POLICY_NOT_INSTALLED = 0xC01A0015; +pub const LOG_POLICY_INVALID = 0xC01A0016; +pub const LOG_POLICY_CONFLICT = 0xC01A0017; +pub const LOG_PINNED_ARCHIVE_TAIL = 0xC01A0018; +pub const LOG_RECORD_NONEXISTENT = 0xC01A0019; +pub const LOG_RECORDS_RESERVED_INVALID = 0xC01A001A; +pub const LOG_SPACE_RESERVED_INVALID = 0xC01A001B; +pub const LOG_TAIL_INVALID = 0xC01A001C; +pub const LOG_FULL = 0xC01A001D; +pub const LOG_MULTIPLEXED = 0xC01A001E; +pub const LOG_DEDICATED = 0xC01A001F; +pub const LOG_ARCHIVE_NOT_IN_PROGRESS = 0xC01A0020; +pub const LOG_ARCHIVE_IN_PROGRESS = 0xC01A0021; +pub const LOG_EPHEMERAL = 0xC01A0022; +pub const LOG_NOT_ENOUGH_CONTAINERS = 0xC01A0023; +pub const LOG_CLIENT_ALREADY_REGISTERED = 0xC01A0024; +pub const LOG_CLIENT_NOT_REGISTERED = 0xC01A0025; +pub const LOG_FULL_HANDLER_IN_PROGRESS = 0xC01A0026; +pub const LOG_CONTAINER_READ_FAILED = 0xC01A0027; +pub const LOG_CONTAINER_WRITE_FAILED = 0xC01A0028; +pub const LOG_CONTAINER_OPEN_FAILED = 0xC01A0029; +pub const LOG_CONTAINER_STATE_INVALID = 0xC01A002A; +pub const LOG_STATE_INVALID = 0xC01A002B; +pub const LOG_PINNED = 0xC01A002C; +pub const LOG_METADATA_FLUSH_FAILED = 0xC01A002D; +pub const LOG_INCONSISTENT_SECURITY = 0xC01A002E; +pub const LOG_APPENDED_FLUSH_FAILED = 0xC01A002F; +pub const LOG_PINNED_RESERVATION = 0xC01A0030; +pub const VIDEO_HUNG_DISPLAY_DRIVER_THREAD = 0xC01B00EA; +pub const FLT_NO_HANDLER_DEFINED = 0xC01C0001; +pub const FLT_CONTEXT_ALREADY_DEFINED = 0xC01C0002; +pub const FLT_INVALID_ASYNCHRONOUS_REQUEST = 0xC01C0003; +pub const FLT_DISALLOW_FAST_IO = 0xC01C0004; +pub const FLT_INVALID_NAME_REQUEST = 0xC01C0005; +pub const FLT_NOT_SAFE_TO_POST_OPERATION = 0xC01C0006; +pub const FLT_NOT_INITIALIZED = 0xC01C0007; +pub const FLT_FILTER_NOT_READY = 0xC01C0008; +pub const FLT_POST_OPERATION_CLEANUP = 0xC01C0009; +pub const FLT_INTERNAL_ERROR = 0xC01C000A; +pub const FLT_DELETING_OBJECT = 0xC01C000B; +pub const FLT_MUST_BE_NONPAGED_POOL = 0xC01C000C; +pub const FLT_DUPLICATE_ENTRY = 0xC01C000D; +pub const FLT_CBDQ_DISABLED = 0xC01C000E; +pub const FLT_DO_NOT_ATTACH = 0xC01C000F; +pub const FLT_DO_NOT_DETACH = 0xC01C0010; +pub const FLT_INSTANCE_ALTITUDE_COLLISION = 0xC01C0011; +pub const FLT_INSTANCE_NAME_COLLISION = 0xC01C0012; +pub const FLT_FILTER_NOT_FOUND = 0xC01C0013; +pub const FLT_VOLUME_NOT_FOUND = 0xC01C0014; +pub const FLT_INSTANCE_NOT_FOUND = 0xC01C0015; +pub const FLT_CONTEXT_ALLOCATION_NOT_FOUND = 0xC01C0016; +pub const FLT_INVALID_CONTEXT_REGISTRATION = 0xC01C0017; +pub const FLT_NAME_CACHE_MISS = 0xC01C0018; +pub const FLT_NO_DEVICE_OBJECT = 0xC01C0019; +pub const FLT_VOLUME_ALREADY_MOUNTED = 0xC01C001A; +pub const FLT_ALREADY_ENLISTED = 0xC01C001B; +pub const FLT_CONTEXT_ALREADY_LINKED = 0xC01C001C; +pub const FLT_NO_WAITER_FOR_REPLY = 0xC01C0020; +pub const MONITOR_NO_DESCRIPTOR = 0xC01D0001; +pub const MONITOR_UNKNOWN_DESCRIPTOR_FORMAT = 0xC01D0002; +pub const MONITOR_INVALID_DESCRIPTOR_CHECKSUM = 0xC01D0003; +pub const MONITOR_INVALID_STANDARD_TIMING_BLOCK = 0xC01D0004; +pub const MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED = 0xC01D0005; +pub const MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK = 0xC01D0006; +pub const MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK = 0xC01D0007; +pub const MONITOR_NO_MORE_DESCRIPTOR_DATA = 0xC01D0008; +pub const MONITOR_INVALID_DETAILED_TIMING_BLOCK = 0xC01D0009; +pub const MONITOR_INVALID_MANUFACTURE_DATE = 0xC01D000A; +pub const GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER = 0xC01E0000; +pub const GRAPHICS_INSUFFICIENT_DMA_BUFFER = 0xC01E0001; +pub const GRAPHICS_INVALID_DISPLAY_ADAPTER = 0xC01E0002; +pub const GRAPHICS_ADAPTER_WAS_RESET = 0xC01E0003; +pub const GRAPHICS_INVALID_DRIVER_MODEL = 0xC01E0004; +pub const GRAPHICS_PRESENT_MODE_CHANGED = 0xC01E0005; +pub const GRAPHICS_PRESENT_OCCLUDED = 0xC01E0006; +pub const GRAPHICS_PRESENT_DENIED = 0xC01E0007; +pub const GRAPHICS_CANNOTCOLORCONVERT = 0xC01E0008; +pub const GRAPHICS_PRESENT_REDIRECTION_DISABLED = 0xC01E000B; +pub const GRAPHICS_PRESENT_UNOCCLUDED = 0xC01E000C; +pub const GRAPHICS_NO_VIDEO_MEMORY = 0xC01E0100; +pub const GRAPHICS_CANT_LOCK_MEMORY = 0xC01E0101; +pub const GRAPHICS_ALLOCATION_BUSY = 0xC01E0102; +pub const GRAPHICS_TOO_MANY_REFERENCES = 0xC01E0103; +pub const GRAPHICS_TRY_AGAIN_LATER = 0xC01E0104; +pub const GRAPHICS_TRY_AGAIN_NOW = 0xC01E0105; +pub const GRAPHICS_ALLOCATION_INVALID = 0xC01E0106; +pub const GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE = 0xC01E0107; +pub const GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED = 0xC01E0108; +pub const GRAPHICS_CANT_EVICT_PINNED_ALLOCATION = 0xC01E0109; +pub const GRAPHICS_INVALID_ALLOCATION_USAGE = 0xC01E0110; +pub const GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION = 0xC01E0111; +pub const GRAPHICS_ALLOCATION_CLOSED = 0xC01E0112; +pub const GRAPHICS_INVALID_ALLOCATION_INSTANCE = 0xC01E0113; +pub const GRAPHICS_INVALID_ALLOCATION_HANDLE = 0xC01E0114; +pub const GRAPHICS_WRONG_ALLOCATION_DEVICE = 0xC01E0115; +pub const GRAPHICS_ALLOCATION_CONTENT_LOST = 0xC01E0116; +pub const GRAPHICS_GPU_EXCEPTION_ON_DEVICE = 0xC01E0200; +pub const GRAPHICS_INVALID_VIDPN_TOPOLOGY = 0xC01E0300; +pub const GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED = 0xC01E0301; +pub const GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED = 0xC01E0302; +pub const GRAPHICS_INVALID_VIDPN = 0xC01E0303; +pub const GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE = 0xC01E0304; +pub const GRAPHICS_INVALID_VIDEO_PRESENT_TARGET = 0xC01E0305; +pub const GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED = 0xC01E0306; +pub const GRAPHICS_INVALID_VIDPN_SOURCEMODESET = 0xC01E0308; +pub const GRAPHICS_INVALID_VIDPN_TARGETMODESET = 0xC01E0309; +pub const GRAPHICS_INVALID_FREQUENCY = 0xC01E030A; +pub const GRAPHICS_INVALID_ACTIVE_REGION = 0xC01E030B; +pub const GRAPHICS_INVALID_TOTAL_REGION = 0xC01E030C; +pub const GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE = 0xC01E0310; +pub const GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE = 0xC01E0311; +pub const GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET = 0xC01E0312; +pub const GRAPHICS_PATH_ALREADY_IN_TOPOLOGY = 0xC01E0313; +pub const GRAPHICS_MODE_ALREADY_IN_MODESET = 0xC01E0314; +pub const GRAPHICS_INVALID_VIDEOPRESENTSOURCESET = 0xC01E0315; +pub const GRAPHICS_INVALID_VIDEOPRESENTTARGETSET = 0xC01E0316; +pub const GRAPHICS_SOURCE_ALREADY_IN_SET = 0xC01E0317; +pub const GRAPHICS_TARGET_ALREADY_IN_SET = 0xC01E0318; +pub const GRAPHICS_INVALID_VIDPN_PRESENT_PATH = 0xC01E0319; +pub const GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY = 0xC01E031A; +pub const GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET = 0xC01E031B; +pub const GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE = 0xC01E031C; +pub const GRAPHICS_FREQUENCYRANGE_NOT_IN_SET = 0xC01E031D; +pub const GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET = 0xC01E031F; +pub const GRAPHICS_STALE_MODESET = 0xC01E0320; +pub const GRAPHICS_INVALID_MONITOR_SOURCEMODESET = 0xC01E0321; +pub const GRAPHICS_INVALID_MONITOR_SOURCE_MODE = 0xC01E0322; +pub const GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN = 0xC01E0323; +pub const GRAPHICS_MODE_ID_MUST_BE_UNIQUE = 0xC01E0324; +pub const GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION = 0xC01E0325; +pub const GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES = 0xC01E0326; +pub const GRAPHICS_PATH_NOT_IN_TOPOLOGY = 0xC01E0327; +pub const GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE = 0xC01E0328; +pub const GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET = 0xC01E0329; +pub const GRAPHICS_INVALID_MONITORDESCRIPTORSET = 0xC01E032A; +pub const GRAPHICS_INVALID_MONITORDESCRIPTOR = 0xC01E032B; +pub const GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET = 0xC01E032C; +pub const GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET = 0xC01E032D; +pub const GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE = 0xC01E032E; +pub const GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE = 0xC01E032F; +pub const GRAPHICS_RESOURCES_NOT_RELATED = 0xC01E0330; +pub const GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE = 0xC01E0331; +pub const GRAPHICS_TARGET_ID_MUST_BE_UNIQUE = 0xC01E0332; +pub const GRAPHICS_NO_AVAILABLE_VIDPN_TARGET = 0xC01E0333; +pub const GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER = 0xC01E0334; +pub const GRAPHICS_NO_VIDPNMGR = 0xC01E0335; +pub const GRAPHICS_NO_ACTIVE_VIDPN = 0xC01E0336; +pub const GRAPHICS_STALE_VIDPN_TOPOLOGY = 0xC01E0337; +pub const GRAPHICS_MONITOR_NOT_CONNECTED = 0xC01E0338; +pub const GRAPHICS_SOURCE_NOT_IN_TOPOLOGY = 0xC01E0339; +pub const GRAPHICS_INVALID_PRIMARYSURFACE_SIZE = 0xC01E033A; +pub const GRAPHICS_INVALID_VISIBLEREGION_SIZE = 0xC01E033B; +pub const GRAPHICS_INVALID_STRIDE = 0xC01E033C; +pub const GRAPHICS_INVALID_PIXELFORMAT = 0xC01E033D; +pub const GRAPHICS_INVALID_COLORBASIS = 0xC01E033E; +pub const GRAPHICS_INVALID_PIXELVALUEACCESSMODE = 0xC01E033F; +pub const GRAPHICS_TARGET_NOT_IN_TOPOLOGY = 0xC01E0340; +pub const GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT = 0xC01E0341; +pub const GRAPHICS_VIDPN_SOURCE_IN_USE = 0xC01E0342; +pub const GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN = 0xC01E0343; +pub const GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL = 0xC01E0344; +pub const GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION = 0xC01E0345; +pub const GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED = 0xC01E0346; +pub const GRAPHICS_INVALID_GAMMA_RAMP = 0xC01E0347; +pub const GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED = 0xC01E0348; +pub const GRAPHICS_MULTISAMPLING_NOT_SUPPORTED = 0xC01E0349; +pub const GRAPHICS_MODE_NOT_IN_MODESET = 0xC01E034A; +pub const GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON = 0xC01E034D; +pub const GRAPHICS_INVALID_PATH_CONTENT_TYPE = 0xC01E034E; +pub const GRAPHICS_INVALID_COPYPROTECTION_TYPE = 0xC01E034F; +pub const GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS = 0xC01E0350; +pub const GRAPHICS_INVALID_SCANLINE_ORDERING = 0xC01E0352; +pub const GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED = 0xC01E0353; +pub const GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS = 0xC01E0354; +pub const GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT = 0xC01E0355; +pub const GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM = 0xC01E0356; +pub const GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN = 0xC01E0357; +pub const GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT = 0xC01E0358; +pub const GRAPHICS_MAX_NUM_PATHS_REACHED = 0xC01E0359; +pub const GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION = 0xC01E035A; +pub const GRAPHICS_INVALID_CLIENT_TYPE = 0xC01E035B; +pub const GRAPHICS_CLIENTVIDPN_NOT_SET = 0xC01E035C; +pub const GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED = 0xC01E0400; +pub const GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED = 0xC01E0401; +pub const GRAPHICS_NOT_A_LINKED_ADAPTER = 0xC01E0430; +pub const GRAPHICS_LEADLINK_NOT_ENUMERATED = 0xC01E0431; +pub const GRAPHICS_CHAINLINKS_NOT_ENUMERATED = 0xC01E0432; +pub const GRAPHICS_ADAPTER_CHAIN_NOT_READY = 0xC01E0433; +pub const GRAPHICS_CHAINLINKS_NOT_STARTED = 0xC01E0434; +pub const GRAPHICS_CHAINLINKS_NOT_POWERED_ON = 0xC01E0435; +pub const GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE = 0xC01E0436; +pub const GRAPHICS_NOT_POST_DEVICE_DRIVER = 0xC01E0438; +pub const GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED = 0xC01E043B; +pub const GRAPHICS_OPM_NOT_SUPPORTED = 0xC01E0500; +pub const GRAPHICS_COPP_NOT_SUPPORTED = 0xC01E0501; +pub const GRAPHICS_UAB_NOT_SUPPORTED = 0xC01E0502; +pub const GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS = 0xC01E0503; +pub const GRAPHICS_OPM_PARAMETER_ARRAY_TOO_SMALL = 0xC01E0504; +pub const GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST = 0xC01E0505; +pub const GRAPHICS_PVP_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME = 0xC01E0506; +pub const GRAPHICS_PVP_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP = 0xC01E0507; +pub const GRAPHICS_PVP_MIRRORING_DEVICES_NOT_SUPPORTED = 0xC01E0508; +pub const GRAPHICS_OPM_INVALID_POINTER = 0xC01E050A; +pub const GRAPHICS_OPM_INTERNAL_ERROR = 0xC01E050B; +pub const GRAPHICS_OPM_INVALID_HANDLE = 0xC01E050C; +pub const GRAPHICS_PVP_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE = 0xC01E050D; +pub const GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH = 0xC01E050E; +pub const GRAPHICS_OPM_SPANNING_MODE_ENABLED = 0xC01E050F; +pub const GRAPHICS_OPM_THEATER_MODE_ENABLED = 0xC01E0510; +pub const GRAPHICS_PVP_HFS_FAILED = 0xC01E0511; +pub const GRAPHICS_OPM_INVALID_SRM = 0xC01E0512; +pub const GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP = 0xC01E0513; +pub const GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP = 0xC01E0514; +pub const GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA = 0xC01E0515; +pub const GRAPHICS_OPM_HDCP_SRM_NEVER_SET = 0xC01E0516; +pub const GRAPHICS_OPM_RESOLUTION_TOO_HIGH = 0xC01E0517; +pub const GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE = 0xC01E0518; +pub const GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS = 0xC01E051A; +pub const GRAPHICS_OPM_SESSION_TYPE_CHANGE_IN_PROGRESS = 0xC01E051B; +pub const GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS = 0xC01E051C; +pub const GRAPHICS_OPM_INVALID_INFORMATION_REQUEST = 0xC01E051D; +pub const GRAPHICS_OPM_DRIVER_INTERNAL_ERROR = 0xC01E051E; +pub const GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS = 0xC01E051F; +pub const GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED = 0xC01E0520; +pub const GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST = 0xC01E0521; +pub const GRAPHICS_I2C_NOT_SUPPORTED = 0xC01E0580; +pub const GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST = 0xC01E0581; +pub const GRAPHICS_I2C_ERROR_TRANSMITTING_DATA = 0xC01E0582; +pub const GRAPHICS_I2C_ERROR_RECEIVING_DATA = 0xC01E0583; +pub const GRAPHICS_DDCCI_VCP_NOT_SUPPORTED = 0xC01E0584; +pub const GRAPHICS_DDCCI_INVALID_DATA = 0xC01E0585; +pub const GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE = 0xC01E0586; +pub const GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING = 0xC01E0587; +pub const GRAPHICS_MCA_INTERNAL_ERROR = 0xC01E0588; +pub const GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND = 0xC01E0589; +pub const GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH = 0xC01E058A; +pub const GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM = 0xC01E058B; +pub const GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE = 0xC01E058C; +pub const GRAPHICS_MONITOR_NO_LONGER_EXISTS = 0xC01E058D; +pub const GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED = 0xC01E05E0; +pub const GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME = 0xC01E05E1; +pub const GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP = 0xC01E05E2; +pub const GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED = 0xC01E05E3; +pub const GRAPHICS_INVALID_POINTER = 0xC01E05E4; +pub const GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE = 0xC01E05E5; +pub const GRAPHICS_PARAMETER_ARRAY_TOO_SMALL = 0xC01E05E6; +pub const GRAPHICS_INTERNAL_ERROR = 0xC01E05E7; +pub const GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS = 0xC01E05E8; +pub const FVE_LOCKED_VOLUME = 0xC0210000; +pub const FVE_NOT_ENCRYPTED = 0xC0210001; +pub const FVE_BAD_INFORMATION = 0xC0210002; +pub const FVE_TOO_SMALL = 0xC0210003; +pub const FVE_FAILED_WRONG_FS = 0xC0210004; +pub const FVE_FAILED_BAD_FS = 0xC0210005; +pub const FVE_FS_NOT_EXTENDED = 0xC0210006; +pub const FVE_FS_MOUNTED = 0xC0210007; +pub const FVE_NO_LICENSE = 0xC0210008; +pub const FVE_ACTION_NOT_ALLOWED = 0xC0210009; +pub const FVE_BAD_DATA = 0xC021000A; +pub const FVE_VOLUME_NOT_BOUND = 0xC021000B; +pub const FVE_NOT_DATA_VOLUME = 0xC021000C; +pub const FVE_CONV_READ_ERROR = 0xC021000D; +pub const FVE_CONV_WRITE_ERROR = 0xC021000E; +pub const FVE_OVERLAPPED_UPDATE = 0xC021000F; +pub const FVE_FAILED_SECTOR_SIZE = 0xC0210010; +pub const FVE_FAILED_AUTHENTICATION = 0xC0210011; +pub const FVE_NOT_OS_VOLUME = 0xC0210012; +pub const FVE_KEYFILE_NOT_FOUND = 0xC0210013; +pub const FVE_KEYFILE_INVALID = 0xC0210014; +pub const FVE_KEYFILE_NO_VMK = 0xC0210015; +pub const FVE_TPM_DISABLED = 0xC0210016; +pub const FVE_TPM_SRK_AUTH_NOT_ZERO = 0xC0210017; +pub const FVE_TPM_INVALID_PCR = 0xC0210018; +pub const FVE_TPM_NO_VMK = 0xC0210019; +pub const FVE_PIN_INVALID = 0xC021001A; +pub const FVE_AUTH_INVALID_APPLICATION = 0xC021001B; +pub const FVE_AUTH_INVALID_CONFIG = 0xC021001C; +pub const FVE_DEBUGGER_ENABLED = 0xC021001D; +pub const FVE_DRY_RUN_FAILED = 0xC021001E; +pub const FVE_BAD_METADATA_POINTER = 0xC021001F; +pub const FVE_OLD_METADATA_COPY = 0xC0210020; +pub const FVE_REBOOT_REQUIRED = 0xC0210021; +pub const FVE_RAW_ACCESS = 0xC0210022; +pub const FVE_RAW_BLOCKED = 0xC0210023; +pub const FVE_NO_FEATURE_LICENSE = 0xC0210026; +pub const FVE_POLICY_USER_DISABLE_RDV_NOT_ALLOWED = 0xC0210027; +pub const FVE_CONV_RECOVERY_FAILED = 0xC0210028; +pub const FVE_VIRTUALIZED_SPACE_TOO_BIG = 0xC0210029; +pub const FVE_VOLUME_TOO_SMALL = 0xC0210030; +pub const FWP_CALLOUT_NOT_FOUND = 0xC0220001; +pub const FWP_CONDITION_NOT_FOUND = 0xC0220002; +pub const FWP_FILTER_NOT_FOUND = 0xC0220003; +pub const FWP_LAYER_NOT_FOUND = 0xC0220004; +pub const FWP_PROVIDER_NOT_FOUND = 0xC0220005; +pub const FWP_PROVIDER_CONTEXT_NOT_FOUND = 0xC0220006; +pub const FWP_SUBLAYER_NOT_FOUND = 0xC0220007; +pub const FWP_NOT_FOUND = 0xC0220008; +pub const FWP_ALREADY_EXISTS = 0xC0220009; +pub const FWP_IN_USE = 0xC022000A; +pub const FWP_DYNAMIC_SESSION_IN_PROGRESS = 0xC022000B; +pub const FWP_WRONG_SESSION = 0xC022000C; +pub const FWP_NO_TXN_IN_PROGRESS = 0xC022000D; +pub const FWP_TXN_IN_PROGRESS = 0xC022000E; +pub const FWP_TXN_ABORTED = 0xC022000F; +pub const FWP_SESSION_ABORTED = 0xC0220010; +pub const FWP_INCOMPATIBLE_TXN = 0xC0220011; +pub const FWP_TIMEOUT = 0xC0220012; +pub const FWP_NET_EVENTS_DISABLED = 0xC0220013; +pub const FWP_INCOMPATIBLE_LAYER = 0xC0220014; +pub const FWP_KM_CLIENTS_ONLY = 0xC0220015; +pub const FWP_LIFETIME_MISMATCH = 0xC0220016; +pub const FWP_BUILTIN_OBJECT = 0xC0220017; +pub const FWP_TOO_MANY_BOOTTIME_FILTERS = 0xC0220018; +pub const FWP_TOO_MANY_CALLOUTS = 0xC0220018; +pub const FWP_NOTIFICATION_DROPPED = 0xC0220019; +pub const FWP_TRAFFIC_MISMATCH = 0xC022001A; +pub const FWP_INCOMPATIBLE_SA_STATE = 0xC022001B; +pub const FWP_NULL_POINTER = 0xC022001C; +pub const FWP_INVALID_ENUMERATOR = 0xC022001D; +pub const FWP_INVALID_FLAGS = 0xC022001E; +pub const FWP_INVALID_NET_MASK = 0xC022001F; +pub const FWP_INVALID_RANGE = 0xC0220020; +pub const FWP_INVALID_INTERVAL = 0xC0220021; +pub const FWP_ZERO_LENGTH_ARRAY = 0xC0220022; +pub const FWP_NULL_DISPLAY_NAME = 0xC0220023; +pub const FWP_INVALID_ACTION_TYPE = 0xC0220024; +pub const FWP_INVALID_WEIGHT = 0xC0220025; +pub const FWP_MATCH_TYPE_MISMATCH = 0xC0220026; +pub const FWP_TYPE_MISMATCH = 0xC0220027; +pub const FWP_OUT_OF_BOUNDS = 0xC0220028; +pub const FWP_RESERVED = 0xC0220029; +pub const FWP_DUPLICATE_CONDITION = 0xC022002A; +pub const FWP_DUPLICATE_KEYMOD = 0xC022002B; +pub const FWP_ACTION_INCOMPATIBLE_WITH_LAYER = 0xC022002C; +pub const FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER = 0xC022002D; +pub const FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER = 0xC022002E; +pub const FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT = 0xC022002F; +pub const FWP_INCOMPATIBLE_AUTH_METHOD = 0xC0220030; +pub const FWP_INCOMPATIBLE_DH_GROUP = 0xC0220031; +pub const FWP_EM_NOT_SUPPORTED = 0xC0220032; +pub const FWP_NEVER_MATCH = 0xC0220033; +pub const FWP_PROVIDER_CONTEXT_MISMATCH = 0xC0220034; +pub const FWP_INVALID_PARAMETER = 0xC0220035; +pub const FWP_TOO_MANY_SUBLAYERS = 0xC0220036; +pub const FWP_CALLOUT_NOTIFICATION_FAILED = 0xC0220037; +pub const FWP_INCOMPATIBLE_AUTH_CONFIG = 0xC0220038; +pub const FWP_INCOMPATIBLE_CIPHER_CONFIG = 0xC0220039; +pub const FWP_DUPLICATE_AUTH_METHOD = 0xC022003C; +pub const FWP_TCPIP_NOT_READY = 0xC0220100; +pub const FWP_INJECT_HANDLE_CLOSING = 0xC0220101; +pub const FWP_INJECT_HANDLE_STALE = 0xC0220102; +pub const FWP_CANNOT_PEND = 0xC0220103; +pub const NDIS_CLOSING = 0xC0230002; +pub const NDIS_BAD_VERSION = 0xC0230004; +pub const NDIS_BAD_CHARACTERISTICS = 0xC0230005; +pub const NDIS_ADAPTER_NOT_FOUND = 0xC0230006; +pub const NDIS_OPEN_FAILED = 0xC0230007; +pub const NDIS_DEVICE_FAILED = 0xC0230008; +pub const NDIS_MULTICAST_FULL = 0xC0230009; +pub const NDIS_MULTICAST_EXISTS = 0xC023000A; +pub const NDIS_MULTICAST_NOT_FOUND = 0xC023000B; +pub const NDIS_REQUEST_ABORTED = 0xC023000C; +pub const NDIS_RESET_IN_PROGRESS = 0xC023000D; +pub const NDIS_INVALID_PACKET = 0xC023000F; +pub const NDIS_INVALID_DEVICE_REQUEST = 0xC0230010; +pub const NDIS_ADAPTER_NOT_READY = 0xC0230011; +pub const NDIS_INVALID_LENGTH = 0xC0230014; +pub const NDIS_INVALID_DATA = 0xC0230015; +pub const NDIS_BUFFER_TOO_SHORT = 0xC0230016; +pub const NDIS_INVALID_OID = 0xC0230017; +pub const NDIS_ADAPTER_REMOVED = 0xC0230018; +pub const NDIS_UNSUPPORTED_MEDIA = 0xC0230019; +pub const NDIS_GROUP_ADDRESS_IN_USE = 0xC023001A; +pub const NDIS_FILE_NOT_FOUND = 0xC023001B; +pub const NDIS_ERROR_READING_FILE = 0xC023001C; +pub const NDIS_ALREADY_MAPPED = 0xC023001D; +pub const NDIS_RESOURCE_CONFLICT = 0xC023001E; +pub const NDIS_MEDIA_DISCONNECTED = 0xC023001F; +pub const NDIS_INVALID_ADDRESS = 0xC0230022; +pub const NDIS_PAUSED = 0xC023002A; +pub const NDIS_INTERFACE_NOT_FOUND = 0xC023002B; +pub const NDIS_UNSUPPORTED_REVISION = 0xC023002C; +pub const NDIS_INVALID_PORT = 0xC023002D; +pub const NDIS_INVALID_PORT_STATE = 0xC023002E; +pub const NDIS_LOW_POWER_STATE = 0xC023002F; +pub const NDIS_NOT_SUPPORTED = 0xC02300BB; +pub const NDIS_OFFLOAD_POLICY = 0xC023100F; +pub const NDIS_OFFLOAD_CONNECTION_REJECTED = 0xC0231012; +pub const NDIS_OFFLOAD_PATH_REJECTED = 0xC0231013; +pub const NDIS_DOT11_AUTO_CONFIG_ENABLED = 0xC0232000; +pub const NDIS_DOT11_MEDIA_IN_USE = 0xC0232001; +pub const NDIS_DOT11_POWER_STATE_INVALID = 0xC0232002; +pub const NDIS_PM_WOL_PATTERN_LIST_FULL = 0xC0232003; +pub const NDIS_PM_PROTOCOL_OFFLOAD_LIST_FULL = 0xC0232004; +pub const IPSEC_BAD_SPI = 0xC0360001; +pub const IPSEC_SA_LIFETIME_EXPIRED = 0xC0360002; +pub const IPSEC_WRONG_SA = 0xC0360003; +pub const IPSEC_REPLAY_CHECK_FAILED = 0xC0360004; +pub const IPSEC_INVALID_PACKET = 0xC0360005; +pub const IPSEC_INTEGRITY_CHECK_FAILED = 0xC0360006; +pub const IPSEC_CLEAR_TEXT_DROP = 0xC0360007; +pub const IPSEC_AUTH_FIREWALL_DROP = 0xC0360008; +pub const IPSEC_THROTTLE_DROP = 0xC0360009; +pub const IPSEC_DOSP_BLOCK = 0xC0368000; +pub const IPSEC_DOSP_RECEIVED_MULTICAST = 0xC0368001; +pub const IPSEC_DOSP_INVALID_PACKET = 0xC0368002; +pub const IPSEC_DOSP_STATE_LOOKUP_FAILED = 0xC0368003; +pub const IPSEC_DOSP_MAX_ENTRIES = 0xC0368004; +pub const IPSEC_DOSP_KEYMOD_NOT_ALLOWED = 0xC0368005; +pub const IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES = 0xC0368006; +pub const VOLMGR_MIRROR_NOT_SUPPORTED = 0xC038005B; +pub const VOLMGR_RAID5_NOT_SUPPORTED = 0xC038005C; +pub const VIRTDISK_PROVIDER_NOT_FOUND = 0xC03A0014; +pub const VIRTDISK_NOT_VIRTUAL_DISK = 0xC03A0015; +pub const VHD_PARENT_VHD_ACCESS_DENIED = 0xC03A0016; +pub const VHD_CHILD_PARENT_SIZE_MISMATCH = 0xC03A0017; +pub const VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED = 0xC03A0018; +pub const VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT = 0xC03A0019; diff --git a/lib/std/os/windows/ws2_32.zig b/lib/std/os/windows/ws2_32.zig @@ -0,0 +1,257 @@ +usingnamespace @import("bits.zig"); + +pub const SOCKET = *@OpaqueType(); +pub const INVALID_SOCKET = @intToPtr(SOCKET, ~@as(usize, 0)); +pub const SOCKET_ERROR = -1; + +pub const WSADESCRIPTION_LEN = 256; +pub const WSASYS_STATUS_LEN = 128; + +pub const WSADATA = if (usize.bit_count == u64.bit_count) + extern struct { + wVersion: WORD, + wHighVersion: WORD, + iMaxSockets: u16, + iMaxUdpDg: u16, + lpVendorInfo: *u8, + szDescription: [WSADESCRIPTION_LEN + 1]u8, + szSystemStatus: [WSASYS_STATUS_LEN + 1]u8, + } +else + extern struct { + wVersion: WORD, + wHighVersion: WORD, + szDescription: [WSADESCRIPTION_LEN + 1]u8, + szSystemStatus: [WSASYS_STATUS_LEN + 1]u8, + iMaxSockets: u16, + iMaxUdpDg: u16, + lpVendorInfo: *u8, + }; + +pub const MAX_PROTOCOL_CHAIN = 7; + +pub const WSAPROTOCOLCHAIN = extern struct { + ChainLen: c_int, + ChainEntries: [MAX_PROTOCOL_CHAIN]DWORD, +}; + +pub const WSAPROTOCOL_LEN = 255; + +pub const WSAPROTOCOL_INFOA = extern struct { + dwServiceFlags1: DWORD, + dwServiceFlags2: DWORD, + dwServiceFlags3: DWORD, + dwServiceFlags4: DWORD, + dwProviderFlags: DWORD, + ProviderId: GUID, + dwCatalogEntryId: DWORD, + ProtocolChain: WSAPROTOCOLCHAIN, + iVersion: c_int, + iAddressFamily: c_int, + iMaxSockAddr: c_int, + iMinSockAddr: c_int, + iSocketType: c_int, + iProtocol: c_int, + iProtocolMaxOffset: c_int, + iNetworkByteOrder: c_int, + iSecurityScheme: c_int, + dwMessageSize: DWORD, + dwProviderReserved: DWORD, + szProtocol: [WSAPROTOCOL_LEN + 1]CHAR, +}; + +pub const WSAPROTOCOL_INFOW = extern struct { + dwServiceFlags1: DWORD, + dwServiceFlags2: DWORD, + dwServiceFlags3: DWORD, + dwServiceFlags4: DWORD, + dwProviderFlags: DWORD, + ProviderId: GUID, + dwCatalogEntryId: DWORD, + ProtocolChain: WSAPROTOCOLCHAIN, + iVersion: c_int, + iAddressFamily: c_int, + iMaxSockAddr: c_int, + iMinSockAddr: c_int, + iSocketType: c_int, + iProtocol: c_int, + iProtocolMaxOffset: c_int, + iNetworkByteOrder: c_int, + iSecurityScheme: c_int, + dwMessageSize: DWORD, + dwProviderReserved: DWORD, + szProtocol: [WSAPROTOCOL_LEN + 1]WCHAR, +}; + +pub const GROUP = u32; + +pub const SG_UNCONSTRAINED_GROUP = 0x1; +pub const SG_CONSTRAINED_GROUP = 0x2; + +pub const WSA_FLAG_OVERLAPPED = 0x01; +pub const WSA_FLAG_MULTIPOINT_C_ROOT = 0x02; +pub const WSA_FLAG_MULTIPOINT_C_LEAF = 0x04; +pub const WSA_FLAG_MULTIPOINT_D_ROOT = 0x08; +pub const WSA_FLAG_MULTIPOINT_D_LEAF = 0x10; +pub const WSA_FLAG_ACCESS_SYSTEM_SECURITY = 0x40; +pub const WSA_FLAG_NO_HANDLE_INHERIT = 0x80; + +pub const WSAEVENT = HANDLE; + +pub const WSAOVERLAPPED = extern struct { + Internal: DWORD, + InternalHigh: DWORD, + Offset: DWORD, + OffsetHigh: DWORD, + hEvent: ?WSAEVENT, +}; + +pub const WSAOVERLAPPED_COMPLETION_ROUTINE = extern fn ( + dwError: DWORD, + cbTransferred: DWORD, + lpOverlapped: *WSAOVERLAPPED, + dwFlags: DWORD +) void; + +pub const WSA_INVALID_HANDLE = 6; +pub const WSA_NOT_ENOUGH_MEMORY = 8; +pub const WSA_INVALID_PARAMETER = 87; +pub const WSA_OPERATION_ABORTED = 995; +pub const WSA_IO_INCOMPLETE = 996; +pub const WSA_IO_PENDING = 997; +pub const WSAEINTR = 10004; +pub const WSAEBADF = 10009; +pub const WSAEACCES = 10013; +pub const WSAEFAULT = 10014; +pub const WSAEINVAL = 10022; +pub const WSAEMFILE = 10024; +pub const WSAEWOULDBLOCK = 10035; +pub const WSAEINPROGRESS = 10036; +pub const WSAEALREADY = 10037; +pub const WSAENOTSOCK = 10038; +pub const WSAEDESTADDRREQ = 10039; +pub const WSAEMSGSIZE = 10040; +pub const WSAEPROTOTYPE = 10041; +pub const WSAENOPROTOOPT = 10042; +pub const WSAEPROTONOSUPPORT = 10043; +pub const WSAESOCKTNOSUPPORT = 10044; +pub const WSAEOPNOTSUPP = 10045; +pub const WSAEPFNOSUPPORT = 10046; +pub const WSAEAFNOSUPPORT = 10047; +pub const WSAEADDRINUSE = 10048; +pub const WSAEADDRNOTAVAIL = 10049; +pub const WSAENETDOWN = 10050; +pub const WSAENETUNREACH = 10051; +pub const WSAENETRESET = 10052; +pub const WSAECONNABORTED = 10053; +pub const WSAECONNRESET = 10054; +pub const WSAENOBUFS = 10055; +pub const WSAEISCONN = 10056; +pub const WSAENOTCONN = 10057; +pub const WSAESHUTDOWN = 10058; +pub const WSAETOOMANYREFS = 10059; +pub const WSAETIMEDOUT = 10060; +pub const WSAECONNREFUSED = 10061; +pub const WSAELOOP = 10062; +pub const WSAENAMETOOLONG = 10063; +pub const WSAEHOSTDOWN = 10064; +pub const WSAEHOSTUNREACH = 10065; +pub const WSAENOTEMPTY = 10066; +pub const WSAEPROCLIM = 10067; +pub const WSAEUSERS = 10068; +pub const WSAEDQUOT = 10069; +pub const WSAESTALE = 10070; +pub const WSAEREMOTE = 10071; +pub const WSASYSNOTREADY = 10091; +pub const WSAVERNOTSUPPORTED = 10092; +pub const WSANOTINITIALISED = 10093; +pub const WSAEDISCON = 10101; +pub const WSAENOMORE = 10102; +pub const WSAECANCELLED = 10103; +pub const WSAEINVALIDPROCTABLE = 10104; +pub const WSAEINVALIDPROVIDER = 10105; +pub const WSAEPROVIDERFAILEDINIT = 10106; +pub const WSASYSCALLFAILURE = 10107; +pub const WSASERVICE_NOT_FOUND = 10108; +pub const WSATYPE_NOT_FOUND = 10109; +pub const WSA_E_NO_MORE = 10110; +pub const WSA_E_CANCELLED = 10111; +pub const WSAEREFUSED = 10112; +pub const WSAHOST_NOT_FOUND = 11001; +pub const WSATRY_AGAIN = 11002; +pub const WSANO_RECOVERY = 11003; +pub const WSANO_DATA = 11004; +pub const WSA_QOS_RECEIVERS = 11005; +pub const WSA_QOS_SENDERS = 11006; +pub const WSA_QOS_NO_SENDERS = 11007; +pub const WSA_QOS_NO_RECEIVERS = 11008; +pub const WSA_QOS_REQUEST_CONFIRMED = 11009; +pub const WSA_QOS_ADMISSION_FAILURE = 11010; +pub const WSA_QOS_POLICY_FAILURE = 11011; +pub const WSA_QOS_BAD_STYLE = 11012; +pub const WSA_QOS_BAD_OBJECT = 11013; +pub const WSA_QOS_TRAFFIC_CTRL_ERROR = 11014; +pub const WSA_QOS_GENERIC_ERROR = 11015; +pub const WSA_QOS_ESERVICETYPE = 11016; +pub const WSA_QOS_EFLOWSPEC = 11017; +pub const WSA_QOS_EPROVSPECBUF = 11018; +pub const WSA_QOS_EFILTERSTYLE = 11019; +pub const WSA_QOS_EFILTERTYPE = 11020; +pub const WSA_QOS_EFILTERCOUNT = 11021; +pub const WSA_QOS_EOBJLENGTH = 11022; +pub const WSA_QOS_EFLOWCOUNT = 11023; +pub const WSA_QOS_EUNKOWNPSOBJ = 11024; +pub const WSA_QOS_EPOLICYOBJ = 11025; +pub const WSA_QOS_EFLOWDESC = 11026; +pub const WSA_QOS_EPSFLOWSPEC = 11027; +pub const WSA_QOS_EPSFILTERSPEC = 11028; +pub const WSA_QOS_ESDMODEOBJ = 11029; +pub const WSA_QOS_ESHAPERATEOBJ = 11030; +pub const WSA_QOS_RESERVED_PETYPE = 11031; + + +/// no parameters +const IOC_VOID = 0x80000000; +/// copy out parameters +const IOC_OUT = 0x40000000; +/// copy in parameters +const IOC_IN = 0x80000000; + +/// The IOCTL is a generic Windows Sockets 2 IOCTL code. New IOCTL codes defined for Windows Sockets 2 will have T == 1. +const IOC_WS2 = 0x08000000; + +pub const SIO_BASE_HANDLE = IOC_OUT | IOC_WS2 | 34; + +pub extern "ws2_32" stdcallcc fn WSAStartup( + wVersionRequired: WORD, + lpWSAData: *WSADATA, +) c_int; +pub extern "ws2_32" stdcallcc fn WSACleanup() c_int; +pub extern "ws2_32" stdcallcc fn WSAGetLastError() c_int; +pub extern "ws2_32" stdcallcc fn WSASocketA( + af: c_int, + type: c_int, + protocol: c_int, + lpProtocolInfo: ?*WSAPROTOCOL_INFOA, + g: GROUP, + dwFlags: DWORD, +) SOCKET; +pub extern "ws2_32" stdcallcc fn WSASocketW( + af: c_int, + type: c_int, + protocol: c_int, + lpProtocolInfo: ?*WSAPROTOCOL_INFOW, + g: GROUP, + dwFlags: DWORD, +) SOCKET; +pub extern "ws2_32" stdcallcc fn WSAIoctl( + s: SOCKET, + dwIoControlCode: DWORD, + lpvInBuffer: ?*const c_void, + cbInBuffer: DWORD, + lpvOutBuffer: ?LPVOID, + cbOutBuffer: DWORD, + lpcbBytesReturned: LPDWORD, + lpOverlapped: ?*WSAOVERLAPPED, + lpCompletionRoutine: ?*WSAOVERLAPPED_COMPLETION_ROUTINE, +) c_int; diff --git a/lib/std/os/zen.zig b/lib/std/os/zen.zig @@ -138,7 +138,7 @@ pub const Syscall = enum(usize) { //////////////////// pub fn exit(status: i32) noreturn { - _ = syscall1(Syscall.exit, @bitCast(usize, isize(status))); + _ = syscall1(Syscall.exit, @bitCast(usize, @as(isize, status))); unreachable; } @@ -167,7 +167,7 @@ pub fn map(v_addr: usize, p_addr: usize, size: usize, writable: bool) bool { } pub fn createThread(function: fn () void) u16 { - return u16(syscall1(Syscall.createThread, @ptrToInt(function))); + return @as(u16, syscall1(Syscall.createThread, @ptrToInt(function))); } ///////////////////////// diff --git a/lib/std/packed_int_array.zig b/lib/std/packed_int_array.zig @@ -193,7 +193,7 @@ pub fn PackedIntArrayEndian(comptime Int: type, comptime endian: builtin.Endian, ///Initialize a packed array using an unpacked array /// or, more likely, an array literal. pub fn init(ints: [int_count]Int) Self { - var self = Self(undefined); + var self = @as(Self, undefined); for (ints) |int, i| self.set(i, int); return self; } @@ -328,11 +328,11 @@ test "PackedIntArray" { const expected_bytes = ((bits * int_count) + 7) / 8; testing.expect(@sizeOf(PackedArray) == expected_bytes); - var data = PackedArray(undefined); + var data = @as(PackedArray, undefined); //write values, counting up - var i = usize(0); - var count = I(0); + var i = @as(usize, 0); + var count = @as(I, 0); while (i < data.len()) : (i += 1) { data.set(i, count); if (bits > 0) count +%= 1; @@ -352,7 +352,7 @@ test "PackedIntArray" { test "PackedIntArray init" { const PackedArray = PackedIntArray(u3, 8); var packed_array = PackedArray.init([_]u3{ 0, 1, 2, 3, 4, 5, 6, 7 }); - var i = usize(0); + var i = @as(usize, 0); while (i < packed_array.len()) : (i += 1) testing.expect(packed_array.get(i) == i); } @@ -375,8 +375,8 @@ test "PackedIntSlice" { var data = P.init(&buffer, int_count); //write values, counting up - var i = usize(0); - var count = I(0); + var i = @as(usize, 0); + var count = @as(I, 0); while (i < data.len()) : (i += 1) { data.set(i, count); if (bits > 0) count +%= 1; @@ -402,11 +402,11 @@ test "PackedIntSlice of PackedInt(Array/Slice)" { const Int = @IntType(false, bits); const PackedArray = PackedIntArray(Int, int_count); - var packed_array = PackedArray(undefined); + var packed_array = @as(PackedArray, undefined); const limit = (1 << bits); - var i = usize(0); + var i = @as(usize, 0); while (i < packed_array.len()) : (i += 1) { packed_array.set(i, @intCast(Int, i % limit)); } @@ -463,20 +463,20 @@ test "PackedIntSlice accumulating bit offsets" { // anything { const PackedArray = PackedIntArray(u3, 16); - var packed_array = PackedArray(undefined); + var packed_array = @as(PackedArray, undefined); var packed_slice = packed_array.slice(0, packed_array.len()); - var i = usize(0); + var i = @as(usize, 0); while (i < packed_array.len() - 1) : (i += 1) { packed_slice = packed_slice.slice(1, packed_slice.len()); } } { const PackedArray = PackedIntArray(u11, 88); - var packed_array = PackedArray(undefined); + var packed_array = @as(PackedArray, undefined); var packed_slice = packed_array.slice(0, packed_array.len()); - var i = usize(0); + var i = @as(usize, 0); while (i < packed_array.len() - 1) : (i += 1) { packed_slice = packed_slice.slice(1, packed_slice.len()); } @@ -493,7 +493,7 @@ test "PackedInt(Array/Slice) sliceCast" { var packed_slice_cast_9 = packed_array.slice(0, (packed_array.len() / 9) * 9).sliceCast(u9); const packed_slice_cast_3 = packed_slice_cast_9.sliceCast(u3); - var i = usize(0); + var i = @as(usize, 0); while (i < packed_slice_cast_2.len()) : (i += 1) { const val = switch (builtin.endian) { .Big => 0b01, @@ -518,8 +518,8 @@ test "PackedInt(Array/Slice) sliceCast" { i = 0; while (i < packed_slice_cast_3.len()) : (i += 1) { const val = switch (builtin.endian) { - .Big => if (i % 2 == 0) u3(0b111) else u3(0b000), - .Little => if (i % 2 == 0) u3(0b111) else u3(0b000), + .Big => if (i % 2 == 0) @as(u3, 0b111) else @as(u3, 0b000), + .Little => if (i % 2 == 0) @as(u3, 0b111) else @as(u3, 0b000), }; testing.expect(packed_slice_cast_3.get(i) == val); } @@ -541,7 +541,7 @@ test "PackedInt(Array/Slice)Endian" { testing.expect(packed_array_be.bytes[0] == 0b00000001); testing.expect(packed_array_be.bytes[1] == 0b00100011); - var i = usize(0); + var i = @as(usize, 0); while (i < packed_array_be.len()) : (i += 1) { testing.expect(packed_array_be.get(i) == i); } @@ -579,7 +579,7 @@ test "PackedInt(Array/Slice)Endian" { testing.expect(packed_array_be.bytes[3] == 0b00000001); testing.expect(packed_array_be.bytes[4] == 0b00000000); - var i = usize(0); + var i = @as(usize, 0); while (i < packed_array_be.len()) : (i += 1) { testing.expect(packed_array_be.get(i) == i); } diff --git a/lib/std/parker.zig b/lib/std/parker.zig @@ -0,0 +1,180 @@ +const std = @import("std.zig"); +const builtin = @import("builtin"); +const time = std.time; +const testing = std.testing; +const assert = std.debug.assert; +const SpinLock = std.SpinLock; +const linux = std.os.linux; +const windows = std.os.windows; + +pub const ThreadParker = switch (builtin.os) { + .linux => if (builtin.link_libc) PosixParker else LinuxParker, + .windows => WindowsParker, + else => if (builtin.link_libc) PosixParker else SpinParker, +}; + +const SpinParker = struct { + pub fn init() SpinParker { + return SpinParker{}; + } + pub fn deinit(self: *SpinParker) void {} + + pub fn unpark(self: *SpinParker, ptr: *const u32) void {} + + pub fn park(self: *SpinParker, ptr: *const u32, expected: u32) void { + var backoff = SpinLock.Backoff.init(); + while (@atomicLoad(u32, ptr, .Acquire) == expected) + backoff.yield(); + } +}; + +const LinuxParker = struct { + pub fn init() LinuxParker { + return LinuxParker{}; + } + pub fn deinit(self: *LinuxParker) void {} + + pub fn unpark(self: *LinuxParker, ptr: *const u32) void { + const rc = linux.futex_wake(@ptrCast(*const i32, ptr), linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1); + assert(linux.getErrno(rc) == 0); + } + + pub fn park(self: *LinuxParker, ptr: *const u32, expected: u32) void { + const value = @intCast(i32, expected); + while (@atomicLoad(u32, ptr, .Acquire) == expected) { + const rc = linux.futex_wait(@ptrCast(*const i32, ptr), linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG, value, null); + switch (linux.getErrno(rc)) { + 0, linux.EAGAIN => return, + linux.EINTR => continue, + linux.EINVAL => unreachable, + else => continue, + } + } + } +}; + +const WindowsParker = struct { + waiters: u32, + + pub fn init() WindowsParker { + return WindowsParker{ .waiters = 0 }; + } + pub fn deinit(self: *WindowsParker) void {} + + pub fn unpark(self: *WindowsParker, ptr: *const u32) void { + const key = @ptrCast(*const c_void, ptr); + const handle = getEventHandle() orelse return; + + var waiting = @atomicLoad(u32, &self.waiters, .Monotonic); + while (waiting != 0) { + waiting = @cmpxchgWeak(u32, &self.waiters, waiting, waiting - 1, .Acquire, .Monotonic) orelse { + const rc = windows.ntdll.NtReleaseKeyedEvent(handle, key, windows.FALSE, null); + assert(rc == 0); + return; + }; + } + } + + pub fn park(self: *WindowsParker, ptr: *const u32, expected: u32) void { + var spin = SpinLock.Backoff.init(); + const ev_handle = getEventHandle(); + const key = @ptrCast(*const c_void, ptr); + + while (@atomicLoad(u32, ptr, .Monotonic) == expected) { + if (ev_handle) |handle| { + _ = @atomicRmw(u32, &self.waiters, .Add, 1, .Release); + const rc = windows.ntdll.NtWaitForKeyedEvent(handle, key, windows.FALSE, null); + assert(rc == 0); + } else { + spin.yield(); + } + } + } + + var event_handle = std.lazyInit(windows.HANDLE); + + fn getEventHandle() ?windows.HANDLE { + if (event_handle.get()) |handle_ptr| + return handle_ptr.*; + defer event_handle.resolve(); + + const access_mask = windows.GENERIC_READ | windows.GENERIC_WRITE; + if (windows.ntdll.NtCreateKeyedEvent(&event_handle.data, access_mask, null, 0) != 0) + return null; + return event_handle.data; + } +}; + +const PosixParker = struct { + cond: c.pthread_cond_t, + mutex: c.pthread_mutex_t, + + const c = std.c; + + pub fn init() PosixParker { + return PosixParker{ + .cond = c.PTHREAD_COND_INITIALIZER, + .mutex = c.PTHREAD_MUTEX_INITIALIZER, + }; + } + + pub fn deinit(self: *PosixParker) void { + // On dragonfly, the destroy functions return EINVAL if they were initialized statically. + const retm = c.pthread_mutex_destroy(&self.mutex); + assert(retm == 0 or retm == (if (builtin.os == .dragonfly) os.EINVAL else 0)); + const retc = c.pthread_cond_destroy(&self.cond); + assert(retc == 0 or retc == (if (builtin.os == .dragonfly) os.EINVAL else 0)); + } + + pub fn unpark(self: *PosixParker, ptr: *const u32) void { + assert(c.pthread_mutex_lock(&self.mutex) == 0); + defer assert(c.pthread_mutex_unlock(&self.mutex) == 0); + assert(c.pthread_cond_signal(&self.cond) == 0); + } + + pub fn park(self: *PosixParker, ptr: *const u32, expected: u32) void { + assert(c.pthread_mutex_lock(&self.mutex) == 0); + defer assert(c.pthread_mutex_unlock(&self.mutex) == 0); + while (@atomicLoad(u32, ptr, .Acquire) == expected) + assert(c.pthread_cond_wait(&self.cond, &self.mutex) == 0); + } +}; + +test "std.ThreadParker" { + if (builtin.single_threaded) + return error.SkipZigTest; + + const Context = struct { + parker: ThreadParker, + data: u32, + + fn receiver(self: *@This()) void { + self.parker.park(&self.data, 0); // receives 1 + assert(@atomicRmw(u32, &self.data, .Xchg, 2, .SeqCst) == 1); // sends 2 + self.parker.unpark(&self.data); // wakes up waiters on 2 + self.parker.park(&self.data, 2); // receives 3 + assert(@atomicRmw(u32, &self.data, .Xchg, 4, .SeqCst) == 3); // sends 4 + self.parker.unpark(&self.data); // wakes up waiters on 4 + } + + fn sender(self: *@This()) void { + assert(@atomicRmw(u32, &self.data, .Xchg, 1, .SeqCst) == 0); // sends 1 + self.parker.unpark(&self.data); // wakes up waiters on 1 + self.parker.park(&self.data, 1); // receives 2 + assert(@atomicRmw(u32, &self.data, .Xchg, 3, .SeqCst) == 2); // sends 3 + self.parker.unpark(&self.data); // wakes up waiters on 3 + self.parker.park(&self.data, 3); // receives 4 + } + }; + + var context = Context{ + .parker = ThreadParker.init(), + .data = 0, + }; + defer context.parker.deinit(); + + var receiver = try std.Thread.spawn(&context, Context.receiver); + defer receiver.wait(); + + context.sender(); +} diff --git a/lib/std/pdb.zig b/lib/std/pdb.zig @@ -532,7 +532,7 @@ const Msf = struct { const stream_sizes = try allocator.alloc(u32, stream_count); defer allocator.free(stream_sizes); - // Microsoft's implementation uses u32(-1) for inexistant streams. + // Microsoft's implementation uses @as(u32, -1) for inexistant streams. // These streams are not used, but still participate in the file // and must be taken into account when resolving stream indices. const Nil = 0xFFFFFFFF; diff --git a/lib/std/priority_queue.zig b/lib/std/priority_queue.zig @@ -236,12 +236,12 @@ test "std.PriorityQueue: add and remove min heap" { try queue.add(23); try queue.add(25); try queue.add(13); - expectEqual(u32(7), queue.remove()); - expectEqual(u32(12), queue.remove()); - expectEqual(u32(13), queue.remove()); - expectEqual(u32(23), queue.remove()); - expectEqual(u32(25), queue.remove()); - expectEqual(u32(54), queue.remove()); + expectEqual(@as(u32, 7), queue.remove()); + expectEqual(@as(u32, 12), queue.remove()); + expectEqual(@as(u32, 13), queue.remove()); + expectEqual(@as(u32, 23), queue.remove()); + expectEqual(@as(u32, 25), queue.remove()); + expectEqual(@as(u32, 54), queue.remove()); } test "std.PriorityQueue: add and remove same min heap" { @@ -254,12 +254,12 @@ test "std.PriorityQueue: add and remove same min heap" { try queue.add(2); try queue.add(1); try queue.add(1); - expectEqual(u32(1), queue.remove()); - expectEqual(u32(1), queue.remove()); - expectEqual(u32(1), queue.remove()); - expectEqual(u32(1), queue.remove()); - expectEqual(u32(2), queue.remove()); - expectEqual(u32(2), queue.remove()); + expectEqual(@as(u32, 1), queue.remove()); + expectEqual(@as(u32, 1), queue.remove()); + expectEqual(@as(u32, 1), queue.remove()); + expectEqual(@as(u32, 1), queue.remove()); + expectEqual(@as(u32, 2), queue.remove()); + expectEqual(@as(u32, 2), queue.remove()); } test "std.PriorityQueue: removeOrNull on empty" { @@ -276,9 +276,9 @@ test "std.PriorityQueue: edge case 3 elements" { try queue.add(9); try queue.add(3); try queue.add(2); - expectEqual(u32(2), queue.remove()); - expectEqual(u32(3), queue.remove()); - expectEqual(u32(9), queue.remove()); + expectEqual(@as(u32, 2), queue.remove()); + expectEqual(@as(u32, 3), queue.remove()); + expectEqual(@as(u32, 9), queue.remove()); } test "std.PriorityQueue: peek" { @@ -289,8 +289,8 @@ test "std.PriorityQueue: peek" { try queue.add(9); try queue.add(3); try queue.add(2); - expectEqual(u32(2), queue.peek().?); - expectEqual(u32(2), queue.peek().?); + expectEqual(@as(u32, 2), queue.peek().?); + expectEqual(@as(u32, 2), queue.peek().?); } test "std.PriorityQueue: sift up with odd indices" { @@ -341,12 +341,12 @@ test "std.PriorityQueue: add and remove max heap" { try queue.add(23); try queue.add(25); try queue.add(13); - expectEqual(u32(54), queue.remove()); - expectEqual(u32(25), queue.remove()); - expectEqual(u32(23), queue.remove()); - expectEqual(u32(13), queue.remove()); - expectEqual(u32(12), queue.remove()); - expectEqual(u32(7), queue.remove()); + expectEqual(@as(u32, 54), queue.remove()); + expectEqual(@as(u32, 25), queue.remove()); + expectEqual(@as(u32, 23), queue.remove()); + expectEqual(@as(u32, 13), queue.remove()); + expectEqual(@as(u32, 12), queue.remove()); + expectEqual(@as(u32, 7), queue.remove()); } test "std.PriorityQueue: add and remove same max heap" { @@ -359,12 +359,12 @@ test "std.PriorityQueue: add and remove same max heap" { try queue.add(2); try queue.add(1); try queue.add(1); - expectEqual(u32(2), queue.remove()); - expectEqual(u32(2), queue.remove()); - expectEqual(u32(1), queue.remove()); - expectEqual(u32(1), queue.remove()); - expectEqual(u32(1), queue.remove()); - expectEqual(u32(1), queue.remove()); + expectEqual(@as(u32, 2), queue.remove()); + expectEqual(@as(u32, 2), queue.remove()); + expectEqual(@as(u32, 1), queue.remove()); + expectEqual(@as(u32, 1), queue.remove()); + expectEqual(@as(u32, 1), queue.remove()); + expectEqual(@as(u32, 1), queue.remove()); } test "std.PriorityQueue: iterator" { @@ -386,5 +386,5 @@ test "std.PriorityQueue: iterator" { _ = map.remove(e); } - expectEqual(usize(0), map.count()); + expectEqual(@as(usize, 0), map.count()); } diff --git a/lib/std/progress.zig b/lib/std/progress.zig @@ -98,11 +98,8 @@ pub const Progress = struct { /// TODO solve https://github.com/ziglang/zig/issues/2765 and then change this /// API to return Progress rather than accept it as a parameter. pub fn start(self: *Progress, name: []const u8, estimated_total_items: ?usize) !*Node { - if (std.io.getStdErr()) |stderr| { - self.terminal = if (stderr.supportsAnsiEscapeCodes()) stderr else null; - } else |_| { - self.terminal = null; - } + const stderr = std.io.getStdErr(); + self.terminal = if (stderr.supportsAnsiEscapeCodes()) stderr else null; self.root = Node{ .context = self, .parent = null, diff --git a/lib/std/rand.zig b/lib/std/rand.zig @@ -93,13 +93,13 @@ pub const Random = struct { // http://www.pcg-random.org/posts/bounded-rands.html // "Lemire's (with an extra tweak from me)" var x: Small = r.int(Small); - var m: Large = Large(x) * Large(less_than); + var m: Large = @as(Large, x) * @as(Large, less_than); var l: Small = @truncate(Small, m); if (l < less_than) { // TODO: workaround for https://github.com/ziglang/zig/issues/1770 // should be: // var t: Small = -%less_than; - var t: Small = @bitCast(Small, -%@bitCast(@IntType(true, Small.bit_count), Small(less_than))); + var t: Small = @bitCast(Small, -%@bitCast(@IntType(true, Small.bit_count), @as(Small, less_than))); if (t >= less_than) { t -= less_than; @@ -109,7 +109,7 @@ pub const Random = struct { } while (l < t) { x = r.int(Small); - m = Large(x) * Large(less_than); + m = @as(Large, x) * @as(Large, less_than); l = @truncate(Small, m); } } @@ -286,7 +286,7 @@ pub fn limitRangeBiased(comptime T: type, random_int: T, less_than: T) T { // adapted from: // http://www.pcg-random.org/posts/bounded-rands.html // "Integer Multiplication (Biased)" - var m: T2 = T2(random_int) * T2(less_than); + var m: T2 = @as(T2, random_int) * @as(T2, less_than); return @intCast(T, m >> T.bit_count); } @@ -633,8 +633,8 @@ pub const Xoroshiro128 = struct { const r = s0 +% s1; s1 ^= s0; - self.s[0] = math.rotl(u64, s0, u8(55)) ^ s1 ^ (s1 << 14); - self.s[1] = math.rotl(u64, s1, u8(36)); + self.s[0] = math.rotl(u64, s0, @as(u8, 55)) ^ s1 ^ (s1 << 14); + self.s[1] = math.rotl(u64, s1, @as(u8, 36)); return r; } @@ -652,7 +652,7 @@ pub const Xoroshiro128 = struct { inline for (table) |entry| { var b: usize = 0; while (b < 64) : (b += 1) { - if ((entry & (u64(1) << @intCast(u6, b))) != 0) { + if ((entry & (@as(u64, 1) << @intCast(u6, b))) != 0) { s0 ^= self.s[0]; s1 ^= self.s[1]; } @@ -1090,7 +1090,7 @@ fn testRange(r: *Random, start: i8, end: i8) void { testRangeBias(r, start, end, false); } fn testRangeBias(r: *Random, start: i8, end: i8, biased: bool) void { - const count = @intCast(usize, i32(end) - i32(start)); + const count = @intCast(usize, @as(i32, end) - @as(i32, start)); var values_buffer = [_]bool{false} ** 0x100; const values = values_buffer[0..count]; var i: usize = 0; diff --git a/lib/std/rand/ziggurat.zig b/lib/std/rand/ziggurat.zig @@ -17,7 +17,7 @@ pub fn next_f64(random: *Random, comptime tables: ZigTable) f64 { // We manually construct a float from parts as we can avoid an extra random lookup here by // using the unused exponent for the lookup table entry. const bits = random.scalar(u64); - const i = usize(bits & 0xff); + const i = @as(usize, bits & 0xff); const u = blk: { if (tables.is_symmetric) { diff --git a/lib/std/segmented_list.zig b/lib/std/segmented_list.zig @@ -162,7 +162,7 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type /// Grows or shrinks capacity to match usage. pub fn setCapacity(self: *Self, new_capacity: usize) !void { if (prealloc_item_count != 0) { - if (new_capacity <= usize(1) << (prealloc_exp + @intCast(ShelfIndex, self.dynamic_segments.len))) { + if (new_capacity <= @as(usize, 1) << (prealloc_exp + @intCast(ShelfIndex, self.dynamic_segments.len))) { return self.shrinkCapacity(new_capacity); } } @@ -231,9 +231,9 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type fn shelfSize(shelf_index: ShelfIndex) usize { if (prealloc_item_count == 0) { - return usize(1) << shelf_index; + return @as(usize, 1) << shelf_index; } - return usize(1) << (shelf_index + (prealloc_exp + 1)); + return @as(usize, 1) << (shelf_index + (prealloc_exp + 1)); } fn shelfIndex(list_index: usize) ShelfIndex { @@ -245,9 +245,9 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type fn boxIndex(list_index: usize, shelf_index: ShelfIndex) usize { if (prealloc_item_count == 0) { - return (list_index + 1) - (usize(1) << shelf_index); + return (list_index + 1) - (@as(usize, 1) << shelf_index); } - return list_index + prealloc_item_count - (usize(1) << ((prealloc_exp + 1) + shelf_index)); + return list_index + prealloc_item_count - (@as(usize, 1) << ((prealloc_exp + 1) + shelf_index)); } fn freeShelves(self: *Self, from_count: ShelfIndex, to_count: ShelfIndex) void { diff --git a/lib/std/sort.zig b/lib/std/sort.zig @@ -813,7 +813,7 @@ fn blockSwap(comptime T: type, items: []T, start1: usize, start2: usize, block_s // where have some idea as to how many unique values there are and where the next value might be fn findFirstForward(comptime T: type, items: []T, value: T, range: Range, lessThan: fn (T, T) bool, unique: usize) usize { if (range.length() == 0) return range.start; - const skip = math.max(range.length() / unique, usize(1)); + const skip = math.max(range.length() / unique, @as(usize, 1)); var index = range.start + skip; while (lessThan(items[index - 1], value)) : (index += skip) { @@ -827,7 +827,7 @@ fn findFirstForward(comptime T: type, items: []T, value: T, range: Range, lessTh fn findFirstBackward(comptime T: type, items: []T, value: T, range: Range, lessThan: fn (T, T) bool, unique: usize) usize { if (range.length() == 0) return range.start; - const skip = math.max(range.length() / unique, usize(1)); + const skip = math.max(range.length() / unique, @as(usize, 1)); var index = range.end - skip; while (index > range.start and !lessThan(items[index - 1], value)) : (index -= skip) { @@ -841,7 +841,7 @@ fn findFirstBackward(comptime T: type, items: []T, value: T, range: Range, lessT fn findLastForward(comptime T: type, items: []T, value: T, range: Range, lessThan: fn (T, T) bool, unique: usize) usize { if (range.length() == 0) return range.start; - const skip = math.max(range.length() / unique, usize(1)); + const skip = math.max(range.length() / unique, @as(usize, 1)); var index = range.start + skip; while (!lessThan(value, items[index - 1])) : (index += skip) { @@ -855,7 +855,7 @@ fn findLastForward(comptime T: type, items: []T, value: T, range: Range, lessTha fn findLastBackward(comptime T: type, items: []T, value: T, range: Range, lessThan: fn (T, T) bool, unique: usize) usize { if (range.length() == 0) return range.start; - const skip = math.max(range.length() / unique, usize(1)); + const skip = math.max(range.length() / unique, @as(usize, 1)); var index = range.end - skip; while (index > range.start and lessThan(value, items[index - 1])) : (index -= skip) { diff --git a/lib/std/special/build_runner.zig b/lib/std/special/build_runner.zig @@ -43,19 +43,8 @@ pub fn main() !void { var targets = ArrayList([]const u8).init(allocator); - var stderr_file = io.getStdErr(); - var stderr_file_stream: File.OutStream = undefined; - var stderr_stream = if (stderr_file) |f| x: { - stderr_file_stream = f.outStream(); - break :x &stderr_file_stream.stream; - } else |err| err; - - var stdout_file = io.getStdOut(); - var stdout_file_stream: File.OutStream = undefined; - var stdout_stream = if (stdout_file) |f| x: { - stdout_file_stream = f.outStream(); - break :x &stdout_file_stream.stream; - } else |err| err; + const stderr_stream = &io.getStdErr().outStream().stream; + const stdout_stream = &io.getStdOut().outStream().stream; while (arg_it.next(allocator)) |err_or_arg| { const arg = try unwrapArg(err_or_arg); @@ -63,37 +52,37 @@ pub fn main() !void { const option_contents = arg[2..]; if (option_contents.len == 0) { warn("Expected option name after '-D'\n\n"); - return usageAndErr(builder, false, try stderr_stream); + return usageAndErr(builder, false, stderr_stream); } if (mem.indexOfScalar(u8, option_contents, '=')) |name_end| { const option_name = option_contents[0..name_end]; const option_value = option_contents[name_end + 1 ..]; if (try builder.addUserInputOption(option_name, option_value)) - return usageAndErr(builder, false, try stderr_stream); + return usageAndErr(builder, false, stderr_stream); } else { if (try builder.addUserInputFlag(option_contents)) - return usageAndErr(builder, false, try stderr_stream); + return usageAndErr(builder, false, stderr_stream); } } else if (mem.startsWith(u8, arg, "-")) { if (mem.eql(u8, arg, "--verbose")) { builder.verbose = true; } else if (mem.eql(u8, arg, "--help")) { - return usage(builder, false, try stdout_stream); + return usage(builder, false, stdout_stream); } else if (mem.eql(u8, arg, "--prefix")) { builder.install_prefix = try unwrapArg(arg_it.next(allocator) orelse { warn("Expected argument after --prefix\n\n"); - return usageAndErr(builder, false, try stderr_stream); + return usageAndErr(builder, false, stderr_stream); }); } else if (mem.eql(u8, arg, "--search-prefix")) { const search_prefix = try unwrapArg(arg_it.next(allocator) orelse { warn("Expected argument after --search-prefix\n\n"); - return usageAndErr(builder, false, try stderr_stream); + return usageAndErr(builder, false, stderr_stream); }); builder.addSearchPrefix(search_prefix); } else if (mem.eql(u8, arg, "--override-lib-dir")) { builder.override_lib_dir = try unwrapArg(arg_it.next(allocator) orelse { warn("Expected argument after --override-lib-dir\n\n"); - return usageAndErr(builder, false, try stderr_stream); + return usageAndErr(builder, false, stderr_stream); }); } else if (mem.eql(u8, arg, "--verbose-tokenize")) { builder.verbose_tokenize = true; @@ -111,7 +100,7 @@ pub fn main() !void { builder.verbose_cc = true; } else { warn("Unrecognized argument: {}\n\n", arg); - return usageAndErr(builder, false, try stderr_stream); + return usageAndErr(builder, false, stderr_stream); } } else { try targets.append(arg); @@ -122,12 +111,12 @@ pub fn main() !void { try runBuild(builder); if (builder.validateUserInputDidItFail()) - return usageAndErr(builder, true, try stderr_stream); + return usageAndErr(builder, true, stderr_stream); builder.make(targets.toSliceConst()) catch |err| { switch (err) { error.InvalidStepName => { - return usageAndErr(builder, true, try stderr_stream); + return usageAndErr(builder, true, stderr_stream); }, error.UncleanExit => process.exit(1), else => return err, diff --git a/lib/std/special/c.zig b/lib/std/special/c.zig @@ -62,7 +62,7 @@ extern fn strncmp(_l: [*]const u8, _r: [*]const u8, _n: usize) c_int { r += 1; n -= 1; } - return c_int(l[0]) - c_int(r[0]); + return @as(c_int, l[0]) - @as(c_int, r[0]); } extern fn strerror(errnum: c_int) [*]const u8 { @@ -540,7 +540,7 @@ fn generic_fmod(comptime T: type, x: T, y: T) T { // scale result up if (ex > 0) { ux -%= 1 << digits; - ux |= uint(@bitCast(u32, ex)) << digits; + ux |= @as(uint, @bitCast(u32, ex)) << digits; } else { ux >>= @intCast(log2uint, @bitCast(u32, -ex + 1)); } @@ -687,7 +687,7 @@ export fn sqrt(x: f64) f64 { export fn sqrtf(x: f32) f32 { const tiny: f32 = 1.0e-30; - const sign: i32 = @bitCast(i32, u32(0x80000000)); + const sign: i32 = @bitCast(i32, @as(u32, 0x80000000)); var ix: i32 = @bitCast(i32, x); if ((ix & 0x7F800000) == 0x7F800000) { diff --git a/lib/std/special/compiler_rt.zig b/lib/std/special/compiler_rt.zig @@ -672,7 +672,7 @@ extern fn __udivsi3(n: u32, d: u32) u32 { // special cases if (d == 0) return 0; // ?! if (n == 0) return 0; - var sr = @bitCast(c_uint, c_int(@clz(u32, d)) - c_int(@clz(u32, n))); + var sr = @bitCast(c_uint, @as(c_int, @clz(u32, d)) - @as(c_int, @clz(u32, n))); // 0 <= sr <= n_uword_bits - 1 or sr large if (sr > n_uword_bits - 1) { // d > r @@ -1414,10 +1414,10 @@ test "test_divsi3" { [_]i32{ -2, 1, -2 }, [_]i32{ -2, -1, 2 }, - [_]i32{ @bitCast(i32, u32(0x80000000)), 1, @bitCast(i32, u32(0x80000000)) }, - [_]i32{ @bitCast(i32, u32(0x80000000)), -1, @bitCast(i32, u32(0x80000000)) }, - [_]i32{ @bitCast(i32, u32(0x80000000)), -2, 0x40000000 }, - [_]i32{ @bitCast(i32, u32(0x80000000)), 2, @bitCast(i32, u32(0xC0000000)) }, + [_]i32{ @bitCast(i32, @as(u32, 0x80000000)), 1, @bitCast(i32, @as(u32, 0x80000000)) }, + [_]i32{ @bitCast(i32, @as(u32, 0x80000000)), -1, @bitCast(i32, @as(u32, 0x80000000)) }, + [_]i32{ @bitCast(i32, @as(u32, 0x80000000)), -2, 0x40000000 }, + [_]i32{ @bitCast(i32, @as(u32, 0x80000000)), 2, @bitCast(i32, @as(u32, 0xC0000000)) }, }; for (cases) |case| { @@ -1443,8 +1443,8 @@ test "test_divmodsi4" { [_]i32{ 19, 5, 3, 4 }, [_]i32{ 19, -5, -3, 4 }, - [_]i32{ @bitCast(i32, u32(0x80000000)), 8, @bitCast(i32, u32(0xf0000000)), 0 }, - [_]i32{ @bitCast(i32, u32(0x80000007)), 8, @bitCast(i32, u32(0xf0000001)), -1 }, + [_]i32{ @bitCast(i32, @as(u32, 0x80000000)), 8, @bitCast(i32, @as(u32, 0xf0000000)), 0 }, + [_]i32{ @bitCast(i32, @as(u32, 0x80000007)), 8, @bitCast(i32, @as(u32, 0xf0000001)), -1 }, }; for (cases) |case| { @@ -1467,10 +1467,10 @@ test "test_divdi3" { [_]i64{ -2, 1, -2 }, [_]i64{ -2, -1, 2 }, - [_]i64{ @bitCast(i64, u64(0x8000000000000000)), 1, @bitCast(i64, u64(0x8000000000000000)) }, - [_]i64{ @bitCast(i64, u64(0x8000000000000000)), -1, @bitCast(i64, u64(0x8000000000000000)) }, - [_]i64{ @bitCast(i64, u64(0x8000000000000000)), -2, 0x4000000000000000 }, - [_]i64{ @bitCast(i64, u64(0x8000000000000000)), 2, @bitCast(i64, u64(0xC000000000000000)) }, + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 1, @bitCast(i64, @as(u64, 0x8000000000000000)) }, + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -1, @bitCast(i64, @as(u64, 0x8000000000000000)) }, + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -2, 0x4000000000000000 }, + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 2, @bitCast(i64, @as(u64, 0xC000000000000000)) }, }; for (cases) |case| { @@ -1492,12 +1492,12 @@ test "test_moddi3" { [_]i64{ -5, 3, -2 }, [_]i64{ -5, -3, -2 }, - [_]i64{ @bitCast(i64, @intCast(u64, 0x8000000000000000)), 1, 0 }, - [_]i64{ @bitCast(i64, @intCast(u64, 0x8000000000000000)), -1, 0 }, - [_]i64{ @bitCast(i64, @intCast(u64, 0x8000000000000000)), 2, 0 }, - [_]i64{ @bitCast(i64, @intCast(u64, 0x8000000000000000)), -2, 0 }, - [_]i64{ @bitCast(i64, @intCast(u64, 0x8000000000000000)), 3, -2 }, - [_]i64{ @bitCast(i64, @intCast(u64, 0x8000000000000000)), -3, -2 }, + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 1, 0 }, + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -1, 0 }, + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 2, 0 }, + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -2, 0 }, + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), 3, -2 }, + [_]i64{ @bitCast(i64, @as(u64, 0x8000000000000000)), -3, -2 }, }; for (cases) |case| { diff --git a/lib/std/special/compiler_rt/addXf3.zig b/lib/std/special/compiler_rt/addXf3.zig @@ -19,26 +19,26 @@ pub extern fn __addtf3(a: f128, b: f128) f128 { } pub extern fn __subsf3(a: f32, b: f32) f32 { - const neg_b = @bitCast(f32, @bitCast(u32, b) ^ (u32(1) << 31)); + const neg_b = @bitCast(f32, @bitCast(u32, b) ^ (@as(u32, 1) << 31)); return addXf3(f32, a, neg_b); } pub extern fn __subdf3(a: f64, b: f64) f64 { - const neg_b = @bitCast(f64, @bitCast(u64, b) ^ (u64(1) << 63)); + const neg_b = @bitCast(f64, @bitCast(u64, b) ^ (@as(u64, 1) << 63)); return addXf3(f64, a, neg_b); } pub extern fn __subtf3(a: f128, b: f128) f128 { - const neg_b = @bitCast(f128, @bitCast(u128, b) ^ (u128(1) << 127)); + const neg_b = @bitCast(f128, @bitCast(u128, b) ^ (@as(u128, 1) << 127)); return addXf3(f128, a, neg_b); } // TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154 fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 { const Z = @IntType(false, T.bit_count); - const S = @IntType(false, T.bit_count - @clz(Z, Z(T.bit_count) - 1)); + const S = @IntType(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1)); const significandBits = std.math.floatMantissaBits(T); - const implicitBit = Z(1) << significandBits; + const implicitBit = @as(Z, 1) << significandBits; const shift = @clz(@IntType(false, T.bit_count), significand.*) - @clz(Z, implicitBit); significand.* <<= @intCast(S, shift); @@ -48,17 +48,17 @@ fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 { // TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154 fn addXf3(comptime T: type, a: T, b: T) T { const Z = @IntType(false, T.bit_count); - const S = @IntType(false, T.bit_count - @clz(Z, Z(T.bit_count) - 1)); + const S = @IntType(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1)); const typeWidth = T.bit_count; const significandBits = std.math.floatMantissaBits(T); const exponentBits = std.math.floatExponentBits(T); - const signBit = (Z(1) << (significandBits + exponentBits)); + const signBit = (@as(Z, 1) << (significandBits + exponentBits)); const maxExponent = ((1 << exponentBits) - 1); const exponentBias = (maxExponent >> 1); - const implicitBit = (Z(1) << significandBits); + const implicitBit = (@as(Z, 1) << significandBits); const quietBit = implicitBit >> 1; const significandMask = implicitBit - 1; @@ -78,8 +78,8 @@ fn addXf3(comptime T: type, a: T, b: T) T { const infRep = @bitCast(Z, std.math.inf(T)); // Detect if a or b is zero, infinity, or NaN. - if (aAbs -% Z(1) >= infRep - Z(1) or - bAbs -% Z(1) >= infRep - Z(1)) + if (aAbs -% @as(Z, 1) >= infRep - @as(Z, 1) or + bAbs -% @as(Z, 1) >= infRep - @as(Z, 1)) { // NaN + anything = qNaN if (aAbs > infRep) return @bitCast(T, @bitCast(Z, a) | quietBit); @@ -148,7 +148,7 @@ fn addXf3(comptime T: type, a: T, b: T) T { const @"align" = @intCast(Z, aExponent - bExponent); if (@"align" != 0) { if (@"align" < typeWidth) { - const sticky = if (bSignificand << @intCast(S, typeWidth - @"align") != 0) Z(1) else 0; + const sticky = if (bSignificand << @intCast(S, typeWidth - @"align") != 0) @as(Z, 1) else 0; bSignificand = (bSignificand >> @truncate(S, @"align")) | sticky; } else { bSignificand = 1; // sticky; b is known to be non-zero. @@ -157,7 +157,7 @@ fn addXf3(comptime T: type, a: T, b: T) T { if (subtraction) { aSignificand -= bSignificand; // If a == -b, return +zero. - if (aSignificand == 0) return @bitCast(T, Z(0)); + if (aSignificand == 0) return @bitCast(T, @as(Z, 0)); // If partial cancellation occured, we need to left-shift the result // and adjust the exponent: @@ -185,7 +185,7 @@ fn addXf3(comptime T: type, a: T, b: T) T { // Result is denormal before rounding; the exponent is zero and we // need to shift the significand. const shift = @intCast(Z, 1 - aExponent); - const sticky = if (aSignificand << @intCast(S, typeWidth - shift) != 0) Z(1) else 0; + const sticky = if (aSignificand << @intCast(S, typeWidth - shift) != 0) @as(Z, 1) else 0; aSignificand = aSignificand >> @intCast(S, shift | sticky); aExponent = 0; } diff --git a/lib/std/special/compiler_rt/addXf3_test.zig b/lib/std/special/compiler_rt/addXf3_test.zig @@ -3,8 +3,8 @@ // https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/test/builtins/Unit/addtf3_test.c // https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/test/builtins/Unit/subtf3_test.c -const qnan128 = @bitCast(f128, u128(0x7fff800000000000) << 64); -const inf128 = @bitCast(f128, u128(0x7fff000000000000) << 64); +const qnan128 = @bitCast(f128, @as(u128, 0x7fff800000000000) << 64); +const inf128 = @bitCast(f128, @as(u128, 0x7fff000000000000) << 64); const __addtf3 = @import("addXf3.zig").__addtf3; @@ -34,7 +34,7 @@ test "addtf3" { test__addtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); // NaN + any = NaN - test__addtf3(@bitCast(f128, (u128(0x7fff000000000000) << 64) | u128(0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); + test__addtf3(@bitCast(f128, (@as(u128, 0x7fff000000000000) << 64) | @as(u128, 0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); // inf + inf = inf test__addtf3(inf128, inf128, 0x7fff000000000000, 0x0); @@ -75,7 +75,7 @@ test "subtf3" { test__subtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); // NaN + any = NaN - test__subtf3(@bitCast(f128, (u128(0x7fff000000000000) << 64) | u128(0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); + test__subtf3(@bitCast(f128, (@as(u128, 0x7fff000000000000) << 64) | @as(u128, 0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); // inf - any = inf test__subtf3(inf128, 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0); diff --git a/lib/std/special/compiler_rt/comparedf2.zig b/lib/std/special/compiler_rt/comparedf2.zig @@ -13,19 +13,19 @@ const srep_t = i64; const typeWidth = rep_t.bit_count; const significandBits = std.math.floatMantissaBits(fp_t); const exponentBits = std.math.floatExponentBits(fp_t); -const signBit = (rep_t(1) << (significandBits + exponentBits)); +const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); const absMask = signBit - 1; -const implicitBit = rep_t(1) << significandBits; +const implicitBit = @as(rep_t, 1) << significandBits; const significandMask = implicitBit - 1; const exponentMask = absMask ^ significandMask; const infRep = @bitCast(rep_t, std.math.inf(fp_t)); // TODO https://github.com/ziglang/zig/issues/641 // and then make the return types of some of these functions the enum instead of c_int -const LE_LESS = c_int(-1); -const LE_EQUAL = c_int(0); -const LE_GREATER = c_int(1); -const LE_UNORDERED = c_int(1); +const LE_LESS = @as(c_int, -1); +const LE_EQUAL = @as(c_int, 0); +const LE_GREATER = @as(c_int, 1); +const LE_UNORDERED = @as(c_int, 1); pub extern fn __ledf2(a: fp_t, b: fp_t) c_int { @setRuntimeSafety(is_test); @@ -65,10 +65,10 @@ pub extern fn __ledf2(a: fp_t, b: fp_t) c_int { // TODO https://github.com/ziglang/zig/issues/641 // and then make the return types of some of these functions the enum instead of c_int -const GE_LESS = c_int(-1); -const GE_EQUAL = c_int(0); -const GE_GREATER = c_int(1); -const GE_UNORDERED = c_int(-1); // Note: different from LE_UNORDERED +const GE_LESS = @as(c_int, -1); +const GE_EQUAL = @as(c_int, 0); +const GE_GREATER = @as(c_int, 1); +const GE_UNORDERED = @as(c_int, -1); // Note: different from LE_UNORDERED pub extern fn __gedf2(a: fp_t, b: fp_t) c_int { @setRuntimeSafety(is_test); diff --git a/lib/std/special/compiler_rt/comparesf2.zig b/lib/std/special/compiler_rt/comparesf2.zig @@ -13,19 +13,19 @@ const srep_t = i32; const typeWidth = rep_t.bit_count; const significandBits = std.math.floatMantissaBits(fp_t); const exponentBits = std.math.floatExponentBits(fp_t); -const signBit = (rep_t(1) << (significandBits + exponentBits)); +const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); const absMask = signBit - 1; -const implicitBit = rep_t(1) << significandBits; +const implicitBit = @as(rep_t, 1) << significandBits; const significandMask = implicitBit - 1; const exponentMask = absMask ^ significandMask; const infRep = @bitCast(rep_t, std.math.inf(fp_t)); // TODO https://github.com/ziglang/zig/issues/641 // and then make the return types of some of these functions the enum instead of c_int -const LE_LESS = c_int(-1); -const LE_EQUAL = c_int(0); -const LE_GREATER = c_int(1); -const LE_UNORDERED = c_int(1); +const LE_LESS = @as(c_int, -1); +const LE_EQUAL = @as(c_int, 0); +const LE_GREATER = @as(c_int, 1); +const LE_UNORDERED = @as(c_int, 1); pub extern fn __lesf2(a: fp_t, b: fp_t) c_int { @setRuntimeSafety(is_test); @@ -65,10 +65,10 @@ pub extern fn __lesf2(a: fp_t, b: fp_t) c_int { // TODO https://github.com/ziglang/zig/issues/641 // and then make the return types of some of these functions the enum instead of c_int -const GE_LESS = c_int(-1); -const GE_EQUAL = c_int(0); -const GE_GREATER = c_int(1); -const GE_UNORDERED = c_int(-1); // Note: different from LE_UNORDERED +const GE_LESS = @as(c_int, -1); +const GE_EQUAL = @as(c_int, 0); +const GE_GREATER = @as(c_int, 1); +const GE_UNORDERED = @as(c_int, -1); // Note: different from LE_UNORDERED pub extern fn __gesf2(a: fp_t, b: fp_t) c_int { @setRuntimeSafety(is_test); diff --git a/lib/std/special/compiler_rt/comparetf2.zig b/lib/std/special/compiler_rt/comparetf2.zig @@ -1,9 +1,9 @@ // TODO https://github.com/ziglang/zig/issues/641 // and then make the return types of some of these functions the enum instead of c_int -const LE_LESS = c_int(-1); -const LE_EQUAL = c_int(0); -const LE_GREATER = c_int(1); -const LE_UNORDERED = c_int(1); +const LE_LESS = @as(c_int, -1); +const LE_EQUAL = @as(c_int, 0); +const LE_GREATER = @as(c_int, 1); +const LE_UNORDERED = @as(c_int, 1); const rep_t = u128; const srep_t = i128; @@ -11,9 +11,9 @@ const srep_t = i128; const typeWidth = rep_t.bit_count; const significandBits = 112; const exponentBits = (typeWidth - significandBits - 1); -const signBit = (rep_t(1) << (significandBits + exponentBits)); +const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); const absMask = signBit - 1; -const implicitBit = rep_t(1) << significandBits; +const implicitBit = @as(rep_t, 1) << significandBits; const significandMask = implicitBit - 1; const exponentMask = absMask ^ significandMask; const infRep = exponentMask; @@ -60,10 +60,10 @@ pub extern fn __letf2(a: f128, b: f128) c_int { // TODO https://github.com/ziglang/zig/issues/641 // and then make the return types of some of these functions the enum instead of c_int -const GE_LESS = c_int(-1); -const GE_EQUAL = c_int(0); -const GE_GREATER = c_int(1); -const GE_UNORDERED = c_int(-1); // Note: different from LE_UNORDERED +const GE_LESS = @as(c_int, -1); +const GE_EQUAL = @as(c_int, 0); +const GE_GREATER = @as(c_int, 1); +const GE_UNORDERED = @as(c_int, -1); // Note: different from LE_UNORDERED pub extern fn __getf2(a: f128, b: f128) c_int { @setRuntimeSafety(is_test); diff --git a/lib/std/special/compiler_rt/divdf3.zig b/lib/std/special/compiler_rt/divdf3.zig @@ -14,11 +14,11 @@ pub extern fn __divdf3(a: f64, b: f64) f64 { const significandBits = std.math.floatMantissaBits(f64); const exponentBits = std.math.floatExponentBits(f64); - const signBit = (Z(1) << (significandBits + exponentBits)); + const signBit = (@as(Z, 1) << (significandBits + exponentBits)); const maxExponent = ((1 << exponentBits) - 1); const exponentBias = (maxExponent >> 1); - const implicitBit = (Z(1) << significandBits); + const implicitBit = (@as(Z, 1) << significandBits); const quietBit = implicitBit >> 1; const significandMask = implicitBit - 1; @@ -91,7 +91,7 @@ pub extern fn __divdf3(a: f64, b: f64) f64 { // polynomial approximation: reciprocal = 3/4 + 1/sqrt(2) - b/2. This // is accurate to about 3.5 binary digits. const q31b: u32 = @truncate(u32, bSignificand >> 21); - var recip32 = u32(0x7504f333) -% q31b; + var recip32 = @as(u32, 0x7504f333) -% q31b; // Now refine the reciprocal estimate using a Newton-Raphson iteration: // @@ -101,12 +101,12 @@ pub extern fn __divdf3(a: f64, b: f64) f64 { // with each iteration, so after three iterations, we have about 28 binary // digits of accuracy. var correction32: u32 = undefined; - correction32 = @truncate(u32, ~(u64(recip32) *% q31b >> 32) +% 1); - recip32 = @truncate(u32, u64(recip32) *% correction32 >> 31); - correction32 = @truncate(u32, ~(u64(recip32) *% q31b >> 32) +% 1); - recip32 = @truncate(u32, u64(recip32) *% correction32 >> 31); - correction32 = @truncate(u32, ~(u64(recip32) *% q31b >> 32) +% 1); - recip32 = @truncate(u32, u64(recip32) *% correction32 >> 31); + correction32 = @truncate(u32, ~(@as(u64, recip32) *% q31b >> 32) +% 1); + recip32 = @truncate(u32, @as(u64, recip32) *% correction32 >> 31); + correction32 = @truncate(u32, ~(@as(u64, recip32) *% q31b >> 32) +% 1); + recip32 = @truncate(u32, @as(u64, recip32) *% correction32 >> 31); + correction32 = @truncate(u32, ~(@as(u64, recip32) *% q31b >> 32) +% 1); + recip32 = @truncate(u32, @as(u64, recip32) *% correction32 >> 31); // recip32 might have overflowed to exactly zero in the preceding // computation if the high word of b is exactly 1.0. This would sabotage @@ -119,10 +119,10 @@ pub extern fn __divdf3(a: f64, b: f64) f64 { const q63blo: u32 = @truncate(u32, bSignificand << 11); var correction: u64 = undefined; var reciprocal: u64 = undefined; - correction = ~(u64(recip32) *% q31b +% (u64(recip32) *% q63blo >> 32)) +% 1; + correction = ~(@as(u64, recip32) *% q31b +% (@as(u64, recip32) *% q63blo >> 32)) +% 1; const cHi = @truncate(u32, correction >> 32); const cLo = @truncate(u32, correction); - reciprocal = u64(recip32) *% cHi +% (u64(recip32) *% cLo >> 32); + reciprocal = @as(u64, recip32) *% cHi +% (@as(u64, recip32) *% cLo >> 32); // We already adjusted the 32-bit estimate, now we need to adjust the final // 64-bit reciprocal estimate downward to ensure that it is strictly smaller @@ -195,7 +195,7 @@ pub extern fn __divdf3(a: f64, b: f64) f64 { // Clear the implicit bit var absResult = quotient & significandMask; // Insert the exponent - absResult |= @bitCast(Z, SignedZ(writtenExponent)) << significandBits; + absResult |= @bitCast(Z, @as(SignedZ, writtenExponent)) << significandBits; // Round absResult +%= round; // Insert the sign and return @@ -208,7 +208,7 @@ fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void { switch (Z) { u32 => { // 32x32 --> 64 bit multiply - const product = u64(a) * u64(b); + const product = @as(u64, a) * @as(u64, b); hi.* = @truncate(u32, product >> 32); lo.* = @truncate(u32, product); }, @@ -237,9 +237,9 @@ fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void { hi.* = S.hiWord(plohi) +% S.hiWord(philo) +% S.hiWord(r1) +% phihi; }, u128 => { - const Word_LoMask = u64(0x00000000ffffffff); - const Word_HiMask = u64(0xffffffff00000000); - const Word_FullMask = u64(0xffffffffffffffff); + const Word_LoMask = @as(u64, 0x00000000ffffffff); + const Word_HiMask = @as(u64, 0xffffffff00000000); + const Word_FullMask = @as(u64, 0xffffffffffffffff); const S = struct { fn Word_1(x: u128) u64 { return @truncate(u32, x >> 96); @@ -275,22 +275,22 @@ fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void { const product43: u64 = S.Word_4(a) * S.Word_3(b); const product44: u64 = S.Word_4(a) * S.Word_4(b); - const sum0: u128 = u128(product44); - const sum1: u128 = u128(product34) +% - u128(product43); - const sum2: u128 = u128(product24) +% - u128(product33) +% - u128(product42); - const sum3: u128 = u128(product14) +% - u128(product23) +% - u128(product32) +% - u128(product41); - const sum4: u128 = u128(product13) +% - u128(product22) +% - u128(product31); - const sum5: u128 = u128(product12) +% - u128(product21); - const sum6: u128 = u128(product11); + const sum0: u128 = @as(u128, product44); + const sum1: u128 = @as(u128, product34) +% + @as(u128, product43); + const sum2: u128 = @as(u128, product24) +% + @as(u128, product33) +% + @as(u128, product42); + const sum3: u128 = @as(u128, product14) +% + @as(u128, product23) +% + @as(u128, product32) +% + @as(u128, product41); + const sum4: u128 = @as(u128, product13) +% + @as(u128, product22) +% + @as(u128, product31); + const sum5: u128 = @as(u128, product12) +% + @as(u128, product21); + const sum6: u128 = @as(u128, product11); const r0: u128 = (sum0 & Word_FullMask) +% ((sum1 & Word_LoMask) << 32); @@ -316,7 +316,7 @@ fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 { @setRuntimeSafety(builtin.is_test); const Z = @IntType(false, T.bit_count); const significandBits = std.math.floatMantissaBits(T); - const implicitBit = Z(1) << significandBits; + const implicitBit = @as(Z, 1) << significandBits; const shift = @clz(Z, significand.*) - @clz(Z, implicitBit); significand.* <<= @intCast(std.math.Log2Int(Z), shift); diff --git a/lib/std/special/compiler_rt/divsf3.zig b/lib/std/special/compiler_rt/divsf3.zig @@ -13,11 +13,11 @@ pub extern fn __divsf3(a: f32, b: f32) f32 { const significandBits = std.math.floatMantissaBits(f32); const exponentBits = std.math.floatExponentBits(f32); - const signBit = (Z(1) << (significandBits + exponentBits)); + const signBit = (@as(Z, 1) << (significandBits + exponentBits)); const maxExponent = ((1 << exponentBits) - 1); const exponentBias = (maxExponent >> 1); - const implicitBit = (Z(1) << significandBits); + const implicitBit = (@as(Z, 1) << significandBits); const quietBit = implicitBit >> 1; const significandMask = implicitBit - 1; @@ -90,7 +90,7 @@ pub extern fn __divsf3(a: f32, b: f32) f32 { // polynomial approximation: reciprocal = 3/4 + 1/sqrt(2) - b/2. This // is accurate to about 3.5 binary digits. const q31b = bSignificand << 8; - var reciprocal = u32(0x7504f333) -% q31b; + var reciprocal = @as(u32, 0x7504f333) -% q31b; // Now refine the reciprocal estimate using a Newton-Raphson iteration: // @@ -100,12 +100,12 @@ pub extern fn __divsf3(a: f32, b: f32) f32 { // with each iteration, so after three iterations, we have about 28 binary // digits of accuracy. var correction: u32 = undefined; - correction = @truncate(u32, ~(u64(reciprocal) *% q31b >> 32) +% 1); - reciprocal = @truncate(u32, u64(reciprocal) *% correction >> 31); - correction = @truncate(u32, ~(u64(reciprocal) *% q31b >> 32) +% 1); - reciprocal = @truncate(u32, u64(reciprocal) *% correction >> 31); - correction = @truncate(u32, ~(u64(reciprocal) *% q31b >> 32) +% 1); - reciprocal = @truncate(u32, u64(reciprocal) *% correction >> 31); + correction = @truncate(u32, ~(@as(u64, reciprocal) *% q31b >> 32) +% 1); + reciprocal = @truncate(u32, @as(u64, reciprocal) *% correction >> 31); + correction = @truncate(u32, ~(@as(u64, reciprocal) *% q31b >> 32) +% 1); + reciprocal = @truncate(u32, @as(u64, reciprocal) *% correction >> 31); + correction = @truncate(u32, ~(@as(u64, reciprocal) *% q31b >> 32) +% 1); + reciprocal = @truncate(u32, @as(u64, reciprocal) *% correction >> 31); // Exhaustive testing shows that the error in reciprocal after three steps // is in the interval [-0x1.f58108p-31, 0x1.d0e48cp-29], in line with our @@ -127,7 +127,7 @@ pub extern fn __divsf3(a: f32, b: f32) f32 { // is the error in the reciprocal of b scaled by the maximum // possible value of a. As a consequence of this error bound, // either q or nextafter(q) is the correctly rounded - var quotient: Z = @truncate(u32, u64(reciprocal) *% (aSignificand << 1) >> 32); + var quotient: Z = @truncate(u32, @as(u64, reciprocal) *% (aSignificand << 1) >> 32); // Two cases: quotient is in [0.5, 1.0) or quotient is in [1.0, 2.0). // In either case, we are going to compute a residual of the form @@ -189,7 +189,7 @@ fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 { @setRuntimeSafety(builtin.is_test); const Z = @IntType(false, T.bit_count); const significandBits = std.math.floatMantissaBits(T); - const implicitBit = Z(1) << significandBits; + const implicitBit = @as(Z, 1) << significandBits; const shift = @clz(Z, significand.*) - @clz(Z, implicitBit); significand.* <<= @intCast(std.math.Log2Int(Z), shift); diff --git a/lib/std/special/compiler_rt/divti3_test.zig b/lib/std/special/compiler_rt/divti3_test.zig @@ -14,8 +14,8 @@ test "divti3" { test__divti3(-2, 1, -2); test__divti3(-2, -1, 2); - test__divti3(@bitCast(i128, u128(0x8 << 124)), 1, @bitCast(i128, u128(0x8 << 124))); - test__divti3(@bitCast(i128, u128(0x8 << 124)), -1, @bitCast(i128, u128(0x8 << 124))); - test__divti3(@bitCast(i128, u128(0x8 << 124)), -2, @bitCast(i128, u128(0x4 << 124))); - test__divti3(@bitCast(i128, u128(0x8 << 124)), 2, @bitCast(i128, u128(0xc << 124))); + test__divti3(@bitCast(i128, @as(u128, 0x8 << 124)), 1, @bitCast(i128, @as(u128, 0x8 << 124))); + test__divti3(@bitCast(i128, @as(u128, 0x8 << 124)), -1, @bitCast(i128, @as(u128, 0x8 << 124))); + test__divti3(@bitCast(i128, @as(u128, 0x8 << 124)), -2, @bitCast(i128, @as(u128, 0x4 << 124))); + test__divti3(@bitCast(i128, @as(u128, 0x8 << 124)), 2, @bitCast(i128, @as(u128, 0xc << 124))); } diff --git a/lib/std/special/compiler_rt/extendXfYf2.zig b/lib/std/special/compiler_rt/extendXfYf2.zig @@ -49,7 +49,7 @@ fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: @IntType(false, @t const dstInfExp = (1 << dstExpBits) - 1; const dstExpBias = dstInfExp >> 1; - const dstMinNormal: dst_rep_t = dst_rep_t(1) << dstSigBits; + const dstMinNormal: dst_rep_t = @as(dst_rep_t, 1) << dstSigBits; // Break a into a sign and representation of the absolute value const aRep: src_rep_t = @bitCast(src_rep_t, a); @@ -61,7 +61,7 @@ fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: @IntType(false, @t // a is a normal number. // Extend to the destination type by shifting the significand and // exponent into the proper position and rebiasing the exponent. - absResult = dst_rep_t(aAbs) << (dstSigBits - srcSigBits); + absResult = @as(dst_rep_t, aAbs) << (dstSigBits - srcSigBits); absResult += (dstExpBias - srcExpBias) << dstSigBits; } else if (aAbs >= srcInfinity) { // a is NaN or infinity. @@ -69,15 +69,15 @@ fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: @IntType(false, @t // bit (if needed) and right-aligning the rest of the trailing NaN // payload field. absResult = dstInfExp << dstSigBits; - absResult |= dst_rep_t(aAbs & srcQNaN) << (dstSigBits - srcSigBits); - absResult |= dst_rep_t(aAbs & srcNaNCode) << (dstSigBits - srcSigBits); + absResult |= @as(dst_rep_t, aAbs & srcQNaN) << (dstSigBits - srcSigBits); + absResult |= @as(dst_rep_t, aAbs & srcNaNCode) << (dstSigBits - srcSigBits); } else if (aAbs != 0) { // a is denormal. // renormalize the significand and clear the leading bit, then insert // the correct adjusted exponent in the destination type. const scale: u32 = @clz(src_rep_t, aAbs) - - @clz(src_rep_t, src_rep_t(srcMinNormal)); - absResult = dst_rep_t(aAbs) << @intCast(DstShift, dstSigBits - srcSigBits + scale); + @clz(src_rep_t, @as(src_rep_t, srcMinNormal)); + absResult = @as(dst_rep_t, aAbs) << @intCast(DstShift, dstSigBits - srcSigBits + scale); absResult ^= dstMinNormal; const resultExponent: u32 = dstExpBias - srcExpBias - scale + 1; absResult |= @intCast(dst_rep_t, resultExponent) << dstSigBits; @@ -87,7 +87,7 @@ fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: @IntType(false, @t } // Apply the signbit to (dst_t)abs(a). - const result: dst_rep_t align(@alignOf(dst_t)) = absResult | dst_rep_t(sign) << (dstBits - srcBits); + const result: dst_rep_t align(@alignOf(dst_t)) = absResult | @as(dst_rep_t, sign) << (dstBits - srcBits); return @bitCast(dst_t, result); } diff --git a/lib/std/special/compiler_rt/extendXfYf2_test.zig b/lib/std/special/compiler_rt/extendXfYf2_test.zig @@ -134,11 +134,11 @@ test "extendsftf2" { } fn makeQNaN64() f64 { - return @bitCast(f64, u64(0x7ff8000000000000)); + return @bitCast(f64, @as(u64, 0x7ff8000000000000)); } fn makeInf64() f64 { - return @bitCast(f64, u64(0x7ff0000000000000)); + return @bitCast(f64, @as(u64, 0x7ff0000000000000)); } fn makeNaN64(rand: u64) f64 { @@ -146,7 +146,7 @@ fn makeNaN64(rand: u64) f64 { } fn makeQNaN32() f32 { - return @bitCast(f32, u32(0x7fc00000)); + return @bitCast(f32, @as(u32, 0x7fc00000)); } fn makeNaN32(rand: u32) f32 { @@ -154,5 +154,5 @@ fn makeNaN32(rand: u32) f32 { } fn makeInf32() f32 { - return @bitCast(f32, u32(0x7f800000)); + return @bitCast(f32, @as(u32, 0x7f800000)); } diff --git a/lib/std/special/compiler_rt/fixdfdi_test.zig b/lib/std/special/compiler_rt/fixdfdi_test.zig @@ -6,7 +6,7 @@ const warn = std.debug.warn; fn test__fixdfdi(a: f64, expected: i64) void { const x = __fixdfdi(a); - //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u64, expected)); + //warn("a={}:{x} x={}:{x} expected={}:{x}:@as(u64, {x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u64, expected)); testing.expect(x == expected); } diff --git a/lib/std/special/compiler_rt/fixdfsi_test.zig b/lib/std/special/compiler_rt/fixdfsi_test.zig @@ -6,7 +6,7 @@ const warn = std.debug.warn; fn test__fixdfsi(a: f64, expected: i32) void { const x = __fixdfsi(a); - //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u32, expected)); + //warn("a={}:{x} x={}:{x} expected={}:{x}:@as(u64, {x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u32, expected)); testing.expect(x == expected); } diff --git a/lib/std/special/compiler_rt/fixdfti_test.zig b/lib/std/special/compiler_rt/fixdfti_test.zig @@ -6,7 +6,7 @@ const warn = std.debug.warn; fn test__fixdfti(a: f64, expected: i128) void { const x = __fixdfti(a); - //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u128, expected)); + //warn("a={}:{x} x={}:{x} expected={}:{x}:@as(u64, {x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u128, expected)); testing.expect(x == expected); } diff --git a/lib/std/special/compiler_rt/fixint.zig b/lib/std/special/compiler_rt/fixint.zig @@ -25,11 +25,11 @@ pub fn fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t) fixint_t { const typeWidth = rep_t.bit_count; const exponentBits = (typeWidth - significandBits - 1); - const signBit = (rep_t(1) << (significandBits + exponentBits)); + const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); const maxExponent = ((1 << exponentBits) - 1); const exponentBias = (maxExponent >> 1); - const implicitBit = (rep_t(1) << significandBits); + const implicitBit = (@as(rep_t, 1) << significandBits); const significandMask = (implicitBit - 1); // Break a into sign, exponent, significand @@ -51,7 +51,7 @@ pub fn fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t) fixint_t { // If the value is too large for the integer type, saturate. if (@intCast(usize, exponent) >= fixint_t.bit_count) { - return if (negative) fixint_t(minInt(fixint_t)) else fixint_t(maxInt(fixint_t)); + return if (negative) @as(fixint_t, minInt(fixint_t)) else @as(fixint_t, maxInt(fixint_t)); } // If 0 <= exponent < significandBits, right shift else left shift diff --git a/lib/std/special/compiler_rt/fixint_test.zig b/lib/std/special/compiler_rt/fixint_test.zig @@ -81,8 +81,8 @@ test "fixint.i3" { test "fixint.i32" { test__fixint(f64, i32, -math.inf_f64, math.minInt(i32)); test__fixint(f64, i32, -math.f64_max, math.minInt(i32)); - test__fixint(f64, i32, f64(math.minInt(i32)), math.minInt(i32)); - test__fixint(f64, i32, f64(math.minInt(i32)) + 1, math.minInt(i32) + 1); + test__fixint(f64, i32, @as(f64, math.minInt(i32)), math.minInt(i32)); + test__fixint(f64, i32, @as(f64, math.minInt(i32)) + 1, math.minInt(i32) + 1); test__fixint(f64, i32, -2.0, -2); test__fixint(f64, i32, -1.9, -1); test__fixint(f64, i32, -1.1, -1); @@ -96,8 +96,8 @@ test "fixint.i32" { test__fixint(f64, i32, 0.1, 0); test__fixint(f64, i32, 0.9, 0); test__fixint(f64, i32, 1.0, 1); - test__fixint(f64, i32, f64(math.maxInt(i32)) - 1, math.maxInt(i32) - 1); - test__fixint(f64, i32, f64(math.maxInt(i32)), math.maxInt(i32)); + test__fixint(f64, i32, @as(f64, math.maxInt(i32)) - 1, math.maxInt(i32) - 1); + test__fixint(f64, i32, @as(f64, math.maxInt(i32)), math.maxInt(i32)); test__fixint(f64, i32, math.f64_max, math.maxInt(i32)); test__fixint(f64, i32, math.inf_f64, math.maxInt(i32)); } @@ -105,9 +105,9 @@ test "fixint.i32" { test "fixint.i64" { test__fixint(f64, i64, -math.inf_f64, math.minInt(i64)); test__fixint(f64, i64, -math.f64_max, math.minInt(i64)); - test__fixint(f64, i64, f64(math.minInt(i64)), math.minInt(i64)); - test__fixint(f64, i64, f64(math.minInt(i64)) + 1, math.minInt(i64)); - test__fixint(f64, i64, f64(math.minInt(i64) / 2), math.minInt(i64) / 2); + test__fixint(f64, i64, @as(f64, math.minInt(i64)), math.minInt(i64)); + test__fixint(f64, i64, @as(f64, math.minInt(i64)) + 1, math.minInt(i64)); + test__fixint(f64, i64, @as(f64, math.minInt(i64) / 2), math.minInt(i64) / 2); test__fixint(f64, i64, -2.0, -2); test__fixint(f64, i64, -1.9, -1); test__fixint(f64, i64, -1.1, -1); @@ -121,8 +121,8 @@ test "fixint.i64" { test__fixint(f64, i64, 0.1, 0); test__fixint(f64, i64, 0.9, 0); test__fixint(f64, i64, 1.0, 1); - test__fixint(f64, i64, f64(math.maxInt(i64)) - 1, math.maxInt(i64)); - test__fixint(f64, i64, f64(math.maxInt(i64)), math.maxInt(i64)); + test__fixint(f64, i64, @as(f64, math.maxInt(i64)) - 1, math.maxInt(i64)); + test__fixint(f64, i64, @as(f64, math.maxInt(i64)), math.maxInt(i64)); test__fixint(f64, i64, math.f64_max, math.maxInt(i64)); test__fixint(f64, i64, math.inf_f64, math.maxInt(i64)); } @@ -130,8 +130,8 @@ test "fixint.i64" { test "fixint.i128" { test__fixint(f64, i128, -math.inf_f64, math.minInt(i128)); test__fixint(f64, i128, -math.f64_max, math.minInt(i128)); - test__fixint(f64, i128, f64(math.minInt(i128)), math.minInt(i128)); - test__fixint(f64, i128, f64(math.minInt(i128)) + 1, math.minInt(i128)); + test__fixint(f64, i128, @as(f64, math.minInt(i128)), math.minInt(i128)); + test__fixint(f64, i128, @as(f64, math.minInt(i128)) + 1, math.minInt(i128)); test__fixint(f64, i128, -2.0, -2); test__fixint(f64, i128, -1.9, -1); test__fixint(f64, i128, -1.1, -1); @@ -145,8 +145,8 @@ test "fixint.i128" { test__fixint(f64, i128, 0.1, 0); test__fixint(f64, i128, 0.9, 0); test__fixint(f64, i128, 1.0, 1); - test__fixint(f64, i128, f64(math.maxInt(i128)) - 1, math.maxInt(i128)); - test__fixint(f64, i128, f64(math.maxInt(i128)), math.maxInt(i128)); + test__fixint(f64, i128, @as(f64, math.maxInt(i128)) - 1, math.maxInt(i128)); + test__fixint(f64, i128, @as(f64, math.maxInt(i128)), math.maxInt(i128)); test__fixint(f64, i128, math.f64_max, math.maxInt(i128)); test__fixint(f64, i128, math.inf_f64, math.maxInt(i128)); } diff --git a/lib/std/special/compiler_rt/fixsfdi_test.zig b/lib/std/special/compiler_rt/fixsfdi_test.zig @@ -6,7 +6,7 @@ const warn = std.debug.warn; fn test__fixsfdi(a: f32, expected: i64) void { const x = __fixsfdi(a); - //warn("a={}:{x} x={}:{x} expected={}:{x}:u32({x})\n", a, @bitCast(u32, a), x, x, expected, expected, @bitCast(u64, expected)); + //warn("a={}:{x} x={}:{x} expected={}:{x}:@as(u32, {x})\n", a, @bitCast(u32, a), x, x, expected, expected, @bitCast(u64, expected)); testing.expect(x == expected); } diff --git a/lib/std/special/compiler_rt/fixsfsi_test.zig b/lib/std/special/compiler_rt/fixsfsi_test.zig @@ -6,7 +6,7 @@ const warn = std.debug.warn; fn test__fixsfsi(a: f32, expected: i32) void { const x = __fixsfsi(a); - //warn("a={}:{x} x={}:{x} expected={}:{x}:u32({x})\n", a, @bitCast(u32, a), x, x, expected, expected, @bitCast(u32, expected)); + //warn("a={}:{x} x={}:{x} expected={}:{x}:@as(u32, {x})\n", a, @bitCast(u32, a), x, x, expected, expected, @bitCast(u32, expected)); testing.expect(x == expected); } diff --git a/lib/std/special/compiler_rt/fixsfti_test.zig b/lib/std/special/compiler_rt/fixsfti_test.zig @@ -6,7 +6,7 @@ const warn = std.debug.warn; fn test__fixsfti(a: f32, expected: i128) void { const x = __fixsfti(a); - //warn("a={}:{x} x={}:{x} expected={}:{x}:u128({x})\n", a, @bitCast(u32, a), x, x, expected, expected, @bitCast(u128, expected)); + //warn("a={}:{x} x={}:{x} expected={}:{x}:@as(u128, {x})\n", a, @bitCast(u32, a), x, x, expected, expected, @bitCast(u128, expected)); testing.expect(x == expected); } diff --git a/lib/std/special/compiler_rt/fixtfdi_test.zig b/lib/std/special/compiler_rt/fixtfdi_test.zig @@ -6,7 +6,7 @@ const warn = std.debug.warn; fn test__fixtfdi(a: f128, expected: i64) void { const x = __fixtfdi(a); - //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u128, a), x, x, expected, expected, @bitCast(u64, expected)); + //warn("a={}:{x} x={}:{x} expected={}:{x}:@as(u64, {x})\n", a, @bitCast(u128, a), x, x, expected, expected, @bitCast(u64, expected)); testing.expect(x == expected); } diff --git a/lib/std/special/compiler_rt/fixtfsi_test.zig b/lib/std/special/compiler_rt/fixtfsi_test.zig @@ -6,7 +6,7 @@ const warn = std.debug.warn; fn test__fixtfsi(a: f128, expected: i32) void { const x = __fixtfsi(a); - //warn("a={}:{x} x={}:{x} expected={}:{x}:u32({x})\n", a, @bitCast(u128, a), x, x, expected, expected, @bitCast(u32, expected)); + //warn("a={}:{x} x={}:{x} expected={}:{x}:@as(u32, {x})\n", a, @bitCast(u128, a), x, x, expected, expected, @bitCast(u32, expected)); testing.expect(x == expected); } diff --git a/lib/std/special/compiler_rt/fixtfti_test.zig b/lib/std/special/compiler_rt/fixtfti_test.zig @@ -6,7 +6,7 @@ const warn = std.debug.warn; fn test__fixtfti(a: f128, expected: i128) void { const x = __fixtfti(a); - //warn("a={}:{x} x={}:{x} expected={}:{x}:u128({x})\n", a, @bitCast(u128, a), x, x, expected, expected, @bitCast(u128, expected)); + //warn("a={}:{x} x={}:{x} expected={}:{x}:@as(u128, {x})\n", a, @bitCast(u128, a), x, x, expected, expected, @bitCast(u128, expected)); testing.expect(x == expected); } diff --git a/lib/std/special/compiler_rt/fixuint.zig b/lib/std/special/compiler_rt/fixuint.zig @@ -19,11 +19,11 @@ pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t }; const typeWidth = rep_t.bit_count; const exponentBits = (typeWidth - significandBits - 1); - const signBit = (rep_t(1) << (significandBits + exponentBits)); + const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); const maxExponent = ((1 << exponentBits) - 1); const exponentBias = (maxExponent >> 1); - const implicitBit = (rep_t(1) << significandBits); + const implicitBit = (@as(rep_t, 1) << significandBits); const significandMask = (implicitBit - 1); // Break a into sign, exponent, significand @@ -31,7 +31,7 @@ pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t const absMask = signBit - 1; const aAbs: rep_t = aRep & absMask; - const sign = if ((aRep & signBit) != 0) i32(-1) else i32(1); + const sign = if ((aRep & signBit) != 0) @as(i32, -1) else @as(i32, 1); const exponent = @intCast(i32, aAbs >> significandBits) - exponentBias; const significand: rep_t = (aAbs & significandMask) | implicitBit; @@ -39,7 +39,7 @@ pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t if (sign == -1 or exponent < 0) return 0; // If the value is too large for the integer type, saturate. - if (@intCast(c_uint, exponent) >= fixuint_t.bit_count) return ~fixuint_t(0); + if (@intCast(c_uint, exponent) >= fixuint_t.bit_count) return ~@as(fixuint_t, 0); // If 0 <= exponent < significandBits, right shift to get the result. // Otherwise, shift left. diff --git a/lib/std/special/compiler_rt/fixunstfsi_test.zig b/lib/std/special/compiler_rt/fixunstfsi_test.zig @@ -6,7 +6,7 @@ fn test__fixunstfsi(a: f128, expected: u32) void { testing.expect(x == expected); } -const inf128 = @bitCast(f128, u128(0x7fff0000000000000000000000000000)); +const inf128 = @bitCast(f128, @as(u128, 0x7fff0000000000000000000000000000)); test "fixunstfsi" { test__fixunstfsi(inf128, 0xffffffff); diff --git a/lib/std/special/compiler_rt/fixunstfti_test.zig b/lib/std/special/compiler_rt/fixunstfti_test.zig @@ -6,7 +6,7 @@ fn test__fixunstfti(a: f128, expected: u128) void { testing.expect(x == expected); } -const inf128 = @bitCast(f128, u128(0x7fff0000000000000000000000000000)); +const inf128 = @bitCast(f128, @as(u128, 0x7fff0000000000000000000000000000)); test "fixunstfti" { test__fixunstfti(inf128, 0xffffffffffffffffffffffffffffffff); diff --git a/lib/std/special/compiler_rt/floatsiXf.zig b/lib/std/special/compiler_rt/floatsiXf.zig @@ -6,24 +6,24 @@ fn floatsiXf(comptime T: type, a: i32) T { @setRuntimeSafety(builtin.is_test); const Z = @IntType(false, T.bit_count); - const S = @IntType(false, T.bit_count - @clz(Z, Z(T.bit_count) - 1)); + const S = @IntType(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1)); if (a == 0) { - return T(0.0); + return @as(T, 0.0); } const significandBits = std.math.floatMantissaBits(T); const exponentBits = std.math.floatExponentBits(T); const exponentBias = ((1 << exponentBits - 1) - 1); - const implicitBit = Z(1) << significandBits; - const signBit = Z(1 << Z.bit_count - 1); + const implicitBit = @as(Z, 1) << significandBits; + const signBit = @as(Z, 1 << Z.bit_count - 1); const sign = a >> 31; // Take absolute value of a via abs(x) = (x^(x >> 31)) - (x >> 31). const abs_a = (a ^ sign) -% sign; // The exponent is the width of abs(a) - const exp = Z(31 - @clz(i32, abs_a)); + const exp = @as(Z, 31 - @clz(i32, abs_a)); const sign_bit = if (sign < 0) signBit else 0; diff --git a/lib/std/special/compiler_rt/floattidf.zig b/lib/std/special/compiler_rt/floattidf.zig @@ -47,7 +47,7 @@ pub extern fn __floattidf(arg: i128) f64 { a += 1; // round - this step may add a significant bit a >>= 2; // dump Q and R // a is now rounded to DBL_MANT_DIG or DBL_MANT_DIG+1 bits - if ((a & (u128(1) << DBL_MANT_DIG)) != 0) { + if ((a & (@as(u128, 1) << DBL_MANT_DIG)) != 0) { a >>= 1; e += 1; } diff --git a/lib/std/special/compiler_rt/floattisf.zig b/lib/std/special/compiler_rt/floattisf.zig @@ -48,7 +48,7 @@ pub extern fn __floattisf(arg: i128) f32 { a += 1; // round - this step may add a significant bit a >>= 2; // dump Q and R // a is now rounded to FLT_MANT_DIG or FLT_MANT_DIG+1 bits - if ((a & (u128(1) << FLT_MANT_DIG)) != 0) { + if ((a & (@as(u128, 1) << FLT_MANT_DIG)) != 0) { a >>= 1; e += 1; } diff --git a/lib/std/special/compiler_rt/floattitf.zig b/lib/std/special/compiler_rt/floattitf.zig @@ -47,7 +47,7 @@ pub extern fn __floattitf(arg: i128) f128 { a += 1; // round - this step may add a significant bit a >>= 2; // dump Q and R // a is now rounded to LDBL_MANT_DIG or LDBL_MANT_DIG+1 bits - if ((a & (u128(1) << LDBL_MANT_DIG)) != 0) { + if ((a & (@as(u128, 1) << LDBL_MANT_DIG)) != 0) { a >>= 1; e += 1; } diff --git a/lib/std/special/compiler_rt/floatunsidf.zig b/lib/std/special/compiler_rt/floatunsidf.zig @@ -2,7 +2,7 @@ const builtin = @import("builtin"); const std = @import("std"); const maxInt = std.math.maxInt; -const implicitBit = u64(1) << 52; +const implicitBit = @as(u64, 1) << 52; pub extern fn __floatunsidf(arg: u32) f64 { @setRuntimeSafety(builtin.is_test); @@ -10,10 +10,10 @@ pub extern fn __floatunsidf(arg: u32) f64 { if (arg == 0) return 0.0; // The exponent is the width of abs(a) - const exp = u64(31) - @clz(u32, arg); + const exp = @as(u64, 31) - @clz(u32, arg); // Shift a into the significand field and clear the implicit bit const shift = @intCast(u6, 52 - exp); - const mant = u64(arg) << shift ^ implicitBit; + const mant = @as(u64, arg) << shift ^ implicitBit; return @bitCast(f64, mant | (exp + 1023) << 52); } diff --git a/lib/std/special/compiler_rt/floatuntidf.zig b/lib/std/special/compiler_rt/floatuntidf.zig @@ -32,7 +32,7 @@ pub extern fn __floatuntidf(arg: u128) f64 { const shift_amt = @bitCast(i32, N + (DBL_MANT_DIG + 2)) - sd; const shift_amt_u7 = @intCast(u7, shift_amt); a = (a >> @intCast(u7, sd - (DBL_MANT_DIG + 2))) | - @boolToInt((a & (u128(maxInt(u128)) >> shift_amt_u7)) != 0); + @boolToInt((a & (@as(u128, maxInt(u128)) >> shift_amt_u7)) != 0); }, } // finish @@ -40,7 +40,7 @@ pub extern fn __floatuntidf(arg: u128) f64 { a += 1; // round - this step may add a significant bit a >>= 2; // dump Q and R // a is now rounded to DBL_MANT_DIG or DBL_MANT_DIG+1 bits - if ((a & (u128(1) << DBL_MANT_DIG)) != 0) { + if ((a & (@as(u128, 1) << DBL_MANT_DIG)) != 0) { a >>= 1; e += 1; } diff --git a/lib/std/special/compiler_rt/floatuntisf.zig b/lib/std/special/compiler_rt/floatuntisf.zig @@ -32,7 +32,7 @@ pub extern fn __floatuntisf(arg: u128) f32 { const shift_amt = @bitCast(i32, N + (FLT_MANT_DIG + 2)) - sd; const shift_amt_u7 = @intCast(u7, shift_amt); a = (a >> @intCast(u7, sd - (FLT_MANT_DIG + 2))) | - @boolToInt((a & (u128(maxInt(u128)) >> shift_amt_u7)) != 0); + @boolToInt((a & (@as(u128, maxInt(u128)) >> shift_amt_u7)) != 0); }, } // finish @@ -40,7 +40,7 @@ pub extern fn __floatuntisf(arg: u128) f32 { a += 1; // round - this step may add a significant bit a >>= 2; // dump Q and R // a is now rounded to FLT_MANT_DIG or FLT_MANT_DIG+1 bits - if ((a & (u128(1) << FLT_MANT_DIG)) != 0) { + if ((a & (@as(u128, 1) << FLT_MANT_DIG)) != 0) { a >>= 1; e += 1; } diff --git a/lib/std/special/compiler_rt/floatuntitf.zig b/lib/std/special/compiler_rt/floatuntitf.zig @@ -32,7 +32,7 @@ pub extern fn __floatuntitf(arg: u128) f128 { const shift_amt = @bitCast(i32, N + (LDBL_MANT_DIG + 2)) - sd; const shift_amt_u7 = @intCast(u7, shift_amt); a = (a >> @intCast(u7, sd - (LDBL_MANT_DIG + 2))) | - @boolToInt((a & (u128(maxInt(u128)) >> shift_amt_u7)) != 0); + @boolToInt((a & (@as(u128, maxInt(u128)) >> shift_amt_u7)) != 0); }, } // finish @@ -40,7 +40,7 @@ pub extern fn __floatuntitf(arg: u128) f128 { a += 1; // round - this step may add a significant bit a >>= 2; // dump Q and R // a is now rounded to LDBL_MANT_DIG or LDBL_MANT_DIG+1 bits - if ((a & (u128(1) << LDBL_MANT_DIG)) != 0) { + if ((a & (@as(u128, 1) << LDBL_MANT_DIG)) != 0) { a >>= 1; e += 1; } diff --git a/lib/std/special/compiler_rt/mulXf3.zig b/lib/std/special/compiler_rt/mulXf3.zig @@ -24,11 +24,11 @@ fn mulXf3(comptime T: type, a: T, b: T) T { const significandBits = std.math.floatMantissaBits(T); const exponentBits = std.math.floatExponentBits(T); - const signBit = (Z(1) << (significandBits + exponentBits)); + const signBit = (@as(Z, 1) << (significandBits + exponentBits)); const maxExponent = ((1 << exponentBits) - 1); const exponentBias = (maxExponent >> 1); - const implicitBit = (Z(1) << significandBits); + const implicitBit = (@as(Z, 1) << significandBits); const quietBit = implicitBit >> 1; const significandMask = implicitBit - 1; @@ -122,7 +122,7 @@ fn mulXf3(comptime T: type, a: T, b: T) T { // a zero of the appropriate sign. Mathematically there is no need to // handle this case separately, but we make it a special case to // simplify the shift logic. - const shift: u32 = @truncate(u32, Z(1) -% @bitCast(u32, productExponent)); + const shift: u32 = @truncate(u32, @as(Z, 1) -% @bitCast(u32, productExponent)); if (shift >= typeWidth) return @bitCast(T, productSign); // Otherwise, shift the significand of the result so that the round @@ -131,7 +131,7 @@ fn mulXf3(comptime T: type, a: T, b: T) T { } else { // Result is normal before rounding; insert the exponent. productHi &= significandMask; - productHi |= Z(@bitCast(u32, productExponent)) << significandBits; + productHi |= @as(Z, @bitCast(u32, productExponent)) << significandBits; } // Insert the sign of the result: @@ -150,7 +150,7 @@ fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void { switch (Z) { u32 => { // 32x32 --> 64 bit multiply - const product = u64(a) * u64(b); + const product = @as(u64, a) * @as(u64, b); hi.* = @truncate(u32, product >> 32); lo.* = @truncate(u32, product); }, @@ -179,9 +179,9 @@ fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void { hi.* = S.hiWord(plohi) +% S.hiWord(philo) +% S.hiWord(r1) +% phihi; }, u128 => { - const Word_LoMask = u64(0x00000000ffffffff); - const Word_HiMask = u64(0xffffffff00000000); - const Word_FullMask = u64(0xffffffffffffffff); + const Word_LoMask = @as(u64, 0x00000000ffffffff); + const Word_HiMask = @as(u64, 0xffffffff00000000); + const Word_FullMask = @as(u64, 0xffffffffffffffff); const S = struct { fn Word_1(x: u128) u64 { return @truncate(u32, x >> 96); @@ -217,22 +217,22 @@ fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void { const product43: u64 = S.Word_4(a) * S.Word_3(b); const product44: u64 = S.Word_4(a) * S.Word_4(b); - const sum0: u128 = u128(product44); - const sum1: u128 = u128(product34) +% - u128(product43); - const sum2: u128 = u128(product24) +% - u128(product33) +% - u128(product42); - const sum3: u128 = u128(product14) +% - u128(product23) +% - u128(product32) +% - u128(product41); - const sum4: u128 = u128(product13) +% - u128(product22) +% - u128(product31); - const sum5: u128 = u128(product12) +% - u128(product21); - const sum6: u128 = u128(product11); + const sum0: u128 = @as(u128, product44); + const sum1: u128 = @as(u128, product34) +% + @as(u128, product43); + const sum2: u128 = @as(u128, product24) +% + @as(u128, product33) +% + @as(u128, product42); + const sum3: u128 = @as(u128, product14) +% + @as(u128, product23) +% + @as(u128, product32) +% + @as(u128, product41); + const sum4: u128 = @as(u128, product13) +% + @as(u128, product22) +% + @as(u128, product31); + const sum5: u128 = @as(u128, product12) +% + @as(u128, product21); + const sum6: u128 = @as(u128, product11); const r0: u128 = (sum0 & Word_FullMask) +% ((sum1 & Word_LoMask) << 32); @@ -258,7 +258,7 @@ fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 { @setRuntimeSafety(builtin.is_test); const Z = @IntType(false, T.bit_count); const significandBits = std.math.floatMantissaBits(T); - const implicitBit = Z(1) << significandBits; + const implicitBit = @as(Z, 1) << significandBits; const shift = @clz(Z, significand.*) - @clz(Z, implicitBit); significand.* <<= @intCast(std.math.Log2Int(Z), shift); diff --git a/lib/std/special/compiler_rt/mulXf3_test.zig b/lib/std/special/compiler_rt/mulXf3_test.zig @@ -2,8 +2,8 @@ // // https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/test/builtins/Unit/multf3_test.c -const qnan128 = @bitCast(f128, u128(0x7fff800000000000) << 64); -const inf128 = @bitCast(f128, u128(0x7fff000000000000) << 64); +const qnan128 = @bitCast(f128, @as(u128, 0x7fff800000000000) << 64); +const inf128 = @bitCast(f128, @as(u128, 0x7fff000000000000) << 64); const __multf3 = @import("mulXf3.zig").__multf3; @@ -39,7 +39,7 @@ fn test__multf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) void { } fn makeNaN128(rand: u64) f128 { - const int_result = u128(0x7fff000000000000 | (rand & 0xffffffffffff)) << 64; + const int_result = @as(u128, 0x7fff000000000000 | (rand & 0xffffffffffff)) << 64; const float_result = @bitCast(f128, int_result); return float_result; } @@ -55,15 +55,15 @@ test "multf3" { // any * any test__multf3( - @bitCast(f128, u128(0x40042eab345678439abcdefea5678234)), - @bitCast(f128, u128(0x3ffeedcb34a235253948765432134675)), + @bitCast(f128, @as(u128, 0x40042eab345678439abcdefea5678234)), + @bitCast(f128, @as(u128, 0x3ffeedcb34a235253948765432134675)), 0x400423e7f9e3c9fc, 0xd906c2c2a85777c4, ); test__multf3( - @bitCast(f128, u128(0x3fcd353e45674d89abacc3a2ebf3ff50)), - @bitCast(f128, u128(0x3ff6ed8764648369535adf4be3214568)), + @bitCast(f128, @as(u128, 0x3fcd353e45674d89abacc3a2ebf3ff50)), + @bitCast(f128, @as(u128, 0x3ff6ed8764648369535adf4be3214568)), 0x3fc52a163c6223fc, 0xc94c4bf0430768b4, ); @@ -76,8 +76,8 @@ test "multf3" { ); test__multf3( - @bitCast(f128, u128(0x3f154356473c82a9fabf2d22ace345df)), - @bitCast(f128, u128(0x3e38eda98765476743ab21da23d45679)), + @bitCast(f128, @as(u128, 0x3f154356473c82a9fabf2d22ace345df)), + @bitCast(f128, @as(u128, 0x3e38eda98765476743ab21da23d45679)), 0x3d4f37c1a3137cae, 0xfc6807048bc2836a, ); diff --git a/lib/std/special/compiler_rt/muldi3.zig b/lib/std/special/compiler_rt/muldi3.zig @@ -21,7 +21,7 @@ fn __muldsi3(a: u32, b: u32) i64 { @setRuntimeSafety(builtin.is_test); const bits_in_word_2 = @sizeOf(i32) * 8 / 2; - const lower_mask = (~u32(0)) >> bits_in_word_2; + const lower_mask = (~@as(u32, 0)) >> bits_in_word_2; var r: dwords = undefined; r.s.low = (a & lower_mask) *% (b & lower_mask); diff --git a/lib/std/special/compiler_rt/mulodi4.zig b/lib/std/special/compiler_rt/mulodi4.zig @@ -6,7 +6,7 @@ const minInt = std.math.minInt; pub extern fn __mulodi4(a: i64, b: i64, overflow: *c_int) i64 { @setRuntimeSafety(builtin.is_test); - const min = @bitCast(i64, u64(1 << (i64.bit_count - 1))); + const min = @bitCast(i64, @as(u64, 1 << (i64.bit_count - 1))); const max = ~min; overflow.* = 0; diff --git a/lib/std/special/compiler_rt/mulodi4_test.zig b/lib/std/special/compiler_rt/mulodi4_test.zig @@ -52,34 +52,34 @@ test "mulodi4" { test__mulodi4(0x7FFFFFFFFFFFFFFF, -2, 2, 1); test__mulodi4(-2, 0x7FFFFFFFFFFFFFFF, 2, 1); - test__mulodi4(0x7FFFFFFFFFFFFFFF, -1, @bitCast(i64, u64(0x8000000000000001)), 0); - test__mulodi4(-1, 0x7FFFFFFFFFFFFFFF, @bitCast(i64, u64(0x8000000000000001)), 0); + test__mulodi4(0x7FFFFFFFFFFFFFFF, -1, @bitCast(i64, @as(u64, 0x8000000000000001)), 0); + test__mulodi4(-1, 0x7FFFFFFFFFFFFFFF, @bitCast(i64, @as(u64, 0x8000000000000001)), 0); test__mulodi4(0x7FFFFFFFFFFFFFFF, 0, 0, 0); test__mulodi4(0, 0x7FFFFFFFFFFFFFFF, 0, 0); test__mulodi4(0x7FFFFFFFFFFFFFFF, 1, 0x7FFFFFFFFFFFFFFF, 0); test__mulodi4(1, 0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFF, 0); - test__mulodi4(0x7FFFFFFFFFFFFFFF, 2, @bitCast(i64, u64(0x8000000000000001)), 1); - test__mulodi4(2, 0x7FFFFFFFFFFFFFFF, @bitCast(i64, u64(0x8000000000000001)), 1); + test__mulodi4(0x7FFFFFFFFFFFFFFF, 2, @bitCast(i64, @as(u64, 0x8000000000000001)), 1); + test__mulodi4(2, 0x7FFFFFFFFFFFFFFF, @bitCast(i64, @as(u64, 0x8000000000000001)), 1); - test__mulodi4(@bitCast(i64, u64(0x8000000000000000)), -2, @bitCast(i64, u64(0x8000000000000000)), 1); - test__mulodi4(-2, @bitCast(i64, u64(0x8000000000000000)), @bitCast(i64, u64(0x8000000000000000)), 1); - test__mulodi4(@bitCast(i64, u64(0x8000000000000000)), -1, @bitCast(i64, u64(0x8000000000000000)), 1); - test__mulodi4(-1, @bitCast(i64, u64(0x8000000000000000)), @bitCast(i64, u64(0x8000000000000000)), 1); - test__mulodi4(@bitCast(i64, u64(0x8000000000000000)), 0, 0, 0); - test__mulodi4(0, @bitCast(i64, u64(0x8000000000000000)), 0, 0); - test__mulodi4(@bitCast(i64, u64(0x8000000000000000)), 1, @bitCast(i64, u64(0x8000000000000000)), 0); - test__mulodi4(1, @bitCast(i64, u64(0x8000000000000000)), @bitCast(i64, u64(0x8000000000000000)), 0); - test__mulodi4(@bitCast(i64, u64(0x8000000000000000)), 2, @bitCast(i64, u64(0x8000000000000000)), 1); - test__mulodi4(2, @bitCast(i64, u64(0x8000000000000000)), @bitCast(i64, u64(0x8000000000000000)), 1); + test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000000)), -2, @bitCast(i64, @as(u64, 0x8000000000000000)), 1); + test__mulodi4(-2, @bitCast(i64, @as(u64, 0x8000000000000000)), @bitCast(i64, @as(u64, 0x8000000000000000)), 1); + test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000000)), -1, @bitCast(i64, @as(u64, 0x8000000000000000)), 1); + test__mulodi4(-1, @bitCast(i64, @as(u64, 0x8000000000000000)), @bitCast(i64, @as(u64, 0x8000000000000000)), 1); + test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000000)), 0, 0, 0); + test__mulodi4(0, @bitCast(i64, @as(u64, 0x8000000000000000)), 0, 0); + test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000000)), 1, @bitCast(i64, @as(u64, 0x8000000000000000)), 0); + test__mulodi4(1, @bitCast(i64, @as(u64, 0x8000000000000000)), @bitCast(i64, @as(u64, 0x8000000000000000)), 0); + test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000000)), 2, @bitCast(i64, @as(u64, 0x8000000000000000)), 1); + test__mulodi4(2, @bitCast(i64, @as(u64, 0x8000000000000000)), @bitCast(i64, @as(u64, 0x8000000000000000)), 1); - test__mulodi4(@bitCast(i64, u64(0x8000000000000001)), -2, @bitCast(i64, u64(0x8000000000000001)), 1); - test__mulodi4(-2, @bitCast(i64, u64(0x8000000000000001)), @bitCast(i64, u64(0x8000000000000001)), 1); - test__mulodi4(@bitCast(i64, u64(0x8000000000000001)), -1, 0x7FFFFFFFFFFFFFFF, 0); - test__mulodi4(-1, @bitCast(i64, u64(0x8000000000000001)), 0x7FFFFFFFFFFFFFFF, 0); - test__mulodi4(@bitCast(i64, u64(0x8000000000000001)), 0, 0, 0); - test__mulodi4(0, @bitCast(i64, u64(0x8000000000000001)), 0, 0); - test__mulodi4(@bitCast(i64, u64(0x8000000000000001)), 1, @bitCast(i64, u64(0x8000000000000001)), 0); - test__mulodi4(1, @bitCast(i64, u64(0x8000000000000001)), @bitCast(i64, u64(0x8000000000000001)), 0); - test__mulodi4(@bitCast(i64, u64(0x8000000000000001)), 2, @bitCast(i64, u64(0x8000000000000000)), 1); - test__mulodi4(2, @bitCast(i64, u64(0x8000000000000001)), @bitCast(i64, u64(0x8000000000000000)), 1); + test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000001)), -2, @bitCast(i64, @as(u64, 0x8000000000000001)), 1); + test__mulodi4(-2, @bitCast(i64, @as(u64, 0x8000000000000001)), @bitCast(i64, @as(u64, 0x8000000000000001)), 1); + test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000001)), -1, 0x7FFFFFFFFFFFFFFF, 0); + test__mulodi4(-1, @bitCast(i64, @as(u64, 0x8000000000000001)), 0x7FFFFFFFFFFFFFFF, 0); + test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000001)), 0, 0, 0); + test__mulodi4(0, @bitCast(i64, @as(u64, 0x8000000000000001)), 0, 0); + test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000001)), 1, @bitCast(i64, @as(u64, 0x8000000000000001)), 0); + test__mulodi4(1, @bitCast(i64, @as(u64, 0x8000000000000001)), @bitCast(i64, @as(u64, 0x8000000000000001)), 0); + test__mulodi4(@bitCast(i64, @as(u64, 0x8000000000000001)), 2, @bitCast(i64, @as(u64, 0x8000000000000000)), 1); + test__mulodi4(2, @bitCast(i64, @as(u64, 0x8000000000000001)), @bitCast(i64, @as(u64, 0x8000000000000000)), 1); } diff --git a/lib/std/special/compiler_rt/muloti4.zig b/lib/std/special/compiler_rt/muloti4.zig @@ -4,7 +4,7 @@ const compiler_rt = @import("../compiler_rt.zig"); pub extern fn __muloti4(a: i128, b: i128, overflow: *c_int) i128 { @setRuntimeSafety(builtin.is_test); - const min = @bitCast(i128, u128(1 << (i128.bit_count - 1))); + const min = @bitCast(i128, @as(u128, 1 << (i128.bit_count - 1))); const max = ~min; overflow.* = 0; diff --git a/lib/std/special/compiler_rt/muloti4_test.zig b/lib/std/special/compiler_rt/muloti4_test.zig @@ -39,38 +39,38 @@ test "muloti4" { test__muloti4(2097152, -4398046511103, -9223372036852678656, 0); test__muloti4(-2097152, -4398046511103, 9223372036852678656, 0); - test__muloti4(@bitCast(i128, u128(0x00000000000000B504F333F9DE5BE000)), @bitCast(i128, u128(0x000000000000000000B504F333F9DE5B)), @bitCast(i128, u128(0x7FFFFFFFFFFFF328DF915DA296E8A000)), 0); - test__muloti4(@bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), -2, @bitCast(i128, u128(0x80000000000000000000000000000001)), 1); - test__muloti4(-2, @bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), @bitCast(i128, u128(0x80000000000000000000000000000001)), 1); + test__muloti4(@bitCast(i128, @as(u128, 0x00000000000000B504F333F9DE5BE000)), @bitCast(i128, @as(u128, 0x000000000000000000B504F333F9DE5B)), @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFF328DF915DA296E8A000)), 0); + test__muloti4(@bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), -2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 1); + test__muloti4(-2, @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 1); - test__muloti4(@bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), -1, @bitCast(i128, u128(0x80000000000000000000000000000001)), 0); - test__muloti4(-1, @bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), @bitCast(i128, u128(0x80000000000000000000000000000001)), 0); - test__muloti4(@bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0, 0, 0); - test__muloti4(0, @bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0, 0); - test__muloti4(@bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 1, @bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0); - test__muloti4(1, @bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), @bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0); - test__muloti4(@bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 2, @bitCast(i128, u128(0x80000000000000000000000000000001)), 1); - test__muloti4(2, @bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), @bitCast(i128, u128(0x80000000000000000000000000000001)), 1); + test__muloti4(@bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), -1, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 0); + test__muloti4(-1, @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 0); + test__muloti4(@bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0, 0, 0); + test__muloti4(0, @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0, 0); + test__muloti4(@bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 1, @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0); + test__muloti4(1, @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0); + test__muloti4(@bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 1); + test__muloti4(2, @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 1); - test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000000)), -2, @bitCast(i128, u128(0x80000000000000000000000000000000)), 1); - test__muloti4(-2, @bitCast(i128, u128(0x80000000000000000000000000000000)), @bitCast(i128, u128(0x80000000000000000000000000000000)), 1); - test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000000)), -1, @bitCast(i128, u128(0x80000000000000000000000000000000)), 1); - test__muloti4(-1, @bitCast(i128, u128(0x80000000000000000000000000000000)), @bitCast(i128, u128(0x80000000000000000000000000000000)), 1); - test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000000)), 0, 0, 0); - test__muloti4(0, @bitCast(i128, u128(0x80000000000000000000000000000000)), 0, 0); - test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000000)), 1, @bitCast(i128, u128(0x80000000000000000000000000000000)), 0); - test__muloti4(1, @bitCast(i128, u128(0x80000000000000000000000000000000)), @bitCast(i128, u128(0x80000000000000000000000000000000)), 0); - test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000000)), 2, @bitCast(i128, u128(0x80000000000000000000000000000000)), 1); - test__muloti4(2, @bitCast(i128, u128(0x80000000000000000000000000000000)), @bitCast(i128, u128(0x80000000000000000000000000000000)), 1); + test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), -2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 1); + test__muloti4(-2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 1); + test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), -1, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 1); + test__muloti4(-1, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 1); + test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 0, 0, 0); + test__muloti4(0, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 0, 0); + test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 1, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 0); + test__muloti4(1, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 0); + test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 1); + test__muloti4(2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 1); - test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000001)), -2, @bitCast(i128, u128(0x80000000000000000000000000000001)), 1); - test__muloti4(-2, @bitCast(i128, u128(0x80000000000000000000000000000001)), @bitCast(i128, u128(0x80000000000000000000000000000001)), 1); - test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000001)), -1, @bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0); - test__muloti4(-1, @bitCast(i128, u128(0x80000000000000000000000000000001)), @bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0); - test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000001)), 0, 0, 0); - test__muloti4(0, @bitCast(i128, u128(0x80000000000000000000000000000001)), 0, 0); - test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000001)), 1, @bitCast(i128, u128(0x80000000000000000000000000000001)), 0); - test__muloti4(1, @bitCast(i128, u128(0x80000000000000000000000000000001)), @bitCast(i128, u128(0x80000000000000000000000000000001)), 0); - test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000001)), 2, @bitCast(i128, u128(0x80000000000000000000000000000000)), 1); - test__muloti4(2, @bitCast(i128, u128(0x80000000000000000000000000000001)), @bitCast(i128, u128(0x80000000000000000000000000000000)), 1); + test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), -2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 1); + test__muloti4(-2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 1); + test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), -1, @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0); + test__muloti4(-1, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), @bitCast(i128, @as(u128, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0); + test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 0, 0, 0); + test__muloti4(0, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 0, 0); + test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 1, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 0); + test__muloti4(1, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 0); + test__muloti4(@bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), 2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 1); + test__muloti4(2, @bitCast(i128, @as(u128, 0x80000000000000000000000000000001)), @bitCast(i128, @as(u128, 0x80000000000000000000000000000000)), 1); } diff --git a/lib/std/special/compiler_rt/multi3.zig b/lib/std/special/compiler_rt/multi3.zig @@ -21,7 +21,7 @@ pub extern fn __multi3_windows_x86_64(a: v128, b: v128) v128 { fn __mulddi3(a: u64, b: u64) i128 { const bits_in_dword_2 = (@sizeOf(i64) * 8) / 2; - const lower_mask = ~u64(0) >> bits_in_dword_2; + const lower_mask = ~@as(u64, 0) >> bits_in_dword_2; var r: twords = undefined; r.s.low = (a & lower_mask) *% (b & lower_mask); var t: u64 = r.s.low >> bits_in_dword_2; diff --git a/lib/std/special/compiler_rt/negXf2.zig b/lib/std/special/compiler_rt/negXf2.zig @@ -15,7 +15,7 @@ fn negXf2(comptime T: type, a: T) T { const significandBits = std.math.floatMantissaBits(T); const exponentBits = std.math.floatExponentBits(T); - const signBit = (Z(1) << (significandBits + exponentBits)); + const signBit = (@as(Z, 1) << (significandBits + exponentBits)); return @bitCast(T, @bitCast(Z, a) ^ signBit); } diff --git a/lib/std/special/compiler_rt/popcountdi2_test.zig b/lib/std/special/compiler_rt/popcountdi2_test.zig @@ -20,8 +20,8 @@ test "popcountdi2" { test__popcountdi2(0); test__popcountdi2(1); test__popcountdi2(2); - test__popcountdi2(@bitCast(i64, u64(0xFFFFFFFFFFFFFFFD))); - test__popcountdi2(@bitCast(i64, u64(0xFFFFFFFFFFFFFFFE))); - test__popcountdi2(@bitCast(i64, u64(0xFFFFFFFFFFFFFFFF))); + test__popcountdi2(@bitCast(i64, @as(u64, 0xFFFFFFFFFFFFFFFD))); + test__popcountdi2(@bitCast(i64, @as(u64, 0xFFFFFFFFFFFFFFFE))); + test__popcountdi2(@bitCast(i64, @as(u64, 0xFFFFFFFFFFFFFFFF))); // TODO some fuzz testing } diff --git a/lib/std/special/compiler_rt/truncXfYf2.zig b/lib/std/special/compiler_rt/truncXfYf2.zig @@ -69,7 +69,7 @@ inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t // destination format. We can convert by simply right-shifting with // rounding and adjusting the exponent. absResult = @truncate(dst_rep_t, aAbs >> (srcSigBits - dstSigBits)); - absResult -%= dst_rep_t(srcExpBias - dstExpBias) << dstSigBits; + absResult -%= @as(dst_rep_t, srcExpBias - dstExpBias) << dstSigBits; const roundBits: src_rep_t = aAbs & roundMask; if (roundBits > halfway) { diff --git a/lib/std/special/compiler_rt/truncXfYf2_test.zig b/lib/std/special/compiler_rt/truncXfYf2_test.zig @@ -152,11 +152,11 @@ fn test__trunctfsf2(a: f128, expected: u32) void { test "trunctfsf2" { // qnan - test__trunctfsf2(@bitCast(f128, u128(0x7fff800000000000 << 64)), 0x7fc00000); + test__trunctfsf2(@bitCast(f128, @as(u128, 0x7fff800000000000 << 64)), 0x7fc00000); // nan - test__trunctfsf2(@bitCast(f128, u128((0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7fc08000); + test__trunctfsf2(@bitCast(f128, @as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7fc08000); // inf - test__trunctfsf2(@bitCast(f128, u128(0x7fff000000000000 << 64)), 0x7f800000); + test__trunctfsf2(@bitCast(f128, @as(u128, 0x7fff000000000000 << 64)), 0x7f800000); // zero test__trunctfsf2(0.0, 0x0); @@ -187,11 +187,11 @@ fn test__trunctfdf2(a: f128, expected: u64) void { test "trunctfdf2" { // qnan - test__trunctfdf2(@bitCast(f128, u128(0x7fff800000000000 << 64)), 0x7ff8000000000000); + test__trunctfdf2(@bitCast(f128, @as(u128, 0x7fff800000000000 << 64)), 0x7ff8000000000000); // nan - test__trunctfdf2(@bitCast(f128, u128((0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7ff8100000000000); + test__trunctfdf2(@bitCast(f128, @as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7ff8100000000000); // inf - test__trunctfdf2(@bitCast(f128, u128(0x7fff000000000000 << 64)), 0x7ff0000000000000); + test__trunctfdf2(@bitCast(f128, @as(u128, 0x7fff000000000000 << 64)), 0x7ff0000000000000); // zero test__trunctfdf2(0.0, 0x0); @@ -224,11 +224,11 @@ fn test__truncdfsf2(a: f64, expected: u32) void { test "truncdfsf2" { // nan & qnan - test__truncdfsf2(@bitCast(f64, u64(0x7ff8000000000000)), 0x7fc00000); - test__truncdfsf2(@bitCast(f64, u64(0x7ff0000000000001)), 0x7fc00000); + test__truncdfsf2(@bitCast(f64, @as(u64, 0x7ff8000000000000)), 0x7fc00000); + test__truncdfsf2(@bitCast(f64, @as(u64, 0x7ff0000000000001)), 0x7fc00000); // inf - test__truncdfsf2(@bitCast(f64, u64(0x7ff0000000000000)), 0x7f800000); - test__truncdfsf2(@bitCast(f64, u64(0xfff0000000000000)), 0xff800000); + test__truncdfsf2(@bitCast(f64, @as(u64, 0x7ff0000000000000)), 0x7f800000); + test__truncdfsf2(@bitCast(f64, @as(u64, 0xfff0000000000000)), 0xff800000); test__truncdfsf2(0.0, 0x0); test__truncdfsf2(1.0, 0x3f800000); diff --git a/lib/std/special/compiler_rt/udivmod.zig b/lib/std/special/compiler_rt/udivmod.zig @@ -76,7 +76,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: // K K // --- // K 0 - sr = @bitCast(c_uint, c_int(@clz(SingleInt, d[high])) - c_int(@clz(SingleInt, n[high]))); + sr = @bitCast(c_uint, @as(c_int, @clz(SingleInt, d[high])) - @as(c_int, @clz(SingleInt, n[high]))); // 0 <= sr <= SingleInt.bit_count - 2 or sr large if (sr > SingleInt.bit_count - 2) { if (maybe_rem) |rem| { @@ -114,7 +114,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: // K X // --- // 0 K - sr = 1 + SingleInt.bit_count + c_uint(@clz(SingleInt, d[low])) - c_uint(@clz(SingleInt, n[high])); + sr = 1 + SingleInt.bit_count + @as(c_uint, @clz(SingleInt, d[low])) - @as(c_uint, @clz(SingleInt, n[high])); // 2 <= sr <= DoubleInt.bit_count - 1 // q.all = a << (DoubleInt.bit_count - sr); // r.all = a >> sr; @@ -140,7 +140,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: // K X // --- // K K - sr = @bitCast(c_uint, c_int(@clz(SingleInt, d[high])) - c_int(@clz(SingleInt, n[high]))); + sr = @bitCast(c_uint, @as(c_int, @clz(SingleInt, d[high])) - @as(c_int, @clz(SingleInt, n[high]))); // 0 <= sr <= SingleInt.bit_count - 1 or sr large if (sr > SingleInt.bit_count - 1) { if (maybe_rem) |rem| { diff --git a/lib/std/special/docs/index.html b/lib/std/special/docs/index.html @@ -484,7 +484,7 @@ doc comments. </p> </div> - <div id="fnDocs" class="hidden"></div> + <div id="tldDocs" class="hidden"></div> <div id="sectFnErrors" class="hidden"> <h2>Errors</h2> <div id="fnErrorsAnyError"> diff --git a/lib/std/special/docs/main.js b/lib/std/special/docs/main.js @@ -20,7 +20,7 @@ var domListValues = document.getElementById("listValues"); var domFnProto = document.getElementById("fnProto"); var domFnProtoCode = document.getElementById("fnProtoCode"); - var domFnDocs = document.getElementById("fnDocs"); + var domTldDocs = document.getElementById("tldDocs"); var domSectFnErrors = document.getElementById("sectFnErrors"); var domListFnErrors = document.getElementById("listFnErrors"); var domTableFnErrors = document.getElementById("tableFnErrors"); @@ -34,7 +34,6 @@ var domListSearchResults = document.getElementById("listSearchResults"); var domSectSearchNoResults = document.getElementById("sectSearchNoResults"); var domSectInfo = document.getElementById("sectInfo"); - var domListInfo = document.getElementById("listInfo"); var domTdTarget = document.getElementById("tdTarget"); var domTdZigVer = document.getElementById("tdZigVer"); var domHdrName = document.getElementById("hdrName"); @@ -102,7 +101,7 @@ function render() { domStatus.classList.add("hidden"); domFnProto.classList.add("hidden"); - domFnDocs.classList.add("hidden"); + domTldDocs.classList.add("hidden"); domSectPkgs.classList.add("hidden"); domSectTypes.classList.add("hidden"); domSectNamespaces.classList.add("hidden"); @@ -190,11 +189,11 @@ var docs = zigAnalysis.astNodes[decl.src].docs; if (docs != null) { - domFnDocs.innerHTML = markdown(docs); + domTldDocs.innerHTML = markdown(docs); } else { - domFnDocs.innerHTML = '<p>There are no doc comments for this declaration.</p>'; + domTldDocs.innerHTML = '<p>There are no doc comments for this declaration.</p>'; } - domFnDocs.classList.remove("hidden"); + domTldDocs.classList.remove("hidden"); } function typeIsErrSet(typeIndex) { @@ -274,8 +273,8 @@ docsSource = protoSrcNode.docs; } if (docsSource != null) { - domFnDocs.innerHTML = markdown(docsSource); - domFnDocs.classList.remove("hidden"); + domTldDocs.innerHTML = markdown(docsSource); + domTldDocs.classList.remove("hidden"); } domFnProto.classList.remove("hidden"); } @@ -893,8 +892,8 @@ var docs = zigAnalysis.astNodes[decl.src].docs; if (docs != null) { - domFnDocs.innerHTML = markdown(docs); - domFnDocs.classList.remove("hidden"); + domTldDocs.innerHTML = markdown(docs); + domTldDocs.classList.remove("hidden"); } domFnProto.classList.remove("hidden"); @@ -906,8 +905,8 @@ var docs = zigAnalysis.astNodes[decl.src].docs; if (docs != null) { - domFnDocs.innerHTML = markdown(docs); - domFnDocs.classList.remove("hidden"); + domTldDocs.innerHTML = markdown(docs); + domTldDocs.classList.remove("hidden"); } domFnProto.classList.remove("hidden"); @@ -957,6 +956,14 @@ varsList.sort(byNameProperty); valsList.sort(byNameProperty); + if (container.src != null) { + var docs = zigAnalysis.astNodes[container.src].docs; + if (docs != null) { + domTldDocs.innerHTML = markdown(docs); + domTldDocs.classList.remove("hidden"); + } + } + if (typesList.length !== 0) { resizeDomList(domListTypes, typesList.length, '<li><a href="#"></a></li>'); for (var i = 0; i < typesList.length; i += 1) { diff --git a/lib/std/special/start.zig b/lib/std/special/start.zig @@ -214,7 +214,7 @@ inline fn initEventLoopAndCallMain() u8 { return @inlineCall(callMain); } -fn callMainAsync(loop: *std.event.Loop) u8 { +async fn callMainAsync(loop: *std.event.Loop) u8 { // This prevents the event loop from terminating at least until main() has returned. loop.beginOneEvent(); defer loop.finishOneEvent(); diff --git a/lib/std/spinlock.zig b/lib/std/spinlock.zig @@ -1,8 +1,8 @@ const std = @import("std.zig"); const builtin = @import("builtin"); -const AtomicOrder = builtin.AtomicOrder; -const AtomicRmwOp = builtin.AtomicRmwOp; const assert = std.debug.assert; +const time = std.time; +const os = std.os; pub const SpinLock = struct { lock: u8, // TODO use a bool or enum @@ -11,7 +11,7 @@ pub const SpinLock = struct { spinlock: *SpinLock, pub fn release(self: Held) void { - assert(@atomicRmw(u8, &self.spinlock.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1); + @atomicStore(u8, &self.spinlock.lock, 0, .Release); } }; @@ -20,9 +20,46 @@ pub const SpinLock = struct { } pub fn acquire(self: *SpinLock) Held { - while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {} + var backoff = Backoff.init(); + while (@atomicRmw(u8, &self.lock, .Xchg, 1, .Acquire) != 0) + backoff.yield(); return Held{ .spinlock = self }; } + + pub fn yield(iterations: usize) void { + var i = iterations; + while (i != 0) : (i -= 1) { + switch (builtin.arch) { + .i386, .x86_64 => asm volatile ("pause"), + .arm, .aarch64 => asm volatile ("yield"), + else => time.sleep(0), + } + } + } + + /// Provides a method to incrementally yield longer each time its called. + pub const Backoff = struct { + iteration: usize, + + pub fn init() @This() { + return @This(){ .iteration = 0 }; + } + + /// Modified hybrid yielding from + /// http://www.1024cores.net/home/lock-free-algorithms/tricks/spinning + pub fn yield(self: *@This()) void { + defer self.iteration +%= 1; + if (self.iteration < 20) { + SpinLock.yield(self.iteration); + } else if (self.iteration < 24) { + os.sched_yield() catch time.sleep(1); + } else if (self.iteration < 26) { + time.sleep(1 * time.millisecond); + } else { + time.sleep(10 * time.millisecond); + } + } + }; }; test "spinlock" { diff --git a/lib/std/statically_initialized_mutex.zig b/lib/std/statically_initialized_mutex.zig @@ -1,105 +0,0 @@ -const std = @import("std.zig"); -const builtin = @import("builtin"); -const AtomicOrder = builtin.AtomicOrder; -const AtomicRmwOp = builtin.AtomicRmwOp; -const assert = std.debug.assert; -const expect = std.testing.expect; -const windows = std.os.windows; - -/// Lock may be held only once. If the same thread -/// tries to acquire the same mutex twice, it deadlocks. -/// This type is intended to be initialized statically. If you don't -/// require static initialization, use std.Mutex. -/// On Windows, this mutex allocates resources when it is -/// first used, and the resources cannot be freed. -/// On Linux, this is an alias of std.Mutex. -pub const StaticallyInitializedMutex = switch (builtin.os) { - builtin.Os.linux => std.Mutex, - builtin.Os.windows => struct { - lock: windows.CRITICAL_SECTION, - init_once: windows.RTL_RUN_ONCE, - - pub const Held = struct { - mutex: *StaticallyInitializedMutex, - - pub fn release(self: Held) void { - windows.kernel32.LeaveCriticalSection(&self.mutex.lock); - } - }; - - pub fn init() StaticallyInitializedMutex { - return StaticallyInitializedMutex{ - .lock = undefined, - .init_once = windows.INIT_ONCE_STATIC_INIT, - }; - } - - extern fn initCriticalSection( - InitOnce: *windows.RTL_RUN_ONCE, - Parameter: ?*c_void, - Context: ?*c_void, - ) windows.BOOL { - const lock = @ptrCast(*windows.CRITICAL_SECTION, @alignCast(@alignOf(windows.CRITICAL_SECTION), Parameter)); - windows.kernel32.InitializeCriticalSection(lock); - return windows.TRUE; - } - - /// TODO: once https://github.com/ziglang/zig/issues/287 is solved and std.Mutex has a better - /// implementation of a runtime initialized mutex, remove this function. - pub fn deinit(self: *StaticallyInitializedMutex) void { - windows.InitOnceExecuteOnce(&self.init_once, initCriticalSection, &self.lock, null); - windows.kernel32.DeleteCriticalSection(&self.lock); - } - - pub fn acquire(self: *StaticallyInitializedMutex) Held { - windows.InitOnceExecuteOnce(&self.init_once, initCriticalSection, &self.lock, null); - windows.kernel32.EnterCriticalSection(&self.lock); - return Held{ .mutex = self }; - } - }, - else => std.Mutex, -}; - -test "std.StaticallyInitializedMutex" { - const TestContext = struct { - data: i128, - - const TestContext = @This(); - const incr_count = 10000; - - var mutex = StaticallyInitializedMutex.init(); - - fn worker(ctx: *TestContext) void { - var i: usize = 0; - while (i != TestContext.incr_count) : (i += 1) { - const held = mutex.acquire(); - defer held.release(); - - ctx.data += 1; - } - } - }; - - var plenty_of_memory = try std.heap.direct_allocator.alloc(u8, 300 * 1024); - defer std.heap.direct_allocator.free(plenty_of_memory); - - var fixed_buffer_allocator = std.heap.ThreadSafeFixedBufferAllocator.init(plenty_of_memory); - var a = &fixed_buffer_allocator.allocator; - - var context = TestContext{ .data = 0 }; - - if (builtin.single_threaded) { - TestContext.worker(&context); - expect(context.data == TestContext.incr_count); - } else { - const thread_count = 10; - var threads: [thread_count]*std.Thread = undefined; - for (threads) |*t| { - t.* = try std.Thread.spawn(&context, TestContext.worker); - } - for (threads) |t| - t.wait(); - - expect(context.data == thread_count * TestContext.incr_count); - } -} diff --git a/lib/std/std.zig b/lib/std/std.zig @@ -19,11 +19,11 @@ pub const Progress = @import("progress.zig").Progress; pub const SegmentedList = @import("segmented_list.zig").SegmentedList; pub const SinglyLinkedList = @import("linked_list.zig").SinglyLinkedList; pub const SpinLock = @import("spinlock.zig").SpinLock; -pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex; pub const StringHashMap = @import("hash_map.zig").StringHashMap; pub const TailQueue = @import("linked_list.zig").TailQueue; pub const Target = @import("target.zig").Target; pub const Thread = @import("thread.zig").Thread; +pub const ThreadParker = @import("parker.zig").ThreadParker; pub const atomic = @import("atomic.zig"); pub const base64 = @import("base64.zig"); diff --git a/lib/std/target.zig b/lib/std/target.zig @@ -218,6 +218,40 @@ pub const Target = union(enum) { ); } + /// Returned slice must be freed by the caller. + pub fn vcpkgTriplet(allocator: *mem.Allocator, target: Target, linkage: std.build.VcpkgLinkage) ![]const u8 { + const arch = switch (target.getArch()) { + .i386 => "x86", + .x86_64 => "x64", + + .arm, + .armeb, + .thumb, + .thumbeb, + .aarch64_32, + => "arm", + + .aarch64, + .aarch64_be, + => "arm64", + + else => return error.VcpkgNoSuchArchitecture, + }; + + const os = switch (target.getOs()) { + .windows => "windows", + .linux => "linux", + .macosx => "macos", + else => return error.VcpkgNoSuchOs, + }; + + if (linkage == .Static) { + return try mem.join(allocator, "-", [_][]const u8{ arch, os, "static" }); + } else { + return try mem.join(allocator, "-", [_][]const u8{ arch, os }); + } + } + pub fn allocDescription(self: Target, allocator: *mem.Allocator) ![]u8 { // TODO is there anything else worthy of the description that is not // already captured in the triple? @@ -319,7 +353,7 @@ pub const Target = union(enum) { inline for (info.Union.fields) |field| { if (mem.eql(u8, text, field.name)) { if (field.field_type == void) { - return (Arch)(@field(Arch, field.name)); + return @as(Arch, @field(Arch, field.name)); } else { const sub_info = @typeInfo(field.field_type); inline for (sub_info.Enum.fields) |sub_field| { @@ -581,7 +615,7 @@ pub const Target = union(enum) { }; pub fn getExternalExecutor(self: Target) Executor { - if (@TagType(Target)(self) == .Native) return .native; + if (@as(@TagType(Target), self) == .Native) return .native; // If the target OS matches the host OS, we can use QEMU to emulate a foreign architecture. if (self.getOs() == builtin.os) { diff --git a/lib/std/testing.zig b/lib/std/testing.zig @@ -62,7 +62,7 @@ pub fn expectEqual(expected: var, actual: @typeOf(expected)) void { builtin.TypeInfo.Pointer.Size.C, => { if (actual != expected) { - std.debug.panic("expected {}, found {}", expected, actual); + std.debug.panic("expected {*}, found {*}", expected, actual); } }, diff --git a/lib/std/thread.zig b/lib/std/thread.zig @@ -344,7 +344,7 @@ pub const Thread = struct { pub fn cpuCount() CpuCountError!usize { if (builtin.os == .linux) { const cpu_set = try os.sched_getaffinity(0); - return usize(os.CPU_COUNT(cpu_set)); // TODO should not need this usize cast + return @as(usize, os.CPU_COUNT(cpu_set)); // TODO should not need this usize cast } if (builtin.os == .windows) { var system_info: windows.SYSTEM_INFO = undefined; diff --git a/lib/std/time.zig b/lib/std/time.zig @@ -38,7 +38,7 @@ pub fn milliTimestamp() u64 { const hns_per_ms = (ns_per_s / 100) / ms_per_s; const epoch_adj = epoch.windows * ms_per_s; - const ft64 = (u64(ft.dwHighDateTime) << 32) | ft.dwLowDateTime; + const ft64 = (@as(u64, ft.dwHighDateTime) << 32) | ft.dwLowDateTime; return @divFloor(ft64, hns_per_ms) - -epoch_adj; } if (builtin.os == .wasi and !builtin.link_libc) { @@ -142,10 +142,10 @@ pub const Timer = struct { // seccomp is going to block us it will at least do so consistently var ts: os.timespec = undefined; os.clock_getres(monotonic_clock_id, &ts) catch return error.TimerUnsupported; - self.resolution = @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec); + self.resolution = @intCast(u64, ts.tv_sec) * @as(u64, ns_per_s) + @intCast(u64, ts.tv_nsec); os.clock_gettime(monotonic_clock_id, &ts) catch return error.TimerUnsupported; - self.start_time = @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec); + self.start_time = @intCast(u64, ts.tv_sec) * @as(u64, ns_per_s) + @intCast(u64, ts.tv_nsec); } return self; @@ -185,7 +185,7 @@ pub const Timer = struct { } var ts: os.timespec = undefined; os.clock_gettime(monotonic_clock_id, &ts) catch unreachable; - return @intCast(u64, ts.tv_sec) * u64(ns_per_s) + @intCast(u64, ts.tv_nsec); + return @intCast(u64, ts.tv_sec) * @as(u64, ns_per_s) + @intCast(u64, ts.tv_nsec); } }; diff --git a/lib/std/unicode.zig b/lib/std/unicode.zig @@ -7,10 +7,10 @@ const mem = std.mem; /// Returns how many bytes the UTF-8 representation would require /// for the given codepoint. pub fn utf8CodepointSequenceLength(c: u32) !u3 { - if (c < 0x80) return u3(1); - if (c < 0x800) return u3(2); - if (c < 0x10000) return u3(3); - if (c < 0x110000) return u3(4); + if (c < 0x80) return @as(u3, 1); + if (c < 0x800) return @as(u3, 2); + if (c < 0x10000) return @as(u3, 3); + if (c < 0x110000) return @as(u3, 4); return error.CodepointTooLarge; } @@ -18,10 +18,10 @@ pub fn utf8CodepointSequenceLength(c: u32) !u3 { /// returns a number 1-4 indicating the total length of the codepoint in bytes. /// If this byte does not match the form of a UTF-8 start byte, returns Utf8InvalidStartByte. pub fn utf8ByteSequenceLength(first_byte: u8) !u3 { - if (first_byte < 0b10000000) return u3(1); - if (first_byte & 0b11100000 == 0b11000000) return u3(2); - if (first_byte & 0b11110000 == 0b11100000) return u3(3); - if (first_byte & 0b11111000 == 0b11110000) return u3(4); + if (first_byte < 0b10000000) return @as(u3, 1); + if (first_byte & 0b11100000 == 0b11000000) return @as(u3, 2); + if (first_byte & 0b11110000 == 0b11100000) return @as(u3, 3); + if (first_byte & 0b11111000 == 0b11110000) return @as(u3, 4); return error.Utf8InvalidStartByte; } @@ -68,7 +68,7 @@ const Utf8DecodeError = Utf8Decode2Error || Utf8Decode3Error || Utf8Decode4Error /// utf8Decode2,utf8Decode3,utf8Decode4 directly instead of this function. pub fn utf8Decode(bytes: []const u8) Utf8DecodeError!u32 { return switch (bytes.len) { - 1 => u32(bytes[0]), + 1 => @as(u32, bytes[0]), 2 => utf8Decode2(bytes), 3 => utf8Decode3(bytes), 4 => utf8Decode4(bytes), @@ -226,7 +226,7 @@ pub const Utf8Iterator = struct { const slice = it.nextCodepointSlice() orelse return null; switch (slice.len) { - 1 => return u32(slice[0]), + 1 => return @as(u32, slice[0]), 2 => return utf8Decode2(slice) catch unreachable, 3 => return utf8Decode3(slice) catch unreachable, 4 => return utf8Decode4(slice) catch unreachable, @@ -250,15 +250,15 @@ pub const Utf16LeIterator = struct { assert(it.i <= it.bytes.len); if (it.i == it.bytes.len) return null; const c0: u32 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]); - if (c0 & ~u32(0x03ff) == 0xd800) { + if (c0 & ~@as(u32, 0x03ff) == 0xd800) { // surrogate pair it.i += 2; if (it.i >= it.bytes.len) return error.DanglingSurrogateHalf; const c1: u32 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]); - if (c1 & ~u32(0x03ff) != 0xdc00) return error.ExpectedSecondSurrogateHalf; + if (c1 & ~@as(u32, 0x03ff) != 0xdc00) return error.ExpectedSecondSurrogateHalf; it.i += 2; return 0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff)); - } else if (c0 & ~u32(0x03ff) == 0xdc00) { + } else if (c0 & ~@as(u32, 0x03ff) == 0xdc00) { return error.UnexpectedSecondSurrogateHalf; } else { it.i += 2; diff --git a/lib/std/unicode/throughput_test.zig b/lib/std/unicode/throughput_test.zig @@ -2,9 +2,7 @@ const builtin = @import("builtin"); const std = @import("std"); pub fn main() !void { - var stdout_file = try std.io.getStdOut(); - var stdout_out_stream = stdout_file.outStream(); - const stdout = &stdout_out_stream.stream; + const stdout = &std.io.getStdOut().outStream().stream; const args = try std.process.argsAlloc(std.heap.direct_allocator); diff --git a/lib/std/valgrind.zig b/lib/std/valgrind.zig @@ -1,5 +1,6 @@ const builtin = @import("builtin"); -const math = @import("index.zig").math; +const std = @import("std.zig"); +const math = std.math; pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3: usize, a4: usize, a5: usize) usize { if (!builtin.valgrind_support) { @@ -13,7 +14,7 @@ pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3: \\ roll $29, %%edi ; roll $19, %%edi \\ xchgl %%ebx,%%ebx : [_] "={edx}" (-> usize) - : [_] "{eax}" (&[]usize{ request, a1, a2, a3, a4, a5 }), + : [_] "{eax}" (&[_]usize{ request, a1, a2, a3, a4, a5 }), [_] "0" (default) : "cc", "memory" ); @@ -24,7 +25,7 @@ pub fn doClientRequest(default: usize, request: usize, a1: usize, a2: usize, a3: \\ rolq $61, %%rdi ; rolq $51, %%rdi \\ xchgq %%rbx,%%rbx : [_] "={rdx}" (-> usize) - : [_] "{rax}" (&[]usize{ request, a1, a2, a3, a4, a5 }), + : [_] "{rax}" (&[_]usize{ request, a1, a2, a3, a4, a5 }), [_] "0" (default) : "cc", "memory" ); @@ -76,7 +77,7 @@ pub const ClientRequest = extern enum { InnerThreads = 6402, }; pub fn ToolBase(base: [2]u8) u32 { - return (u32(base[0] & 0xff) << 24) | (u32(base[1] & 0xff) << 16); + return (@as(u32, base[0] & 0xff) << 24) | (@as(u32, base[1] & 0xff) << 16); } pub fn IsTool(base: [2]u8, code: usize) bool { return ToolBase(base) == (code & 0xffff0000); @@ -95,48 +96,52 @@ fn doClientRequestStmt(request: ClientRequest, a1: usize, a2: usize, a3: usize, /// running under Valgrind which is running under another Valgrind, /// etc. pub fn runningOnValgrind() usize { - return doClientRequestExpr(0, ClientRequest.RunningOnValgrind, 0, 0, 0, 0, 0); + return doClientRequestExpr(0, .RunningOnValgrind, 0, 0, 0, 0, 0); +} + +test "works whether running on valgrind or not" { + _ = runningOnValgrind(); } /// Discard translation of code in the slice qzz. Useful if you are debugging /// a JITter or some such, since it provides a way to make sure valgrind will /// retranslate the invalidated area. Returns no value. pub fn discardTranslations(qzz: []const u8) void { - doClientRequestStmt(ClientRequest.DiscardTranslations, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0); + doClientRequestStmt(.DiscardTranslations, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0); } pub fn innerThreads(qzz: [*]u8) void { - doClientRequestStmt(ClientRequest.InnerThreads, qzz, 0, 0, 0, 0); + doClientRequestStmt(.InnerThreads, qzz, 0, 0, 0, 0); } //pub fn printf(format: [*]const u8, args: ...) usize { // return doClientRequestExpr(0, -// ClientRequest.PrintfValistByRef, +// .PrintfValistByRef, // @ptrToInt(format), @ptrToInt(args), // 0, 0, 0); //} //pub fn printfBacktrace(format: [*]const u8, args: ...) usize { // return doClientRequestExpr(0, -// ClientRequest.PrintfBacktraceValistByRef, +// .PrintfBacktraceValistByRef, // @ptrToInt(format), @ptrToInt(args), // 0, 0, 0); //} pub fn nonSIMDCall0(func: fn (usize) usize) usize { - return doClientRequestExpr(0, ClientRequest.ClientCall0, @ptrToInt(func), 0, 0, 0, 0); + return doClientRequestExpr(0, .ClientCall0, @ptrToInt(func), 0, 0, 0, 0); } pub fn nonSIMDCall1(func: fn (usize, usize) usize, a1: usize) usize { - return doClientRequestExpr(0, ClientRequest.ClientCall1, @ptrToInt(func), a1, 0, 0, 0); + return doClientRequestExpr(0, .ClientCall1, @ptrToInt(func), a1, 0, 0, 0); } pub fn nonSIMDCall2(func: fn (usize, usize, usize) usize, a1: usize, a2: usize) usize { - return doClientRequestExpr(0, ClientRequest.ClientCall2, @ptrToInt(func), a1, a2, 0, 0); + return doClientRequestExpr(0, .ClientCall2, @ptrToInt(func), a1, a2, 0, 0); } pub fn nonSIMDCall3(func: fn (usize, usize, usize, usize) usize, a1: usize, a2: usize, a3: usize) usize { - return doClientRequestExpr(0, ClientRequest.ClientCall3, @ptrToInt(func), a1, a2, a3, 0); + return doClientRequestExpr(0, .ClientCall3, @ptrToInt(func), a1, a2, a3, 0); } /// Counts the number of errors that have been recorded by a tool. Nb: @@ -144,19 +149,19 @@ pub fn nonSIMDCall3(func: fn (usize, usize, usize, usize) usize, a1: usize, a2: /// VG_(unique_error)() for them to be counted. pub fn countErrors() usize { return doClientRequestExpr(0, // default return - ClientRequest.CountErrors, 0, 0, 0, 0, 0); + .CountErrors, 0, 0, 0, 0, 0); } pub fn mallocLikeBlock(mem: []u8, rzB: usize, is_zeroed: bool) void { - doClientRequestStmt(ClientRequest.MalloclikeBlock, @ptrToInt(mem.ptr), mem.len, rzB, @boolToInt(is_zeroed), 0); + doClientRequestStmt(.MalloclikeBlock, @ptrToInt(mem.ptr), mem.len, rzB, @boolToInt(is_zeroed), 0); } pub fn resizeInPlaceBlock(oldmem: []u8, newsize: usize, rzB: usize) void { - doClientRequestStmt(ClientRequest.ResizeinplaceBlock, @ptrToInt(oldmem.ptr), oldmem.len, newsize, rzB, 0); + doClientRequestStmt(.ResizeinplaceBlock, @ptrToInt(oldmem.ptr), oldmem.len, newsize, rzB, 0); } pub fn freeLikeBlock(addr: [*]u8, rzB: usize) void { - doClientRequestStmt(ClientRequest.FreelikeBlock, @ptrToInt(addr), rzB, 0, 0, 0); + doClientRequestStmt(.FreelikeBlock, @ptrToInt(addr), rzB, 0, 0, 0); } /// Create a memory pool. @@ -165,66 +170,66 @@ pub const MempoolFlags = extern enum { MetaPool = 2, }; pub fn createMempool(pool: [*]u8, rzB: usize, is_zeroed: bool, flags: usize) void { - doClientRequestStmt(ClientRequest.CreateMempool, @ptrToInt(pool), rzB, @boolToInt(is_zeroed), flags, 0); + doClientRequestStmt(.CreateMempool, @ptrToInt(pool), rzB, @boolToInt(is_zeroed), flags, 0); } /// Destroy a memory pool. pub fn destroyMempool(pool: [*]u8) void { - doClientRequestStmt(ClientRequest.DestroyMempool, pool, 0, 0, 0, 0); + doClientRequestStmt(.DestroyMempool, pool, 0, 0, 0, 0); } /// Associate a piece of memory with a memory pool. pub fn mempoolAlloc(pool: [*]u8, mem: []u8) void { - doClientRequestStmt(ClientRequest.MempoolAlloc, @ptrToInt(pool), @ptrToInt(mem.ptr), mem.len, 0, 0); + doClientRequestStmt(.MempoolAlloc, @ptrToInt(pool), @ptrToInt(mem.ptr), mem.len, 0, 0); } /// Disassociate a piece of memory from a memory pool. pub fn mempoolFree(pool: [*]u8, addr: [*]u8) void { - doClientRequestStmt(ClientRequest.MempoolFree, @ptrToInt(pool), @ptrToInt(addr), 0, 0, 0); + doClientRequestStmt(.MempoolFree, @ptrToInt(pool), @ptrToInt(addr), 0, 0, 0); } /// Disassociate any pieces outside a particular range. pub fn mempoolTrim(pool: [*]u8, mem: []u8) void { - doClientRequestStmt(ClientRequest.MempoolTrim, @ptrToInt(pool), @ptrToInt(mem.ptr), mem.len, 0, 0); + doClientRequestStmt(.MempoolTrim, @ptrToInt(pool), @ptrToInt(mem.ptr), mem.len, 0, 0); } /// Resize and/or move a piece associated with a memory pool. pub fn moveMempool(poolA: [*]u8, poolB: [*]u8) void { - doClientRequestStmt(ClientRequest.MoveMempool, @ptrToInt(poolA), @ptrToInt(poolB), 0, 0, 0); + doClientRequestStmt(.MoveMempool, @ptrToInt(poolA), @ptrToInt(poolB), 0, 0, 0); } /// Resize and/or move a piece associated with a memory pool. pub fn mempoolChange(pool: [*]u8, addrA: [*]u8, mem: []u8) void { - doClientRequestStmt(ClientRequest.MempoolChange, @ptrToInt(pool), @ptrToInt(addrA), @ptrToInt(mem.ptr), mem.len, 0); + doClientRequestStmt(.MempoolChange, @ptrToInt(pool), @ptrToInt(addrA), @ptrToInt(mem.ptr), mem.len, 0); } /// Return if a mempool exists. pub fn mempoolExists(pool: [*]u8) bool { - return doClientRequestExpr(0, ClientRequest.MempoolExists, @ptrToInt(pool), 0, 0, 0, 0) != 0; + return doClientRequestExpr(0, .MempoolExists, @ptrToInt(pool), 0, 0, 0, 0) != 0; } /// Mark a piece of memory as being a stack. Returns a stack id. /// start is the lowest addressable stack byte, end is the highest /// addressable stack byte. pub fn stackRegister(stack: []u8) usize { - return doClientRequestExpr(0, ClientRequest.StackRegister, @ptrToInt(stack.ptr), @ptrToInt(stack.ptr) + stack.len, 0, 0, 0); + return doClientRequestExpr(0, .StackRegister, @ptrToInt(stack.ptr), @ptrToInt(stack.ptr) + stack.len, 0, 0, 0); } /// Unmark the piece of memory associated with a stack id as being a stack. pub fn stackDeregister(id: usize) void { - doClientRequestStmt(ClientRequest.StackDeregister, id, 0, 0, 0, 0); + doClientRequestStmt(.StackDeregister, id, 0, 0, 0, 0); } /// Change the start and end address of the stack id. /// start is the new lowest addressable stack byte, end is the new highest /// addressable stack byte. pub fn stackChange(id: usize, newstack: []u8) void { - doClientRequestStmt(ClientRequest.StackChange, id, @ptrToInt(newstack.ptr), @ptrToInt(newstack.ptr) + newstack.len, 0, 0); + doClientRequestStmt(.StackChange, id, @ptrToInt(newstack.ptr), @ptrToInt(newstack.ptr) + newstack.len, 0, 0); } // Load PDB debug info for Wine PE image_map. // pub fn loadPdbDebuginfo(fd, ptr, total_size, delta) void { -// doClientRequestStmt(ClientRequest.LoadPdbDebuginfo, +// doClientRequestStmt(.LoadPdbDebuginfo, // fd, ptr, total_size, delta, // 0); // } @@ -234,7 +239,7 @@ pub fn stackChange(id: usize, newstack: []u8) void { /// result will be dumped in there and is guaranteed to be zero /// terminated. If no info is found, the first byte is set to zero. pub fn mapIpToSrcloc(addr: *const u8, buf64: [64]u8) usize { - return doClientRequestExpr(0, ClientRequest.MapIpToSrcloc, @ptrToInt(addr), @ptrToInt(&buf64[0]), 0, 0, 0); + return doClientRequestExpr(0, .MapIpToSrcloc, @ptrToInt(addr), @ptrToInt(&buf64[0]), 0, 0, 0); } /// Disable error reporting for this thread. Behaves in a stack like @@ -246,12 +251,12 @@ pub fn mapIpToSrcloc(addr: *const u8, buf64: [64]u8) usize { /// reporting. Child threads do not inherit this setting from their /// parents -- they are always created with reporting enabled. pub fn disableErrorReporting() void { - doClientRequestStmt(ClientRequest.ChangeErrDisablement, 1, 0, 0, 0, 0); + doClientRequestStmt(.ChangeErrDisablement, 1, 0, 0, 0, 0); } /// Re-enable error reporting, (see disableErrorReporting()) pub fn enableErrorReporting() void { - doClientRequestStmt(ClientRequest.ChangeErrDisablement, math.maxInt(usize), 0, 0, 0, 0); + doClientRequestStmt(.ChangeErrDisablement, math.maxInt(usize), 0, 0, 0, 0); } /// Execute a monitor command from the client program. @@ -260,8 +265,13 @@ pub fn enableErrorReporting() void { /// If no connection is opened, output will go to the log output. /// Returns 1 if command not recognised, 0 otherwise. pub fn monitorCommand(command: [*]u8) bool { - return doClientRequestExpr(0, ClientRequest.GdbMonitorCommand, @ptrToInt(command.ptr), 0, 0, 0, 0) != 0; + return doClientRequestExpr(0, .GdbMonitorCommand, @ptrToInt(command.ptr), 0, 0, 0, 0) != 0; } -pub const memcheck = @import("memcheck.zig"); -pub const callgrind = @import("callgrind.zig"); +pub const memcheck = @import("valgrind/memcheck.zig"); +pub const callgrind = @import("valgrind/callgrind.zig"); + +test "" { + _ = @import("valgrind/memcheck.zig"); + _ = @import("valgrind/callgrind.zig"); +} diff --git a/lib/std/valgrind/callgrind.zig b/lib/std/valgrind/callgrind.zig @@ -1,4 +1,4 @@ -const std = @import("../index.zig"); +const std = @import("../std.zig"); const valgrind = std.valgrind; pub const CallgrindClientRequest = extern enum { @@ -20,7 +20,7 @@ fn doCallgrindClientRequestStmt(request: CallgrindClientRequest, a1: usize, a2: /// Dump current state of cost centers, and zero them afterwards pub fn dumpStats() void { - doCallgrindClientRequestStmt(CallgrindClientRequest.DumpStats, 0, 0, 0, 0, 0); + doCallgrindClientRequestStmt(.DumpStats, 0, 0, 0, 0, 0); } /// Dump current state of cost centers, and zero them afterwards. @@ -28,12 +28,12 @@ pub fn dumpStats() void { /// the dump. This string is written as a description field into the /// profile data dump. pub fn dumpStatsAt(pos_str: [*]u8) void { - doCallgrindClientRequestStmt(CallgrindClientRequest.DumpStatsAt, @ptrToInt(pos_str), 0, 0, 0, 0); + doCallgrindClientRequestStmt(.DumpStatsAt, @ptrToInt(pos_str), 0, 0, 0, 0); } /// Zero cost centers pub fn zeroStats() void { - doCallgrindClientRequestStmt(CallgrindClientRequest.ZeroStats, 0, 0, 0, 0, 0); + doCallgrindClientRequestStmt(.ZeroStats, 0, 0, 0, 0, 0); } /// Toggles collection state. @@ -41,7 +41,7 @@ pub fn zeroStats() void { /// should be noted or if they are to be ignored. Events are noted /// by increment of counters in a cost center pub fn toggleCollect() void { - doCallgrindClientRequestStmt(CallgrindClientRequest.ToggleCollect, 0, 0, 0, 0, 0); + doCallgrindClientRequestStmt(.ToggleCollect, 0, 0, 0, 0, 0); } /// Start full callgrind instrumentation if not already switched on. @@ -49,7 +49,7 @@ pub fn toggleCollect() void { /// this will lead to an artificial cache warmup phase afterwards with /// cache misses which would not have happened in reality. pub fn startInstrumentation() void { - doCallgrindClientRequestStmt(CallgrindClientRequest.StartInstrumentation, 0, 0, 0, 0, 0); + doCallgrindClientRequestStmt(.StartInstrumentation, 0, 0, 0, 0, 0); } /// Stop full callgrind instrumentation if not already switched off. @@ -60,5 +60,5 @@ pub fn startInstrumentation() void { /// To start Callgrind in this mode to ignore the setup phase, use /// the option "--instr-atstart=no". pub fn stopInstrumentation() void { - doCallgrindClientRequestStmt(CallgrindClientRequest.StopInstrumentation, 0, 0, 0, 0, 0); + doCallgrindClientRequestStmt(.StopInstrumentation, 0, 0, 0, 0, 0); } diff --git a/lib/std/valgrind/memcheck.zig b/lib/std/valgrind/memcheck.zig @@ -1,4 +1,5 @@ -const std = @import("../index.zig"); +const std = @import("../std.zig"); +const testing = std.testing; const valgrind = std.valgrind; pub const MemCheckClientRequest = extern enum { @@ -31,7 +32,7 @@ fn doMemCheckClientRequestStmt(request: MemCheckClientRequest, a1: usize, a2: us /// This returns -1 when run on Valgrind and 0 otherwise. pub fn makeMemNoAccess(qzz: []u8) i1 { return @intCast(i1, doMemCheckClientRequestExpr(0, // default return - MemCheckClientRequest.MakeMemNoAccess, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0)); + .MakeMemNoAccess, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0)); } /// Similarly, mark memory at qzz.ptr as addressable but undefined @@ -39,7 +40,7 @@ pub fn makeMemNoAccess(qzz: []u8) i1 { /// This returns -1 when run on Valgrind and 0 otherwise. pub fn makeMemUndefined(qzz: []u8) i1 { return @intCast(i1, doMemCheckClientRequestExpr(0, // default return - MemCheckClientRequest.MakeMemUndefined, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0)); + .MakeMemUndefined, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0)); } /// Similarly, mark memory at qzz.ptr as addressable and defined @@ -47,7 +48,7 @@ pub fn makeMemUndefined(qzz: []u8) i1 { pub fn makeMemDefined(qzz: []u8) i1 { // This returns -1 when run on Valgrind and 0 otherwise. return @intCast(i1, doMemCheckClientRequestExpr(0, // default return - MemCheckClientRequest.MakeMemDefined, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0)); + .MakeMemDefined, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0)); } /// Similar to makeMemDefined except that addressability is @@ -56,7 +57,7 @@ pub fn makeMemDefined(qzz: []u8) i1 { /// This returns -1 when run on Valgrind and 0 otherwise. pub fn makeMemDefinedIfAddressable(qzz: []u8) i1 { return @intCast(i1, doMemCheckClientRequestExpr(0, // default return - MemCheckClientRequest.MakeMemDefinedIfAddressable, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0)); + .MakeMemDefinedIfAddressable, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0)); } /// Create a block-description handle. The description is an ascii @@ -65,14 +66,14 @@ pub fn makeMemDefinedIfAddressable(qzz: []u8) i1 { /// properties of the memory range. pub fn createBlock(qzz: []u8, desc: [*]u8) usize { return doMemCheckClientRequestExpr(0, // default return - MemCheckClientRequest.CreateBlock, @ptrToInt(qzz.ptr), qzz.len, @ptrToInt(desc), 0, 0); + .CreateBlock, @ptrToInt(qzz.ptr), qzz.len, @ptrToInt(desc), 0, 0); } /// Discard a block-description-handle. Returns 1 for an /// invalid handle, 0 for a valid handle. pub fn discard(blkindex) bool { return doMemCheckClientRequestExpr(0, // default return - MemCheckClientRequest.Discard, 0, blkindex, 0, 0, 0) != 0; + .Discard, 0, blkindex, 0, 0, 0) != 0; } /// Check that memory at qzz.ptr is addressable for qzz.len bytes. @@ -80,7 +81,7 @@ pub fn discard(blkindex) bool { /// error message and returns the address of the first offending byte. /// Otherwise it returns zero. pub fn checkMemIsAddressable(qzz: []u8) usize { - return doMemCheckClientRequestExpr(0, MemCheckClientRequest.CheckMemIsAddressable, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0); + return doMemCheckClientRequestExpr(0, .CheckMemIsAddressable, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0); } /// Check that memory at qzz.ptr is addressable and defined for @@ -88,31 +89,31 @@ pub fn checkMemIsAddressable(qzz: []u8) usize { /// established, Valgrind prints an error message and returns the /// address of the first offending byte. Otherwise it returns zero. pub fn checkMemIsDefined(qzz: []u8) usize { - return doMemCheckClientRequestExpr(0, MemCheckClientRequest.CheckMemIsDefined, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0); + return doMemCheckClientRequestExpr(0, .CheckMemIsDefined, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0); } /// Do a full memory leak check (like --leak-check=full) mid-execution. pub fn doLeakCheck() void { - doMemCheckClientRequestStmt(MemCheckClientRequest.DO_LEAK_CHECK, 0, 0, 0, 0, 0); + doMemCheckClientRequestStmt(.DO_LEAK_CHECK, 0, 0, 0, 0, 0); } /// Same as doLeakCheck() but only showing the entries for /// which there was an increase in leaked bytes or leaked nr of blocks /// since the previous leak search. pub fn doAddedLeakCheck() void { - doMemCheckClientRequestStmt(MemCheckClientRequest.DO_LEAK_CHECK, 0, 1, 0, 0, 0); + doMemCheckClientRequestStmt(.DO_LEAK_CHECK, 0, 1, 0, 0, 0); } /// Same as doAddedLeakCheck() but showing entries with /// increased or decreased leaked bytes/blocks since previous leak /// search. pub fn doChangedLeakCheck() void { - doMemCheckClientRequestStmt(MemCheckClientRequest.DO_LEAK_CHECK, 0, 2, 0, 0, 0); + doMemCheckClientRequestStmt(.DO_LEAK_CHECK, 0, 2, 0, 0, 0); } /// Do a summary memory leak check (like --leak-check=summary) mid-execution. pub fn doQuickLeakCheck() void { - doMemCheckClientRequestStmt(MemCheckClientRequest.DO_LEAK_CHECK, 1, 0, 0, 0, 0); + doMemCheckClientRequestStmt(.DO_LEAK_CHECK, 1, 0, 0, 0, 0); } /// Return number of leaked, dubious, reachable and suppressed bytes found by @@ -125,27 +126,65 @@ const CountResult = struct { }; pub fn countLeaks() CountResult { - var res = CountResult{ + var res: CountResult = .{ .leaked = 0, .dubious = 0, .reachable = 0, .suppressed = 0, }; - doMemCheckClientRequestStmt(MemCheckClientRequest.CountLeaks, &res.leaked, &res.dubious, &res.reachable, &res.suppressed, 0); + doMemCheckClientRequestStmt( + .CountLeaks, + @ptrToInt(&res.leaked), + @ptrToInt(&res.dubious), + @ptrToInt(&res.reachable), + @ptrToInt(&res.suppressed), + 0, + ); return res; } +test "countLeaks" { + testing.expectEqual( + @as(CountResult, .{ + .leaked = 0, + .dubious = 0, + .reachable = 0, + .suppressed = 0, + }), + countLeaks(), + ); +} + pub fn countLeakBlocks() CountResult { - var res = CountResult{ + var res: CountResult = .{ .leaked = 0, .dubious = 0, .reachable = 0, .suppressed = 0, }; - doMemCheckClientRequestStmt(MemCheckClientRequest.CountLeakBlocks, &res.leaked, &res.dubious, &res.reachable, &res.suppressed, 0); + doMemCheckClientRequestStmt( + .CountLeakBlocks, + @ptrToInt(&res.leaked), + @ptrToInt(&res.dubious), + @ptrToInt(&res.reachable), + @ptrToInt(&res.suppressed), + 0, + ); return res; } +test "countLeakBlocks" { + testing.expectEqual( + @as(CountResult, .{ + .leaked = 0, + .dubious = 0, + .reachable = 0, + .suppressed = 0, + }), + countLeakBlocks(), + ); +} + /// Get the validity data for addresses zza and copy it /// into the provided zzvbits array. Return values: /// 0 if not running on valgrind @@ -156,7 +195,7 @@ pub fn countLeakBlocks() CountResult { /// impossible to segfault your system by using this call. pub fn getVbits(zza: []u8, zzvbits: []u8) u2 { std.debug.assert(zzvbits.len >= zza.len / 8); - return @intCast(u2, doMemCheckClientRequestExpr(0, MemCheckClientRequest.GetVbits, @ptrToInt(zza.ptr), @ptrToInt(zzvbits), zza.len, 0, 0)); + return @intCast(u2, doMemCheckClientRequestExpr(0, .GetVbits, @ptrToInt(zza.ptr), @ptrToInt(zzvbits), zza.len, 0, 0)); } /// Set the validity data for addresses zza, copying it @@ -169,17 +208,17 @@ pub fn getVbits(zza: []u8, zzvbits: []u8) u2 { /// impossible to segfault your system by using this call. pub fn setVbits(zzvbits: []u8, zza: []u8) u2 { std.debug.assert(zzvbits.len >= zza.len / 8); - return @intCast(u2, doMemCheckClientRequestExpr(0, MemCheckClientRequest.SetVbits, @ptrToInt(zza.ptr), @ptrToInt(zzvbits), zza.len, 0, 0)); + return @intCast(u2, doMemCheckClientRequestExpr(0, .SetVbits, @ptrToInt(zza.ptr), @ptrToInt(zzvbits), zza.len, 0, 0)); } /// Disable and re-enable reporting of addressing errors in the /// specified address range. pub fn disableAddrErrorReportingInRange(qzz: []u8) usize { return doMemCheckClientRequestExpr(0, // default return - MemCheckClientRequest.DisableAddrErrorReportingInRange, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0); + .DisableAddrErrorReportingInRange, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0); } pub fn enableAddrErrorReportingInRange(qzz: []u8) usize { return doMemCheckClientRequestExpr(0, // default return - MemCheckClientRequest.EnableAddrErrorReportingInRange, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0); + .EnableAddrErrorReportingInRange, @ptrToInt(qzz.ptr), qzz.len, 0, 0, 0); } diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig @@ -576,7 +576,6 @@ pub const Node = struct { pub const Root = struct { base: Node, - doc_comments: ?*DocComment, decls: DeclList, eof_token: TokenIndex, @@ -1648,10 +1647,15 @@ pub const Node = struct { pub const SuffixOp = struct { base: Node, - lhs: *Node, + lhs: Lhs, op: Op, rtoken: TokenIndex, + pub const Lhs = union(enum) { + node: *Node, + dot: TokenIndex, + }; + pub const Op = union(enum) { Call: Call, ArrayAccess: *Node, @@ -1679,8 +1683,13 @@ pub const Node = struct { pub fn iterate(self: *SuffixOp, index: usize) ?*Node { var i = index; - if (i < 1) return self.lhs; - i -= 1; + switch (self.lhs) { + .node => |node| { + if (i == 0) return node; + i -= 1; + }, + .dot => {}, + } switch (self.op) { .Call => |*call_info| { @@ -1721,7 +1730,10 @@ pub const Node = struct { .Call => |*call_info| if (call_info.async_token) |async_token| return async_token, else => {}, } - return self.lhs.firstToken(); + switch (self.lhs) { + .node => |node| return node.firstToken(), + .dot => |dot| return dot, + } } pub fn lastToken(self: *const SuffixOp) TokenIndex { @@ -2241,7 +2253,6 @@ pub const Node = struct { test "iterate" { var root = Node.Root{ .base = Node{ .id = Node.Id.Root }, - .doc_comments = null, .decls = Node.Root.DeclList.init(std.debug.global_allocator), .eof_token = 0, }; diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig @@ -58,13 +58,6 @@ fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error node.* = Node.Root{ .base = Node{ .id = .Root }, .decls = undefined, - // TODO: Because zig fmt collapses consecutive comments separated by blank lines into - // a single multi-line comment, it is currently impossible to have a container-level - // doc comment and NO doc comment on the first decl. For now, simply - // ignore the problem and assume that there will be no container-level - // doc comments. - // See: https://github.com/ziglang/zig/issues/2288 - .doc_comments = null, .eof_token = undefined, }; node.decls = parseContainerMembers(arena, it, tree) catch |err| { @@ -94,6 +87,11 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !No var list = Node.Root.DeclList.init(arena); while (true) { + if (try parseContainerDocComments(arena, it, tree)) |node| { + try list.push(node); + continue; + } + const doc_comments = try parseDocComment(arena, it, tree); if (try parseTestDecl(arena, it, tree)) |node| { @@ -155,12 +153,35 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !No continue; } + // Dangling doc comment + if (doc_comments != null) { + try tree.errors.push(AstError{ + .UnattachedDocComment = AstError.UnattachedDocComment{ .token = doc_comments.?.firstToken() }, + }); + } break; } return list; } +/// Eat a multiline container doc comment +fn parseContainerDocComments(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { + var lines = Node.DocComment.LineList.init(arena); + while (eatToken(it, .ContainerDocComment)) |line| { + try lines.push(line); + } + + if (lines.len == 0) return null; + + const node = try arena.create(Node.DocComment); + node.* = Node.DocComment{ + .base = Node{ .id = .DocComment }, + .lines = lines, + }; + return &node.base; +} + /// TestDecl <- KEYWORD_test STRINGLITERAL Block fn parseTestDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { const test_token = eatToken(it, .Keyword_test) orelse return null; @@ -1026,16 +1047,16 @@ fn parseWhileExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { /// CurlySuffixExpr <- TypeExpr InitList? fn parseCurlySuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { const type_expr = (try parseTypeExpr(arena, it, tree)) orelse return null; - const init_list = (try parseInitList(arena, it, tree)) orelse return type_expr; - init_list.cast(Node.SuffixOp).?.lhs = type_expr; - return init_list; + const suffix_op = (try parseInitList(arena, it, tree)) orelse return type_expr; + suffix_op.lhs.node = type_expr; + return &suffix_op.base; } /// InitList /// <- LBRACE FieldInit (COMMA FieldInit)* COMMA? RBRACE /// / LBRACE Expr (COMMA Expr)* COMMA? RBRACE /// / LBRACE RBRACE -fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { +fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.SuffixOp { const lbrace = eatToken(it, .LBrace) orelse return null; var init_list = Node.SuffixOp.Op.InitList.init(arena); @@ -1064,11 +1085,11 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { const node = try arena.create(Node.SuffixOp); node.* = Node.SuffixOp{ .base = Node{ .id = .SuffixOp }, - .lhs = undefined, // set by caller + .lhs = .{.node = undefined}, // set by caller .op = op, .rtoken = try expectToken(it, tree, .RBrace), }; - return &node.base; + return node; } /// TypeExpr <- PrefixTypeOp* ErrorUnionExpr @@ -1117,7 +1138,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { while (try parseSuffixOp(arena, it, tree)) |node| { switch (node.id) { - .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res, + .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res}, .InfixOp => node.cast(Node.InfixOp).?.lhs = res, else => unreachable, } @@ -1133,7 +1154,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { const node = try arena.create(Node.SuffixOp); node.* = Node.SuffixOp{ .base = Node{ .id = .SuffixOp }, - .lhs = res, + .lhs = .{.node = res}, .op = Node.SuffixOp.Op{ .Call = Node.SuffixOp.Op.Call{ .params = params.list, @@ -1150,7 +1171,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { while (true) { if (try parseSuffixOp(arena, it, tree)) |node| { switch (node.id) { - .SuffixOp => node.cast(Node.SuffixOp).?.lhs = res, + .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res}, .InfixOp => node.cast(Node.InfixOp).?.lhs = res, else => unreachable, } @@ -1161,7 +1182,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { const call = try arena.create(Node.SuffixOp); call.* = Node.SuffixOp{ .base = Node{ .id = .SuffixOp }, - .lhs = res, + .lhs = .{.node = res}, .op = Node.SuffixOp.Op{ .Call = Node.SuffixOp.Op.Call{ .params = params.list, @@ -1215,7 +1236,7 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N return &node.base; } if (try parseContainerDecl(arena, it, tree)) |node| return node; - if (try parseEnumLiteral(arena, it, tree)) |node| return node; + if (try parseAnonLiteral(arena, it, tree)) |node| return node; if (try parseErrorSetDecl(arena, it, tree)) |node| return node; if (try parseFloatLiteral(arena, it, tree)) |node| return node; if (try parseFnProto(arena, it, tree)) |node| return node; @@ -1494,16 +1515,28 @@ fn parseAsmExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { } /// DOT IDENTIFIER -fn parseEnumLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { +fn parseAnonLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { const dot = eatToken(it, .Period) orelse return null; - const name = try expectToken(it, tree, .Identifier); - const node = try arena.create(Node.EnumLiteral); - node.* = Node.EnumLiteral{ - .base = Node{ .id = .EnumLiteral }, - .dot = dot, - .name = name, - }; - return &node.base; + + // anon enum literal + if (eatToken(it, .Identifier)) |name| { + const node = try arena.create(Node.EnumLiteral); + node.* = Node.EnumLiteral{ + .base = Node{ .id = .EnumLiteral }, + .dot = dot, + .name = name, + }; + return &node.base; + } + + // anon container literal + if (try parseInitList(arena, it, tree)) |node| { + node.lhs = .{.dot = dot}; + return &node.base; + } + + putBackToken(it, dot); + return null; } /// AsmOutput <- COLON AsmOutputList AsmInput? @@ -1618,7 +1651,11 @@ fn parseBlockLabel(arena: *Allocator, it: *TokenIterator, tree: *Tree) ?TokenInd /// FieldInit <- DOT IDENTIFIER EQUAL Expr fn parseFieldInit(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { const period_token = eatToken(it, .Period) orelse return null; - const name_token = try expectToken(it, tree, .Identifier); + const name_token = eatToken(it, .Identifier) orelse { + // Because of anon literals `.{` is also valid. + putBackToken(it, period_token); + return null; + }; const eq_token = eatToken(it, .Equal) orelse { // `.Name` may also be an enum literal, which is a later rule. putBackToken(it, name_token); diff --git a/lib/std/zig/parse_string_literal.zig b/lib/std/zig/parse_string_literal.zig @@ -19,7 +19,7 @@ pub fn parseStringLiteral( bytes: []const u8, bad_index: *usize, // populated if error.InvalidCharacter is returned ) ParseStringLiteralError![]u8 { - const first_index = if (bytes[0] == 'c') usize(2) else usize(1); + const first_index = if (bytes[0] == 'c') @as(usize, 2) else @as(usize, 1); assert(bytes[bytes.len - 1] == '"'); var list = std.ArrayList(u8).init(allocator); diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig @@ -1,9 +1,26 @@ -// TODO remove `use` keyword eventually: https://github.com/ziglang/zig/issues/2591 -test "zig fmt: change use to usingnamespace" { - try testTransform( - \\use @import("std"); - , - \\usingnamespace @import("std"); +test "zig fmt: anon literal in array" { + try testCanonical( + \\var arr: [2]Foo = .{ + \\ .{ .a = 2 }, + \\ .{ .b = 3 }, + \\}; + \\ + ); +} + +test "zig fmt: anon struct literal syntax" { + try testCanonical( + \\const x = .{ + \\ .a = b, + \\ .c = d, + \\}; + \\ + ); +} + +test "zig fmt: anon list literal syntax" { + try testCanonical( + \\const x = .{ a, b, c }; \\ ); } @@ -37,7 +54,7 @@ test "zig fmt: while else err prong with no block" { \\test "" { \\ const result = while (returnError()) |value| { \\ break value; - \\ } else |err| i32(2); + \\ } else |err| @as(i32, 2); \\ expect(result == 2); \\} \\ @@ -1444,11 +1461,11 @@ test "zig fmt: preserve spacing" { \\const std = @import("std"); \\ \\pub fn main() !void { - \\ var stdout_file = try std.io.getStdOut; - \\ var stdout_file = try std.io.getStdOut; + \\ var stdout_file = std.io.getStdOut; + \\ var stdout_file = std.io.getStdOut; \\ - \\ var stdout_file = try std.io.getStdOut; - \\ var stdout_file = try std.io.getStdOut; + \\ var stdout_file = std.io.getStdOut; + \\ var stdout_file = std.io.getStdOut; \\} \\ ); @@ -2549,6 +2566,62 @@ test "zig fmt: comments at several places in struct init" { ); } +test "zig fmt: top level doc comments" { + try testCanonical( + \\//! tld 1 + \\//! tld 2 + \\//! tld 3 + \\ + \\// comment + \\ + \\/// A doc + \\const A = struct { + \\ //! A tld 1 + \\ //! A tld 2 + \\ //! A tld 3 + \\}; + \\ + \\/// B doc + \\const B = struct { + \\ //! B tld 1 + \\ //! B tld 2 + \\ //! B tld 3 + \\ + \\ /// b doc + \\ b: u32, + \\}; + \\ + \\/// C doc + \\const C = struct { + \\ //! C tld 1 + \\ //! C tld 2 + \\ //! C tld 3 + \\ + \\ /// c1 doc + \\ c1: u32, + \\ + \\ //! C tld 4 + \\ //! C tld 5 + \\ //! C tld 6 + \\ + \\ /// c2 doc + \\ c2: u32, + \\}; + \\ + ); + try testCanonical( + \\//! Top-level documentation. + \\ + \\/// This is A + \\pub const A = usize; + \\ + ); + try testCanonical( + \\//! Nothing here + \\ + ); +} + const std = @import("std"); const mem = std.mem; const warn = std.debug.warn; @@ -2558,8 +2631,7 @@ const maxInt = std.math.maxInt; var fixed_buffer_mem: [100 * 1024]u8 = undefined; fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *bool) ![]u8 { - var stderr_file = try io.getStdErr(); - var stderr = &stderr_file.outStream().stream; + const stderr = &io.getStdErr().outStream().stream; const tree = try std.zig.parse(allocator, source); defer tree.deinit(); diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig @@ -226,9 +226,7 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i if (use_decl.visib_token) |visib_token| { try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub } - // TODO after depracating use, go back to this: - //try renderToken(tree, stream, use_decl.use_token, indent, start_col, Space.Space); // usingnamespace - try stream.write("usingnamespace "); + try renderToken(tree, stream, use_decl.use_token, indent, start_col, Space.Space); // usingnamespace try renderExpression(allocator, stream, tree, indent, start_col, use_decl.expr, Space.None); try renderToken(tree, stream, use_decl.semicolon_token, indent, start_col, Space.Newline); // ; }, @@ -301,6 +299,17 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i assert(!decl.requireSemiColon()); try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.Newline); }, + + ast.Node.Id.DocComment => { + const comment = @fieldParentPtr(ast.Node.DocComment, "base", decl); + var it = comment.lines.iterator(0); + while (it.next()) |line_token_index| { + try renderToken(tree, stream, line_token_index.*, indent, start_col, Space.Newline); + if (it.peek()) |_| { + try stream.writeByteNTimes(' ', indent); + } + } + }, else => unreachable, } } @@ -410,8 +419,8 @@ fn renderExpression( switch (prefix_op_node.op) { ast.Node.PrefixOp.Op.PtrType => |ptr_info| { const star_offset = switch (tree.tokens.at(prefix_op_node.op_token).id) { - Token.Id.AsteriskAsterisk => usize(1), - else => usize(0), + Token.Id.AsteriskAsterisk => @as(usize, 1), + else => @as(usize, 0), }; try renderTokenOffset(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None, star_offset); // * if (ptr_info.allowzero_token) |allowzero_token| { @@ -540,9 +549,9 @@ fn renderExpression( try renderToken(tree, stream, async_token, indent, start_col, Space.Space); } - try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None); - const lparen = tree.nextToken(suffix_op.lhs.lastToken()); + const lparen = tree.nextToken(suffix_op.lhs.node.lastToken()); if (call_info.params.len == 0) { try renderToken(tree, stream, lparen, indent, start_col, Space.None); @@ -600,7 +609,7 @@ fn renderExpression( const lbracket = tree.prevToken(index_expr.firstToken()); const rbracket = tree.nextToken(index_expr.lastToken()); - try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None); try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [ const starts_with_comment = tree.tokens.at(lbracket + 1).id == .LineComment; @@ -618,18 +627,18 @@ fn renderExpression( }, ast.Node.SuffixOp.Op.Deref => { - try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None); return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // .* }, ast.Node.SuffixOp.Op.UnwrapOptional => { - try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None); try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, start_col, Space.None); // . return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ? }, @TagType(ast.Node.SuffixOp.Op).Slice => |range| { - try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs.node, Space.None); const lbracket = tree.prevToken(range.start.firstToken()); const dotdot = tree.nextToken(range.start.lastToken()); @@ -649,10 +658,16 @@ fn renderExpression( }, ast.Node.SuffixOp.Op.StructInitializer => |*field_inits| { - const lbrace = tree.nextToken(suffix_op.lhs.lastToken()); + const lbrace = switch (suffix_op.lhs) { + .dot => |dot| tree.nextToken(dot), + .node => |node| tree.nextToken(node.lastToken()), + }; if (field_inits.len == 0) { - try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + switch (suffix_op.lhs) { + .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None), + .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None), + } try renderToken(tree, stream, lbrace, indent + indent_delta, start_col, Space.None); return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); } @@ -693,7 +708,10 @@ fn renderExpression( break :blk; } - try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + switch (suffix_op.lhs) { + .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None), + .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None), + } try renderToken(tree, stream, lbrace, indent, start_col, Space.Space); try renderExpression(allocator, stream, tree, indent, start_col, &field_init.base, Space.Space); return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); @@ -701,7 +719,10 @@ fn renderExpression( if (!src_has_trailing_comma and src_same_line and expr_outputs_one_line) { // render all on one line, no trailing comma - try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + switch (suffix_op.lhs) { + .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None), + .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None), + } try renderToken(tree, stream, lbrace, indent, start_col, Space.Space); var it = field_inits.iterator(0); @@ -721,7 +742,10 @@ fn renderExpression( const new_indent = indent + indent_delta; - try renderExpression(allocator, stream, tree, new_indent, start_col, suffix_op.lhs, Space.None); + switch (suffix_op.lhs) { + .dot => |dot| try renderToken(tree, stream, dot, new_indent, start_col, Space.None), + .node => |node| try renderExpression(allocator, stream, tree, new_indent, start_col, node, Space.None), + } try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline); var it = field_inits.iterator(0); @@ -745,23 +769,35 @@ fn renderExpression( }, ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| { - const lbrace = tree.nextToken(suffix_op.lhs.lastToken()); + const lbrace = switch (suffix_op.lhs) { + .dot => |dot| tree.nextToken(dot), + .node => |node| tree.nextToken(node.lastToken()), + }; if (exprs.len == 0) { - try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + switch (suffix_op.lhs) { + .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None), + .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None), + } try renderToken(tree, stream, lbrace, indent, start_col, Space.None); return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); } if (exprs.len == 1 and tree.tokens.at(exprs.at(0).*.lastToken() + 1).id == .RBrace) { const expr = exprs.at(0).*; - try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + switch (suffix_op.lhs) { + .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None), + .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None), + } try renderToken(tree, stream, lbrace, indent, start_col, Space.None); try renderExpression(allocator, stream, tree, indent, start_col, expr, Space.None); return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); } - try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None); + switch (suffix_op.lhs) { + .dot => |dot| try renderToken(tree, stream, dot, indent, start_col, Space.None), + .node => |node| try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None), + } // scan to find row size const maybe_row_size: ?usize = blk: { @@ -2097,7 +2133,7 @@ fn renderTokenOffset( while (true) { assert(loc.line != 0); - const newline_count = if (loc.line == 1) u8(1) else u8(2); + const newline_count = if (loc.line == 1) @as(u8, 1) else @as(u8, 2); try stream.writeByteNTimes('\n', newline_count); try stream.writeByteNTimes(' ', indent); try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(next_token), " ")); diff --git a/lib/std/zig/tokenizer.zig b/lib/std/zig/tokenizer.zig @@ -59,7 +59,6 @@ pub const Token = struct { Keyword{ .bytes = "undefined", .id = Id.Keyword_undefined }, Keyword{ .bytes = "union", .id = Id.Keyword_union }, Keyword{ .bytes = "unreachable", .id = Id.Keyword_unreachable }, - Keyword{ .bytes = "use", .id = Id.Keyword_usingnamespace }, Keyword{ .bytes = "usingnamespace", .id = Id.Keyword_usingnamespace }, Keyword{ .bytes = "var", .id = Id.Keyword_var }, Keyword{ .bytes = "volatile", .id = Id.Keyword_volatile }, @@ -143,6 +142,7 @@ pub const Token = struct { FloatLiteral, LineComment, DocComment, + ContainerDocComment, BracketStarBracket, BracketStarCBracket, ShebangLine, @@ -212,6 +212,7 @@ pub const Token = struct { .FloatLiteral => "FloatLiteral", .LineComment => "LineComment", .DocComment => "DocComment", + .ContainerDocComment => "ContainerDocComment", .ShebangLine => "ShebangLine", .Bang => "!", @@ -337,26 +338,13 @@ pub const Tokenizer = struct { } pub fn init(buffer: []const u8) Tokenizer { - if (mem.startsWith(u8, buffer, "#!")) { - const src_start = if (mem.indexOfScalar(u8, buffer, '\n')) |i| i + 1 else buffer.len; - return Tokenizer{ - .buffer = buffer, - .index = src_start, - .pending_invalid_token = Token{ - .id = Token.Id.ShebangLine, - .start = 0, - .end = src_start, - }, - }; - } else { - // Skip the UTF-8 BOM if present - const src_start = if (mem.startsWith(u8, buffer, "\xEF\xBB\xBF")) 3 else usize(0); - return Tokenizer{ - .buffer = buffer, - .index = src_start, - .pending_invalid_token = null, - }; - } + // Skip the UTF-8 BOM if present + const src_start = if (mem.startsWith(u8, buffer, "\xEF\xBB\xBF")) 3 else @as(usize, 0); + return Tokenizer{ + .buffer = buffer, + .index = src_start, + .pending_invalid_token = null, + }; } const State = enum { @@ -388,6 +376,7 @@ pub const Tokenizer = struct { LineComment, DocCommentStart, DocComment, + ContainerDocComment, Zero, IntegerLiteral, IntegerLiteralWithRadix, @@ -763,12 +752,12 @@ pub const Tokenizer = struct { self.index += 1; break; }, - '\n' => break, // Look for this error later. + '\n', '\r' => break, // Look for this error later. else => self.checkLiteralCharacter(), }, State.StringLiteralBackslash => switch (c) { - '\n' => break, // Look for this error later. + '\n', '\r' => break, // Look for this error later. else => { state = State.StringLiteral; }, @@ -1077,6 +1066,10 @@ pub const Tokenizer = struct { '/' => { state = State.DocCommentStart; }, + '!' => { + result.id = Token.Id.ContainerDocComment; + state = State.ContainerDocComment; + }, '\n' => break, else => { state = State.LineComment; @@ -1097,7 +1090,7 @@ pub const Tokenizer = struct { self.checkLiteralCharacter(); }, }, - State.LineComment, State.DocComment => switch (c) { + State.LineComment, State.DocComment, State.ContainerDocComment => switch (c) { '\n' => break, else => self.checkLiteralCharacter(), }, @@ -1235,6 +1228,9 @@ pub const Tokenizer = struct { State.DocComment, State.DocCommentStart => { result.id = Token.Id.DocComment; }, + State.ContainerDocComment => { + result.id = Token.Id.ContainerDocComment; + }, State.NumberDot, State.NumberDotHex, @@ -1602,6 +1598,8 @@ test "tokenizer - line comment and doc comment" { testTokenize("/// a", [_]Token.Id{Token.Id.DocComment}); testTokenize("///", [_]Token.Id{Token.Id.DocComment}); testTokenize("////", [_]Token.Id{Token.Id.LineComment}); + testTokenize("//!", [_]Token.Id{Token.Id.ContainerDocComment}); + testTokenize("//!!", [_]Token.Id{Token.Id.ContainerDocComment}); } test "tokenizer - line comment followed by identifier" { @@ -1625,6 +1623,16 @@ test "tokenizer - UTF-8 BOM is recognized and skipped" { }); } +test "correctly parse pointer assignment" { + testTokenize("b.*=3;\n", [_]Token.Id{ + Token.Id.Identifier, + Token.Id.PeriodAsterisk, + Token.Id.Equal, + Token.Id.IntegerLiteral, + Token.Id.Semicolon, + }); +} + fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void { var tokenizer = Tokenizer.init(source); for (expected_tokens) |expected_token_id| { diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig @@ -42,6 +42,7 @@ pub const struct_ZigClangImplicitCastExpr = @OpaqueType(); pub const struct_ZigClangIncompleteArrayType = @OpaqueType(); pub const struct_ZigClangIntegerLiteral = @OpaqueType(); pub const struct_ZigClangMacroDefinitionRecord = @OpaqueType(); +pub const struct_ZigClangMacroQualifiedType = @OpaqueType(); pub const struct_ZigClangMemberExpr = @OpaqueType(); pub const struct_ZigClangNamedDecl = @OpaqueType(); pub const struct_ZigClangNone = @OpaqueType(); @@ -831,6 +832,7 @@ pub const ZigClangImplicitCastExpr = struct_ZigClangImplicitCastExpr; pub const ZigClangIncompleteArrayType = struct_ZigClangIncompleteArrayType; pub const ZigClangIntegerLiteral = struct_ZigClangIntegerLiteral; pub const ZigClangMacroDefinitionRecord = struct_ZigClangMacroDefinitionRecord; +pub const ZigClangMacroQualifiedType = struct_ZigClangMacroQualifiedType; pub const ZigClangMemberExpr = struct_ZigClangMemberExpr; pub const ZigClangNamedDecl = struct_ZigClangNamedDecl; pub const ZigClangNone = struct_ZigClangNone; @@ -937,6 +939,8 @@ pub extern fn ZigClangElaboratedType_getNamedType(*const ZigClangElaboratedType) pub extern fn ZigClangAttributedType_getEquivalentType(*const ZigClangAttributedType) ZigClangQualType; +pub extern fn ZigClangMacroQualifiedType_getModifiedType(*const ZigClangMacroQualifiedType) ZigClangQualType; + pub extern fn ZigClangCStyleCastExpr_getBeginLoc(*const ZigClangCStyleCastExpr) ZigClangSourceLocation; pub extern fn ZigClangCStyleCastExpr_getSubExpr(*const ZigClangCStyleCastExpr) *const ZigClangExpr; pub extern fn ZigClangCStyleCastExpr_getType(*const ZigClangCStyleCastExpr) ZigClangQualType; diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig @@ -58,13 +58,10 @@ pub fn main() !void { // libc allocator is guaranteed to have this property. const allocator = std.heap.c_allocator; - var stdout_file = try std.io.getStdOut(); - var stdout_out_stream = stdout_file.outStream(); - stdout = &stdout_out_stream.stream; + stdout = &std.io.getStdOut().outStream().stream; - stderr_file = try std.io.getStdErr(); - var stderr_out_stream = stderr_file.outStream(); - stderr = &stderr_out_stream.stream; + stderr_file = std.io.getStdErr(); + stderr = &stderr_file.outStream().stream; const args = try process.argsAlloc(allocator); // TODO I'm getting unreachable code here, which shouldn't happen @@ -610,7 +607,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { process.exit(1); } - var stdin_file = try io.getStdIn(); + var stdin_file = io.getStdIn(); var stdin = stdin_file.inStream(); const source_code = try stdin.stream.readAllAlloc(allocator, max_src_size); diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig @@ -165,13 +165,9 @@ fn fmtMain(argc: c_int, argv: [*]const [*]const u8) !void { try args_list.append(std.mem.toSliceConst(u8, argv[arg_i])); } - var stdout_file = try std.io.getStdOut(); - var stdout_out_stream = stdout_file.outStream(); - stdout = &stdout_out_stream.stream; - - stderr_file = try std.io.getStdErr(); - var stderr_out_stream = stderr_file.outStream(); - stderr = &stderr_out_stream.stream; + stdout = &std.io.getStdOut().outStream().stream; + stderr_file = std.io.getStdErr(); + stderr = &stderr_file.outStream().stream; const args = args_list.toSliceConst(); var flags = try Args.parse(allocator, self_hosted_main.args_fmt_spec, args[2..]); @@ -202,7 +198,7 @@ fn fmtMain(argc: c_int, argv: [*]const [*]const u8) !void { process.exit(1); } - var stdin_file = try io.getStdIn(); + const stdin_file = io.getStdIn(); var stdin = stdin_file.inStream(); const source_code = try stdin.stream.readAllAlloc(allocator, self_hosted_main.max_src_size); @@ -223,7 +219,7 @@ fn fmtMain(argc: c_int, argv: [*]const [*]const u8) !void { } if (flags.present("check")) { const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree); - const code = if (anything_changed) u8(1) else u8(0); + const code = if (anything_changed) @as(u8, 1) else @as(u8, 0); process.exit(code); } diff --git a/src-self-hosted/test.zig b/src-self-hosted/test.zig @@ -171,8 +171,8 @@ pub const TestContext = struct { return error.OutputMismatch; } }, - .Error => |err| return err, - .Fail => |msgs| { + Compilation.Event.Error => |err| return err, + Compilation.Event.Fail => |msgs| { var stderr = try std.io.getStdErr(); try stderr.write("build incorrectly failed:\n"); for (msgs) |msg| { @@ -223,7 +223,7 @@ pub const TestContext = struct { text, ); std.debug.warn("\n====found:========\n"); - var stderr = try std.io.getStdErr(); + const stderr = std.io.getStdErr(); for (msgs) |msg| { defer msg.destroy(); try msg.printToFile(stderr, errmsg.Color.Auto); diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig @@ -122,7 +122,7 @@ const Context = struct { fn locStr(c: *Context, loc: ZigClangSourceLocation) ![]u8 { const spelling_loc = ZigClangSourceManager_getSpellingLoc(c.source_manager, loc); const filename_c = ZigClangSourceManager_getFilename(c.source_manager, spelling_loc); - const filename = if (filename_c) |s| try c.str(s) else ([]const u8)("(no file)"); + const filename = if (filename_c) |s| try c.str(s) else @as([]const u8, "(no file)"); const line = ZigClangSourceManager_getSpellingLineNumber(c.source_manager, spelling_loc); const column = ZigClangSourceManager_getSpellingColumnNumber(c.source_manager, spelling_loc); @@ -173,7 +173,6 @@ pub fn translate( tree.root_node.* = ast.Node.Root{ .base = ast.Node{ .id = ast.Node.Id.Root }, .decls = ast.Node.Root.DeclList.init(arena), - .doc_comments = null, // initialized with the eof token at the end .eof_token = undefined, }; @@ -773,12 +772,14 @@ fn transCCast( if (qualTypeIsPtr(dst_type) and qualTypeIsPtr(src_type)) return transCPtrCast(rp, loc, dst_type, src_type, expr); if (cIsUnsignedInteger(dst_type) and qualTypeIsPtr(src_type)) { - const cast_node = try transCreateNodeFnCall(rp.c, try transQualType(rp, dst_type, loc)); + const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@as"); + try cast_node.params.push(try transQualType(rp, dst_type, loc)); + _ = try appendToken(rp.c, .Comma, ","); const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "@ptrToInt"); try builtin_node.params.push(expr); builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")"); - try cast_node.op.Call.params.push(&builtin_node.base); - cast_node.rtoken = try appendToken(rp.c, .RParen, ")"); + try cast_node.params.push(&builtin_node.base); + cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); return &cast_node.base; } if (cIsUnsignedInteger(src_type) and qualTypeIsPtr(dst_type)) { @@ -792,9 +793,11 @@ fn transCCast( // TODO: maybe widen to increase size // TODO: maybe bitcast to change sign // TODO: maybe truncate to reduce size - const cast_node = try transCreateNodeFnCall(rp.c, try transQualType(rp, dst_type, loc)); - try cast_node.op.Call.params.push(expr); - cast_node.rtoken = try appendToken(rp.c, .RParen, ")"); + const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@as"); + try cast_node.params.push(try transQualType(rp, dst_type, loc)); + _ = try appendToken(rp.c, .Comma, ","); + try cast_node.params.push(expr); + cast_node.rparen_token = try appendToken(rp.c, .RParen, ")"); return &cast_node.base; } diff --git a/src/all_types.hpp b/src/all_types.hpp @@ -48,6 +48,7 @@ struct ResultLoc; struct ResultLocPeer; struct ResultLocPeerParent; struct ResultLocBitCast; +struct ResultLocCast; struct ResultLocReturn; enum PtrLen { @@ -151,7 +152,7 @@ struct ConstParent { }; struct ConstStructValue { - ConstExprValue *fields; + ConstExprValue **fields; }; struct ConstUnionValue { @@ -967,6 +968,7 @@ struct AstNodeContainerDecl { AstNode *init_arg_expr; // enum(T), struct(endianness), or union(T), or union(enum(T)) ZigList<AstNode *> fields; ZigList<AstNode *> decls; + Buf doc_comments; ContainerKind kind; ContainerLayout layout; @@ -1186,10 +1188,22 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b); static const uint32_t VECTOR_INDEX_NONE = UINT32_MAX; static const uint32_t VECTOR_INDEX_RUNTIME = UINT32_MAX - 1; +struct InferredStructField { + ZigType *inferred_struct_type; + Buf *field_name; +}; + struct ZigTypePointer { ZigType *child_type; ZigType *slice_parent; + // Anonymous struct literal syntax uses this when the result location has + // no type in it. This field is null if this pointer does not refer to + // a field of a currently-being-inferred struct type. + // When this is non-null, the pointer is pointing to the base of the inferred + // struct. + InferredStructField *inferred_struct_field; + PtrLen ptr_len; uint32_t explicit_alignment; // 0 means use ABI alignment @@ -1236,6 +1250,7 @@ struct TypeStructField { enum ResolveStatus { ResolveStatusUnstarted, ResolveStatusInvalid, + ResolveStatusBeingInferred, ResolveStatusZeroBitsKnown, ResolveStatusAlignmentKnown, ResolveStatusSizeKnown, @@ -1265,7 +1280,7 @@ struct RootStruct { struct ZigTypeStruct { AstNode *decl_node; - TypeStructField *fields; + TypeStructField **fields; ScopeDecls *decls_scope; HashMap<Buf *, TypeStructField *, buf_hash, buf_eql_buf> fields_by_name; RootStruct *root_struct; @@ -1284,6 +1299,7 @@ struct ZigTypeStruct { bool requires_comptime; bool resolve_loop_flag_zero_bits; bool resolve_loop_flag_other; + bool is_inferred; }; struct ZigTypeOptional { @@ -1685,12 +1701,14 @@ enum BuiltinFnId { BuiltinFnIdErrorReturnTrace, BuiltinFnIdAtomicRmw, BuiltinFnIdAtomicLoad, + BuiltinFnIdAtomicStore, BuiltinFnIdHasDecl, BuiltinFnIdUnionInit, BuiltinFnIdFrameAddress, BuiltinFnIdFrameType, BuiltinFnIdFrameHandle, BuiltinFnIdFrameSize, + BuiltinFnIdAs, }; struct BuiltinFnEntry { @@ -1739,6 +1757,7 @@ struct TypeId { union { struct { ZigType *child_type; + InferredStructField *inferred_struct_field; PtrLen ptr_len; uint32_t alignment; @@ -2552,6 +2571,7 @@ enum IrInstructionId { IrInstructionIdErrorUnion, IrInstructionIdAtomicRmw, IrInstructionIdAtomicLoad, + IrInstructionIdAtomicStore, IrInstructionIdSaveErrRetAddr, IrInstructionIdAddImplicitReturnType, IrInstructionIdErrSetCast, @@ -2810,7 +2830,7 @@ struct IrInstructionElemPtr { IrInstruction *array_ptr; IrInstruction *elem_index; - IrInstruction *init_array_type; + AstNode *init_array_type_source_node; PtrLen ptr_len; bool safety_check_on; }; @@ -2907,11 +2927,11 @@ struct IrInstructionResizeSlice { struct IrInstructionContainerInitList { IrInstruction base; - IrInstruction *container_type; IrInstruction *elem_type; size_t item_count; IrInstruction **elem_result_loc_list; IrInstruction *result_loc; + AstNode *init_array_type_source_node; }; struct IrInstructionContainerInitFieldsField { @@ -2924,7 +2944,6 @@ struct IrInstructionContainerInitFieldsField { struct IrInstructionContainerInitFields { IrInstruction base; - IrInstruction *container_type; size_t field_count; IrInstructionContainerInitFieldsField *fields; IrInstruction *result_loc; @@ -3458,6 +3477,13 @@ struct IrInstructionPtrCastGen { bool safety_check_on; }; +struct IrInstructionImplicitCast { + IrInstruction base; + + IrInstruction *operand; + ResultLocCast *result_loc_cast; +}; + struct IrInstructionBitCastSrc { IrInstruction base; @@ -3642,6 +3668,7 @@ struct IrInstructionArgType { IrInstruction *fn_type; IrInstruction *arg_index; + bool allow_var; }; struct IrInstructionExport { @@ -3690,6 +3717,16 @@ struct IrInstructionAtomicLoad { AtomicOrder resolved_ordering; }; +struct IrInstructionAtomicStore { + IrInstruction base; + + IrInstruction *operand_type; + IrInstruction *ptr; + IrInstruction *value; + IrInstruction *ordering; + AtomicOrder resolved_ordering; +}; + struct IrInstructionSaveErrRetAddr { IrInstruction base; }; @@ -3823,14 +3860,6 @@ struct IrInstructionEndExpr { ResultLoc *result_loc; }; -struct IrInstructionImplicitCast { - IrInstruction base; - - IrInstruction *dest_type; - IrInstruction *target; - ResultLoc *result_loc; -}; - // This one is for writing through the result pointer. struct IrInstructionResolveResult { IrInstruction base; @@ -3928,6 +3957,7 @@ enum ResultLocId { ResultLocIdPeerParent, ResultLocIdInstruction, ResultLocIdBitCast, + ResultLocIdCast, }; // Additions to this struct may need to be handled in @@ -3995,6 +4025,13 @@ struct ResultLocBitCast { ResultLoc *parent; }; +// The source_instruction is the destination type +struct ResultLocCast { + ResultLoc base; + + ResultLoc *parent; +}; + static const size_t slice_ptr_index = 0; static const size_t slice_len_index = 1; diff --git a/src/analyze.cpp b/src/analyze.cpp @@ -140,7 +140,6 @@ void init_scope(CodeGen *g, Scope *dest, ScopeId id, AstNode *source_node, Scope static ScopeDecls *create_decls_scope(CodeGen *g, AstNode *node, Scope *parent, ZigType *container_type, ZigType *import, Buf *bare_name) { - assert(node == nullptr || node->type == NodeTypeContainerDecl || node->type == NodeTypeFnCallExpr); ScopeDecls *scope = allocate<ScopeDecls>(1); init_scope(g, &scope->base, ScopeIdDecls, node, parent); scope->decl_table.init(4); @@ -346,6 +345,8 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) { switch (status) { case ResolveStatusInvalid: zig_unreachable(); + case ResolveStatusBeingInferred: + zig_unreachable(); case ResolveStatusUnstarted: case ResolveStatusZeroBitsKnown: return true; @@ -362,6 +363,8 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) { switch (status) { case ResolveStatusInvalid: zig_unreachable(); + case ResolveStatusBeingInferred: + zig_unreachable(); case ResolveStatusUnstarted: return true; case ResolveStatusZeroBitsKnown: @@ -483,7 +486,7 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) { ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const, bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero, - uint32_t vector_index) + uint32_t vector_index, InferredStructField *inferred_struct_field) { assert(ptr_len != PtrLenC || allow_zero); assert(!type_is_invalid(child_type)); @@ -506,7 +509,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con TypeId type_id = {}; ZigType **parent_pointer = nullptr; if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || - allow_zero || vector_index != VECTOR_INDEX_NONE) + allow_zero || vector_index != VECTOR_INDEX_NONE || inferred_struct_field != nullptr) { type_id.id = ZigTypeIdPointer; type_id.data.pointer.child_type = child_type; @@ -518,6 +521,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con type_id.data.pointer.ptr_len = ptr_len; type_id.data.pointer.allow_zero = allow_zero; type_id.data.pointer.vector_index = vector_index; + type_id.data.pointer.inferred_struct_field = inferred_struct_field; auto existing_entry = g->type_table.maybe_get(type_id); if (existing_entry) @@ -545,8 +549,15 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con } buf_resize(&entry->name, 0); if (host_int_bytes == 0 && byte_alignment == 0 && vector_index == VECTOR_INDEX_NONE) { - buf_appendf(&entry->name, "%s%s%s%s%s", - star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); + if (inferred_struct_field == nullptr) { + buf_appendf(&entry->name, "%s%s%s%s%s", + star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); + } else { + buf_appendf(&entry->name, "(%s%s%s%s field '%s' of %s)", + star_str, const_str, volatile_str, allow_zero_str, + buf_ptr(inferred_struct_field->field_name), + buf_ptr(&inferred_struct_field->inferred_struct_type->name)); + } } else if (host_int_bytes == 0 && vector_index == VECTOR_INDEX_NONE) { buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name)); @@ -603,6 +614,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con entry->data.pointer.host_int_bytes = host_int_bytes; entry->data.pointer.allow_zero = allow_zero; entry->data.pointer.vector_index = vector_index; + entry->data.pointer.inferred_struct_field = inferred_struct_field; if (parent_pointer) { *parent_pointer = entry; @@ -617,12 +629,12 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero) { return get_pointer_to_type_extra2(g, child_type, is_const, is_volatile, ptr_len, - byte_alignment, bit_offset_in_host, host_int_bytes, allow_zero, VECTOR_INDEX_NONE); + byte_alignment, bit_offset_in_host, host_int_bytes, allow_zero, VECTOR_INDEX_NONE, nullptr); } ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) { return get_pointer_to_type_extra2(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false, - VECTOR_INDEX_NONE); + VECTOR_INDEX_NONE, nullptr); } ZigType *get_optional_type(CodeGen *g, ZigType *child_type) { @@ -791,19 +803,19 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { entry->data.structure.is_slice = true; entry->data.structure.src_field_count = element_count; entry->data.structure.gen_field_count = element_count; - entry->data.structure.fields = allocate<TypeStructField>(element_count); + entry->data.structure.fields = alloc_type_struct_fields(element_count); entry->data.structure.fields_by_name.init(element_count); - entry->data.structure.fields[slice_ptr_index].name = ptr_field_name; - entry->data.structure.fields[slice_ptr_index].type_entry = ptr_type; - entry->data.structure.fields[slice_ptr_index].src_index = slice_ptr_index; - entry->data.structure.fields[slice_ptr_index].gen_index = 0; - entry->data.structure.fields[slice_len_index].name = len_field_name; - entry->data.structure.fields[slice_len_index].type_entry = g->builtin_types.entry_usize; - entry->data.structure.fields[slice_len_index].src_index = slice_len_index; - entry->data.structure.fields[slice_len_index].gen_index = 1; - - entry->data.structure.fields_by_name.put(ptr_field_name, &entry->data.structure.fields[slice_ptr_index]); - entry->data.structure.fields_by_name.put(len_field_name, &entry->data.structure.fields[slice_len_index]); + entry->data.structure.fields[slice_ptr_index]->name = ptr_field_name; + entry->data.structure.fields[slice_ptr_index]->type_entry = ptr_type; + entry->data.structure.fields[slice_ptr_index]->src_index = slice_ptr_index; + entry->data.structure.fields[slice_ptr_index]->gen_index = 0; + entry->data.structure.fields[slice_len_index]->name = len_field_name; + entry->data.structure.fields[slice_len_index]->type_entry = g->builtin_types.entry_usize; + entry->data.structure.fields[slice_len_index]->src_index = slice_len_index; + entry->data.structure.fields[slice_len_index]->gen_index = 1; + + entry->data.structure.fields_by_name.put(ptr_field_name, entry->data.structure.fields[slice_ptr_index]); + entry->data.structure.fields_by_name.put(len_field_name, entry->data.structure.fields[slice_len_index]); switch (type_requires_comptime(g, ptr_type)) { case ReqCompTimeInvalid: @@ -816,8 +828,8 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { if (!type_has_bits(ptr_type)) { entry->data.structure.gen_field_count = 1; - entry->data.structure.fields[slice_ptr_index].gen_index = SIZE_MAX; - entry->data.structure.fields[slice_len_index].gen_index = 0; + entry->data.structure.fields[slice_ptr_index]->gen_index = SIZE_MAX; + entry->data.structure.fields[slice_len_index]->gen_index = 0; } ZigType *child_type = ptr_type->data.pointer.child_type; @@ -1449,8 +1461,8 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf ** if (type_is_invalid(result_val->type)) return false; - ConstExprValue *ptr_field = &result_val->data.x_struct.fields[slice_ptr_index]; - ConstExprValue *len_field = &result_val->data.x_struct.fields[slice_len_index]; + ConstExprValue *ptr_field = result_val->data.x_struct.fields[slice_ptr_index]; + ConstExprValue *len_field = result_val->data.x_struct.fields[slice_len_index]; assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray); ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val; @@ -1972,12 +1984,12 @@ static ZigType *get_struct_type(CodeGen *g, const char *type_name, SrcField fiel struct_type->data.structure.src_field_count = field_count; struct_type->data.structure.gen_field_count = 0; struct_type->data.structure.resolve_status = ResolveStatusSizeKnown; - struct_type->data.structure.fields = allocate<TypeStructField>(field_count); + struct_type->data.structure.fields = alloc_type_struct_fields(field_count); struct_type->data.structure.fields_by_name.init(field_count); size_t abi_align = min_abi_align; for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; + TypeStructField *field = struct_type->data.structure.fields[i]; field->name = buf_create_from_str(fields[i].name); field->type_entry = fields[i].ty; field->src_index = i; @@ -1997,7 +2009,7 @@ static ZigType *get_struct_type(CodeGen *g, const char *type_name, SrcField fiel size_t next_offset = 0; for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; + TypeStructField *field = struct_type->data.structure.fields[i]; if (!type_has_bits(field->type_entry)) continue; @@ -2006,7 +2018,7 @@ static ZigType *get_struct_type(CodeGen *g, const char *type_name, SrcField fiel // find the next non-zero-byte field for offset calculations size_t next_src_field_index = i + 1; for (; next_src_field_index < field_count; next_src_field_index += 1) { - if (type_has_bits(struct_type->data.structure.fields[next_src_field_index].type_entry)) + if (type_has_bits(struct_type->data.structure.fields[next_src_field_index]->type_entry)) break; } size_t next_abi_align; @@ -2014,7 +2026,7 @@ static ZigType *get_struct_type(CodeGen *g, const char *type_name, SrcField fiel next_abi_align = abi_align; } else { next_abi_align = max(fields[next_src_field_index].align, - struct_type->data.structure.fields[next_src_field_index].type_entry->abi_align); + struct_type->data.structure.fields[next_src_field_index]->type_entry->abi_align); } next_offset = next_field_offset(next_offset, abi_align, field->type_entry->abi_size, next_abi_align); } @@ -2079,7 +2091,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { } assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0); - assert(decl_node->type == NodeTypeContainerDecl); + assert(decl_node->type == NodeTypeContainerDecl || decl_node->type == NodeTypeContainerInitExpr); size_t field_count = struct_type->data.structure.src_field_count; @@ -2097,7 +2109,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { // Calculate offsets for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; + TypeStructField *field = struct_type->data.structure.fields[i]; if (field->gen_index == SIZE_MAX) continue; @@ -2166,12 +2178,12 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { gen_field_index += 1; size_t next_src_field_index = i + 1; for (; next_src_field_index < field_count; next_src_field_index += 1) { - if (struct_type->data.structure.fields[next_src_field_index].gen_index != SIZE_MAX) { + if (struct_type->data.structure.fields[next_src_field_index]->gen_index != SIZE_MAX) { break; } } size_t next_align = (next_src_field_index == field_count) ? - abi_align : struct_type->data.structure.fields[next_src_field_index].align; + abi_align : struct_type->data.structure.fields[next_src_field_index]->align; next_offset = next_field_offset(next_offset, abi_align, field_abi_size, next_align); size_in_bits = next_offset * 8; } @@ -2194,7 +2206,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { // Resolve types for fields for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; + TypeStructField *field = struct_type->data.structure.fields[i]; ZigType *field_type = resolve_struct_field_type(g, field); if (field_type == nullptr) { struct_type->data.structure.resolve_status = ResolveStatusInvalid; @@ -2667,7 +2679,6 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { return ErrorNone; AstNode *decl_node = struct_type->data.structure.decl_node; - assert(decl_node->type == NodeTypeContainerDecl); if (struct_type->data.structure.resolve_loop_flag_zero_bits) { if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) { @@ -2678,29 +2689,46 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { } return ErrorSemanticAnalyzeFail; } - struct_type->data.structure.resolve_loop_flag_zero_bits = true; - assert(!struct_type->data.structure.fields); - size_t field_count = decl_node->data.container_decl.fields.length; - struct_type->data.structure.src_field_count = (uint32_t)field_count; - struct_type->data.structure.fields = allocate<TypeStructField>(field_count); + size_t field_count; + if (decl_node->type == NodeTypeContainerDecl) { + field_count = decl_node->data.container_decl.fields.length; + struct_type->data.structure.src_field_count = (uint32_t)field_count; + + src_assert(struct_type->data.structure.fields == nullptr, decl_node); + struct_type->data.structure.fields = alloc_type_struct_fields(field_count); + } else if (decl_node->type == NodeTypeContainerInitExpr) { + src_assert(struct_type->data.structure.is_inferred, decl_node); + src_assert(struct_type->data.structure.fields != nullptr, decl_node); + + field_count = struct_type->data.structure.src_field_count; + } else zig_unreachable(); + struct_type->data.structure.fields_by_name.init(field_count); Scope *scope = &struct_type->data.structure.decls_scope->base; size_t gen_field_index = 0; for (size_t i = 0; i < field_count; i += 1) { - AstNode *field_node = decl_node->data.container_decl.fields.at(i); - TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; - type_struct_field->name = field_node->data.struct_field.name; - type_struct_field->decl_node = field_node; + TypeStructField *type_struct_field = struct_type->data.structure.fields[i]; - if (field_node->data.struct_field.type == nullptr) { - add_node_error(g, field_node, buf_sprintf("struct field missing type")); - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - return ErrorSemanticAnalyzeFail; - } + AstNode *field_node; + if (decl_node->type == NodeTypeContainerDecl) { + field_node = decl_node->data.container_decl.fields.at(i); + type_struct_field->name = field_node->data.struct_field.name; + type_struct_field->decl_node = field_node; + + if (field_node->data.struct_field.type == nullptr) { + add_node_error(g, field_node, buf_sprintf("struct field missing type")); + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; + } + } else if (decl_node->type == NodeTypeContainerInitExpr) { + field_node = type_struct_field->decl_node; + + src_assert(type_struct_field->type_entry != nullptr, field_node); + } else zig_unreachable(); auto field_entry = struct_type->data.structure.fields_by_name.put_unique(type_struct_field->name, type_struct_field); if (field_entry != nullptr) { @@ -2711,16 +2739,21 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { return ErrorSemanticAnalyzeFail; } - ConstExprValue *field_type_val = analyze_const_value(g, scope, - field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef); - if (type_is_invalid(field_type_val->type)) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - return ErrorSemanticAnalyzeFail; - } - assert(field_type_val->special != ConstValSpecialRuntime); - type_struct_field->type_val = field_type_val; - if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) - return ErrorSemanticAnalyzeFail; + ConstExprValue *field_type_val; + if (decl_node->type == NodeTypeContainerDecl) { + field_type_val = analyze_const_value(g, scope, + field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, LazyOkNoUndef); + if (type_is_invalid(field_type_val->type)) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; + } + assert(field_type_val->special != ConstValSpecialRuntime); + type_struct_field->type_val = field_type_val; + if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) + return ErrorSemanticAnalyzeFail; + } else if (decl_node->type == NodeTypeContainerInitExpr) { + field_type_val = type_struct_field->type_val; + } else zig_unreachable(); bool field_is_opaque_type; if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) { @@ -2804,17 +2837,18 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { } struct_type->data.structure.resolve_loop_flag_other = true; - assert(decl_node->type == NodeTypeContainerDecl); + assert(decl_node->type == NodeTypeContainerDecl || decl_node->type == NodeTypeContainerInitExpr); size_t field_count = struct_type->data.structure.src_field_count; bool packed = struct_type->data.structure.layout == ContainerLayoutPacked; for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; + TypeStructField *field = struct_type->data.structure.fields[i]; if (field->gen_index == SIZE_MAX) continue; - AstNode *align_expr = field->decl_node->data.struct_field.align_expr; + AstNode *align_expr = (field->decl_node->type == NodeTypeStructField) ? + field->decl_node->data.struct_field.align_expr : nullptr; if (align_expr != nullptr) { if (!analyze_const_align(g, &struct_type->data.structure.decls_scope->base, align_expr, &field->align)) @@ -5249,7 +5283,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) { zig_unreachable(); case ZigTypeIdStruct: for (uint32_t i = 0; i < value->type->data.structure.src_field_count; i += 1) { - if (can_mutate_comptime_var_state(&value->data.x_struct.fields[i])) + if (can_mutate_comptime_var_state(value->data.x_struct.fields[i])) return true; } return false; @@ -5398,7 +5432,7 @@ bool fn_eval_eql(Scope *a, Scope *b) { return false; } -// Whether the type has bits at runtime. +// Deprecated. Use type_has_bits2. bool type_has_bits(ZigType *type_entry) { assert(type_entry != nullptr); assert(!type_is_invalid(type_entry)); @@ -5406,6 +5440,27 @@ bool type_has_bits(ZigType *type_entry) { return type_entry->abi_size != 0; } +// Whether the type has bits at runtime. +Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result) { + Error err; + + if (type_is_invalid(type_entry)) + return ErrorSemanticAnalyzeFail; + + if (type_entry->id == ZigTypeIdStruct && + type_entry->data.structure.resolve_status == ResolveStatusBeingInferred) + { + *result = true; + return ErrorNone; + } + + if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) + return err; + + *result = type_entry->abi_size != 0; + return ErrorNone; +} + // Whether you can infer the value based solely on the type. OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { assert(type_entry != nullptr); @@ -5413,6 +5468,12 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { if (type_entry->one_possible_value != OnePossibleValueInvalid) return type_entry->one_possible_value; + if (type_entry->id == ZigTypeIdStruct && + type_entry->data.structure.resolve_status == ResolveStatusBeingInferred) + { + return OnePossibleValueNo; + } + Error err; if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) return OnePossibleValueInvalid; @@ -5445,7 +5506,7 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) { return type_has_one_possible_value(g, type_entry->data.array.child_type); case ZigTypeIdStruct: for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { - TypeStructField *field = &type_entry->data.structure.fields[i]; + TypeStructField *field = type_entry->data.structure.fields[i]; OnePossibleValue opv = (field->type_entry != nullptr) ? type_has_one_possible_value(g, field->type_entry) : type_val_resolve_has_one_possible_value(g, field->type_val); @@ -5737,11 +5798,11 @@ void init_const_slice(CodeGen *g, ConstExprValue *const_val, ConstExprValue *arr const_val->special = ConstValSpecialStatic; const_val->type = get_slice_type(g, ptr_type); - const_val->data.x_struct.fields = create_const_vals(2); + const_val->data.x_struct.fields = alloc_const_vals_ptrs(2); - init_const_ptr_array(g, &const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const, + init_const_ptr_array(g, const_val->data.x_struct.fields[slice_ptr_index], array_val, start, is_const, PtrLenUnknown); - init_const_usize(g, &const_val->data.x_struct.fields[slice_len_index], len); + init_const_usize(g, const_val->data.x_struct.fields[slice_len_index], len); } ConstExprValue *create_const_slice(CodeGen *g, ConstExprValue *array_val, size_t start, size_t len, bool is_const) { @@ -5825,6 +5886,38 @@ ConstExprValue *create_const_vals(size_t count) { return vals; } +ConstExprValue **alloc_const_vals_ptrs(size_t count) { + return realloc_const_vals_ptrs(nullptr, 0, count); +} + +ConstExprValue **realloc_const_vals_ptrs(ConstExprValue **ptr, size_t old_count, size_t new_count) { + assert(new_count >= old_count); + + size_t new_item_count = new_count - old_count; + ConstExprValue **result = reallocate(ptr, old_count, new_count, "ConstExprValue*"); + ConstExprValue *vals = create_const_vals(new_item_count); + for (size_t i = old_count; i < new_count; i += 1) { + result[i] = &vals[i - old_count]; + } + return result; +} + +TypeStructField **alloc_type_struct_fields(size_t count) { + return realloc_type_struct_fields(nullptr, 0, count); +} + +TypeStructField **realloc_type_struct_fields(TypeStructField **ptr, size_t old_count, size_t new_count) { + assert(new_count >= old_count); + + size_t new_item_count = new_count - old_count; + TypeStructField **result = reallocate(ptr, old_count, new_count, "TypeStructField*"); + TypeStructField *vals = allocate<TypeStructField>(new_item_count, "TypeStructField"); + for (size_t i = old_count; i < new_count; i += 1) { + result[i] = &vals[i - old_count]; + } + return result; +} + static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) { if (orig_fn_type->data.fn.fn_type_id.cc == CallingConventionAsync) return orig_fn_type; @@ -6132,6 +6225,8 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { continue; if (instruction->ref_count == 0) continue; + if ((err = type_resolve(g, instruction->value.type, ResolveStatusZeroBitsKnown))) + return ErrorSemanticAnalyzeFail; if (!type_has_bits(instruction->value.type)) continue; if (scope_needs_spill(instruction->scope)) { @@ -6271,6 +6366,8 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) { switch (status) { case ResolveStatusUnstarted: return ErrorNone; + case ResolveStatusBeingInferred: + zig_unreachable(); case ResolveStatusInvalid: zig_unreachable(); case ResolveStatusZeroBitsKnown: @@ -6502,8 +6599,8 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { } case ZigTypeIdStruct: for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) { - ConstExprValue *field_a = &a->data.x_struct.fields[i]; - ConstExprValue *field_b = &b->data.x_struct.fields[i]; + ConstExprValue *field_a = a->data.x_struct.fields[i]; + ConstExprValue *field_b = b->data.x_struct.fields[i]; if (!const_values_equal(g, field_a, field_b)) return false; } @@ -6811,10 +6908,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { case ZigTypeIdStruct: { if (is_slice(type_entry)) { - ConstExprValue *len_val = &const_val->data.x_struct.fields[slice_len_index]; + ConstExprValue *len_val = const_val->data.x_struct.fields[slice_len_index]; size_t len = bigint_as_usize(&len_val->data.x_bigint); - ConstExprValue *ptr_val = &const_val->data.x_struct.fields[slice_ptr_index]; + ConstExprValue *ptr_val = const_val->data.x_struct.fields[slice_ptr_index]; if (ptr_val->special == ConstValSpecialUndef) { assert(len == 0); buf_appendf(buf, "((%s)(undefined))[0..0]", buf_ptr(&type_entry->name)); @@ -6995,7 +7092,16 @@ bool type_id_eql(TypeId a, TypeId b) { a.data.pointer.alignment == b.data.pointer.alignment && a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host && a.data.pointer.vector_index == b.data.pointer.vector_index && - a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes; + a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes && + ( + a.data.pointer.inferred_struct_field == b.data.pointer.inferred_struct_field || + (a.data.pointer.inferred_struct_field != nullptr && + b.data.pointer.inferred_struct_field != nullptr && + a.data.pointer.inferred_struct_field->inferred_struct_type == + b.data.pointer.inferred_struct_field->inferred_struct_type && + buf_eql_buf(a.data.pointer.inferred_struct_field->field_name, + b.data.pointer.inferred_struct_field->field_name)) + ); case ZigTypeIdArray: return a.data.array.child_type == b.data.array.child_type && a.data.array.size == b.data.array.size; @@ -7082,10 +7188,10 @@ static void init_const_undefined(CodeGen *g, ConstExprValue *const_val) { const_val->special = ConstValSpecialStatic; size_t field_count = wanted_type->data.structure.src_field_count; - const_val->data.x_struct.fields = create_const_vals(field_count); + const_val->data.x_struct.fields = alloc_const_vals_ptrs(field_count); for (size_t i = 0; i < field_count; i += 1) { - ConstExprValue *field_val = &const_val->data.x_struct.fields[i]; - field_val->type = wanted_type->data.structure.fields[i].type_entry; + ConstExprValue *field_val = const_val->data.x_struct.fields[i]; + field_val->type = resolve_struct_field_type(g, wanted_type->data.structure.fields[i]); assert(field_val->type); init_const_undefined(g, field_val); field_val->parent.id = ConstParentIdStruct; @@ -7517,7 +7623,7 @@ static X64CABIClass type_system_V_abi_x86_64_class(CodeGen *g, ZigType *ty, size } X64CABIClass working_class = X64CABIClass_Unknown; for (uint32_t i = 0; i < ty->data.structure.src_field_count; i += 1) { - X64CABIClass field_class = type_c_abi_x86_64_class(g, ty->data.structure.fields->type_entry); + X64CABIClass field_class = type_c_abi_x86_64_class(g, ty->data.structure.fields[0]->type_entry); if (field_class == X64CABIClass_Unknown) return X64CABIClass_Unknown; if (i == 0 || field_class == X64CABIClass_MEMORY || working_class == X64CABIClass_SSE) { @@ -7649,7 +7755,7 @@ Buf *type_h_name(ZigType *t) { static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) { if (type->data.structure.resolve_status >= wanted_resolve_status) return; - ZigType *ptr_type = type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *ptr_type = type->data.structure.fields[slice_ptr_index]->type_entry; ZigType *child_type = ptr_type->data.pointer.child_type; ZigType *usize_type = g->builtin_types.entry_usize; @@ -7671,7 +7777,7 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa // If the child type is []const T then we need to make sure the type ref // and debug info is the same as if the child type were []T. if (is_slice(child_type)) { - ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index]->type_entry; assert(child_ptr_type->id == ZigTypeIdPointer); if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile || child_ptr_type->data.pointer.explicit_alignment != 0 || child_ptr_type->data.pointer.allow_zero) @@ -7808,7 +7914,6 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS ZigLLVMDIScope *di_scope; unsigned line; if (decl_node != nullptr) { - assert(decl_node->type == NodeTypeContainerDecl); Scope *scope = &struct_type->data.structure.decls_scope->base; ZigType *import = get_scope_import(scope); di_file = import->data.structure.root_struct->di_file; @@ -7849,7 +7954,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS // trigger all the recursive get_llvm_type calls for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; + TypeStructField *field = struct_type->data.structure.fields[i]; ZigType *field_type = field->type_entry; if (!type_has_bits(field_type)) continue; @@ -7863,7 +7968,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS // inserting padding bytes where LLVM would do it automatically. size_t llvm_struct_abi_align = 0; for (size_t i = 0; i < field_count; i += 1) { - ZigType *field_type = struct_type->data.structure.fields[i].type_entry; + ZigType *field_type = struct_type->data.structure.fields[i]->type_entry; if (!type_has_bits(field_type)) continue; LLVMTypeRef field_llvm_type = get_llvm_type(g, field_type); @@ -7872,7 +7977,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS } for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; + TypeStructField *field = struct_type->data.structure.fields[i]; ZigType *field_type = field->type_entry; if (!type_has_bits(field_type)) { @@ -7922,23 +8027,23 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS // find the next non-zero-byte field for offset calculations size_t next_src_field_index = i + 1; for (; next_src_field_index < field_count; next_src_field_index += 1) { - if (type_has_bits(struct_type->data.structure.fields[next_src_field_index].type_entry)) + if (type_has_bits(struct_type->data.structure.fields[next_src_field_index]->type_entry)) break; } size_t next_abi_align; if (next_src_field_index == field_count) { next_abi_align = struct_type->abi_align; } else { - if (struct_type->data.structure.fields[next_src_field_index].align == 0) { - next_abi_align = struct_type->data.structure.fields[next_src_field_index].type_entry->abi_align; + if (struct_type->data.structure.fields[next_src_field_index]->align == 0) { + next_abi_align = struct_type->data.structure.fields[next_src_field_index]->type_entry->abi_align; } else { - next_abi_align = struct_type->data.structure.fields[next_src_field_index].align; + next_abi_align = struct_type->data.structure.fields[next_src_field_index]->align; } } size_t llvm_next_abi_align = (next_src_field_index == field_count) ? llvm_struct_abi_align : LLVMABIAlignmentOfType(g->target_data_ref, - get_llvm_type(g, struct_type->data.structure.fields[next_src_field_index].type_entry)); + get_llvm_type(g, struct_type->data.structure.fields[next_src_field_index]->type_entry)); size_t next_offset = next_field_offset(field->offset, struct_type->abi_align, field_type->abi_size, next_abi_align); @@ -7977,7 +8082,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(debug_field_count); size_t debug_field_index = 0; for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; + TypeStructField *field = struct_type->data.structure.fields[i]; size_t gen_field_index = field->gen_index; if (gen_field_index == SIZE_MAX) { continue; @@ -8011,7 +8116,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS } unsigned line; if (decl_node != nullptr) { - AstNode *field_node = decl_node->data.container_decl.fields.at(i); + AstNode *field_node = field->decl_node; line = field_node->line + 1; } else { line = 0; @@ -8307,12 +8412,12 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus if (type->data.pointer.vector_index == VECTOR_INDEX_NONE) { peer_type = get_pointer_to_type_extra2(g, elem_type, false, false, PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false, - VECTOR_INDEX_NONE); + VECTOR_INDEX_NONE, nullptr); } else { uint32_t host_vec_len = type->data.pointer.host_int_bytes; ZigType *host_vec_type = get_vector_type(g, host_vec_len, elem_type); peer_type = get_pointer_to_type_extra2(g, host_vec_type, false, false, - PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE); + PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr); } type->llvm_type = get_llvm_type(g, peer_type); type->llvm_di_type = get_llvm_di_type(g, peer_type); @@ -9038,4 +9143,3 @@ Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str, *out_import = add_source_file(g, target_package, resolved_path, import_code, source_kind); return ErrorNone; } - diff --git a/src/analyze.hpp b/src/analyze.hpp @@ -24,7 +24,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const, bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count, - bool allow_zero, uint32_t vector_index); + bool allow_zero, uint32_t vector_index, InferredStructField *inferred_struct_field); uint64_t type_size(CodeGen *g, ZigType *type_entry); uint64_t type_size_bits(CodeGen *g, ZigType *type_entry); ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); @@ -46,6 +46,8 @@ ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type); bool handle_is_ptr(ZigType *type_entry); bool type_has_bits(ZigType *type_entry); +Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result); + Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result); bool ptr_allows_addr_zero(ZigType *ptr_type); bool type_is_nonnull_ptr(ZigType *type); @@ -175,6 +177,11 @@ void init_const_arg_tuple(CodeGen *g, ConstExprValue *const_val, size_t arg_inde ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_t arg_index_end); ConstExprValue *create_const_vals(size_t count); +ConstExprValue **alloc_const_vals_ptrs(size_t count); +ConstExprValue **realloc_const_vals_ptrs(ConstExprValue **ptr, size_t old_count, size_t new_count); + +TypeStructField **alloc_type_struct_fields(size_t count); +TypeStructField **realloc_type_struct_fields(TypeStructField **ptr, size_t old_count, size_t new_count); ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); void expand_undef_array(CodeGen *g, ConstExprValue *const_val); diff --git a/src/ast_render.cpp b/src/ast_render.cpp @@ -821,7 +821,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { break; } case NodeTypeContainerInitExpr: - render_node_ungrouped(ar, node->data.container_init_expr.type); + if (node->data.container_init_expr.type != nullptr) { + render_node_ungrouped(ar, node->data.container_init_expr.type); + } if (node->data.container_init_expr.kind == ContainerInitKindStruct) { fprintf(ar->f, "{\n"); ar->indent += ar->indent_size; @@ -1137,10 +1139,20 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { for (size_t i = 0; i < node->data.err_set_decl.decls.length; i += 1) { AstNode *field_node = node->data.err_set_decl.decls.at(i); - assert(field_node->type == NodeTypeSymbol); - print_indent(ar); - print_symbol(ar, field_node->data.symbol_expr.symbol); - fprintf(ar->f, ",\n"); + switch (field_node->type) { + case NodeTypeSymbol: + print_indent(ar); + print_symbol(ar, field_node->data.symbol_expr.symbol); + fprintf(ar->f, ",\n"); + break; + case NodeTypeErrorSetField: + print_indent(ar); + print_symbol(ar, field_node->data.err_set_field.field_name->data.symbol_expr.symbol); + fprintf(ar->f, ",\n"); + break; + default: + zig_unreachable(); + } } ar->indent -= ar->indent_size; diff --git a/src/codegen.cpp b/src/codegen.cpp @@ -1108,15 +1108,15 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) { LLVMValueRef err_ret_trace_ptr = LLVMGetParam(fn_val, 0); LLVMValueRef address_value = LLVMGetParam(fn_val, 1); - size_t index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index; + size_t index_field_index = g->stack_trace_type->data.structure.fields[0]->gen_index; LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, err_ret_trace_ptr, (unsigned)index_field_index, ""); - size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index; + size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1]->gen_index; LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, err_ret_trace_ptr, (unsigned)addresses_field_index, ""); - ZigType *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry; - size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index; + ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry; + size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)ptr_field_index, ""); - size_t len_field_index = slice_type->data.structure.fields[slice_len_index].gen_index; + size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index; LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)len_field_index, ""); LLVMValueRef len_value = gen_load_untyped(g, len_field_ptr, 0, false, ""); @@ -1699,6 +1699,10 @@ static void gen_var_debug_decl(CodeGen *g, ZigVar *var) { } static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) { + Error err; + if ((err = type_resolve(g, instruction->value.type, ResolveStatusZeroBitsKnown))) { + codegen_report_errors_and_exit(g); + } if (!type_has_bits(instruction->value.type)) return nullptr; if (!instruction->llvm_value) { @@ -2172,16 +2176,16 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { LLVMBuildCondBr(g->builder, null_bit, return_block, non_null_block); LLVMPositionBuilderAtEnd(g->builder, non_null_block); - size_t src_index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index; - size_t src_addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index; + size_t src_index_field_index = g->stack_trace_type->data.structure.fields[0]->gen_index; + size_t src_addresses_field_index = g->stack_trace_type->data.structure.fields[1]->gen_index; LLVMValueRef src_index_field_ptr = LLVMBuildStructGEP(g->builder, src_stack_trace_ptr, (unsigned)src_index_field_index, ""); LLVMValueRef src_addresses_field_ptr = LLVMBuildStructGEP(g->builder, src_stack_trace_ptr, (unsigned)src_addresses_field_index, ""); - ZigType *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry; - size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index; + ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry; + size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; LLVMValueRef src_ptr_field_ptr = LLVMBuildStructGEP(g->builder, src_addresses_field_ptr, (unsigned)ptr_field_index, ""); - size_t len_field_index = slice_type->data.structure.fields[slice_len_index].gen_index; + size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index; LLVMValueRef src_len_field_ptr = LLVMBuildStructGEP(g->builder, src_addresses_field_ptr, (unsigned)len_field_index, ""); LLVMValueRef src_index_val = LLVMBuildLoad(g->builder, src_index_field_ptr, ""); LLVMValueRef src_ptr_val = LLVMBuildLoad(g->builder, src_ptr_field_ptr, ""); @@ -3006,21 +3010,21 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable, assert(actual_type->id == ZigTypeIdStruct); assert(actual_type->data.structure.is_slice); - ZigType *actual_pointer_type = actual_type->data.structure.fields[0].type_entry; + ZigType *actual_pointer_type = actual_type->data.structure.fields[0]->type_entry; ZigType *actual_child_type = actual_pointer_type->data.pointer.child_type; - ZigType *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry; + ZigType *wanted_pointer_type = wanted_type->data.structure.fields[0]->type_entry; ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type; - size_t actual_ptr_index = actual_type->data.structure.fields[slice_ptr_index].gen_index; - size_t actual_len_index = actual_type->data.structure.fields[slice_len_index].gen_index; - size_t wanted_ptr_index = wanted_type->data.structure.fields[slice_ptr_index].gen_index; - size_t wanted_len_index = wanted_type->data.structure.fields[slice_len_index].gen_index; + size_t actual_ptr_index = actual_type->data.structure.fields[slice_ptr_index]->gen_index; + size_t actual_len_index = actual_type->data.structure.fields[slice_len_index]->gen_index; + size_t wanted_ptr_index = wanted_type->data.structure.fields[slice_ptr_index]->gen_index; + size_t wanted_len_index = wanted_type->data.structure.fields[slice_len_index]->gen_index; LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_ptr_index, ""); LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, ""); LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, - get_llvm_type(g, wanted_type->data.structure.fields[0].type_entry), ""); + get_llvm_type(g, wanted_type->data.structure.fields[0]->type_entry), ""); LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, result_loc, (unsigned)wanted_ptr_index, ""); gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false); @@ -3136,9 +3140,9 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, IrExecutable *ex { ZigType *actual_type = instruction->operand->value.type; ZigType *slice_type = instruction->base.value.type; - ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index].type_entry; - size_t ptr_index = slice_type->data.structure.fields[slice_ptr_index].gen_index; - size_t len_index = slice_type->data.structure.fields[slice_len_index].gen_index; + ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry; + size_t ptr_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; + size_t len_index = slice_type->data.structure.fields[slice_len_index]->gen_index; LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); @@ -3504,7 +3508,7 @@ static bool value_is_all_undef(CodeGen *g, ConstExprValue *const_val) { case ConstValSpecialStatic: if (const_val->type->id == ZigTypeIdStruct) { for (size_t i = 0; i < const_val->type->data.structure.src_field_count; i += 1) { - if (!value_is_all_undef(g, &const_val->data.x_struct.fields[i])) + if (!value_is_all_undef(g, const_val->data.x_struct.fields[i])) return false; } return true; @@ -3618,9 +3622,14 @@ static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_ } static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) { + Error err; + ZigType *ptr_type = instruction->ptr->value.type; assert(ptr_type->id == ZigTypeIdPointer); - if (!type_has_bits(ptr_type)) + bool ptr_type_has_bits; + if ((err = type_has_bits2(g, ptr_type, &ptr_type_has_bits))) + codegen_report_errors_and_exit(g); + if (!ptr_type_has_bits) return nullptr; if (instruction->ptr->ref_count == 0) { // In this case, this StorePtr instruction should be elided. Something happened like this: @@ -3757,14 +3766,14 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind); if (safety_check_on) { - size_t len_index = array_type->data.structure.fields[slice_len_index].gen_index; + size_t len_index = array_type->data.structure.fields[slice_len_index]->gen_index; assert(len_index != SIZE_MAX); LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)len_index, ""); LLVMValueRef len = gen_load_untyped(g, len_ptr, 0, false, ""); add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, len); } - size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index; + size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index; assert(ptr_index != SIZE_MAX); LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)ptr_index, ""); LLVMValueRef ptr = gen_load_untyped(g, ptr_ptr, 0, false, ""); @@ -3856,7 +3865,7 @@ static void render_async_spills(CodeGen *g) { if (instruction->field_index == SIZE_MAX) continue; - size_t gen_index = frame_type->data.structure.fields[instruction->field_index].gen_index; + size_t gen_index = frame_type->data.structure.fields[instruction->field_index]->gen_index; instruction->base.llvm_value = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, gen_index, instruction->name_hint); } @@ -4342,17 +4351,32 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab TypeUnionField *field = instruction->field; if (!type_has_bits(field->type_entry)) { - if (union_type->data.unionation.gen_tag_index == SIZE_MAX) { + ZigType *tag_type = union_type->data.unionation.tag_type; + if (!instruction->initializing || !type_has_bits(tag_type)) return nullptr; + + // The field has no bits but we still have to change the discriminant + // value here + LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr); + + LLVMTypeRef tag_type_ref = get_llvm_type(g, tag_type); + LLVMValueRef tag_field_ptr = nullptr; + if (union_type->data.unionation.gen_field_count == 0) { + assert(union_type->data.unionation.gen_tag_index == SIZE_MAX); + // The whole union is collapsed into the discriminant + tag_field_ptr = LLVMBuildBitCast(g->builder, union_ptr, + LLVMPointerType(tag_type_ref, 0), ""); + } else { + assert(union_type->data.unionation.gen_tag_index != SIZE_MAX); + tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, + union_type->data.unionation.gen_tag_index, ""); } - if (instruction->initializing) { - LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr); - LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, - union_type->data.unionation.gen_tag_index, ""); - LLVMValueRef tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type), - &field->enum_field->value); - gen_store_untyped(g, tag_value, tag_field_ptr, 0, false); - } + + LLVMValueRef tag_value = bigint_to_llvm_const(tag_type_ref, + &field->enum_field->value); + assert(tag_field_ptr != nullptr); + gen_store_untyped(g, tag_value, tag_field_ptr, 0, false); + return nullptr; } @@ -4983,10 +5007,10 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I align_bytes = target_type->data.maybe.child_type->data.fn.fn_type_id.alignment; ptr_val = target_val; } else if (target_type->id == ZigTypeIdStruct && target_type->data.structure.is_slice) { - ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index]->type_entry; align_bytes = get_ptr_align(g, slice_ptr_type); - size_t ptr_index = target_type->data.structure.fields[slice_ptr_index].gen_index; + size_t ptr_index = target_type->data.structure.fields[slice_ptr_index]->gen_index; LLVMValueRef ptr_val_ptr = LLVMBuildStructGEP(g->builder, target_val, (unsigned)ptr_index, ""); ptr_val = gen_load_untyped(g, ptr_val_ptr, 0, false, ""); } else { @@ -5128,7 +5152,7 @@ static LLVMValueRef ir_render_memset(CodeGen *g, IrExecutable *executable, IrIns bool val_is_undef = value_is_all_undef(g, &instruction->byte->value); LLVMValueRef fill_char; - if (val_is_undef) { + if (val_is_undef && ir_want_runtime_safety_scope(g, instruction->base.scope)) { fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); } else { fill_char = ir_llvm_value(g, instruction->byte); @@ -5231,13 +5255,13 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst } if (type_has_bits(array_type)) { - size_t gen_ptr_index = instruction->base.value.type->data.structure.fields[slice_ptr_index].gen_index; + size_t gen_ptr_index = instruction->base.value.type->data.structure.fields[slice_ptr_index]->gen_index; LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_ptr_index, ""); LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, ""); gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false); } - size_t gen_len_index = instruction->base.value.type->data.structure.fields[slice_len_index].gen_index; + size_t gen_len_index = instruction->base.value.type->data.structure.fields[slice_len_index]->gen_index; LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_len_index, ""); LLVMValueRef len_value = LLVMBuildNSWSub(g->builder, end_val, start_val, ""); gen_store_untyped(g, len_value, len_field_ptr, 0, false); @@ -5249,9 +5273,9 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind); assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind); - size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index; + size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index; assert(ptr_index != SIZE_MAX); - size_t len_index = array_type->data.structure.fields[slice_len_index].gen_index; + size_t len_index = array_type->data.structure.fields[slice_len_index]->gen_index; assert(len_index != SIZE_MAX); LLVMValueRef prev_end = nullptr; @@ -5646,6 +5670,17 @@ static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutable *executable, return load_inst; } +static LLVMValueRef ir_render_atomic_store(CodeGen *g, IrExecutable *executable, + IrInstructionAtomicStore *instruction) +{ + LLVMAtomicOrdering ordering = to_LLVMAtomicOrdering(instruction->resolved_ordering); + LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); + LLVMValueRef value = ir_llvm_value(g, instruction->value); + LLVMValueRef store_inst = gen_store(g, value, ptr, instruction->ptr->value.type); + LLVMSetOrdering(store_inst, ordering); + return nullptr; +} + static LLVMValueRef ir_render_float_op(CodeGen *g, IrExecutable *executable, IrInstructionFloatOp *instruction) { LLVMValueRef op = ir_llvm_value(g, instruction->op1); assert(instruction->base.value.type->id == ZigTypeIdFloat); @@ -6249,6 +6284,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, return ir_render_atomic_rmw(g, executable, (IrInstructionAtomicRmw *)instruction); case IrInstructionIdAtomicLoad: return ir_render_atomic_load(g, executable, (IrInstructionAtomicLoad *)instruction); + case IrInstructionIdAtomicStore: + return ir_render_atomic_store(g, executable, (IrInstructionAtomicStore *)instruction); case IrInstructionIdSaveErrRetAddr: return ir_render_save_err_ret_addr(g, executable, (IrInstructionSaveErrRetAddr *)instruction); case IrInstructionIdFloatOp: @@ -6546,11 +6583,11 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false); size_t used_bits = 0; for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { - TypeStructField *field = &type_entry->data.structure.fields[i]; + TypeStructField *field = type_entry->data.structure.fields[i]; if (field->gen_index == SIZE_MAX) { continue; } - LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, &const_val->data.x_struct.fields[i]); + LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, const_val->data.x_struct.fields[i]); uint32_t packed_bits_size = type_size_bits(g, field->type_entry); if (is_big_endian) { LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, packed_bits_size, false); @@ -6625,7 +6662,7 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con return const_val->global_refs->llvm_value; } size_t src_field_index = const_val->data.x_ptr.data.base_struct.field_index; - size_t gen_field_index = struct_const_val->type->data.structure.fields[src_field_index].gen_index; + size_t gen_field_index = struct_const_val->type->data.structure.fields[src_field_index]->gen_index; LLVMValueRef uncasted_ptr_val = gen_const_ptr_struct_recursive(g, struct_const_val, gen_field_index); LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, get_llvm_type(g, const_val->type)); @@ -6804,7 +6841,7 @@ check: switch (const_val->special) { if (type_entry->data.structure.layout == ContainerLayoutPacked) { size_t src_field_index = 0; while (src_field_index < src_field_count) { - TypeStructField *type_struct_field = &type_entry->data.structure.fields[src_field_index]; + TypeStructField *type_struct_field = type_entry->data.structure.fields[src_field_index]; if (type_struct_field->gen_index == SIZE_MAX) { src_field_index += 1; continue; @@ -6812,13 +6849,13 @@ check: switch (const_val->special) { size_t src_field_index_end = src_field_index + 1; for (; src_field_index_end < src_field_count; src_field_index_end += 1) { - TypeStructField *it_field = &type_entry->data.structure.fields[src_field_index_end]; + TypeStructField *it_field = type_entry->data.structure.fields[src_field_index_end]; if (it_field->gen_index != type_struct_field->gen_index) break; } if (src_field_index + 1 == src_field_index_end) { - ConstExprValue *field_val = &const_val->data.x_struct.fields[src_field_index]; + ConstExprValue *field_val = const_val->data.x_struct.fields[src_field_index]; LLVMValueRef val = gen_const_val(g, field_val, ""); fields[type_struct_field->gen_index] = val; make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, field_val->type, val); @@ -6831,12 +6868,12 @@ check: switch (const_val->special) { LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false); size_t used_bits = 0; for (size_t i = src_field_index; i < src_field_index_end; i += 1) { - TypeStructField *it_field = &type_entry->data.structure.fields[i]; + TypeStructField *it_field = type_entry->data.structure.fields[i]; if (it_field->gen_index == SIZE_MAX) { continue; } LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, - &const_val->data.x_struct.fields[i]); + const_val->data.x_struct.fields[i]); uint32_t packed_bits_size = type_size_bits(g, it_field->type_entry); if (is_big_endian) { LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, @@ -6871,11 +6908,11 @@ check: switch (const_val->special) { } } else { for (uint32_t i = 0; i < src_field_count; i += 1) { - TypeStructField *type_struct_field = &type_entry->data.structure.fields[i]; + TypeStructField *type_struct_field = type_entry->data.structure.fields[i]; if (type_struct_field->gen_index == SIZE_MAX) { continue; } - ConstExprValue *field_val = &const_val->data.x_struct.fields[i]; + ConstExprValue *field_val = const_val->data.x_struct.fields[i]; assert(field_val->type != nullptr); if ((err = ensure_const_val_repr(nullptr, g, nullptr, field_val, type_struct_field->type_entry))) @@ -6888,10 +6925,10 @@ check: switch (const_val->special) { make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, field_val->type, val); size_t end_pad_gen_index = (i + 1 < src_field_count) ? - type_entry->data.structure.fields[i + 1].gen_index : + type_entry->data.structure.fields[i + 1]->gen_index : type_entry->data.structure.gen_field_count; size_t next_offset = (i + 1 < src_field_count) ? - type_entry->data.structure.fields[i + 1].offset : type_entry->abi_size; + type_entry->data.structure.fields[i + 1]->offset : type_entry->abi_size; if (end_pad_gen_index != SIZE_MAX) { for (size_t gen_i = type_struct_field->gen_index + 1; gen_i < end_pad_gen_index; gen_i += 1) @@ -7050,16 +7087,12 @@ check: switch (const_val->special) { case ZigTypeIdEnum: return bigint_to_llvm_const(get_llvm_type(g, type_entry), &const_val->data.x_enum_tag); case ZigTypeIdFn: - if (const_val->data.x_ptr.special == ConstPtrSpecialFunction) { - assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst); - return fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry); - } else if (const_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { - LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; - uint64_t addr = const_val->data.x_ptr.data.hard_coded_addr.addr; - return LLVMConstIntToPtr(LLVMConstInt(usize_type_ref, addr, false), get_llvm_type(g, type_entry)); - } else { + if (const_val->data.x_ptr.special == ConstPtrSpecialFunction && + const_val->data.x_ptr.mut != ConstPtrMutComptimeConst) { zig_unreachable(); } + // Treat it the same as we do for pointers + return gen_const_val_ptr(g, const_val, name); case ZigTypeIdPointer: return gen_const_val_ptr(g, const_val, name); case ZigTypeIdErrorUnion: @@ -7558,15 +7591,15 @@ static void do_code_gen(CodeGen *g) { // finishing error return trace setup. we have to do this after all the allocas. if (have_err_ret_trace_stack) { ZigType *usize = g->builtin_types.entry_usize; - size_t index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index; + size_t index_field_index = g->stack_trace_type->data.structure.fields[0]->gen_index; LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val_stack, (unsigned)index_field_index, ""); gen_store_untyped(g, LLVMConstNull(usize->llvm_type), index_field_ptr, 0, false); - size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index; + size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1]->gen_index; LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val_stack, (unsigned)addresses_field_index, ""); - ZigType *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry; - size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index; + ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry; + size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)ptr_field_index, ""); LLVMValueRef zero = LLVMConstNull(usize->llvm_type); LLVMValueRef indices[] = {zero, zero}; @@ -7575,7 +7608,7 @@ static void do_code_gen(CodeGen *g) { ZigType *ptr_ptr_usize_type = get_pointer_to_type(g, get_pointer_to_type(g, usize, false), false); gen_store(g, err_ret_array_val_elem0_ptr, ptr_field_ptr, ptr_ptr_usize_type); - size_t len_field_index = slice_type->data.structure.fields[slice_len_index].gen_index; + size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index; LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)len_field_index, ""); gen_store(g, LLVMConstInt(usize->llvm_type, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false)); } @@ -7692,7 +7725,7 @@ static void do_code_gen(CodeGen *g) { char *error = nullptr; if (LLVMVerifyModule(g->module, LLVMReturnStatusAction, &error)) { - zig_panic("broken LLVM module found: %s", error); + zig_panic("broken LLVM module found: %s\nThis is a bug in the Zig compiler.", error); } } @@ -7821,6 +7854,11 @@ static void define_builtin_types(CodeGen *g) { g->builtin_types.entry_null = entry; } { + ZigType *entry = new_type_table_entry(ZigTypeIdOpaque); + buf_init_from_str(&entry->name, "(var)"); + g->builtin_types.entry_var = entry; + } + { ZigType *entry = new_type_table_entry(ZigTypeIdArgTuple); buf_init_from_str(&entry->name, "(args)"); g->builtin_types.entry_arg_tuple = entry; @@ -8064,6 +8102,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdErrorReturnTrace, "errorReturnTrace", 0); create_builtin_fn(g, BuiltinFnIdAtomicRmw, "atomicRmw", 5); create_builtin_fn(g, BuiltinFnIdAtomicLoad, "atomicLoad", 3); + create_builtin_fn(g, BuiltinFnIdAtomicStore, "atomicStore", 4); create_builtin_fn(g, BuiltinFnIdErrSetCast, "errSetCast", 2); create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1); create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2); @@ -8074,6 +8113,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdFrameType, "Frame", 1); create_builtin_fn(g, BuiltinFnIdFrameAddress, "frameAddress", 0); create_builtin_fn(g, BuiltinFnIdFrameSize, "frameSize", 1); + create_builtin_fn(g, BuiltinFnIdAs, "as", 2); } static const char *bool_to_str(bool b) { @@ -9049,13 +9089,13 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { this_val->parent.id = ConstParentIdArray; this_val->parent.data.p_array.array_val = test_fn_array; this_val->parent.data.p_array.elem_index = i; - this_val->data.x_struct.fields = create_const_vals(2); + this_val->data.x_struct.fields = alloc_const_vals_ptrs(2); - ConstExprValue *name_field = &this_val->data.x_struct.fields[0]; + ConstExprValue *name_field = this_val->data.x_struct.fields[0]; ConstExprValue *name_array_val = create_const_str_lit(g, &test_fn_entry->symbol_name); init_const_slice(g, name_field, name_array_val, 0, buf_len(&test_fn_entry->symbol_name), true); - ConstExprValue *fn_field = &this_val->data.x_struct.fields[1]; + ConstExprValue *fn_field = this_val->data.x_struct.fields[1]; fn_field->type = fn_type; fn_field->special = ConstValSpecialStatic; fn_field->data.x_ptr.special = ConstPtrSpecialFunction; @@ -9483,7 +9523,7 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e return; case ZigTypeIdStruct: for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { - TypeStructField *field = &type_entry->data.structure.fields[i]; + TypeStructField *field = type_entry->data.structure.fields[i]; prepend_c_type_to_decl_list(g, gen_h, field->type_entry); } gen_h->types_to_declare.append(type_entry); @@ -9849,7 +9889,7 @@ static void gen_h_file(CodeGen *g) { if (type_entry->data.structure.layout == ContainerLayoutExtern) { fprintf(out_h, "struct %s {\n", buf_ptr(type_h_name(type_entry))); for (uint32_t field_i = 0; field_i < type_entry->data.structure.src_field_count; field_i += 1) { - TypeStructField *struct_field = &type_entry->data.structure.fields[field_i]; + TypeStructField *struct_field = type_entry->data.structure.fields[field_i]; Buf *type_name_buf = buf_alloc(); get_c_type(g, gen_h, struct_field->type_entry, type_name_buf); diff --git a/src/dump_analysis.cpp b/src/dump_analysis.cpp @@ -268,7 +268,7 @@ static void tree_print_struct(FILE *f, ZigType *struct_type, size_t indent) { ZigList<ZigType *> children = {}; uint64_t sum_from_fields = 0; for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; + TypeStructField *field = struct_type->data.structure.fields[i]; children.append(field->type_entry); sum_from_fields += field->type_entry->abi_size; } @@ -747,7 +747,7 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { if (ty->data.structure.is_slice) { jw_object_field(jw, "len"); jw_int(jw, 2); - anal_dump_pointer_attrs(ctx, ty->data.structure.fields[slice_ptr_index].type_entry); + anal_dump_pointer_attrs(ctx, ty->data.structure.fields[slice_ptr_index]->type_entry); break; } @@ -803,7 +803,7 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { for(size_t i = 0; i < ty->data.structure.src_field_count; i += 1) { jw_array_elem(jw); - anal_dump_type_ref(ctx, ty->data.structure.fields[i].type_entry); + anal_dump_type_ref(ctx, ty->data.structure.fields[i]->type_entry); } jw_end_array(jw); } @@ -1088,6 +1088,7 @@ static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) { break; case NodeTypeContainerDecl: field_nodes = &node->data.container_decl.fields; + doc_comments_buf = &node->data.container_decl.doc_comments; break; default: break; diff --git a/src/ir.cpp b/src/ir.cpp @@ -200,6 +200,13 @@ static IrInstruction *ir_gen_union_init_expr(IrBuilder *irb, Scope *scope, AstNo static void ir_reset_result(ResultLoc *result_loc); static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char *kind_name, Scope *scope, AstNode *source_node, Buf *out_bare_name); +static ResultLocCast *ir_build_cast_result_loc(IrBuilder *irb, IrInstruction *dest_type, + ResultLoc *parent_result_loc); +static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction *source_instr, + TypeStructField *field, IrInstruction *struct_ptr, ZigType *struct_type, bool initializing); +static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name, + IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type); +static ResultLoc *no_result_loc(void); static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) { assert(get_src_ptr_type(const_val->type) != nullptr); @@ -233,7 +240,7 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c case ConstPtrSpecialBaseStruct: { ConstExprValue *struct_val = const_val->data.x_ptr.data.base_struct.struct_val; expand_undef_struct(g, struct_val); - result = &struct_val->data.x_struct.fields[const_val->data.x_ptr.data.base_struct.field_index]; + result = struct_val->data.x_struct.fields[const_val->data.x_ptr.data.base_struct.field_index]; break; } case ConstPtrSpecialBaseErrorUnionCode: @@ -270,7 +277,7 @@ static bool is_slice(ZigType *type) { static bool slice_is_const(ZigType *type) { assert(is_slice(type)); - return type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const; + return type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const; } // This function returns true when you can change the type of a ConstExprValue and the @@ -1003,6 +1010,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicLoad *) { return IrInstructionIdAtomicLoad; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionAtomicStore *) { + return IrInstructionIdAtomicStore; +} + static constexpr IrInstructionId ir_instruction_id(IrInstructionSaveErrRetAddr *) { return IrInstructionIdSaveErrRetAddr; } @@ -1348,18 +1359,17 @@ static IrInstruction *ir_build_return_ptr(IrAnalyze *ira, IrInstruction *source_ static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *array_ptr, IrInstruction *elem_index, bool safety_check_on, PtrLen ptr_len, - IrInstruction *init_array_type) + AstNode *init_array_type_source_node) { IrInstructionElemPtr *instruction = ir_build_instruction<IrInstructionElemPtr>(irb, scope, source_node); instruction->array_ptr = array_ptr; instruction->elem_index = elem_index; instruction->safety_check_on = safety_check_on; instruction->ptr_len = ptr_len; - instruction->init_array_type = init_array_type; + instruction->init_array_type_source_node = init_array_type_source_node; ir_ref_instruction(array_ptr, irb->current_basic_block); ir_ref_instruction(elem_index, irb->current_basic_block); - if (init_array_type != nullptr) ir_ref_instruction(init_array_type, irb->current_basic_block); return &instruction->base; } @@ -1573,17 +1583,16 @@ static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *sour } static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *container_type, size_t item_count, IrInstruction **elem_result_loc_list, - IrInstruction *result_loc) + size_t item_count, IrInstruction **elem_result_loc_list, IrInstruction *result_loc, + AstNode *init_array_type_source_node) { IrInstructionContainerInitList *container_init_list_instruction = ir_build_instruction<IrInstructionContainerInitList>(irb, scope, source_node); - container_init_list_instruction->container_type = container_type; container_init_list_instruction->item_count = item_count; container_init_list_instruction->elem_result_loc_list = elem_result_loc_list; container_init_list_instruction->result_loc = result_loc; + container_init_list_instruction->init_array_type_source_node = init_array_type_source_node; - ir_ref_instruction(container_type, irb->current_basic_block); for (size_t i = 0; i < item_count; i += 1) { ir_ref_instruction(elem_result_loc_list[i], irb->current_basic_block); } @@ -1593,17 +1602,14 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, } static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *container_type, size_t field_count, IrInstructionContainerInitFieldsField *fields, - IrInstruction *result_loc) + size_t field_count, IrInstructionContainerInitFieldsField *fields, IrInstruction *result_loc) { IrInstructionContainerInitFields *container_init_fields_instruction = ir_build_instruction<IrInstructionContainerInitFields>(irb, scope, source_node); - container_init_fields_instruction->container_type = container_type; container_init_fields_instruction->field_count = field_count; container_init_fields_instruction->fields = fields; container_init_fields_instruction->result_loc = result_loc; - ir_ref_instruction(container_type, irb->current_basic_block); for (size_t i = 0; i < field_count; i += 1) { ir_ref_instruction(fields[i].result_loc, irb->current_basic_block); } @@ -2766,6 +2772,18 @@ static IrInstruction *ir_build_load_ptr_gen(IrAnalyze *ira, IrInstruction *sourc return &instruction->base; } +static IrInstruction *ir_build_implicit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction *operand, ResultLocCast *result_loc_cast) +{ + IrInstructionImplicitCast *instruction = ir_build_instruction<IrInstructionImplicitCast>(irb, scope, source_node); + instruction->operand = operand; + instruction->result_loc_cast = result_loc_cast; + + ir_ref_instruction(operand, irb->current_basic_block); + + return &instruction->base; +} + static IrInstruction *ir_build_bit_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *operand, ResultLocBitCast *result_loc_bit_cast) { @@ -3063,20 +3081,6 @@ static IrInstruction *ir_build_align_cast(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstruction *ir_build_implicit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *dest_type, IrInstruction *target, ResultLoc *result_loc) -{ - IrInstructionImplicitCast *instruction = ir_build_instruction<IrInstructionImplicitCast>(irb, scope, source_node); - instruction->dest_type = dest_type; - instruction->target = target; - instruction->result_loc = result_loc; - - ir_ref_instruction(dest_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstNode *source_node, ResultLoc *result_loc, IrInstruction *ty) { @@ -3084,7 +3088,7 @@ static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstN instruction->result_loc = result_loc; instruction->ty = ty; - ir_ref_instruction(ty, irb->current_basic_block); + if (ty != nullptr) ir_ref_instruction(ty, irb->current_basic_block); return &instruction->base; } @@ -3116,11 +3120,12 @@ static IrInstruction *ir_build_set_align_stack(IrBuilder *irb, Scope *scope, Ast } static IrInstruction *ir_build_arg_type(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *fn_type, IrInstruction *arg_index) + IrInstruction *fn_type, IrInstruction *arg_index, bool allow_var) { IrInstructionArgType *instruction = ir_build_instruction<IrInstructionArgType>(irb, scope, source_node); instruction->fn_type = fn_type; instruction->arg_index = arg_index; + instruction->allow_var = allow_var; ir_ref_instruction(fn_type, irb->current_basic_block); ir_ref_instruction(arg_index, irb->current_basic_block); @@ -3187,6 +3192,25 @@ static IrInstruction *ir_build_atomic_load(IrBuilder *irb, Scope *scope, AstNode return &instruction->base; } +static IrInstruction *ir_build_atomic_store(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction *operand_type, IrInstruction *ptr, IrInstruction *value, + IrInstruction *ordering, AtomicOrder resolved_ordering) +{ + IrInstructionAtomicStore *instruction = ir_build_instruction<IrInstructionAtomicStore>(irb, scope, source_node); + instruction->operand_type = operand_type; + instruction->ptr = ptr; + instruction->value = value; + instruction->ordering = ordering; + instruction->resolved_ordering = resolved_ordering; + + if (operand_type != nullptr) ir_ref_instruction(operand_type, irb->current_basic_block); + ir_ref_instruction(ptr, irb->current_basic_block); + ir_ref_instruction(value, irb->current_basic_block); + if (ordering != nullptr) ir_ref_instruction(ordering, irb->current_basic_block); + + return &instruction->base; +} + static IrInstruction *ir_build_save_err_ret_addr(IrBuilder *irb, Scope *scope, AstNode *source_node) { IrInstructionSaveErrRetAddr *instruction = ir_build_instruction<IrInstructionSaveErrRetAddr>(irb, scope, source_node); return &instruction->base; @@ -5374,6 +5398,24 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo IrInstruction *bitcast = ir_build_bit_cast_src(irb, scope, arg1_node, arg1_value, result_loc_bit_cast); return ir_lval_wrap(irb, scope, bitcast, lval, result_loc); } + case BuiltinFnIdAs: + { + AstNode *dest_type_node = node->data.fn_call_expr.params.at(0); + IrInstruction *dest_type = ir_gen_node(irb, dest_type_node, scope); + if (dest_type == irb->codegen->invalid_instruction) + return dest_type; + + ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, dest_type, result_loc); + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstruction *arg1_value = ir_gen_node_extra(irb, arg1_node, scope, LValNone, + &result_loc_cast->base); + if (arg1_value == irb->codegen->invalid_instruction) + return arg1_value; + + IrInstruction *result = ir_build_implicit_cast(irb, scope, node, arg1_value, result_loc_cast); + return ir_lval_wrap(irb, scope, result, lval, result_loc); + } case BuiltinFnIdIntToPtr: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); @@ -5630,7 +5672,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo if (arg1_value == irb->codegen->invalid_instruction) return arg1_value; - IrInstruction *arg_type = ir_build_arg_type(irb, scope, node, arg0_value, arg1_value); + IrInstruction *arg_type = ir_build_arg_type(irb, scope, node, arg0_value, arg1_value, false); return ir_lval_wrap(irb, scope, arg_type, lval, result_loc); } case BuiltinFnIdExport: @@ -5713,6 +5755,33 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo AtomicOrderMonotonic); return ir_lval_wrap(irb, scope, inst, lval, result_loc); } + case BuiltinFnIdAtomicStore: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_instruction) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_instruction) + return arg1_value; + + AstNode *arg2_node = node->data.fn_call_expr.params.at(2); + IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_instruction) + return arg2_value; + + AstNode *arg3_node = node->data.fn_call_expr.params.at(3); + IrInstruction *arg3_value = ir_gen_node(irb, arg3_node, scope); + if (arg3_value == irb->codegen->invalid_instruction) + return arg3_value; + + IrInstruction *inst = ir_build_atomic_store(irb, scope, node, arg0_value, arg1_value, arg2_value, arg3_value, + // this value does not mean anything since we passed non-null values for other arg + AtomicOrderMonotonic); + return ir_lval_wrap(irb, scope, inst, lval, result_loc); + } case BuiltinFnIdIntToEnum: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); @@ -5825,13 +5894,22 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node if (fn_ref == irb->codegen->invalid_instruction) return fn_ref; + IrInstruction *fn_type = ir_build_typeof(irb, scope, node, fn_ref); + size_t arg_count = node->data.fn_call_expr.params.length; IrInstruction **args = allocate<IrInstruction*>(arg_count); for (size_t i = 0; i < arg_count; i += 1) { AstNode *arg_node = node->data.fn_call_expr.params.at(i); - args[i] = ir_gen_node(irb, arg_node, scope); - if (args[i] == irb->codegen->invalid_instruction) - return args[i]; + + IrInstruction *arg_index = ir_build_const_usize(irb, scope, arg_node, i); + IrInstruction *arg_type = ir_build_arg_type(irb, scope, node, fn_type, arg_index, true); + ResultLocCast *result_loc_cast = ir_build_cast_result_loc(irb, arg_type, no_result_loc()); + + IrInstruction *arg = ir_gen_node_extra(irb, arg_node, scope, LValNone, &result_loc_cast->base); + if (arg == irb->codegen->invalid_instruction) + return arg; + + args[i] = ir_build_implicit_cast(irb, scope, arg_node, arg, result_loc_cast); } IrInstruction *fn_call = ir_build_call_src(irb, scope, node, nullptr, fn_ref, arg_count, args, false, @@ -6109,28 +6187,46 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr; ContainerInitKind kind = container_init_expr->kind; - IrInstruction *container_type = nullptr; - IrInstruction *elem_type = nullptr; - if (container_init_expr->type->type == NodeTypeInferredArrayType) { - elem_type = ir_gen_node(irb, container_init_expr->type->data.inferred_array_type.child_type, scope); - if (elem_type == irb->codegen->invalid_instruction) - return elem_type; - } else { - container_type = ir_gen_node(irb, container_init_expr->type, scope); - if (container_type == irb->codegen->invalid_instruction) - return container_type; - } - - switch (kind) { - case ContainerInitKindStruct: { - if (elem_type != nullptr) { + ResultLocCast *result_loc_cast = nullptr; + ResultLoc *child_result_loc; + AstNode *init_array_type_source_node; + if (container_init_expr->type != nullptr) { + IrInstruction *container_type; + if (container_init_expr->type->type == NodeTypeInferredArrayType) { + if (kind == ContainerInitKindStruct) { add_node_error(irb->codegen, container_init_expr->type, buf_sprintf("initializing array with struct syntax")); return irb->codegen->invalid_instruction; } + IrInstruction *elem_type = ir_gen_node(irb, + container_init_expr->type->data.inferred_array_type.child_type, scope); + if (elem_type == irb->codegen->invalid_instruction) + return elem_type; + size_t item_count = container_init_expr->entries.length; + IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count); + container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type); + } else { + container_type = ir_gen_node(irb, container_init_expr->type, scope); + if (container_type == irb->codegen->invalid_instruction) + return container_type; + } - IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc, - container_type); + result_loc_cast = ir_build_cast_result_loc(irb, container_type, parent_result_loc); + child_result_loc = &result_loc_cast->base; + init_array_type_source_node = container_type->source_node; + } else { + child_result_loc = parent_result_loc; + if (parent_result_loc->source_instruction != nullptr) { + init_array_type_source_node = parent_result_loc->source_instruction->source_node; + } else { + init_array_type_source_node = node; + } + } + + switch (kind) { + case ContainerInitKindStruct: { + IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc, + nullptr); size_t field_count = container_init_expr->entries.length; IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count); @@ -6158,29 +6254,27 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A fields[i].source_node = entry_node; fields[i].result_loc = field_ptr; } - IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type, - field_count, fields, container_ptr); + IrInstruction *result = ir_build_container_init_fields(irb, scope, node, field_count, + fields, container_ptr); - return ir_lval_wrap(irb, scope, init_fields, lval, parent_result_loc); + if (result_loc_cast != nullptr) { + result = ir_build_implicit_cast(irb, scope, node, result, result_loc_cast); + } + return ir_lval_wrap(irb, scope, result, lval, parent_result_loc); } case ContainerInitKindArray: { size_t item_count = container_init_expr->entries.length; - if (container_type == nullptr) { - IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count); - container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type); - } - - IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc, - container_type); + IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc, + nullptr); IrInstruction **result_locs = allocate<IrInstruction *>(item_count); for (size_t i = 0; i < item_count; i += 1) { AstNode *expr_node = container_init_expr->entries.at(i); IrInstruction *elem_index = ir_build_const_usize(irb, scope, expr_node, i); - IrInstruction *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, elem_index, - false, PtrLenSingle, container_type); + IrInstruction *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, + elem_index, false, PtrLenSingle, init_array_type_source_node); ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1); result_loc_inst->base.id = ResultLocIdInstruction; result_loc_inst->base.source_instruction = elem_ptr; @@ -6195,9 +6289,12 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A result_locs[i] = elem_ptr; } - IrInstruction *init_list = ir_build_container_init_list(irb, scope, node, container_type, - item_count, result_locs, container_ptr); - return ir_lval_wrap(irb, scope, init_list, lval, parent_result_loc); + IrInstruction *result = ir_build_container_init_list(irb, scope, node, item_count, + result_locs, container_ptr, init_array_type_source_node); + if (result_loc_cast != nullptr) { + result = ir_build_implicit_cast(irb, scope, node, result, result_loc_cast); + } + return ir_lval_wrap(irb, scope, result, lval, parent_result_loc); } } zig_unreachable(); @@ -6214,6 +6311,20 @@ static ResultLocVar *ir_build_var_result_loc(IrBuilder *irb, IrInstruction *allo return result_loc_var; } +static ResultLocCast *ir_build_cast_result_loc(IrBuilder *irb, IrInstruction *dest_type, + ResultLoc *parent_result_loc) +{ + ResultLocCast *result_loc_cast = allocate<ResultLocCast>(1); + result_loc_cast->base.id = ResultLocIdCast; + result_loc_cast->base.source_instruction = dest_type; + ir_ref_instruction(dest_type, irb->current_basic_block); + result_loc_cast->parent = parent_result_loc; + + ir_build_reset_result(irb, dest_type->scope, dest_type->source_node, &result_loc_cast->base); + + return result_loc_cast; +} + static void build_decl_var_and_init(IrBuilder *irb, Scope *scope, AstNode *source_node, ZigVar *var, IrInstruction *init, const char *name_hint, IrInstruction *is_comptime) { @@ -6282,7 +6393,15 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod // Create a result location for the initialization expression. ResultLocVar *result_loc_var = ir_build_var_result_loc(irb, alloca, var); - ResultLoc *init_result_loc = (type_instruction == nullptr) ? &result_loc_var->base : nullptr; + ResultLoc *init_result_loc; + ResultLocCast *result_loc_cast; + if (type_instruction != nullptr) { + result_loc_cast = ir_build_cast_result_loc(irb, type_instruction, &result_loc_var->base); + init_result_loc = &result_loc_cast->base; + } else { + result_loc_cast = nullptr; + init_result_loc = &result_loc_var->base; + } Scope *init_scope = is_comptime_scalar ? create_comptime_scope(irb->codegen, variable_declaration->expr, scope) : scope; @@ -6298,9 +6417,9 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod if (init_value == irb->codegen->invalid_instruction) return irb->codegen->invalid_instruction; - if (type_instruction != nullptr) { - IrInstruction *implicit_cast = ir_build_implicit_cast(irb, scope, node, type_instruction, init_value, - &result_loc_var->base); + if (result_loc_cast != nullptr) { + IrInstruction *implicit_cast = ir_build_implicit_cast(irb, scope, init_value->source_node, + init_value, result_loc_cast); ir_build_end_expr(irb, scope, node, implicit_cast, &result_loc_var->base); } @@ -7895,14 +8014,14 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char *kind_name, Scope *scope, AstNode *source_node, Buf *out_bare_name) { - if (exec->name) { + if (exec != nullptr && exec->name) { ZigType *import = get_scope_import(scope); Buf *namespace_name = buf_alloc(); append_namespace_qualification(codegen, namespace_name, import); buf_append_buf(namespace_name, exec->name); buf_init_from_buf(out_bare_name, exec->name); return namespace_name; - } else if (exec->name_fn != nullptr) { + } else if (exec != nullptr && exec->name_fn != nullptr) { Buf *name = buf_alloc(); buf_append_buf(name, &exec->name_fn->symbol_name); buf_appendf(name, "("); @@ -8009,7 +8128,6 @@ static ZigType *get_error_set_union(CodeGen *g, ErrorTableEntry **errors, ZigTyp } } assert(index == count); - assert(count != 0); if (type_name == nullptr) { buf_appendf(&err_set_type->name, "}"); @@ -9571,7 +9689,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc } ir_add_error(ira, instruction, - buf_sprintf("%s value %s cannot be implicitly casted to type '%s'", + buf_sprintf("%s value %s cannot be coerced to type '%s'", num_lit_str, buf_ptr(val_buf), buf_ptr(&other_type->name))); @@ -9739,8 +9857,8 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted // slice const if (is_slice(wanted_type) && is_slice(actual_type)) { - ZigType *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry; - ZigType *wanted_ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index]->type_entry; + ZigType *wanted_ptr_type = wanted_type->data.structure.fields[slice_ptr_index]->type_entry; if ((err = type_resolve(g, actual_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) { result.id = ConstCastResultIdInvalid; return result; @@ -10494,22 +10612,67 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT continue; } + // *[N]T to []T + // *[N]T to E![]T + if (cur_type->id == ZigTypeIdPointer && + cur_type->data.pointer.child_type->id == ZigTypeIdArray && + ((prev_type->id == ZigTypeIdErrorUnion && is_slice(prev_type->data.error_union.payload_type)) || + is_slice(prev_type))) + { + ZigType *array_type = cur_type->data.pointer.child_type; + ZigType *slice_type = (prev_type->id == ZigTypeIdErrorUnion) ? + prev_type->data.error_union.payload_type : prev_type; + ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry; + if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0) && + types_match_const_cast_only(ira, + slice_ptr_type->data.pointer.child_type, + array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk) + { + convert_to_const_slice = false; + continue; + } + } + + // *[N]T to []T + // *[N]T to E![]T + if (prev_type->id == ZigTypeIdPointer && + prev_type->data.pointer.child_type->id == ZigTypeIdArray && + ((cur_type->id == ZigTypeIdErrorUnion && is_slice(cur_type->data.error_union.payload_type)) || + is_slice(cur_type))) + { + ZigType *array_type = prev_type->data.pointer.child_type; + ZigType *slice_type = (cur_type->id == ZigTypeIdErrorUnion) ? + cur_type->data.error_union.payload_type : cur_type; + ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry; + if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0) && + types_match_const_cast_only(ira, + slice_ptr_type->data.pointer.child_type, + array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk) + { + prev_inst = cur_inst; + convert_to_const_slice = false; + continue; + } + } + + // [N]T to []T if (cur_type->id == ZigTypeIdArray && is_slice(prev_type) && - (prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const || + (prev_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const || cur_type->data.array.len == 0) && types_match_const_cast_only(ira, - prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type, + prev_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.child_type, cur_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk) { convert_to_const_slice = false; continue; } + // [N]T to []T if (prev_type->id == ZigTypeIdArray && is_slice(cur_type) && - (cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const || + (cur_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const || prev_type->data.array.len == 0) && types_match_const_cast_only(ira, - cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type, + cur_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.child_type, prev_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk) { prev_inst = cur_inst; @@ -10620,9 +10783,9 @@ static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_ if (src->special != ConstValSpecialStatic) return; if (dest->type->id == ZigTypeIdStruct) { - dest->data.x_struct.fields = create_const_vals(dest->type->data.structure.src_field_count); + dest->data.x_struct.fields = alloc_const_vals_ptrs(dest->type->data.structure.src_field_count); for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) { - copy_const_val(&dest->data.x_struct.fields[i], &src->data.x_struct.fields[i], false); + copy_const_val(dest->data.x_struct.fields[i], src->data.x_struct.fields[i], false); } } } @@ -10814,12 +10977,11 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc assert(value->value.type->id == ZigTypeIdPointer); ZigType *array_type = value->value.type->data.pointer.child_type; assert(is_slice(wanted_type)); - bool is_const = wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const; + bool is_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const; IrInstruction *result = ir_const(ira, source_instr, wanted_type); init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const); - result->value.data.x_struct.fields[slice_ptr_index].data.x_ptr.mut = - value->value.data.x_ptr.mut; + result->value.data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = value->value.data.x_ptr.mut; result->value.type = wanted_type; return result; } @@ -12401,6 +12563,27 @@ static IrInstruction *ir_analyze_enum_literal(IrAnalyze *ira, IrInstruction *sou return result; } +static IrInstruction *ir_analyze_struct_literal_to_array(IrAnalyze *ira, IrInstruction *source_instr, + IrInstruction *value, ZigType *wanted_type) +{ + ir_add_error(ira, source_instr, buf_sprintf("TODO: type coercion of anon list literal to array")); + return ira->codegen->invalid_instruction; +} + +static IrInstruction *ir_analyze_struct_literal_to_struct(IrAnalyze *ira, IrInstruction *source_instr, + IrInstruction *value, ZigType *wanted_type) +{ + ir_add_error(ira, source_instr, buf_sprintf("TODO: type coercion of anon struct literal to struct")); + return ira->codegen->invalid_instruction; +} + +static IrInstruction *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInstruction *source_instr, + IrInstruction *value, ZigType *wanted_type) +{ + ir_add_error(ira, source_instr, buf_sprintf("TODO: type coercion of anon struct literal to union")); + return ira->codegen->invalid_instruction; +} + static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, ZigType *wanted_type, IrInstruction *value, ResultLoc *result_loc) { @@ -12412,6 +12595,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst return ira->codegen->invalid_instruction; } + // This means the wanted type is anything. + if (wanted_type == ira->codegen->builtin_types.entry_var) { + return value; + } + // perfect match or non-const to const ConstCastOnly const_cast_result = types_match_const_cast_only(ira, wanted_type, actual_type, source_node, false); @@ -12586,7 +12774,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst // cast from [N]T to []const T // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) { - ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index]->type_entry; assert(ptr_type->id == ZigTypeIdPointer); if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) && types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type, @@ -12603,7 +12791,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst actual_type->id == ZigTypeIdArray) { ZigType *ptr_type = - wanted_type->data.maybe.child_type->data.structure.fields[slice_ptr_index].type_entry; + wanted_type->data.maybe.child_type->data.structure.fields[slice_ptr_index]->type_entry; assert(ptr_type->id == ZigTypeIdPointer); if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) && types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type, @@ -12642,12 +12830,71 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst } // *[N]T to []T - if (is_slice(wanted_type) && + // *[N]T to E![]T + if ((is_slice(wanted_type) || + (wanted_type->id == ZigTypeIdErrorUnion && + is_slice(wanted_type->data.error_union.payload_type))) && actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenSingle && actual_type->data.pointer.child_type->id == ZigTypeIdArray) { - ZigType *slice_ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *slice_type = (wanted_type->id == ZigTypeIdErrorUnion) ? + wanted_type->data.error_union.payload_type : wanted_type; + ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry; + assert(slice_ptr_type->id == ZigTypeIdPointer); + ZigType *array_type = actual_type->data.pointer.child_type; + bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 + || !actual_type->data.pointer.is_const); + if (const_ok && types_match_const_cast_only(ira, slice_ptr_type->data.pointer.child_type, + array_type->data.array.child_type, source_node, + !slice_ptr_type->data.pointer.is_const).id == ConstCastResultIdOk) + { + // If the pointers both have ABI align, it works. + // Or if the array length is 0, alignment doesn't matter. + bool ok_align = array_type->data.array.len == 0 || + (slice_ptr_type->data.pointer.explicit_alignment == 0 && + actual_type->data.pointer.explicit_alignment == 0); + if (!ok_align) { + // If either one has non ABI align, we have to resolve them both + if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, + ResolveStatusAlignmentKnown))) + { + return ira->codegen->invalid_instruction; + } + if ((err = type_resolve(ira->codegen, slice_ptr_type->data.pointer.child_type, + ResolveStatusAlignmentKnown))) + { + return ira->codegen->invalid_instruction; + } + ok_align = get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, slice_ptr_type); + } + if (ok_align) { + if (wanted_type->id == ZigTypeIdErrorUnion) { + IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, slice_type, value, nullptr); + if (type_is_invalid(cast1->value.type)) + return ira->codegen->invalid_instruction; + + IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1, result_loc); + if (type_is_invalid(cast2->value.type)) + return ira->codegen->invalid_instruction; + + return cast2; + } else { + return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, slice_type, result_loc); + } + } + } + } + + // *[N]T to E![]T + if (wanted_type->id == ZigTypeIdErrorUnion && + is_slice(wanted_type->data.error_union.payload_type) && + actual_type->id == ZigTypeIdPointer && + actual_type->data.pointer.ptr_len == PtrLenSingle && + actual_type->data.pointer.child_type->id == ZigTypeIdArray) + { + ZigType *slice_type = wanted_type->data.error_union.payload_type; + ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry; assert(slice_ptr_type->id == ZigTypeIdPointer); ZigType *array_type = actual_type->data.pointer.child_type; bool const_ok = (slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 @@ -12674,7 +12921,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst ok_align = get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, slice_ptr_type); } if (ok_align) { - return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, wanted_type, result_loc); + return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, slice_type, result_loc); } } } @@ -12724,7 +12971,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst actual_type->id == ZigTypeIdArray) { ZigType *ptr_type = - wanted_type->data.error_union.payload_type->data.structure.fields[slice_ptr_index].type_entry; + wanted_type->data.error_union.payload_type->data.structure.fields[slice_ptr_index]->type_entry; assert(ptr_type->id == ZigTypeIdPointer); if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) && types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type, @@ -12909,6 +13156,25 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst return ir_analyze_int_to_c_ptr(ira, source_instr, value, wanted_type); } + // cast from inferred struct type to array, union, or struct + if (actual_type->id == ZigTypeIdStruct && actual_type->data.structure.is_inferred) { + AstNode *decl_node = actual_type->data.structure.decl_node; + ir_assert(decl_node->type == NodeTypeContainerInitExpr, source_instr); + ContainerInitKind init_kind = decl_node->data.container_init_expr.kind; + uint32_t field_count = actual_type->data.structure.src_field_count; + if (wanted_type->id == ZigTypeIdArray && (init_kind == ContainerInitKindArray || field_count == 0) && + wanted_type->data.array.len == field_count) + { + return ir_analyze_struct_literal_to_array(ira, source_instr, value, wanted_type); + } else if (wanted_type->id == ZigTypeIdStruct && + (init_kind == ContainerInitKindStruct || field_count == 0)) + { + return ir_analyze_struct_literal_to_struct(ira, source_instr, value, wanted_type); + } else if (wanted_type->id == ZigTypeIdUnion && init_kind == ContainerInitKindStruct && field_count == 1) { + return ir_analyze_struct_literal_to_union(ira, source_instr, value, wanted_type); + } + } + // cast from undefined to anything if (actual_type->id == ZigTypeIdUndefined) { return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type); @@ -12922,8 +13188,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst return ira->codegen->invalid_instruction; } -static IrInstruction *ir_implicit_cast_with_result(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type, - ResultLoc *result_loc) +static IrInstruction *ir_implicit_cast_with_result(IrAnalyze *ira, IrInstruction *source_instr, + IrInstruction *value, ZigType *expected_type, ResultLoc *result_loc) { assert(value); assert(value != ira->codegen->invalid_instruction); @@ -12937,11 +13203,11 @@ static IrInstruction *ir_implicit_cast_with_result(IrAnalyze *ira, IrInstruction if (value->value.type->id == ZigTypeIdUnreachable) return value; - return ir_analyze_cast(ira, value, expected_type, value, result_loc); + return ir_analyze_cast(ira, source_instr, expected_type, value, result_loc); } static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type) { - return ir_implicit_cast_with_result(ira, value, expected_type, nullptr); + return ir_implicit_cast_with_result(ira, value, value, expected_type, nullptr); } static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr, @@ -13223,8 +13489,8 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { if (!const_val) return nullptr; - ConstExprValue *ptr_field = &const_val->data.x_struct.fields[slice_ptr_index]; - ConstExprValue *len_field = &const_val->data.x_struct.fields[slice_len_index]; + ConstExprValue *ptr_field = const_val->data.x_struct.fields[slice_ptr_index]; + ConstExprValue *len_field = const_val->data.x_struct.fields[slice_len_index]; assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray); ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val; @@ -13269,16 +13535,6 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio if (type_is_invalid(operand->value.type)) return ir_unreach_error(ira); - if (!instr_is_comptime(operand) && ira->explicit_return_type != nullptr && - handle_is_ptr(ira->explicit_return_type)) - { - // result location mechanism took care of it. - IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, nullptr); - result->value.type = ira->codegen->builtin_types.entry_unreachable; - return ir_finish_anal(ira, result); - } - IrInstruction *casted_operand = ir_implicit_cast(ira, operand, ira->explicit_return_type); if (type_is_invalid(casted_operand->value.type)) { AstNode *source_node = ira->explicit_return_type_source_node; @@ -13290,6 +13546,16 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio return ir_unreach_error(ira); } + if (!instr_is_comptime(operand) && ira->explicit_return_type != nullptr && + handle_is_ptr(ira->explicit_return_type)) + { + // result location mechanism took care of it. + IrInstruction *result = ir_build_return(&ira->new_irb, instruction->base.scope, + instruction->base.source_node, nullptr); + result->value.type = ira->codegen->builtin_types.entry_unreachable; + return ir_finish_anal(ira, result); + } + if (casted_operand->value.special == ConstValSpecialRuntime && casted_operand->value.type->id == ZigTypeIdPointer && casted_operand->value.data.rh_ptr == RuntimeHintPtrStack) @@ -14550,13 +14816,13 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i op1_array_index = op1_val->data.x_ptr.data.base_array.elem_index; op1_array_end = op1_array_val->type->data.array.len - 1; } else if (is_slice(op1_type)) { - ZigType *ptr_type = op1_type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *ptr_type = op1_type->data.structure.fields[slice_ptr_index]->type_entry; child_type = ptr_type->data.pointer.child_type; - ConstExprValue *ptr_val = &op1_val->data.x_struct.fields[slice_ptr_index]; + ConstExprValue *ptr_val = op1_val->data.x_struct.fields[slice_ptr_index]; assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray); op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val; op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index; - ConstExprValue *len_val = &op1_val->data.x_struct.fields[slice_len_index]; + ConstExprValue *len_val = op1_val->data.x_struct.fields[slice_len_index]; op1_array_end = op1_array_index + bigint_as_usize(&len_val->data.x_bigint); } else { ir_add_error(ira, op1, @@ -14583,13 +14849,13 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index; op2_array_end = op2_array_val->type->data.array.len - 1; } else if (is_slice(op2_type)) { - ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index]->type_entry; op2_type_valid = ptr_type->data.pointer.child_type == child_type; - ConstExprValue *ptr_val = &op2_val->data.x_struct.fields[slice_ptr_index]; + ConstExprValue *ptr_val = op2_val->data.x_struct.fields[slice_ptr_index]; assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray); op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val; op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index; - ConstExprValue *len_val = &op2_val->data.x_struct.fields[slice_len_index]; + ConstExprValue *len_val = op2_val->data.x_struct.fields[slice_len_index]; op2_array_end = op2_array_index + bigint_as_usize(&len_val->data.x_bigint); } else { ir_add_error(ira, op2, @@ -14621,17 +14887,17 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i out_array_val->special = ConstValSpecialStatic; out_array_val->type = get_array_type(ira->codegen, child_type, new_len); - out_val->data.x_struct.fields = create_const_vals(2); + out_val->data.x_struct.fields = alloc_const_vals_ptrs(2); - out_val->data.x_struct.fields[slice_ptr_index].type = ptr_type; - out_val->data.x_struct.fields[slice_ptr_index].special = ConstValSpecialStatic; - out_val->data.x_struct.fields[slice_ptr_index].data.x_ptr.special = ConstPtrSpecialBaseArray; - out_val->data.x_struct.fields[slice_ptr_index].data.x_ptr.data.base_array.array_val = out_array_val; - out_val->data.x_struct.fields[slice_ptr_index].data.x_ptr.data.base_array.elem_index = 0; + out_val->data.x_struct.fields[slice_ptr_index]->type = ptr_type; + out_val->data.x_struct.fields[slice_ptr_index]->special = ConstValSpecialStatic; + out_val->data.x_struct.fields[slice_ptr_index]->data.x_ptr.special = ConstPtrSpecialBaseArray; + out_val->data.x_struct.fields[slice_ptr_index]->data.x_ptr.data.base_array.array_val = out_array_val; + out_val->data.x_struct.fields[slice_ptr_index]->data.x_ptr.data.base_array.elem_index = 0; - out_val->data.x_struct.fields[slice_len_index].type = ira->codegen->builtin_types.entry_usize; - out_val->data.x_struct.fields[slice_len_index].special = ConstValSpecialStatic; - bigint_init_unsigned(&out_val->data.x_struct.fields[slice_len_index].data.x_bigint, new_len); + out_val->data.x_struct.fields[slice_len_index]->type = ira->codegen->builtin_types.entry_usize; + out_val->data.x_struct.fields[slice_len_index]->special = ConstValSpecialStatic; + bigint_init_unsigned(&out_val->data.x_struct.fields[slice_len_index]->data.x_bigint, new_len); } else { new_len += 1; // null byte @@ -15295,15 +15561,16 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in result->base.value.data.x_ptr.mut = force_comptime ? ConstPtrMutComptimeVar : ConstPtrMutInfer; result->base.value.data.x_ptr.data.ref.pointee = pointee; - if ((err = type_resolve(ira->codegen, var_type, ResolveStatusZeroBitsKnown))) + bool var_type_has_bits; + if ((err = type_has_bits2(ira->codegen, var_type, &var_type_has_bits))) return ira->codegen->invalid_instruction; if (align != 0) { if ((err = type_resolve(ira->codegen, var_type, ResolveStatusAlignmentKnown))) return ira->codegen->invalid_instruction; - if (!type_has_bits(var_type)) { - ir_add_error(ira, source_inst, - buf_sprintf("variable '%s' of zero-bit type '%s' has no in-memory representation, it cannot be aligned", - name_hint, buf_ptr(&var_type->name))); + if (!var_type_has_bits) { + ir_add_error(ira, source_inst, + buf_sprintf("variable '%s' of zero-bit type '%s' has no in-memory representation, it cannot be aligned", + name_hint, buf_ptr(&var_type->name))); return ira->codegen->invalid_instruction; } } @@ -15331,6 +15598,7 @@ static ZigType *ir_result_loc_expected_type(IrAnalyze *ira, IrInstruction *suspe case ResultLocIdNone: case ResultLocIdVar: case ResultLocIdBitCast: + case ResultLocIdCast: return nullptr; case ResultLocIdInstruction: return result_loc->source_instruction->child->value.type; @@ -15374,24 +15642,51 @@ static void set_up_result_loc_for_inferred_comptime(IrInstruction *ptr) { ptr->value.data.x_ptr.data.ref.pointee = undef_child; } -static bool ir_result_has_type(ResultLoc *result_loc) { +static Error ir_result_has_type(IrAnalyze *ira, ResultLoc *result_loc, bool *out) { switch (result_loc->id) { case ResultLocIdInvalid: case ResultLocIdPeerParent: zig_unreachable(); case ResultLocIdNone: case ResultLocIdPeer: - return false; + *out = false; + return ErrorNone; case ResultLocIdReturn: case ResultLocIdInstruction: case ResultLocIdBitCast: - return true; + *out = true; + return ErrorNone; + case ResultLocIdCast: { + ResultLocCast *result_cast = reinterpret_cast<ResultLocCast *>(result_loc); + ZigType *dest_type = ir_resolve_type(ira, result_cast->base.source_instruction->child); + if (type_is_invalid(dest_type)) + return ErrorSemanticAnalyzeFail; + *out = (dest_type != ira->codegen->builtin_types.entry_var); + return ErrorNone; + } case ResultLocIdVar: - return reinterpret_cast<ResultLocVar *>(result_loc)->var->decl_node->data.variable_declaration.type != nullptr; + *out = reinterpret_cast<ResultLocVar *>(result_loc)->var->decl_node->data.variable_declaration.type != nullptr; + return ErrorNone; } zig_unreachable(); } +static IrInstruction *ir_resolve_no_result_loc(IrAnalyze *ira, IrInstruction *suspend_source_instr, + ResultLoc *result_loc, ZigType *value_type, bool force_runtime, bool non_null_comptime) +{ + IrInstructionAllocaGen *alloca_gen = ir_build_alloca_gen(ira, suspend_source_instr, 0, ""); + alloca_gen->base.value.type = get_pointer_to_type_extra(ira->codegen, value_type, false, false, + PtrLenSingle, 0, 0, 0, false); + set_up_result_loc_for_inferred_comptime(&alloca_gen->base); + ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); + if (fn_entry != nullptr && get_scope_typeof(suspend_source_instr->scope) == nullptr) { + fn_entry->alloca_gen_list.append(alloca_gen); + } + result_loc->written = true; + result_loc->resolved_loc = &alloca_gen->base; + return result_loc->resolved_loc; +} + // when calling this function, at the callsite must check for result type noreturn and propagate it up static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspend_source_instr, ResultLoc *result_loc, ZigType *value_type, IrInstruction *value, bool force_runtime, bool non_null_comptime) @@ -15414,19 +15709,8 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe return nullptr; } // need to return a result location and don't have one. use a stack allocation - IrInstructionAllocaGen *alloca_gen = ir_build_alloca_gen(ira, suspend_source_instr, 0, ""); - if ((err = type_resolve(ira->codegen, value_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; - alloca_gen->base.value.type = get_pointer_to_type_extra(ira->codegen, value_type, false, false, - PtrLenSingle, 0, 0, 0, false); - set_up_result_loc_for_inferred_comptime(&alloca_gen->base); - ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); - if (fn_entry != nullptr && get_scope_typeof(suspend_source_instr->scope) == nullptr) { - fn_entry->alloca_gen_list.append(alloca_gen); - } - result_loc->written = true; - result_loc->resolved_loc = &alloca_gen->base; - return result_loc->resolved_loc; + return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type, + force_runtime, non_null_comptime); } case ResultLocIdVar: { ResultLocVar *result_loc_var = reinterpret_cast<ResultLocVar *>(result_loc); @@ -15529,7 +15813,10 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe } return nullptr; } - if (ir_result_has_type(peer_parent->parent)) { + bool peer_parent_has_type; + if ((err = ir_result_has_type(ira, peer_parent->parent, &peer_parent_has_type))) + return ira->codegen->invalid_instruction; + if (peer_parent_has_type) { if (peer_parent->parent->id == ResultLocIdReturn && value != nullptr) { reinterpret_cast<ResultLocReturn *>(peer_parent->parent)->implicit_return_type_done = true; ira->src_implicit_return_type_list.append(value); @@ -15564,6 +15851,89 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe result_loc->resolved_loc = parent_result_loc; return result_loc->resolved_loc; } + case ResultLocIdCast: { + if (value != nullptr && value->value.special != ConstValSpecialRuntime) + return nullptr; + ResultLocCast *result_cast = reinterpret_cast<ResultLocCast *>(result_loc); + ZigType *dest_type = ir_resolve_type(ira, result_cast->base.source_instruction->child); + if (type_is_invalid(dest_type)) + return ira->codegen->invalid_instruction; + + if (dest_type == ira->codegen->builtin_types.entry_var) { + return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type, + force_runtime, non_null_comptime); + } + + ConstCastOnly const_cast_result = types_match_const_cast_only(ira, dest_type, value_type, + result_cast->base.source_instruction->source_node, false); + if (const_cast_result.id == ConstCastResultIdInvalid) + return ira->codegen->invalid_instruction; + if (const_cast_result.id != ConstCastResultIdOk) { + // We will not be able to provide a result location for this value. Create + // a new result location. + return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type, + force_runtime, non_null_comptime); + } + + // In this case we can pointer cast the result location. + IrInstruction *casted_value; + if (value != nullptr) { + casted_value = ir_implicit_cast(ira, value, dest_type); + } else { + casted_value = nullptr; + } + + if (casted_value != nullptr && type_is_invalid(casted_value->value.type)) { + return casted_value; + } + + bool old_parent_result_loc_written = result_cast->parent->written; + IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_cast->parent, + dest_type, casted_value, force_runtime, non_null_comptime, true); + if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) || + parent_result_loc->value.type->id == ZigTypeIdUnreachable) + { + return parent_result_loc; + } + ZigType *parent_ptr_type = parent_result_loc->value.type; + assert(parent_ptr_type->id == ZigTypeIdPointer); + if ((err = type_resolve(ira->codegen, parent_ptr_type->data.pointer.child_type, + ResolveStatusAlignmentKnown))) + { + return ira->codegen->invalid_instruction; + } + uint64_t parent_ptr_align = get_ptr_align(ira->codegen, parent_ptr_type); + if ((err = type_resolve(ira->codegen, value_type, ResolveStatusAlignmentKnown))) { + return ira->codegen->invalid_instruction; + } + if (!type_has_bits(value_type)) { + parent_ptr_align = 0; + } + ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value_type, + parent_ptr_type->data.pointer.is_const, parent_ptr_type->data.pointer.is_volatile, PtrLenSingle, + parent_ptr_align, 0, 0, parent_ptr_type->data.pointer.allow_zero); + + { + // we also need to check that this cast is OK. + ConstCastOnly const_cast_result = types_match_const_cast_only(ira, + parent_result_loc->value.type, ptr_type, + result_cast->base.source_instruction->source_node, false); + if (const_cast_result.id == ConstCastResultIdInvalid) + return ira->codegen->invalid_instruction; + if (const_cast_result.id != ConstCastResultIdOk) { + // We will not be able to provide a result location for this value. Create + // a new result location. + result_cast->parent->written = old_parent_result_loc_written; + return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type, + force_runtime, non_null_comptime); + } + } + + result_loc->written = true; + result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc, + ptr_type, result_cast->base.source_instruction, false); + return result_loc->resolved_loc; + } case ResultLocIdBitCast: { ResultLocBitCast *result_bit_cast = reinterpret_cast<ResultLocBitCast *>(result_loc); ZigType *dest_type = ir_resolve_type(ira, result_bit_cast->base.source_instruction->child); @@ -15686,22 +16056,40 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s return result_loc; } -static IrInstruction *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrInstructionImplicitCast *instruction) { - ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child); - if (type_is_invalid(dest_type)) - return ira->codegen->invalid_instruction; - - IrInstruction *target = instruction->target->child; - if (type_is_invalid(target->value.type)) - return ira->codegen->invalid_instruction; - - return ir_implicit_cast_with_result(ira, target, dest_type, instruction->result_loc); -} +static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, + IrInstructionResolveResult *instruction) +{ + ZigType *implicit_elem_type; + if (instruction->ty == nullptr) { + if (instruction->result_loc->id == ResultLocIdCast) { + implicit_elem_type = ir_resolve_type(ira, + instruction->result_loc->source_instruction->child); + if (type_is_invalid(implicit_elem_type)) + return ira->codegen->invalid_instruction; + } else if (instruction->result_loc->id == ResultLocIdReturn) { + implicit_elem_type = ira->explicit_return_type; + if (type_is_invalid(implicit_elem_type)) + return ira->codegen->invalid_instruction; + } else { + implicit_elem_type = ira->codegen->builtin_types.entry_var; + } + if (implicit_elem_type == ira->codegen->builtin_types.entry_var) { + Buf *bare_name = buf_alloc(); + Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct), + instruction->base.scope, instruction->base.source_node, bare_name); -static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrInstructionResolveResult *instruction) { - ZigType *implicit_elem_type = ir_resolve_type(ira, instruction->ty->child); - if (type_is_invalid(implicit_elem_type)) - return ira->codegen->invalid_instruction; + ZigType *inferred_struct_type = get_partial_container_type(ira->codegen, + instruction->base.scope, ContainerKindStruct, instruction->base.source_node, + buf_ptr(name), bare_name, ContainerLayoutAuto); + inferred_struct_type->data.structure.is_inferred = true; + inferred_struct_type->data.structure.resolve_status = ResolveStatusBeingInferred; + implicit_elem_type = inferred_struct_type; + } + } else { + implicit_elem_type = ir_resolve_type(ira, instruction->ty->child); + if (type_is_invalid(implicit_elem_type)) + return ira->codegen->invalid_instruction; + } IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc, implicit_elem_type, nullptr, false, true, true); if (result_loc != nullptr) @@ -15760,6 +16148,7 @@ static void ir_reset_result(ResultLoc *result_loc) { case ResultLocIdNone: case ResultLocIdInstruction: case ResultLocIdBitCast: + case ResultLocIdCast: break; } } @@ -16062,13 +16451,63 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source return ir_const_void(ira, source_instr); } - ZigType *child_type = ptr->value.type->data.pointer.child_type; + InferredStructField *isf = ptr->value.type->data.pointer.inferred_struct_field; + if (allow_write_through_const && isf != nullptr) { + // Now it's time to add the field to the struct type. + uint32_t old_field_count = isf->inferred_struct_type->data.structure.src_field_count; + uint32_t new_field_count = old_field_count + 1; + isf->inferred_struct_type->data.structure.src_field_count = new_field_count; + isf->inferred_struct_type->data.structure.fields = realloc_type_struct_fields( + isf->inferred_struct_type->data.structure.fields, old_field_count, new_field_count); + + TypeStructField *field = isf->inferred_struct_type->data.structure.fields[old_field_count]; + field->name = isf->field_name; + field->type_entry = uncasted_value->value.type; + field->type_val = create_const_type(ira->codegen, field->type_entry); + field->src_index = old_field_count; + field->decl_node = uncasted_value->source_node; + + ZigType *struct_ptr_type = get_pointer_to_type(ira->codegen, isf->inferred_struct_type, false); + IrInstruction *casted_ptr; + if (instr_is_comptime(ptr)) { + casted_ptr = ir_const(ira, source_instr, struct_ptr_type); + copy_const_val(&casted_ptr->value, &ptr->value, false); + casted_ptr->value.type = struct_ptr_type; + } else { + casted_ptr = ir_build_cast(&ira->new_irb, source_instr->scope, + source_instr->source_node, struct_ptr_type, ptr, CastOpNoop); + casted_ptr->value.type = struct_ptr_type; + } + if (instr_is_comptime(casted_ptr)) { + ConstExprValue *ptr_val = ir_resolve_const(ira, casted_ptr, UndefBad); + if (!ptr_val) + return ira->codegen->invalid_instruction; + if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { + ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, + source_instr->source_node); + struct_val->special = ConstValSpecialStatic; + struct_val->data.x_struct.fields = realloc_const_vals_ptrs(struct_val->data.x_struct.fields, + old_field_count, new_field_count); + + ConstExprValue *field_val = struct_val->data.x_struct.fields[old_field_count]; + field_val->special = ConstValSpecialUndef; + field_val->type = field->type_entry; + field_val->parent.id = ConstParentIdStruct; + field_val->parent.data.p_struct.struct_val = struct_val; + field_val->parent.data.p_struct.field_index = old_field_count; + } + } + + ptr = ir_analyze_struct_field_ptr(ira, source_instr, field, casted_ptr, + isf->inferred_struct_type, true); + } if (ptr->value.type->data.pointer.is_const && !allow_write_through_const) { ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); return ira->codegen->invalid_instruction; } + ZigType *child_type = ptr->value.type->data.pointer.child_type; IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type); if (value == ira->codegen->invalid_instruction) return ira->codegen->invalid_instruction; @@ -16799,25 +17238,14 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC if (is_comptime || instr_is_comptime(fn_ref)) { if (fn_ref->value.type->id == ZigTypeIdMetaType) { - ZigType *dest_type = ir_resolve_type(ira, fn_ref); - if (type_is_invalid(dest_type)) - return ira->codegen->invalid_instruction; - - size_t actual_param_count = call_instruction->arg_count; - - if (actual_param_count != 1) { - ir_add_error_node(ira, call_instruction->base.source_node, - buf_sprintf("cast expression expects exactly one parameter")); + ZigType *ty = ir_resolve_type(ira, fn_ref); + if (ty == nullptr) return ira->codegen->invalid_instruction; - } - - IrInstruction *arg = call_instruction->args[0]->child; - - IrInstruction *cast_instruction = ir_analyze_cast(ira, &call_instruction->base, dest_type, arg, - call_instruction->result_loc); - if (type_is_invalid(cast_instruction->value.type)) - return ira->codegen->invalid_instruction; - return ir_finish_anal(ira, cast_instruction); + ErrorMsg *msg = ir_add_error_node(ira, fn_ref->source_node, + buf_sprintf("type '%s' not a function", buf_ptr(&ty->name))); + add_error_note(ira->codegen, msg, call_instruction->base.source_node, + buf_sprintf("use @as builtin for type coercion")); + return ira->codegen->invalid_instruction; } else if (fn_ref->value.type->id == ZigTypeIdFn) { ZigFn *fn_table_entry = ir_resolve_fn(ira, fn_ref); ZigType *fn_type = fn_table_entry ? fn_table_entry->type_entry : fn_ref->value.type; @@ -17215,6 +17643,8 @@ static IrInstruction *ir_analyze_instruction_unreachable(IrAnalyze *ira, } static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi_instruction) { + Error err; + if (ira->const_predecessor_bb) { for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) { IrBasicBlock *predecessor = phi_instruction->incoming_blocks[i]; @@ -17264,6 +17694,8 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh peer_parent->resolved_type = ir_resolve_peer_types(ira, peer_parent->base.source_instruction->source_node, expected_type, instructions, peer_parent->peers.length); + if (type_is_invalid(peer_parent->resolved_type)) + return ira->codegen->invalid_instruction; // the logic below assumes there are no instructions in the new current basic block yet ir_assert(ira->new_irb.current_basic_block->instruction_list.length == 0, &phi_instruction->base); @@ -17346,20 +17778,32 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh } ZigType *resolved_type; - if (peer_parent != nullptr && ir_result_has_type(peer_parent->parent)) { - if (peer_parent->parent->id == ResultLocIdReturn) { - resolved_type = ira->explicit_return_type; - } else { - ZigType *resolved_loc_ptr_type = peer_parent->parent->resolved_loc->value.type; - ir_assert(resolved_loc_ptr_type->id == ZigTypeIdPointer, &phi_instruction->base); - resolved_type = resolved_loc_ptr_type->data.pointer.child_type; + if (peer_parent != nullptr) { + bool peer_parent_has_type; + if ((err = ir_result_has_type(ira, peer_parent->parent, &peer_parent_has_type))) + return ira->codegen->invalid_instruction; + if (peer_parent_has_type) { + if (peer_parent->parent->id == ResultLocIdReturn) { + resolved_type = ira->explicit_return_type; + } else if (peer_parent->parent->id == ResultLocIdCast) { + resolved_type = ir_resolve_type(ira, peer_parent->parent->source_instruction->child); + if (type_is_invalid(resolved_type)) + return ira->codegen->invalid_instruction; + } else { + ZigType *resolved_loc_ptr_type = peer_parent->parent->resolved_loc->value.type; + ir_assert(resolved_loc_ptr_type->id == ZigTypeIdPointer, &phi_instruction->base); + resolved_type = resolved_loc_ptr_type->data.pointer.child_type; + } + goto skip_resolve_peer_types; } - } else { + } + { resolved_type = ir_resolve_peer_types(ira, phi_instruction->base.source_node, nullptr, new_incoming_values.items, new_incoming_values.length); if (type_is_invalid(resolved_type)) return ira->codegen->invalid_instruction; } +skip_resolve_peer_types: switch (type_has_one_possible_value(ira->codegen, resolved_type)) { case OnePossibleValueInvalid: @@ -17449,7 +17893,7 @@ static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_ali static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align) { assert(is_slice(slice_type)); - ZigType *ptr_type = adjust_ptr_align(g, slice_type->data.structure.fields[slice_ptr_index].type_entry, + ZigType *ptr_type = adjust_ptr_align(g, slice_type->data.structure.fields[slice_ptr_index]->type_entry, new_align); return get_slice_type(g, ptr_type); } @@ -17535,7 +17979,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct } return_type = adjust_ptr_len(ira->codegen, array_type, elem_ptr_instruction->ptr_len); } else if (is_slice(array_type)) { - return_type = adjust_ptr_len(ira->codegen, array_type->data.structure.fields[slice_ptr_index].type_entry, + return_type = adjust_ptr_len(ira->codegen, array_type->data.structure.fields[slice_ptr_index]->type_entry, elem_ptr_instruction->ptr_len); } else if (array_type->id == ZigTypeIdArgTuple) { ConstExprValue *ptr_val = ir_resolve_const(ira, array_ptr, UndefBad); @@ -17571,6 +18015,19 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct } else if (array_type->id == ZigTypeIdVector) { // This depends on whether the element index is comptime, so it is computed later. return_type = nullptr; + } else if (elem_ptr_instruction->init_array_type_source_node != nullptr && + array_type->id == ZigTypeIdStruct && + array_type->data.structure.resolve_status == ResolveStatusBeingInferred) + { + ZigType *usize = ira->codegen->builtin_types.entry_usize; + IrInstruction *casted_elem_index = ir_implicit_cast(ira, elem_index, usize); + if (casted_elem_index == ira->codegen->invalid_instruction) + return ira->codegen->invalid_instruction; + ir_assert(instr_is_comptime(casted_elem_index), &elem_ptr_instruction->base); + Buf *field_name = buf_alloc(); + bigint_append_buf(field_name, &casted_elem_index->value.data.x_bigint, 10); + return ir_analyze_inferred_field_ptr(ira, field_name, &elem_ptr_instruction->base, + array_ptr, array_type); } else { ir_add_error_node(ira, elem_ptr_instruction->base.source_node, buf_sprintf("array access of non-array type '%s'", buf_ptr(&array_type->name))); @@ -17601,7 +18058,8 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct return_type = get_pointer_to_type_extra2(ira->codegen, elem_type, ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, elem_ptr_instruction->ptr_len, - get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index); + get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index, + nullptr); } else if (return_type->data.pointer.explicit_alignment != 0) { // figure out the largest alignment possible @@ -17639,7 +18097,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct if (array_ptr_val == nullptr) return ira->codegen->invalid_instruction; - if (array_ptr_val->special == ConstValSpecialUndef && elem_ptr_instruction->init_array_type != nullptr) { + if (array_ptr_val->special == ConstValSpecialUndef && + elem_ptr_instruction->init_array_type_source_node != nullptr) + { if (array_type->id == ZigTypeIdArray || array_type->id == ZigTypeIdVector) { array_ptr_val->data.x_array.special = ConstArraySpecialNone; array_ptr_val->data.x_array.data.s_none.elements = create_const_vals(array_type->data.array.len); @@ -17653,11 +18113,13 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct elem_val->parent.data.p_array.elem_index = i; } } else if (is_slice(array_type)) { - ZigType *actual_array_type = ir_resolve_type(ira, elem_ptr_instruction->init_array_type->child); + ir_assert(array_ptr->value.type->id == ZigTypeIdPointer, &elem_ptr_instruction->base); + ZigType *actual_array_type = array_ptr->value.type->data.pointer.child_type; + if (type_is_invalid(actual_array_type)) return ira->codegen->invalid_instruction; if (actual_array_type->id != ZigTypeIdArray) { - ir_add_error(ira, elem_ptr_instruction->init_array_type, + ir_add_error_node(ira, elem_ptr_instruction->init_array_type_source_node, buf_sprintf("expected array type or [_], found slice")); return ira->codegen->invalid_instruction; } @@ -17679,9 +18141,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct init_const_slice(ira->codegen, array_ptr_val, array_init_val, 0, actual_array_type->data.array.len, false); - array_ptr_val->data.x_struct.fields[slice_ptr_index].data.x_ptr.mut = ConstPtrMutInfer; + array_ptr_val->data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = ConstPtrMutInfer; } else { - ir_add_error(ira, elem_ptr_instruction->init_array_type, + ir_add_error_node(ira, elem_ptr_instruction->init_array_type_source_node, buf_sprintf("expected array type or [_], found '%s'", buf_ptr(&array_type->name))); return ira->codegen->invalid_instruction; @@ -17751,7 +18213,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct } return result; } else if (is_slice(array_type)) { - ConstExprValue *ptr_field = &array_ptr_val->data.x_struct.fields[slice_ptr_index]; + ConstExprValue *ptr_field = array_ptr_val->data.x_struct.fields[slice_ptr_index]; ir_assert(ptr_field != nullptr, &elem_ptr_instruction->base); if (ptr_field->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, @@ -17760,7 +18222,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct result->value.type = return_type; return result; } - ConstExprValue *len_field = &array_ptr_val->data.x_struct.fields[slice_len_index]; + ConstExprValue *len_field = array_ptr_val->data.x_struct.fields[slice_len_index]; IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type); ConstExprValue *out_val = &result->value; uint64_t slice_len = bigint_as_u64(&len_field->data.x_bigint); @@ -17814,7 +18276,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct if (orig_array_ptr_val->data.x_ptr.mut == ConstPtrMutInfer) { result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, - false, elem_ptr_instruction->ptr_len, elem_ptr_instruction->init_array_type); + false, elem_ptr_instruction->ptr_len, nullptr); result->value.type = return_type; result->value.special = ConstValSpecialStatic; } else { @@ -17838,7 +18300,8 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct return_type = get_pointer_to_type_extra2(ira->codegen, elem_type, ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, elem_ptr_instruction->ptr_len, - get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, VECTOR_INDEX_RUNTIME); + get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, VECTOR_INDEX_RUNTIME, + nullptr); } else { // runtime known element index switch (type_requires_comptime(ira->codegen, return_type)) { @@ -17875,7 +18338,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope, elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, safety_check_on, - elem_ptr_instruction->ptr_len, elem_ptr_instruction->init_array_type); + elem_ptr_instruction->ptr_len, nullptr); result->value.type = return_type; return result; } @@ -17954,43 +18417,47 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction case OnePossibleValueNo: break; } - ResolveStatus needed_resolve_status = - (struct_type->data.structure.layout == ContainerLayoutAuto) ? - ResolveStatusZeroBitsKnown : ResolveStatusSizeKnown; - if ((err = type_resolve(ira->codegen, struct_type, needed_resolve_status))) - return ira->codegen->invalid_instruction; - assert(struct_ptr->value.type->id == ZigTypeIdPointer); - uint32_t ptr_bit_offset = struct_ptr->value.type->data.pointer.bit_offset_in_host; - uint32_t ptr_host_int_bytes = struct_ptr->value.type->data.pointer.host_int_bytes; - uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ? - get_host_int_bytes(ira->codegen, struct_type, field) : ptr_host_int_bytes; bool is_const = struct_ptr->value.type->data.pointer.is_const; bool is_volatile = struct_ptr->value.type->data.pointer.is_volatile; - ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type, - is_const, is_volatile, PtrLenSingle, field->align, - (uint32_t)(ptr_bit_offset + field->bit_offset_in_host), - (uint32_t)host_int_bytes_for_result_type, false); + ZigType *ptr_type; + if (struct_type->data.structure.is_inferred) { + ptr_type = get_pointer_to_type_extra(ira->codegen, field_type, + is_const, is_volatile, PtrLenSingle, 0, 0, 0, false); + } else { + ResolveStatus needed_resolve_status = + (struct_type->data.structure.layout == ContainerLayoutAuto) ? + ResolveStatusZeroBitsKnown : ResolveStatusSizeKnown; + if ((err = type_resolve(ira->codegen, struct_type, needed_resolve_status))) + return ira->codegen->invalid_instruction; + assert(struct_ptr->value.type->id == ZigTypeIdPointer); + uint32_t ptr_bit_offset = struct_ptr->value.type->data.pointer.bit_offset_in_host; + uint32_t ptr_host_int_bytes = struct_ptr->value.type->data.pointer.host_int_bytes; + uint32_t host_int_bytes_for_result_type = (ptr_host_int_bytes == 0) ? + get_host_int_bytes(ira->codegen, struct_type, field) : ptr_host_int_bytes; + ptr_type = get_pointer_to_type_extra(ira->codegen, field_type, + is_const, is_volatile, PtrLenSingle, field->align, + (uint32_t)(ptr_bit_offset + field->bit_offset_in_host), + (uint32_t)host_int_bytes_for_result_type, false); + } if (instr_is_comptime(struct_ptr)) { ConstExprValue *ptr_val = ir_resolve_const(ira, struct_ptr, UndefBad); if (!ptr_val) return ira->codegen->invalid_instruction; if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { - if ((err = type_resolve(ira->codegen, struct_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_instruction; - ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); if (struct_val == nullptr) return ira->codegen->invalid_instruction; if (type_is_invalid(struct_val->type)) return ira->codegen->invalid_instruction; if (initializing && struct_val->special == ConstValSpecialUndef) { - struct_val->data.x_struct.fields = create_const_vals(struct_type->data.structure.src_field_count); + struct_val->data.x_struct.fields = alloc_const_vals_ptrs(struct_type->data.structure.src_field_count); struct_val->special = ConstValSpecialStatic; for (size_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) { - ConstExprValue *field_val = &struct_val->data.x_struct.fields[i]; + ConstExprValue *field_val = struct_val->data.x_struct.fields[i]; field_val->special = ConstValSpecialUndef; - field_val->type = struct_type->data.structure.fields[i].type_entry; + field_val->type = resolve_struct_field_type(ira->codegen, + struct_type->data.structure.fields[i]); field_val->parent.id = ConstParentIdStruct; field_val->parent.data.p_struct.struct_val = struct_val; field_val->parent.data.p_struct.field_index = i; @@ -18019,12 +18486,53 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction return result; } +static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name, + IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type) +{ + // The type of the field is not available until a store using this pointer happens. + // So, here we create a special pointer type which has the inferred struct type and + // field name encoded in the type. Later, when there is a store via this pointer, + // the field type will then be available, and the field will be added to the inferred + // struct. + + ZigType *container_ptr_type = container_ptr->value.type; + ir_assert(container_ptr_type->id == ZigTypeIdPointer, source_instr); + + InferredStructField *inferred_struct_field = allocate<InferredStructField>(1, "InferredStructField"); + inferred_struct_field->inferred_struct_type = container_type; + inferred_struct_field->field_name = field_name; + + ZigType *elem_type = ira->codegen->builtin_types.entry_var; + ZigType *field_ptr_type = get_pointer_to_type_extra2(ira->codegen, elem_type, + container_ptr_type->data.pointer.is_const, container_ptr_type->data.pointer.is_volatile, + PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, inferred_struct_field); + + if (instr_is_comptime(container_ptr)) { + IrInstruction *result = ir_const(ira, source_instr, field_ptr_type); + copy_const_val(&result->value, &container_ptr->value, false); + result->value.type = field_ptr_type; + return result; + } + + IrInstruction *result = ir_build_cast(&ira->new_irb, source_instr->scope, + source_instr->source_node, field_ptr_type, container_ptr, CastOpNoop); + result->value.type = field_ptr_type; + return result; +} + static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name, IrInstruction *source_instr, IrInstruction *container_ptr, ZigType *container_type, bool initializing) { Error err; ZigType *bare_type = container_ref_type(container_type); + + if (initializing && bare_type->id == ZigTypeIdStruct && + bare_type->data.structure.resolve_status == ResolveStatusBeingInferred) + { + return ir_analyze_inferred_field_ptr(ira, field_name, source_instr, container_ptr, bare_type); + } + if ((err = type_resolve(ira->codegen, bare_type, ResolveStatusZeroBitsKnown))) return ira->codegen->invalid_instruction; @@ -18065,7 +18573,8 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ if (!ptr_val) return ira->codegen->invalid_instruction; - if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { + if (ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar && + ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { ConstExprValue *union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node); if (union_val == nullptr) return ira->codegen->invalid_instruction; @@ -18097,7 +18606,6 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_ ConstExprValue *payload_val = union_val->data.x_union.payload; - IrInstruction *result; if (ptr_val->data.x_ptr.mut == ConstPtrMutInfer) { result = ir_build_union_field_ptr(&ira->new_irb, source_instr->scope, @@ -19799,6 +20307,11 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc return ira->codegen->invalid_instruction; } + if (container_type->data.structure.resolve_status == ResolveStatusBeingInferred) { + // We're now done inferring the type. + container_type->data.structure.resolve_status = ResolveStatusUnstarted; + } + if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown))) return ira->codegen->invalid_instruction; @@ -19865,14 +20378,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc if (field_assign_nodes[i] != nullptr) continue; // look for a default field value - TypeStructField *field = &container_type->data.structure.fields[i]; + TypeStructField *field = container_type->data.structure.fields[i]; if (field->init_val == nullptr) { // it's not memoized. time to go analyze it - assert(field->decl_node->type == NodeTypeStructField); - AstNode *init_node = field->decl_node->data.struct_field.value; + AstNode *init_node; + if (field->decl_node->type == NodeTypeStructField) { + init_node = field->decl_node->data.struct_field.value; + } else { + init_node = nullptr; + } if (init_node == nullptr) { ir_add_error_node(ira, instruction->source_node, - buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name))); + buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i]->name))); any_missing = true; continue; } @@ -19926,14 +20443,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, IrInstructionContainerInitList *instruction) { - ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child); - if (type_is_invalid(container_type)) - return ira->codegen->invalid_instruction; + ir_assert(instruction->result_loc != nullptr, &instruction->base); + IrInstruction *result_loc = instruction->result_loc->child; + if (type_is_invalid(result_loc->value.type)) + return result_loc; + ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base); + + ZigType *container_type = result_loc->value.type->data.pointer.child_type; size_t elem_count = instruction->item_count; if (is_slice(container_type)) { - ir_add_error(ira, instruction->container_type, + ir_add_error_node(ira, instruction->init_array_type_source_node, buf_sprintf("expected array type or [_], found slice")); return ira->codegen->invalid_instruction; } @@ -19955,29 +20476,28 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, return ir_analyze_container_init_fields(ira, &instruction->base, container_type, 0, nullptr, result_loc); } - if (container_type->id != ZigTypeIdArray) { + if (container_type->id == ZigTypeIdArray) { + ZigType *child_type = container_type->data.array.child_type; + if (container_type->data.array.len != elem_count) { + ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count); + + ir_add_error(ira, &instruction->base, + buf_sprintf("expected %s literal, found %s literal", + buf_ptr(&container_type->name), buf_ptr(&literal_type->name))); + return ira->codegen->invalid_instruction; + } + } else if (container_type->id == ZigTypeIdStruct && + container_type->data.structure.resolve_status == ResolveStatusBeingInferred) + { + // We're now done inferring the type. + container_type->data.structure.resolve_status = ResolveStatusUnstarted; + } else { ir_add_error_node(ira, instruction->base.source_node, buf_sprintf("type '%s' does not support array initialization", buf_ptr(&container_type->name))); return ira->codegen->invalid_instruction; } - ir_assert(instruction->result_loc != nullptr, &instruction->base); - IrInstruction *result_loc = instruction->result_loc->child; - if (type_is_invalid(result_loc->value.type)) - return result_loc; - ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base); - - ZigType *child_type = container_type->data.array.child_type; - if (container_type->data.array.len != elem_count) { - ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count); - - ir_add_error(ira, &instruction->base, - buf_sprintf("expected %s literal, found %s literal", - buf_ptr(&container_type->name), buf_ptr(&literal_type->name))); - return ira->codegen->invalid_instruction; - } - switch (type_has_one_possible_value(ira->codegen, container_type)) { case OnePossibleValueInvalid: return ira->codegen->invalid_instruction; @@ -20064,16 +20584,14 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, IrInstructionContainerInitFields *instruction) { - IrInstruction *container_type_value = instruction->container_type->child; - ZigType *container_type = ir_resolve_type(ira, container_type_value); - if (type_is_invalid(container_type)) - return ira->codegen->invalid_instruction; - ir_assert(instruction->result_loc != nullptr, &instruction->base); IrInstruction *result_loc = instruction->result_loc->child; if (type_is_invalid(result_loc->value.type)) return result_loc; + ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base); + ZigType *container_type = result_loc->value.type->data.pointer.child_type; + return ir_analyze_container_init_fields(ira, &instruction->base, container_type, instruction->field_count, instruction->fields, result_loc); } @@ -20472,17 +20990,17 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr declaration_val->special = ConstValSpecialStatic; declaration_val->type = type_info_declaration_type; - ConstExprValue *inner_fields = create_const_vals(3); + ConstExprValue **inner_fields = alloc_const_vals_ptrs(3); ConstExprValue *name = create_const_str_lit(ira->codegen, curr_entry->key); - init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(curr_entry->key), true); - inner_fields[1].special = ConstValSpecialStatic; - inner_fields[1].type = ira->codegen->builtin_types.entry_bool; - inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub; - inner_fields[2].special = ConstValSpecialStatic; - inner_fields[2].type = type_info_declaration_data_type; - inner_fields[2].parent.id = ConstParentIdStruct; - inner_fields[2].parent.data.p_struct.struct_val = declaration_val; - inner_fields[2].parent.data.p_struct.field_index = 1; + init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(curr_entry->key), true); + inner_fields[1]->special = ConstValSpecialStatic; + inner_fields[1]->type = ira->codegen->builtin_types.entry_bool; + inner_fields[1]->data.x_bool = curr_entry->value->visib_mod == VisibModPub; + inner_fields[2]->special = ConstValSpecialStatic; + inner_fields[2]->type = type_info_declaration_data_type; + inner_fields[2]->parent.id = ConstParentIdStruct; + inner_fields[2]->parent.data.p_struct.struct_val = declaration_val; + inner_fields[2]->parent.data.p_struct.field_index = 1; switch (curr_entry->value->id) { case TldIdVar: @@ -20494,19 +21012,19 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr if (var->const_value->type->id == ZigTypeIdMetaType) { // We have a variable of type 'type', so it's actually a type declaration. // 0: Data.Type: type - bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0); - inner_fields[2].data.x_union.payload = var->const_value; + bigint_init_unsigned(&inner_fields[2]->data.x_union.tag, 0); + inner_fields[2]->data.x_union.payload = var->const_value; } else { // We have a variable of another type, so we store the type of the variable. // 1: Data.Var: type - bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 1); + bigint_init_unsigned(&inner_fields[2]->data.x_union.tag, 1); ConstExprValue *payload = create_const_vals(1); payload->special = ConstValSpecialStatic; payload->type = ira->codegen->builtin_types.entry_type; payload->data.x_type = var->const_value->type; - inner_fields[2].data.x_union.payload = payload; + inner_fields[2]->data.x_union.payload = payload; } break; @@ -20514,7 +21032,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr case TldIdFn: { // 2: Data.Fn: Data.FnDecl - bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 2); + bigint_init_unsigned(&inner_fields[2]->data.x_union.tag, 2); ZigFn *fn_entry = ((TldFn *)curr_entry->value)->fn_entry; assert(!fn_entry->is_test); @@ -20530,63 +21048,63 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr fn_decl_val->special = ConstValSpecialStatic; fn_decl_val->type = type_info_fn_decl_type; fn_decl_val->parent.id = ConstParentIdUnion; - fn_decl_val->parent.data.p_union.union_val = &inner_fields[2]; + fn_decl_val->parent.data.p_union.union_val = inner_fields[2]; - ConstExprValue *fn_decl_fields = create_const_vals(9); + ConstExprValue **fn_decl_fields = alloc_const_vals_ptrs(9); fn_decl_val->data.x_struct.fields = fn_decl_fields; // fn_type: type ensure_field_index(fn_decl_val->type, "fn_type", 0); - fn_decl_fields[0].special = ConstValSpecialStatic; - fn_decl_fields[0].type = ira->codegen->builtin_types.entry_type; - fn_decl_fields[0].data.x_type = fn_entry->type_entry; + fn_decl_fields[0]->special = ConstValSpecialStatic; + fn_decl_fields[0]->type = ira->codegen->builtin_types.entry_type; + fn_decl_fields[0]->data.x_type = fn_entry->type_entry; // inline_type: Data.FnDecl.Inline ensure_field_index(fn_decl_val->type, "inline_type", 1); - fn_decl_fields[1].special = ConstValSpecialStatic; - fn_decl_fields[1].type = type_info_fn_decl_inline_type; - bigint_init_unsigned(&fn_decl_fields[1].data.x_enum_tag, fn_entry->fn_inline); + fn_decl_fields[1]->special = ConstValSpecialStatic; + fn_decl_fields[1]->type = type_info_fn_decl_inline_type; + bigint_init_unsigned(&fn_decl_fields[1]->data.x_enum_tag, fn_entry->fn_inline); // calling_convention: TypeInfo.CallingConvention ensure_field_index(fn_decl_val->type, "calling_convention", 2); - fn_decl_fields[2].special = ConstValSpecialStatic; - fn_decl_fields[2].type = ir_type_info_get_type(ira, "CallingConvention", nullptr); - bigint_init_unsigned(&fn_decl_fields[2].data.x_enum_tag, fn_node->cc); + fn_decl_fields[2]->special = ConstValSpecialStatic; + fn_decl_fields[2]->type = ir_type_info_get_type(ira, "CallingConvention", nullptr); + bigint_init_unsigned(&fn_decl_fields[2]->data.x_enum_tag, fn_node->cc); // is_var_args: bool ensure_field_index(fn_decl_val->type, "is_var_args", 3); bool is_varargs = fn_node->is_var_args; - fn_decl_fields[3].special = ConstValSpecialStatic; - fn_decl_fields[3].type = ira->codegen->builtin_types.entry_bool; - fn_decl_fields[3].data.x_bool = is_varargs; + fn_decl_fields[3]->special = ConstValSpecialStatic; + fn_decl_fields[3]->type = ira->codegen->builtin_types.entry_bool; + fn_decl_fields[3]->data.x_bool = is_varargs; // is_extern: bool ensure_field_index(fn_decl_val->type, "is_extern", 4); - fn_decl_fields[4].special = ConstValSpecialStatic; - fn_decl_fields[4].type = ira->codegen->builtin_types.entry_bool; - fn_decl_fields[4].data.x_bool = fn_node->is_extern; + fn_decl_fields[4]->special = ConstValSpecialStatic; + fn_decl_fields[4]->type = ira->codegen->builtin_types.entry_bool; + fn_decl_fields[4]->data.x_bool = fn_node->is_extern; // is_export: bool ensure_field_index(fn_decl_val->type, "is_export", 5); - fn_decl_fields[5].special = ConstValSpecialStatic; - fn_decl_fields[5].type = ira->codegen->builtin_types.entry_bool; - fn_decl_fields[5].data.x_bool = fn_node->is_export; + fn_decl_fields[5]->special = ConstValSpecialStatic; + fn_decl_fields[5]->type = ira->codegen->builtin_types.entry_bool; + fn_decl_fields[5]->data.x_bool = fn_node->is_export; // lib_name: ?[]const u8 ensure_field_index(fn_decl_val->type, "lib_name", 6); - fn_decl_fields[6].special = ConstValSpecialStatic; + fn_decl_fields[6]->special = ConstValSpecialStatic; ZigType *u8_ptr = get_pointer_to_type_extra( ira->codegen, ira->codegen->builtin_types.entry_u8, true, false, PtrLenUnknown, 0, 0, 0, false); - fn_decl_fields[6].type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr)); + fn_decl_fields[6]->type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr)); if (fn_node->is_extern && fn_node->lib_name != nullptr && buf_len(fn_node->lib_name) > 0) { - fn_decl_fields[6].data.x_optional = create_const_vals(1); + fn_decl_fields[6]->data.x_optional = create_const_vals(1); ConstExprValue *lib_name = create_const_str_lit(ira->codegen, fn_node->lib_name); - init_const_slice(ira->codegen, fn_decl_fields[6].data.x_optional, lib_name, 0, + init_const_slice(ira->codegen, fn_decl_fields[6]->data.x_optional, lib_name, 0, buf_len(fn_node->lib_name), true); } else { - fn_decl_fields[6].data.x_optional = nullptr; + fn_decl_fields[6]->data.x_optional = nullptr; } // return_type: type ensure_field_index(fn_decl_val->type, "return_type", 7); - fn_decl_fields[7].special = ConstValSpecialStatic; - fn_decl_fields[7].type = ira->codegen->builtin_types.entry_type; - fn_decl_fields[7].data.x_type = fn_entry->type_entry->data.fn.fn_type_id.return_type; + fn_decl_fields[7]->special = ConstValSpecialStatic; + fn_decl_fields[7]->type = ira->codegen->builtin_types.entry_type; + fn_decl_fields[7]->data.x_type = fn_entry->type_entry->data.fn.fn_type_id.return_type; // arg_names: [][] const u8 ensure_field_index(fn_decl_val->type, "arg_names", 8); size_t fn_arg_count = fn_entry->variable_list.length; @@ -20597,7 +21115,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr fn_arg_name_array->data.x_array.special = ConstArraySpecialNone; fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count); - init_const_slice(ira->codegen, &fn_decl_fields[8], fn_arg_name_array, 0, fn_arg_count, false); + init_const_slice(ira->codegen, fn_decl_fields[8], fn_arg_name_array, 0, fn_arg_count, false); for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) { ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index); @@ -20610,7 +21128,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr fn_arg_name_val->parent.data.p_array.elem_index = fn_arg_index; } - inner_fields[2].data.x_union.payload = fn_decl_val; + inner_fields[2]->data.x_union.payload = fn_decl_val; break; } case TldIdContainer: @@ -20620,14 +21138,14 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr return ErrorSemanticAnalyzeFail; // This is a type. - bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0); + bigint_init_unsigned(&inner_fields[2]->data.x_union.tag, 0); ConstExprValue *payload = create_const_vals(1); payload->special = ConstValSpecialStatic; payload->type = ira->codegen->builtin_types.entry_type; payload->data.x_type = type_entry; - inner_fields[2].data.x_union.payload = payload; + inner_fields[2]->data.x_union.payload = payload; break; } @@ -20636,7 +21154,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr } declaration_val->data.x_struct.fields = inner_fields; - declaration_index++; + declaration_index += 1; } assert(declaration_index == declaration_count); @@ -20673,7 +21191,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty ZigType *attrs_type; BuiltinPtrSize size_enum_index; if (is_slice(ptr_type_entry)) { - attrs_type = ptr_type_entry->data.structure.fields[slice_ptr_index].type_entry; + attrs_type = ptr_type_entry->data.structure.fields[slice_ptr_index]->type_entry; size_enum_index = BuiltinPtrSizeSlice; } else if (ptr_type_entry->id == ZigTypeIdPointer) { attrs_type = ptr_type_entry; @@ -20692,42 +21210,42 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty result->special = ConstValSpecialStatic; result->type = type_info_pointer_type; - ConstExprValue *fields = create_const_vals(6); + ConstExprValue **fields = alloc_const_vals_ptrs(6); result->data.x_struct.fields = fields; // size: Size ensure_field_index(result->type, "size", 0); ZigType *type_info_pointer_size_type = ir_type_info_get_type(ira, "Size", type_info_pointer_type); assertNoError(type_resolve(ira->codegen, type_info_pointer_size_type, ResolveStatusSizeKnown)); - fields[0].special = ConstValSpecialStatic; - fields[0].type = type_info_pointer_size_type; - bigint_init_unsigned(&fields[0].data.x_enum_tag, size_enum_index); + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = type_info_pointer_size_type; + bigint_init_unsigned(&fields[0]->data.x_enum_tag, size_enum_index); // is_const: bool ensure_field_index(result->type, "is_const", 1); - fields[1].special = ConstValSpecialStatic; - fields[1].type = ira->codegen->builtin_types.entry_bool; - fields[1].data.x_bool = attrs_type->data.pointer.is_const; + fields[1]->special = ConstValSpecialStatic; + fields[1]->type = ira->codegen->builtin_types.entry_bool; + fields[1]->data.x_bool = attrs_type->data.pointer.is_const; // is_volatile: bool ensure_field_index(result->type, "is_volatile", 2); - fields[2].special = ConstValSpecialStatic; - fields[2].type = ira->codegen->builtin_types.entry_bool; - fields[2].data.x_bool = attrs_type->data.pointer.is_volatile; + fields[2]->special = ConstValSpecialStatic; + fields[2]->type = ira->codegen->builtin_types.entry_bool; + fields[2]->data.x_bool = attrs_type->data.pointer.is_volatile; // alignment: u32 ensure_field_index(result->type, "alignment", 3); - fields[3].special = ConstValSpecialStatic; - fields[3].type = ira->codegen->builtin_types.entry_num_lit_int; - bigint_init_unsigned(&fields[3].data.x_bigint, get_ptr_align(ira->codegen, attrs_type)); + fields[3]->special = ConstValSpecialStatic; + fields[3]->type = ira->codegen->builtin_types.entry_num_lit_int; + bigint_init_unsigned(&fields[3]->data.x_bigint, get_ptr_align(ira->codegen, attrs_type)); // child: type ensure_field_index(result->type, "child", 4); - fields[4].special = ConstValSpecialStatic; - fields[4].type = ira->codegen->builtin_types.entry_type; - fields[4].data.x_type = attrs_type->data.pointer.child_type; + fields[4]->special = ConstValSpecialStatic; + fields[4]->type = ira->codegen->builtin_types.entry_type; + fields[4]->data.x_type = attrs_type->data.pointer.child_type; // is_allowzero: bool ensure_field_index(result->type, "is_allowzero", 5); - fields[5].special = ConstValSpecialStatic; - fields[5].type = ira->codegen->builtin_types.entry_bool; - fields[5].data.x_bool = attrs_type->data.pointer.allow_zero; + fields[5]->special = ConstValSpecialStatic; + fields[5]->type = ira->codegen->builtin_types.entry_bool; + fields[5]->data.x_bool = attrs_type->data.pointer.allow_zero; return result; }; @@ -20738,14 +21256,14 @@ static void make_enum_field_val(IrAnalyze *ira, ConstExprValue *enum_field_val, enum_field_val->special = ConstValSpecialStatic; enum_field_val->type = type_info_enum_field_type; - ConstExprValue *inner_fields = create_const_vals(2); - inner_fields[1].special = ConstValSpecialStatic; - inner_fields[1].type = ira->codegen->builtin_types.entry_num_lit_int; + ConstExprValue **inner_fields = alloc_const_vals_ptrs(2); + inner_fields[1]->special = ConstValSpecialStatic; + inner_fields[1]->type = ira->codegen->builtin_types.entry_num_lit_int; ConstExprValue *name = create_const_str_lit(ira->codegen, enum_field->name); - init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(enum_field->name), true); + init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(enum_field->name), true); - bigint_init_bigint(&inner_fields[1].data.x_bigint, &enum_field->value); + bigint_init_bigint(&inner_fields[1]->data.x_bigint, &enum_field->value); enum_field_val->data.x_struct.fields = inner_fields; } @@ -20789,19 +21307,19 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Int", nullptr); - ConstExprValue *fields = create_const_vals(2); + ConstExprValue **fields = alloc_const_vals_ptrs(2); result->data.x_struct.fields = fields; // is_signed: bool ensure_field_index(result->type, "is_signed", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ira->codegen->builtin_types.entry_bool; - fields[0].data.x_bool = type_entry->data.integral.is_signed; + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ira->codegen->builtin_types.entry_bool; + fields[0]->data.x_bool = type_entry->data.integral.is_signed; // bits: u8 ensure_field_index(result->type, "bits", 1); - fields[1].special = ConstValSpecialStatic; - fields[1].type = ira->codegen->builtin_types.entry_num_lit_int; - bigint_init_unsigned(&fields[1].data.x_bigint, type_entry->data.integral.bit_count); + fields[1]->special = ConstValSpecialStatic; + fields[1]->type = ira->codegen->builtin_types.entry_num_lit_int; + bigint_init_unsigned(&fields[1]->data.x_bigint, type_entry->data.integral.bit_count); break; } @@ -20811,14 +21329,14 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Float", nullptr); - ConstExprValue *fields = create_const_vals(1); + ConstExprValue **fields = alloc_const_vals_ptrs(1); result->data.x_struct.fields = fields; // bits: u8 ensure_field_index(result->type, "bits", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ira->codegen->builtin_types.entry_num_lit_int; - bigint_init_unsigned(&fields->data.x_bigint, type_entry->data.floating.bit_count); + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ira->codegen->builtin_types.entry_num_lit_int; + bigint_init_unsigned(&fields[0]->data.x_bigint, type_entry->data.floating.bit_count); break; } @@ -20835,19 +21353,19 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Array", nullptr); - ConstExprValue *fields = create_const_vals(2); + ConstExprValue **fields = alloc_const_vals_ptrs(2); result->data.x_struct.fields = fields; // len: usize ensure_field_index(result->type, "len", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ira->codegen->builtin_types.entry_num_lit_int; - bigint_init_unsigned(&fields[0].data.x_bigint, type_entry->data.array.len); + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ira->codegen->builtin_types.entry_num_lit_int; + bigint_init_unsigned(&fields[0]->data.x_bigint, type_entry->data.array.len); // child: type ensure_field_index(result->type, "child", 1); - fields[1].special = ConstValSpecialStatic; - fields[1].type = ira->codegen->builtin_types.entry_type; - fields[1].data.x_type = type_entry->data.array.child_type; + fields[1]->special = ConstValSpecialStatic; + fields[1]->type = ira->codegen->builtin_types.entry_type; + fields[1]->data.x_type = type_entry->data.array.child_type; break; } @@ -20856,19 +21374,19 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Vector", nullptr); - ConstExprValue *fields = create_const_vals(2); + ConstExprValue **fields = alloc_const_vals_ptrs(2); result->data.x_struct.fields = fields; // len: usize ensure_field_index(result->type, "len", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ira->codegen->builtin_types.entry_num_lit_int; - bigint_init_unsigned(&fields[0].data.x_bigint, type_entry->data.vector.len); + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ira->codegen->builtin_types.entry_num_lit_int; + bigint_init_unsigned(&fields[0]->data.x_bigint, type_entry->data.vector.len); // child: type ensure_field_index(result->type, "child", 1); - fields[1].special = ConstValSpecialStatic; - fields[1].type = ira->codegen->builtin_types.entry_type; - fields[1].data.x_type = type_entry->data.vector.elem_type; + fields[1]->special = ConstValSpecialStatic; + fields[1]->type = ira->codegen->builtin_types.entry_type; + fields[1]->data.x_type = type_entry->data.vector.elem_type; break; } @@ -20878,14 +21396,14 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Optional", nullptr); - ConstExprValue *fields = create_const_vals(1); + ConstExprValue **fields = alloc_const_vals_ptrs(1); result->data.x_struct.fields = fields; // child: type ensure_field_index(result->type, "child", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ira->codegen->builtin_types.entry_type; - fields[0].data.x_type = type_entry->data.maybe.child_type; + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ira->codegen->builtin_types.entry_type; + fields[0]->data.x_type = type_entry->data.maybe.child_type; break; } @@ -20894,14 +21412,14 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "AnyFrame", nullptr); - ConstExprValue *fields = create_const_vals(1); + ConstExprValue **fields = alloc_const_vals_ptrs(1); result->data.x_struct.fields = fields; // child: ?type ensure_field_index(result->type, "child", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type); - fields[0].data.x_optional = (type_entry->data.any_frame.result_type == nullptr) ? nullptr : + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type); + fields[0]->data.x_optional = (type_entry->data.any_frame.result_type == nullptr) ? nullptr : create_const_type(ira->codegen, type_entry->data.any_frame.result_type); break; } @@ -20911,19 +21429,19 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Enum", nullptr); - ConstExprValue *fields = create_const_vals(4); + ConstExprValue **fields = alloc_const_vals_ptrs(4); result->data.x_struct.fields = fields; // layout: ContainerLayout ensure_field_index(result->type, "layout", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ir_type_info_get_type(ira, "ContainerLayout", nullptr); - bigint_init_unsigned(&fields[0].data.x_enum_tag, type_entry->data.enumeration.layout); + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ir_type_info_get_type(ira, "ContainerLayout", nullptr); + bigint_init_unsigned(&fields[0]->data.x_enum_tag, type_entry->data.enumeration.layout); // tag_type: type ensure_field_index(result->type, "tag_type", 1); - fields[1].special = ConstValSpecialStatic; - fields[1].type = ira->codegen->builtin_types.entry_type; - fields[1].data.x_type = type_entry->data.enumeration.tag_int_type; + fields[1]->special = ConstValSpecialStatic; + fields[1]->type = ira->codegen->builtin_types.entry_type; + fields[1]->data.x_type = type_entry->data.enumeration.tag_int_type; // fields: []TypeInfo.EnumField ensure_field_index(result->type, "fields", 2); @@ -20939,7 +21457,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr enum_field_array->data.x_array.special = ConstArraySpecialNone; enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count); - init_const_slice(ira->codegen, &fields[2], enum_field_array, 0, enum_field_count, false); + init_const_slice(ira->codegen, fields[2], enum_field_array, 0, enum_field_count, false); for (uint32_t enum_field_index = 0; enum_field_index < enum_field_count; enum_field_index++) { @@ -20952,7 +21470,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr } // decls: []TypeInfo.Declaration ensure_field_index(result->type, "decls", 3); - if ((err = ir_make_type_info_decls(ira, source_instr, &fields[3], + if ((err = ir_make_type_info_decls(ira, source_instr, fields[3], type_entry->data.enumeration.decls_scope))) { return err; @@ -20995,17 +21513,17 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr error_val->special = ConstValSpecialStatic; error_val->type = type_info_error_type; - ConstExprValue *inner_fields = create_const_vals(2); - inner_fields[1].special = ConstValSpecialStatic; - inner_fields[1].type = ira->codegen->builtin_types.entry_num_lit_int; + ConstExprValue **inner_fields = alloc_const_vals_ptrs(2); + inner_fields[1]->special = ConstValSpecialStatic; + inner_fields[1]->type = ira->codegen->builtin_types.entry_num_lit_int; ConstExprValue *name = nullptr; if (error->cached_error_name_val != nullptr) name = error->cached_error_name_val; if (name == nullptr) name = create_const_str_lit(ira->codegen, &error->name); - init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(&error->name), true); - bigint_init_unsigned(&inner_fields[1].data.x_bigint, error->value); + init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(&error->name), true); + bigint_init_unsigned(&inner_fields[1]->data.x_bigint, error->value); error_val->data.x_struct.fields = inner_fields; error_val->parent.id = ConstParentIdArray; @@ -21021,20 +21539,20 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "ErrorUnion", nullptr); - ConstExprValue *fields = create_const_vals(2); + ConstExprValue **fields = alloc_const_vals_ptrs(2); result->data.x_struct.fields = fields; // error_set: type ensure_field_index(result->type, "error_set", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ira->codegen->builtin_types.entry_type; - fields[0].data.x_type = type_entry->data.error_union.err_set_type; + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ira->codegen->builtin_types.entry_type; + fields[0]->data.x_type = type_entry->data.error_union.err_set_type; // payload: type ensure_field_index(result->type, "payload", 1); - fields[1].special = ConstValSpecialStatic; - fields[1].type = ira->codegen->builtin_types.entry_type; - fields[1].data.x_type = type_entry->data.error_union.payload_type; + fields[1]->special = ConstValSpecialStatic; + fields[1]->type = ira->codegen->builtin_types.entry_type; + fields[1]->data.x_type = type_entry->data.error_union.payload_type; break; } @@ -21044,18 +21562,18 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Union", nullptr); - ConstExprValue *fields = create_const_vals(4); + ConstExprValue **fields = alloc_const_vals_ptrs(4); result->data.x_struct.fields = fields; // layout: ContainerLayout ensure_field_index(result->type, "layout", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ir_type_info_get_type(ira, "ContainerLayout", nullptr); - bigint_init_unsigned(&fields[0].data.x_enum_tag, type_entry->data.unionation.layout); + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ir_type_info_get_type(ira, "ContainerLayout", nullptr); + bigint_init_unsigned(&fields[0]->data.x_enum_tag, type_entry->data.unionation.layout); // tag_type: ?type ensure_field_index(result->type, "tag_type", 1); - fields[1].special = ConstValSpecialStatic; - fields[1].type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type); + fields[1]->special = ConstValSpecialStatic; + fields[1]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type); AstNode *union_decl_node = type_entry->data.unionation.decl_node; if (union_decl_node->data.container_decl.auto_enum || @@ -21065,9 +21583,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr tag_type->special = ConstValSpecialStatic; tag_type->type = ira->codegen->builtin_types.entry_type; tag_type->data.x_type = type_entry->data.unionation.tag_type; - fields[1].data.x_optional = tag_type; + fields[1]->data.x_optional = tag_type; } else { - fields[1].data.x_optional = nullptr; + fields[1]->data.x_optional = nullptr; } // fields: []TypeInfo.UnionField ensure_field_index(result->type, "fields", 2); @@ -21083,7 +21601,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr union_field_array->data.x_array.special = ConstArraySpecialNone; union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count); - init_const_slice(ira->codegen, &fields[2], union_field_array, 0, union_field_count, false); + init_const_slice(ira->codegen, fields[2], union_field_array, 0, union_field_count, false); ZigType *type_info_enum_field_type = ir_type_info_get_type(ira, "EnumField", nullptr); @@ -21094,23 +21612,23 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr union_field_val->special = ConstValSpecialStatic; union_field_val->type = type_info_union_field_type; - ConstExprValue *inner_fields = create_const_vals(3); - inner_fields[1].special = ConstValSpecialStatic; - inner_fields[1].type = get_optional_type(ira->codegen, type_info_enum_field_type); + ConstExprValue **inner_fields = alloc_const_vals_ptrs(3); + inner_fields[1]->special = ConstValSpecialStatic; + inner_fields[1]->type = get_optional_type(ira->codegen, type_info_enum_field_type); - if (fields[1].data.x_optional == nullptr) { - inner_fields[1].data.x_optional = nullptr; + if (fields[1]->data.x_optional == nullptr) { + inner_fields[1]->data.x_optional = nullptr; } else { - inner_fields[1].data.x_optional = create_const_vals(1); - make_enum_field_val(ira, inner_fields[1].data.x_optional, union_field->enum_field, type_info_enum_field_type); + inner_fields[1]->data.x_optional = create_const_vals(1); + make_enum_field_val(ira, inner_fields[1]->data.x_optional, union_field->enum_field, type_info_enum_field_type); } - inner_fields[2].special = ConstValSpecialStatic; - inner_fields[2].type = ira->codegen->builtin_types.entry_type; - inner_fields[2].data.x_type = union_field->type_entry; + inner_fields[2]->special = ConstValSpecialStatic; + inner_fields[2]->type = ira->codegen->builtin_types.entry_type; + inner_fields[2]->data.x_type = union_field->type_entry; ConstExprValue *name = create_const_str_lit(ira->codegen, union_field->name); - init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true); + init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(union_field->name), true); union_field_val->data.x_struct.fields = inner_fields; union_field_val->parent.id = ConstParentIdArray; @@ -21119,7 +21637,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr } // decls: []TypeInfo.Declaration ensure_field_index(result->type, "decls", 3); - if ((err = ir_make_type_info_decls(ira, source_instr, &fields[3], + if ((err = ir_make_type_info_decls(ira, source_instr, fields[3], type_entry->data.unionation.decls_scope))) { return err; @@ -21140,14 +21658,14 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Struct", nullptr); - ConstExprValue *fields = create_const_vals(3); + ConstExprValue **fields = alloc_const_vals_ptrs(3); result->data.x_struct.fields = fields; // layout: ContainerLayout ensure_field_index(result->type, "layout", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ir_type_info_get_type(ira, "ContainerLayout", nullptr); - bigint_init_unsigned(&fields[0].data.x_enum_tag, type_entry->data.structure.layout); + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ir_type_info_get_type(ira, "ContainerLayout", nullptr); + bigint_init_unsigned(&fields[0]->data.x_enum_tag, type_entry->data.structure.layout); // fields: []TypeInfo.StructField ensure_field_index(result->type, "fields", 1); @@ -21163,18 +21681,18 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr struct_field_array->data.x_array.special = ConstArraySpecialNone; struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count); - init_const_slice(ira->codegen, &fields[1], struct_field_array, 0, struct_field_count, false); + init_const_slice(ira->codegen, fields[1], struct_field_array, 0, struct_field_count, false); for (uint32_t struct_field_index = 0; struct_field_index < struct_field_count; struct_field_index++) { - TypeStructField *struct_field = &type_entry->data.structure.fields[struct_field_index]; + TypeStructField *struct_field = type_entry->data.structure.fields[struct_field_index]; ConstExprValue *struct_field_val = &struct_field_array->data.x_array.data.s_none.elements[struct_field_index]; struct_field_val->special = ConstValSpecialStatic; struct_field_val->type = type_info_struct_field_type; - ConstExprValue *inner_fields = create_const_vals(3); - inner_fields[1].special = ConstValSpecialStatic; - inner_fields[1].type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int); + ConstExprValue **inner_fields = alloc_const_vals_ptrs(3); + inner_fields[1]->special = ConstValSpecialStatic; + inner_fields[1]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int); ZigType *field_type = resolve_struct_field_type(ira->codegen, struct_field); if (field_type == nullptr) @@ -21182,21 +21700,21 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr if ((err = type_resolve(ira->codegen, field_type, ResolveStatusZeroBitsKnown))) return err; if (!type_has_bits(struct_field->type_entry)) { - inner_fields[1].data.x_optional = nullptr; + inner_fields[1]->data.x_optional = nullptr; } else { size_t byte_offset = struct_field->offset; - inner_fields[1].data.x_optional = create_const_vals(1); - inner_fields[1].data.x_optional->special = ConstValSpecialStatic; - inner_fields[1].data.x_optional->type = ira->codegen->builtin_types.entry_num_lit_int; - bigint_init_unsigned(&inner_fields[1].data.x_optional->data.x_bigint, byte_offset); + inner_fields[1]->data.x_optional = create_const_vals(1); + inner_fields[1]->data.x_optional->special = ConstValSpecialStatic; + inner_fields[1]->data.x_optional->type = ira->codegen->builtin_types.entry_num_lit_int; + bigint_init_unsigned(&inner_fields[1]->data.x_optional->data.x_bigint, byte_offset); } - inner_fields[2].special = ConstValSpecialStatic; - inner_fields[2].type = ira->codegen->builtin_types.entry_type; - inner_fields[2].data.x_type = struct_field->type_entry; + inner_fields[2]->special = ConstValSpecialStatic; + inner_fields[2]->type = ira->codegen->builtin_types.entry_type; + inner_fields[2]->data.x_type = struct_field->type_entry; ConstExprValue *name = create_const_str_lit(ira->codegen, struct_field->name); - init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(struct_field->name), true); + init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(struct_field->name), true); struct_field_val->data.x_struct.fields = inner_fields; struct_field_val->parent.id = ConstParentIdArray; @@ -21205,7 +21723,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr } // decls: []TypeInfo.Declaration ensure_field_index(result->type, "decls", 2); - if ((err = ir_make_type_info_decls(ira, source_instr, &fields[2], + if ((err = ir_make_type_info_decls(ira, source_instr, fields[2], type_entry->data.structure.decls_scope))) { return err; @@ -21219,38 +21737,38 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->special = ConstValSpecialStatic; result->type = ir_type_info_get_type(ira, "Fn", nullptr); - ConstExprValue *fields = create_const_vals(5); + ConstExprValue **fields = alloc_const_vals_ptrs(5); result->data.x_struct.fields = fields; // calling_convention: TypeInfo.CallingConvention ensure_field_index(result->type, "calling_convention", 0); - fields[0].special = ConstValSpecialStatic; - fields[0].type = ir_type_info_get_type(ira, "CallingConvention", nullptr); - bigint_init_unsigned(&fields[0].data.x_enum_tag, type_entry->data.fn.fn_type_id.cc); + fields[0]->special = ConstValSpecialStatic; + fields[0]->type = ir_type_info_get_type(ira, "CallingConvention", nullptr); + bigint_init_unsigned(&fields[0]->data.x_enum_tag, type_entry->data.fn.fn_type_id.cc); // is_generic: bool ensure_field_index(result->type, "is_generic", 1); bool is_generic = type_entry->data.fn.is_generic; - fields[1].special = ConstValSpecialStatic; - fields[1].type = ira->codegen->builtin_types.entry_bool; - fields[1].data.x_bool = is_generic; + fields[1]->special = ConstValSpecialStatic; + fields[1]->type = ira->codegen->builtin_types.entry_bool; + fields[1]->data.x_bool = is_generic; // is_varargs: bool ensure_field_index(result->type, "is_var_args", 2); bool is_varargs = type_entry->data.fn.fn_type_id.is_var_args; - fields[2].special = ConstValSpecialStatic; - fields[2].type = ira->codegen->builtin_types.entry_bool; - fields[2].data.x_bool = type_entry->data.fn.fn_type_id.is_var_args; + fields[2]->special = ConstValSpecialStatic; + fields[2]->type = ira->codegen->builtin_types.entry_bool; + fields[2]->data.x_bool = type_entry->data.fn.fn_type_id.is_var_args; // return_type: ?type ensure_field_index(result->type, "return_type", 3); - fields[3].special = ConstValSpecialStatic; - fields[3].type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type); + fields[3]->special = ConstValSpecialStatic; + fields[3]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type); if (type_entry->data.fn.fn_type_id.return_type == nullptr) - fields[3].data.x_optional = nullptr; + fields[3]->data.x_optional = nullptr; else { ConstExprValue *return_type = create_const_vals(1); return_type->special = ConstValSpecialStatic; return_type->type = ira->codegen->builtin_types.entry_type; return_type->data.x_type = type_entry->data.fn.fn_type_id.return_type; - fields[3].data.x_optional = return_type; + fields[3]->data.x_optional = return_type; } // args: []TypeInfo.FnArg ZigType *type_info_fn_arg_type = ir_type_info_get_type(ira, "FnArg", nullptr); @@ -21266,7 +21784,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr fn_arg_array->data.x_array.special = ConstArraySpecialNone; fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count); - init_const_slice(ira->codegen, &fields[4], fn_arg_array, 0, fn_arg_count, false); + init_const_slice(ira->codegen, fields[4], fn_arg_array, 0, fn_arg_count, false); for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) { FnTypeParamInfo *fn_param_info = &type_entry->data.fn.fn_type_id.param_info[fn_arg_index]; @@ -21278,24 +21796,24 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr bool arg_is_generic = fn_param_info->type == nullptr; if (arg_is_generic) assert(is_generic); - ConstExprValue *inner_fields = create_const_vals(3); - inner_fields[0].special = ConstValSpecialStatic; - inner_fields[0].type = ira->codegen->builtin_types.entry_bool; - inner_fields[0].data.x_bool = arg_is_generic; - inner_fields[1].special = ConstValSpecialStatic; - inner_fields[1].type = ira->codegen->builtin_types.entry_bool; - inner_fields[1].data.x_bool = fn_param_info->is_noalias; - inner_fields[2].special = ConstValSpecialStatic; - inner_fields[2].type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type); + ConstExprValue **inner_fields = alloc_const_vals_ptrs(3); + inner_fields[0]->special = ConstValSpecialStatic; + inner_fields[0]->type = ira->codegen->builtin_types.entry_bool; + inner_fields[0]->data.x_bool = arg_is_generic; + inner_fields[1]->special = ConstValSpecialStatic; + inner_fields[1]->type = ira->codegen->builtin_types.entry_bool; + inner_fields[1]->data.x_bool = fn_param_info->is_noalias; + inner_fields[2]->special = ConstValSpecialStatic; + inner_fields[2]->type = get_optional_type(ira->codegen, ira->codegen->builtin_types.entry_type); if (arg_is_generic) - inner_fields[2].data.x_optional = nullptr; + inner_fields[2]->data.x_optional = nullptr; else { ConstExprValue *arg_type = create_const_vals(1); arg_type->special = ConstValSpecialStatic; arg_type->type = ira->codegen->builtin_types.entry_type; arg_type->data.x_type = fn_param_info->type; - inner_fields[2].data.x_optional = arg_type; + inner_fields[2]->data.x_optional = arg_type; } fn_arg_val->data.x_struct.fields = inner_fields; @@ -21356,8 +21874,8 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira, static ConstExprValue *get_const_field(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index) { ensure_field_index(struct_value->type, name, field_index); - assert(struct_value->data.x_struct.fields[field_index].special == ConstValSpecialStatic); - return &struct_value->data.x_struct.fields[field_index]; + assert(struct_value->data.x_struct.fields[field_index]->special == ConstValSpecialStatic); + return struct_value->data.x_struct.fields[field_index]; } static bool get_const_field_bool(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index) @@ -21656,15 +22174,15 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct } for (size_t i = 0; i < errors_len; i += 1) { Stage2ErrorMsg *clang_err = &errors_ptr[i]; - // Clang can emit "too many errors, stopping now", in which case `source` and `filename_ptr` are null - if (clang_err->source && clang_err->filename_ptr) { + // Clang can emit "too many errors, stopping now", in which case `source` and `filename_ptr` are null + if (clang_err->source && clang_err->filename_ptr) { ErrorMsg *err_msg = err_msg_create_with_offset( clang_err->filename_ptr ? buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : buf_alloc(), clang_err->line, clang_err->column, clang_err->offset, clang_err->source, buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len)); err_msg_add_note(parent_err_msg, err_msg); - } + } } return ira->codegen->invalid_instruction; @@ -22122,7 +22640,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru if ((err = resolve_ptr_align(ira, target->value.type, &src_ptr_align))) return ira->codegen->invalid_instruction; } else if (is_slice(target->value.type)) { - ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index]->type_entry; src_ptr_const = src_ptr_type->data.pointer.is_const; src_ptr_volatile = src_ptr_type->data.pointer.is_volatile; @@ -22165,7 +22683,7 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru if (!val) return ira->codegen->invalid_instruction; - ConstExprValue *len_val = &val->data.x_struct.fields[slice_len_index]; + ConstExprValue *len_val = val->data.x_struct.fields[slice_len_index]; if (value_is_comptime(len_val)) { known_len = bigint_as_u64(&len_val->data.x_bigint); have_known_len = true; @@ -22215,7 +22733,7 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct return ira->codegen->invalid_instruction; } - ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index]->type_entry; uint32_t alignment; if ((err = resolve_ptr_align(ira, src_ptr_type, &alignment))) @@ -22232,17 +22750,17 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct return ira->codegen->invalid_instruction; IrInstruction *result = ir_const(ira, &instruction->base, dest_slice_type); - result->value.data.x_struct.fields = create_const_vals(2); + result->value.data.x_struct.fields = alloc_const_vals_ptrs(2); - ConstExprValue *ptr_val = &result->value.data.x_struct.fields[slice_ptr_index]; - ConstExprValue *target_ptr_val = &target_val->data.x_struct.fields[slice_ptr_index]; + ConstExprValue *ptr_val = result->value.data.x_struct.fields[slice_ptr_index]; + ConstExprValue *target_ptr_val = target_val->data.x_struct.fields[slice_ptr_index]; copy_const_val(ptr_val, target_ptr_val, false); ptr_val->type = dest_ptr_type; - ConstExprValue *len_val = &result->value.data.x_struct.fields[slice_len_index]; + ConstExprValue *len_val = result->value.data.x_struct.fields[slice_len_index]; len_val->special = ConstValSpecialStatic; len_val->type = ira->codegen->builtin_types.entry_usize; - ConstExprValue *target_len_val = &target_val->data.x_struct.fields[slice_len_index]; + ConstExprValue *target_len_val = target_val->data.x_struct.fields[slice_len_index]; ZigType *elem_type = src_ptr_type->data.pointer.child_type; BigInt elem_size_bigint; bigint_init_unsigned(&elem_size_bigint, type_size(ira->codegen, elem_type)); @@ -23023,7 +23541,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction } } } else if (is_slice(array_type)) { - ZigType *ptr_type = array_type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry; return_type = get_slice_type(ira->codegen, ptr_type); } else { ir_add_error(ira, &instruction->base, @@ -23131,13 +23649,13 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction return ira->codegen->invalid_instruction; } - parent_ptr = &slice_ptr->data.x_struct.fields[slice_ptr_index]; + parent_ptr = slice_ptr->data.x_struct.fields[slice_ptr_index]; if (parent_ptr->special == ConstValSpecialUndef) { ir_add_error(ira, &instruction->base, buf_sprintf("slice of undefined")); return ira->codegen->invalid_instruction; } - ConstExprValue *len_val = &slice_ptr->data.x_struct.fields[slice_len_index]; + ConstExprValue *len_val = slice_ptr->data.x_struct.fields[slice_len_index]; switch (parent_ptr->data.x_ptr.special) { case ConstPtrSpecialInvalid: @@ -23209,9 +23727,9 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction IrInstruction *result = ir_const(ira, &instruction->base, return_type); ConstExprValue *out_val = &result->value; - out_val->data.x_struct.fields = create_const_vals(2); + out_val->data.x_struct.fields = alloc_const_vals_ptrs(2); - ConstExprValue *ptr_val = &out_val->data.x_struct.fields[slice_ptr_index]; + ConstExprValue *ptr_val = out_val->data.x_struct.fields[slice_ptr_index]; if (array_val) { size_t index = abs_offset + start_scalar; @@ -23258,7 +23776,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction zig_panic("TODO"); } - ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index]; + ConstExprValue *len_val = out_val->data.x_struct.fields[slice_len_index]; init_const_usize(ira->codegen, len_val, end_scalar - start_scalar); return result; @@ -23332,7 +23850,7 @@ static IrInstruction *ir_analyze_instruction_member_type(IrAnalyze *ira, IrInstr member_index, buf_ptr(&container_type->name), container_type->data.structure.src_field_count)); return ira->codegen->invalid_instruction; } - TypeStructField *field = &container_type->data.structure.fields[member_index]; + TypeStructField *field = container_type->data.structure.fields[member_index]; return ir_const_type(ira, &instruction->base, field->type_entry); } else if (container_type->id == ZigTypeIdUnion) { @@ -23374,7 +23892,7 @@ static IrInstruction *ir_analyze_instruction_member_name(IrAnalyze *ira, IrInstr member_index, buf_ptr(&container_type->name), container_type->data.structure.src_field_count)); return ira->codegen->invalid_instruction; } - TypeStructField *field = &container_type->data.structure.fields[member_index]; + TypeStructField *field = container_type->data.structure.fields[member_index]; IrInstruction *result = ir_const(ira, &instruction->base, nullptr); init_const_str_lit(ira->codegen, &result->value, field->name); @@ -24360,7 +24878,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 ZigType *fn_type = get_fn_type(ira->codegen, &fn_type_id); result_type = get_optional_type(ira->codegen, fn_type); } else if (is_slice(target_type)) { - ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index]->type_entry; if ((err = resolve_ptr_align(ira, slice_ptr_type, &old_align_bytes))) return ira->codegen->invalid_instruction; ZigType *result_ptr_type = adjust_ptr_align(ira->codegen, slice_ptr_type, align_bytes); @@ -24409,6 +24927,10 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ ZigType *src_type = ptr->value.type; assert(!type_is_invalid(src_type)); + if (src_type == dest_type) { + return ptr; + } + // We have a check for zero bits later so we use get_src_ptr_type to // validate src_type and dest_type. @@ -24458,6 +24980,9 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_ IrInstruction *result; if (ptr->value.data.x_ptr.mut == ConstPtrMutInfer) { result = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on); + + if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown))) + return ira->codegen->invalid_instruction; } else { result = ir_const(ira, source_instr, dest_type); } @@ -24598,10 +25123,10 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue case ContainerLayoutExtern: { size_t src_field_count = val->type->data.structure.src_field_count; for (size_t field_i = 0; field_i < src_field_count; field_i += 1) { - TypeStructField *struct_field = &val->type->data.structure.fields[field_i]; + TypeStructField *struct_field = val->type->data.structure.fields[field_i]; if (struct_field->gen_index == SIZE_MAX) continue; - ConstExprValue *field_val = &val->data.x_struct.fields[field_i]; + ConstExprValue *field_val = val->data.x_struct.fields[field_i]; size_t offset = struct_field->offset; buf_write_value_bytes(codegen, buf + offset, field_val); } @@ -24627,12 +25152,12 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue bigint_init_unsigned(&big_int, 0); size_t used_bits = 0; while (src_i < src_field_count) { - TypeStructField *field = &val->type->data.structure.fields[src_i]; + TypeStructField *field = val->type->data.structure.fields[src_i]; assert(field->gen_index != SIZE_MAX); if (field->gen_index != gen_i) break; uint32_t packed_bits_size = type_size_bits(codegen, field->type_entry); - buf_write_value_bytes(codegen, child_buf, &val->data.x_struct.fields[src_i]); + buf_write_value_bytes(codegen, child_buf, val->data.x_struct.fields[src_i]); BigInt child_val; bigint_read_twos_complement(&child_val, child_buf, packed_bits_size, is_big_endian, false); @@ -24770,11 +25295,11 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou } case ContainerLayoutExtern: { size_t src_field_count = val->type->data.structure.src_field_count; - val->data.x_struct.fields = create_const_vals(src_field_count); + val->data.x_struct.fields = alloc_const_vals_ptrs(src_field_count); for (size_t field_i = 0; field_i < src_field_count; field_i += 1) { - ConstExprValue *field_val = &val->data.x_struct.fields[field_i]; + ConstExprValue *field_val = val->data.x_struct.fields[field_i]; field_val->special = ConstValSpecialStatic; - TypeStructField *struct_field = &val->type->data.structure.fields[field_i]; + TypeStructField *struct_field = val->type->data.structure.fields[field_i]; field_val->type = struct_field->type_entry; if (struct_field->gen_index == SIZE_MAX) continue; @@ -24787,7 +25312,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou } case ContainerLayoutPacked: { size_t src_field_count = val->type->data.structure.src_field_count; - val->data.x_struct.fields = create_const_vals(src_field_count); + val->data.x_struct.fields = alloc_const_vals_ptrs(src_field_count); size_t gen_field_count = val->type->data.structure.gen_field_count; size_t gen_i = 0; size_t src_i = 0; @@ -24805,11 +25330,11 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou BigInt big_int; bigint_read_twos_complement(&big_int, buf + offset, big_int_byte_count * 8, is_big_endian, false); while (src_i < src_field_count) { - TypeStructField *field = &val->type->data.structure.fields[src_i]; + TypeStructField *field = val->type->data.structure.fields[src_i]; src_assert(field->gen_index != SIZE_MAX, source_node); if (field->gen_index != gen_i) break; - ConstExprValue *field_val = &val->data.x_struct.fields[src_i]; + ConstExprValue *field_val = val->data.x_struct.fields[src_i]; field_val->special = ConstValSpecialStatic; field_val->type = field->type_entry; uint32_t packed_bits_size = type_size_bits(codegen, field->type_entry); @@ -24992,6 +25517,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, } static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstructionPtrToInt *instruction) { + Error err; IrInstruction *target = instruction->target->child; if (type_is_invalid(target->value.type)) return ira->codegen->invalid_instruction; @@ -25005,6 +25531,8 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru return ira->codegen->invalid_instruction; } + if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown))) + return ira->codegen->invalid_instruction; if (!type_has_bits(target->value.type)) { ir_add_error(ira, target, buf_sprintf("pointer to size 0 type has no address")); @@ -25065,7 +25593,7 @@ static IrInstruction *ir_analyze_instruction_align_cast(IrAnalyze *ira, IrInstru ZigType *elem_type = nullptr; if (is_slice(target->value.type)) { - ZigType *slice_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *slice_ptr_type = target->value.type->data.structure.fields[slice_ptr_index]->type_entry; elem_type = slice_ptr_type->data.pointer.child_type; } else if (target->value.type->id == ZigTypeIdPointer) { elem_type = target->value.type->data.pointer.child_type; @@ -25142,6 +25670,10 @@ static IrInstruction *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstruct if (!ir_resolve_usize(ira, arg_index_inst, &arg_index)) return ira->codegen->invalid_instruction; + if (fn_type->id == ZigTypeIdBoundFn) { + fn_type = fn_type->data.bound_fn.fn_type; + arg_index += 1; + } if (fn_type->id != ZigTypeIdFn) { ir_add_error(ira, fn_type_inst, buf_sprintf("expected function, found '%s'", buf_ptr(&fn_type->name))); return ira->codegen->invalid_instruction; @@ -25149,6 +25681,10 @@ static IrInstruction *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstruct FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; if (arg_index >= fn_type_id->param_count) { + if (instruction->allow_var) { + // TODO remove this with var args + return ir_const_type(ira, &instruction->base, ira->codegen->builtin_types.entry_var); + } ir_add_error(ira, arg_index_inst, buf_sprintf("arg index %" ZIG_PRI_u64 " out of bounds; '%s' has %" ZIG_PRI_usize " arguments", arg_index, buf_ptr(&fn_type->name), fn_type_id->param_count)); @@ -25160,10 +25696,14 @@ static IrInstruction *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstruct // Args are only unresolved if our function is generic. ir_assert(fn_type->data.fn.is_generic, &instruction->base); - ir_add_error(ira, arg_index_inst, - buf_sprintf("@ArgType could not resolve the type of arg %" ZIG_PRI_u64 " because '%s' is generic", - arg_index, buf_ptr(&fn_type->name))); - return ira->codegen->invalid_instruction; + if (instruction->allow_var) { + return ir_const_type(ira, &instruction->base, ira->codegen->builtin_types.entry_var); + } else { + ir_add_error(ira, arg_index_inst, + buf_sprintf("@ArgType could not resolve the type of arg %" ZIG_PRI_u64 " because '%s' is generic", + arg_index, buf_ptr(&fn_type->name))); + return ira->codegen->invalid_instruction; + } } return ir_const_type(ira, &instruction->base, result_type); } @@ -25216,9 +25756,29 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op buf_sprintf("%" PRIu32 "-bit integer type is not a power of 2", operand_type->data.integral.bit_count)); return ira->codegen->builtin_types.entry_invalid; } + } else if (operand_type->id == ZigTypeIdEnum) { + ZigType *int_type = operand_type->data.enumeration.tag_int_type; + if (int_type->data.integral.bit_count < 8) { + ir_add_error(ira, op, + buf_sprintf("expected enum tag type 8 bits or larger, found %" PRIu32 "-bit tag type", + int_type->data.integral.bit_count)); + return ira->codegen->builtin_types.entry_invalid; + } + uint32_t max_atomic_bits = target_arch_largest_atomic_bits(ira->codegen->zig_target->arch); + if (int_type->data.integral.bit_count > max_atomic_bits) { + ir_add_error(ira, op, + buf_sprintf("expected %" PRIu32 "-bit enum tag type or smaller, found %" PRIu32 "-bit tag type", + max_atomic_bits, int_type->data.integral.bit_count)); + return ira->codegen->builtin_types.entry_invalid; + } + if (!is_power_of_2(int_type->data.integral.bit_count)) { + ir_add_error(ira, op, + buf_sprintf("%" PRIu32 "-bit enum tag type is not a power of 2", int_type->data.integral.bit_count)); + return ira->codegen->builtin_types.entry_invalid; + } } else if (get_codegen_ptr_type(operand_type) == nullptr) { ir_add_error(ira, op, - buf_sprintf("expected integer or pointer type, found '%s'", buf_ptr(&operand_type->name))); + buf_sprintf("expected integer, enum or pointer type, found '%s'", buf_ptr(&operand_type->name))); return ira->codegen->builtin_types.entry_invalid; } @@ -25249,6 +25809,12 @@ static IrInstruction *ir_analyze_instruction_atomic_rmw(IrAnalyze *ira, IrInstru } } + if (operand_type->id == ZigTypeIdEnum && op != AtomicRmwOp_xchg) { + ir_add_error(ira, instruction->op, + buf_sprintf("@atomicRmw on enum only works with .Xchg")); + return ira->codegen->invalid_instruction; + } + IrInstruction *operand = instruction->operand->child; if (type_is_invalid(operand->value.type)) return ira->codegen->invalid_instruction; @@ -25323,6 +25889,56 @@ static IrInstruction *ir_analyze_instruction_atomic_load(IrAnalyze *ira, IrInstr return result; } +static IrInstruction *ir_analyze_instruction_atomic_store(IrAnalyze *ira, IrInstructionAtomicStore *instruction) { + ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->operand_type->child); + if (type_is_invalid(operand_type)) + return ira->codegen->invalid_instruction; + + IrInstruction *ptr_inst = instruction->ptr->child; + if (type_is_invalid(ptr_inst->value.type)) + return ira->codegen->invalid_instruction; + + ZigType *ptr_type = get_pointer_to_type(ira->codegen, operand_type, false); + IrInstruction *casted_ptr = ir_implicit_cast(ira, ptr_inst, ptr_type); + if (type_is_invalid(casted_ptr->value.type)) + return ira->codegen->invalid_instruction; + + IrInstruction *value = instruction->value->child; + if (type_is_invalid(value->value.type)) + return ira->codegen->invalid_instruction; + + IrInstruction *casted_value = ir_implicit_cast(ira, value, operand_type); + if (type_is_invalid(casted_value->value.type)) + return ira->codegen->invalid_instruction; + + + AtomicOrder ordering; + if (instruction->ordering == nullptr) { + ordering = instruction->resolved_ordering; + } else { + if (!ir_resolve_atomic_order(ira, instruction->ordering->child, &ordering)) + return ira->codegen->invalid_instruction; + } + + if (ordering == AtomicOrderAcquire || ordering == AtomicOrderAcqRel) { + ir_assert(instruction->ordering != nullptr, &instruction->base); + ir_add_error(ira, instruction->ordering, + buf_sprintf("@atomicStore atomic ordering must not be Acquire or AcqRel")); + return ira->codegen->invalid_instruction; + } + + if (instr_is_comptime(casted_value) && instr_is_comptime(casted_ptr)) { + IrInstruction *result = ir_analyze_store_ptr(ira, &instruction->base, casted_ptr, value, false); + result->value.type = ira->codegen->builtin_types.entry_void; + return result; + } + + IrInstruction *result = ir_build_atomic_store(&ira->new_irb, instruction->base.scope, + instruction->base.source_node, nullptr, casted_ptr, casted_value, nullptr, ordering); + result->value.type = ira->codegen->builtin_types.entry_void; + return result; +} + static IrInstruction *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira, IrInstructionSaveErrRetAddr *instruction) { IrInstruction *result = ir_build_save_err_ret_addr(&ira->new_irb, instruction->base.scope, instruction->base.source_node); @@ -25854,6 +26470,26 @@ static IrInstruction *ir_analyze_instruction_end_expr(IrAnalyze *ira, IrInstruct return ir_const_void(ira, &instruction->base); } +static IrInstruction *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrInstructionImplicitCast *instruction) { + IrInstruction *operand = instruction->operand->child; + if (type_is_invalid(operand->value.type)) + return operand; + + IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, + &instruction->result_loc_cast->base, operand->value.type, operand, false, false, true); + if (result_loc != nullptr && (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))) + return result_loc; + + if (instruction->result_loc_cast->parent->gen_instruction != nullptr) { + return instruction->result_loc_cast->parent->gen_instruction; + } + + ZigType *dest_type = ir_resolve_type(ira, instruction->result_loc_cast->base.source_instruction->child); + if (type_is_invalid(dest_type)) + return ira->codegen->invalid_instruction; + return ir_implicit_cast_with_result(ira, &instruction->base, operand, dest_type, nullptr); +} + static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInstructionBitCastSrc *instruction) { IrInstruction *operand = instruction->operand->child; if (type_is_invalid(operand->value.type)) @@ -26337,6 +26973,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction return ir_analyze_instruction_atomic_rmw(ira, (IrInstructionAtomicRmw *)instruction); case IrInstructionIdAtomicLoad: return ir_analyze_instruction_atomic_load(ira, (IrInstructionAtomicLoad *)instruction); + case IrInstructionIdAtomicStore: + return ir_analyze_instruction_atomic_store(ira, (IrInstructionAtomicStore *)instruction); case IrInstructionIdSaveErrRetAddr: return ir_analyze_instruction_save_err_ret_addr(ira, (IrInstructionSaveErrRetAddr *)instruction); case IrInstructionIdAddImplicitReturnType: @@ -26517,6 +27155,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdSaveErrRetAddr: case IrInstructionIdAddImplicitReturnType: case IrInstructionIdAtomicRmw: + case IrInstructionIdAtomicStore: case IrInstructionIdCmpxchgGen: case IrInstructionIdCmpxchgSrc: case IrInstructionIdAssertZero: diff --git a/src/ir_print.cpp b/src/ir_print.cpp @@ -324,6 +324,8 @@ const char* ir_instruction_type_str(IrInstructionId id) { return "AtomicRmw"; case IrInstructionIdAtomicLoad: return "AtomicLoad"; + case IrInstructionIdAtomicStore: + return "AtomicStore"; case IrInstructionIdSaveErrRetAddr: return "SaveErrRetAddr"; case IrInstructionIdAddImplicitReturnType: @@ -601,6 +603,12 @@ static void ir_print_result_loc_bit_cast(IrPrint *irp, ResultLocBitCast *result_ fprintf(irp->f, ")"); } +static void ir_print_result_loc_cast(IrPrint *irp, ResultLocCast *result_loc_cast) { + fprintf(irp->f, "cast(ty="); + ir_print_other_instruction(irp, result_loc_cast->base.source_instruction); + fprintf(irp->f, ")"); +} + static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) { switch (result_loc->id) { case ResultLocIdInvalid: @@ -619,6 +627,8 @@ static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) { return ir_print_result_loc_peer(irp, (ResultLocPeer *)result_loc); case ResultLocIdBitCast: return ir_print_result_loc_bit_cast(irp, (ResultLocBitCast *)result_loc); + case ResultLocIdCast: + return ir_print_result_loc_cast(irp, (ResultLocCast *)result_loc); case ResultLocIdPeerParent: fprintf(irp->f, "peer_parent"); return; @@ -723,7 +733,6 @@ static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) { } static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerInitList *instruction) { - ir_print_other_instruction(irp, instruction->container_type); fprintf(irp->f, "{"); if (instruction->item_count > 50) { fprintf(irp->f, "...(%" ZIG_PRI_usize " items)...", instruction->item_count); @@ -735,11 +744,11 @@ static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerIni ir_print_other_instruction(irp, result_loc); } } - fprintf(irp->f, "}"); + fprintf(irp->f, "}result="); + ir_print_other_instruction(irp, instruction->result_loc); } static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerInitFields *instruction) { - ir_print_other_instruction(irp, instruction->container_type); fprintf(irp->f, "{"); for (size_t i = 0; i < instruction->field_count; i += 1) { IrInstructionContainerInitFieldsField *field = &instruction->fields[i]; @@ -747,7 +756,8 @@ static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerI fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field->name)); ir_print_other_instruction(irp, field->result_loc); } - fprintf(irp->f, "} // container init"); + fprintf(irp->f, "}result="); + ir_print_other_instruction(irp, instruction->result_loc); } static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruction) { @@ -1484,6 +1494,13 @@ static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruc fprintf(irp->f, ")"); } +static void ir_print_implicit_cast(IrPrint *irp, IrInstructionImplicitCast *instruction) { + fprintf(irp->f, "@implicitCast("); + ir_print_other_instruction(irp, instruction->operand); + fprintf(irp->f, ")result="); + ir_print_result_loc(irp, &instruction->result_loc_cast->base); +} + static void ir_print_bit_cast_src(IrPrint *irp, IrInstructionBitCastSrc *instruction) { fprintf(irp->f, "@bitCast("); ir_print_other_instruction(irp, instruction->operand); @@ -1739,14 +1756,6 @@ static void ir_print_align_cast(IrPrint *irp, IrInstructionAlignCast *instructio fprintf(irp->f, ")"); } -static void ir_print_implicit_cast(IrPrint *irp, IrInstructionImplicitCast *instruction) { - fprintf(irp->f, "@implicitCast("); - ir_print_other_instruction(irp, instruction->dest_type); - fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->target); - fprintf(irp->f, ")"); -} - static void ir_print_resolve_result(IrPrint *irp, IrInstructionResolveResult *instruction) { fprintf(irp->f, "ResolveResult("); ir_print_result_loc(irp, instruction->result_loc); @@ -1864,6 +1873,27 @@ static void ir_print_atomic_load(IrPrint *irp, IrInstructionAtomicLoad *instruct fprintf(irp->f, ")"); } +static void ir_print_atomic_store(IrPrint *irp, IrInstructionAtomicStore *instruction) { + fprintf(irp->f, "@atomicStore("); + if (instruction->operand_type != nullptr) { + ir_print_other_instruction(irp, instruction->operand_type); + } else { + fprintf(irp->f, "[TODO print]"); + } + fprintf(irp->f, ","); + ir_print_other_instruction(irp, instruction->ptr); + fprintf(irp->f, ","); + ir_print_other_instruction(irp, instruction->value); + fprintf(irp->f, ","); + if (instruction->ordering != nullptr) { + ir_print_other_instruction(irp, instruction->ordering); + } else { + fprintf(irp->f, "[TODO print]"); + } + fprintf(irp->f, ")"); +} + + static void ir_print_save_err_ret_addr(IrPrint *irp, IrInstructionSaveErrRetAddr *instruction) { fprintf(irp->f, "@saveErrRetAddr()"); } @@ -2424,6 +2454,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction, bool case IrInstructionIdAtomicLoad: ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction); break; + case IrInstructionIdAtomicStore: + ir_print_atomic_store(irp, (IrInstructionAtomicStore *)instruction); + break; case IrInstructionIdEnumToInt: ir_print_enum_to_int(irp, (IrInstructionEnumToInt *)instruction); break; @@ -2542,3 +2575,18 @@ void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, ir_print_instruction(irp, instruction, false); } + +void ir_print_const_expr(CodeGen *codegen, FILE *f, ConstExprValue *value, int indent_size, IrPass pass) { + IrPrint ir_print = {}; + IrPrint *irp = &ir_print; + irp->pass = pass; + irp->codegen = codegen; + irp->f = f; + irp->indent = indent_size; + irp->indent_size = indent_size; + irp->printed = {}; + irp->printed.init(4); + irp->pending = {}; + + ir_print_const_value(irp, value); +} diff --git a/src/ir_print.hpp b/src/ir_print.hpp @@ -14,6 +14,7 @@ void ir_print(CodeGen *codegen, FILE *f, IrExecutable *executable, int indent_size, IrPass pass); void ir_print_instruction(CodeGen *codegen, FILE *f, IrInstruction *instruction, int indent_size, IrPass pass); +void ir_print_const_expr(CodeGen *codegen, FILE *f, ConstExprValue *value, int indent_size, IrPass pass); const char* ir_instruction_type_str(IrInstructionId id); diff --git a/src/parser.cpp b/src/parser.cpp @@ -81,7 +81,7 @@ static AstNode *ast_parse_for_type_expr(ParseContext *pc); static AstNode *ast_parse_while_type_expr(ParseContext *pc); static AstNode *ast_parse_switch_expr(ParseContext *pc); static AstNode *ast_parse_asm_expr(ParseContext *pc); -static AstNode *ast_parse_enum_lit(ParseContext *pc); +static AstNode *ast_parse_anon_lit(ParseContext *pc); static AstNode *ast_parse_asm_output(ParseContext *pc); static AsmOutput *ast_parse_asm_output_item(ParseContext *pc); static AstNode *ast_parse_asm_input(ParseContext *pc); @@ -493,6 +493,9 @@ static AstNode *ast_parse_root(ParseContext *pc) { node->data.container_decl.layout = ContainerLayoutAuto; node->data.container_decl.kind = ContainerKindStruct; node->data.container_decl.is_root = true; + if (buf_len(&members.doc_comments) != 0) { + node->data.container_decl.doc_comments = members.doc_comments; + } return node; } @@ -514,6 +517,21 @@ static Token *ast_parse_doc_comments(ParseContext *pc, Buf *buf) { return first_doc_token; } +static void ast_parse_container_doc_comments(ParseContext *pc, Buf *buf) { + if (buf_len(buf) != 0 && peek_token(pc)->id == TokenIdContainerDocComment) { + buf_append_char(buf, '\n'); + } + Token *doc_token = nullptr; + while ((doc_token = eat_token_if(pc, TokenIdContainerDocComment))) { + if (buf->list.length == 0) { + buf_resize(buf, 0); + } + // chops off '//!' but leaves '\n' + buf_append_mem(buf, buf_ptr(pc->buf) + doc_token->start_pos + 3, + doc_token->end_pos - doc_token->start_pos - 3); + } +} + // ContainerMembers // <- TestDecl ContainerMembers // / TopLevelComptime ContainerMembers @@ -523,7 +541,11 @@ static Token *ast_parse_doc_comments(ParseContext *pc, Buf *buf) { // / static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { AstNodeContainerDecl res = {}; + Buf tld_doc_comment_buf = BUF_INIT; + buf_resize(&tld_doc_comment_buf, 0); for (;;) { + ast_parse_container_doc_comments(pc, &tld_doc_comment_buf); + AstNode *test_decl = ast_parse_test_decl(pc); if (test_decl != nullptr) { res.decls.append(test_decl); @@ -566,7 +588,7 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { break; } - + res.doc_comments = tld_doc_comment_buf; return res; } @@ -1600,9 +1622,9 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { if (container_decl != nullptr) return container_decl; - AstNode *enum_lit = ast_parse_enum_lit(pc); - if (enum_lit != nullptr) - return enum_lit; + AstNode *anon_lit = ast_parse_anon_lit(pc); + if (anon_lit != nullptr) + return anon_lit; AstNode *error_set_decl = ast_parse_error_set_decl(pc); if (error_set_decl != nullptr) @@ -1876,16 +1898,22 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc) { return res; } -static AstNode *ast_parse_enum_lit(ParseContext *pc) { +static AstNode *ast_parse_anon_lit(ParseContext *pc) { Token *period = eat_token_if(pc, TokenIdDot); if (period == nullptr) return nullptr; - Token *identifier = expect_token(pc, TokenIdSymbol); - AstNode *res = ast_create_node(pc, NodeTypeEnumLiteral, period); - res->data.enum_literal.period = period; - res->data.enum_literal.identifier = identifier; - return res; + // anon enum literal + Token *identifier = eat_token_if(pc, TokenIdSymbol); + if (identifier != nullptr) { + AstNode *res = ast_create_node(pc, NodeTypeEnumLiteral, period); + res->data.enum_literal.period = period; + res->data.enum_literal.identifier = identifier; + return res; + } + + // anon container literal + return ast_parse_init_list(pc); } // AsmOutput <- COLON AsmOutputList AsmInput? @@ -2019,7 +2047,12 @@ static AstNode *ast_parse_field_init(ParseContext *pc) { if (first == nullptr) return nullptr; - Token *name = expect_token(pc, TokenIdSymbol); + Token *name = eat_token_if(pc, TokenIdSymbol); + if (name == nullptr) { + // Because of anon literals ".{" is also valid. + put_back_token(pc); + return nullptr; + } if (eat_token_if(pc, TokenIdEq) == nullptr) { // Because ".Name" can also be intepreted as an enum literal, we should put back // those two tokens again so that the parser can try to parse them as the enum @@ -2791,6 +2824,9 @@ static AstNode *ast_parse_container_decl_auto(ParseContext *pc) { res->data.container_decl.fields = members.fields; res->data.container_decl.decls = members.decls; + if (buf_len(&members.doc_comments) != 0) { + res->data.container_decl.doc_comments = members.doc_comments; + } return res; } diff --git a/src/range_set.cpp b/src/range_set.cpp @@ -40,6 +40,9 @@ void rangeset_sort(RangeSet *rs) { } bool rangeset_spans(RangeSet *rs, BigInt *first, BigInt *last) { + if (rs->src_range_list.length == 0) + return false; + rangeset_sort(rs); const Range *first_range = &rs->src_range_list.at(0).range; diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp @@ -153,7 +153,6 @@ static const struct ZigKeyword zig_keywords[] = { {"undefined", TokenIdKeywordUndefined}, {"union", TokenIdKeywordUnion}, {"unreachable", TokenIdKeywordUnreachable}, - {"use", TokenIdKeywordUsingNamespace}, {"usingnamespace", TokenIdKeywordUsingNamespace}, {"var", TokenIdKeywordVar}, {"volatile", TokenIdKeywordVolatile}, @@ -199,6 +198,7 @@ enum TokenizeState { TokenizeStateSawSlash, TokenizeStateSawSlash2, TokenizeStateSawSlash3, + TokenizeStateSawSlashBang, TokenizeStateSawBackslash, TokenizeStateSawPercent, TokenizeStateSawPlus, @@ -210,6 +210,7 @@ enum TokenizeState { TokenizeStateSawBar, TokenizeStateSawBarBar, TokenizeStateDocComment, + TokenizeStateContainerDocComment, TokenizeStateLineComment, TokenizeStateLineString, TokenizeStateLineStringEnd, @@ -939,6 +940,9 @@ void tokenize(Buf *buf, Tokenization *out) { case '/': t.state = TokenizeStateSawSlash3; break; + case '!': + t.state = TokenizeStateSawSlashBang; + break; case '\n': cancel_token(&t); t.state = TokenizeStateStart; @@ -966,6 +970,19 @@ void tokenize(Buf *buf, Tokenization *out) { break; } break; + case TokenizeStateSawSlashBang: + switch (c) { + case '\n': + set_token_id(&t, t.cur_tok, TokenIdContainerDocComment); + end_token(&t); + t.state = TokenizeStateStart; + break; + default: + set_token_id(&t, t.cur_tok, TokenIdContainerDocComment); + t.state = TokenizeStateContainerDocComment; + break; + } + break; case TokenizeStateSawBackslash: switch (c) { case '\\': @@ -1056,6 +1073,17 @@ void tokenize(Buf *buf, Tokenization *out) { break; } break; + case TokenizeStateContainerDocComment: + switch (c) { + case '\n': + end_token(&t); + t.state = TokenizeStateStart; + break; + default: + // do nothing + break; + } + break; case TokenizeStateSymbolFirstC: switch (c) { case '"': @@ -1546,6 +1574,7 @@ void tokenize(Buf *buf, Tokenization *out) { case TokenizeStateSawBarBar: case TokenizeStateLBracket: case TokenizeStateDocComment: + case TokenizeStateContainerDocComment: end_token(&t); break; case TokenizeStateSawDotDot: @@ -1560,6 +1589,7 @@ void tokenize(Buf *buf, Tokenization *out) { case TokenizeStateLineComment: case TokenizeStateSawSlash2: case TokenizeStateSawSlash3: + case TokenizeStateSawSlashBang: break; } if (t.state != TokenizeStateError) { @@ -1607,6 +1637,7 @@ const char * token_name(TokenId id) { case TokenIdDash: return "-"; case TokenIdDivEq: return "/="; case TokenIdDocComment: return "DocComment"; + case TokenIdContainerDocComment: return "ContainerDocComment"; case TokenIdDot: return "."; case TokenIdDotStar: return ".*"; case TokenIdEllipsis2: return ".."; diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp @@ -43,6 +43,7 @@ enum TokenId { TokenIdDash, TokenIdDivEq, TokenIdDocComment, + TokenIdContainerDocComment, TokenIdDot, TokenIdDotStar, TokenIdEllipsis2, diff --git a/src/translate_c.cpp b/src/translate_c.cpp @@ -221,6 +221,15 @@ static AstNode *trans_create_node_opaque(Context *c) { return trans_create_node_builtin_fn_call_str(c, "OpaqueType"); } +static AstNode *trans_create_node_cast(Context *c, AstNode *dest_type, AstNode *operand) { + AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); + node->data.fn_call_expr.fn_ref_expr = trans_create_node_symbol(c, buf_create_from_str("as")); + node->data.fn_call_expr.modifier = CallModifierBuiltin; + node->data.fn_call_expr.params.append(dest_type); + node->data.fn_call_expr.params.append(operand); + return node; +} + static AstNode *trans_create_node_fn_call_1(Context *c, AstNode *fn_ref_expr, AstNode *arg1) { AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); node->data.fn_call_expr.fn_ref_expr = fn_ref_expr; @@ -337,14 +346,6 @@ static AstNode *trans_create_node_unsigned(Context *c, uint64_t x) { return trans_create_node_unsigned_negative(c, x, false); } -static AstNode *trans_create_node_cast(Context *c, AstNode *dest, AstNode *src) { - AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); - node->data.fn_call_expr.fn_ref_expr = dest; - node->data.fn_call_expr.params.resize(1); - node->data.fn_call_expr.params.items[0] = src; - return node; -} - static AstNode *trans_create_node_unsigned_negative_type(Context *c, uint64_t x, bool is_negative, const char *type_name) { @@ -701,7 +702,7 @@ static AstNode* trans_c_cast(Context *c, ZigClangSourceLocation source_location, if (c_is_unsigned_integer(c, dest_type) && qual_type_is_ptr(src_type)) { AstNode *addr_node = trans_create_node_builtin_fn_call_str(c, "ptrToInt"); addr_node->data.fn_call_expr.params.append(expr); - return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), addr_node); + return trans_create_node_cast(c, trans_qual_type(c, dest_type, source_location), addr_node); } if (c_is_unsigned_integer(c, src_type) && qual_type_is_ptr(dest_type)) { AstNode *ptr_node = trans_create_node_builtin_fn_call_str(c, "intToPtr"); @@ -712,7 +713,7 @@ static AstNode* trans_c_cast(Context *c, ZigClangSourceLocation source_location, // TODO: maybe widen to increase size // TODO: maybe bitcast to change sign // TODO: maybe truncate to reduce size - return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr); + return trans_create_node_cast(c, trans_qual_type(c, dest_type, source_location), expr); } static bool c_is_signed_integer(Context *c, ZigClangQualType qt) { @@ -1212,6 +1213,11 @@ static AstNode *trans_type(Context *c, const ZigClangType *ty, ZigClangSourceLoc const ZigClangAttributedType *attributed_ty = reinterpret_cast<const ZigClangAttributedType *>(ty); return trans_qual_type(c, ZigClangAttributedType_getEquivalentType(attributed_ty), source_loc); } + case ZigClangType_MacroQualified: + { + const ZigClangMacroQualifiedType *macroqualified_ty = reinterpret_cast<const ZigClangMacroQualifiedType *>(ty); + return trans_qual_type(c, ZigClangMacroQualifiedType_getModifiedType(macroqualified_ty), source_loc); + } case ZigClangType_IncompleteArray: { const ZigClangIncompleteArrayType *incomplete_array_ty = reinterpret_cast<const ZigClangIncompleteArrayType *>(ty); @@ -1261,7 +1267,6 @@ static AstNode *trans_type(Context *c, const ZigClangType *ty, ZigClangSourceLoc case ZigClangType_DeducedTemplateSpecialization: case ZigClangType_DependentAddressSpace: case ZigClangType_DependentVector: - case ZigClangType_MacroQualified: emit_warning(c, source_loc, "unsupported type: '%s'", ZigClangType_getTypeClassName(ty)); return nullptr; } @@ -1527,7 +1532,7 @@ static AstNode *trans_create_shift_op(Context *c, TransScope *scope, ZigClangQua AstNode *rhs = trans_expr(c, ResultUsedYes, scope, rhs_expr, TransRValue); if (rhs == nullptr) return nullptr; - AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); + AstNode *coerced_rhs = trans_create_node_cast(c, rhs_type, rhs); return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs); } @@ -1702,7 +1707,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result AstNode *rhs = trans_expr(c, ResultUsedYes, scope, ZigClangCompoundAssignOperator_getRHS(stmt), TransRValue); if (rhs == nullptr) return nullptr; - AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); + AstNode *coerced_rhs = trans_create_node_cast(c, rhs_type, rhs); return trans_create_node_bin_op(c, lhs, assign_op, coerced_rhs); } else { @@ -1733,7 +1738,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result AstNode *rhs = trans_expr(c, ResultUsedYes, &child_scope->base, ZigClangCompoundAssignOperator_getRHS(stmt), TransRValue); if (rhs == nullptr) return nullptr; - AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs); + AstNode *coerced_rhs = trans_create_node_cast(c, rhs_type, rhs); // operation_type(*_ref) AstNode *operation_type_cast = trans_c_cast(c, rhs_location, @@ -2684,7 +2689,7 @@ static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type) // @TagType(Enum)(0) AstNode *zero = trans_create_node_unsigned_negative(c, 0, false); - AstNode *casted_zero = trans_create_node_fn_call_1(c, tag_type, zero); + AstNode *casted_zero = trans_create_node_cast(c, tag_type, zero); // @bitCast(Enum, @TagType(Enum)(0)) AstNode *bitcast = trans_create_node_builtin_fn_call_str(c, "bitCast"); diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp @@ -2214,6 +2214,11 @@ struct ZigClangQualType ZigClangAttributedType_getEquivalentType(const struct Zi return bitcast(casted->getEquivalentType()); } +struct ZigClangQualType ZigClangMacroQualifiedType_getModifiedType(const struct ZigClangMacroQualifiedType *self) { + auto casted = reinterpret_cast<const clang::MacroQualifiedType *>(self); + return bitcast(casted->getModifiedType()); +} + struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *self) { auto casted = reinterpret_cast<const clang::ElaboratedType *>(self); return bitcast(casted->getNamedType()); diff --git a/src/zig_clang.h b/src/zig_clang.h @@ -112,6 +112,7 @@ struct ZigClangImplicitCastExpr; struct ZigClangIncompleteArrayType; struct ZigClangIntegerLiteral; struct ZigClangMacroDefinitionRecord; +struct ZigClangMacroQualifiedType; struct ZigClangMemberExpr; struct ZigClangNamedDecl; struct ZigClangNone; @@ -1004,6 +1005,8 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangParenType_getInnerType(const struct ZIG_EXTERN_C struct ZigClangQualType ZigClangAttributedType_getEquivalentType(const struct ZigClangAttributedType *); +ZIG_EXTERN_C struct ZigClangQualType ZigClangMacroQualifiedType_getModifiedType(const struct ZigClangMacroQualifiedType *); + ZIG_EXTERN_C struct ZigClangQualType ZigClangElaboratedType_getNamedType(const struct ZigClangElaboratedType *); ZIG_EXTERN_C enum ZigClangElaboratedTypeKeyword ZigClangElaboratedType_getKeyword(const struct ZigClangElaboratedType *); diff --git a/test/compare_output.zig b/test/compare_output.zig @@ -14,12 +14,12 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { cases.addCase(x: { var tc = cases.create("multiple files with private function", - \\use @import("std").io; - \\use @import("foo.zig"); + \\usingnamespace @import("std").io; + \\usingnamespace @import("foo.zig"); \\ \\pub fn main() void { \\ privateFunction(); - \\ const stdout = &(getStdOut() catch unreachable).outStream().stream; + \\ const stdout = &getStdOut().outStream().stream; \\ stdout.print("OK 2\n") catch unreachable; \\} \\ @@ -29,12 +29,12 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { , "OK 1\nOK 2\n"); tc.addSourceFile("foo.zig", - \\use @import("std").io; + \\usingnamespace @import("std").io; \\ \\// purposefully conflicting function with main.zig \\// but it's private so it should be OK \\fn privateFunction() void { - \\ const stdout = &(getStdOut() catch unreachable).outStream().stream; + \\ const stdout = &getStdOut().outStream().stream; \\ stdout.print("OK 1\n") catch unreachable; \\} \\ @@ -48,8 +48,8 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { cases.addCase(x: { var tc = cases.create("import segregation", - \\use @import("foo.zig"); - \\use @import("bar.zig"); + \\usingnamespace @import("foo.zig"); + \\usingnamespace @import("bar.zig"); \\ \\pub fn main() void { \\ foo_function(); @@ -58,20 +58,20 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { , "OK\nOK\n"); tc.addSourceFile("foo.zig", - \\use @import("std").io; + \\usingnamespace @import("std").io; \\pub fn foo_function() void { - \\ const stdout = &(getStdOut() catch unreachable).outStream().stream; + \\ const stdout = &getStdOut().outStream().stream; \\ stdout.print("OK\n") catch unreachable; \\} ); tc.addSourceFile("bar.zig", - \\use @import("other.zig"); - \\use @import("std").io; + \\usingnamespace @import("other.zig"); + \\usingnamespace @import("std").io; \\ \\pub fn bar_function() void { \\ if (foo_function()) { - \\ const stdout = &(getStdOut() catch unreachable).outStream().stream; + \\ const stdout = &getStdOut().outStream().stream; \\ stdout.print("OK\n") catch unreachable; \\ } \\} @@ -88,8 +88,8 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { }); cases.addCase(x: { - var tc = cases.create("two files use import each other", - \\use @import("a.zig"); + var tc = cases.create("two files usingnamespace import each other", + \\usingnamespace @import("a.zig"); \\ \\pub fn main() void { \\ ok(); @@ -97,19 +97,19 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { , "OK\n"); tc.addSourceFile("a.zig", - \\use @import("b.zig"); + \\usingnamespace @import("b.zig"); \\const io = @import("std").io; \\ \\pub const a_text = "OK\n"; \\ \\pub fn ok() void { - \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream; + \\ const stdout = &io.getStdOut().outStream().stream; \\ stdout.print(b_text) catch unreachable; \\} ); tc.addSourceFile("b.zig", - \\use @import("a.zig"); + \\usingnamespace @import("a.zig"); \\ \\pub const b_text = a_text; ); @@ -121,8 +121,8 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { \\const io = @import("std").io; \\ \\pub fn main() void { - \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream; - \\ stdout.print("Hello, world!\n{d:4} {x:3} {c}\n", u32(12), u16(0x12), u8('a')) catch unreachable; + \\ const stdout = &io.getStdOut().outStream().stream; + \\ stdout.print("Hello, world!\n{d:4} {x:3} {c}\n", @as(u32, 12), @as(u16, 0x12), @as(u8, 'a')) catch unreachable; \\} , "Hello, world!\n 12 12 a\n"); @@ -145,75 +145,75 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { \\ _ = c._setmode(1, c._O_BINARY); \\ } \\ _ = c.printf(c"0: %llu\n", - \\ u64(0)); + \\ @as(u64, 0)); \\ _ = c.printf(c"320402575052271: %llu\n", - \\ u64(320402575052271)); + \\ @as(u64, 320402575052271)); \\ _ = c.printf(c"0x01236789abcdef: %llu\n", - \\ u64(0x01236789abcdef)); + \\ @as(u64, 0x01236789abcdef)); \\ _ = c.printf(c"0xffffffffffffffff: %llu\n", - \\ u64(0xffffffffffffffff)); + \\ @as(u64, 0xffffffffffffffff)); \\ _ = c.printf(c"0x000000ffffffffffffffff: %llu\n", - \\ u64(0x000000ffffffffffffffff)); + \\ @as(u64, 0x000000ffffffffffffffff)); \\ _ = c.printf(c"0o1777777777777777777777: %llu\n", - \\ u64(0o1777777777777777777777)); + \\ @as(u64, 0o1777777777777777777777)); \\ _ = c.printf(c"0o0000001777777777777777777777: %llu\n", - \\ u64(0o0000001777777777777777777777)); + \\ @as(u64, 0o0000001777777777777777777777)); \\ _ = c.printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n", - \\ u64(0b1111111111111111111111111111111111111111111111111111111111111111)); + \\ @as(u64, 0b1111111111111111111111111111111111111111111111111111111111111111)); \\ _ = c.printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n", - \\ u64(0b0000001111111111111111111111111111111111111111111111111111111111111111)); + \\ @as(u64, 0b0000001111111111111111111111111111111111111111111111111111111111111111)); \\ \\ _ = c.printf(c"\n"); \\ \\ _ = c.printf(c"0.0: %.013a\n", - \\ f64(0.0)); + \\ @as(f64, 0.0)); \\ _ = c.printf(c"0e0: %.013a\n", - \\ f64(0e0)); + \\ @as(f64, 0e0)); \\ _ = c.printf(c"0.0e0: %.013a\n", - \\ f64(0.0e0)); + \\ @as(f64, 0.0e0)); \\ _ = c.printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %.013a\n", - \\ f64(000000000000000000000000000000000000000000000000000000000.0e0)); + \\ @as(f64, 000000000000000000000000000000000000000000000000000000000.0e0)); \\ _ = c.printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %.013a\n", - \\ f64(0.000000000000000000000000000000000000000000000000000000000e0)); + \\ @as(f64, 0.000000000000000000000000000000000000000000000000000000000e0)); \\ _ = c.printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %.013a\n", - \\ f64(0.0e000000000000000000000000000000000000000000000000000000000)); + \\ @as(f64, 0.0e000000000000000000000000000000000000000000000000000000000)); \\ _ = c.printf(c"1.0: %.013a\n", - \\ f64(1.0)); + \\ @as(f64, 1.0)); \\ _ = c.printf(c"10.0: %.013a\n", - \\ f64(10.0)); + \\ @as(f64, 10.0)); \\ _ = c.printf(c"10.5: %.013a\n", - \\ f64(10.5)); + \\ @as(f64, 10.5)); \\ _ = c.printf(c"10.5e5: %.013a\n", - \\ f64(10.5e5)); + \\ @as(f64, 10.5e5)); \\ _ = c.printf(c"10.5e+5: %.013a\n", - \\ f64(10.5e+5)); + \\ @as(f64, 10.5e+5)); \\ _ = c.printf(c"50.0e-2: %.013a\n", - \\ f64(50.0e-2)); + \\ @as(f64, 50.0e-2)); \\ _ = c.printf(c"50e-2: %.013a\n", - \\ f64(50e-2)); + \\ @as(f64, 50e-2)); \\ \\ _ = c.printf(c"\n"); \\ \\ _ = c.printf(c"0x1.0: %.013a\n", - \\ f64(0x1.0)); + \\ @as(f64, 0x1.0)); \\ _ = c.printf(c"0x10.0: %.013a\n", - \\ f64(0x10.0)); + \\ @as(f64, 0x10.0)); \\ _ = c.printf(c"0x100.0: %.013a\n", - \\ f64(0x100.0)); + \\ @as(f64, 0x100.0)); \\ _ = c.printf(c"0x103.0: %.013a\n", - \\ f64(0x103.0)); + \\ @as(f64, 0x103.0)); \\ _ = c.printf(c"0x103.7: %.013a\n", - \\ f64(0x103.7)); + \\ @as(f64, 0x103.7)); \\ _ = c.printf(c"0x103.70: %.013a\n", - \\ f64(0x103.70)); + \\ @as(f64, 0x103.70)); \\ _ = c.printf(c"0x103.70p4: %.013a\n", - \\ f64(0x103.70p4)); + \\ @as(f64, 0x103.70p4)); \\ _ = c.printf(c"0x103.70p5: %.013a\n", - \\ f64(0x103.70p5)); + \\ @as(f64, 0x103.70p5)); \\ _ = c.printf(c"0x103.70p+5: %.013a\n", - \\ f64(0x103.70p+5)); + \\ @as(f64, 0x103.70p+5)); \\ _ = c.printf(c"0x103.70p-5: %.013a\n", - \\ f64(0x103.70p-5)); + \\ @as(f64, 0x103.70p-5)); \\ \\ return 0; \\} @@ -264,7 +264,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { \\ var x_local : i32 = print_ok(x); \\} \\fn print_ok(val: @typeOf(x)) @typeOf(foo) { - \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream; + \\ const stdout = &io.getStdOut().outStream().stream; \\ stdout.print("OK\n") catch unreachable; \\ return 0; \\} @@ -323,7 +323,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { \\ const x: f64 = small; \\ const y = @floatToInt(i32, x); \\ const z = @intToFloat(f64, y); - \\ _ = c.printf(c"%.2f\n%d\n%.2f\n%.2f\n", x, y, z, f64(-0.4)); + \\ _ = c.printf(c"%.2f\n%d\n%.2f\n%.2f\n", x, y, z, @as(f64, -0.4)); \\ return 0; \\} , "3.25\n3\n3.00\n-0.40\n"); @@ -346,7 +346,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { \\pub fn main() void { \\ const bar = Bar {.field2 = 13,}; \\ const foo = Foo {.field1 = bar,}; - \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream; + \\ const stdout = &io.getStdOut().outStream().stream; \\ if (!foo.method()) { \\ stdout.print("BAD\n") catch unreachable; \\ } @@ -360,7 +360,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { cases.add("defer with only fallthrough", \\const io = @import("std").io; \\pub fn main() void { - \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream; + \\ const stdout = &io.getStdOut().outStream().stream; \\ stdout.print("before\n") catch unreachable; \\ defer stdout.print("defer1\n") catch unreachable; \\ defer stdout.print("defer2\n") catch unreachable; @@ -373,7 +373,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { \\const io = @import("std").io; \\const os = @import("std").os; \\pub fn main() void { - \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream; + \\ const stdout = &io.getStdOut().outStream().stream; \\ stdout.print("before\n") catch unreachable; \\ defer stdout.print("defer1\n") catch unreachable; \\ defer stdout.print("defer2\n") catch unreachable; @@ -390,7 +390,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { \\ do_test() catch return; \\} \\fn do_test() !void { - \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream; + \\ const stdout = &io.getStdOut().outStream().stream; \\ stdout.print("before\n") catch unreachable; \\ defer stdout.print("defer1\n") catch unreachable; \\ errdefer stdout.print("deferErr\n") catch unreachable; @@ -409,7 +409,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { \\ do_test() catch return; \\} \\fn do_test() !void { - \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream; + \\ const stdout = &io.getStdOut().outStream().stream; \\ stdout.print("before\n") catch unreachable; \\ defer stdout.print("defer1\n") catch unreachable; \\ errdefer stdout.print("deferErr\n") catch unreachable; @@ -426,7 +426,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { \\const io = @import("std").io; \\ \\pub fn main() void { - \\ const stdout = &(io.getStdOut() catch unreachable).outStream().stream; + \\ const stdout = &io.getStdOut().outStream().stream; \\ stdout.print(foo_txt) catch unreachable; \\} , "1234\nabcd\n"); @@ -445,7 +445,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { \\ \\pub fn main() !void { \\ var args_it = std.process.args(); - \\ var stdout_file = try io.getStdOut(); + \\ var stdout_file = io.getStdOut(); \\ var stdout_adapter = stdout_file.outStream(); \\ const stdout = &stdout_adapter.stream; \\ var index: usize = 0; @@ -486,7 +486,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { \\ \\pub fn main() !void { \\ var args_it = std.process.args(); - \\ var stdout_file = try io.getStdOut(); + \\ var stdout_file = io.getStdOut(); \\ var stdout_adapter = stdout_file.outStream(); \\ const stdout = &stdout_adapter.stream; \\ var index: usize = 0; diff --git a/test/compile_errors.zig b/test/compile_errors.zig @@ -3,6 +3,130 @@ const builtin = @import("builtin"); pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( + "empty switch on an integer", + \\export fn entry() void { + \\ var x: u32 = 0; + \\ switch(x) {} + \\} + , + "tmp.zig:3:5: error: switch must handle all possibilities", + ); + + cases.add( + "incorrect return type", + \\ pub export fn entry() void{ + \\ _ = foo(); + \\ } + \\ const A = struct { + \\ a: u32, + \\ }; + \\ fn foo() A { + \\ return bar(); + \\ } + \\ const B = struct { + \\ a: u32, + \\ }; + \\ fn bar() B { + \\ unreachable; + \\ } + , + "tmp.zig:8:16: error: expected type 'A', found 'B'", + ); + + cases.add( + "regression test #2980: base type u32 is not type checked properly when assigning a value within a struct", + \\const Foo = struct { + \\ ptr: ?*usize, + \\ uval: u32, + \\}; + \\fn get_uval(x: u32) !u32 { + \\ return error.NotFound; + \\} + \\export fn entry() void { + \\ const afoo = Foo{ + \\ .ptr = null, + \\ .uval = get_uval(42), + \\ }; + \\} + , + "tmp.zig:11:25: error: expected type 'u32', found '@typeOf(get_uval).ReturnType.ErrorSet!u32'", + ); + + cases.add( + "asigning to struct or union fields that are not optionals with a function that returns an optional", + \\fn maybe(is: bool) ?u8 { + \\ if (is) return @as(u8, 10) else return null; + \\} + \\const U = union { + \\ Ye: u8, + \\}; + \\const S = struct { + \\ num: u8, + \\}; + \\export fn entry() void { + \\ var u = U{ .Ye = maybe(false) }; + \\ var s = S{ .num = maybe(false) }; + \\} + , + "tmp.zig:11:27: error: expected type 'u8', found '?u8'", + ); + + cases.add( + "missing result type for phi node", + \\fn foo() !void { + \\ return anyerror.Foo; + \\} + \\export fn entry() void { + \\ foo() catch 0; + \\} + , + "tmp.zig:5:17: error: integer value 0 cannot be coerced to type 'void'", + ); + + cases.add( + "atomicrmw with enum op not .Xchg", + \\export fn entry() void { + \\ const E = enum(u8) { + \\ a, + \\ b, + \\ c, + \\ d, + \\ }; + \\ var x: E = .a; + \\ _ = @atomicRmw(E, &x, .Add, .b, .SeqCst); + \\} + , + "tmp.zig:9:27: error: @atomicRmw on enum only works with .Xchg", + ); + + cases.add( + "atomic orderings of atomicStore Acquire or AcqRel", + \\export fn entry() void { + \\ var x: u32 = 0; + \\ @atomicStore(u32, &x, 1, .Acquire); + \\} + , + "tmp.zig:3:30: error: @atomicStore atomic ordering must not be Acquire or AcqRel", + ); + + cases.add( + "missing const in slice with nested array type", + \\const Geo3DTex2D = struct { vertices: [][2]f32 }; + \\pub fn getGeo3DTex2D() Geo3DTex2D { + \\ return Geo3DTex2D{ + \\ .vertices = [_][2]f32{ + \\ [_]f32{ -0.5, -0.5}, + \\ }, + \\ }; + \\} + \\export fn entry() void { + \\ var geo_data = getGeo3DTex2D(); + \\} + , + "tmp.zig:4:30: error: expected type '[][2]f32', found '[1][2]f32'", + ); + + cases.add( "slicing of global undefined pointer", \\var buf: *[1]u8 = undefined; \\export fn entry() void { @@ -186,21 +310,21 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "shift amount has to be an integer type", \\export fn entry() void { - \\ const x = 1 << &u8(10); + \\ const x = 1 << &@as(u8, 10); \\} , - "tmp.zig:2:23: error: shift amount has to be an integer type, but found '*u8'", + "tmp.zig:2:21: error: shift amount has to be an integer type, but found '*u8'", "tmp.zig:2:17: note: referenced here", ); cases.add( "bit shifting only works on integer types", \\export fn entry() void { - \\ const x = &u8(1) << 10; + \\ const x = &@as(u8, 1) << 10; \\} , - "tmp.zig:2:18: error: bit shifting operation expected integer type, found '*u8'", - "tmp.zig:2:22: note: referenced here", + "tmp.zig:2:16: error: bit shifting operation expected integer type, found '*u8'", + "tmp.zig:2:27: note: referenced here", ); cases.add( @@ -216,9 +340,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ const obj = AstObject{ .lhsExpr = lhsExpr }; \\} , - "tmp.zig:4:19: error: union 'AstObject' depends on itself", - "tmp.zig:2:5: note: while checking this field", + "tmp.zig:1:17: error: struct 'LhsExpr' depends on itself", "tmp.zig:5:5: note: while checking this field", + "tmp.zig:2:5: note: while checking this field", ); cases.add( @@ -241,11 +365,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ var x: []align(true) i32 = undefined; \\} \\export fn entry2() void { - \\ var x: *align(f64(12.34)) i32 = undefined; + \\ var x: *align(@as(f64, 12.34)) i32 = undefined; \\} , "tmp.zig:2:20: error: expected type 'u29', found 'bool'", - "tmp.zig:5:22: error: fractional component prevents float value 12.340000 from being casted to type 'u29'", + "tmp.zig:5:19: error: fractional component prevents float value 12.340000 from being casted to type 'u29'", ); cases.addCase(x: { @@ -1243,7 +1367,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ var ptr: [*c]u8 = x; \\} , - "tmp.zig:2:33: error: integer value 18446744073709551617 cannot be implicitly casted to type 'usize'", + "tmp.zig:2:33: error: integer value 18446744073709551617 cannot be coerced to type 'usize'", "tmp.zig:6:23: error: integer type 'u65' too big for implicit @intToPtr to type '[*c]u8'", ); @@ -1297,17 +1421,17 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "@truncate undefined value", \\export fn entry() void { - \\ var z = @truncate(u8, u16(undefined)); + \\ var z = @truncate(u8, @as(u16, undefined)); \\} , - "tmp.zig:2:30: error: use of undefined value here causes undefined behavior", + "tmp.zig:2:27: error: use of undefined value here causes undefined behavior", ); cases.addTest( "return invalid type from test", \\test "example" { return 1; } , - "tmp.zig:1:25: error: integer value 1 cannot be implicitly casted to type 'void'", + "tmp.zig:1:25: error: integer value 1 cannot be coerced to type 'void'", ); cases.add( @@ -1332,7 +1456,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "@bitCast with different sizes inside an expression", \\export fn entry() void { - \\ var foo = (@bitCast(u8, f32(1.0)) == 0xf); + \\ var foo = (@bitCast(u8, @as(f32, 1.0)) == 0xf); \\} , "tmp.zig:2:25: error: destination type 'u8' has size 1 but source type 'f32' has size 4", @@ -1464,8 +1588,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ var byte: u8 = spartan_count; \\} , - "tmp.zig:3:31: error: integer value 300 cannot be implicitly casted to type 'u8'", - "tmp.zig:7:22: error: integer value 300 cannot be implicitly casted to type 'u8'", + "tmp.zig:3:31: error: integer value 300 cannot be coerced to type 'u8'", + "tmp.zig:7:22: error: integer value 300 cannot be coerced to type 'u8'", "tmp.zig:11:20: error: expected type 'u8', found 'u16'", ); @@ -1498,7 +1622,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ var x: i65536 = 1; \\} , - "tmp.zig:2:31: error: integer value 65536 cannot be implicitly casted to type 'u16'", + "tmp.zig:2:31: error: integer value 65536 cannot be coerced to type 'u16'", "tmp.zig:5:12: error: primitive integer type 'i65536' exceeds maximum bit width of 65535", ); @@ -1686,10 +1810,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "non float passed to @floatToInt", \\export fn entry() void { - \\ const x = @floatToInt(i32, i32(54)); + \\ const x = @floatToInt(i32, @as(i32, 54)); \\} , - "tmp.zig:2:35: error: expected float type, found 'i32'", + "tmp.zig:2:32: error: expected float type, found 'i32'", ); cases.add( @@ -1698,7 +1822,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ const x = @floatToInt(i8, 200); \\} , - "tmp.zig:2:31: error: integer value 200 cannot be implicitly casted to type 'i8'", + "tmp.zig:2:31: error: integer value 200 cannot be coerced to type 'i8'", ); cases.add( @@ -2096,8 +2220,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ \\fn bar(x: *b.Foo) void {} , - "tmp.zig:6:10: error: expected type '*b.Foo', found '*a.Foo'", - "tmp.zig:6:10: note: pointer type child 'a.Foo' cannot cast into pointer type child 'b.Foo'", + "tmp.zig:6:9: error: expected type '*b.Foo', found '*a.Foo'", + "tmp.zig:6:9: note: pointer type child 'a.Foo' cannot cast into pointer type child 'b.Foo'", "a.zig:1:17: note: a.Foo declared here", "b.zig:1:17: note: b.Foo declared here", ); @@ -2120,13 +2244,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "@floatToInt comptime safety", \\comptime { - \\ _ = @floatToInt(i8, f32(-129.1)); + \\ _ = @floatToInt(i8, @as(f32, -129.1)); \\} \\comptime { - \\ _ = @floatToInt(u8, f32(-1.1)); + \\ _ = @floatToInt(u8, @as(f32, -1.1)); \\} \\comptime { - \\ _ = @floatToInt(u8, f32(256.1)); + \\ _ = @floatToInt(u8, @as(f32, 256.1)); \\} , "tmp.zig:2:9: error: integer value '-129' cannot be stored in type 'i8'", @@ -2197,7 +2321,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "error when evaluating return type", \\const Foo = struct { - \\ map: i32(i32), + \\ map: @as(i32, i32), \\ \\ fn init() Foo { \\ return undefined; @@ -2207,7 +2331,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ var rule_set = try Foo.init(); \\} , - "tmp.zig:2:13: error: expected type 'i32', found 'type'", + "tmp.zig:2:10: error: expected type 'i32', found 'type'", ); cases.add( @@ -2338,7 +2462,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "var not allowed in structs", \\export fn entry() void { - \\ var s = (struct{v: var}){.v=i32(10)}; + \\ var s = (struct{v: var}){.v=@as(i32, 10)}; \\} , "tmp.zig:2:23: error: invalid token: 'var'", @@ -2357,10 +2481,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "comptime slice of undefined pointer non-zero len", \\export fn entry() void { - \\ const slice = ([*]i32)(undefined)[0..1]; + \\ const slice = @as([*]i32, undefined)[0..1]; \\} , - "tmp.zig:2:38: error: non-zero length slice of undefined pointer", + "tmp.zig:2:41: error: non-zero length slice of undefined pointer", ); cases.add( @@ -2657,10 +2781,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "cast negative integer literal to usize", \\export fn entry() void { - \\ const x = usize(-10); + \\ const x = @as(usize, -10); \\} , - "tmp.zig:2:21: error: cannot cast negative value -10 to unsigned integer type 'usize'", + "tmp.zig:2:26: error: cannot cast negative value -10 to unsigned integer type 'usize'", ); cases.add( @@ -3384,11 +3508,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ const x : i32 = if (b) h: { break :h 1; }; \\} \\fn g(b: bool) void { - \\ const y = if (b) h: { break :h i32(1); }; + \\ const y = if (b) h: { break :h @as(i32, 1); }; \\} \\export fn entry() void { f(true); g(true); } , - "tmp.zig:2:42: error: integer value 1 cannot be implicitly casted to type 'void'", + "tmp.zig:2:21: error: expected type 'i32', found 'void'", "tmp.zig:5:15: error: incompatible types: 'i32' and 'void'", ); @@ -3520,11 +3644,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "cast unreachable", \\fn f() i32 { - \\ return i32(return 1); + \\ return @as(i32, return 1); \\} \\export fn entry() void { _ = f(); } , - "tmp.zig:2:15: error: unreachable code", + "tmp.zig:2:12: error: unreachable code", ); cases.add( @@ -3595,7 +3719,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ switch (n) { \\ Number.One => 1, \\ Number.Two => 2, - \\ Number.Three => i32(3), + \\ Number.Three => @as(i32, 3), \\ } \\} \\ @@ -3616,7 +3740,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ switch (n) { \\ Number.One => 1, \\ Number.Two => 2, - \\ Number.Three => i32(3), + \\ Number.Three => @as(i32, 3), \\ Number.Four => 4, \\ Number.Two => 2, \\ } @@ -3640,7 +3764,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ switch (n) { \\ Number.One => 1, \\ Number.Two => 2, - \\ Number.Three => i32(3), + \\ Number.Three => @as(i32, 3), \\ Number.Four => 4, \\ Number.Two => 2, \\ else => 10, @@ -3685,7 +3809,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "switch expression - duplicate or overlapping integer value", \\fn foo(x: u8) u8 { \\ return switch (x) { - \\ 0 ... 100 => u8(0), + \\ 0 ... 100 => @as(u8, 0), \\ 101 ... 200 => 1, \\ 201, 203 ... 207 => 2, \\ 206 ... 255 => 3, @@ -3722,7 +3846,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "array concatenation with wrong type", \\const src = "aoeu"; - \\const derp = usize(1234); + \\const derp = @as(usize, 1234); \\const a = derp ++ "foo"; \\ \\export fn entry() usize { return @sizeOf(@typeOf(a)); } @@ -3765,7 +3889,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\const x : u8 = 300; \\export fn entry() usize { return @sizeOf(@typeOf(x)); } , - "tmp.zig:1:16: error: integer value 300 cannot be implicitly casted to type 'u8'", + "tmp.zig:1:16: error: integer value 300 cannot be coerced to type 'u8'", ); cases.add( @@ -3887,8 +4011,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "division by zero", \\const lit_int_x = 1 / 0; \\const lit_float_x = 1.0 / 0.0; - \\const int_x = u32(1) / u32(0); - \\const float_x = f32(1.0) / f32(0.0); + \\const int_x = @as(u32, 1) / @as(u32, 0); + \\const float_x = @as(f32, 1.0) / @as(f32, 0.0); \\ \\export fn entry1() usize { return @sizeOf(@typeOf(lit_int_x)); } \\export fn entry2() usize { return @sizeOf(@typeOf(lit_float_x)); } @@ -3897,8 +4021,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { , "tmp.zig:1:21: error: division by zero", "tmp.zig:2:25: error: division by zero", - "tmp.zig:3:22: error: division by zero", - "tmp.zig:4:26: error: division by zero", + "tmp.zig:3:27: error: division by zero", + "tmp.zig:4:31: error: division by zero", ); cases.add( @@ -4590,7 +4714,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\var bytes: [ext()]u8 = undefined; \\export fn f() void { \\ for (bytes) |*b, i| { - \\ b.* = u8(i); + \\ b.* = @as(u8, i); \\ } \\} , @@ -4874,7 +4998,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\} \\ \\fn foo() i32 { - \\ return add(i32(1234)); + \\ return add(@as(i32, 1234)); \\} \\ \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } @@ -4886,7 +5010,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "pass integer literal to var args", \\fn add(args: ...) i32 { - \\ var sum = i32(0); + \\ var sum = @as(i32, 0); \\ {comptime var i: usize = 0; inline while (i < args.len) : (i += 1) { \\ sum += args[i]; \\ }} @@ -4908,7 +5032,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ var vga_mem: u16 = 0xB8000; \\} , - "tmp.zig:2:24: error: integer value 753664 cannot be implicitly casted to type 'u16'", + "tmp.zig:2:24: error: integer value 753664 cannot be coerced to type 'u16'", ); cases.add( @@ -4961,7 +5085,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ \\export fn entry() usize { return @sizeOf(@typeOf(foo)); } , - "tmp.zig:8:26: error: expected type '*const u3', found '*align(:3:1) const u3'", + "tmp.zig:8:16: error: expected type '*const u3', found '*align(:3:1) const u3'", ); cases.add( @@ -5080,7 +5204,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "pass const ptr to mutable ptr fn", \\fn foo() bool { - \\ const a = ([]const u8)("a",); + \\ const a = @as([]const u8, "a",); \\ const b = &a; \\ return ptrEql(b, b); \\} @@ -5581,10 +5705,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "explicit cast float literal to integer when there is a fraction component", \\export fn entry() i32 { - \\ return i32(12.34); + \\ return @as(i32, 12.34); \\} , - "tmp.zig:2:16: error: fractional component prevents float value 12.340000 from being casted to type 'i32'", + "tmp.zig:2:21: error: fractional component prevents float value 12.340000 from being casted to type 'i32'", ); cases.add( @@ -5599,7 +5723,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "@shlExact shifts out 1 bits", \\comptime { - \\ const x = @shlExact(u8(0b01010101), 2); + \\ const x = @shlExact(@as(u8, 0b01010101), 2); \\} , "tmp.zig:2:15: error: operation caused overflow", @@ -5608,7 +5732,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "@shrExact shifts out 1 bits", \\comptime { - \\ const x = @shrExact(u8(0b10101010), 2); + \\ const x = @shrExact(@as(u8, 0b10101010), 2); \\} , "tmp.zig:2:15: error: exact shift shifted out 1 bits", @@ -5658,7 +5782,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ x.* += 1; \\} , - "tmp.zig:8:13: error: expected type '*u32', found '*align(1) u32'", + "tmp.zig:8:9: error: expected type '*u32', found '*align(1) u32'", ); cases.add( @@ -5671,16 +5795,16 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn entry() void { \\ var foo = Foo { .a = 1, .b = 10 }; \\ foo.b += 1; - \\ bar((*[1]u32)(&foo.b)[0..]); + \\ bar(@as(*[1]u32, &foo.b)[0..]); \\} \\ \\fn bar(x: []u32) void { \\ x[0] += 1; \\} , - "tmp.zig:9:18: error: cast increases pointer alignment", - "tmp.zig:9:23: note: '*align(1) u32' has alignment 1", - "tmp.zig:9:18: note: '*[1]u32' has alignment 4", + "tmp.zig:9:9: error: cast increases pointer alignment", + "tmp.zig:9:26: note: '*align(1) u32' has alignment 1", + "tmp.zig:9:9: note: '*[1]u32' has alignment 4", ); cases.add( @@ -5699,10 +5823,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add( "@alignCast expects pointer or slice", \\export fn entry() void { - \\ @alignCast(4, u32(3)); + \\ @alignCast(4, @as(u32, 3)); \\} , - "tmp.zig:2:22: error: expected pointer or slice, found 'u32'", + "tmp.zig:2:19: error: expected pointer or slice, found 'u32'", ); cases.add( @@ -5740,11 +5864,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { ); cases.add( - "wrong pointer implicitly casted to pointer to @OpaqueType()", + "wrong pointer coerced to pointer to @OpaqueType()", \\const Derp = @OpaqueType(); \\extern fn bar(d: *Derp) void; \\export fn foo() void { - \\ var x = u8(1); + \\ var x = @as(u8, 1); \\ bar(@ptrCast(*c_void, &x)); \\} , @@ -5793,27 +5917,27 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:17:4: error: variable of type 'Opaque' not allowed", "tmp.zig:20:4: error: variable of type 'type' must be const or comptime", "tmp.zig:23:4: error: variable of type '(bound fn(*const Foo) void)' must be const or comptime", - "tmp.zig:26:4: error: unreachable code", + "tmp.zig:26:22: error: unreachable code", ); cases.add( "wrong types given to atomic order args in cmpxchg", \\export fn entry() void { \\ var x: i32 = 1234; - \\ while (!@cmpxchgWeak(i32, &x, 1234, 5678, u32(1234), u32(1234))) {} + \\ while (!@cmpxchgWeak(i32, &x, 1234, 5678, @as(u32, 1234), @as(u32, 1234))) {} \\} , - "tmp.zig:3:50: error: expected type 'std.builtin.AtomicOrder', found 'u32'", + "tmp.zig:3:47: error: expected type 'std.builtin.AtomicOrder', found 'u32'", ); cases.add( "wrong types given to @export", \\extern fn entry() void { } \\comptime { - \\ @export("entry", entry, u32(1234)); + \\ @export("entry", entry, @as(u32, 1234)); \\} , - "tmp.zig:3:32: error: expected type 'std.builtin.GlobalLinkage', found 'u32'", + "tmp.zig:3:29: error: expected type 'std.builtin.GlobalLinkage', found 'u32'", ); cases.add( @@ -6185,7 +6309,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\}; \\ \\export fn entry() void { - \\ var y = u3(3); + \\ var y = @as(u3, 3); \\ var x = @intToEnum(Small, y); \\} , @@ -6722,8 +6846,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:1:1: note: declared here", ); - // fixed bug #2032 - cases.add( + cases.add( // fixed bug #2032 "compile diagnostic string for top level decl type", \\export fn entry() void { \\ var foo: u32 = @This(){}; @@ -6731,6 +6854,5 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { , "tmp.zig:2:27: error: expected type 'u32', found '(root)'", "tmp.zig:1:1: note: (root) declared here", - "tmp.zig:2:5: note: referenced here", ); } diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig @@ -32,6 +32,8 @@ comptime { _ = @import("behavior/bugs/2346.zig"); _ = @import("behavior/bugs/2578.zig"); _ = @import("behavior/bugs/2692.zig"); + _ = @import("behavior/bugs/2889.zig"); + _ = @import("behavior/bugs/3007.zig"); _ = @import("behavior/bugs/3046.zig"); _ = @import("behavior/bugs/3112.zig"); _ = @import("behavior/bugs/3367.zig"); diff --git a/test/stage1/behavior/align.zig b/test/stage1/behavior/align.zig @@ -7,7 +7,7 @@ var foo: u8 align(4) = 100; test "global variable alignment" { expect(@typeOf(&foo).alignment == 4); expect(@typeOf(&foo) == *align(4) u8); - const slice = (*[1]u8)(&foo)[0..]; + const slice = @as(*[1]u8, &foo)[0..]; expect(@typeOf(slice) == []align(4) u8); } @@ -61,7 +61,7 @@ fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 { test "implicitly decreasing slice alignment" { const a: u32 align(4) = 3; const b: u32 align(8) = 4; - expect(addUnalignedSlice((*const [1]u32)(&a)[0..], (*const [1]u32)(&b)[0..]) == 7); + expect(addUnalignedSlice(@as(*const [1]u32, &a)[0..], @as(*const [1]u32, &b)[0..]) == 7); } fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 { return a[0] + b[0]; diff --git a/test/stage1/behavior/array.zig b/test/stage1/behavior/array.zig @@ -12,7 +12,7 @@ test "arrays" { } i = 0; - var accumulator = u32(0); + var accumulator = @as(u32, 0); while (i < 5) { accumulator += array[i]; @@ -149,7 +149,7 @@ test "implicit cast single-item pointer" { fn testImplicitCastSingleItemPtr() void { var byte: u8 = 100; - const slice = (*[1]u8)(&byte)[0..]; + const slice = @as(*[1]u8, &byte)[0..]; slice[0] += 1; expect(byte == 101); } @@ -298,3 +298,38 @@ test "implicit cast zero sized array ptr to slice" { const c: []const u8 = &b; expect(c.len == 0); } + +test "anonymous list literal syntax" { + const S = struct { + fn doTheTest() void { + var array: [4]u8 = .{1, 2, 3, 4}; + expect(array[0] == 1); + expect(array[1] == 2); + expect(array[2] == 3); + expect(array[3] == 4); + } + }; + S.doTheTest(); + comptime S.doTheTest(); +} + +test "anonymous literal in array" { + const S = struct { + const Foo = struct { + a: usize = 2, + b: usize = 4, + }; + fn doTheTest() void { + var array: [2]Foo = .{ + .{.a = 3}, + .{.b = 3}, + }; + expect(array[0].a == 3); + expect(array[0].b == 4); + expect(array[1].a == 2); + expect(array[1].b == 3); + } + }; + S.doTheTest(); + comptime S.doTheTest(); +} diff --git a/test/stage1/behavior/asm.zig b/test/stage1/behavior/asm.zig @@ -45,42 +45,42 @@ test "alternative constraints" { test "sized integer/float in asm input" { asm volatile ("" : - : [_] "m" (usize(3)) + : [_] "m" (@as(usize, 3)) : "" ); asm volatile ("" : - : [_] "m" (i15(-3)) + : [_] "m" (@as(i15, -3)) : "" ); asm volatile ("" : - : [_] "m" (u3(3)) + : [_] "m" (@as(u3, 3)) : "" ); asm volatile ("" : - : [_] "m" (i3(3)) + : [_] "m" (@as(i3, 3)) : "" ); asm volatile ("" : - : [_] "m" (u121(3)) + : [_] "m" (@as(u121, 3)) : "" ); asm volatile ("" : - : [_] "m" (i121(3)) + : [_] "m" (@as(i121, 3)) : "" ); asm volatile ("" : - : [_] "m" (f32(3.17)) + : [_] "m" (@as(f32, 3.17)) : "" ); asm volatile ("" : - : [_] "m" (f64(3.17)) + : [_] "m" (@as(f64, 3.17)) : "" ); } diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig @@ -191,7 +191,7 @@ async fn testSuspendBlock() void { // Test to make sure that @frame() works as advertised (issue #1296) // var our_handle: anyframe = @frame(); - expect(a_promise == anyframe(@frame())); + expect(a_promise == @as(anyframe, @frame())); global_result = true; } @@ -543,7 +543,7 @@ test "pass string literal to async function" { fn hello(msg: []const u8) void { frame = @frame(); suspend; - expectEqual(([]const u8)("hello"), msg); + expectEqual(@as([]const u8, "hello"), msg); ok = true; } }; @@ -1048,7 +1048,7 @@ test "using @typeOf on a generic function call" { return await @asyncCall(frame, {}, amain, x - 1); } }; - _ = async S.amain(u32(1)); + _ = async S.amain(@as(u32, 1)); resume S.global_frame; expect(S.global_ok); } @@ -1080,8 +1080,8 @@ test "recursive call of await @asyncCall with struct return type" { }; }; var res: S.Foo = undefined; - var frame: @typeOf(async S.amain(u32(1))) = undefined; - _ = @asyncCall(&frame, &res, S.amain, u32(1)); + var frame: @typeOf(async S.amain(@as(u32, 1))) = undefined; + _ = @asyncCall(&frame, &res, S.amain, @as(u32, 1)); resume S.global_frame; expect(S.global_ok); expect(res.x == 1); @@ -1214,7 +1214,7 @@ test "spill target expr in a for loop" { } const Foo = struct { - slice: []i32, + slice: []const i32, }; fn atest(foo: *Foo) i32 { @@ -1245,7 +1245,7 @@ test "spill target expr in a for loop, with a var decl in the loop body" { } const Foo = struct { - slice: []i32, + slice: []const i32, }; fn atest(foo: *Foo) i32 { diff --git a/test/stage1/behavior/atomics.zig b/test/stage1/behavior/atomics.zig @@ -98,12 +98,49 @@ test "cmpxchg with ignored result" { _ = @cmpxchgStrong(i32, &x, 1234, 5678, .Monotonic, .Monotonic); - expectEqual(i32(5678), x); + expectEqual(@as(i32, 5678), x); } -var a_global_variable = u32(1234); +var a_global_variable = @as(u32, 1234); test "cmpxchg on a global variable" { _ = @cmpxchgWeak(u32, &a_global_variable, 1234, 42, .Acquire, .Monotonic); - expectEqual(u32(42), a_global_variable); + expectEqual(@as(u32, 42), a_global_variable); } + +test "atomic load and rmw with enum" { + const Value = enum(u8) { + a, + b, + c, + }; + var x = Value.a; + + expect(@atomicLoad(Value, &x, .SeqCst) != .b); + + _ = @atomicRmw(Value, &x, .Xchg, .c, .SeqCst); + expect(@atomicLoad(Value, &x, .SeqCst) == .c); + expect(@atomicLoad(Value, &x, .SeqCst) != .a); + expect(@atomicLoad(Value, &x, .SeqCst) != .b); +} + +test "atomic store" { + var x: u32 = 0; + @atomicStore(u32, &x, 1, .SeqCst); + expect(@atomicLoad(u32, &x, .SeqCst) == 1); + @atomicStore(u32, &x, 12345678, .SeqCst); + expect(@atomicLoad(u32, &x, .SeqCst) == 12345678); +} + +test "atomic store comptime" { + comptime testAtomicStore(); + testAtomicStore(); +} + +fn testAtomicStore() void { + var x: u32 = 0; + @atomicStore(u32, &x, 1, .SeqCst); + expect(@atomicLoad(u32, &x, .SeqCst) == 1); + @atomicStore(u32, &x, 12345678, .SeqCst); + expect(@atomicLoad(u32, &x, .SeqCst) == 12345678); +} +\ No newline at end of file diff --git a/test/stage1/behavior/bitreverse.zig b/test/stage1/behavior/bitreverse.zig @@ -46,24 +46,24 @@ fn testBitReverse() void { expect(@bitReverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48); // using comptime_ints, signed, positive - expect(@bitReverse(u8, u8(0)) == 0); - expect(@bitReverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8(0x49))); - expect(@bitReverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x2c48))); - expect(@bitReverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x6a2c48))); - expect(@bitReverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x1e6a2c48))); - expect(@bitReverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x591e6a2c48))); - expect(@bitReverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0x3d591e6a2c48))); - expect(@bitReverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0x7b3d591e6a2c48))); - expect(@bitReverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0x8f7b3d591e6a2c48))); - expect(@bitReverse(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == @bitCast(i128, u128(0x818e868a828c84888f7b3d591e6a2c48))); + expect(@bitReverse(u8, @as(u8, 0)) == 0); + expect(@bitReverse(i8, @bitCast(i8, @as(u8, 0x92))) == @bitCast(i8, @as(u8, 0x49))); + expect(@bitReverse(i16, @bitCast(i16, @as(u16, 0x1234))) == @bitCast(i16, @as(u16, 0x2c48))); + expect(@bitReverse(i24, @bitCast(i24, @as(u24, 0x123456))) == @bitCast(i24, @as(u24, 0x6a2c48))); + expect(@bitReverse(i32, @bitCast(i32, @as(u32, 0x12345678))) == @bitCast(i32, @as(u32, 0x1e6a2c48))); + expect(@bitReverse(i40, @bitCast(i40, @as(u40, 0x123456789a))) == @bitCast(i40, @as(u40, 0x591e6a2c48))); + expect(@bitReverse(i48, @bitCast(i48, @as(u48, 0x123456789abc))) == @bitCast(i48, @as(u48, 0x3d591e6a2c48))); + expect(@bitReverse(i56, @bitCast(i56, @as(u56, 0x123456789abcde))) == @bitCast(i56, @as(u56, 0x7b3d591e6a2c48))); + expect(@bitReverse(i64, @bitCast(i64, @as(u64, 0x123456789abcdef1))) == @bitCast(i64, @as(u64, 0x8f7b3d591e6a2c48))); + expect(@bitReverse(i128, @bitCast(i128, @as(u128, 0x123456789abcdef11121314151617181))) == @bitCast(i128, @as(u128, 0x818e868a828c84888f7b3d591e6a2c48))); // using signed, negative. Compare to runtime ints returned from llvm. var neg8: i8 = -18; - expect(@bitReverse(i8, i8(-18)) == @bitReverse(i8, neg8)); + expect(@bitReverse(i8, @as(i8, -18)) == @bitReverse(i8, neg8)); var neg16: i16 = -32694; - expect(@bitReverse(i16, i16(-32694)) == @bitReverse(i16, neg16)); + expect(@bitReverse(i16, @as(i16, -32694)) == @bitReverse(i16, neg16)); var neg24: i24 = -6773785; - expect(@bitReverse(i24, i24(-6773785)) == @bitReverse(i24, neg24)); + expect(@bitReverse(i24, @as(i24, -6773785)) == @bitReverse(i24, neg24)); var neg32: i32 = -16773785; - expect(@bitReverse(i32, i32(-16773785)) == @bitReverse(i32, neg32)); + expect(@bitReverse(i32, @as(i32, -16773785)) == @bitReverse(i32, neg32)); } diff --git a/test/stage1/behavior/bool.zig b/test/stage1/behavior/bool.zig @@ -8,14 +8,14 @@ test "bool literals" { test "cast bool to int" { const t = true; const f = false; - expect(@boolToInt(t) == u32(1)); - expect(@boolToInt(f) == u32(0)); + expect(@boolToInt(t) == @as(u32, 1)); + expect(@boolToInt(f) == @as(u32, 0)); nonConstCastBoolToInt(t, f); } fn nonConstCastBoolToInt(t: bool, f: bool) void { - expect(@boolToInt(t) == u32(1)); - expect(@boolToInt(f) == u32(0)); + expect(@boolToInt(t) == @as(u32, 1)); + expect(@boolToInt(f) == @as(u32, 0)); } test "bool cmp" { diff --git a/test/stage1/behavior/bugs/1322.zig b/test/stage1/behavior/bugs/1322.zig @@ -13,7 +13,7 @@ const C = struct {}; test "tagged union with all void fields but a meaningful tag" { var a: A = A{ .b = B{ .c = C{} } }; - std.testing.expect(@TagType(B)(a.b) == @TagType(B).c); + std.testing.expect(@as(@TagType(B), a.b) == @TagType(B).c); a = A{ .b = B.None }; - std.testing.expect(@TagType(B)(a.b) == @TagType(B).None); + std.testing.expect(@as(@TagType(B), a.b) == @TagType(B).None); } diff --git a/test/stage1/behavior/bugs/1421.zig b/test/stage1/behavior/bugs/1421.zig @@ -10,5 +10,5 @@ const S = struct { test "functions with return type required to be comptime are generic" { const ti = S.method(); - expect(builtin.TypeId(ti) == builtin.TypeId.Struct); + expect(@as(builtin.TypeId, ti) == builtin.TypeId.Struct); } diff --git a/test/stage1/behavior/bugs/2114.zig b/test/stage1/behavior/bugs/2114.zig @@ -12,8 +12,8 @@ test "fixed" { } fn testClz() void { - expect(ctz(u128(0x40000000000000000000000000000000)) == 126); - expect(math.rotl(u128, u128(0x40000000000000000000000000000000), u8(1)) == u128(0x80000000000000000000000000000000)); - expect(ctz(u128(0x80000000000000000000000000000000)) == 127); - expect(ctz(math.rotl(u128, u128(0x40000000000000000000000000000000), u8(1))) == 127); + expect(ctz(@as(u128, 0x40000000000000000000000000000000)) == 126); + expect(math.rotl(u128, @as(u128, 0x40000000000000000000000000000000), @as(u8, 1)) == @as(u128, 0x80000000000000000000000000000000)); + expect(ctz(@as(u128, 0x80000000000000000000000000000000)) == 127); + expect(ctz(math.rotl(u128, @as(u128, 0x40000000000000000000000000000000), @as(u8, 1))) == 127); } diff --git a/test/stage1/behavior/bugs/2889.zig b/test/stage1/behavior/bugs/2889.zig @@ -0,0 +1,31 @@ +const std = @import("std"); + +const source = "A-"; + +fn parseNote() ?i32 { + const letter = source[0]; + const modifier = source[1]; + + const semitone = blk: { + if (letter == 'C' and modifier == '-') break :blk @as(i32, 0); + if (letter == 'C' and modifier == '#') break :blk @as(i32, 1); + if (letter == 'D' and modifier == '-') break :blk @as(i32, 2); + if (letter == 'D' and modifier == '#') break :blk @as(i32, 3); + if (letter == 'E' and modifier == '-') break :blk @as(i32, 4); + if (letter == 'F' and modifier == '-') break :blk @as(i32, 5); + if (letter == 'F' and modifier == '#') break :blk @as(i32, 6); + if (letter == 'G' and modifier == '-') break :blk @as(i32, 7); + if (letter == 'G' and modifier == '#') break :blk @as(i32, 8); + if (letter == 'A' and modifier == '-') break :blk @as(i32, 9); + if (letter == 'A' and modifier == '#') break :blk @as(i32, 10); + if (letter == 'B' and modifier == '-') break :blk @as(i32, 11); + return null; + }; + + return semitone; +} + +test "fixed" { + const result = parseNote(); + std.testing.expect(result.? == 9); +} diff --git a/test/stage1/behavior/bugs/3007.zig b/test/stage1/behavior/bugs/3007.zig @@ -0,0 +1,23 @@ +const std = @import("std"); + +const Foo = struct { + free: bool, + + pub const FooError = error{NotFree}; +}; + +var foo = Foo{ .free = true }; +var default_foo: ?*Foo = null; + +fn get_foo() Foo.FooError!*Foo { + if (foo.free) { + foo.free = false; + return &foo; + } + return error.NotFree; +} + +test "fixed" { + default_foo = get_foo() catch null; // This Line + std.testing.expect(!default_foo.?.free); +} diff --git a/test/stage1/behavior/bugs/3046.zig b/test/stage1/behavior/bugs/3046.zig @@ -13,7 +13,7 @@ var some_struct: SomeStruct = undefined; test "fixed" { some_struct = SomeStruct{ - .field = couldFail() catch |_| i32(0), + .field = couldFail() catch |_| @as(i32, 0), }; expect(some_struct.field == 1); } diff --git a/test/stage1/behavior/byteswap.zig b/test/stage1/behavior/byteswap.zig @@ -11,24 +11,24 @@ test "@byteSwap integers" { t(u24, 0x123456, 0x563412); t(u32, 0x12345678, 0x78563412); t(u40, 0x123456789a, 0x9a78563412); - t(i48, 0x123456789abc, @bitCast(i48, u48(0xbc9a78563412))); + t(i48, 0x123456789abc, @bitCast(i48, @as(u48, 0xbc9a78563412))); t(u56, 0x123456789abcde, 0xdebc9a78563412); t(u64, 0x123456789abcdef1, 0xf1debc9a78563412); t(u128, 0x123456789abcdef11121314151617181, 0x8171615141312111f1debc9a78563412); - t(u0, u0(0), 0); - t(i8, i8(-50), -50); - t(i16, @bitCast(i16, u16(0x1234)), @bitCast(i16, u16(0x3412))); - t(i24, @bitCast(i24, u24(0x123456)), @bitCast(i24, u24(0x563412))); - t(i32, @bitCast(i32, u32(0x12345678)), @bitCast(i32, u32(0x78563412))); - t(u40, @bitCast(i40, u40(0x123456789a)), u40(0x9a78563412)); - t(i48, @bitCast(i48, u48(0x123456789abc)), @bitCast(i48, u48(0xbc9a78563412))); - t(i56, @bitCast(i56, u56(0x123456789abcde)), @bitCast(i56, u56(0xdebc9a78563412))); - t(i64, @bitCast(i64, u64(0x123456789abcdef1)), @bitCast(i64, u64(0xf1debc9a78563412))); + t(u0, @as(u0, 0), 0); + t(i8, @as(i8, -50), -50); + t(i16, @bitCast(i16, @as(u16, 0x1234)), @bitCast(i16, @as(u16, 0x3412))); + t(i24, @bitCast(i24, @as(u24, 0x123456)), @bitCast(i24, @as(u24, 0x563412))); + t(i32, @bitCast(i32, @as(u32, 0x12345678)), @bitCast(i32, @as(u32, 0x78563412))); + t(u40, @bitCast(i40, @as(u40, 0x123456789a)), @as(u40, 0x9a78563412)); + t(i48, @bitCast(i48, @as(u48, 0x123456789abc)), @bitCast(i48, @as(u48, 0xbc9a78563412))); + t(i56, @bitCast(i56, @as(u56, 0x123456789abcde)), @bitCast(i56, @as(u56, 0xdebc9a78563412))); + t(i64, @bitCast(i64, @as(u64, 0x123456789abcdef1)), @bitCast(i64, @as(u64, 0xf1debc9a78563412))); t( i128, - @bitCast(i128, u128(0x123456789abcdef11121314151617181)), - @bitCast(i128, u128(0x8171615141312111f1debc9a78563412)), + @bitCast(i128, @as(u128, 0x123456789abcdef11121314151617181)), + @bitCast(i128, @as(u128, 0x8171615141312111f1debc9a78563412)), ); } fn t(comptime I: type, input: I, expected_output: I) void { diff --git a/test/stage1/behavior/cast.zig b/test/stage1/behavior/cast.zig @@ -4,7 +4,7 @@ const mem = std.mem; const maxInt = std.math.maxInt; test "int to ptr cast" { - const x = usize(13); + const x = @as(usize, 13); const y = @intToPtr(*u8, x); const z = @ptrToInt(y); expect(z == 13); @@ -75,8 +75,8 @@ test "peer resolve array and const slice" { comptime testPeerResolveArrayConstSlice(true); } fn testPeerResolveArrayConstSlice(b: bool) void { - const value1 = if (b) "aoeu" else ([]const u8)("zz"); - const value2 = if (b) ([]const u8)("zz") else "aoeu"; + const value1 = if (b) "aoeu" else @as([]const u8, "zz"); + const value2 = if (b) @as([]const u8, "zz") else "aoeu"; expect(mem.eql(u8, value1, "aoeu")); expect(mem.eql(u8, value2, "zz")); } @@ -90,7 +90,7 @@ const A = struct { a: i32, }; fn castToOptionalTypeError(z: i32) void { - const x = i32(1); + const x = @as(i32, 1); const y: anyerror!?i32 = x; expect((try y).? == 1); @@ -134,10 +134,10 @@ test "peer type resolution: ?T and T" { } fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize { if (c) { - return if (b) null else usize(0); + return if (b) null else @as(usize, 0); } - return usize(3); + return @as(usize, 3); } test "peer type resolution: [0]u8 and []const u8" { @@ -256,9 +256,9 @@ test "@floatToInt" { } fn testFloatToInts() void { - const x = i32(1e4); + const x = @as(i32, 1e4); expect(x == 10000); - const y = @floatToInt(i32, f32(1e4)); + const y = @floatToInt(i32, @as(f32, 1e4)); expect(y == 10000); expectFloatToInt(f16, 255.1, u8, 255); expectFloatToInt(f16, 127.2, i8, 127); @@ -392,7 +392,7 @@ fn MakeType(comptime T: type) type { } fn getNonNull() ?T { - return T(undefined); + return @as(T, undefined); } }; } @@ -442,7 +442,7 @@ fn incrementVoidPtrArray(array: ?*c_void, len: usize) void { } test "*usize to *void" { - var i = usize(0); + var i = @as(usize, 0); var v = @ptrCast(*void, &i); v.* = {}; } @@ -535,6 +535,33 @@ test "peer type resolution: unreachable, error set, unreachable" { } test "implicit cast comptime_int to comptime_float" { - comptime expect(comptime_float(10) == f32(10)); + comptime expect(@as(comptime_float, 10) == @as(f32, 10)); expect(2 == 2.0); } + +test "implicit cast *[0]T to E![]const u8" { + var x = @as(anyerror![]const u8, &[0]u8{}); + expect((x catch unreachable).len == 0); +} + +test "peer cast *[0]T to E![]const T" { + var buffer: [5]u8 = "abcde"; + var buf: anyerror![]const u8 = buffer[0..]; + var b = false; + var y = if (b) &[0]u8{} else buf; + expect(mem.eql(u8, "abcde", y catch unreachable)); +} + +test "peer cast *[0]T to []const T" { + var buffer: [5]u8 = "abcde"; + var buf: []const u8 = buffer[0..]; + var b = false; + var y = if (b) &[0]u8{} else buf; + expect(mem.eql(u8, "abcde", y)); +} + +var global_array: [4]u8 = undefined; +test "cast from array reference to fn" { + const f = @ptrCast(extern fn () void, &global_array); + expect(@ptrToInt(f) == @ptrToInt(&global_array)); +} diff --git a/test/stage1/behavior/defer.zig b/test/stage1/behavior/defer.zig @@ -52,7 +52,7 @@ fn testBreakContInDefer(x: usize) void { } test "defer and labeled break" { - var i = usize(0); + var i = @as(usize, 0); blk: { defer i += 1; diff --git a/test/stage1/behavior/enum.zig b/test/stage1/behavior/enum.zig @@ -788,7 +788,7 @@ fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void { expect(1234 == switch (x) { MultipleChoice.A => 1, MultipleChoice.B => 2, - MultipleChoice.C => u32(1234), + MultipleChoice.C => @as(u32, 1234), MultipleChoice.D => 4, }); } @@ -816,7 +816,7 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void { MultipleChoice2.A => 1, MultipleChoice2.B => 2, MultipleChoice2.C => 3, - MultipleChoice2.D => u32(1234), + MultipleChoice2.D => @as(u32, 1234), MultipleChoice2.Unspecified1 => 5, MultipleChoice2.Unspecified2 => 6, MultipleChoice2.Unspecified3 => 7, diff --git a/test/stage1/behavior/error.zig b/test/stage1/behavior/error.zig @@ -51,7 +51,7 @@ test "error binary operator" { expect(b == 10); } fn errBinaryOperatorG(x: bool) anyerror!isize { - return if (x) error.ItBroke else isize(10); + return if (x) error.ItBroke else @as(isize, 10); } test "unwrap simple value from error" { @@ -160,6 +160,10 @@ fn testErrToIntWithOnePossibleValue( } } +test "empty error union" { + const x = error{} || error{}; +} + test "error union peer type resolution" { testErrorUnionPeerTypeResolution(1); } @@ -295,7 +299,7 @@ test "nested error union function call in optional unwrap" { test "widen cast integer payload of error union function call" { const S = struct { fn errorable() !u64 { - var x = u64(try number()); + var x = @as(u64, try number()); return x; } diff --git a/test/stage1/behavior/eval.zig b/test/stage1/behavior/eval.zig @@ -405,19 +405,19 @@ test "float literal at compile time not lossy" { } test "f32 at compile time is lossy" { - expect(f32(1 << 24) + 1 == 1 << 24); + expect(@as(f32, 1 << 24) + 1 == 1 << 24); } test "f64 at compile time is lossy" { - expect(f64(1 << 53) + 1 == 1 << 53); + expect(@as(f64, 1 << 53) + 1 == 1 << 53); } test "f128 at compile time is lossy" { - expect(f128(10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0); + expect(@as(f128, 10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0); } comptime { - expect(f128(1 << 113) == 10384593717069655257060992658440192); + expect(@as(f128, 1 << 113) == 10384593717069655257060992658440192); } pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type { @@ -434,9 +434,9 @@ test "string literal used as comptime slice is memoized" { } test "comptime slice of undefined pointer of length 0" { - const slice1 = ([*]i32)(undefined)[0..0]; + const slice1 = @as([*]i32, undefined)[0..0]; expect(slice1.len == 0); - const slice2 = ([*]i32)(undefined)[100..100]; + const slice2 = @as([*]i32, undefined)[100..100]; expect(slice2.len == 0); } @@ -444,10 +444,10 @@ fn copyWithPartialInline(s: []u32, b: []u8) void { comptime var i: usize = 0; inline while (i < 4) : (i += 1) { s[i] = 0; - s[i] |= u32(b[i * 4 + 0]) << 24; - s[i] |= u32(b[i * 4 + 1]) << 16; - s[i] |= u32(b[i * 4 + 2]) << 8; - s[i] |= u32(b[i * 4 + 3]) << 0; + s[i] |= @as(u32, b[i * 4 + 0]) << 24; + s[i] |= @as(u32, b[i * 4 + 1]) << 16; + s[i] |= @as(u32, b[i * 4 + 2]) << 8; + s[i] |= @as(u32, b[i * 4 + 3]) << 0; } } @@ -557,14 +557,14 @@ test "array concat of slices gives slice" { test "comptime shlWithOverflow" { const ct_shifted: u64 = comptime amt: { - var amt = u64(0); - _ = @shlWithOverflow(u64, ~u64(0), 16, &amt); + var amt = @as(u64, 0); + _ = @shlWithOverflow(u64, ~@as(u64, 0), 16, &amt); break :amt amt; }; const rt_shifted: u64 = amt: { - var amt = u64(0); - _ = @shlWithOverflow(u64, ~u64(0), 16, &amt); + var amt = @as(u64, 0); + _ = @shlWithOverflow(u64, ~@as(u64, 0), 16, &amt); break :amt amt; }; @@ -670,7 +670,7 @@ fn loopNTimes(comptime n: usize) void { } test "variable inside inline loop that has different types on different iterations" { - testVarInsideInlineLoop(true, u32(42)); + testVarInsideInlineLoop(true, @as(u32, 42)); } fn testVarInsideInlineLoop(args: ...) void { @@ -757,11 +757,11 @@ test "comptime bitwise operators" { expect(-3 | -1 == -1); expect(3 ^ -1 == -4); expect(-3 ^ -1 == 2); - expect(~i8(-1) == 0); - expect(~i128(-1) == 0); + expect(~@as(i8, -1) == 0); + expect(~@as(i128, -1) == 0); expect(18446744073709551615 & 18446744073709551611 == 18446744073709551611); expect(-18446744073709551615 & -18446744073709551611 == -18446744073709551615); - expect(~u128(0) == 0xffffffffffffffffffffffffffffffff); + expect(~@as(u128, 0) == 0xffffffffffffffffffffffffffffffff); } } diff --git a/test/stage1/behavior/floatop.zig b/test/stage1/behavior/floatop.zig @@ -117,11 +117,11 @@ test "@ln" { fn testLn() void { { var a: f32 = e; - expect(@ln(f32, a) == 1 or @ln(f32, a) == @bitCast(f32, u32(0x3f7fffff))); + expect(@ln(f32, a) == 1 or @ln(f32, a) == @bitCast(f32, @as(u32, 0x3f7fffff))); } { var a: f64 = e; - expect(@ln(f64, a) == 1 or @ln(f64, a) == @bitCast(f64, u64(0x3ff0000000000000))); + expect(@ln(f64, a) == 1 or @ln(f64, a) == @bitCast(f64, @as(u64, 0x3ff0000000000000))); } } diff --git a/test/stage1/behavior/fn.zig b/test/stage1/behavior/fn.zig @@ -29,7 +29,7 @@ test "mutable local variables" { var zero: i32 = 0; expect(zero == 0); - var i = i32(0); + var i = @as(i32, 0); while (i != 3) { i += 1; } @@ -43,7 +43,7 @@ test "separate block scopes" { } const c = x: { - const no_conflict = i32(10); + const no_conflict = @as(i32, 10); break :x no_conflict; }; expect(c == 10); @@ -247,3 +247,19 @@ test "discard the result of a function that returns a struct" { S.entry(); comptime S.entry(); } + +test "function call with anon list literal" { + const S = struct { + fn doTheTest() void { + consumeVec(.{9, 8, 7}); + } + + fn consumeVec(vec: [3]f32) void { + expect(vec[0] == 9); + expect(vec[1] == 8); + expect(vec[2] == 7); + } + }; + S.doTheTest(); + comptime S.doTheTest(); +} diff --git a/test/stage1/behavior/if.zig b/test/stage1/behavior/if.zig @@ -32,7 +32,7 @@ fn elseIfExpressionF(c: u8) u8 { } else if (c == 1) { return 1; } else { - return u8(2); + return @as(u8, 2); } } @@ -58,7 +58,7 @@ test "labeled break inside comptime if inside runtime if" { var c = true; if (c) { answer = if (true) blk: { - break :blk i32(42); + break :blk @as(i32, 42); }; } expect(answer == 42); diff --git a/test/stage1/behavior/import.zig b/test/stage1/behavior/import.zig @@ -3,7 +3,7 @@ const expectEqual = @import("std").testing.expectEqual; const a_namespace = @import("import/a_namespace.zig"); test "call fn via namespace lookup" { - expectEqual(i32(1234), a_namespace.foo()); + expectEqual(@as(i32, 1234), a_namespace.foo()); } test "importing the same thing gives the same import" { @@ -14,5 +14,5 @@ test "import in non-toplevel scope" { const S = struct { usingnamespace @import("import/a_namespace.zig"); }; - expectEqual(i32(1234), S.foo()); + expectEqual(@as(i32, 1234), S.foo()); } diff --git a/test/stage1/behavior/math.zig b/test/stage1/behavior/math.zig @@ -186,9 +186,9 @@ fn testThreeExprInARow(f: bool, t: bool) void { assertFalse(90 >> 1 >> 2 != 90 >> 3); assertFalse(100 - 1 + 1000 != 1099); assertFalse(5 * 4 / 2 % 3 != 1); - assertFalse(i32(i32(5)) != 5); + assertFalse(@as(i32, @as(i32, 5)) != 5); assertFalse(!!false); - assertFalse(i32(7) != --(i32(7))); + assertFalse(@as(i32, 7) != --(@as(i32, 7))); } fn assertFalse(b: bool) void { expect(!b); @@ -256,10 +256,10 @@ const DivResult = struct { test "binary not" { expect(comptime x: { - break :x ~u16(0b1010101010101010) == 0b0101010101010101; + break :x ~@as(u16, 0b1010101010101010) == 0b0101010101010101; }); expect(comptime x: { - break :x ~u64(2147483647) == 18446744071562067968; + break :x ~@as(u64, 2147483647) == 18446744071562067968; }); testBinaryNot(0b1010101010101010); } @@ -472,7 +472,7 @@ test "comptime_int multiplication" { test "comptime_int shifting" { comptime { - expect((u128(1) << 127) == 0x80000000000000000000000000000000); + expect((@as(u128, 1) << 127) == 0x80000000000000000000000000000000); } } @@ -480,13 +480,13 @@ test "comptime_int multi-limb shift and mask" { comptime { var a = 0xefffffffa0000001eeeeeeefaaaaaaab; - expect(u32(a & 0xffffffff) == 0xaaaaaaab); + expect(@as(u32, a & 0xffffffff) == 0xaaaaaaab); a >>= 32; - expect(u32(a & 0xffffffff) == 0xeeeeeeef); + expect(@as(u32, a & 0xffffffff) == 0xeeeeeeef); a >>= 32; - expect(u32(a & 0xffffffff) == 0xa0000001); + expect(@as(u32, a & 0xffffffff) == 0xa0000001); a >>= 32; - expect(u32(a & 0xffffffff) == 0xefffffff); + expect(@as(u32, a & 0xffffffff) == 0xefffffff); a >>= 32; expect(a == 0); @@ -552,7 +552,7 @@ fn should_not_be_zero(x: f128) void { test "comptime float rem int" { comptime { - var x = f32(1) % 2; + var x = @as(f32, 1) % 2; expect(x == 1.0); } } @@ -568,8 +568,8 @@ test "remainder division" { } fn remdiv(comptime T: type) void { - expect(T(1) == T(1) % T(2)); - expect(T(1) == T(7) % T(3)); + expect(@as(T, 1) == @as(T, 1) % @as(T, 2)); + expect(@as(T, 1) == @as(T, 7) % @as(T, 3)); } test "@sqrt" { diff --git a/test/stage1/behavior/misc.zig b/test/stage1/behavior/misc.zig @@ -241,14 +241,14 @@ fn memFree(comptime T: type, memory: []T) void {} test "cast undefined" { const array: [100]u8 = undefined; - const slice = ([]const u8)(array); + const slice = @as([]const u8, array); testCastUndefined(slice); } fn testCastUndefined(x: []const u8) void {} test "cast small unsigned to larger signed" { - expect(castSmallUnsignedToLargerSigned1(200) == i16(200)); - expect(castSmallUnsignedToLargerSigned2(9999) == i64(9999)); + expect(castSmallUnsignedToLargerSigned1(200) == @as(i16, 200)); + expect(castSmallUnsignedToLargerSigned2(9999) == @as(i64, 9999)); } fn castSmallUnsignedToLargerSigned1(x: u8) i16 { return x; @@ -268,7 +268,7 @@ fn outer() i64 { } test "pointer dereferencing" { - var x = i32(3); + var x = @as(i32, 3); const y = &x; y.* += 1; @@ -350,7 +350,7 @@ fn testTakeAddressOfParameter(f: f32) void { } test "pointer comparison" { - const a = ([]const u8)("a"); + const a = @as([]const u8, "a"); const b = &a; expect(ptrEql(b, b)); } @@ -500,7 +500,7 @@ fn TypeFromFn(comptime T: type) type { } test "double implicit cast in same expression" { - var x = i32(u16(nine())); + var x = @as(i32, @as(u16, nine())); expect(x == 9); } fn nine() u8 { @@ -642,7 +642,7 @@ test "self reference through fn ptr field" { test "volatile load and store" { var number: i32 = 1234; - const ptr = (*volatile i32)(&number); + const ptr = @as(*volatile i32, &number); ptr.* += 1; expect(ptr.* == 1235); } @@ -761,7 +761,7 @@ test "nested optional field in struct" { fn maybe(x: bool) anyerror!?u32 { return switch (x) { - true => u32(42), + true => @as(u32, 42), else => null, }; } diff --git a/test/stage1/behavior/popcount.zig b/test/stage1/behavior/popcount.zig @@ -35,7 +35,7 @@ fn testPopCount() void { expect(@popCount(i8, x) == 2); } comptime { - expect(@popCount(u8, @bitCast(u8, i8(-120))) == 2); + expect(@popCount(u8, @bitCast(u8, @as(i8, -120))) == 2); } comptime { expect(@popCount(i128, 0b11111111000110001100010000100001000011000011100101010001) == 24); diff --git a/test/stage1/behavior/pub_enum.zig b/test/stage1/behavior/pub_enum.zig @@ -9,5 +9,5 @@ fn pubEnumTest(foo: other.APubEnum) void { } test "cast with imported symbol" { - expect(other.size_t(42) == 42); + expect(@as(other.size_t, 42) == 42); } diff --git a/test/stage1/behavior/shuffle.zig b/test/stage1/behavior/shuffle.zig @@ -7,39 +7,39 @@ test "@shuffle" { fn doTheTest() void { var v: @Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 }; var x: @Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 }; - const mask: @Vector(4, i32) = [4]i32{ 0, ~i32(2), 3, ~i32(3) }; + const mask: @Vector(4, i32) = [4]i32{ 0, ~@as(i32, 2), 3, ~@as(i32, 3) }; var res = @shuffle(i32, v, x, mask); - expect(mem.eql(i32, ([4]i32)(res), [4]i32{ 2147483647, 3, 40, 4 })); + expect(mem.eql(i32, @as([4]i32,res), [4]i32{ 2147483647, 3, 40, 4 })); // Implicit cast from array (of mask) - res = @shuffle(i32, v, x, [4]i32{ 0, ~i32(2), 3, ~i32(3) }); - expect(mem.eql(i32, ([4]i32)(res), [4]i32{ 2147483647, 3, 40, 4 })); + res = @shuffle(i32, v, x, [4]i32{ 0, ~@as(i32, 2), 3, ~@as(i32, 3) }); + expect(mem.eql(i32, @as([4]i32,res), [4]i32{ 2147483647, 3, 40, 4 })); // Undefined const mask2: @Vector(4, i32) = [4]i32{ 3, 1, 2, 0 }; res = @shuffle(i32, v, undefined, mask2); - expect(mem.eql(i32, ([4]i32)(res), [4]i32{ 40, -2, 30, 2147483647 })); + expect(mem.eql(i32, @as([4]i32,res), [4]i32{ 40, -2, 30, 2147483647 })); // Upcasting of b var v2: @Vector(2, i32) = [2]i32{ 2147483647, undefined }; - const mask3: @Vector(4, i32) = [4]i32{ ~i32(0), 2, ~i32(0), 3 }; + const mask3: @Vector(4, i32) = [4]i32{ ~@as(i32, 0), 2, ~@as(i32, 0), 3 }; res = @shuffle(i32, x, v2, mask3); - expect(mem.eql(i32, ([4]i32)(res), [4]i32{ 2147483647, 3, 2147483647, 4 })); + expect(mem.eql(i32, @as([4]i32,res), [4]i32{ 2147483647, 3, 2147483647, 4 })); // Upcasting of a var v3: @Vector(2, i32) = [2]i32{ 2147483647, -2 }; - const mask4: @Vector(4, i32) = [4]i32{ 0, ~i32(2), 1, ~i32(3) }; + const mask4: @Vector(4, i32) = [4]i32{ 0, ~@as(i32, 2), 1, ~@as(i32, 3) }; res = @shuffle(i32, v3, x, mask4); - expect(mem.eql(i32, ([4]i32)(res), [4]i32{ 2147483647, 3, -2, 4 })); + expect(mem.eql(i32, @as([4]i32,res), [4]i32{ 2147483647, 3, -2, 4 })); // bool // Disabled because of #3317 if (@import("builtin").arch != .mipsel) { var x2: @Vector(4, bool) = [4]bool{ false, true, false, true }; var v4: @Vector(2, bool) = [2]bool{ true, false }; - const mask5: @Vector(4, i32) = [4]i32{ 0, ~i32(1), 1, 2 }; + const mask5: @Vector(4, i32) = [4]i32{ 0, ~@as(i32, 1), 1, 2 }; var res2 = @shuffle(bool, x2, v4, mask5); - expect(mem.eql(bool, ([4]bool)(res2), [4]bool{ false, false, true, false })); + expect(mem.eql(bool, @as([4]bool,res2), [4]bool{ false, false, true, false })); } // TODO re-enable when LLVM codegen is fixed @@ -47,9 +47,9 @@ test "@shuffle" { if (false) { var x2: @Vector(3, bool) = [3]bool{ false, true, false }; var v4: @Vector(2, bool) = [2]bool{ true, false }; - const mask5: @Vector(4, i32) = [4]i32{ 0, ~i32(1), 1, 2 }; + const mask5: @Vector(4, i32) = [4]i32{ 0, ~@as(i32, 1), 1, 2 }; var res2 = @shuffle(bool, x2, v4, mask5); - expect(mem.eql(bool, ([4]bool)(res2), [4]bool{ false, false, true, false })); + expect(mem.eql(bool, @as([4]bool,res2), [4]bool{ false, false, true, false })); } } }; diff --git a/test/stage1/behavior/slicetobytes.zig b/test/stage1/behavior/slicetobytes.zig @@ -10,7 +10,7 @@ test "@sliceToBytes packed struct at runtime and comptime" { const S = struct { fn doTheTest() void { var foo: Foo = undefined; - var slice = @sliceToBytes(((*[1]Foo)(&foo))[0..1]); + var slice = @sliceToBytes(@as(*[1]Foo, &foo)[0..1]); slice[0] = 0x13; switch (builtin.endian) { builtin.Endian.Big => { diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig @@ -388,8 +388,8 @@ test "runtime struct initialization of bitfield" { expect(s2.y == @intCast(u4, x2)); } -var x1 = u4(1); -var x2 = u8(2); +var x1 = @as(u4, 1); +var x2 = @as(u8, 2); const Nibbles = packed struct { x: u4, @@ -545,9 +545,9 @@ test "packed struct with fp fields" { s.data[1] = 2.0; s.data[2] = 3.0; s.frob(); - expectEqual(f32(6.0), s.data[0]); - expectEqual(f32(11.0), s.data[1]); - expectEqual(f32(20.0), s.data[2]); + expectEqual(@as(f32, 6.0), s.data[0]); + expectEqual(@as(f32, 11.0), s.data[1]); + expectEqual(@as(f32, 20.0), s.data[2]); } test "use within struct scope" { @@ -558,7 +558,7 @@ test "use within struct scope" { } }; }; - expectEqual(i32(42), S.inner()); + expectEqual(@as(i32, 42), S.inner()); } test "default struct initialization fields" { @@ -583,7 +583,7 @@ test "extern fn returns struct by value" { const S = struct { fn entry() void { var x = makeBar(10); - expectEqual(i32(10), x.handle); + expectEqual(@as(i32, 10), x.handle); } const ExternBar = extern struct { @@ -614,7 +614,7 @@ test "for loop over pointers to struct, getting field from struct pointer" { const ArrayList = struct { fn toSlice(self: *ArrayList) []*Foo { - return ([*]*Foo)(undefined)[0..0]; + return @as([*]*Foo, undefined)[0..0]; } }; @@ -709,3 +709,71 @@ test "packed struct field passed to generic function" { var loaded = S.genericReadPackedField(&p.b); expect(loaded == 29); } + +test "anonymous struct literal syntax" { + const S = struct { + const Point = struct { + x: i32, + y: i32, + }; + + fn doTheTest() void { + var p: Point = .{ + .x = 1, + .y = 2, + }; + expect(p.x == 1); + expect(p.y == 2); + } + }; + S.doTheTest(); + comptime S.doTheTest(); +} + +test "fully anonymous struct" { + const S = struct { + fn doTheTest() void { + dump(.{ + .int = @as(u32, 1234), + .float = @as(f64, 12.34), + .b = true, + .s = "hi", + }); + } + fn dump(args: var) void { + expect(args.int == 1234); + expect(args.float == 12.34); + expect(args.b); + expect(args.s[0] == 'h'); + expect(args.s[1] == 'i'); + } + }; + S.doTheTest(); + comptime S.doTheTest(); +} + +test "fully anonymous list literal" { + const S = struct { + fn doTheTest() void { + dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi" }); + } + fn dump(args: var) void { + expect(args.@"0" == 1234); + expect(args.@"1" == 12.34); + expect(args.@"2"); + expect(args.@"3"[0] == 'h'); + expect(args.@"3"[1] == 'i'); + } + }; + S.doTheTest(); + comptime S.doTheTest(); +} + +test "anonymous struct literal assigned to variable" { + var vec = .{ @as(i32, 22), @as(i32, 55), @as(i32, 99) }; + expect(vec.@"0" == 22); + expect(vec.@"1" == 55); + expect(vec.@"2" == 99); + vec.@"1" += 1; + expect(vec.@"1" == 56); +} diff --git a/test/stage1/behavior/switch.zig b/test/stage1/behavior/switch.zig @@ -68,7 +68,7 @@ test "switch statement" { } fn nonConstSwitch(foo: SwitchStatmentFoo) void { const val = switch (foo) { - SwitchStatmentFoo.A => i32(1), + SwitchStatmentFoo.A => @as(i32, 1), SwitchStatmentFoo.B => 2, SwitchStatmentFoo.C => 3, SwitchStatmentFoo.D => 4, @@ -127,7 +127,7 @@ test "switch with multiple expressions" { const x = switch (returnsFive()) { 1, 2, 3 => 1, 4, 5, 6 => 2, - else => i32(3), + else => @as(i32, 3), }; expect(x == 2); } @@ -186,7 +186,7 @@ fn testSwitchHandleAllCases() void { fn testSwitchHandleAllCasesExhaustive(x: u2) u2 { return switch (x) { - 0 => u2(3), + 0 => @as(u2, 3), 1 => 2, 2 => 1, 3 => 0, @@ -195,7 +195,7 @@ fn testSwitchHandleAllCasesExhaustive(x: u2) u2 { fn testSwitchHandleAllCasesRange(x: u8) u8 { return switch (x) { - 0...100 => u8(0), + 0...100 => @as(u8, 0), 101...200 => 1, 201, 203 => 2, 202 => 4, diff --git a/test/stage1/behavior/try.zig b/test/stage1/behavior/try.zig @@ -8,7 +8,7 @@ test "try on error union" { fn tryOnErrorUnionImpl() void { const x = if (returnsTen()) |val| val + 1 else |err| switch (err) { error.ItBroke, error.NoMem => 1, - error.CrappedOut => i32(2), + error.CrappedOut => @as(i32, 2), else => unreachable, }; expect(x == 11); @@ -19,10 +19,10 @@ fn returnsTen() anyerror!i32 { } test "try without vars" { - const result1 = if (failIfTrue(true)) 1 else |_| i32(2); + const result1 = if (failIfTrue(true)) 1 else |_| @as(i32, 2); expect(result1 == 2); - const result2 = if (failIfTrue(false)) 1 else |_| i32(2); + const result2 = if (failIfTrue(false)) 1 else |_| @as(i32, 2); expect(result2 == 1); } diff --git a/test/stage1/behavior/type_info.zig b/test/stage1/behavior/type_info.zig @@ -13,7 +13,7 @@ test "type info: tag type, void info" { fn testBasic() void { expect(@TagType(TypeInfo) == TypeId); const void_info = @typeInfo(void); - expect(TypeId(void_info) == TypeId.Void); + expect(@as(TypeId, void_info) == TypeId.Void); expect(void_info.Void == {}); } @@ -24,12 +24,12 @@ test "type info: integer, floating point type info" { fn testIntFloat() void { const u8_info = @typeInfo(u8); - expect(TypeId(u8_info) == TypeId.Int); + expect(@as(TypeId, u8_info) == TypeId.Int); expect(!u8_info.Int.is_signed); expect(u8_info.Int.bits == 8); const f64_info = @typeInfo(f64); - expect(TypeId(f64_info) == TypeId.Float); + expect(@as(TypeId, f64_info) == TypeId.Float); expect(f64_info.Float.bits == 64); } @@ -40,7 +40,7 @@ test "type info: pointer type info" { fn testPointer() void { const u32_ptr_info = @typeInfo(*u32); - expect(TypeId(u32_ptr_info) == TypeId.Pointer); + expect(@as(TypeId, u32_ptr_info) == TypeId.Pointer); expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One); expect(u32_ptr_info.Pointer.is_const == false); expect(u32_ptr_info.Pointer.is_volatile == false); @@ -55,7 +55,7 @@ test "type info: unknown length pointer type info" { fn testUnknownLenPtr() void { const u32_ptr_info = @typeInfo([*]const volatile f64); - expect(TypeId(u32_ptr_info) == TypeId.Pointer); + expect(@as(TypeId,u32_ptr_info) == TypeId.Pointer); expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many); expect(u32_ptr_info.Pointer.is_const == true); expect(u32_ptr_info.Pointer.is_volatile == true); @@ -70,7 +70,7 @@ test "type info: C pointer type info" { fn testCPtr() void { const ptr_info = @typeInfo([*c]align(4) const i8); - expect(TypeId(ptr_info) == TypeId.Pointer); + expect(@as(TypeId,ptr_info) == TypeId.Pointer); expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.C); expect(ptr_info.Pointer.is_const); expect(!ptr_info.Pointer.is_volatile); @@ -85,7 +85,7 @@ test "type info: slice type info" { fn testSlice() void { const u32_slice_info = @typeInfo([]u32); - expect(TypeId(u32_slice_info) == TypeId.Pointer); + expect(@as(TypeId, u32_slice_info) == TypeId.Pointer); expect(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice); expect(u32_slice_info.Pointer.is_const == false); expect(u32_slice_info.Pointer.is_volatile == false); @@ -100,7 +100,7 @@ test "type info: array type info" { fn testArray() void { const arr_info = @typeInfo([42]bool); - expect(TypeId(arr_info) == TypeId.Array); + expect(@as(TypeId, arr_info) == TypeId.Array); expect(arr_info.Array.len == 42); expect(arr_info.Array.child == bool); } @@ -112,7 +112,7 @@ test "type info: optional type info" { fn testOptional() void { const null_info = @typeInfo(?void); - expect(TypeId(null_info) == TypeId.Optional); + expect(@as(TypeId, null_info) == TypeId.Optional); expect(null_info.Optional.child == void); } @@ -129,18 +129,18 @@ fn testErrorSet() void { }; const error_set_info = @typeInfo(TestErrorSet); - expect(TypeId(error_set_info) == TypeId.ErrorSet); + expect(@as(TypeId, error_set_info) == TypeId.ErrorSet); expect(error_set_info.ErrorSet.?.len == 3); expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "First")); expect(error_set_info.ErrorSet.?[2].value == @errorToInt(TestErrorSet.Third)); const error_union_info = @typeInfo(TestErrorSet!usize); - expect(TypeId(error_union_info) == TypeId.ErrorUnion); + expect(@as(TypeId, error_union_info) == TypeId.ErrorUnion); expect(error_union_info.ErrorUnion.error_set == TestErrorSet); expect(error_union_info.ErrorUnion.payload == usize); const global_info = @typeInfo(anyerror); - expect(TypeId(global_info) == TypeId.ErrorSet); + expect(@as(TypeId, global_info) == TypeId.ErrorSet); expect(global_info.ErrorSet == null); } @@ -158,7 +158,7 @@ fn testEnum() void { }; const os_info = @typeInfo(Os); - expect(TypeId(os_info) == TypeId.Enum); + expect(@as(TypeId, os_info) == TypeId.Enum); expect(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto); expect(os_info.Enum.fields.len == 4); expect(mem.eql(u8, os_info.Enum.fields[1].name, "Macos")); @@ -174,7 +174,7 @@ test "type info: union info" { fn testUnion() void { const typeinfo_info = @typeInfo(TypeInfo); - expect(TypeId(typeinfo_info) == TypeId.Union); + expect(@as(TypeId, typeinfo_info) == TypeId.Union); expect(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto); expect(typeinfo_info.Union.tag_type.? == TypeId); expect(typeinfo_info.Union.fields.len == 26); @@ -189,7 +189,7 @@ fn testUnion() void { }; const notag_union_info = @typeInfo(TestNoTagUnion); - expect(TypeId(notag_union_info) == TypeId.Union); + expect(@as(TypeId, notag_union_info) == TypeId.Union); expect(notag_union_info.Union.tag_type == null); expect(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto); expect(notag_union_info.Union.fields.len == 2); @@ -214,7 +214,7 @@ test "type info: struct info" { fn testStruct() void { const struct_info = @typeInfo(TestStruct); - expect(TypeId(struct_info) == TypeId.Struct); + expect(@as(TypeId, struct_info) == TypeId.Struct); expect(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed); expect(struct_info.Struct.fields.len == 3); expect(struct_info.Struct.fields[1].offset == null); @@ -244,7 +244,7 @@ test "type info: function type info" { fn testFunction() void { const fn_info = @typeInfo(@typeOf(foo)); - expect(TypeId(fn_info) == TypeId.Fn); + expect(@as(TypeId, fn_info) == TypeId.Fn); expect(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified); expect(fn_info.Fn.is_generic); expect(fn_info.Fn.args.len == 2); @@ -253,7 +253,7 @@ fn testFunction() void { const test_instance: TestStruct = undefined; const bound_fn_info = @typeInfo(@typeOf(test_instance.foo)); - expect(TypeId(bound_fn_info) == TypeId.BoundFn); + expect(@as(TypeId, bound_fn_info) == TypeId.BoundFn); expect(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct); } @@ -275,7 +275,7 @@ test "type info: vectors" { fn testVector() void { const vec_info = @typeInfo(@Vector(4, i32)); - expect(TypeId(vec_info) == TypeId.Vector); + expect(@as(TypeId, vec_info) == TypeId.Vector); expect(vec_info.Vector.len == 4); expect(vec_info.Vector.child == i32); } @@ -288,13 +288,13 @@ test "type info: anyframe and anyframe->T" { fn testAnyFrame() void { { const anyframe_info = @typeInfo(anyframe->i32); - expect(TypeId(anyframe_info) == .AnyFrame); + expect(@as(TypeId,anyframe_info) == .AnyFrame); expect(anyframe_info.AnyFrame.child.? == i32); } { const anyframe_info = @typeInfo(anyframe); - expect(TypeId(anyframe_info) == .AnyFrame); + expect(@as(TypeId,anyframe_info) == .AnyFrame); expect(anyframe_info.AnyFrame.child == null); } } @@ -334,7 +334,7 @@ test "type info: extern fns with and without lib names" { if (std.mem.eql(u8, decl.name, "bar1")) { expect(decl.data.Fn.lib_name == null); } else { - std.testing.expectEqual(([]const u8)("cool"), decl.data.Fn.lib_name.?); + std.testing.expectEqual(@as([]const u8,"cool"), decl.data.Fn.lib_name.?); } } } @@ -342,7 +342,7 @@ test "type info: extern fns with and without lib names" { test "data field is a compile-time value" { const S = struct { - const Bar = isize(-1); + const Bar = @as(isize, -1); }; comptime expect(@typeInfo(S).Struct.decls[0].data.Var == isize); } diff --git a/test/stage1/behavior/union.zig b/test/stage1/behavior/union.zig @@ -14,7 +14,7 @@ const Agg = struct { const v1 = Value{ .Int = 1234 }; const v2 = Value{ .Array = [_]u8{3} ** 9 }; -const err = (anyerror!Agg)(Agg{ +const err = @as(anyerror!Agg, Agg{ .val1 = v1, .val2 = v2, }); @@ -110,11 +110,11 @@ fn doTest() void { } fn bar(value: Payload) i32 { - expect(Letter(value) == Letter.A); + expect(@as(Letter, value) == Letter.A); return switch (value) { Payload.A => |x| return x - 1244, - Payload.B => |x| if (x == 12.34) i32(20) else 21, - Payload.C => |x| if (x) i32(30) else 31, + Payload.B => |x| if (x == 12.34) @as(i32, 20) else 21, + Payload.C => |x| if (x) @as(i32, 30) else 31, }; } @@ -127,7 +127,7 @@ const MultipleChoice = union(enum(u32)) { test "simple union(enum(u32))" { var x = MultipleChoice.C; expect(x == MultipleChoice.C); - expect(@enumToInt(@TagType(MultipleChoice)(x)) == 60); + expect(@enumToInt(@as(@TagType(MultipleChoice), x)) == 60); } const MultipleChoice2 = union(enum(u32)) { @@ -149,11 +149,11 @@ test "union(enum(u32)) with specified and unspecified tag values" { } fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void { - expect(@enumToInt(@TagType(MultipleChoice2)(x)) == 60); + expect(@enumToInt(@as(@TagType(MultipleChoice2), x)) == 60); expect(1123 == switch (x) { MultipleChoice2.A => 1, MultipleChoice2.B => 2, - MultipleChoice2.C => |v| i32(1000) + v, + MultipleChoice2.C => |v| @as(i32, 1000) + v, MultipleChoice2.D => 4, MultipleChoice2.Unspecified1 => 5, MultipleChoice2.Unspecified2 => 6, @@ -208,12 +208,12 @@ test "cast union to tag type of union" { } fn testCastUnionToTagType(x: TheUnion) void { - expect(TheTag(x) == TheTag.B); + expect(@as(TheTag, x) == TheTag.B); } test "cast tag type of union to union" { var x: Value2 = Letter2.B; - expect(Letter2(x) == Letter2.B); + expect(@as(Letter2, x) == Letter2.B); } const Letter2 = enum { A, @@ -297,7 +297,7 @@ const TaggedUnionWithAVoid = union(enum) { fn testTaggedUnionInit(x: var) bool { const y = TaggedUnionWithAVoid{ .A = x }; - return @TagType(TaggedUnionWithAVoid)(y) == TaggedUnionWithAVoid.A; + return @as(@TagType(TaggedUnionWithAVoid), y) == TaggedUnionWithAVoid.A; } pub const UnionEnumNoPayloads = union(enum) { @@ -326,7 +326,7 @@ test "union with only 1 field casted to its enum type" { var e = Expr{ .Literal = Literal{ .Bool = true } }; const Tag = @TagType(Expr); comptime expect(@TagType(Tag) == u0); - var t = Tag(e); + var t = @as(Tag, e); expect(t == Expr.Literal); } @@ -346,7 +346,7 @@ test "union with only 1 field casted to its enum type which has enum value speci var e = Expr{ .Literal = Literal{ .Bool = true } }; comptime expect(@TagType(Tag) == comptime_int); - var t = Tag(e); + var t = @as(Tag, e); expect(t == Expr.Literal); expect(@enumToInt(t) == 33); comptime expect(@enumToInt(t) == 33); @@ -535,3 +535,50 @@ test "global union with single field is correctly initialized" { }; expect(glbl.f.x == 123); } + +pub const FooUnion = union(enum) { + U0: usize, + U1: u8, +}; + +var glbl_array: [2]FooUnion = undefined; + +test "initialize global array of union" { + glbl_array[1] = FooUnion{ .U1 = 2 }; + glbl_array[0] = FooUnion{ .U0 = 1 }; + expect(glbl_array[0].U0 == 1); + expect(glbl_array[1].U1 == 2); +} + +test "anonymous union literal syntax" { + const S = struct { + const Number = union { + int: i32, + float: f64, + }; + + fn doTheTest() void { + var i: Number = .{ .int = 42 }; + var f = makeNumber(); + expect(i.int == 42); + expect(f.float == 12.34); + } + + fn makeNumber() Number { + return .{ .float = 12.34 }; + } + }; + S.doTheTest(); + comptime S.doTheTest(); +} + +test "update the tag value for zero-sized unions" { + const S = union(enum) { + U0: void, + U1: void, + }; + var x = S{ .U0 = {} }; + expect(x == .U0); + x = S{ .U1 = {} }; + expect(x == .U1); +} diff --git a/test/stage1/behavior/var_args.zig b/test/stage1/behavior/var_args.zig @@ -1,7 +1,7 @@ const expect = @import("std").testing.expect; fn add(args: ...) i32 { - var sum = i32(0); + var sum = @as(i32, 0); { comptime var i: usize = 0; inline while (i < args.len) : (i += 1) { @@ -12,8 +12,8 @@ fn add(args: ...) i32 { } test "add arbitrary args" { - expect(add(i32(1), i32(2), i32(3), i32(4)) == 10); - expect(add(i32(1234)) == 1234); + expect(add(@as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4)) == 10); + expect(add(@as(i32, 1234)) == 1234); expect(add() == 0); } @@ -26,8 +26,8 @@ test "send void arg to var args" { } test "pass args directly" { - expect(addSomeStuff(i32(1), i32(2), i32(3), i32(4)) == 10); - expect(addSomeStuff(i32(1234)) == 1234); + expect(addSomeStuff(@as(i32, 1), @as(i32, 2), @as(i32, 3), @as(i32, 4)) == 10); + expect(addSomeStuff(@as(i32, 1234)) == 1234); expect(addSomeStuff() == 0); } diff --git a/test/stage1/behavior/vector.zig b/test/stage1/behavior/vector.zig @@ -20,11 +20,11 @@ test "vector wrap operators" { fn doTheTest() void { var v: @Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 }; var x: @Vector(4, i32) = [4]i32{ 1, 2147483647, 3, 4 }; - expect(mem.eql(i32, ([4]i32)(v +% x), [4]i32{ -2147483648, 2147483645, 33, 44 })); - expect(mem.eql(i32, ([4]i32)(v -% x), [4]i32{ 2147483646, 2147483647, 27, 36 })); - expect(mem.eql(i32, ([4]i32)(v *% x), [4]i32{ 2147483647, 2, 90, 160 })); + expect(mem.eql(i32, @as([4]i32, v +% x), [4]i32{ -2147483648, 2147483645, 33, 44 })); + expect(mem.eql(i32, @as([4]i32, v -% x), [4]i32{ 2147483646, 2147483647, 27, 36 })); + expect(mem.eql(i32, @as([4]i32, v *% x), [4]i32{ 2147483647, 2, 90, 160 })); var z: @Vector(4, i32) = [4]i32{ 1, 2, 3, -2147483648 }; - expect(mem.eql(i32, ([4]i32)(-%z), [4]i32{ -1, -2, -3, -2147483648 })); + expect(mem.eql(i32, @as([4]i32, -%z), [4]i32{ -1, -2, -3, -2147483648 })); } }; S.doTheTest(); @@ -36,12 +36,12 @@ test "vector bin compares with mem.eql" { fn doTheTest() void { var v: @Vector(4, i32) = [4]i32{ 2147483647, -2, 30, 40 }; var x: @Vector(4, i32) = [4]i32{ 1, 2147483647, 30, 4 }; - expect(mem.eql(bool, ([4]bool)(v == x), [4]bool{ false, false, true, false })); - expect(mem.eql(bool, ([4]bool)(v != x), [4]bool{ true, true, false, true })); - expect(mem.eql(bool, ([4]bool)(v < x), [4]bool{ false, true, false, false })); - expect(mem.eql(bool, ([4]bool)(v > x), [4]bool{ true, false, false, true })); - expect(mem.eql(bool, ([4]bool)(v <= x), [4]bool{ false, true, true, false })); - expect(mem.eql(bool, ([4]bool)(v >= x), [4]bool{ true, false, true, true })); + expect(mem.eql(bool, @as([4]bool, v == x), [4]bool{ false, false, true, false })); + expect(mem.eql(bool, @as([4]bool, v != x), [4]bool{ true, true, false, true })); + expect(mem.eql(bool, @as([4]bool, v < x), [4]bool{ false, true, false, false })); + expect(mem.eql(bool, @as([4]bool, v > x), [4]bool{ true, false, false, true })); + expect(mem.eql(bool, @as([4]bool, v <= x), [4]bool{ false, true, true, false })); + expect(mem.eql(bool, @as([4]bool, v >= x), [4]bool{ true, false, true, true })); } }; S.doTheTest(); @@ -53,10 +53,10 @@ test "vector int operators" { fn doTheTest() void { var v: @Vector(4, i32) = [4]i32{ 10, 20, 30, 40 }; var x: @Vector(4, i32) = [4]i32{ 1, 2, 3, 4 }; - expect(mem.eql(i32, ([4]i32)(v + x), [4]i32{ 11, 22, 33, 44 })); - expect(mem.eql(i32, ([4]i32)(v - x), [4]i32{ 9, 18, 27, 36 })); - expect(mem.eql(i32, ([4]i32)(v * x), [4]i32{ 10, 40, 90, 160 })); - expect(mem.eql(i32, ([4]i32)(-v), [4]i32{ -10, -20, -30, -40 })); + expect(mem.eql(i32, @as([4]i32, v + x), [4]i32{ 11, 22, 33, 44 })); + expect(mem.eql(i32, @as([4]i32, v - x), [4]i32{ 9, 18, 27, 36 })); + expect(mem.eql(i32, @as([4]i32, v * x), [4]i32{ 10, 40, 90, 160 })); + expect(mem.eql(i32, @as([4]i32, -v), [4]i32{ -10, -20, -30, -40 })); } }; S.doTheTest(); @@ -68,10 +68,10 @@ test "vector float operators" { fn doTheTest() void { var v: @Vector(4, f32) = [4]f32{ 10, 20, 30, 40 }; var x: @Vector(4, f32) = [4]f32{ 1, 2, 3, 4 }; - expect(mem.eql(f32, ([4]f32)(v + x), [4]f32{ 11, 22, 33, 44 })); - expect(mem.eql(f32, ([4]f32)(v - x), [4]f32{ 9, 18, 27, 36 })); - expect(mem.eql(f32, ([4]f32)(v * x), [4]f32{ 10, 40, 90, 160 })); - expect(mem.eql(f32, ([4]f32)(-x), [4]f32{ -1, -2, -3, -4 })); + expect(mem.eql(f32, @as([4]f32, v + x), [4]f32{ 11, 22, 33, 44 })); + expect(mem.eql(f32, @as([4]f32, v - x), [4]f32{ 9, 18, 27, 36 })); + expect(mem.eql(f32, @as([4]f32, v * x), [4]f32{ 10, 40, 90, 160 })); + expect(mem.eql(f32, @as([4]f32, -x), [4]f32{ -1, -2, -3, -4 })); } }; S.doTheTest(); @@ -83,9 +83,9 @@ test "vector bit operators" { fn doTheTest() void { var v: @Vector(4, u8) = [4]u8{ 0b10101010, 0b10101010, 0b10101010, 0b10101010 }; var x: @Vector(4, u8) = [4]u8{ 0b11110000, 0b00001111, 0b10101010, 0b01010101 }; - expect(mem.eql(u8, ([4]u8)(v ^ x), [4]u8{ 0b01011010, 0b10100101, 0b00000000, 0b11111111 })); - expect(mem.eql(u8, ([4]u8)(v | x), [4]u8{ 0b11111010, 0b10101111, 0b10101010, 0b11111111 })); - expect(mem.eql(u8, ([4]u8)(v & x), [4]u8{ 0b10100000, 0b00001010, 0b10101010, 0b00000000 })); + expect(mem.eql(u8, @as([4]u8, v ^ x), [4]u8{ 0b01011010, 0b10100101, 0b00000000, 0b11111111 })); + expect(mem.eql(u8, @as([4]u8, v | x), [4]u8{ 0b11111010, 0b10101111, 0b10101010, 0b11111111 })); + expect(mem.eql(u8, @as([4]u8, v & x), [4]u8{ 0b10100000, 0b00001010, 0b10101010, 0b00000000 })); } }; S.doTheTest(); @@ -120,22 +120,22 @@ test "vector casts of sizes not divisable by 8" { { var v: @Vector(4, u3) = [4]u3{ 5, 2, 3, 0 }; var x: [4]u3 = v; - expect(mem.eql(u3, x, ([4]u3)(v))); + expect(mem.eql(u3, x, @as([4]u3, v))); } { var v: @Vector(4, u2) = [4]u2{ 1, 2, 3, 0 }; var x: [4]u2 = v; - expect(mem.eql(u2, x, ([4]u2)(v))); + expect(mem.eql(u2, x, @as([4]u2, v))); } { var v: @Vector(4, u1) = [4]u1{ 1, 0, 1, 0 }; var x: [4]u1 = v; - expect(mem.eql(u1, x, ([4]u1)(v))); + expect(mem.eql(u1, x, @as([4]u1, v))); } { var v: @Vector(4, bool) = [4]bool{ false, false, true, false }; var x: [4]bool = v; - expect(mem.eql(bool, x, ([4]bool)(v))); + expect(mem.eql(bool, x, @as([4]bool, v))); } } }; diff --git a/test/stage1/behavior/void.zig b/test/stage1/behavior/void.zig @@ -26,7 +26,7 @@ test "iterate over a void slice" { } fn times(n: usize) []const void { - return ([*]void)(undefined)[0..n]; + return @as([*]void, undefined)[0..n]; } test "void optional" { diff --git a/test/stage1/behavior/while.zig b/test/stage1/behavior/while.zig @@ -137,7 +137,7 @@ test "while on optional with else result follow else prong" { const result = while (returnNull()) |value| { break value; } else - i32(2); + @as(i32, 2); expect(result == 2); } @@ -145,7 +145,7 @@ test "while on optional with else result follow break prong" { const result = while (returnOptional(10)) |value| { break value; } else - i32(2); + @as(i32, 2); expect(result == 10); } @@ -153,7 +153,7 @@ test "while on error union with else result follow else prong" { const result = while (returnError()) |value| { break value; } else |err| - i32(2); + @as(i32, 2); expect(result == 2); } @@ -161,23 +161,23 @@ test "while on error union with else result follow break prong" { const result = while (returnSuccess(10)) |value| { break value; } else |err| - i32(2); + @as(i32, 2); expect(result == 10); } test "while on bool with else result follow else prong" { const result = while (returnFalse()) { - break i32(10); + break @as(i32, 10); } else - i32(2); + @as(i32, 2); expect(result == 2); } test "while on bool with else result follow break prong" { const result = while (returnTrue()) { - break i32(10); + break @as(i32, 10); } else - i32(2); + @as(i32, 2); expect(result == 10); } diff --git a/test/standalone/brace_expansion/main.zig b/test/standalone/brace_expansion/main.zig @@ -179,8 +179,8 @@ fn expandNode(node: Node, output: *ArrayList(Buffer)) ExpandNodeError!void { } pub fn main() !void { - var stdin_file = try io.getStdIn(); - var stdout_file = try io.getStdOut(); + const stdin_file = io.getStdIn(); + const stdout_file = io.getStdOut(); var arena = std.heap.ArenaAllocator.init(std.heap.direct_allocator); defer arena.deinit(); diff --git a/test/standalone/cat/main.zig b/test/standalone/cat/main.zig @@ -10,30 +10,28 @@ pub fn main() !void { var args_it = process.args(); const exe = try unwrapArg(args_it.next(allocator).?); var catted_anything = false; - var stdout_file = try io.getStdOut(); + const stdout_file = io.getStdOut(); while (args_it.next(allocator)) |arg_or_err| { const arg = try unwrapArg(arg_or_err); if (mem.eql(u8, arg, "-")) { catted_anything = true; - var stdin_file = try io.getStdIn(); - try cat_file(&stdout_file, &stdin_file); + try cat_file(stdout_file, io.getStdIn()); } else if (arg[0] == '-') { return usage(exe); } else { - var file = File.openRead(arg) catch |err| { + const file = File.openRead(arg) catch |err| { warn("Unable to open file: {}\n", @errorName(err)); return err; }; defer file.close(); catted_anything = true; - try cat_file(&stdout_file, &file); + try cat_file(stdout_file, file); } } if (!catted_anything) { - var stdin_file = try io.getStdIn(); - try cat_file(&stdout_file, &stdin_file); + try cat_file(stdout_file, io.getStdIn()); } } @@ -42,7 +40,7 @@ fn usage(exe: []const u8) !void { return error.Invalid; } -fn cat_file(stdout: *File, file: *File) !void { +fn cat_file(stdout: File, file: File) !void { var buf: [1024 * 4]u8 = undefined; while (true) { diff --git a/test/standalone/guess_number/main.zig b/test/standalone/guess_number/main.zig @@ -4,8 +4,7 @@ const io = std.io; const fmt = std.fmt; pub fn main() !void { - var stdout_file = try io.getStdOut(); - const stdout = &stdout_file.outStream().stream; + const stdout = &io.getStdOut().outStream().stream; try stdout.print("Welcome to the Guess Number Game in Zig.\n"); diff --git a/test/standalone/hello_world/hello.zig b/test/standalone/hello_world/hello.zig @@ -1,8 +1,7 @@ const std = @import("std"); pub fn main() !void { - // If this program is run without stdout attached, exit with an error. - const stdout_file = try std.io.getStdOut(); + const stdout_file = std.io.getStdOut(); // If this program encounters pipe failure when printing to stdout, exit // with an error. try stdout_file.write("Hello, world!\n"); diff --git a/test/tests.zig b/test/tests.zig @@ -411,7 +411,7 @@ pub fn addPkgTests( const ArchTag = @TagType(builtin.Arch); if (test_target.disable_native and test_target.target.getOs() == builtin.os and - ArchTag(test_target.target.getArch()) == ArchTag(builtin.arch)) + @as(ArchTag,test_target.target.getArch()) == @as(ArchTag,builtin.arch)) { continue; } @@ -429,7 +429,7 @@ pub fn addPkgTests( "bare"; const triple_prefix = if (test_target.target == .Native) - ([]const u8)("native") + @as([]const u8,"native") else test_target.target.zigTripleNoSubArch(b.allocator) catch unreachable; diff --git a/test/translate_c.zig b/test/translate_c.zig @@ -28,9 +28,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { , \\pub fn foo() void { \\ var a: c_int = undefined; - \\ var b: u8 = u8(123); + \\ var b: u8 = @as(u8, 123); \\ const c: c_int = undefined; - \\ const d: c_uint = c_uint(440); + \\ const d: c_uint = @as(c_uint, 440); \\} ); @@ -144,7 +144,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub extern fn foo() void; \\pub fn bar() void { \\ var func_ptr: ?*c_void = @ptrCast(?*c_void, foo); - \\ var typed_func_ptr: ?extern fn () void = @intToPtr(?extern fn () void, c_ulong(@ptrToInt(func_ptr))); + \\ var typed_func_ptr: ?extern fn () void = @intToPtr(?extern fn () void, @as(c_ulong, @ptrToInt(func_ptr))); \\} ); @@ -561,43 +561,43 @@ pub fn addCases(cases: *tests.TranslateCContext) void { cases.add("u integer suffix after hex literal", \\#define SDL_INIT_VIDEO 0x00000020u /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ , - \\pub const SDL_INIT_VIDEO = c_uint(32); + \\pub const SDL_INIT_VIDEO = @as(c_uint, 32); ); cases.add("l integer suffix after hex literal", \\#define SDL_INIT_VIDEO 0x00000020l /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ , - \\pub const SDL_INIT_VIDEO = c_long(32); + \\pub const SDL_INIT_VIDEO = @as(c_long, 32); ); cases.add("ul integer suffix after hex literal", \\#define SDL_INIT_VIDEO 0x00000020ul /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ , - \\pub const SDL_INIT_VIDEO = c_ulong(32); + \\pub const SDL_INIT_VIDEO = @as(c_ulong, 32); ); cases.add("lu integer suffix after hex literal", \\#define SDL_INIT_VIDEO 0x00000020lu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ , - \\pub const SDL_INIT_VIDEO = c_ulong(32); + \\pub const SDL_INIT_VIDEO = @as(c_ulong, 32); ); cases.add("ll integer suffix after hex literal", \\#define SDL_INIT_VIDEO 0x00000020ll /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ , - \\pub const SDL_INIT_VIDEO = c_longlong(32); + \\pub const SDL_INIT_VIDEO = @as(c_longlong, 32); ); cases.add("ull integer suffix after hex literal", \\#define SDL_INIT_VIDEO 0x00000020ull /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ , - \\pub const SDL_INIT_VIDEO = c_ulonglong(32); + \\pub const SDL_INIT_VIDEO = @as(c_ulonglong, 32); ); cases.add("llu integer suffix after hex literal", \\#define SDL_INIT_VIDEO 0x00000020llu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ , - \\pub const SDL_INIT_VIDEO = c_ulonglong(32); + \\pub const SDL_INIT_VIDEO = @as(c_ulonglong, 32); ); cases.add("zig keywords in C code", @@ -676,8 +676,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub export fn log2(_arg_a: c_uint) c_int { \\ var a = _arg_a; \\ var i: c_int = 0; - \\ while (a > c_uint(0)) { - \\ a >>= @import("std").math.Log2Int(c_uint)(1); + \\ while (a > @as(c_uint, 0)) { + \\ a >>= @as(@import("std").math.Log2Int(c_uint), 1); \\ } \\ return i; \\} @@ -848,8 +848,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub export fn log2(_arg_a: u32) c_int { \\ var a = _arg_a; \\ var i: c_int = 0; - \\ while (a > c_uint(0)) { - \\ a >>= u5(1); + \\ while (a > @as(c_uint, 0)) { + \\ a >>= @as(u5, 1); \\ } \\ return i; \\} @@ -937,7 +937,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} , \\pub export fn float_to_int(a: f32) c_int { - \\ return c_int(a); + \\ return @as(c_int, a); \\} ); @@ -1027,7 +1027,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} , \\pub export fn foo() c_int { - \\ return (1 << @import("std").math.Log2Int(c_int)(2)) >> @import("std").math.Log2Int(c_int)(1); + \\ return (1 << @as(@import("std").math.Log2Int(c_int), 2)) >> @as(@import("std").math.Log2Int(c_int), 1); \\} ); @@ -1076,14 +1076,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ _ref.* = (_ref.* ^ 1); \\ break :x _ref.*; \\ }); - \\ a >>= @import("std").math.Log2Int(c_int)((x: { + \\ a >>= @as(@import("std").math.Log2Int(c_int), (x: { \\ const _ref = &a; - \\ _ref.* = (_ref.* >> @import("std").math.Log2Int(c_int)(1)); + \\ _ref.* = (_ref.* >> @as(@import("std").math.Log2Int(c_int), 1)); \\ break :x _ref.*; \\ })); - \\ a <<= @import("std").math.Log2Int(c_int)((x: { + \\ a <<= @as(@import("std").math.Log2Int(c_int), (x: { \\ const _ref = &a; - \\ _ref.* = (_ref.* << @import("std").math.Log2Int(c_int)(1)); + \\ _ref.* = (_ref.* << @as(@import("std").math.Log2Int(c_int), 1)); \\ break :x _ref.*; \\ })); \\} @@ -1103,45 +1103,45 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} , \\pub export fn foo() void { - \\ var a: c_uint = c_uint(0); + \\ var a: c_uint = @as(c_uint, 0); \\ a +%= (x: { \\ const _ref = &a; - \\ _ref.* = (_ref.* +% c_uint(1)); + \\ _ref.* = (_ref.* +% @as(c_uint, 1)); \\ break :x _ref.*; \\ }); \\ a -%= (x: { \\ const _ref = &a; - \\ _ref.* = (_ref.* -% c_uint(1)); + \\ _ref.* = (_ref.* -% @as(c_uint, 1)); \\ break :x _ref.*; \\ }); \\ a *%= (x: { \\ const _ref = &a; - \\ _ref.* = (_ref.* *% c_uint(1)); + \\ _ref.* = (_ref.* *% @as(c_uint, 1)); \\ break :x _ref.*; \\ }); \\ a &= (x: { \\ const _ref = &a; - \\ _ref.* = (_ref.* & c_uint(1)); + \\ _ref.* = (_ref.* & @as(c_uint, 1)); \\ break :x _ref.*; \\ }); \\ a |= (x: { \\ const _ref = &a; - \\ _ref.* = (_ref.* | c_uint(1)); + \\ _ref.* = (_ref.* | @as(c_uint, 1)); \\ break :x _ref.*; \\ }); \\ a ^= (x: { \\ const _ref = &a; - \\ _ref.* = (_ref.* ^ c_uint(1)); + \\ _ref.* = (_ref.* ^ @as(c_uint, 1)); \\ break :x _ref.*; \\ }); - \\ a >>= @import("std").math.Log2Int(c_uint)((x: { + \\ a >>= @as(@import("std").math.Log2Int(c_uint), (x: { \\ const _ref = &a; - \\ _ref.* = (_ref.* >> @import("std").math.Log2Int(c_uint)(1)); + \\ _ref.* = (_ref.* >> @as(@import("std").math.Log2Int(c_uint), 1)); \\ break :x _ref.*; \\ })); - \\ a <<= @import("std").math.Log2Int(c_uint)((x: { + \\ a <<= @as(@import("std").math.Log2Int(c_uint), (x: { \\ const _ref = &a; - \\ _ref.* = (_ref.* << @import("std").math.Log2Int(c_uint)(1)); + \\ _ref.* = (_ref.* << @as(@import("std").math.Log2Int(c_uint), 1)); \\ break :x _ref.*; \\ })); \\} @@ -1174,7 +1174,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { , \\pub export fn foo() void { \\ var i: c_int = 0; - \\ var u: c_uint = c_uint(0); + \\ var u: c_uint = @as(c_uint, 0); \\ i += 1; \\ i -= 1; \\ u +%= 1; @@ -1222,7 +1222,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { , \\pub export fn foo() void { \\ var i: c_int = 0; - \\ var u: c_uint = c_uint(0); + \\ var u: c_uint = @as(c_uint, 0); \\ i += 1; \\ i -= 1; \\ u +%= 1; @@ -1539,7 +1539,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { cases.add("macro pointer cast", \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE) , - \\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else ([*c]NRF_GPIO_Type)(NRF_GPIO_BASE); + \\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE); ); cases.add("if on non-bool", @@ -1564,7 +1564,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ if (a != 0) return 0; \\ if (b != 0) return 1; \\ if (c != null) return 2; - \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3; + \\ if (d != @bitCast(enum_SomeEnum, @as(@TagType(enum_SomeEnum), 0))) return 3; \\ return 4; \\} ); @@ -1646,49 +1646,49 @@ pub fn addCases(cases: *tests.TranslateCContext) void { cases.addC( "u integer suffix after 0 (zero) in macro definition", "#define ZERO 0U", - "pub const ZERO = c_uint(0);", + "pub const ZERO = @as(c_uint, 0);", ); cases.addC( "l integer suffix after 0 (zero) in macro definition", "#define ZERO 0L", - "pub const ZERO = c_long(0);", + "pub const ZERO = @as(c_long, 0);", ); cases.addC( "ul integer suffix after 0 (zero) in macro definition", "#define ZERO 0UL", - "pub const ZERO = c_ulong(0);", + "pub const ZERO = @as(c_ulong, 0);", ); cases.addC( "lu integer suffix after 0 (zero) in macro definition", "#define ZERO 0LU", - "pub const ZERO = c_ulong(0);", + "pub const ZERO = @as(c_ulong, 0);", ); cases.addC( "ll integer suffix after 0 (zero) in macro definition", "#define ZERO 0LL", - "pub const ZERO = c_longlong(0);", + "pub const ZERO = @as(c_longlong, 0);", ); cases.addC( "ull integer suffix after 0 (zero) in macro definition", "#define ZERO 0ULL", - "pub const ZERO = c_ulonglong(0);", + "pub const ZERO = @as(c_ulonglong, 0);", ); cases.addC( "llu integer suffix after 0 (zero) in macro definition", "#define ZERO 0LLU", - "pub const ZERO = c_ulonglong(0);", + "pub const ZERO = @as(c_ulonglong, 0);", ); cases.addC( "bitwise not on u-suffixed 0 (zero) in macro definition", "#define NOT_ZERO (~0U)", - "pub const NOT_ZERO = ~c_uint(0);", + "pub const NOT_ZERO = ~@as(c_uint, 0);", ); cases.addC("implicit casts", @@ -1733,9 +1733,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ fn_int(1094861636); \\ fn_f32(@intToFloat(f32, 3)); \\ fn_f64(@intToFloat(f64, 3)); - \\ fn_char(u8('3')); - \\ fn_char(u8('\x01')); - \\ fn_char(u8(0)); + \\ fn_char(@as(u8, '3')); + \\ fn_char(@as(u8, '\x01')); + \\ fn_char(@as(u8, 0)); \\ fn_f32(3.000000); \\ fn_f64(3.000000); \\ fn_bool(true); @@ -1798,22 +1798,31 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ , \\pub export fn escapes() [*c]const u8 { - \\ var a: u8 = u8('\''); - \\ var b: u8 = u8('\\'); - \\ var c: u8 = u8('\x07'); - \\ var d: u8 = u8('\x08'); - \\ var e: u8 = u8('\x0c'); - \\ var f: u8 = u8('\n'); - \\ var g: u8 = u8('\r'); - \\ var h: u8 = u8('\t'); - \\ var i: u8 = u8('\x0b'); - \\ var j: u8 = u8('\x00'); - \\ var k: u8 = u8('\"'); + \\ var a: u8 = @as(u8, '\''); + \\ var b: u8 = @as(u8, '\\'); + \\ var c: u8 = @as(u8, '\x07'); + \\ var d: u8 = @as(u8, '\x08'); + \\ var e: u8 = @as(u8, '\x0c'); + \\ var f: u8 = @as(u8, '\n'); + \\ var g: u8 = @as(u8, '\r'); + \\ var h: u8 = @as(u8, '\t'); + \\ var i: u8 = @as(u8, '\x0b'); + \\ var j: u8 = @as(u8, '\x00'); + \\ var k: u8 = @as(u8, '\"'); \\ return c"\'\\\x07\x08\x0c\n\r\t\x0b\x00\""; \\} \\ ); + if (builtin.os != builtin.Os.windows) { + // sysv_abi not currently supported on windows + cases.add("Macro qualified functions", + \\void __attribute__((sysv_abi)) foo(void); + , + \\pub extern fn foo() void; + ); + } + /////////////// Cases for only stage1 because stage2 behavior is better //////////////// cases.addC("Parameterless function prototypes", \\void foo() {}