authorgravatar for BenoitJGirard@users.noreply.github.comBenoitJGirard <BenoitJGirard@users.noreply.github.com> 2019-02-17 14:38:55-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-02-17 14:38:55-05:00
log6daa041932ae5ab03eed953dacf3ca506078390c
tree0f51f6c2ff84dde51b61bba6799e5c5abccf91b4
parentf0ec308e26ff957c7fbb50ccc69d3d549c42c4da
parent8d2a902945ef97f28152c3d5a68bb974809c8539
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #2 from ziglang/master

Refreshing fork.

426 files changed, 25085 insertions(+), 16300 deletions(-)

.builds/freebsd.yml created+43
...@@ -0,0 +1,43 @@
1image: freebsd/latest
2packages:
3 - cmake
4 - ninja
5 - llvm70
6sources:
7 - https://github.com/ziglang/zig
8tasks:
9 - build: |
10 cd zig && mkdir build && cd build
11 cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release
12 ninja install
13 - test: |
14 cd zig/build
15 bin/zig test ../test/stage1/behavior.zig
16 bin/zig test ../std/special/compiler_rt/index.zig
17
18 bin/zig test ../test/stage1/behavior.zig --library c
19 bin/zig test ../std/special/compiler_rt/index.zig --library c
20
21 bin/zig test ../test/stage1/behavior.zig --release-fast
22 bin/zig test ../std/special/compiler_rt/index.zig --release-fast
23
24 bin/zig test ../test/stage1/behavior.zig --release-fast --library c
25 bin/zig test ../std/special/compiler_rt/index.zig --release-fast --library c
26
27 bin/zig test ../test/stage1/behavior.zig --release-small --library c
28 bin/zig test ../std/special/compiler_rt/index.zig --release-small --library c
29
30 bin/zig test ../test/stage1/behavior.zig --release-small
31 bin/zig test ../std/special/compiler_rt/index.zig --release-small
32
33 bin/zig test ../test/stage1/behavior.zig --release-safe
34 bin/zig test ../std/special/compiler_rt/index.zig --release-safe
35
36 bin/zig test ../test/stage1/behavior.zig --release-safe --library c
37 bin/zig test ../std/special/compiler_rt/index.zig --release-safe --library c
38 # TODO enable all tests
39 #bin/zig build --build-file ../build.zig test
40 # TODO integrate with the download page updater and make a
41 # static build available to download for FreeBSD.
42 # This will require setting up a cache of LLVM/Clang built
43 # statically.
CMakeLists.txt+27-7
...@@ -429,6 +429,7 @@ set(BLAKE_SOURCES...@@ -429,6 +429,7 @@ set(BLAKE_SOURCES
429)429)
430set(ZIG_CPP_SOURCES430set(ZIG_CPP_SOURCES
431 "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"431 "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"
432 "${CMAKE_SOURCE_DIR}/src/zig_clang.cpp"
432 "${CMAKE_SOURCE_DIR}/src/windows_sdk.cpp"433 "${CMAKE_SOURCE_DIR}/src/windows_sdk.cpp"
433)434)
434435
...@@ -454,10 +455,10 @@ set(ZIG_STD_FILES...@@ -454,10 +455,10 @@ set(ZIG_STD_FILES
454 "crypto/hmac.zig"455 "crypto/hmac.zig"
455 "crypto/index.zig"456 "crypto/index.zig"
456 "crypto/md5.zig"457 "crypto/md5.zig"
458 "crypto/poly1305.zig"
457 "crypto/sha1.zig"459 "crypto/sha1.zig"
458 "crypto/sha2.zig"460 "crypto/sha2.zig"
459 "crypto/sha3.zig"461 "crypto/sha3.zig"
460 "crypto/poly1305.zig"
461 "crypto/x25519.zig"462 "crypto/x25519.zig"
462 "cstr.zig"463 "cstr.zig"
463 "debug/failing_allocator.zig"464 "debug/failing_allocator.zig"
...@@ -482,6 +483,7 @@ set(ZIG_STD_FILES...@@ -482,6 +483,7 @@ set(ZIG_STD_FILES
482 "fmt/errol/index.zig"483 "fmt/errol/index.zig"
483 "fmt/errol/lookup.zig"484 "fmt/errol/lookup.zig"
484 "fmt/index.zig"485 "fmt/index.zig"
486 "fmt/parse_float.zig"
485 "hash/adler.zig"487 "hash/adler.zig"
486 "hash/crc.zig"488 "hash/crc.zig"
487 "hash/fnv.zig"489 "hash/fnv.zig"
...@@ -566,9 +568,9 @@ set(ZIG_STD_FILES...@@ -566,9 +568,9 @@ set(ZIG_STD_FILES
566 "math/tan.zig"568 "math/tan.zig"
567 "math/tanh.zig"569 "math/tanh.zig"
568 "math/trunc.zig"570 "math/trunc.zig"
571 "mem.zig"
569 "meta/index.zig"572 "meta/index.zig"
570 "meta/trait.zig"573 "meta/trait.zig"
571 "mem.zig"
572 "mutex.zig"574 "mutex.zig"
573 "net.zig"575 "net.zig"
574 "os/child_process.zig"576 "os/child_process.zig"
...@@ -576,20 +578,19 @@ set(ZIG_STD_FILES...@@ -576,20 +578,19 @@ set(ZIG_STD_FILES
576 "os/darwin/errno.zig"578 "os/darwin/errno.zig"
577 "os/epoch.zig"579 "os/epoch.zig"
578 "os/file.zig"580 "os/file.zig"
581 "os/freebsd/errno.zig"
582 "os/freebsd/index.zig"
579 "os/get_app_data_dir.zig"583 "os/get_app_data_dir.zig"
580 "os/get_user_id.zig"584 "os/get_user_id.zig"
581 "os/index.zig"585 "os/index.zig"
586 "os/linux/arm64.zig"
582 "os/linux/errno.zig"587 "os/linux/errno.zig"
583 "os/linux/index.zig"588 "os/linux/index.zig"
584 "os/linux/vdso.zig"589 "os/linux/vdso.zig"
585 "os/linux/x86_64.zig"590 "os/linux/x86_64.zig"
586 "os/linux/arm64.zig"
587 "os/freebsd/errno.zig"
588 "os/freebsd/index.zig"
589 "os/freebsd/syscall.zig"
590 "os/freebsd/x86_64.zig"
591 "os/path.zig"591 "os/path.zig"
592 "os/time.zig"592 "os/time.zig"
593 "os/uefi.zig"
593 "os/windows/advapi32.zig"594 "os/windows/advapi32.zig"
594 "os/windows/error.zig"595 "os/windows/error.zig"
595 "os/windows/index.zig"596 "os/windows/index.zig"
...@@ -597,6 +598,7 @@ set(ZIG_STD_FILES...@@ -597,6 +598,7 @@ set(ZIG_STD_FILES
597 "os/windows/ntdll.zig"598 "os/windows/ntdll.zig"
598 "os/windows/ole32.zig"599 "os/windows/ole32.zig"
599 "os/windows/shell32.zig"600 "os/windows/shell32.zig"
601 "os/windows/tls.zig"
600 "os/windows/util.zig"602 "os/windows/util.zig"
601 "os/zen.zig"603 "os/zen.zig"
602 "pdb.zig"604 "pdb.zig"
...@@ -608,11 +610,22 @@ set(ZIG_STD_FILES...@@ -608,11 +610,22 @@ set(ZIG_STD_FILES
608 "special/bootstrap_lib.zig"610 "special/bootstrap_lib.zig"
609 "special/build_runner.zig"611 "special/build_runner.zig"
610 "special/builtin.zig"612 "special/builtin.zig"
613 "special/compiler_rt/addXf3.zig"
611 "special/compiler_rt/aulldiv.zig"614 "special/compiler_rt/aulldiv.zig"
612 "special/compiler_rt/aullrem.zig"615 "special/compiler_rt/aullrem.zig"
613 "special/compiler_rt/comparetf2.zig"616 "special/compiler_rt/comparetf2.zig"
614 "special/compiler_rt/divti3.zig"617 "special/compiler_rt/divti3.zig"
615 "special/compiler_rt/extendXfYf2.zig"618 "special/compiler_rt/extendXfYf2.zig"
619 "special/compiler_rt/fixdfdi.zig"
620 "special/compiler_rt/fixdfsi.zig"
621 "special/compiler_rt/fixdfti.zig"
622 "special/compiler_rt/fixint.zig"
623 "special/compiler_rt/fixsfdi.zig"
624 "special/compiler_rt/fixsfsi.zig"
625 "special/compiler_rt/fixsfti.zig"
626 "special/compiler_rt/fixtfdi.zig"
627 "special/compiler_rt/fixtfsi.zig"
628 "special/compiler_rt/fixtfti.zig"
616 "special/compiler_rt/fixuint.zig"629 "special/compiler_rt/fixuint.zig"
617 "special/compiler_rt/fixunsdfdi.zig"630 "special/compiler_rt/fixunsdfdi.zig"
618 "special/compiler_rt/fixunsdfsi.zig"631 "special/compiler_rt/fixunsdfsi.zig"
...@@ -640,6 +653,7 @@ set(ZIG_STD_FILES...@@ -640,6 +653,7 @@ set(ZIG_STD_FILES
640 "special/compiler_rt/udivmodti4.zig"653 "special/compiler_rt/udivmodti4.zig"
641 "special/compiler_rt/udivti3.zig"654 "special/compiler_rt/udivti3.zig"
642 "special/compiler_rt/umodti3.zig"655 "special/compiler_rt/umodti3.zig"
656 "special/fmt_runner.zig"
643 "special/init-exe/build.zig"657 "special/init-exe/build.zig"
644 "special/init-exe/src/main.zig"658 "special/init-exe/src/main.zig"
645 "special/init-lib/build.zig"659 "special/init-lib/build.zig"
...@@ -647,6 +661,8 @@ set(ZIG_STD_FILES...@@ -647,6 +661,8 @@ set(ZIG_STD_FILES
647 "special/panic.zig"661 "special/panic.zig"
648 "special/test_runner.zig"662 "special/test_runner.zig"
649 "spinlock.zig"663 "spinlock.zig"
664 "statically_initialized_mutex.zig"
665 "testing.zig"
650 "unicode.zig"666 "unicode.zig"
651 "zig/ast.zig"667 "zig/ast.zig"
652 "zig/index.zig"668 "zig/index.zig"
...@@ -891,3 +907,7 @@ foreach(file ${ZIG_STD_FILES})...@@ -891,3 +907,7 @@ foreach(file ${ZIG_STD_FILES})
891 get_filename_component(file_dir "${ZIG_STD_DEST}/${file}" DIRECTORY)907 get_filename_component(file_dir "${ZIG_STD_DEST}/${file}" DIRECTORY)
892 install(FILES "${CMAKE_SOURCE_DIR}/std/${file}" DESTINATION "${file_dir}")908 install(FILES "${CMAKE_SOURCE_DIR}/std/${file}" DESTINATION "${file_dir}")
893endforeach()909endforeach()
910
911install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/arg.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/")
912install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/main.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/")
913install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/errmsg.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/")
README.md+30-24
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3A programming language designed for robustness, optimality, and3A programming language designed for robustness, optimality, and
4clarity.4clarity.
55
6[ziglang.org](https://ziglang.org)6[Download & Documentation](https://ziglang.org/download/)
77
8## Feature Highlights8## Feature Highlights
99
...@@ -84,29 +84,32 @@ clarity....@@ -84,29 +84,32 @@ clarity.
84 * LLVM may have the target as an experimental target, which means that you84 * LLVM may have the target as an experimental target, which means that you
85 need to use Zig-provided binaries for the target to be available, or85 need to use Zig-provided binaries for the target to be available, or
86 build LLVM from source with special configure flags.86 build LLVM from source with special configure flags.
87 * This target may be considered deprecated by an official party,
88 [such as macosx/i386](https://support.apple.com/en-us/HT208436) in which
89 case this target will remain forever stuck in Tier 4.
8790
88#### Support Table91#### Support Table
8992
90| | freestanding | linux | macosx | windows | freebsd | other |93| | freestanding | linux | macosx | windows | freebsd | UEFI | other |
91|--------|--------------|--------|--------|---------|---------|--------|94|--------|--------------|--------|--------|---------|---------|--------|--------|
92|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 3 |95|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 2 | Tier 3 |
93|i386 | Tier 2 | Tier 2 | Tier 2 | Tier 2 | Tier 3 | Tier 3 |96|i386 | Tier 2 | Tier 2 | Tier 4 | Tier 2 | Tier 3 | Tier 3 | Tier 3 |
94|arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |97|arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
95|arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |98|arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
96|bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |99|bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
97|hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |100|hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
98|mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |101|mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
99|powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |102|powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
100|r600 | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |103|r600 | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
101|amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |104|amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
102|sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |105|sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
103|s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |106|s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
104|spir | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |107|spir | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
105|lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |108|lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
106|wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A |109|wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A |
107|wasm64 | Tier 4 | N/A | N/A | N/A | N/A | N/A |110|wasm64 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A |
108|riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 |111|riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 |
109|riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 |112|riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 |
110113
111## Community114## Community
112115
...@@ -171,7 +174,8 @@ See https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows...@@ -171,7 +174,8 @@ See https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows
171*Note: Stage 2 compiler is not complete. Beta users of Zig should use the174*Note: Stage 2 compiler is not complete. Beta users of Zig should use the
172Stage 1 compiler for now.*175Stage 1 compiler for now.*
173176
174Dependencies are the same as Stage 1, except now you have a working zig compiler.177Dependencies are the same as Stage 1, except now you can use stage 1 to compile
178Zig code.
175179
176```180```
177bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install181bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install
...@@ -183,11 +187,13 @@ binary....@@ -183,11 +187,13 @@ binary.
183187
184### Stage 3: Rebuild Self-Hosted Zig Using the Self-Hosted Compiler188### Stage 3: Rebuild Self-Hosted Zig Using the Self-Hosted Compiler
185189
186This is the actual compiler binary that we will install to the system.
187
188*Note: Stage 2 compiler is not yet able to build Stage 3. Building Stage 3 is190*Note: Stage 2 compiler is not yet able to build Stage 3. Building Stage 3 is
189not yet supported.*191not yet supported.*
190192
193Once the self-hosted compiler can build itself, this will be the actual
194compiler binary that we will install to the system. Until then, users should
195use stage 1.
196
191#### Debug / Development Build197#### Debug / Development Build
192198
193```199```
build.zig+40-19
...@@ -16,7 +16,10 @@ pub fn build(b: *Builder) !void {...@@ -16,7 +16,10 @@ pub fn build(b: *Builder) !void {
16 var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");16 var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
1717
18 const rel_zig_exe = try os.path.relative(b.allocator, b.build_root, b.zig_exe);18 const rel_zig_exe = try os.path.relative(b.allocator, b.build_root, b.zig_exe);
19 const langref_out_path = os.path.join(b.allocator, b.cache_root, "langref.html") catch unreachable;19 const langref_out_path = os.path.join(
20 b.allocator,
21 [][]const u8{ b.cache_root, "langref.html" },
22 ) catch unreachable;
20 var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{23 var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{
21 docgen_exe.getOutputPath(),24 docgen_exe.getOutputPath(),
22 rel_zig_exe,25 rel_zig_exe,
...@@ -104,7 +107,7 @@ pub fn build(b: *Builder) !void {...@@ -104,7 +107,7 @@ pub fn build(b: *Builder) !void {
104 }107 }
105 const modes = chosen_modes[0..chosen_mode_index];108 const modes = chosen_modes[0..chosen_mode_index];
106109
107 test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", modes));110 test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/behavior.zig", "behavior", "Run the behavior tests", modes));
108111
109 test_step.dependOn(tests.addPkgTests(b, test_filter, "std/index.zig", "std", "Run the standard library tests", modes));112 test_step.dependOn(tests.addPkgTests(b, test_filter, "std/index.zig", "std", "Run the standard library tests", modes));
110113
...@@ -125,13 +128,19 @@ fn dependOnLib(b: *Builder, lib_exe_obj: var, dep: LibraryDep) void {...@@ -125,13 +128,19 @@ fn dependOnLib(b: *Builder, lib_exe_obj: var, dep: LibraryDep) void {
125 for (dep.libdirs.toSliceConst()) |lib_dir| {128 for (dep.libdirs.toSliceConst()) |lib_dir| {
126 lib_exe_obj.addLibPath(lib_dir);129 lib_exe_obj.addLibPath(lib_dir);
127 }130 }
128 const lib_dir = os.path.join(b.allocator, dep.prefix, "lib") catch unreachable;131 const lib_dir = os.path.join(
132 b.allocator,
133 [][]const u8{ dep.prefix, "lib" },
134 ) catch unreachable;
129 for (dep.system_libs.toSliceConst()) |lib| {135 for (dep.system_libs.toSliceConst()) |lib| {
130 const static_bare_name = if (mem.eql(u8, lib, "curses"))136 const static_bare_name = if (mem.eql(u8, lib, "curses"))
131 ([]const u8)("libncurses.a")137 ([]const u8)("libncurses.a")
132 else138 else
133 b.fmt("lib{}.a", lib);139 b.fmt("lib{}.a", lib);
134 const static_lib_name = os.path.join(b.allocator, lib_dir, static_bare_name) catch unreachable;140 const static_lib_name = os.path.join(
141 b.allocator,
142 [][]const u8{ lib_dir, static_bare_name },
143 ) catch unreachable;
135 const have_static = fileExists(static_lib_name) catch unreachable;144 const have_static = fileExists(static_lib_name) catch unreachable;
136 if (have_static) {145 if (have_static) {
137 lib_exe_obj.addObjectFile(static_lib_name);146 lib_exe_obj.addObjectFile(static_lib_name);
...@@ -159,7 +168,11 @@ fn fileExists(filename: []const u8) !bool {...@@ -159,7 +168,11 @@ fn fileExists(filename: []const u8) !bool {
159168
160fn addCppLib(b: *Builder, lib_exe_obj: var, cmake_binary_dir: []const u8, lib_name: []const u8) void {169fn addCppLib(b: *Builder, lib_exe_obj: var, cmake_binary_dir: []const u8, lib_name: []const u8) void {
161 const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib";170 const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib";
162 lib_exe_obj.addObjectFile(os.path.join(b.allocator, cmake_binary_dir, "zig_cpp", b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt())) catch unreachable);171 lib_exe_obj.addObjectFile(os.path.join(b.allocator, [][]const u8{
172 cmake_binary_dir,
173 "zig_cpp",
174 b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt()),
175 }) catch unreachable);
163}176}
164177
165const LibraryDep = struct {178const LibraryDep = struct {
...@@ -189,14 +202,14 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {...@@ -189,14 +202,14 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
189 const prefix_output = try b.exec([][]const u8{ llvm_config_exe, "--prefix" });202 const prefix_output = try b.exec([][]const u8{ llvm_config_exe, "--prefix" });
190203
191 var result = LibraryDep{204 var result = LibraryDep{
192 .prefix = mem.split(prefix_output, " \r\n").next().?,205 .prefix = mem.tokenize(prefix_output, " \r\n").next().?,
193 .libs = ArrayList([]const u8).init(b.allocator),206 .libs = ArrayList([]const u8).init(b.allocator),
194 .system_libs = ArrayList([]const u8).init(b.allocator),207 .system_libs = ArrayList([]const u8).init(b.allocator),
195 .includes = ArrayList([]const u8).init(b.allocator),208 .includes = ArrayList([]const u8).init(b.allocator),
196 .libdirs = ArrayList([]const u8).init(b.allocator),209 .libdirs = ArrayList([]const u8).init(b.allocator),
197 };210 };
198 {211 {
199 var it = mem.split(libs_output, " \r\n");212 var it = mem.tokenize(libs_output, " \r\n");
200 while (it.next()) |lib_arg| {213 while (it.next()) |lib_arg| {
201 if (mem.startsWith(u8, lib_arg, "-l")) {214 if (mem.startsWith(u8, lib_arg, "-l")) {
202 try result.system_libs.append(lib_arg[2..]);215 try result.system_libs.append(lib_arg[2..]);
...@@ -210,7 +223,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {...@@ -210,7 +223,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
210 }223 }
211 }224 }
212 {225 {
213 var it = mem.split(includes_output, " \r\n");226 var it = mem.tokenize(includes_output, " \r\n");
214 while (it.next()) |include_arg| {227 while (it.next()) |include_arg| {
215 if (mem.startsWith(u8, include_arg, "-I")) {228 if (mem.startsWith(u8, include_arg, "-I")) {
216 try result.includes.append(include_arg[2..]);229 try result.includes.append(include_arg[2..]);
...@@ -220,7 +233,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {...@@ -220,7 +233,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
220 }233 }
221 }234 }
222 {235 {
223 var it = mem.split(libdir_output, " \r\n");236 var it = mem.tokenize(libdir_output, " \r\n");
224 while (it.next()) |libdir| {237 while (it.next()) |libdir| {
225 if (mem.startsWith(u8, libdir, "-L")) {238 if (mem.startsWith(u8, libdir, "-L")) {
226 try result.libdirs.append(libdir[2..]);239 try result.libdirs.append(libdir[2..]);
...@@ -233,19 +246,25 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {...@@ -233,19 +246,25 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
233}246}
234247
235pub fn installStdLib(b: *Builder, stdlib_files: []const u8) void {248pub fn installStdLib(b: *Builder, stdlib_files: []const u8) void {
236 var it = mem.split(stdlib_files, ";");249 var it = mem.tokenize(stdlib_files, ";");
237 while (it.next()) |stdlib_file| {250 while (it.next()) |stdlib_file| {
238 const src_path = os.path.join(b.allocator, "std", stdlib_file) catch unreachable;251 const src_path = os.path.join(b.allocator, [][]const u8{ "std", stdlib_file }) catch unreachable;
239 const dest_path = os.path.join(b.allocator, "lib", "zig", "std", stdlib_file) catch unreachable;252 const dest_path = os.path.join(
253 b.allocator,
254 [][]const u8{ "lib", "zig", "std", stdlib_file },
255 ) catch unreachable;
240 b.installFile(src_path, dest_path);256 b.installFile(src_path, dest_path);
241 }257 }
242}258}
243259
244pub fn installCHeaders(b: *Builder, c_header_files: []const u8) void {260pub fn installCHeaders(b: *Builder, c_header_files: []const u8) void {
245 var it = mem.split(c_header_files, ";");261 var it = mem.tokenize(c_header_files, ";");
246 while (it.next()) |c_header_file| {262 while (it.next()) |c_header_file| {
247 const src_path = os.path.join(b.allocator, "c_headers", c_header_file) catch unreachable;263 const src_path = os.path.join(b.allocator, [][]const u8{ "c_headers", c_header_file }) catch unreachable;
248 const dest_path = os.path.join(b.allocator, "lib", "zig", "include", c_header_file) catch unreachable;264 const dest_path = os.path.join(
265 b.allocator,
266 [][]const u8{ "lib", "zig", "include", c_header_file },
267 ) catch unreachable;
249 b.installFile(src_path, dest_path);268 b.installFile(src_path, dest_path);
250 }269 }
251}270}
...@@ -277,7 +296,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {...@@ -277,7 +296,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
277 addCppLib(b, exe, ctx.cmake_binary_dir, "zig_cpp");296 addCppLib(b, exe, ctx.cmake_binary_dir, "zig_cpp");
278 if (ctx.lld_include_dir.len != 0) {297 if (ctx.lld_include_dir.len != 0) {
279 exe.addIncludeDir(ctx.lld_include_dir);298 exe.addIncludeDir(ctx.lld_include_dir);
280 var it = mem.split(ctx.lld_libraries, ";");299 var it = mem.tokenize(ctx.lld_libraries, ";");
281 while (it.next()) |lib| {300 while (it.next()) |lib| {
282 exe.addObjectFile(lib);301 exe.addObjectFile(lib);
283 }302 }
...@@ -293,11 +312,13 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {...@@ -293,11 +312,13 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
293 try addCxxKnownPath(b, ctx, exe, "libstdc++.a",312 try addCxxKnownPath(b, ctx, exe, "libstdc++.a",
294 \\Unable to determine path to libstdc++.a313 \\Unable to determine path to libstdc++.a
295 \\On Fedora, install libstdc++-static and try again.314 \\On Fedora, install libstdc++-static and try again.
296 \\
297 );315 );
298316
299 exe.linkSystemLibrary("pthread");317 exe.linkSystemLibrary("pthread");
300 } else if (exe.target.isDarwin() or exe.target.isFreeBSD()) {318 } else if (exe.target.isFreeBSD()) {
319 try addCxxKnownPath(b, ctx, exe, "libc++.a", null);
320 exe.linkSystemLibrary("pthread");
321 } else if (exe.target.isDarwin()) {
301 if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) {322 if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) {
302 // Compiler is GCC.323 // Compiler is GCC.
303 try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null);324 try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null);
...@@ -332,7 +353,7 @@ fn addCxxKnownPath(...@@ -332,7 +353,7 @@ fn addCxxKnownPath(
332 ctx.cxx_compiler,353 ctx.cxx_compiler,
333 b.fmt("-print-file-name={}", objname),354 b.fmt("-print-file-name={}", objname),
334 });355 });
335 const path_unpadded = mem.split(path_padded, "\r\n").next().?;356 const path_unpadded = mem.tokenize(path_padded, "\r\n").next().?;
336 if (mem.eql(u8, path_unpadded, objname)) {357 if (mem.eql(u8, path_unpadded, objname)) {
337 if (errtxt) |msg| {358 if (errtxt) |msg| {
338 warn("{}", msg);359 warn("{}", msg);
ci/azure/windows_install+1
...@@ -3,6 +3,7 @@...@@ -3,6 +3,7 @@
3set -x3set -x
4set -e4set -e
55
6pacman -Su --needed --noconfirm
6pacman -S --needed --noconfirm wget p7zip python3-pip7pacman -S --needed --noconfirm wget p7zip python3-pip
7pip install s3cmd8pip install s3cmd
8wget -nv "https://ziglang.org/deps/llvm%2bclang-7.0.0-win64-msvc-release.tar.xz"9wget -nv "https://ziglang.org/deps/llvm%2bclang-7.0.0-win64-msvc-release.tar.xz"
cmake/Findllvm.cmake+45
...@@ -15,6 +15,51 @@ find_program(LLVM_CONFIG_EXE...@@ -15,6 +15,51 @@ find_program(LLVM_CONFIG_EXE
15 "c:/msys64/mingw64/bin"15 "c:/msys64/mingw64/bin"
16 "C:/Libraries/llvm-7.0.0/bin")16 "C:/Libraries/llvm-7.0.0/bin")
1717
18if ("${LLVM_CONFIG_EXE}" STREQUAL "LLVM_CONFIG_EXE-NOTFOUND")
19 message(FATAL_ERROR "unable to find llvm-config")
20endif()
21
22execute_process(
23 COMMAND ${LLVM_CONFIG_EXE} --version
24 OUTPUT_VARIABLE LLVM_CONFIG_VERSION
25 OUTPUT_STRIP_TRAILING_WHITESPACE)
26
27if("${LLVM_CONFIG_VERSION}" VERSION_LESS 7)
28 message(FATAL_ERROR "expected LLVM 7.x but found ${LLVM_CONFIG_VERSION}")
29endif()
30if("${LLVM_CONFIG_VERSION}" VERSION_EQUAL 8)
31 message(FATAL_ERROR "expected LLVM 7.x but found ${LLVM_CONFIG_VERSION}")
32endif()
33if("${LLVM_CONFIG_VERSION}" VERSION_GREATER 8)
34 message(FATAL_ERROR "expected LLVM 7.x but found ${LLVM_CONFIG_VERSION}")
35endif()
36
37execute_process(
38 COMMAND ${LLVM_CONFIG_EXE} --targets-built
39 OUTPUT_VARIABLE LLVM_TARGETS_BUILT_SPACES
40 OUTPUT_STRIP_TRAILING_WHITESPACE)
41string(REPLACE " " ";" LLVM_TARGETS_BUILT "${LLVM_TARGETS_BUILT_SPACES}")
42function(NEED_TARGET TARGET_NAME)
43 list (FIND LLVM_TARGETS_BUILT "${TARGET_NAME}" _index)
44 if (${_index} EQUAL -1)
45 message(FATAL_ERROR "LLVM is missing target ${TARGET_NAME}. Zig requires LLVM to be built with all default targets enabled.")
46 endif()
47endfunction(NEED_TARGET)
48NEED_TARGET("AArch64")
49NEED_TARGET("AMDGPU")
50NEED_TARGET("ARM")
51NEED_TARGET("BPF")
52NEED_TARGET("Hexagon")
53NEED_TARGET("Lanai")
54NEED_TARGET("Mips")
55NEED_TARGET("MSP430")
56NEED_TARGET("NVPTX")
57NEED_TARGET("PowerPC")
58NEED_TARGET("Sparc")
59NEED_TARGET("SystemZ")
60NEED_TARGET("X86")
61NEED_TARGET("XCore")
62
18if(NOT(CMAKE_BUILD_TYPE STREQUAL "Debug") OR ZIG_STATIC)63if(NOT(CMAKE_BUILD_TYPE STREQUAL "Debug") OR ZIG_STATIC)
19 execute_process(64 execute_process(
20 COMMAND ${LLVM_CONFIG_EXE} --libfiles --link-static65 COMMAND ${LLVM_CONFIG_EXE} --libfiles --link-static
doc/docgen.zig+24-7
...@@ -4,7 +4,7 @@ const io = std.io;...@@ -4,7 +4,7 @@ const io = std.io;
4const os = std.os;4const os = std.os;
5const warn = std.debug.warn;5const warn = std.debug.warn;
6const mem = std.mem;6const mem = std.mem;
7const assert = std.debug.assert;7const testing = std.testing;
88
9const max_doc_file_size = 10 * 1024 * 1024;9const max_doc_file_size = 10 * 1024 * 1024;
1010
...@@ -620,7 +620,7 @@ const TermState = enum {...@@ -620,7 +620,7 @@ const TermState = enum {
620test "term color" {620test "term color" {
621 const input_bytes = "A\x1b[32;1mgreen\x1b[0mB";621 const input_bytes = "A\x1b[32;1mgreen\x1b[0mB";
622 const result = try termColor(std.debug.global_allocator, input_bytes);622 const result = try termColor(std.debug.global_allocator, input_bytes);
623 assert(mem.eql(u8, result, "A<span class=\"t32\">green</span>B"));623 testing.expectEqualSlices(u8, "A<span class=\"t32\">green</span>B", result);
624}624}
625625
626fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 {626fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 {
...@@ -770,6 +770,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok...@@ -770,6 +770,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
770 std.zig.Token.Id.Keyword_suspend,770 std.zig.Token.Id.Keyword_suspend,
771 std.zig.Token.Id.Keyword_switch,771 std.zig.Token.Id.Keyword_switch,
772 std.zig.Token.Id.Keyword_test,772 std.zig.Token.Id.Keyword_test,
773 std.zig.Token.Id.Keyword_threadlocal,
773 std.zig.Token.Id.Keyword_try,774 std.zig.Token.Id.Keyword_try,
774 std.zig.Token.Id.Keyword_union,775 std.zig.Token.Id.Keyword_union,
775 std.zig.Token.Id.Keyword_unreachable,776 std.zig.Token.Id.Keyword_unreachable,
...@@ -915,6 +916,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok...@@ -915,6 +916,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
915 std.zig.Token.Id.AngleBracketAngleBracketRightEqual,916 std.zig.Token.Id.AngleBracketAngleBracketRightEqual,
916 std.zig.Token.Id.Tilde,917 std.zig.Token.Id.Tilde,
917 std.zig.Token.Id.BracketStarBracket,918 std.zig.Token.Id.BracketStarBracket,
919 std.zig.Token.Id.BracketStarCBracket,
918 => try writeEscaped(out, src[token.start..token.end]),920 => try writeEscaped(out, src[token.start..token.end]),
919921
920 std.zig.Token.Id.Invalid => return parseError(922 std.zig.Token.Id.Invalid => return parseError(
...@@ -990,13 +992,19 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -990,13 +992,19 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
990 try tokenizeAndPrint(tokenizer, out, code.source_token);992 try tokenizeAndPrint(tokenizer, out, code.source_token);
991 try out.write("</pre>");993 try out.write("</pre>");
992 const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name);994 const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name);
993 const tmp_source_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_ext);995 const tmp_source_file_name = try os.path.join(
996 allocator,
997 [][]const u8{ tmp_dir_name, name_plus_ext },
998 );
994 try io.writeFile(tmp_source_file_name, trimmed_raw_source);999 try io.writeFile(tmp_source_file_name, trimmed_raw_source);
9951000
996 switch (code.id) {1001 switch (code.id) {
997 Code.Id.Exe => |expected_outcome| {1002 Code.Id.Exe => |expected_outcome| {
998 const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, exe_ext);1003 const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, exe_ext);
999 const tmp_bin_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_bin_ext);1004 const tmp_bin_file_name = try os.path.join(
1005 allocator,
1006 [][]const u8{ tmp_dir_name, name_plus_bin_ext },
1007 );
1000 var build_args = std.ArrayList([]const u8).init(allocator);1008 var build_args = std.ArrayList([]const u8).init(allocator);
1001 defer build_args.deinit();1009 defer build_args.deinit();
1002 try build_args.appendSlice([][]const u8{1010 try build_args.appendSlice([][]const u8{
...@@ -1024,7 +1032,10 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -1024,7 +1032,10 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
1024 }1032 }
1025 for (code.link_objects) |link_object| {1033 for (code.link_objects) |link_object| {
1026 const name_with_ext = try std.fmt.allocPrint(allocator, "{}{}", link_object, obj_ext);1034 const name_with_ext = try std.fmt.allocPrint(allocator, "{}{}", link_object, obj_ext);
1027 const full_path_object = try os.path.join(allocator, tmp_dir_name, name_with_ext);1035 const full_path_object = try os.path.join(
1036 allocator,
1037 [][]const u8{ tmp_dir_name, name_with_ext },
1038 );
1028 try build_args.append("--object");1039 try build_args.append("--object");
1029 try build_args.append(full_path_object);1040 try build_args.append(full_path_object);
1030 try out.print(" --object {}", name_with_ext);1041 try out.print(" --object {}", name_with_ext);
...@@ -1216,12 +1227,18 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -1216,12 +1227,18 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
1216 },1227 },
1217 Code.Id.Obj => |maybe_error_match| {1228 Code.Id.Obj => |maybe_error_match| {
1218 const name_plus_obj_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, obj_ext);1229 const name_plus_obj_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, obj_ext);
1219 const tmp_obj_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_obj_ext);1230 const tmp_obj_file_name = try os.path.join(
1231 allocator,
1232 [][]const u8{ tmp_dir_name, name_plus_obj_ext },
1233 );
1220 var build_args = std.ArrayList([]const u8).init(allocator);1234 var build_args = std.ArrayList([]const u8).init(allocator);
1221 defer build_args.deinit();1235 defer build_args.deinit();
12221236
1223 const name_plus_h_ext = try std.fmt.allocPrint(allocator, "{}.h", code.name);1237 const name_plus_h_ext = try std.fmt.allocPrint(allocator, "{}.h", code.name);
1224 const output_h_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_h_ext);1238 const output_h_file_name = try os.path.join(
1239 allocator,
1240 [][]const u8{ tmp_dir_name, name_plus_h_ext },
1241 );
12251242
1226 try build_args.appendSlice([][]const u8{1243 try build_args.appendSlice([][]const u8{
1227 zig_exe,1244 zig_exe,
doc/langref.html.in+280-85
...@@ -165,7 +165,7 @@ const std = @import("std");...@@ -165,7 +165,7 @@ const std = @import("std");
165165
166pub fn main() !void {166pub fn main() !void {
167 // If this program is run without stdout attached, exit with an error.167 // If this program is run without stdout attached, exit with an error.
168 var stdout_file = try std.io.getStdOut();168 const stdout_file = try std.io.getStdOut();
169 // If this program encounters pipe failure when printing to stdout, exit169 // If this program encounters pipe failure when printing to stdout, exit
170 // with an error.170 // with an error.
171 try stdout_file.write("Hello, world!\n");171 try stdout_file.write("Hello, world!\n");
...@@ -1531,6 +1531,29 @@ test "array initialization with function calls" {...@@ -1531,6 +1531,29 @@ test "array initialization with function calls" {
1531 {#code_end#}1531 {#code_end#}
1532 {#see_also|for|Slices#}1532 {#see_also|for|Slices#}
1533 {#header_close#}1533 {#header_close#}
1534
1535 {#header_open|Vectors#}
1536 <p>
1537 A vector is a group of {#link|Integers#}, {#link|Floats#}, or {#link|Pointers#} which are operated on
1538 in parallel using a single instruction ({#link|SIMD#}). Vector types are created with the builtin
1539 function {#link|@Vector#}.
1540 </p>
1541 <p>
1542 TODO talk about C ABI interop
1543 </p>
1544 {#header_open|SIMD#}
1545 <p>
1546 TODO Zig's SIMD abilities are just beginning to be fleshed out. Here are some talking points to update the
1547 docs with:
1548 * What kind of operations can you do? All the operations on integers and floats? What about mixing scalar and vector?
1549 * How to convert to/from vectors/arrays
1550 * How to access individual elements from vectors, how to loop over the elements
1551 * "shuffle"
1552 * Advice on writing high perf software, how to abstract the best way
1553 </p>
1554 {#header_close#}
1555 {#header_close#}
1556
1534 {#header_open|Pointers#}1557 {#header_open|Pointers#}
1535 <p>1558 <p>
1536 Zig has two kinds of pointers:1559 Zig has two kinds of pointers:
...@@ -1671,7 +1694,7 @@ test "comptime @intToPtr" {...@@ -1671,7 +1694,7 @@ test "comptime @intToPtr" {
1671 }1694 }
1672}1695}
1673 {#code_end#}1696 {#code_end#}
1674 {#see_also|Optional Pointers#}1697 {#see_also|Optional Pointers|@intToPtr|@ptrToInt#}
1675 {#header_open|volatile#}1698 {#header_open|volatile#}
1676 <p>Loads and stores are assumed to not have side effects. If a given load or store1699 <p>Loads and stores are assumed to not have side effects. If a given load or store
1677 should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}.1700 should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}.
...@@ -1800,7 +1823,9 @@ fn foo(bytes: []u8) u32 {...@@ -1800,7 +1823,9 @@ fn foo(bytes: []u8) u32 {
1800}1823}
1801 {#code_end#}1824 {#code_end#}
1802 {#header_close#}1825 {#header_close#}
1826 {#see_also|C Pointers#}
1803 {#header_close#}1827 {#header_close#}
1828
1804 {#header_open|Slices#}1829 {#header_open|Slices#}
1805 {#code_begin|test_safety|index out of bounds#}1830 {#code_begin|test_safety|index out of bounds#}
1806const assert = @import("std").debug.assert;1831const assert = @import("std").debug.assert;
...@@ -3169,7 +3194,16 @@ fn foo() void { }...@@ -3169,7 +3194,16 @@ fn foo() void { }
3169 {#code_end#}3194 {#code_end#}
3170 {#header_open|Pass-by-value Parameters#}3195 {#header_open|Pass-by-value Parameters#}
3171 <p>3196 <p>
3172 In Zig, structs, unions, and enums with payloads can be passed directly to a function:3197 Primitive types such as {#link|Integers#} and {#link|Floats#} passed as parameters
3198 are copied, and then the copy is available in the function body. This is called "passing by value".
3199 Copying a primitive type is essentially free and typically involves nothing more than
3200 setting a register.
3201 </p>
3202 <p>
3203 Structs, unions, and arrays can sometimes be more efficiently passed as a reference, since a copy
3204 could be arbitrarily expensive depending on the size. When these types are passed
3205 as parameters, Zig may choose to copy and pass by value, or pass by reference, whichever way
3206 Zig decides will be faster. This is made possible, in part, by the fact that parameters are immutable.
3173 </p>3207 </p>
3174 {#code_begin|test#}3208 {#code_begin|test#}
3175const Point = struct {3209const Point = struct {
...@@ -3178,20 +3212,20 @@ const Point = struct {...@@ -3178,20 +3212,20 @@ const Point = struct {
3178};3212};
31793213
3180fn foo(point: Point) i32 {3214fn foo(point: Point) i32 {
3215 // Here, `point` could be a reference, or a copy. The function body
3216 // can ignore the difference and treat it as a value. Be very careful
3217 // taking the address of the parameter - it should be treated as if
3218 // the address will become invalid when the function returns.
3181 return point.x + point.y;3219 return point.x + point.y;
3182}3220}
31833221
3184const assert = @import("std").debug.assert;3222const assert = @import("std").debug.assert;
31853223
3186test "pass aggregate type by non-copy value to function" {3224test "pass struct to function" {
3187 assert(foo(Point{ .x = 1, .y = 2 }) == 3);3225 assert(foo(Point{ .x = 1, .y = 2 }) == 3);
3188}3226}
3189 {#code_end#}3227 {#code_end#}
3190 <p>3228 <p>
3191 In this case, the value may be passed by reference, or by value, whichever way
3192 Zig decides will be faster.
3193 </p>
3194 <p>
3195 For extern functions, Zig follows the C ABI for passing structs and unions by value.3229 For extern functions, Zig follows the C ABI for passing structs and unions by value.
3196 </p>3230 </p>
3197 {#header_close#}3231 {#header_close#}
...@@ -3949,7 +3983,7 @@ test "implicit cast - invoke a type as a function" {...@@ -3949,7 +3983,7 @@ test "implicit cast - invoke a type as a function" {
3949 {#code_end#}3983 {#code_end#}
3950 <p>3984 <p>
3951 Implicit casts are only allowed when it is completely unambiguous how to get from one type to another,3985 Implicit casts are only allowed when it is completely unambiguous how to get from one type to another,
3952 and the transformation is guaranteed to be safe.3986 and the transformation is guaranteed to be safe. There is one exception, which is {#link|C Pointers#}.
3953 </p>3987 </p>
3954 {#header_open|Implicit Cast: Stricter Qualification#}3988 {#header_open|Implicit Cast: Stricter Qualification#}
3955 <p>3989 <p>
...@@ -4327,7 +4361,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {...@@ -4327,7 +4361,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {
4327 <p>4361 <p>
4328 For example, if we were to introduce another function to the above snippet:4362 For example, if we were to introduce another function to the above snippet:
4329 </p>4363 </p>
4330 {#code_begin|test_err|unable to evaluate constant expression#}4364 {#code_begin|test_err|values of type 'type' must be comptime known#}
4331fn max(comptime T: type, a: T, b: T) T {4365fn max(comptime T: type, a: T, b: T) T {
4332 return if (a > b) a else b;4366 return if (a > b) a else b;
4333}4367}
...@@ -4595,7 +4629,7 @@ test "fibonacci" {...@@ -4595,7 +4629,7 @@ test "fibonacci" {
4595 <p>4629 <p>
4596 What if we fix the base case, but put the wrong value in the {#syntax#}assert{#endsyntax#} line?4630 What if we fix the base case, but put the wrong value in the {#syntax#}assert{#endsyntax#} line?
4597 </p>4631 </p>
4598 {#code_begin|test_err|encountered @panic at compile-time#}4632 {#code_begin|test_err|unable to evaluate constant expression#}
4599const assert = @import("std").debug.assert;4633const assert = @import("std").debug.assert;
46004634
4601fn fibonacci(index: i32) i32 {4635fn fibonacci(index: i32) i32 {
...@@ -5169,6 +5203,34 @@ fn seq(c: u8) void {...@@ -5169,6 +5203,34 @@ fn seq(c: u8) void {
5169 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.5203 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
5170 </p>5204 </p>
5171 {#header_close#}5205 {#header_close#}
5206 {#header_open|@alignCast#}
5207 <pre>{#syntax#}@alignCast(comptime alignment: u29, ptr: var) var{#endsyntax#}</pre>
5208 <p>
5209 {#syntax#}ptr{#endsyntax#} can be {#syntax#}*T{#endsyntax#}, {#syntax#}fn(){#endsyntax#}, {#syntax#}?*T{#endsyntax#},
5210 {#syntax#}?fn(){#endsyntax#}, or {#syntax#}[]T{#endsyntax#}. It returns the same type as {#syntax#}ptr{#endsyntax#}
5211 except with the alignment adjusted to the new value.
5212 </p>
5213 <p>A {#link|pointer alignment safety check|Incorrect Pointer Alignment#} is added
5214 to the generated code to make sure the pointer is aligned as promised.</p>
5215
5216 {#header_close#}
5217 {#header_open|@alignOf#}
5218 <pre>{#syntax#}@alignOf(comptime T: type) comptime_int{#endsyntax#}</pre>
5219 <p>
5220 This function returns the number of bytes that this type should be aligned to
5221 for the current target to match the C ABI. When the child type of a pointer has
5222 this alignment, the alignment can be omitted from the type.
5223 </p>
5224 <pre>{#syntax#}const assert = @import("std").debug.assert;
5225comptime {
5226 assert(*u32 == *align(@alignOf(u32)) u32);
5227}{#endsyntax#}</pre>
5228 <p>
5229 The result is a target-specific compile time constant. It is guaranteed to be
5230 less than or equal to {#link|@sizeOf(T)|@sizeOf#}.
5231 </p>
5232 {#see_also|Alignment#}
5233 {#header_close#}
5172 {#header_open|@ArgType#}5234 {#header_open|@ArgType#}
5173 <pre>{#syntax#}@ArgType(comptime T: type, comptime n: usize) type{#endsyntax#}</pre>5235 <pre>{#syntax#}@ArgType(comptime T: type, comptime n: usize) type{#endsyntax#}</pre>
5174 <p>5236 <p>
...@@ -5241,6 +5303,7 @@ fn seq(c: u8) void {...@@ -5241,6 +5303,7 @@ fn seq(c: u8) void {
5241 Works at compile-time if {#syntax#}value{#endsyntax#} is known at compile time. It's a compile error to bitcast a struct to a scalar type of the same size since structs have undefined layout. However if the struct is packed then it works.5303 Works at compile-time if {#syntax#}value{#endsyntax#} is known at compile time. It's a compile error to bitcast a struct to a scalar type of the same size since structs have undefined layout. However if the struct is packed then it works.
5242 </p>5304 </p>
5243 {#header_close#}5305 {#header_close#}
5306
5244 {#header_open|@bitOffsetOf#}5307 {#header_open|@bitOffsetOf#}
5245 <pre>{#syntax#}@bitOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre>5308 <pre>{#syntax#}@bitOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre>
5246 <p>5309 <p>
...@@ -5253,6 +5316,19 @@ fn seq(c: u8) void {...@@ -5253,6 +5316,19 @@ fn seq(c: u8) void {
5253 </p>5316 </p>
5254 {#see_also|@byteOffsetOf#}5317 {#see_also|@byteOffsetOf#}
5255 {#header_close#}5318 {#header_close#}
5319
5320 {#header_open|@boolToInt#}
5321 <pre>{#syntax#}@boolToInt(value: bool) u1{#endsyntax#}</pre>
5322 <p>
5323 Converts {#syntax#}true{#endsyntax#} to {#syntax#}u1(1){#endsyntax#} and {#syntax#}false{#endsyntax#} to
5324 {#syntax#}u1(0){#endsyntax#}.
5325 </p>
5326 <p>
5327 If the value is known at compile-time, the return type is {#syntax#}comptime_int{#endsyntax#}
5328 instead of {#syntax#}u1{#endsyntax#}.
5329 </p>
5330 {#header_close#}
5331
5256 {#header_open|@breakpoint#}5332 {#header_open|@breakpoint#}
5257 <pre>{#syntax#}@breakpoint(){#endsyntax#}</pre>5333 <pre>{#syntax#}@breakpoint(){#endsyntax#}</pre>
5258 <p>5334 <p>
...@@ -5264,52 +5340,34 @@ fn seq(c: u8) void {...@@ -5264,52 +5340,34 @@ fn seq(c: u8) void {
5264 </p>5340 </p>
52655341
5266 {#header_close#}5342 {#header_close#}
5267 {#header_open|@byteOffsetOf#}5343
5268 <pre>{#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre>5344 {#header_open|@bswap#}
5345 <pre>{#syntax#}@bswap(comptime T: type, value: T) T{#endsyntax#}</pre>
5346 <p>{#syntax#}T{#endsyntax#} must be an integer type with bit count evenly divisible by 8.</p>
5269 <p>5347 <p>
5270 Returns the byte offset of a field relative to its containing struct.5348 Swaps the byte order of the integer. This converts a big endian integer to a little endian integer,
5349 and converts a little endian integer to a big endian integer.
5271 </p>5350 </p>
5272 {#see_also|@bitOffsetOf#}
5273 {#header_close#}5351 {#header_close#}
5274 {#header_open|@alignCast#}
5275 <pre>{#syntax#}@alignCast(comptime alignment: u29, ptr: var) var{#endsyntax#}</pre>
5276 <p>
5277 {#syntax#}ptr{#endsyntax#} can be {#syntax#}*T{#endsyntax#}, {#syntax#}fn(){#endsyntax#}, {#syntax#}?*T{#endsyntax#},
5278 {#syntax#}?fn(){#endsyntax#}, or {#syntax#}[]T{#endsyntax#}. It returns the same type as {#syntax#}ptr{#endsyntax#}
5279 except with the alignment adjusted to the new value.
5280 </p>
5281 <p>A {#link|pointer alignment safety check|Incorrect Pointer Alignment#} is added
5282 to the generated code to make sure the pointer is aligned as promised.</p>
52835352
5284 {#header_close#}5353 {#header_open|@bitreverse#}
5285 {#header_open|@alignOf#}5354 <pre>{#syntax#}@bitreverse(comptime T: type, value: T) T{#endsyntax#}</pre>
5286 <pre>{#syntax#}@alignOf(comptime T: type) comptime_int{#endsyntax#}</pre>5355 <p>{#syntax#}T{#endsyntax#} accepts any integer type.</p>
5287 <p>5356 <p>
5288 This function returns the number of bytes that this type should be aligned to5357 Reverses the bitpattern of an integer value, including the sign bit if applicable.
5289 for the current target to match the C ABI. When the child type of a pointer has
5290 this alignment, the alignment can be omitted from the type.
5291 </p>5358 </p>
5292 <pre>{#syntax#}const assert = @import("std").debug.assert;
5293comptime {
5294 assert(*u32 == *align(@alignOf(u32)) u32);
5295}{#endsyntax#}</pre>
5296 <p>5359 <p>
5297 The result is a target-specific compile time constant. It is guaranteed to be5360 For example 0b10110110 ({#syntax#}u8 = 182{#endsyntax#}, {#syntax#}i8 = -74{#endsyntax#})
5298 less than or equal to {#link|@sizeOf(T)|@sizeOf#}.5361 becomes 0b01101101 ({#syntax#}u8 = 109{#endsyntax#}, {#syntax#}i8 = 109{#endsyntax#}).
5299 </p>5362 </p>
5300 {#see_also|Alignment#}
5301 {#header_close#}5363 {#header_close#}
53025364
5303 {#header_open|@boolToInt#}5365 {#header_open|@byteOffsetOf#}
5304 <pre>{#syntax#}@boolToInt(value: bool) u1{#endsyntax#}</pre>5366 <pre>{#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre>
5305 <p>
5306 Converts {#syntax#}true{#endsyntax#} to {#syntax#}u1(1){#endsyntax#} and {#syntax#}false{#endsyntax#} to
5307 {#syntax#}u1(0){#endsyntax#}.
5308 </p>
5309 <p>5367 <p>
5310 If the value is known at compile-time, the return type is {#syntax#}comptime_int{#endsyntax#}5368 Returns the byte offset of a field relative to its containing struct.
5311 instead of {#syntax#}u1{#endsyntax#}.
5312 </p>5369 </p>
5370 {#see_also|@bitOffsetOf#}
5313 {#header_close#}5371 {#header_close#}
53145372
5315 {#header_open|@bytesToSlice#}5373 {#header_open|@bytesToSlice#}
...@@ -5378,17 +5436,7 @@ comptime {...@@ -5378,17 +5436,7 @@ comptime {
5378 </p>5436 </p>
5379 {#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#}5437 {#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#}
5380 {#header_close#}5438 {#header_close#}
5381 {#header_open|@cUndef#}5439
5382 <pre>{#syntax#}@cUndef(comptime name: []u8){#endsyntax#}</pre>
5383 <p>
5384 This function can only occur inside {#syntax#}@cImport{#endsyntax#}.
5385 </p>
5386 <p>
5387 This appends <code>#undef $name</code> to the {#syntax#}@cImport{#endsyntax#}
5388 temporary buffer.
5389 </p>
5390 {#see_also|Import from C Header File|@cImport|@cDefine|@cInclude#}
5391 {#header_close#}
5392 {#header_open|@clz#}5440 {#header_open|@clz#}
5393 <pre>{#syntax#}@clz(x: T) U{#endsyntax#}</pre>5441 <pre>{#syntax#}@clz(x: T) U{#endsyntax#}</pre>
5394 <p>5442 <p>
...@@ -5404,6 +5452,7 @@ comptime {...@@ -5404,6 +5452,7 @@ comptime {
5404 </p>5452 </p>
5405 {#see_also|@ctz|@popCount#}5453 {#see_also|@ctz|@popCount#}
5406 {#header_close#}5454 {#header_close#}
5455
5407 {#header_open|@cmpxchgStrong#}5456 {#header_open|@cmpxchgStrong#}
5408 <pre>{#syntax#}@cmpxchgStrong(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}</pre>5457 <pre>{#syntax#}@cmpxchgStrong(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}</pre>
5409 <p>5458 <p>
...@@ -5459,6 +5508,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val...@@ -5459,6 +5508,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
5459 <p>{#syntax#}@typeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>5508 <p>{#syntax#}@typeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
5460 {#see_also|Compile Variables|cmpxchgStrong#}5509 {#see_also|Compile Variables|cmpxchgStrong#}
5461 {#header_close#}5510 {#header_close#}
5511
5462 {#header_open|@compileError#}5512 {#header_open|@compileError#}
5463 <pre>{#syntax#}@compileError(comptime msg: []u8){#endsyntax#}</pre>5513 <pre>{#syntax#}@compileError(comptime msg: []u8){#endsyntax#}</pre>
5464 <p>5514 <p>
...@@ -5471,6 +5521,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val...@@ -5471,6 +5521,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
5471 and {#syntax#}comptime{#endsyntax#} functions.5521 and {#syntax#}comptime{#endsyntax#} functions.
5472 </p>5522 </p>
5473 {#header_close#}5523 {#header_close#}
5524
5474 {#header_open|@compileLog#}5525 {#header_open|@compileLog#}
5475 <pre>{#syntax#}@compileLog(args: ...){#endsyntax#}</pre>5526 <pre>{#syntax#}@compileLog(args: ...){#endsyntax#}</pre>
5476 <p>5527 <p>
...@@ -5525,6 +5576,7 @@ test "main" {...@@ -5525,6 +5576,7 @@ test "main" {
5525}5576}
5526 {#code_end#}5577 {#code_end#}
5527 {#header_close#}5578 {#header_close#}
5579
5528 {#header_open|@ctz#}5580 {#header_open|@ctz#}
5529 <pre>{#syntax#}@ctz(x: T) U{#endsyntax#}</pre>5581 <pre>{#syntax#}@ctz(x: T) U{#endsyntax#}</pre>
5530 <p>5582 <p>
...@@ -5540,6 +5592,19 @@ test "main" {...@@ -5540,6 +5592,19 @@ test "main" {
5540 </p>5592 </p>
5541 {#see_also|@clz|@popCount#}5593 {#see_also|@clz|@popCount#}
5542 {#header_close#}5594 {#header_close#}
5595
5596 {#header_open|@cUndef#}
5597 <pre>{#syntax#}@cUndef(comptime name: []u8){#endsyntax#}</pre>
5598 <p>
5599 This function can only occur inside {#syntax#}@cImport{#endsyntax#}.
5600 </p>
5601 <p>
5602 This appends <code>#undef $name</code> to the {#syntax#}@cImport{#endsyntax#}
5603 temporary buffer.
5604 </p>
5605 {#see_also|Import from C Header File|@cImport|@cDefine|@cInclude#}
5606 {#header_close#}
5607
5543 {#header_open|@divExact#}5608 {#header_open|@divExact#}
5544 <pre>{#syntax#}@divExact(numerator: T, denominator: T) T{#endsyntax#}</pre>5609 <pre>{#syntax#}@divExact(numerator: T, denominator: T) T{#endsyntax#}</pre>
5545 <p>5610 <p>
...@@ -5606,14 +5671,6 @@ test "main" {...@@ -5606,14 +5671,6 @@ test "main" {
5606 {#see_also|@intToEnum#}5671 {#see_also|@intToEnum#}
5607 {#header_close#}5672 {#header_close#}
56085673
5609 {#header_open|@errSetCast#}
5610 <pre>{#syntax#}@errSetCast(comptime T: DestType, value: var) DestType{#endsyntax#}</pre>
5611 <p>
5612 Converts an error value from one error set to another error set. Attempting to convert an error
5613 which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}.
5614 </p>
5615 {#header_close#}
5616
5617 {#header_open|@errorName#}5674 {#header_open|@errorName#}
5618 <pre>{#syntax#}@errorName(err: anyerror) []const u8{#endsyntax#}</pre>5675 <pre>{#syntax#}@errorName(err: anyerror) []const u8{#endsyntax#}</pre>
5619 <p>5676 <p>
...@@ -5656,6 +5713,14 @@ test "main" {...@@ -5656,6 +5713,14 @@ test "main" {
5656 {#see_also|@intToError#}5713 {#see_also|@intToError#}
5657 {#header_close#}5714 {#header_close#}
56585715
5716 {#header_open|@errSetCast#}
5717 <pre>{#syntax#}@errSetCast(comptime T: DestType, value: var) DestType{#endsyntax#}</pre>
5718 <p>
5719 Converts an error value from one error set to another error set. Attempting to convert an error
5720 which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}.
5721 </p>
5722 {#header_close#}
5723
5659 {#header_open|@export#}5724 {#header_open|@export#}
5660 <pre>{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8{#endsyntax#}</pre>5725 <pre>{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8{#endsyntax#}</pre>
5661 <p>5726 <p>
...@@ -5724,6 +5789,7 @@ test "main" {...@@ -5724,6 +5789,7 @@ test "main" {
5724 This function is only valid within function scope.5789 This function is only valid within function scope.
5725 </p>5790 </p>
5726 {#header_close#}5791 {#header_close#}
5792
5727 {#header_open|@handle#}5793 {#header_open|@handle#}
5728 <pre>{#syntax#}@handle(){#endsyntax#}</pre>5794 <pre>{#syntax#}@handle(){#endsyntax#}</pre>
5729 <p>5795 <p>
...@@ -5734,6 +5800,7 @@ test "main" {...@@ -5734,6 +5800,7 @@ test "main" {
5734 This function is only valid within an async function scope.5800 This function is only valid within an async function scope.
5735 </p>5801 </p>
5736 {#header_close#}5802 {#header_close#}
5803
5737 {#header_open|@import#}5804 {#header_open|@import#}
5738 <pre>{#syntax#}@import(comptime path: []u8) (namespace){#endsyntax#}</pre>5805 <pre>{#syntax#}@import(comptime path: []u8) (namespace){#endsyntax#}</pre>
5739 <p>5806 <p>
...@@ -5754,6 +5821,7 @@ test "main" {...@@ -5754,6 +5821,7 @@ test "main" {
5754 </ul>5821 </ul>
5755 {#see_also|Compile Variables|@embedFile#}5822 {#see_also|Compile Variables|@embedFile#}
5756 {#header_close#}5823 {#header_close#}
5824
5757 {#header_open|@inlineCall#}5825 {#header_open|@inlineCall#}
5758 <pre>{#syntax#}@inlineCall(function: X, args: ...) Y{#endsyntax#}</pre>5826 <pre>{#syntax#}@inlineCall(function: X, args: ...) Y{#endsyntax#}</pre>
5759 <p>5827 <p>
...@@ -5833,6 +5901,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -5833,6 +5901,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
5833 bit count for an integer type is {#syntax#}65535{#endsyntax#}.5901 bit count for an integer type is {#syntax#}65535{#endsyntax#}.
5834 </p>5902 </p>
5835 {#header_close#}5903 {#header_close#}
5904
5836 {#header_open|@memberCount#}5905 {#header_open|@memberCount#}
5837 <pre>{#syntax#}@memberCount(comptime T: type) comptime_int{#endsyntax#}</pre>5906 <pre>{#syntax#}@memberCount(comptime T: type) comptime_int{#endsyntax#}</pre>
5838 <p>5907 <p>
...@@ -5859,6 +5928,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -5859,6 +5928,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
5859 <pre>{#syntax#}@memberType(comptime T: type, comptime index: usize) type{#endsyntax#}</pre>5928 <pre>{#syntax#}@memberType(comptime T: type, comptime index: usize) type{#endsyntax#}</pre>
5860 <p>Returns the field type of a struct or union.</p>5929 <p>Returns the field type of a struct or union.</p>
5861 {#header_close#}5930 {#header_close#}
5931
5862 {#header_open|@memcpy#}5932 {#header_open|@memcpy#}
5863 <pre>{#syntax#}@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize){#endsyntax#}</pre>5933 <pre>{#syntax#}@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize){#endsyntax#}</pre>
5864 <p>5934 <p>
...@@ -5869,14 +5939,15 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -5869,14 +5939,15 @@ fn add(a: i32, b: i32) i32 { return a + b; }
5869 This function is a low level intrinsic with no safety mechanisms. Most code5939 This function is a low level intrinsic with no safety mechanisms. Most code
5870 should not use this function, instead using something like this:5940 should not use this function, instead using something like this:
5871 </p>5941 </p>
5872 <pre>{#syntax#}for (source[0...byte_count]) |b, i| dest[i] = b;{#endsyntax#}</pre>5942 <pre>{#syntax#}for (source[0..byte_count]) |b, i| dest[i] = b;{#endsyntax#}</pre>
5873 <p>5943 <p>
5874 The optimizer is intelligent enough to turn the above snippet into a memcpy.5944 The optimizer is intelligent enough to turn the above snippet into a memcpy.
5875 </p>5945 </p>
5876 <p>There is also a standard library function for this:</p>5946 <p>There is also a standard library function for this:</p>
5877 <pre>{#syntax#}const mem = @import("std").mem;5947 <pre>{#syntax#}const mem = @import("std").mem;
5878mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>5948mem.copy(u8, dest[0..byte_count], source[0..byte_count]);{#endsyntax#}</pre>
5879 {#header_close#}5949 {#header_close#}
5950
5880 {#header_open|@memset#}5951 {#header_open|@memset#}
5881 <pre>{#syntax#}@memset(dest: [*]u8, c: u8, byte_count: usize){#endsyntax#}</pre>5952 <pre>{#syntax#}@memset(dest: [*]u8, c: u8, byte_count: usize){#endsyntax#}</pre>
5882 <p>5953 <p>
...@@ -5886,7 +5957,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>...@@ -5886,7 +5957,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>
5886 This function is a low level intrinsic with no safety mechanisms. Most5957 This function is a low level intrinsic with no safety mechanisms. Most
5887 code should not use this function, instead using something like this:5958 code should not use this function, instead using something like this:
5888 </p>5959 </p>
5889 <pre>{#syntax#}for (dest[0...byte_count]) |*b| b.* = c;{#endsyntax#}</pre>5960 <pre>{#syntax#}for (dest[0..byte_count]) |*b| b.* = c;{#endsyntax#}</pre>
5890 <p>5961 <p>
5891 The optimizer is intelligent enough to turn the above snippet into a memset.5962 The optimizer is intelligent enough to turn the above snippet into a memset.
5892 </p>5963 </p>
...@@ -5894,6 +5965,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>...@@ -5894,6 +5965,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>
5894 <pre>{#syntax#}const mem = @import("std").mem;5965 <pre>{#syntax#}const mem = @import("std").mem;
5895mem.set(u8, dest, c);{#endsyntax#}</pre>5966mem.set(u8, dest, c);{#endsyntax#}</pre>
5896 {#header_close#}5967 {#header_close#}
5968
5897 {#header_open|@mod#}5969 {#header_open|@mod#}
5898 <pre>{#syntax#}@mod(numerator: T, denominator: T) T{#endsyntax#}</pre>5970 <pre>{#syntax#}@mod(numerator: T, denominator: T) T{#endsyntax#}</pre>
5899 <p>5971 <p>
...@@ -5907,6 +5979,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>...@@ -5907,6 +5979,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>
5907 <p>For a function that returns an error code, see {#syntax#}@import("std").math.mod{#endsyntax#}.</p>5979 <p>For a function that returns an error code, see {#syntax#}@import("std").math.mod{#endsyntax#}.</p>
5908 {#see_also|@rem#}5980 {#see_also|@rem#}
5909 {#header_close#}5981 {#header_close#}
5982
5910 {#header_open|@mulWithOverflow#}5983 {#header_open|@mulWithOverflow#}
5911 <pre>{#syntax#}@mulWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre>5984 <pre>{#syntax#}@mulWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre>
5912 <p>5985 <p>
...@@ -5915,6 +5988,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>...@@ -5915,6 +5988,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>
5915 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.5988 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
5916 </p>5989 </p>
5917 {#header_close#}5990 {#header_close#}
5991
5918 {#header_open|@newStackCall#}5992 {#header_open|@newStackCall#}
5919 <pre>{#syntax#}@newStackCall(new_stack: []u8, function: var, args: ...) var{#endsyntax#}</pre>5993 <pre>{#syntax#}@newStackCall(new_stack: []u8, function: var, args: ...) var{#endsyntax#}</pre>
5920 <p>5994 <p>
...@@ -5951,6 +6025,7 @@ fn targetFunction(x: i32) usize {...@@ -5951,6 +6025,7 @@ fn targetFunction(x: i32) usize {
5951}6025}
5952 {#code_end#}6026 {#code_end#}
5953 {#header_close#}6027 {#header_close#}
6028
5954 {#header_open|@noInlineCall#}6029 {#header_open|@noInlineCall#}
5955 <pre>{#syntax#}@noInlineCall(function: var, args: ...) var{#endsyntax#}</pre>6030 <pre>{#syntax#}@noInlineCall(function: var, args: ...) var{#endsyntax#}</pre>
5956 <p>6031 <p>
...@@ -5973,6 +6048,7 @@ fn add(a: i32, b: i32) i32 {...@@ -5973,6 +6048,7 @@ fn add(a: i32, b: i32) i32 {
5973 </p>6048 </p>
5974 {#see_also|@inlineCall#}6049 {#see_also|@inlineCall#}
5975 {#header_close#}6050 {#header_close#}
6051
5976 {#header_open|@OpaqueType#}6052 {#header_open|@OpaqueType#}
5977 <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>6053 <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>
5978 <p>6054 <p>
...@@ -5996,6 +6072,7 @@ test "call foo" {...@@ -5996,6 +6072,7 @@ test "call foo" {
5996}6072}
5997 {#code_end#}6073 {#code_end#}
5998 {#header_close#}6074 {#header_close#}
6075
5999 {#header_open|@panic#}6076 {#header_open|@panic#}
6000 <pre>{#syntax#}@panic(message: []const u8) noreturn{#endsyntax#}</pre>6077 <pre>{#syntax#}@panic(message: []const u8) noreturn{#endsyntax#}</pre>
6001 <p>6078 <p>
...@@ -6012,6 +6089,7 @@ test "call foo" {...@@ -6012,6 +6089,7 @@ test "call foo" {
6012 </ul>6089 </ul>
6013 {#see_also|Root Source File#}6090 {#see_also|Root Source File#}
6014 {#header_close#}6091 {#header_close#}
6092
6015 {#header_open|@popCount#}6093 {#header_open|@popCount#}
6016 <pre>{#syntax#}@popCount(integer: var) var{#endsyntax#}</pre>6094 <pre>{#syntax#}@popCount(integer: var) var{#endsyntax#}</pre>
6017 <p>Counts the number of bits set in an integer.</p>6095 <p>Counts the number of bits set in an integer.</p>
...@@ -6022,12 +6100,18 @@ test "call foo" {...@@ -6022,12 +6100,18 @@ test "call foo" {
6022 </p>6100 </p>
6023 {#see_also|@ctz|@clz#}6101 {#see_also|@ctz|@clz#}
6024 {#header_close#}6102 {#header_close#}
6103
6025 {#header_open|@ptrCast#}6104 {#header_open|@ptrCast#}
6026 <pre>{#syntax#}@ptrCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre>6105 <pre>{#syntax#}@ptrCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre>
6027 <p>6106 <p>
6028 Converts a pointer of one type to a pointer of another type.6107 Converts a pointer of one type to a pointer of another type.
6029 </p>6108 </p>
6109 <p>
6110 {#link|Optional Pointers#} are allowed. Casting an optional pointer which is {#link|null#}
6111 to a non-optional pointer invokes safety-checked {#link|Undefined Behavior#}.
6112 </p>
6030 {#header_close#}6113 {#header_close#}
6114
6031 {#header_open|@ptrToInt#}6115 {#header_open|@ptrToInt#}
6032 <pre>{#syntax#}@ptrToInt(value: var) usize{#endsyntax#}</pre>6116 <pre>{#syntax#}@ptrToInt(value: var) usize{#endsyntax#}</pre>
6033 <p>6117 <p>
...@@ -6042,6 +6126,7 @@ test "call foo" {...@@ -6042,6 +6126,7 @@ test "call foo" {
6042 <p>To convert the other way, use {#link|@intToPtr#}</p>6126 <p>To convert the other way, use {#link|@intToPtr#}</p>
60436127
6044 {#header_close#}6128 {#header_close#}
6129
6045 {#header_open|@rem#}6130 {#header_open|@rem#}
6046 <pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre>6131 <pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre>
6047 <p>6132 <p>
...@@ -6055,6 +6140,7 @@ test "call foo" {...@@ -6055,6 +6140,7 @@ test "call foo" {
6055 <p>For a function that returns an error code, see {#syntax#}@import("std").math.rem{#endsyntax#}.</p>6140 <p>For a function that returns an error code, see {#syntax#}@import("std").math.rem{#endsyntax#}.</p>
6056 {#see_also|@mod#}6141 {#see_also|@mod#}
6057 {#header_close#}6142 {#header_close#}
6143
6058 {#header_open|@returnAddress#}6144 {#header_open|@returnAddress#}
6059 <pre>{#syntax#}@returnAddress(){#endsyntax#}</pre>6145 <pre>{#syntax#}@returnAddress(){#endsyntax#}</pre>
6060 <p>6146 <p>
...@@ -6075,19 +6161,14 @@ test "call foo" {...@@ -6075,19 +6161,14 @@ test "call foo" {
6075 Ensures that a function will have a stack alignment of at least {#syntax#}alignment{#endsyntax#} bytes.6161 Ensures that a function will have a stack alignment of at least {#syntax#}alignment{#endsyntax#} bytes.
6076 </p>6162 </p>
6077 {#header_close#}6163 {#header_close#}
6164
6078 {#header_open|@setCold#}6165 {#header_open|@setCold#}
6079 <pre>{#syntax#}@setCold(is_cold: bool){#endsyntax#}</pre>6166 <pre>{#syntax#}@setCold(is_cold: bool){#endsyntax#}</pre>
6080 <p>6167 <p>
6081 Tells the optimizer that a function is rarely called.6168 Tells the optimizer that a function is rarely called.
6082 </p>6169 </p>
6083 {#header_close#}6170 {#header_close#}
6084 {#header_open|@setRuntimeSafety#}
6085 <pre>{#syntax#}@setRuntimeSafety(safety_on: bool){#endsyntax#}</pre>
6086 <p>
6087 Sets whether runtime safety checks are on for the scope that contains the function call.
6088 </p>
60896171
6090 {#header_close#}
6091 {#header_open|@setEvalBranchQuota#}6172 {#header_open|@setEvalBranchQuota#}
6092 <pre>{#syntax#}@setEvalBranchQuota(new_quota: usize){#endsyntax#}</pre>6173 <pre>{#syntax#}@setEvalBranchQuota(new_quota: usize){#endsyntax#}</pre>
6093 <p>6174 <p>
...@@ -6122,6 +6203,7 @@ test "foo" {...@@ -6122,6 +6203,7 @@ test "foo" {
61226203
6123 {#see_also|comptime#}6204 {#see_also|comptime#}
6124 {#header_close#}6205 {#header_close#}
6206
6125 {#header_open|@setFloatMode#}6207 {#header_open|@setFloatMode#}
6126 <pre>{#syntax#}@setFloatMode(mode: @import("builtin").FloatMode){#endsyntax#}</pre>6208 <pre>{#syntax#}@setFloatMode(mode: @import("builtin").FloatMode){#endsyntax#}</pre>
6127 <p>6209 <p>
...@@ -6156,6 +6238,7 @@ pub const FloatMode = enum {...@@ -6156,6 +6238,7 @@ pub const FloatMode = enum {
6156 </p>6238 </p>
6157 {#see_also|Floating Point Operations#}6239 {#see_also|Floating Point Operations#}
6158 {#header_close#}6240 {#header_close#}
6241
6159 {#header_open|@setGlobalLinkage#}6242 {#header_open|@setGlobalLinkage#}
6160 <pre>{#syntax#}@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage){#endsyntax#}</pre>6243 <pre>{#syntax#}@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage){#endsyntax#}</pre>
6161 <p>6244 <p>
...@@ -6163,6 +6246,15 @@ pub const FloatMode = enum {...@@ -6163,6 +6246,15 @@ pub const FloatMode = enum {
6163 </p>6246 </p>
6164 {#see_also|Compile Variables#}6247 {#see_also|Compile Variables#}
6165 {#header_close#}6248 {#header_close#}
6249
6250 {#header_open|@setRuntimeSafety#}
6251 <pre>{#syntax#}@setRuntimeSafety(safety_on: bool){#endsyntax#}</pre>
6252 <p>
6253 Sets whether runtime safety checks are on for the scope that contains the function call.
6254 </p>
6255
6256 {#header_close#}
6257
6166 {#header_open|@shlExact#}6258 {#header_open|@shlExact#}
6167 <pre>{#syntax#}@shlExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre>6259 <pre>{#syntax#}@shlExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre>
6168 <p>6260 <p>
...@@ -6175,6 +6267,7 @@ pub const FloatMode = enum {...@@ -6175,6 +6267,7 @@ pub const FloatMode = enum {
6175 </p>6267 </p>
6176 {#see_also|@shrExact|@shlWithOverflow#}6268 {#see_also|@shrExact|@shlWithOverflow#}
6177 {#header_close#}6269 {#header_close#}
6270
6178 {#header_open|@shlWithOverflow#}6271 {#header_open|@shlWithOverflow#}
6179 <pre>{#syntax#}@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: *T) bool{#endsyntax#}</pre>6272 <pre>{#syntax#}@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: *T) bool{#endsyntax#}</pre>
6180 <p>6273 <p>
...@@ -6188,6 +6281,7 @@ pub const FloatMode = enum {...@@ -6188,6 +6281,7 @@ pub const FloatMode = enum {
6188 </p>6281 </p>
6189 {#see_also|@shlExact|@shrExact#}6282 {#see_also|@shlExact|@shrExact#}
6190 {#header_close#}6283 {#header_close#}
6284
6191 {#header_open|@shrExact#}6285 {#header_open|@shrExact#}
6192 <pre>{#syntax#}@shrExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre>6286 <pre>{#syntax#}@shrExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre>
6193 <p>6287 <p>
...@@ -6205,10 +6299,15 @@ pub const FloatMode = enum {...@@ -6205,10 +6299,15 @@ pub const FloatMode = enum {
6205 <pre>{#syntax#}@sizeOf(comptime T: type) comptime_int{#endsyntax#}</pre>6299 <pre>{#syntax#}@sizeOf(comptime T: type) comptime_int{#endsyntax#}</pre>
6206 <p>6300 <p>
6207 This function returns the number of bytes it takes to store {#syntax#}T{#endsyntax#} in memory.6301 This function returns the number of bytes it takes to store {#syntax#}T{#endsyntax#} in memory.
6302 The result is a target-specific compile time constant.
6208 </p>6303 </p>
6209 <p>6304 <p>
6210 The result is a target-specific compile time constant.6305 This size may contain padding bytes. If there were two consecutive T in memory, this would be the offset
6306 in bytes between element at index 0 and the element at index 1. For {#link|integer|Integers#},
6307 consider whether you want to use {#syntax#}@sizeOf(T){#endsyntax#} or
6308 {#syntax#}@typeInfo(T).Int.bits{#endsyntax#}.
6211 </p>6309 </p>
6310 {#see_also|@typeInfo#}
6212 {#header_close#}6311 {#header_close#}
62136312
6214 {#header_open|@sliceToBytes#}6313 {#header_open|@sliceToBytes#}
...@@ -6229,6 +6328,7 @@ pub const FloatMode = enum {...@@ -6229,6 +6328,7 @@ pub const FloatMode = enum {
6229 This is a low-level intrinsic. Most code can use {#syntax#}std.math.sqrt{#endsyntax#} instead.6328 This is a low-level intrinsic. Most code can use {#syntax#}std.math.sqrt{#endsyntax#} instead.
6230 </p>6329 </p>
6231 {#header_close#}6330 {#header_close#}
6331
6232 {#header_open|@subWithOverflow#}6332 {#header_open|@subWithOverflow#}
6233 <pre>{#syntax#}@subWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre>6333 <pre>{#syntax#}@subWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre>
6234 <p>6334 <p>
...@@ -6237,12 +6337,14 @@ pub const FloatMode = enum {...@@ -6237,12 +6337,14 @@ pub const FloatMode = enum {
6237 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.6337 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
6238 </p>6338 </p>
6239 {#header_close#}6339 {#header_close#}
6340
6240 {#header_open|@tagName#}6341 {#header_open|@tagName#}
6241 <pre>{#syntax#}@tagName(value: var) []const u8{#endsyntax#}</pre>6342 <pre>{#syntax#}@tagName(value: var) []const u8{#endsyntax#}</pre>
6242 <p>6343 <p>
6243 Converts an enum value or union value to a slice of bytes representing the name.6344 Converts an enum value or union value to a slice of bytes representing the name.
6244 </p>6345 </p>
6245 {#header_close#}6346 {#header_close#}
6347
6246 {#header_open|@TagType#}6348 {#header_open|@TagType#}
6247 <pre>{#syntax#}@TagType(T: type) type{#endsyntax#}</pre>6349 <pre>{#syntax#}@TagType(T: type) type{#endsyntax#}</pre>
6248 <p>6350 <p>
...@@ -6252,6 +6354,7 @@ pub const FloatMode = enum {...@@ -6252,6 +6354,7 @@ pub const FloatMode = enum {
6252 For a union, returns the enum type that is used to store the tag value.6354 For a union, returns the enum type that is used to store the tag value.
6253 </p>6355 </p>
6254 {#header_close#}6356 {#header_close#}
6357
6255 {#header_open|@This#}6358 {#header_open|@This#}
6256 <pre>{#syntax#}@This() type{#endsyntax#}</pre>6359 <pre>{#syntax#}@This() type{#endsyntax#}</pre>
6257 <p>6360 <p>
...@@ -6287,15 +6390,16 @@ fn List(comptime T: type) type {...@@ -6287,15 +6390,16 @@ fn List(comptime T: type) type {
6287 <a href="https://github.com/ziglang/zig/issues/1047">#1047</a> for details.6390 <a href="https://github.com/ziglang/zig/issues/1047">#1047</a> for details.
6288 </p>6391 </p>
6289 {#header_close#}6392 {#header_close#}
6393
6290 {#header_open|@truncate#}6394 {#header_open|@truncate#}
6291 <pre>{#syntax#}@truncate(comptime T: type, integer) T{#endsyntax#}</pre>6395 <pre>{#syntax#}@truncate(comptime T: type, integer: var) T{#endsyntax#}</pre>
6292 <p>6396 <p>
6293 This function truncates bits from an integer type, resulting in a smaller6397 This function truncates bits from an integer type, resulting in a smaller
6294 integer type.6398 integer type.
6295 </p>6399 </p>
6296 <p>6400 <p>
6297 The following produces a crash in debug mode and undefined behavior in6401 The following produces a crash in {#link|Debug#} mode and {#link|Undefined Behavior#} in
6298 release mode:6402 {#link|ReleaseFast#} mode:
6299 </p>6403 </p>
6300 <pre>{#syntax#}const a: u16 = 0xabcd;6404 <pre>{#syntax#}const a: u16 = 0xabcd;
6301const b: u8 = u8(a);{#endsyntax#}</pre>6405const b: u8 = u8(a);{#endsyntax#}</pre>
...@@ -6309,8 +6413,12 @@ const b: u8 = @truncate(u8, a);...@@ -6309,8 +6413,12 @@ const b: u8 = @truncate(u8, a);
6309 This function always truncates the significant bits of the integer, regardless6413 This function always truncates the significant bits of the integer, regardless
6310 of endianness on the target platform.6414 of endianness on the target platform.
6311 </p>6415 </p>
63126416 <p>
6417 If {#syntax#}T{#endsyntax#} is {#syntax#}comptime_int{#endsyntax#},
6418 then this is semantically equivalent to an {#link|implicit cast|Implicit Casts#}.
6419 </p>
6313 {#header_close#}6420 {#header_close#}
6421
6314 {#header_open|@typeId#}6422 {#header_open|@typeId#}
6315 <pre>{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}</pre>6423 <pre>{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}</pre>
6316 <p>6424 <p>
...@@ -6345,6 +6453,7 @@ pub const TypeId = enum {...@@ -6345,6 +6453,7 @@ pub const TypeId = enum {
6345};6453};
6346 {#code_end#}6454 {#code_end#}
6347 {#header_close#}6455 {#header_close#}
6456
6348 {#header_open|@typeInfo#}6457 {#header_open|@typeInfo#}
6349 <pre>{#syntax#}@typeInfo(comptime T: type) @import("builtin").TypeInfo{#endsyntax#}</pre>6458 <pre>{#syntax#}@typeInfo(comptime T: type) @import("builtin").TypeInfo{#endsyntax#}</pre>
6350 <p>6459 <p>
...@@ -6527,13 +6636,16 @@ pub const TypeInfo = union(TypeId) {...@@ -6527,13 +6636,16 @@ pub const TypeInfo = union(TypeId) {
6527};6636};
6528 {#code_end#}6637 {#code_end#}
6529 {#header_close#}6638 {#header_close#}
6639
6530 {#header_open|@typeName#}6640 {#header_open|@typeName#}
6531 <pre>{#syntax#}@typeName(T: type) []u8{#endsyntax#}</pre>6641 <pre>{#syntax#}@typeName(T: type) [N]u8{#endsyntax#}</pre>
6532 <p>6642 <p>
6533 This function returns the string representation of a type.6643 This function returns the string representation of a type, as
6644 an array. It is equivalent to a string literal of the type name.
6534 </p>6645 </p>
65356646
6536 {#header_close#}6647 {#header_close#}
6648
6537 {#header_open|@typeOf#}6649 {#header_open|@typeOf#}
6538 <pre>{#syntax#}@typeOf(expression) type{#endsyntax#}</pre>6650 <pre>{#syntax#}@typeOf(expression) type{#endsyntax#}</pre>
6539 <p>6651 <p>
...@@ -6541,8 +6653,20 @@ pub const TypeInfo = union(TypeId) {...@@ -6541,8 +6653,20 @@ pub const TypeInfo = union(TypeId) {
6541 expression passed as an argument. The expression is evaluated.6653 expression passed as an argument. The expression is evaluated.
6542 </p>6654 </p>
65436655
6656 {#header_close#}
6657
6658 {#header_open|@Vector#}
6659 <pre>{#syntax#}@Vector(comptime len: u32, comptime ElemType: type) type{#endsyntax#}</pre>
6660 <p>
6661 This function returns a vector type for {#link|SIMD#}.
6662 </p>
6663 <p>
6664 {#syntax#}ElemType{#endsyntax#} must be an {#link|integer|Integers#}, a {#link|float|Floats#}, or a
6665 {#link|pointer|Pointers#}.
6666 </p>
6544 {#header_close#}6667 {#header_close#}
6545 {#header_close#}6668 {#header_close#}
6669
6546 {#header_open|Build Mode#}6670 {#header_open|Build Mode#}
6547 <p>6671 <p>
6548 Zig has four build modes:6672 Zig has four build modes:
...@@ -6613,6 +6737,25 @@ pub fn build(b: *Builder) void {...@@ -6613,6 +6737,25 @@ pub fn build(b: *Builder) void {
6613 {#header_close#}6737 {#header_close#}
6614 {#see_also|Compile Variables|Zig Build System|Undefined Behavior#}6738 {#see_also|Compile Variables|Zig Build System|Undefined Behavior#}
6615 {#header_close#}6739 {#header_close#}
6740
6741 {#header_open|Single Threaded Builds#}
6742 <p>Zig has a compile option <code>--single-threaded</code> which has the following effects:
6743 <ul>
6744 <li>{#link|@atomicLoad#} is emitted as a normal load.</li>
6745 <li>{#link|@atomicRmw#} is emitted as a normal memory load, modify, store.</li>
6746 <li>{#link|@fence#} becomes a no-op.</li>
6747 <li>Variables which have Thread Local Storage instead become globals. TODO thread local variables
6748 are not implemented yet.</li>
6749 <li>The overhead of {#link|Coroutines#} becomes equivalent to function call overhead.
6750 TODO: please note this will not be implemented until the upcoming Coroutine Rewrite</li>
6751 <li>The {#syntax#}@import("builtin").single_threaded{#endsyntax#} becomes {#syntax#}true{#endsyntax#}
6752 and therefore various userland APIs which read this variable become more efficient.
6753 For example {#syntax#}std.Mutex{#endsyntax#} becomes
6754 an empty data structure and all of its functions become no-ops.</li>
6755 </ul>
6756 </p>
6757 {#header_close#}
6758
6616 {#header_open|Undefined Behavior#}6759 {#header_open|Undefined Behavior#}
6617 <p>6760 <p>
6618 Zig has many instances of undefined behavior. If undefined behavior is6761 Zig has many instances of undefined behavior. If undefined behavior is
...@@ -7213,10 +7356,27 @@ fn bar(f: *Foo) void {...@@ -7213,10 +7356,27 @@ fn bar(f: *Foo) void {
7213 {#code_end#}7356 {#code_end#}
7214 {#header_close#}7357 {#header_close#}
72157358
7216 {#header_open|Out of Bounds Float To Integer Cast#}7359 {#header_open|Out of Bounds Float to Integer Cast#}
7217 <p>TODO</p>7360 <p>TODO</p>
7218 {#header_close#}7361 {#header_close#}
72197362
7363 {#header_open|Pointer Cast Invalid Null#}
7364 <p>At compile-time:</p>
7365 {#code_begin|test_err|null pointer casted to type#}
7366comptime {
7367 const opt_ptr: ?*i32 = null;
7368 const ptr = @ptrCast(*i32, opt_ptr);
7369}
7370 {#code_end#}
7371 <p>At runtime:</p>
7372 {#code_begin|exe_err#}
7373pub fn main() void {
7374 var opt_ptr: ?*i32 = null;
7375 var ptr = @ptrCast(*i32, opt_ptr);
7376}
7377 {#code_end#}
7378 {#header_close#}
7379
7220 {#header_close#}7380 {#header_close#}
7221 {#header_open|Memory#}7381 {#header_open|Memory#}
7222 <p>TODO: explain no default allocator in zig</p>7382 <p>TODO: explain no default allocator in zig</p>
...@@ -7307,6 +7467,7 @@ pub fn main() void {...@@ -7307,6 +7467,7 @@ pub fn main() void {
7307 {#code_end#}7467 {#code_end#}
7308 {#see_also|String Literals#}7468 {#see_also|String Literals#}
7309 {#header_close#}7469 {#header_close#}
7470
7310 {#header_open|Import from C Header File#}7471 {#header_open|Import from C Header File#}
7311 <p>7472 <p>
7312 The {#syntax#}@cImport{#endsyntax#} builtin function can be used7473 The {#syntax#}@cImport{#endsyntax#} builtin function can be used
...@@ -7345,6 +7506,36 @@ const c = @cImport({...@@ -7345,6 +7506,36 @@ const c = @cImport({
7345 {#code_end#}7506 {#code_end#}
7346 {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#}7507 {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#}
7347 {#header_close#}7508 {#header_close#}
7509
7510 {#header_open|C Pointers#}
7511 <p>
7512 This type is to be avoided whenever possible. The only valid reason for using a C pointer is in
7513 auto-generated code from translating C code.
7514 </p>
7515 <p>
7516 When importing C header files, it is ambiguous whether pointers should be translated as
7517 single-item pointers ({#syntax#}*T{#endsyntax#}) or unknown-length pointers ({#syntax#}[*]T{#endsyntax#}).
7518 C pointers are a compromise so that Zig code can utilize translated header files directly.
7519 </p>
7520 <p>{#syntax#}[*c]T{#endsyntax#} - C pointer.</p>
7521 <ul>
7522 <li>Supports all the syntax of the other two pointer types.</li>
7523 <li>Implicitly casts to other pointer types, as well as {#link|Optional Pointers#}.
7524 When a C pointer is implicitly casted to a non-optional pointer, safety-checked
7525 {#link|Undefined Behavior#} occurs if the address is 0.
7526 </li>
7527 <li>Allows address 0. On non-freestanding targets, dereferencing address 0 is safety-checked
7528 {#link|Undefined Behavior#}. Optional C pointers introduce another bit to keep track of
7529 null, just like {#syntax#}?usize{#endsyntax#}. Note that creating an optional C pointer
7530 is unnecessary as one can use normal {#link|Optional Pointers#}.
7531 </li>
7532 <li>Supports {#link|implicit casting|Implicit Casts#} to and from integers.</li>
7533 <li>Supports comparison with integers.</li>
7534 <li>Does not support Zig-only pointer attributes such as alignment. Use normal {#link|Pointers#}
7535 please!</li>
7536 </ul>
7537 {#header_close#}
7538
7348 {#header_open|Exporting a C Library#}7539 {#header_open|Exporting a C Library#}
7349 <p>7540 <p>
7350 One of the primary use cases for Zig is exporting a library with the C ABI for other programming languages7541 One of the primary use cases for Zig is exporting a library with the C ABI for other programming languages
...@@ -7741,7 +7932,7 @@ TopLevelComptime &lt;- KEYWORD_comptime BlockExpr...@@ -7741,7 +7932,7 @@ TopLevelComptime &lt;- KEYWORD_comptime BlockExpr
77417932
7742TopLevelDecl7933TopLevelDecl
7743 &lt;- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block)7934 &lt;- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block)
7744 / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? VarDecl7935 / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
7745 / KEYWORD_use Expr SEMICOLON7936 / KEYWORD_use Expr SEMICOLON
77467937
7747FnProto &lt;- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)7938FnProto &lt;- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
...@@ -8032,7 +8223,8 @@ ArrayTypeStart &lt;- LBRACKET Expr? RBRACKET...@@ -8032,7 +8223,8 @@ ArrayTypeStart &lt;- LBRACKET Expr? RBRACKET
8032PtrTypeStart8223PtrTypeStart
8033 &lt;- ASTERISK8224 &lt;- ASTERISK
8034 / ASTERISK28225 / ASTERISK2
8035 / LBRACKET ASTERISK RBRACKET8226 / PTRUNKNOWN
8227 / PTRC
80368228
8037# ContainerDecl specific8229# ContainerDecl specific
8038ContainerDeclAuto &lt;- ContainerDeclType LBRACE ContainerMembers RBRACE8230ContainerDeclAuto &lt;- ContainerDeclType LBRACE ContainerMembers RBRACE
...@@ -8130,7 +8322,7 @@ LARROW2 &lt;- '&lt;&lt;' ![=] skip...@@ -8130,7 +8322,7 @@ LARROW2 &lt;- '&lt;&lt;' ![=] skip
8130LARROW2EQUAL &lt;- '&lt;&lt;=' skip8322LARROW2EQUAL &lt;- '&lt;&lt;=' skip
8131LARROWEQUAL &lt;- '&lt;=' skip8323LARROWEQUAL &lt;- '&lt;=' skip
8132LBRACE &lt;- '{' skip8324LBRACE &lt;- '{' skip
8133LBRACKET &lt;- '[' skip8325LBRACKET &lt;- '[' ![*] skip
8134LPAREN &lt;- '(' skip8326LPAREN &lt;- '(' skip
8135MINUS &lt;- '-' ![%=&gt;] skip8327MINUS &lt;- '-' ![%=&gt;] skip
8136MINUSEQUAL &lt;- '-=' skip8328MINUSEQUAL &lt;- '-=' skip
...@@ -8147,6 +8339,8 @@ PLUS2 &lt;- '++' skip...@@ -8147,6 +8339,8 @@ PLUS2 &lt;- '++' skip
8147PLUSEQUAL &lt;- '+=' skip8339PLUSEQUAL &lt;- '+=' skip
8148PLUSPERCENT &lt;- '+%' ![=] skip8340PLUSPERCENT &lt;- '+%' ![=] skip
8149PLUSPERCENTEQUAL &lt;- '+%=' skip8341PLUSPERCENTEQUAL &lt;- '+%=' skip
8342PTRC &lt;- '[*c]' skip
8343PTRUNKNOWN &lt;- '[*]' skip
8150QUESTIONMARK &lt;- '?' skip8344QUESTIONMARK &lt;- '?' skip
8151RARROW &lt;- '&gt;' ![&gt;=] skip8345RARROW &lt;- '&gt;' ![&gt;=] skip
8152RARROW2 &lt;- '&gt;&gt;' ![=] skip8346RARROW2 &lt;- '&gt;&gt;' ![=] skip
...@@ -8201,6 +8395,7 @@ KEYWORD_struct &lt;- 'struct' end_of_word...@@ -8201,6 +8395,7 @@ KEYWORD_struct &lt;- 'struct' end_of_word
8201KEYWORD_suspend &lt;- 'suspend' end_of_word8395KEYWORD_suspend &lt;- 'suspend' end_of_word
8202KEYWORD_switch &lt;- 'switch' end_of_word8396KEYWORD_switch &lt;- 'switch' end_of_word
8203KEYWORD_test &lt;- 'test' end_of_word8397KEYWORD_test &lt;- 'test' end_of_word
8398KEYWORD_threadlocal &lt;- 'threadlocal' end_of_word
8204KEYWORD_true &lt;- 'true' end_of_word8399KEYWORD_true &lt;- 'true' end_of_word
8205KEYWORD_try &lt;- 'try' end_of_word8400KEYWORD_try &lt;- 'try' end_of_word
8206KEYWORD_undefined &lt;- 'undefined' end_of_word8401KEYWORD_undefined &lt;- 'undefined' end_of_word
...@@ -8221,7 +8416,7 @@ keyword &lt;- KEYWORD_align / KEYWORD_and / KEYWORD_anyerror / KEYWORD_asm...@@ -8221,7 +8416,7 @@ keyword &lt;- KEYWORD_align / KEYWORD_and / KEYWORD_anyerror / KEYWORD_asm
8221 / KEYWORD_orelse / KEYWORD_packed / KEYWORD_promise / KEYWORD_pub8416 / KEYWORD_orelse / KEYWORD_packed / KEYWORD_promise / KEYWORD_pub
8222 / KEYWORD_resume / KEYWORD_return / KEYWORD_linksection8417 / KEYWORD_resume / KEYWORD_return / KEYWORD_linksection
8223 / KEYWORD_stdcallcc / KEYWORD_struct / KEYWORD_suspend8418 / KEYWORD_stdcallcc / KEYWORD_struct / KEYWORD_suspend
8224 / KEYWORD_switch / KEYWORD_test / KEYWORD_true / KEYWORD_try8419 / KEYWORD_switch / KEYWORD_test / KEYWORD_threadlocal / KEYWORD_true / KEYWORD_try
8225 / KEYWORD_undefined / KEYWORD_union / KEYWORD_unreachable8420 / KEYWORD_undefined / KEYWORD_union / KEYWORD_unreachable
8226 / KEYWORD_use / KEYWORD_var / KEYWORD_volatile / KEYWORD_while</code></pre>8421 / KEYWORD_use / KEYWORD_var / KEYWORD_volatile / KEYWORD_while</code></pre>
8227 {#header_close#}8422 {#header_close#}
doc/targets.md deleted-15
...@@ -1,15 +0,0 @@
1# How to Add Support For More Targets
2
3Create bootstrap code in std/bootstrap.zig and add conditional compilation
4logic. This code is responsible for the real executable entry point, calling
5main() and making the exit syscall when main returns.
6
7How to pass a byvalue struct parameter in the C calling convention is
8target-specific. Add logic for how to do function prototypes and function calls
9for the target when an exported or external function has a byvalue struct.
10
11Write the target-specific code in the standard library.
12
13Update the C integer types to be the correct size for the target.
14
15Make sure that `c_longdouble` codegens the correct floating point value.
example/guess_number/main.zig+1-1
...@@ -15,7 +15,7 @@ pub fn main() !void {...@@ -15,7 +15,7 @@ pub fn main() !void {
15 std.debug.warn("unable to seed random number generator: {}", err);15 std.debug.warn("unable to seed random number generator: {}", err);
16 return err;16 return err;
17 };17 };
18 const seed = std.mem.readInt(seed_bytes, u64, builtin.Endian.Big);18 const seed = std.mem.readIntNative(u64, &seed_bytes);
19 var prng = std.rand.DefaultPrng.init(seed);19 var prng = std.rand.DefaultPrng.init(seed);
2020
21 const answer = prng.random.range(u8, 0, 100) + 1;21 const answer = prng.random.range(u8, 0, 100) + 1;
example/hello_world/hello.zig+1-1
...@@ -2,7 +2,7 @@ const std = @import("std");...@@ -2,7 +2,7 @@ const std = @import("std");
22
3pub fn main() !void {3pub fn main() !void {
4 // If this program is run without stdout attached, exit with an error.4 // If this program is run without stdout attached, exit with an error.
5 var stdout_file = try std.io.getStdOut();5 const stdout_file = try std.io.getStdOut();
6 // If this program encounters pipe failure when printing to stdout, exit6 // If this program encounters pipe failure when printing to stdout, exit
7 // with an error.7 // with an error.
8 try stdout_file.write("Hello, world!\n");8 try stdout_file.write("Hello, world!\n");
src-self-hosted/arg.zig+12-11
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const debug = std.debug;2const debug = std.debug;
3const testing = std.testing;
3const mem = std.mem;4const mem = std.mem;
45
5const Allocator = mem.Allocator;6const Allocator = mem.Allocator;
...@@ -272,21 +273,21 @@ test "parse arguments" {...@@ -272,21 +273,21 @@ test "parse arguments" {
272273
273 var args = try Args.parse(std.debug.global_allocator, spec1, cliargs);274 var args = try Args.parse(std.debug.global_allocator, spec1, cliargs);
274275
275 debug.assert(args.present("help"));276 testing.expect(args.present("help"));
276 debug.assert(!args.present("help2"));277 testing.expect(!args.present("help2"));
277 debug.assert(!args.present("init"));278 testing.expect(!args.present("init"));
278279
279 debug.assert(mem.eql(u8, args.single("build-file").?, "build.zig"));280 testing.expect(mem.eql(u8, args.single("build-file").?, "build.zig"));
280 debug.assert(mem.eql(u8, args.single("color").?, "on"));281 testing.expect(mem.eql(u8, args.single("color").?, "on"));
281282
282 const objects = args.many("object").?;283 const objects = args.many("object").?;
283 debug.assert(mem.eql(u8, objects[0], "obj1"));284 testing.expect(mem.eql(u8, objects[0], "obj1"));
284 debug.assert(mem.eql(u8, objects[1], "obj2"));285 testing.expect(mem.eql(u8, objects[1], "obj2"));
285286
286 debug.assert(mem.eql(u8, args.single("library").?, "lib2"));287 testing.expect(mem.eql(u8, args.single("library").?, "lib2"));
287288
288 const pos = args.positionals.toSliceConst();289 const pos = args.positionals.toSliceConst();
289 debug.assert(mem.eql(u8, pos[0], "build"));290 testing.expect(mem.eql(u8, pos[0], "build"));
290 debug.assert(mem.eql(u8, pos[1], "pos1"));291 testing.expect(mem.eql(u8, pos[1], "pos1"));
291 debug.assert(mem.eql(u8, pos[2], "pos2"));292 testing.expect(mem.eql(u8, pos[2], "pos2"));
292}293}
src-self-hosted/codegen.zig+21-21
...@@ -137,10 +137,10 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)...@@ -137,10 +137,10 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
137137
138pub const ObjectFile = struct {138pub const ObjectFile = struct {
139 comp: *Compilation,139 comp: *Compilation,
140 module: llvm.ModuleRef,140 module: *llvm.Module,
141 builder: llvm.BuilderRef,141 builder: *llvm.Builder,
142 dibuilder: *llvm.DIBuilder,142 dibuilder: *llvm.DIBuilder,
143 context: llvm.ContextRef,143 context: *llvm.Context,
144 lock: event.Lock,144 lock: event.Lock,
145 arena: *std.mem.Allocator,145 arena: *std.mem.Allocator,
146146
...@@ -323,7 +323,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)...@@ -323,7 +323,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
323323
324fn addLLVMAttr(324fn addLLVMAttr(
325 ofile: *ObjectFile,325 ofile: *ObjectFile,
326 val: llvm.ValueRef,326 val: *llvm.Value,
327 attr_index: llvm.AttributeIndex,327 attr_index: llvm.AttributeIndex,
328 attr_name: []const u8,328 attr_name: []const u8,
329) !void {329) !void {
...@@ -335,7 +335,7 @@ fn addLLVMAttr(...@@ -335,7 +335,7 @@ fn addLLVMAttr(
335335
336fn addLLVMAttrStr(336fn addLLVMAttrStr(
337 ofile: *ObjectFile,337 ofile: *ObjectFile,
338 val: llvm.ValueRef,338 val: *llvm.Value,
339 attr_index: llvm.AttributeIndex,339 attr_index: llvm.AttributeIndex,
340 attr_name: []const u8,340 attr_name: []const u8,
341 attr_val: []const u8,341 attr_val: []const u8,
...@@ -351,7 +351,7 @@ fn addLLVMAttrStr(...@@ -351,7 +351,7 @@ fn addLLVMAttrStr(
351}351}
352352
353fn addLLVMAttrInt(353fn addLLVMAttrInt(
354 val: llvm.ValueRef,354 val: *llvm.Value,
355 attr_index: llvm.AttributeIndex,355 attr_index: llvm.AttributeIndex,
356 attr_name: []const u8,356 attr_name: []const u8,
357 attr_val: u64,357 attr_val: u64,
...@@ -362,25 +362,25 @@ fn addLLVMAttrInt(...@@ -362,25 +362,25 @@ fn addLLVMAttrInt(
362 llvm.AddAttributeAtIndex(val, attr_index, llvm_attr);362 llvm.AddAttributeAtIndex(val, attr_index, llvm_attr);
363}363}
364364
365fn addLLVMFnAttr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8) !void {365fn addLLVMFnAttr(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8) !void {
366 return addLLVMAttr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name);366 return addLLVMAttr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name);
367}367}
368368
369fn addLLVMFnAttrStr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8, attr_val: []const u8) !void {369fn addLLVMFnAttrStr(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8, attr_val: []const u8) !void {
370 return addLLVMAttrStr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);370 return addLLVMAttrStr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);
371}371}
372372
373fn addLLVMFnAttrInt(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8, attr_val: u64) !void {373fn addLLVMFnAttrInt(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8, attr_val: u64) !void {
374 return addLLVMAttrInt(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);374 return addLLVMAttrInt(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);
375}375}
376376
377fn renderLoadUntyped(377fn renderLoadUntyped(
378 ofile: *ObjectFile,378 ofile: *ObjectFile,
379 ptr: llvm.ValueRef,379 ptr: *llvm.Value,
380 alignment: Type.Pointer.Align,380 alignment: Type.Pointer.Align,
381 vol: Type.Pointer.Vol,381 vol: Type.Pointer.Vol,
382 name: [*]const u8,382 name: [*]const u8,
383) !llvm.ValueRef {383) !*llvm.Value {
384 const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;384 const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;
385 switch (vol) {385 switch (vol) {
386 Type.Pointer.Vol.Non => {},386 Type.Pointer.Vol.Non => {},
...@@ -390,11 +390,11 @@ fn renderLoadUntyped(...@@ -390,11 +390,11 @@ fn renderLoadUntyped(
390 return result;390 return result;
391}391}
392392
393fn renderLoad(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Pointer, name: [*]const u8) !llvm.ValueRef {393fn renderLoad(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer, name: [*]const u8) !*llvm.Value {
394 return renderLoadUntyped(ofile, ptr, ptr_type.key.alignment, ptr_type.key.vol, name);394 return renderLoadUntyped(ofile, ptr, ptr_type.key.alignment, ptr_type.key.vol, name);
395}395}
396396
397pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Pointer) !?llvm.ValueRef {397pub fn getHandleValue(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer) !?*llvm.Value {
398 const child_type = ptr_type.key.child_type;398 const child_type = ptr_type.key.child_type;
399 if (!child_type.hasBits()) {399 if (!child_type.hasBits()) {
400 return null;400 return null;
...@@ -407,11 +407,11 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Po...@@ -407,11 +407,11 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Po
407407
408pub fn renderStoreUntyped(408pub fn renderStoreUntyped(
409 ofile: *ObjectFile,409 ofile: *ObjectFile,
410 value: llvm.ValueRef,410 value: *llvm.Value,
411 ptr: llvm.ValueRef,411 ptr: *llvm.Value,
412 alignment: Type.Pointer.Align,412 alignment: Type.Pointer.Align,
413 vol: Type.Pointer.Vol,413 vol: Type.Pointer.Vol,
414) !llvm.ValueRef {414) !*llvm.Value {
415 const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory;415 const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory;
416 switch (vol) {416 switch (vol) {
417 Type.Pointer.Vol.Non => {},417 Type.Pointer.Vol.Non => {},
...@@ -423,10 +423,10 @@ pub fn renderStoreUntyped(...@@ -423,10 +423,10 @@ pub fn renderStoreUntyped(
423423
424pub fn renderStore(424pub fn renderStore(
425 ofile: *ObjectFile,425 ofile: *ObjectFile,
426 value: llvm.ValueRef,426 value: *llvm.Value,
427 ptr: llvm.ValueRef,427 ptr: *llvm.Value,
428 ptr_type: *Type.Pointer,428 ptr_type: *Type.Pointer,
429) !llvm.ValueRef {429) !*llvm.Value {
430 return renderStoreUntyped(ofile, value, ptr, ptr_type.key.alignment, ptr_type.key.vol);430 return renderStoreUntyped(ofile, value, ptr, ptr_type.key.alignment, ptr_type.key.vol);
431}431}
432432
...@@ -435,7 +435,7 @@ pub fn renderAlloca(...@@ -435,7 +435,7 @@ pub fn renderAlloca(
435 var_type: *Type,435 var_type: *Type,
436 name: []const u8,436 name: []const u8,
437 alignment: Type.Pointer.Align,437 alignment: Type.Pointer.Align,
438) !llvm.ValueRef {438) !*llvm.Value {
439 const llvm_var_type = try var_type.getLlvmType(ofile.arena, ofile.context);439 const llvm_var_type = try var_type.getLlvmType(ofile.arena, ofile.context);
440 const name_with_null = try std.cstr.addNullByte(ofile.arena, name);440 const name_with_null = try std.cstr.addNullByte(ofile.arena, name);
441 const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, name_with_null.ptr) orelse return error.OutOfMemory;441 const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, name_with_null.ptr) orelse return error.OutOfMemory;
...@@ -443,7 +443,7 @@ pub fn renderAlloca(...@@ -443,7 +443,7 @@ pub fn renderAlloca(
443 return result;443 return result;
444}444}
445445
446pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: llvm.TypeRef) u32 {446pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: *llvm.Type) u32 {
447 return switch (alignment) {447 return switch (alignment) {
448 Type.Pointer.Align.Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type),448 Type.Pointer.Align.Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type),
449 Type.Pointer.Align.Override => |a| a,449 Type.Pointer.Align.Override => |a| a,
src-self-hosted/compilation.zig+57-42
...@@ -37,7 +37,7 @@ const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB...@@ -37,7 +37,7 @@ const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
37/// Data that is local to the event loop.37/// Data that is local to the event loop.
38pub const ZigCompiler = struct {38pub const ZigCompiler = struct {
39 loop: *event.Loop,39 loop: *event.Loop,
40 llvm_handle_pool: std.atomic.Stack(llvm.ContextRef),40 llvm_handle_pool: std.atomic.Stack(*llvm.Context),
41 lld_lock: event.Lock,41 lld_lock: event.Lock,
4242
43 /// TODO pool these so that it doesn't have to lock43 /// TODO pool these so that it doesn't have to lock
...@@ -55,12 +55,12 @@ pub const ZigCompiler = struct {...@@ -55,12 +55,12 @@ pub const ZigCompiler = struct {
5555
56 var seed_bytes: [@sizeOf(u64)]u8 = undefined;56 var seed_bytes: [@sizeOf(u64)]u8 = undefined;
57 try std.os.getRandomBytes(seed_bytes[0..]);57 try std.os.getRandomBytes(seed_bytes[0..]);
58 const seed = std.mem.readInt(seed_bytes, u64, builtin.Endian.Big);58 const seed = mem.readIntNative(u64, &seed_bytes);
5959
60 return ZigCompiler{60 return ZigCompiler{
61 .loop = loop,61 .loop = loop,
62 .lld_lock = event.Lock.init(loop),62 .lld_lock = event.Lock.init(loop),
63 .llvm_handle_pool = std.atomic.Stack(llvm.ContextRef).init(),63 .llvm_handle_pool = std.atomic.Stack(*llvm.Context).init(),
64 .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)),64 .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)),
65 .native_libc = event.Future(LibCInstallation).init(loop),65 .native_libc = event.Future(LibCInstallation).init(loop),
66 };66 };
...@@ -70,7 +70,7 @@ pub const ZigCompiler = struct {...@@ -70,7 +70,7 @@ pub const ZigCompiler = struct {
70 fn deinit(self: *ZigCompiler) void {70 fn deinit(self: *ZigCompiler) void {
71 self.lld_lock.deinit();71 self.lld_lock.deinit();
72 while (self.llvm_handle_pool.pop()) |node| {72 while (self.llvm_handle_pool.pop()) |node| {
73 c.LLVMContextDispose(node.data);73 llvm.ContextDispose(node.data);
74 self.loop.allocator.destroy(node);74 self.loop.allocator.destroy(node);
75 }75 }
76 }76 }
...@@ -80,13 +80,14 @@ pub const ZigCompiler = struct {...@@ -80,13 +80,14 @@ pub const ZigCompiler = struct {
80 pub fn getAnyLlvmContext(self: *ZigCompiler) !LlvmHandle {80 pub fn getAnyLlvmContext(self: *ZigCompiler) !LlvmHandle {
81 if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node };81 if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node };
8282
83 const context_ref = c.LLVMContextCreate() orelse return error.OutOfMemory;83 const context_ref = llvm.ContextCreate() orelse return error.OutOfMemory;
84 errdefer c.LLVMContextDispose(context_ref);84 errdefer llvm.ContextDispose(context_ref);
8585
86 const node = try self.loop.allocator.create(std.atomic.Stack(llvm.ContextRef).Node{86 const node = try self.loop.allocator.create(std.atomic.Stack(*llvm.Context).Node);
87 node.* = std.atomic.Stack(*llvm.Context).Node{
87 .next = undefined,88 .next = undefined,
88 .data = context_ref,89 .data = context_ref,
89 });90 };
90 errdefer self.loop.allocator.destroy(node);91 errdefer self.loop.allocator.destroy(node);
9192
92 return LlvmHandle{ .node = node };93 return LlvmHandle{ .node = node };
...@@ -113,7 +114,7 @@ pub const ZigCompiler = struct {...@@ -113,7 +114,7 @@ pub const ZigCompiler = struct {
113};114};
114115
115pub const LlvmHandle = struct {116pub const LlvmHandle = struct {
116 node: *std.atomic.Stack(llvm.ContextRef).Node,117 node: *std.atomic.Stack(*llvm.Context).Node,
117118
118 pub fn release(self: LlvmHandle, zig_compiler: *ZigCompiler) void {119 pub fn release(self: LlvmHandle, zig_compiler: *ZigCompiler) void {
119 zig_compiler.llvm_handle_pool.push(self.node);120 zig_compiler.llvm_handle_pool.push(self.node);
...@@ -127,7 +128,7 @@ pub const Compilation = struct {...@@ -127,7 +128,7 @@ pub const Compilation = struct {
127 llvm_triple: Buffer,128 llvm_triple: Buffer,
128 root_src_path: ?[]const u8,129 root_src_path: ?[]const u8,
129 target: Target,130 target: Target,
130 llvm_target: llvm.TargetRef,131 llvm_target: *llvm.Target,
131 build_mode: builtin.Mode,132 build_mode: builtin.Mode,
132 zig_lib_dir: []const u8,133 zig_lib_dir: []const u8,
133 zig_std_dir: []const u8,134 zig_std_dir: []const u8,
...@@ -211,8 +212,8 @@ pub const Compilation = struct {...@@ -211,8 +212,8 @@ pub const Compilation = struct {
211 false_value: *Value.Bool,212 false_value: *Value.Bool,
212 noreturn_value: *Value.NoReturn,213 noreturn_value: *Value.NoReturn,
213214
214 target_machine: llvm.TargetMachineRef,215 target_machine: *llvm.TargetMachine,
215 target_data_ref: llvm.TargetDataRef,216 target_data_ref: *llvm.TargetData,
216 target_layout_str: [*]u8,217 target_layout_str: [*]u8,
217 target_ptr_bits: u32,218 target_ptr_bits: u32,
218219
...@@ -300,6 +301,7 @@ pub const Compilation = struct {...@@ -300,6 +301,7 @@ pub const Compilation = struct {
300 UserResourceLimitReached,301 UserResourceLimitReached,
301 InvalidUtf8,302 InvalidUtf8,
302 BadPathName,303 BadPathName,
304 DeviceBusy,
303 };305 };
304306
305 pub const Event = union(enum) {307 pub const Event = union(enum) {
...@@ -485,7 +487,7 @@ pub const Compilation = struct {...@@ -485,7 +487,7 @@ pub const Compilation = struct {
485 comp.name = try Buffer.init(comp.arena(), name);487 comp.name = try Buffer.init(comp.arena(), name);
486 comp.llvm_triple = try target.getTriple(comp.arena());488 comp.llvm_triple = try target.getTriple(comp.arena());
487 comp.llvm_target = try Target.llvmTargetFromTriple(comp.llvm_triple);489 comp.llvm_target = try Target.llvmTargetFromTriple(comp.llvm_triple);
488 comp.zig_std_dir = try std.os.path.join(comp.arena(), zig_lib_dir, "std");490 comp.zig_std_dir = try std.os.path.join(comp.arena(), [][]const u8{ zig_lib_dir, "std" });
489491
490 const opt_level = switch (build_mode) {492 const opt_level = switch (build_mode) {
491 builtin.Mode.Debug => llvm.CodeGenLevelNone,493 builtin.Mode.Debug => llvm.CodeGenLevelNone,
...@@ -595,7 +597,8 @@ pub const Compilation = struct {...@@ -595,7 +597,8 @@ pub const Compilation = struct {
595 }597 }
596598
597 fn initTypes(comp: *Compilation) !void {599 fn initTypes(comp: *Compilation) !void {
598 comp.meta_type = try comp.arena().create(Type.MetaType{600 comp.meta_type = try comp.arena().create(Type.MetaType);
601 comp.meta_type.* = Type.MetaType{
599 .base = Type{602 .base = Type{
600 .name = "type",603 .name = "type",
601 .base = Value{604 .base = Value{
...@@ -607,12 +610,13 @@ pub const Compilation = struct {...@@ -607,12 +610,13 @@ pub const Compilation = struct {
607 .abi_alignment = Type.AbiAlignment.init(comp.loop),610 .abi_alignment = Type.AbiAlignment.init(comp.loop),
608 },611 },
609 .value = undefined,612 .value = undefined,
610 });613 };
611 comp.meta_type.value = &comp.meta_type.base;614 comp.meta_type.value = &comp.meta_type.base;
612 comp.meta_type.base.base.typ = &comp.meta_type.base;615 comp.meta_type.base.base.typ = &comp.meta_type.base;
613 assert((try comp.primitive_type_table.put(comp.meta_type.base.name, &comp.meta_type.base)) == null);616 assert((try comp.primitive_type_table.put(comp.meta_type.base.name, &comp.meta_type.base)) == null);
614617
615 comp.void_type = try comp.arena().create(Type.Void{618 comp.void_type = try comp.arena().create(Type.Void);
619 comp.void_type.* = Type.Void{
616 .base = Type{620 .base = Type{
617 .name = "void",621 .name = "void",
618 .base = Value{622 .base = Value{
...@@ -623,10 +627,11 @@ pub const Compilation = struct {...@@ -623,10 +627,11 @@ pub const Compilation = struct {
623 .id = builtin.TypeId.Void,627 .id = builtin.TypeId.Void,
624 .abi_alignment = Type.AbiAlignment.init(comp.loop),628 .abi_alignment = Type.AbiAlignment.init(comp.loop),
625 },629 },
626 });630 };
627 assert((try comp.primitive_type_table.put(comp.void_type.base.name, &comp.void_type.base)) == null);631 assert((try comp.primitive_type_table.put(comp.void_type.base.name, &comp.void_type.base)) == null);
628632
629 comp.noreturn_type = try comp.arena().create(Type.NoReturn{633 comp.noreturn_type = try comp.arena().create(Type.NoReturn);
634 comp.noreturn_type.* = Type.NoReturn{
630 .base = Type{635 .base = Type{
631 .name = "noreturn",636 .name = "noreturn",
632 .base = Value{637 .base = Value{
...@@ -637,10 +642,11 @@ pub const Compilation = struct {...@@ -637,10 +642,11 @@ pub const Compilation = struct {
637 .id = builtin.TypeId.NoReturn,642 .id = builtin.TypeId.NoReturn,
638 .abi_alignment = Type.AbiAlignment.init(comp.loop),643 .abi_alignment = Type.AbiAlignment.init(comp.loop),
639 },644 },
640 });645 };
641 assert((try comp.primitive_type_table.put(comp.noreturn_type.base.name, &comp.noreturn_type.base)) == null);646 assert((try comp.primitive_type_table.put(comp.noreturn_type.base.name, &comp.noreturn_type.base)) == null);
642647
643 comp.comptime_int_type = try comp.arena().create(Type.ComptimeInt{648 comp.comptime_int_type = try comp.arena().create(Type.ComptimeInt);
649 comp.comptime_int_type.* = Type.ComptimeInt{
644 .base = Type{650 .base = Type{
645 .name = "comptime_int",651 .name = "comptime_int",
646 .base = Value{652 .base = Value{
...@@ -651,10 +657,11 @@ pub const Compilation = struct {...@@ -651,10 +657,11 @@ pub const Compilation = struct {
651 .id = builtin.TypeId.ComptimeInt,657 .id = builtin.TypeId.ComptimeInt,
652 .abi_alignment = Type.AbiAlignment.init(comp.loop),658 .abi_alignment = Type.AbiAlignment.init(comp.loop),
653 },659 },
654 });660 };
655 assert((try comp.primitive_type_table.put(comp.comptime_int_type.base.name, &comp.comptime_int_type.base)) == null);661 assert((try comp.primitive_type_table.put(comp.comptime_int_type.base.name, &comp.comptime_int_type.base)) == null);
656662
657 comp.bool_type = try comp.arena().create(Type.Bool{663 comp.bool_type = try comp.arena().create(Type.Bool);
664 comp.bool_type.* = Type.Bool{
658 .base = Type{665 .base = Type{
659 .name = "bool",666 .name = "bool",
660 .base = Value{667 .base = Value{
...@@ -665,45 +672,50 @@ pub const Compilation = struct {...@@ -665,45 +672,50 @@ pub const Compilation = struct {
665 .id = builtin.TypeId.Bool,672 .id = builtin.TypeId.Bool,
666 .abi_alignment = Type.AbiAlignment.init(comp.loop),673 .abi_alignment = Type.AbiAlignment.init(comp.loop),
667 },674 },
668 });675 };
669 assert((try comp.primitive_type_table.put(comp.bool_type.base.name, &comp.bool_type.base)) == null);676 assert((try comp.primitive_type_table.put(comp.bool_type.base.name, &comp.bool_type.base)) == null);
670677
671 comp.void_value = try comp.arena().create(Value.Void{678 comp.void_value = try comp.arena().create(Value.Void);
679 comp.void_value.* = Value.Void{
672 .base = Value{680 .base = Value{
673 .id = Value.Id.Void,681 .id = Value.Id.Void,
674 .typ = &Type.Void.get(comp).base,682 .typ = &Type.Void.get(comp).base,
675 .ref_count = std.atomic.Int(usize).init(1),683 .ref_count = std.atomic.Int(usize).init(1),
676 },684 },
677 });685 };
678686
679 comp.true_value = try comp.arena().create(Value.Bool{687 comp.true_value = try comp.arena().create(Value.Bool);
688 comp.true_value.* = Value.Bool{
680 .base = Value{689 .base = Value{
681 .id = Value.Id.Bool,690 .id = Value.Id.Bool,
682 .typ = &Type.Bool.get(comp).base,691 .typ = &Type.Bool.get(comp).base,
683 .ref_count = std.atomic.Int(usize).init(1),692 .ref_count = std.atomic.Int(usize).init(1),
684 },693 },
685 .x = true,694 .x = true,
686 });695 };
687696
688 comp.false_value = try comp.arena().create(Value.Bool{697 comp.false_value = try comp.arena().create(Value.Bool);
698 comp.false_value.* = Value.Bool{
689 .base = Value{699 .base = Value{
690 .id = Value.Id.Bool,700 .id = Value.Id.Bool,
691 .typ = &Type.Bool.get(comp).base,701 .typ = &Type.Bool.get(comp).base,
692 .ref_count = std.atomic.Int(usize).init(1),702 .ref_count = std.atomic.Int(usize).init(1),
693 },703 },
694 .x = false,704 .x = false,
695 });705 };
696706
697 comp.noreturn_value = try comp.arena().create(Value.NoReturn{707 comp.noreturn_value = try comp.arena().create(Value.NoReturn);
708 comp.noreturn_value.* = Value.NoReturn{
698 .base = Value{709 .base = Value{
699 .id = Value.Id.NoReturn,710 .id = Value.Id.NoReturn,
700 .typ = &Type.NoReturn.get(comp).base,711 .typ = &Type.NoReturn.get(comp).base,
701 .ref_count = std.atomic.Int(usize).init(1),712 .ref_count = std.atomic.Int(usize).init(1),
702 },713 },
703 });714 };
704715
705 for (CInt.list) |cint, i| {716 for (CInt.list) |cint, i| {
706 const c_int_type = try comp.arena().create(Type.Int{717 const c_int_type = try comp.arena().create(Type.Int);
718 c_int_type.* = Type.Int{
707 .base = Type{719 .base = Type{
708 .name = cint.zig_name,720 .name = cint.zig_name,
709 .base = Value{721 .base = Value{
...@@ -719,11 +731,12 @@ pub const Compilation = struct {...@@ -719,11 +731,12 @@ pub const Compilation = struct {
719 .bit_count = comp.target.cIntTypeSizeInBits(cint.id),731 .bit_count = comp.target.cIntTypeSizeInBits(cint.id),
720 },732 },
721 .garbage_node = undefined,733 .garbage_node = undefined,
722 });734 };
723 comp.c_int_types[i] = c_int_type;735 comp.c_int_types[i] = c_int_type;
724 assert((try comp.primitive_type_table.put(cint.zig_name, &c_int_type.base)) == null);736 assert((try comp.primitive_type_table.put(cint.zig_name, &c_int_type.base)) == null);
725 }737 }
726 comp.u8_type = try comp.arena().create(Type.Int{738 comp.u8_type = try comp.arena().create(Type.Int);
739 comp.u8_type.* = Type.Int{
727 .base = Type{740 .base = Type{
728 .name = "u8",741 .name = "u8",
729 .base = Value{742 .base = Value{
...@@ -739,7 +752,7 @@ pub const Compilation = struct {...@@ -739,7 +752,7 @@ pub const Compilation = struct {
739 .bit_count = 8,752 .bit_count = 8,
740 },753 },
741 .garbage_node = undefined,754 .garbage_node = undefined,
742 });755 };
743 assert((try comp.primitive_type_table.put(comp.u8_type.base.name, &comp.u8_type.base)) == null);756 assert((try comp.primitive_type_table.put(comp.u8_type.base.name, &comp.u8_type.base)) == null);
744 }757 }
745758
...@@ -828,7 +841,7 @@ pub const Compilation = struct {...@@ -828,7 +841,7 @@ pub const Compilation = struct {
828 };841 };
829 errdefer self.gpa().free(source_code);842 errdefer self.gpa().free(source_code);
830843
831 const tree = try self.gpa().createOne(ast.Tree);844 const tree = try self.gpa().create(ast.Tree);
832 tree.* = try std.zig.parse(self.gpa(), source_code);845 tree.* = try std.zig.parse(self.gpa(), source_code);
833 errdefer {846 errdefer {
834 tree.deinit();847 tree.deinit();
...@@ -924,7 +937,8 @@ pub const Compilation = struct {...@@ -924,7 +937,8 @@ pub const Compilation = struct {
924 }937 }
925 } else {938 } else {
926 // add new decl939 // add new decl
927 const fn_decl = try self.gpa().create(Decl.Fn{940 const fn_decl = try self.gpa().create(Decl.Fn);
941 fn_decl.* = Decl.Fn{
928 .base = Decl{942 .base = Decl{
929 .id = Decl.Id.Fn,943 .id = Decl.Id.Fn,
930 .name = name,944 .name = name,
...@@ -935,7 +949,7 @@ pub const Compilation = struct {...@@ -935,7 +949,7 @@ pub const Compilation = struct {
935 },949 },
936 .value = Decl.Fn.Val{ .Unresolved = {} },950 .value = Decl.Fn.Val{ .Unresolved = {} },
937 .fn_proto = fn_proto,951 .fn_proto = fn_proto,
938 });952 };
939 tree_scope.base.ref();953 tree_scope.base.ref();
940 errdefer self.gpa().destroy(fn_decl);954 errdefer self.gpa().destroy(fn_decl);
941955
...@@ -1139,12 +1153,13 @@ pub const Compilation = struct {...@@ -1139,12 +1153,13 @@ pub const Compilation = struct {
1139 }1153 }
1140 }1154 }
11411155
1142 const link_lib = try self.gpa().create(LinkLib{1156 const link_lib = try self.gpa().create(LinkLib);
1157 link_lib.* = LinkLib{
1143 .name = name,1158 .name = name,
1144 .path = null,1159 .path = null,
1145 .provided_explicitly = provided_explicitly,1160 .provided_explicitly = provided_explicitly,
1146 .symbols = ArrayList([]u8).init(self.gpa()),1161 .symbols = ArrayList([]u8).init(self.gpa()),
1147 });1162 };
1148 try self.link_libs_list.append(link_lib);1163 try self.link_libs_list.append(link_lib);
1149 if (is_libc) {1164 if (is_libc) {
1150 self.libc_link_lib = link_lib;1165 self.libc_link_lib = link_lib;
...@@ -1183,7 +1198,7 @@ pub const Compilation = struct {...@@ -1183,7 +1198,7 @@ pub const Compilation = struct {
1183 const file_name = try std.fmt.allocPrint(self.gpa(), "{}{}", file_prefix[0..], suffix);1198 const file_name = try std.fmt.allocPrint(self.gpa(), "{}{}", file_prefix[0..], suffix);
1184 defer self.gpa().free(file_name);1199 defer self.gpa().free(file_name);
11851200
1186 const full_path = try os.path.join(self.gpa(), tmp_dir, file_name[0..]);1201 const full_path = try os.path.join(self.gpa(), [][]const u8{ tmp_dir, file_name[0..] });
1187 errdefer self.gpa().free(full_path);1202 errdefer self.gpa().free(full_path);
11881203
1189 return Buffer.fromOwnedSlice(self.gpa(), full_path);1204 return Buffer.fromOwnedSlice(self.gpa(), full_path);
...@@ -1204,7 +1219,7 @@ pub const Compilation = struct {...@@ -1204,7 +1219,7 @@ pub const Compilation = struct {
1204 const zig_dir_path = try getZigDir(self.gpa());1219 const zig_dir_path = try getZigDir(self.gpa());
1205 defer self.gpa().free(zig_dir_path);1220 defer self.gpa().free(zig_dir_path);
12061221
1207 const tmp_dir = try os.path.join(self.arena(), zig_dir_path, comp_dir_name[0..]);1222 const tmp_dir = try os.path.join(self.arena(), [][]const u8{ zig_dir_path, comp_dir_name[0..] });
1208 try os.makePath(self.gpa(), tmp_dir);1223 try os.makePath(self.gpa(), tmp_dir);
1209 return tmp_dir;1224 return tmp_dir;
1210 }1225 }
src-self-hosted/errmsg.zig+12-8
...@@ -118,7 +118,8 @@ pub const Msg = struct {...@@ -118,7 +118,8 @@ pub const Msg = struct {
118 const realpath = try mem.dupe(comp.gpa(), u8, tree_scope.root().realpath);118 const realpath = try mem.dupe(comp.gpa(), u8, tree_scope.root().realpath);
119 errdefer comp.gpa().free(realpath);119 errdefer comp.gpa().free(realpath);
120120
121 const msg = try comp.gpa().create(Msg{121 const msg = try comp.gpa().create(Msg);
122 msg.* = Msg{
122 .text = text,123 .text = text,
123 .realpath = realpath,124 .realpath = realpath,
124 .data = Data{125 .data = Data{
...@@ -128,7 +129,7 @@ pub const Msg = struct {...@@ -128,7 +129,7 @@ pub const Msg = struct {
128 .span = span,129 .span = span,
129 },130 },
130 },131 },
131 });132 };
132 tree_scope.base.ref();133 tree_scope.base.ref();
133 return msg;134 return msg;
134 }135 }
...@@ -139,13 +140,14 @@ pub const Msg = struct {...@@ -139,13 +140,14 @@ pub const Msg = struct {
139 const realpath_copy = try mem.dupe(comp.gpa(), u8, realpath);140 const realpath_copy = try mem.dupe(comp.gpa(), u8, realpath);
140 errdefer comp.gpa().free(realpath_copy);141 errdefer comp.gpa().free(realpath_copy);
141142
142 const msg = try comp.gpa().create(Msg{143 const msg = try comp.gpa().create(Msg);
144 msg.* = Msg{
143 .text = text,145 .text = text,
144 .realpath = realpath_copy,146 .realpath = realpath_copy,
145 .data = Data{147 .data = Data{
146 .Cli = Cli{ .allocator = comp.gpa() },148 .Cli = Cli{ .allocator = comp.gpa() },
147 },149 },
148 });150 };
149 return msg;151 return msg;
150 }152 }
151153
...@@ -164,7 +166,8 @@ pub const Msg = struct {...@@ -164,7 +166,8 @@ pub const Msg = struct {
164 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;166 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
165 try parse_error.render(&tree_scope.tree.tokens, out_stream);167 try parse_error.render(&tree_scope.tree.tokens, out_stream);
166168
167 const msg = try comp.gpa().create(Msg{169 const msg = try comp.gpa().create(Msg);
170 msg.* = Msg{
168 .text = undefined,171 .text = undefined,
169 .realpath = realpath_copy,172 .realpath = realpath_copy,
170 .data = Data{173 .data = Data{
...@@ -177,7 +180,7 @@ pub const Msg = struct {...@@ -177,7 +180,7 @@ pub const Msg = struct {
177 },180 },
178 },181 },
179 },182 },
180 });183 };
181 tree_scope.base.ref();184 tree_scope.base.ref();
182 msg.text = text_buf.toOwnedSlice();185 msg.text = text_buf.toOwnedSlice();
183 return msg;186 return msg;
...@@ -203,7 +206,8 @@ pub const Msg = struct {...@@ -203,7 +206,8 @@ pub const Msg = struct {
203 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;206 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
204 try parse_error.render(&tree.tokens, out_stream);207 try parse_error.render(&tree.tokens, out_stream);
205208
206 const msg = try allocator.create(Msg{209 const msg = try allocator.create(Msg);
210 msg.* = Msg{
207 .text = undefined,211 .text = undefined,
208 .realpath = realpath_copy,212 .realpath = realpath_copy,
209 .data = Data{213 .data = Data{
...@@ -216,7 +220,7 @@ pub const Msg = struct {...@@ -216,7 +220,7 @@ pub const Msg = struct {
216 },220 },
217 },221 },
218 },222 },
219 });223 };
220 msg.text = text_buf.toOwnedSlice();224 msg.text = text_buf.toOwnedSlice();
221 errdefer allocator.destroy(msg);225 errdefer allocator.destroy(msg);
222226
src-self-hosted/introspect.zig+2-2
...@@ -8,10 +8,10 @@ const warn = std.debug.warn;...@@ -8,10 +8,10 @@ const warn = std.debug.warn;
88
9/// Caller must free result9/// Caller must free result
10pub fn testZigInstallPrefix(allocator: *mem.Allocator, test_path: []const u8) ![]u8 {10pub fn testZigInstallPrefix(allocator: *mem.Allocator, test_path: []const u8) ![]u8 {
11 const test_zig_dir = try os.path.join(allocator, test_path, "lib", "zig");11 const test_zig_dir = try os.path.join(allocator, [][]const u8{ test_path, "lib", "zig" });
12 errdefer allocator.free(test_zig_dir);12 errdefer allocator.free(test_zig_dir);
1313
14 const test_index_file = try os.path.join(allocator, test_zig_dir, "std", "index.zig");14 const test_index_file = try os.path.join(allocator, [][]const u8{ test_zig_dir, "std", "index.zig" });
15 defer allocator.free(test_index_file);15 defer allocator.free(test_index_file);
1616
17 var file = try os.File.openRead(test_index_file);17 var file = try os.File.openRead(test_index_file);
src-self-hosted/ir.zig+19-16
...@@ -67,7 +67,7 @@ pub const Inst = struct {...@@ -67,7 +67,7 @@ pub const Inst = struct {
67 parent: ?*Inst,67 parent: ?*Inst,
6868
69 /// populated durign codegen69 /// populated durign codegen
70 llvm_value: ?llvm.ValueRef,70 llvm_value: ?*llvm.Value,
7171
72 pub fn cast(base: *Inst, comptime T: type) ?*T {72 pub fn cast(base: *Inst, comptime T: type) ?*T {
73 if (base.id == comptime typeToId(T)) {73 if (base.id == comptime typeToId(T)) {
...@@ -129,7 +129,7 @@ pub const Inst = struct {...@@ -129,7 +129,7 @@ pub const Inst = struct {
129 }129 }
130 }130 }
131131
132 pub fn render(base: *Inst, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?llvm.ValueRef) {132 pub fn render(base: *Inst, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?*llvm.Value) {
133 switch (base.id) {133 switch (base.id) {
134 Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val),134 Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val),
135 Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val),135 Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val),
...@@ -313,10 +313,10 @@ pub const Inst = struct {...@@ -313,10 +313,10 @@ pub const Inst = struct {
313 return new_inst;313 return new_inst;
314 }314 }
315315
316 pub fn render(self: *Call, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef {316 pub fn render(self: *Call, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value {
317 const fn_ref = self.params.fn_ref.llvm_value.?;317 const fn_ref = self.params.fn_ref.llvm_value.?;
318318
319 const args = try ofile.arena.alloc(llvm.ValueRef, self.params.args.len);319 const args = try ofile.arena.alloc(*llvm.Value, self.params.args.len);
320 for (self.params.args) |arg, i| {320 for (self.params.args) |arg, i| {
321 args[i] = arg.llvm_value.?;321 args[i] = arg.llvm_value.?;
322 }322 }
...@@ -360,7 +360,7 @@ pub const Inst = struct {...@@ -360,7 +360,7 @@ pub const Inst = struct {
360 return new_inst;360 return new_inst;
361 }361 }
362362
363 pub fn render(self: *Const, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef {363 pub fn render(self: *Const, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value {
364 return self.base.val.KnownValue.getLlvmConst(ofile);364 return self.base.val.KnownValue.getLlvmConst(ofile);
365 }365 }
366 };366 };
...@@ -392,7 +392,7 @@ pub const Inst = struct {...@@ -392,7 +392,7 @@ pub const Inst = struct {
392 return ira.irb.build(Return, self.base.scope, self.base.span, Params{ .return_value = casted_value });392 return ira.irb.build(Return, self.base.scope, self.base.span, Params{ .return_value = casted_value });
393 }393 }
394394
395 pub fn render(self: *Return, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef {395 pub fn render(self: *Return, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value {
396 const value = self.params.return_value.llvm_value;396 const value = self.params.return_value.llvm_value;
397 const return_type = self.params.return_value.getKnownType();397 const return_type = self.params.return_value.getKnownType();
398398
...@@ -540,7 +540,7 @@ pub const Inst = struct {...@@ -540,7 +540,7 @@ pub const Inst = struct {
540 }540 }
541 }541 }
542542
543 pub fn render(self: *VarPtr, ofile: *ObjectFile, fn_val: *Value.Fn) llvm.ValueRef {543 pub fn render(self: *VarPtr, ofile: *ObjectFile, fn_val: *Value.Fn) *llvm.Value {
544 switch (self.params.var_scope.data) {544 switch (self.params.var_scope.data) {
545 Scope.Var.Data.Const => unreachable, // turned into Inst.Const in analyze pass545 Scope.Var.Data.Const => unreachable, // turned into Inst.Const in analyze pass
546 Scope.Var.Data.Param => |param| return param.llvm_value,546 Scope.Var.Data.Param => |param| return param.llvm_value,
...@@ -596,7 +596,7 @@ pub const Inst = struct {...@@ -596,7 +596,7 @@ pub const Inst = struct {
596 return new_inst;596 return new_inst;
597 }597 }
598598
599 pub fn render(self: *LoadPtr, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef {599 pub fn render(self: *LoadPtr, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value {
600 const child_type = self.base.getKnownType();600 const child_type = self.base.getKnownType();
601 if (!child_type.hasBits()) {601 if (!child_type.hasBits()) {
602 return null;602 return null;
...@@ -935,8 +935,8 @@ pub const BasicBlock = struct {...@@ -935,8 +935,8 @@ pub const BasicBlock = struct {
935 ref_instruction: ?*Inst,935 ref_instruction: ?*Inst,
936936
937 /// for codegen937 /// for codegen
938 llvm_block: llvm.BasicBlockRef,938 llvm_block: *llvm.BasicBlock,
939 llvm_exit_block: llvm.BasicBlockRef,939 llvm_exit_block: *llvm.BasicBlock,
940940
941 /// the basic block that is derived from this one in analysis941 /// the basic block that is derived from this one in analysis
942 child: ?*BasicBlock,942 child: ?*BasicBlock,
...@@ -1021,12 +1021,13 @@ pub const Builder = struct {...@@ -1021,12 +1021,13 @@ pub const Builder = struct {
1021 pub const Error = Analyze.Error;1021 pub const Error = Analyze.Error;
10221022
1023 pub fn init(comp: *Compilation, tree_scope: *Scope.AstTree, begin_scope: ?*Scope) !Builder {1023 pub fn init(comp: *Compilation, tree_scope: *Scope.AstTree, begin_scope: ?*Scope) !Builder {
1024 const code = try comp.gpa().create(Code{1024 const code = try comp.gpa().create(Code);
1025 code.* = Code{
1025 .basic_block_list = undefined,1026 .basic_block_list = undefined,
1026 .arena = std.heap.ArenaAllocator.init(comp.gpa()),1027 .arena = std.heap.ArenaAllocator.init(comp.gpa()),
1027 .return_type = null,1028 .return_type = null,
1028 .tree_scope = tree_scope,1029 .tree_scope = tree_scope,
1029 });1030 };
1030 code.basic_block_list = std.ArrayList(*BasicBlock).init(&code.arena.allocator);1031 code.basic_block_list = std.ArrayList(*BasicBlock).init(&code.arena.allocator);
1031 errdefer code.destroy(comp.gpa());1032 errdefer code.destroy(comp.gpa());
10321033
...@@ -1052,7 +1053,8 @@ pub const Builder = struct {...@@ -1052,7 +1053,8 @@ pub const Builder = struct {
10521053
1053 /// No need to clean up resources thanks to the arena allocator.1054 /// No need to clean up resources thanks to the arena allocator.
1054 pub fn createBasicBlock(self: *Builder, scope: *Scope, name_hint: [*]const u8) !*BasicBlock {1055 pub fn createBasicBlock(self: *Builder, scope: *Scope, name_hint: [*]const u8) !*BasicBlock {
1055 const basic_block = try self.arena().create(BasicBlock{1056 const basic_block = try self.arena().create(BasicBlock);
1057 basic_block.* = BasicBlock{
1056 .ref_count = 0,1058 .ref_count = 0,
1057 .name_hint = name_hint,1059 .name_hint = name_hint,
1058 .debug_id = self.next_debug_id,1060 .debug_id = self.next_debug_id,
...@@ -1063,7 +1065,7 @@ pub const Builder = struct {...@@ -1063,7 +1065,7 @@ pub const Builder = struct {
1063 .ref_instruction = null,1065 .ref_instruction = null,
1064 .llvm_block = undefined,1066 .llvm_block = undefined,
1065 .llvm_exit_block = undefined,1067 .llvm_exit_block = undefined,
1066 });1068 };
1067 self.next_debug_id += 1;1069 self.next_debug_id += 1;
1068 return basic_block;1070 return basic_block;
1069 }1071 }
...@@ -1774,7 +1776,8 @@ pub const Builder = struct {...@@ -1774,7 +1776,8 @@ pub const Builder = struct {
1774 params: I.Params,1776 params: I.Params,
1775 is_generated: bool,1777 is_generated: bool,
1776 ) !*Inst {1778 ) !*Inst {
1777 const inst = try self.arena().create(I{1779 const inst = try self.arena().create(I);
1780 inst.* = I{
1778 .base = Inst{1781 .base = Inst{
1779 .id = Inst.typeToId(I),1782 .id = Inst.typeToId(I),
1780 .is_generated = is_generated,1783 .is_generated = is_generated,
...@@ -1793,7 +1796,7 @@ pub const Builder = struct {...@@ -1793,7 +1796,7 @@ pub const Builder = struct {
1793 .owner_bb = self.current_basic_block,1796 .owner_bb = self.current_basic_block,
1794 },1797 },
1795 .params = params,1798 .params = params,
1796 });1799 };
17971800
1798 // Look at the params and ref() other instructions1801 // Look at the params and ref() other instructions
1799 comptime var i = 0;1802 comptime var i = 0;
src-self-hosted/libc_installation.zig+27-18
...@@ -57,10 +57,10 @@ pub const LibCInstallation = struct {...@@ -57,10 +57,10 @@ pub const LibCInstallation = struct {
57 const contents = try std.io.readFileAlloc(allocator, libc_file);57 const contents = try std.io.readFileAlloc(allocator, libc_file);
58 defer allocator.free(contents);58 defer allocator.free(contents);
5959
60 var it = std.mem.split(contents, "\n");60 var it = std.mem.tokenize(contents, "\n");
61 while (it.next()) |line| {61 while (it.next()) |line| {
62 if (line.len == 0 or line[0] == '#') continue;62 if (line.len == 0 or line[0] == '#') continue;
63 var line_it = std.mem.split(line, "=");63 var line_it = std.mem.separate(line, "=");
64 const name = line_it.next() orelse {64 const name = line_it.next() orelse {
65 try stderr.print("missing equal sign after field name\n");65 try stderr.print("missing equal sign after field name\n");
66 return error.ParseError;66 return error.ParseError;
...@@ -154,8 +154,8 @@ pub const LibCInstallation = struct {...@@ -154,8 +154,8 @@ pub const LibCInstallation = struct {
154 c.ZigFindWindowsSdkError.None => {154 c.ZigFindWindowsSdkError.None => {
155 windows_sdk = sdk;155 windows_sdk = sdk;
156156
157 if (sdk.msvc_lib_dir_ptr) |ptr| {157 if (sdk.msvc_lib_dir_ptr != 0) {
158 self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, ptr[0..sdk.msvc_lib_dir_len]);158 self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, sdk.msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]);
159 }159 }
160 try group.call(findNativeKernel32LibDir, self, loop, sdk);160 try group.call(findNativeKernel32LibDir, self, loop, sdk);
161 try group.call(findNativeIncludeDirWindows, self, loop, sdk);161 try group.call(findNativeIncludeDirWindows, self, loop, sdk);
...@@ -213,7 +213,7 @@ pub const LibCInstallation = struct {...@@ -213,7 +213,7 @@ pub const LibCInstallation = struct {
213 },213 },
214 }214 }
215215
216 var it = std.mem.split(exec_result.stderr, "\n\r");216 var it = std.mem.tokenize(exec_result.stderr, "\n\r");
217 var search_paths = std.ArrayList([]const u8).init(loop.allocator);217 var search_paths = std.ArrayList([]const u8).init(loop.allocator);
218 defer search_paths.deinit();218 defer search_paths.deinit();
219 while (it.next()) |line| {219 while (it.next()) |line| {
...@@ -230,7 +230,7 @@ pub const LibCInstallation = struct {...@@ -230,7 +230,7 @@ pub const LibCInstallation = struct {
230 while (path_i < search_paths.len) : (path_i += 1) {230 while (path_i < search_paths.len) : (path_i += 1) {
231 const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1);231 const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1);
232 const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " ");232 const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " ");
233 const stdlib_path = try std.os.path.join(loop.allocator, search_path, "stdlib.h");233 const stdlib_path = try std.os.path.join(loop.allocator, [][]const u8{ search_path, "stdlib.h" });
234 defer loop.allocator.free(stdlib_path);234 defer loop.allocator.free(stdlib_path);
235235
236 if (try fileExists(stdlib_path)) {236 if (try fileExists(stdlib_path)) {
...@@ -254,7 +254,10 @@ pub const LibCInstallation = struct {...@@ -254,7 +254,10 @@ pub const LibCInstallation = struct {
254 const stream = &std.io.BufferOutStream.init(&result_buf).stream;254 const stream = &std.io.BufferOutStream.init(&result_buf).stream;
255 try stream.print("{}\\Include\\{}\\ucrt", search.path, search.version);255 try stream.print("{}\\Include\\{}\\ucrt", search.path, search.version);
256256
257 const stdlib_path = try std.os.path.join(loop.allocator, result_buf.toSliceConst(), "stdlib.h");257 const stdlib_path = try std.os.path.join(
258 loop.allocator,
259 [][]const u8{ result_buf.toSliceConst(), "stdlib.h" },
260 );
258 defer loop.allocator.free(stdlib_path);261 defer loop.allocator.free(stdlib_path);
259262
260 if (try fileExists(stdlib_path)) {263 if (try fileExists(stdlib_path)) {
...@@ -283,7 +286,10 @@ pub const LibCInstallation = struct {...@@ -283,7 +286,10 @@ pub const LibCInstallation = struct {
283 builtin.Arch.aarch64v8 => try stream.write("arm"),286 builtin.Arch.aarch64v8 => try stream.write("arm"),
284 else => return error.UnsupportedArchitecture,287 else => return error.UnsupportedArchitecture,
285 }288 }
286 const ucrt_lib_path = try std.os.path.join(loop.allocator, result_buf.toSliceConst(), "ucrt.lib");289 const ucrt_lib_path = try std.os.path.join(
290 loop.allocator,
291 [][]const u8{ result_buf.toSliceConst(), "ucrt.lib" },
292 );
287 defer loop.allocator.free(ucrt_lib_path);293 defer loop.allocator.free(ucrt_lib_path);
288 if (try fileExists(ucrt_lib_path)) {294 if (try fileExists(ucrt_lib_path)) {
289 self.lib_dir = result_buf.toOwnedSlice();295 self.lib_dir = result_buf.toOwnedSlice();
...@@ -358,7 +364,10 @@ pub const LibCInstallation = struct {...@@ -358,7 +364,10 @@ pub const LibCInstallation = struct {
358 builtin.Arch.aarch64v8 => try stream.write("arm\\"),364 builtin.Arch.aarch64v8 => try stream.write("arm\\"),
359 else => return error.UnsupportedArchitecture,365 else => return error.UnsupportedArchitecture,
360 }366 }
361 const kernel32_path = try std.os.path.join(loop.allocator, result_buf.toSliceConst(), "kernel32.lib");367 const kernel32_path = try std.os.path.join(
368 loop.allocator,
369 [][]const u8{ result_buf.toSliceConst(), "kernel32.lib" },
370 );
362 defer loop.allocator.free(kernel32_path);371 defer loop.allocator.free(kernel32_path);
363 if (try fileExists(kernel32_path)) {372 if (try fileExists(kernel32_path)) {
364 self.kernel32_lib_dir = result_buf.toOwnedSlice();373 self.kernel32_lib_dir = result_buf.toOwnedSlice();
...@@ -410,7 +419,7 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo...@@ -410,7 +419,7 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo
410 return error.CCompilerCrashed;419 return error.CCompilerCrashed;
411 },420 },
412 }421 }
413 var it = std.mem.split(exec_result.stdout, "\n\r");422 var it = std.mem.tokenize(exec_result.stdout, "\n\r");
414 const line = it.next() orelse return error.LibCRuntimeNotFound;423 const line = it.next() orelse return error.LibCRuntimeNotFound;
415 const dirname = std.os.path.dirname(line) orelse return error.LibCRuntimeNotFound;424 const dirname = std.os.path.dirname(line) orelse return error.LibCRuntimeNotFound;
416425
...@@ -428,20 +437,20 @@ const Search = struct {...@@ -428,20 +437,20 @@ const Search = struct {
428437
429fn fillSearch(search_buf: *[2]Search, sdk: *c.ZigWindowsSDK) []Search {438fn fillSearch(search_buf: *[2]Search, sdk: *c.ZigWindowsSDK) []Search {
430 var search_end: usize = 0;439 var search_end: usize = 0;
431 if (sdk.path10_ptr) |path10_ptr| {440 if (sdk.path10_ptr != 0) {
432 if (sdk.version10_ptr) |ver10_ptr| {441 if (sdk.version10_ptr != 0) {
433 search_buf[search_end] = Search{442 search_buf[search_end] = Search{
434 .path = path10_ptr[0..sdk.path10_len],443 .path = sdk.path10_ptr[0..sdk.path10_len],
435 .version = ver10_ptr[0..sdk.version10_len],444 .version = sdk.version10_ptr[0..sdk.version10_len],
436 };445 };
437 search_end += 1;446 search_end += 1;
438 }447 }
439 }448 }
440 if (sdk.path81_ptr) |path81_ptr| {449 if (sdk.path81_ptr != 0) {
441 if (sdk.version81_ptr) |ver81_ptr| {450 if (sdk.version81_ptr != 0) {
442 search_buf[search_end] = Search{451 search_buf[search_end] = Search{
443 .path = path81_ptr[0..sdk.path81_len],452 .path = sdk.path81_ptr[0..sdk.path81_len],
444 .version = ver81_ptr[0..sdk.version81_len],453 .version = sdk.version81_ptr[0..sdk.version81_len],
445 };454 };
446 search_end += 1;455 search_end += 1;
447 }456 }
src-self-hosted/link.zig+1-1
...@@ -315,7 +315,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -315,7 +315,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
315}315}
316316
317fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {317fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {
318 const full_path = try std.os.path.join(&ctx.arena.allocator, dirname, basename);318 const full_path = try std.os.path.join(&ctx.arena.allocator, [][]const u8{ dirname, basename });
319 const full_path_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, full_path);319 const full_path_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, full_path);
320 try ctx.args.append(full_path_with_null.ptr);320 try ctx.args.append(full_path_with_null.ptr);
321}321}
src-self-hosted/llvm.zig+129-52
...@@ -11,45 +11,31 @@ const assert = @import("std").debug.assert;...@@ -11,45 +11,31 @@ const assert = @import("std").debug.assert;
11pub const AttributeIndex = c_uint;11pub const AttributeIndex = c_uint;
12pub const Bool = c_int;12pub const Bool = c_int;
1313
14pub const BuilderRef = removeNullability(c.LLVMBuilderRef);14pub const Builder = c.LLVMBuilderRef.Child.Child;
15pub const ContextRef = removeNullability(c.LLVMContextRef);15pub const Context = c.LLVMContextRef.Child.Child;
16pub const ModuleRef = removeNullability(c.LLVMModuleRef);16pub const Module = c.LLVMModuleRef.Child.Child;
17pub const ValueRef = removeNullability(c.LLVMValueRef);17pub const Value = c.LLVMValueRef.Child.Child;
18pub const TypeRef = removeNullability(c.LLVMTypeRef);18pub const Type = c.LLVMTypeRef.Child.Child;
19pub const BasicBlockRef = removeNullability(c.LLVMBasicBlockRef);19pub const BasicBlock = c.LLVMBasicBlockRef.Child.Child;
20pub const AttributeRef = removeNullability(c.LLVMAttributeRef);20pub const Attribute = c.LLVMAttributeRef.Child.Child;
21pub const TargetRef = removeNullability(c.LLVMTargetRef);21pub const Target = c.LLVMTargetRef.Child.Child;
22pub const TargetMachineRef = removeNullability(c.LLVMTargetMachineRef);22pub const TargetMachine = c.LLVMTargetMachineRef.Child.Child;
23pub const TargetDataRef = removeNullability(c.LLVMTargetDataRef);23pub const TargetData = c.LLVMTargetDataRef.Child.Child;
24pub const DIBuilder = c.ZigLLVMDIBuilder;24pub const DIBuilder = c.ZigLLVMDIBuilder;
25pub const DIFile = c.ZigLLVMDIFile;
26pub const DICompileUnit = c.ZigLLVMDICompileUnit;
2527
26pub const ABIAlignmentOfType = c.LLVMABIAlignmentOfType;28pub const ABIAlignmentOfType = c.LLVMABIAlignmentOfType;
27pub const AddAttributeAtIndex = c.LLVMAddAttributeAtIndex;29pub const AddAttributeAtIndex = c.LLVMAddAttributeAtIndex;
28pub const AddFunction = c.LLVMAddFunction;
29pub const AddGlobal = c.LLVMAddGlobal;
30pub const AddModuleCodeViewFlag = c.ZigLLVMAddModuleCodeViewFlag;30pub const AddModuleCodeViewFlag = c.ZigLLVMAddModuleCodeViewFlag;
31pub const AddModuleDebugInfoFlag = c.ZigLLVMAddModuleDebugInfoFlag;31pub const AddModuleDebugInfoFlag = c.ZigLLVMAddModuleDebugInfoFlag;
32pub const ArrayType = c.LLVMArrayType;
33pub const BuildLoad = c.LLVMBuildLoad;
34pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation;32pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation;
35pub const ConstAllOnes = c.LLVMConstAllOnes;33pub const ConstAllOnes = c.LLVMConstAllOnes;
36pub const ConstArray = c.LLVMConstArray;34pub const ConstArray = c.LLVMConstArray;
37pub const ConstBitCast = c.LLVMConstBitCast;35pub const ConstBitCast = c.LLVMConstBitCast;
38pub const ConstInt = c.LLVMConstInt;
39pub const ConstIntOfArbitraryPrecision = c.LLVMConstIntOfArbitraryPrecision;36pub const ConstIntOfArbitraryPrecision = c.LLVMConstIntOfArbitraryPrecision;
40pub const ConstNeg = c.LLVMConstNeg;37pub const ConstNeg = c.LLVMConstNeg;
41pub const ConstNull = c.LLVMConstNull;
42pub const ConstStringInContext = c.LLVMConstStringInContext;
43pub const ConstStructInContext = c.LLVMConstStructInContext;38pub const ConstStructInContext = c.LLVMConstStructInContext;
44pub const CopyStringRepOfTargetData = c.LLVMCopyStringRepOfTargetData;
45pub const CreateBuilderInContext = c.LLVMCreateBuilderInContext;
46pub const CreateCompileUnit = c.ZigLLVMCreateCompileUnit;
47pub const CreateDIBuilder = c.ZigLLVMCreateDIBuilder;
48pub const CreateEnumAttribute = c.LLVMCreateEnumAttribute;
49pub const CreateFile = c.ZigLLVMCreateFile;
50pub const CreateStringAttribute = c.LLVMCreateStringAttribute;
51pub const CreateTargetDataLayout = c.LLVMCreateTargetDataLayout;
52pub const CreateTargetMachine = c.LLVMCreateTargetMachine;
53pub const DIBuilderFinalize = c.ZigLLVMDIBuilderFinalize;39pub const DIBuilderFinalize = c.ZigLLVMDIBuilderFinalize;
54pub const DisposeBuilder = c.LLVMDisposeBuilder;40pub const DisposeBuilder = c.LLVMDisposeBuilder;
55pub const DisposeDIBuilder = c.ZigLLVMDisposeDIBuilder;41pub const DisposeDIBuilder = c.ZigLLVMDisposeDIBuilder;
...@@ -62,9 +48,7 @@ pub const DumpModule = c.LLVMDumpModule;...@@ -62,9 +48,7 @@ pub const DumpModule = c.LLVMDumpModule;
62pub const FP128TypeInContext = c.LLVMFP128TypeInContext;48pub const FP128TypeInContext = c.LLVMFP128TypeInContext;
63pub const FloatTypeInContext = c.LLVMFloatTypeInContext;49pub const FloatTypeInContext = c.LLVMFloatTypeInContext;
64pub const GetEnumAttributeKindForName = c.LLVMGetEnumAttributeKindForName;50pub const GetEnumAttributeKindForName = c.LLVMGetEnumAttributeKindForName;
65pub const GetHostCPUName = c.ZigLLVMGetHostCPUName;
66pub const GetMDKindIDInContext = c.LLVMGetMDKindIDInContext;51pub const GetMDKindIDInContext = c.LLVMGetMDKindIDInContext;
67pub const GetNativeFeatures = c.ZigLLVMGetNativeFeatures;
68pub const GetUndef = c.LLVMGetUndef;52pub const GetUndef = c.LLVMGetUndef;
69pub const HalfTypeInContext = c.LLVMHalfTypeInContext;53pub const HalfTypeInContext = c.LLVMHalfTypeInContext;
70pub const InitializeAllAsmParsers = c.LLVMInitializeAllAsmParsers;54pub const InitializeAllAsmParsers = c.LLVMInitializeAllAsmParsers;
...@@ -81,14 +65,11 @@ pub const Int64TypeInContext = c.LLVMInt64TypeInContext;...@@ -81,14 +65,11 @@ pub const Int64TypeInContext = c.LLVMInt64TypeInContext;
81pub const Int8TypeInContext = c.LLVMInt8TypeInContext;65pub const Int8TypeInContext = c.LLVMInt8TypeInContext;
82pub const IntPtrTypeForASInContext = c.LLVMIntPtrTypeForASInContext;66pub const IntPtrTypeForASInContext = c.LLVMIntPtrTypeForASInContext;
83pub const IntPtrTypeInContext = c.LLVMIntPtrTypeInContext;67pub const IntPtrTypeInContext = c.LLVMIntPtrTypeInContext;
84pub const IntTypeInContext = c.LLVMIntTypeInContext;
85pub const LabelTypeInContext = c.LLVMLabelTypeInContext;68pub const LabelTypeInContext = c.LLVMLabelTypeInContext;
86pub const MDNodeInContext = c.LLVMMDNodeInContext;69pub const MDNodeInContext = c.LLVMMDNodeInContext;
87pub const MDStringInContext = c.LLVMMDStringInContext;70pub const MDStringInContext = c.LLVMMDStringInContext;
88pub const MetadataTypeInContext = c.LLVMMetadataTypeInContext;71pub const MetadataTypeInContext = c.LLVMMetadataTypeInContext;
89pub const ModuleCreateWithNameInContext = c.LLVMModuleCreateWithNameInContext;
90pub const PPCFP128TypeInContext = c.LLVMPPCFP128TypeInContext;72pub const PPCFP128TypeInContext = c.LLVMPPCFP128TypeInContext;
91pub const PointerType = c.LLVMPointerType;
92pub const SetAlignment = c.LLVMSetAlignment;73pub const SetAlignment = c.LLVMSetAlignment;
93pub const SetDataLayout = c.LLVMSetDataLayout;74pub const SetDataLayout = c.LLVMSetDataLayout;
94pub const SetGlobalConstant = c.LLVMSetGlobalConstant;75pub const SetGlobalConstant = c.LLVMSetGlobalConstant;
...@@ -99,50 +80,146 @@ pub const SetUnnamedAddr = c.LLVMSetUnnamedAddr;...@@ -99,50 +80,146 @@ pub const SetUnnamedAddr = c.LLVMSetUnnamedAddr;
99pub const SetVolatile = c.LLVMSetVolatile;80pub const SetVolatile = c.LLVMSetVolatile;
100pub const StructTypeInContext = c.LLVMStructTypeInContext;81pub const StructTypeInContext = c.LLVMStructTypeInContext;
101pub const TokenTypeInContext = c.LLVMTokenTypeInContext;82pub const TokenTypeInContext = c.LLVMTokenTypeInContext;
102pub const VoidTypeInContext = c.LLVMVoidTypeInContext;
103pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext;83pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext;
104pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext;84pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext;
10585
86pub const AddGlobal = LLVMAddGlobal;
87extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*]const u8) ?*Value;
88
89pub const ConstStringInContext = LLVMConstStringInContext;
90extern fn LLVMConstStringInContext(C: *Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: Bool) ?*Value;
91
92pub const ConstInt = LLVMConstInt;
93extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) ?*Value;
94
95pub const BuildLoad = LLVMBuildLoad;
96extern fn LLVMBuildLoad(arg0: *Builder, PointerVal: *Value, Name: [*]const u8) ?*Value;
97
98pub const ConstNull = LLVMConstNull;
99extern fn LLVMConstNull(Ty: *Type) ?*Value;
100
101pub const CreateStringAttribute = LLVMCreateStringAttribute;
102extern fn LLVMCreateStringAttribute(
103 C: *Context,
104 K: [*]const u8,
105 KLength: c_uint,
106 V: [*]const u8,
107 VLength: c_uint,
108) ?*Attribute;
109
110pub const CreateEnumAttribute = LLVMCreateEnumAttribute;
111extern fn LLVMCreateEnumAttribute(C: *Context, KindID: c_uint, Val: u64) ?*Attribute;
112
113pub const AddFunction = LLVMAddFunction;
114extern fn LLVMAddFunction(M: *Module, Name: [*]const u8, FunctionTy: *Type) ?*Value;
115
116pub const CreateCompileUnit = ZigLLVMCreateCompileUnit;
117extern fn ZigLLVMCreateCompileUnit(
118 dibuilder: *DIBuilder,
119 lang: c_uint,
120 difile: *DIFile,
121 producer: [*]const u8,
122 is_optimized: bool,
123 flags: [*]const u8,
124 runtime_version: c_uint,
125 split_name: [*]const u8,
126 dwo_id: u64,
127 emit_debug_info: bool,
128) ?*DICompileUnit;
129
130pub const CreateFile = ZigLLVMCreateFile;
131extern fn ZigLLVMCreateFile(dibuilder: *DIBuilder, filename: [*]const u8, directory: [*]const u8) ?*DIFile;
132
133pub const ArrayType = LLVMArrayType;
134extern fn LLVMArrayType(ElementType: *Type, ElementCount: c_uint) ?*Type;
135
136pub const CreateDIBuilder = ZigLLVMCreateDIBuilder;
137extern fn ZigLLVMCreateDIBuilder(module: *Module, allow_unresolved: bool) ?*DIBuilder;
138
139pub const PointerType = LLVMPointerType;
140extern fn LLVMPointerType(ElementType: *Type, AddressSpace: c_uint) ?*Type;
141
142pub const CreateBuilderInContext = LLVMCreateBuilderInContext;
143extern fn LLVMCreateBuilderInContext(C: *Context) ?*Builder;
144
145pub const IntTypeInContext = LLVMIntTypeInContext;
146extern fn LLVMIntTypeInContext(C: *Context, NumBits: c_uint) ?*Type;
147
148pub const ModuleCreateWithNameInContext = LLVMModuleCreateWithNameInContext;
149extern fn LLVMModuleCreateWithNameInContext(ModuleID: [*]const u8, C: *Context) ?*Module;
150
151pub const VoidTypeInContext = LLVMVoidTypeInContext;
152extern fn LLVMVoidTypeInContext(C: *Context) ?*Type;
153
154pub const ContextCreate = LLVMContextCreate;
155extern fn LLVMContextCreate() ?*Context;
156
157pub const ContextDispose = LLVMContextDispose;
158extern fn LLVMContextDispose(C: *Context) void;
159
160pub const CopyStringRepOfTargetData = LLVMCopyStringRepOfTargetData;
161extern fn LLVMCopyStringRepOfTargetData(TD: *TargetData) ?[*]u8;
162
163pub const CreateTargetDataLayout = LLVMCreateTargetDataLayout;
164extern fn LLVMCreateTargetDataLayout(T: *TargetMachine) ?*TargetData;
165
166pub const CreateTargetMachine = LLVMCreateTargetMachine;
167extern fn LLVMCreateTargetMachine(
168 T: *Target,
169 Triple: [*]const u8,
170 CPU: [*]const u8,
171 Features: [*]const u8,
172 Level: CodeGenOptLevel,
173 Reloc: RelocMode,
174 CodeModel: CodeModel,
175) ?*TargetMachine;
176
177pub const GetHostCPUName = LLVMGetHostCPUName;
178extern fn LLVMGetHostCPUName() ?[*]u8;
179
180pub const GetNativeFeatures = ZigLLVMGetNativeFeatures;
181extern fn ZigLLVMGetNativeFeatures() ?[*]u8;
182
106pub const GetElementType = LLVMGetElementType;183pub const GetElementType = LLVMGetElementType;
107extern fn LLVMGetElementType(Ty: TypeRef) TypeRef;184extern fn LLVMGetElementType(Ty: *Type) *Type;
108185
109pub const TypeOf = LLVMTypeOf;186pub const TypeOf = LLVMTypeOf;
110extern fn LLVMTypeOf(Val: ValueRef) TypeRef;187extern fn LLVMTypeOf(Val: *Value) *Type;
111188
112pub const BuildStore = LLVMBuildStore;189pub const BuildStore = LLVMBuildStore;
113extern fn LLVMBuildStore(arg0: BuilderRef, Val: ValueRef, Ptr: ValueRef) ?ValueRef;190extern fn LLVMBuildStore(arg0: *Builder, Val: *Value, Ptr: *Value) ?*Value;
114191
115pub const BuildAlloca = LLVMBuildAlloca;192pub const BuildAlloca = LLVMBuildAlloca;
116extern fn LLVMBuildAlloca(arg0: BuilderRef, Ty: TypeRef, Name: ?[*]const u8) ?ValueRef;193extern fn LLVMBuildAlloca(arg0: *Builder, Ty: *Type, Name: ?[*]const u8) ?*Value;
117194
118pub const ConstInBoundsGEP = LLVMConstInBoundsGEP;195pub const ConstInBoundsGEP = LLVMConstInBoundsGEP;
119pub extern fn LLVMConstInBoundsGEP(ConstantVal: ValueRef, ConstantIndices: [*]ValueRef, NumIndices: c_uint) ?ValueRef;196pub extern fn LLVMConstInBoundsGEP(ConstantVal: *Value, ConstantIndices: [*]*Value, NumIndices: c_uint) ?*Value;
120197
121pub const GetTargetFromTriple = LLVMGetTargetFromTriple;198pub const GetTargetFromTriple = LLVMGetTargetFromTriple;
122extern fn LLVMGetTargetFromTriple(Triple: [*]const u8, T: *TargetRef, ErrorMessage: ?*[*]u8) Bool;199extern fn LLVMGetTargetFromTriple(Triple: [*]const u8, T: **Target, ErrorMessage: ?*[*]u8) Bool;
123200
124pub const VerifyModule = LLVMVerifyModule;201pub const VerifyModule = LLVMVerifyModule;
125extern fn LLVMVerifyModule(M: ModuleRef, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool;202extern fn LLVMVerifyModule(M: *Module, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool;
126203
127pub const GetInsertBlock = LLVMGetInsertBlock;204pub const GetInsertBlock = LLVMGetInsertBlock;
128extern fn LLVMGetInsertBlock(Builder: BuilderRef) BasicBlockRef;205extern fn LLVMGetInsertBlock(Builder: *Builder) *BasicBlock;
129206
130pub const FunctionType = LLVMFunctionType;207pub const FunctionType = LLVMFunctionType;
131extern fn LLVMFunctionType(208extern fn LLVMFunctionType(
132 ReturnType: TypeRef,209 ReturnType: *Type,
133 ParamTypes: [*]TypeRef,210 ParamTypes: [*]*Type,
134 ParamCount: c_uint,211 ParamCount: c_uint,
135 IsVarArg: Bool,212 IsVarArg: Bool,
136) ?TypeRef;213) ?*Type;
137214
138pub const GetParam = LLVMGetParam;215pub const GetParam = LLVMGetParam;
139extern fn LLVMGetParam(Fn: ValueRef, Index: c_uint) ValueRef;216extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;
140217
141pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext;218pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext;
142extern fn LLVMAppendBasicBlockInContext(C: ContextRef, Fn: ValueRef, Name: [*]const u8) ?BasicBlockRef;219extern fn LLVMAppendBasicBlockInContext(C: *Context, Fn: *Value, Name: [*]const u8) ?*BasicBlock;
143220
144pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd;221pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd;
145extern fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef) void;222extern fn LLVMPositionBuilderAtEnd(Builder: *Builder, Block: *BasicBlock) void;
146223
147pub const AbortProcessAction = VerifierFailureAction.LLVMAbortProcessAction;224pub const AbortProcessAction = VerifierFailureAction.LLVMAbortProcessAction;
148pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction;225pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction;
...@@ -190,17 +267,17 @@ pub const FnInline = extern enum {...@@ -190,17 +267,17 @@ pub const FnInline = extern enum {
190};267};
191268
192fn removeNullability(comptime T: type) type {269fn removeNullability(comptime T: type) type {
193 comptime assert(@typeId(T) == builtin.TypeId.Optional);270 comptime assert(@typeInfo(T).Pointer.size == @import("builtin").TypeInfo.Pointer.Size.C);
194 return T.Child;271 return *T.Child;
195}272}
196273
197pub const BuildRet = LLVMBuildRet;274pub const BuildRet = LLVMBuildRet;
198extern fn LLVMBuildRet(arg0: BuilderRef, V: ?ValueRef) ?ValueRef;275extern fn LLVMBuildRet(arg0: *Builder, V: ?*Value) ?*Value;
199276
200pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile;277pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile;
201extern fn ZigLLVMTargetMachineEmitToFile(278extern fn ZigLLVMTargetMachineEmitToFile(
202 targ_machine_ref: TargetMachineRef,279 targ_machine_ref: *TargetMachine,
203 module_ref: ModuleRef,280 module_ref: *Module,
204 filename: [*]const u8,281 filename: [*]const u8,
205 output_type: EmitOutputType,282 output_type: EmitOutputType,
206 error_message: *[*]u8,283 error_message: *[*]u8,
...@@ -209,6 +286,6 @@ extern fn ZigLLVMTargetMachineEmitToFile(...@@ -209,6 +286,6 @@ extern fn ZigLLVMTargetMachineEmitToFile(
209) bool;286) bool;
210287
211pub const BuildCall = ZigLLVMBuildCall;288pub const BuildCall = ZigLLVMBuildCall;
212extern fn ZigLLVMBuildCall(B: BuilderRef, Fn: ValueRef, Args: [*]ValueRef, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*]const u8) ?ValueRef;289extern fn ZigLLVMBuildCall(B: *Builder, Fn: *Value, Args: [*]*Value, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*]const u8) ?*Value;
213290
214pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;291pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;
src-self-hosted/main.zig+8-7
...@@ -24,7 +24,7 @@ var stderr_file: os.File = undefined;...@@ -24,7 +24,7 @@ var stderr_file: os.File = undefined;
24var stderr: *io.OutStream(os.File.WriteError) = undefined;24var stderr: *io.OutStream(os.File.WriteError) = undefined;
25var stdout: *io.OutStream(os.File.WriteError) = undefined;25var stdout: *io.OutStream(os.File.WriteError) = undefined;
2626
27const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB27pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
2828
29const usage =29const usage =
30 \\usage: zig [command] [options]30 \\usage: zig [command] [options]
...@@ -351,7 +351,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -351,7 +351,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
351 const root_name = if (provided_name) |n| n else blk: {351 const root_name = if (provided_name) |n| n else blk: {
352 if (root_source_file) |file| {352 if (root_source_file) |file| {
353 const basename = os.path.basename(file);353 const basename = os.path.basename(file);
354 var it = mem.split(basename, ".");354 var it = mem.separate(basename, ".");
355 break :blk it.next() orelse basename;355 break :blk it.next() orelse basename;
356 } else {356 } else {
357 try stderr.write("--name [name] not provided and unable to infer\n");357 try stderr.write("--name [name] not provided and unable to infer\n");
...@@ -510,7 +510,7 @@ fn cmdBuildObj(allocator: *Allocator, args: []const []const u8) !void {...@@ -510,7 +510,7 @@ fn cmdBuildObj(allocator: *Allocator, args: []const []const u8) !void {
510 return buildOutputType(allocator, args, Compilation.Kind.Obj);510 return buildOutputType(allocator, args, Compilation.Kind.Obj);
511}511}
512512
513const usage_fmt =513pub const usage_fmt =
514 \\usage: zig fmt [file]...514 \\usage: zig fmt [file]...
515 \\515 \\
516 \\ Formats the input files and modifies them in-place.516 \\ Formats the input files and modifies them in-place.
...@@ -527,7 +527,7 @@ const usage_fmt =...@@ -527,7 +527,7 @@ const usage_fmt =
527 \\527 \\
528;528;
529529
530const args_fmt_spec = []Flag{530pub const args_fmt_spec = []Flag{
531 Flag.Bool("--help"),531 Flag.Bool("--help"),
532 Flag.Bool("--check"),532 Flag.Bool("--check"),
533 Flag.Option("--color", []const []const u8{533 Flag.Option("--color", []const []const u8{
...@@ -757,7 +757,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro...@@ -757,7 +757,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
757 var group = event.Group(FmtError!void).init(fmt.loop);757 var group = event.Group(FmtError!void).init(fmt.loop);
758 while (try dir.next()) |entry| {758 while (try dir.next()) |entry| {
759 if (entry.kind == std.os.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) {759 if (entry.kind == std.os.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) {
760 const full_path = try os.path.join(fmt.loop.allocator, file_path, entry.name);760 const full_path = try os.path.join(fmt.loop.allocator, [][]const u8{ file_path, entry.name });
761 try group.call(fmtPath, fmt, full_path, check_mode);761 try group.call(fmtPath, fmt, full_path, check_mode);
762 }762 }
763 }763 }
...@@ -944,12 +944,13 @@ const CliPkg = struct {...@@ -944,12 +944,13 @@ const CliPkg = struct {
944 parent: ?*CliPkg,944 parent: ?*CliPkg,
945945
946 pub fn init(allocator: *mem.Allocator, name: []const u8, path: []const u8, parent: ?*CliPkg) !*CliPkg {946 pub fn init(allocator: *mem.Allocator, name: []const u8, path: []const u8, parent: ?*CliPkg) !*CliPkg {
947 var pkg = try allocator.create(CliPkg{947 var pkg = try allocator.create(CliPkg);
948 pkg.* = CliPkg{
948 .name = name,949 .name = name,
949 .path = path,950 .path = path,
950 .children = ArrayList(*CliPkg).init(allocator),951 .children = ArrayList(*CliPkg).init(allocator),
951 .parent = parent,952 .parent = parent,
952 });953 };
953 return pkg;954 return pkg;
954 }955 }
955956
src-self-hosted/package.zig+4-2
...@@ -15,11 +15,13 @@ pub const Package = struct {...@@ -15,11 +15,13 @@ pub const Package = struct {
15 /// makes internal copies of root_src_dir and root_src_path15 /// makes internal copies of root_src_dir and root_src_path
16 /// allocator should be an arena allocator because Package never frees anything16 /// allocator should be an arena allocator because Package never frees anything
17 pub fn create(allocator: *mem.Allocator, root_src_dir: []const u8, root_src_path: []const u8) !*Package {17 pub fn create(allocator: *mem.Allocator, root_src_dir: []const u8, root_src_path: []const u8) !*Package {
18 return allocator.create(Package{18 const ptr = try allocator.create(Package);
19 ptr.* = Package{
19 .root_src_dir = try Buffer.init(allocator, root_src_dir),20 .root_src_dir = try Buffer.init(allocator, root_src_dir),
20 .root_src_path = try Buffer.init(allocator, root_src_path),21 .root_src_path = try Buffer.init(allocator, root_src_path),
21 .table = Table.init(allocator),22 .table = Table.init(allocator),
22 });23 };
24 return ptr;
23 }25 }
2426
25 pub fn add(self: *Package, name: []const u8, package: *Package) !void {27 pub fn add(self: *Package, name: []const u8, package: *Package) !void {
src-self-hosted/scope.zig+10-10
...@@ -120,7 +120,7 @@ pub const Scope = struct {...@@ -120,7 +120,7 @@ pub const Scope = struct {
120 /// Creates a Root scope with 1 reference120 /// Creates a Root scope with 1 reference
121 /// Takes ownership of realpath121 /// Takes ownership of realpath
122 pub fn create(comp: *Compilation, realpath: []u8) !*Root {122 pub fn create(comp: *Compilation, realpath: []u8) !*Root {
123 const self = try comp.gpa().createOne(Root);123 const self = try comp.gpa().create(Root);
124 self.* = Root{124 self.* = Root{
125 .base = Scope{125 .base = Scope{
126 .id = Id.Root,126 .id = Id.Root,
...@@ -150,7 +150,7 @@ pub const Scope = struct {...@@ -150,7 +150,7 @@ pub const Scope = struct {
150 /// Creates a scope with 1 reference150 /// Creates a scope with 1 reference
151 /// Takes ownership of tree, will deinit and destroy when done.151 /// Takes ownership of tree, will deinit and destroy when done.
152 pub fn create(comp: *Compilation, tree: *ast.Tree, root_scope: *Root) !*AstTree {152 pub fn create(comp: *Compilation, tree: *ast.Tree, root_scope: *Root) !*AstTree {
153 const self = try comp.gpa().createOne(AstTree);153 const self = try comp.gpa().create(AstTree);
154 self.* = AstTree{154 self.* = AstTree{
155 .base = undefined,155 .base = undefined,
156 .tree = tree,156 .tree = tree,
...@@ -182,7 +182,7 @@ pub const Scope = struct {...@@ -182,7 +182,7 @@ pub const Scope = struct {
182182
183 /// Creates a Decls scope with 1 reference183 /// Creates a Decls scope with 1 reference
184 pub fn create(comp: *Compilation, parent: *Scope) !*Decls {184 pub fn create(comp: *Compilation, parent: *Scope) !*Decls {
185 const self = try comp.gpa().createOne(Decls);185 const self = try comp.gpa().create(Decls);
186 self.* = Decls{186 self.* = Decls{
187 .base = undefined,187 .base = undefined,
188 .table = event.RwLocked(Decl.Table).init(comp.loop, Decl.Table.init(comp.gpa())),188 .table = event.RwLocked(Decl.Table).init(comp.loop, Decl.Table.init(comp.gpa())),
...@@ -235,7 +235,7 @@ pub const Scope = struct {...@@ -235,7 +235,7 @@ pub const Scope = struct {
235235
236 /// Creates a Block scope with 1 reference236 /// Creates a Block scope with 1 reference
237 pub fn create(comp: *Compilation, parent: *Scope) !*Block {237 pub fn create(comp: *Compilation, parent: *Scope) !*Block {
238 const self = try comp.gpa().createOne(Block);238 const self = try comp.gpa().create(Block);
239 self.* = Block{239 self.* = Block{
240 .base = undefined,240 .base = undefined,
241 .incoming_values = undefined,241 .incoming_values = undefined,
...@@ -262,7 +262,7 @@ pub const Scope = struct {...@@ -262,7 +262,7 @@ pub const Scope = struct {
262 /// Creates a FnDef scope with 1 reference262 /// Creates a FnDef scope with 1 reference
263 /// Must set the fn_val later263 /// Must set the fn_val later
264 pub fn create(comp: *Compilation, parent: *Scope) !*FnDef {264 pub fn create(comp: *Compilation, parent: *Scope) !*FnDef {
265 const self = try comp.gpa().createOne(FnDef);265 const self = try comp.gpa().create(FnDef);
266 self.* = FnDef{266 self.* = FnDef{
267 .base = undefined,267 .base = undefined,
268 .fn_val = null,268 .fn_val = null,
...@@ -281,7 +281,7 @@ pub const Scope = struct {...@@ -281,7 +281,7 @@ pub const Scope = struct {
281281
282 /// Creates a CompTime scope with 1 reference282 /// Creates a CompTime scope with 1 reference
283 pub fn create(comp: *Compilation, parent: *Scope) !*CompTime {283 pub fn create(comp: *Compilation, parent: *Scope) !*CompTime {
284 const self = try comp.gpa().createOne(CompTime);284 const self = try comp.gpa().create(CompTime);
285 self.* = CompTime{ .base = undefined };285 self.* = CompTime{ .base = undefined };
286 self.base.init(Id.CompTime, parent);286 self.base.init(Id.CompTime, parent);
287 return self;287 return self;
...@@ -309,7 +309,7 @@ pub const Scope = struct {...@@ -309,7 +309,7 @@ pub const Scope = struct {
309 kind: Kind,309 kind: Kind,
310 defer_expr_scope: *DeferExpr,310 defer_expr_scope: *DeferExpr,
311 ) !*Defer {311 ) !*Defer {
312 const self = try comp.gpa().createOne(Defer);312 const self = try comp.gpa().create(Defer);
313 self.* = Defer{313 self.* = Defer{
314 .base = undefined,314 .base = undefined,
315 .defer_expr_scope = defer_expr_scope,315 .defer_expr_scope = defer_expr_scope,
...@@ -333,7 +333,7 @@ pub const Scope = struct {...@@ -333,7 +333,7 @@ pub const Scope = struct {
333333
334 /// Creates a DeferExpr scope with 1 reference334 /// Creates a DeferExpr scope with 1 reference
335 pub fn create(comp: *Compilation, parent: *Scope, expr_node: *ast.Node) !*DeferExpr {335 pub fn create(comp: *Compilation, parent: *Scope, expr_node: *ast.Node) !*DeferExpr {
336 const self = try comp.gpa().createOne(DeferExpr);336 const self = try comp.gpa().create(DeferExpr);
337 self.* = DeferExpr{337 self.* = DeferExpr{
338 .base = undefined,338 .base = undefined,
339 .expr_node = expr_node,339 .expr_node = expr_node,
...@@ -362,7 +362,7 @@ pub const Scope = struct {...@@ -362,7 +362,7 @@ pub const Scope = struct {
362 pub const Param = struct {362 pub const Param = struct {
363 index: usize,363 index: usize,
364 typ: *Type,364 typ: *Type,
365 llvm_value: llvm.ValueRef,365 llvm_value: *llvm.Value,
366 };366 };
367367
368 pub fn createParam(368 pub fn createParam(
...@@ -398,7 +398,7 @@ pub const Scope = struct {...@@ -398,7 +398,7 @@ pub const Scope = struct {
398 }398 }
399399
400 fn create(comp: *Compilation, parent: *Scope, name: []const u8, src_node: *ast.Node) !*Var {400 fn create(comp: *Compilation, parent: *Scope, name: []const u8, src_node: *ast.Node) !*Var {
401 const self = try comp.gpa().createOne(Var);401 const self = try comp.gpa().create(Var);
402 self.* = Var{402 self.* = Var{
403 .base = undefined,403 .base = undefined,
404 .name = name,404 .name = name,
src-self-hosted/target.zig+3-3
...@@ -457,8 +457,8 @@ pub const Target = union(enum) {...@@ -457,8 +457,8 @@ pub const Target = union(enum) {
457 }457 }
458 }458 }
459459
460 pub fn llvmTargetFromTriple(triple: std.Buffer) !llvm.TargetRef {460 pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target {
461 var result: llvm.TargetRef = undefined;461 var result: *llvm.Target = undefined;
462 var err_msg: [*]u8 = undefined;462 var err_msg: [*]u8 = undefined;
463 if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) {463 if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) {
464 std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg);464 std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg);
...@@ -520,7 +520,7 @@ pub const Target = union(enum) {...@@ -520,7 +520,7 @@ pub const Target = union(enum) {
520 => return 64,520 => return 64,
521 },521 },
522522
523 builtin.Os.windows => switch (id) {523 builtin.Os.windows, builtin.Os.uefi => switch (id) {
524 CInt.Id.Short,524 CInt.Id.Short,
525 CInt.Id.UShort,525 CInt.Id.UShort,
526 => return 16,526 => return 16,
src-self-hosted/test.zig+4-4
...@@ -4,7 +4,7 @@ const builtin = @import("builtin");...@@ -4,7 +4,7 @@ const builtin = @import("builtin");
4const Target = @import("target.zig").Target;4const Target = @import("target.zig").Target;
5const Compilation = @import("compilation.zig").Compilation;5const Compilation = @import("compilation.zig").Compilation;
6const introspect = @import("introspect.zig");6const introspect = @import("introspect.zig");
7const assertOrPanic = std.debug.assertOrPanic;7const testing = std.testing;
8const errmsg = @import("errmsg.zig");8const errmsg = @import("errmsg.zig");
9const ZigCompiler = @import("compilation.zig").ZigCompiler;9const ZigCompiler = @import("compilation.zig").ZigCompiler;
1010
...@@ -87,7 +87,7 @@ pub const TestContext = struct {...@@ -87,7 +87,7 @@ pub const TestContext = struct {
87 ) !void {87 ) !void {
88 var file_index_buf: [20]u8 = undefined;88 var file_index_buf: [20]u8 = undefined;
89 const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr());89 const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr());
90 const file1_path = try std.os.path.join(allocator, tmp_dir_name, file_index, file1);90 const file1_path = try std.os.path.join(allocator, [][]const u8{ tmp_dir_name, file_index, file1 });
9191
92 if (std.os.path.dirname(file1_path)) |dirname| {92 if (std.os.path.dirname(file1_path)) |dirname| {
93 try std.os.makePath(allocator, dirname);93 try std.os.makePath(allocator, dirname);
...@@ -120,7 +120,7 @@ pub const TestContext = struct {...@@ -120,7 +120,7 @@ pub const TestContext = struct {
120 ) !void {120 ) !void {
121 var file_index_buf: [20]u8 = undefined;121 var file_index_buf: [20]u8 = undefined;
122 const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr());122 const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr());
123 const file1_path = try std.os.path.join(allocator, tmp_dir_name, file_index, file1);123 const file1_path = try std.os.path.join(allocator, [][]const u8{ tmp_dir_name, file_index, file1 });
124124
125 const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", file1_path, Target(Target.Native).exeFileExt());125 const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", file1_path, Target(Target.Native).exeFileExt());
126 if (std.os.path.dirname(file1_path)) |dirname| {126 if (std.os.path.dirname(file1_path)) |dirname| {
...@@ -210,7 +210,7 @@ pub const TestContext = struct {...@@ -210,7 +210,7 @@ pub const TestContext = struct {
210 @panic("build incorrectly failed");210 @panic("build incorrectly failed");
211 },211 },
212 Compilation.Event.Fail => |msgs| {212 Compilation.Event.Fail => |msgs| {
213 assertOrPanic(msgs.len != 0);213 testing.expect(msgs.len != 0);
214 for (msgs) |msg| {214 for (msgs) |msg| {
215 if (mem.endsWith(u8, msg.realpath, path) and mem.eql(u8, msg.text, text)) {215 if (mem.endsWith(u8, msg.realpath, path) and mem.eql(u8, msg.text, text)) {
216 const span = msg.getSpan();216 const span = msg.getSpan();
src-self-hosted/type.zig+48-27
...@@ -44,14 +44,15 @@ pub const Type = struct {...@@ -44,14 +44,15 @@ pub const Type = struct {
44 Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),44 Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),
45 Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),45 Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),
46 Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(comp),46 Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(comp),
47 Id.Vector => @fieldParentPtr(Vector, "base", base).destroy(comp),
47 }48 }
48 }49 }
4950
50 pub fn getLlvmType(51 pub fn getLlvmType(
51 base: *Type,52 base: *Type,
52 allocator: *Allocator,53 allocator: *Allocator,
53 llvm_context: llvm.ContextRef,54 llvm_context: *llvm.Context,
54 ) (error{OutOfMemory}!llvm.TypeRef) {55 ) (error{OutOfMemory}!*llvm.Type) {
55 switch (base.id) {56 switch (base.id) {
56 Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),57 Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),
57 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),58 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),
...@@ -77,6 +78,7 @@ pub const Type = struct {...@@ -77,6 +78,7 @@ pub const Type = struct {
77 Id.ArgTuple => unreachable,78 Id.ArgTuple => unreachable,
78 Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context),79 Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context),
79 Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(allocator, llvm_context),80 Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(allocator, llvm_context),
81 Id.Vector => return @fieldParentPtr(Vector, "base", base).getLlvmType(allocator, llvm_context),
80 }82 }
81 }83 }
8284
...@@ -103,6 +105,7 @@ pub const Type = struct {...@@ -103,6 +105,7 @@ pub const Type = struct {
103 Id.Enum,105 Id.Enum,
104 Id.Fn,106 Id.Fn,
105 Id.Promise,107 Id.Promise,
108 Id.Vector,
106 => return false,109 => return false,
107110
108 Id.Struct => @panic("TODO"),111 Id.Struct => @panic("TODO"),
...@@ -135,6 +138,7 @@ pub const Type = struct {...@@ -135,6 +138,7 @@ pub const Type = struct {
135 Id.Float,138 Id.Float,
136 Id.Fn,139 Id.Fn,
137 Id.Promise,140 Id.Promise,
141 Id.Vector,
138 => return true,142 => return true,
139143
140 Id.Pointer => {144 Id.Pointer => {
...@@ -192,7 +196,7 @@ pub const Type = struct {...@@ -192,7 +196,7 @@ pub const Type = struct {
192 }196 }
193197
194 /// If you have an llvm conext handy, you can use it here.198 /// If you have an llvm conext handy, you can use it here.
195 pub async fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: llvm.ContextRef) !u32 {199 pub async fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {
196 if (await (async base.abi_alignment.start() catch unreachable)) |ptr| return ptr.*;200 if (await (async base.abi_alignment.start() catch unreachable)) |ptr| return ptr.*;
197201
198 base.abi_alignment.data = await (async base.resolveAbiAlignment(comp, llvm_context) catch unreachable);202 base.abi_alignment.data = await (async base.resolveAbiAlignment(comp, llvm_context) catch unreachable);
...@@ -201,7 +205,7 @@ pub const Type = struct {...@@ -201,7 +205,7 @@ pub const Type = struct {
201 }205 }
202206
203 /// Lower level function that does the work. See getAbiAlignment.207 /// Lower level function that does the work. See getAbiAlignment.
204 async fn resolveAbiAlignment(base: *Type, comp: *Compilation, llvm_context: llvm.ContextRef) !u32 {208 async fn resolveAbiAlignment(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {
205 const llvm_type = try base.getLlvmType(comp.gpa(), llvm_context);209 const llvm_type = try base.getLlvmType(comp.gpa(), llvm_context);
206 return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type));210 return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type));
207 }211 }
...@@ -214,7 +218,7 @@ pub const Type = struct {...@@ -214,7 +218,7 @@ pub const Type = struct {
214 comp.gpa().destroy(self);218 comp.gpa().destroy(self);
215 }219 }
216220
217 pub fn getLlvmType(self: *Struct, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {221 pub fn getLlvmType(self: *Struct, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
218 @panic("TODO");222 @panic("TODO");
219 }223 }
220 };224 };
...@@ -409,7 +413,7 @@ pub const Type = struct {...@@ -409,7 +413,7 @@ pub const Type = struct {
409 key.ref();413 key.ref();
410 errdefer key.deref(comp);414 errdefer key.deref(comp);
411415
412 const self = try comp.gpa().createOne(Fn);416 const self = try comp.gpa().create(Fn);
413 self.* = Fn{417 self.* = Fn{
414 .base = undefined,418 .base = undefined,
415 .key = key,419 .key = key,
...@@ -492,13 +496,13 @@ pub const Type = struct {...@@ -492,13 +496,13 @@ pub const Type = struct {
492 comp.gpa().destroy(self);496 comp.gpa().destroy(self);
493 }497 }
494498
495 pub fn getLlvmType(self: *Fn, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef {499 pub fn getLlvmType(self: *Fn, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
496 const normal = &self.key.data.Normal;500 const normal = &self.key.data.Normal;
497 const llvm_return_type = switch (normal.return_type.id) {501 const llvm_return_type = switch (normal.return_type.id) {
498 Type.Id.Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory,502 Type.Id.Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory,
499 else => try normal.return_type.getLlvmType(allocator, llvm_context),503 else => try normal.return_type.getLlvmType(allocator, llvm_context),
500 };504 };
501 const llvm_param_types = try allocator.alloc(llvm.TypeRef, normal.params.len);505 const llvm_param_types = try allocator.alloc(*llvm.Type, normal.params.len);
502 defer allocator.free(llvm_param_types);506 defer allocator.free(llvm_param_types);
503 for (llvm_param_types) |*llvm_param_type, i| {507 for (llvm_param_types) |*llvm_param_type, i| {
504 llvm_param_type.* = try normal.params[i].typ.getLlvmType(allocator, llvm_context);508 llvm_param_type.* = try normal.params[i].typ.getLlvmType(allocator, llvm_context);
...@@ -555,7 +559,7 @@ pub const Type = struct {...@@ -555,7 +559,7 @@ pub const Type = struct {
555 comp.gpa().destroy(self);559 comp.gpa().destroy(self);
556 }560 }
557561
558 pub fn getLlvmType(self: *Bool, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {562 pub fn getLlvmType(self: *Bool, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
559 @panic("TODO");563 @panic("TODO");
560 }564 }
561 };565 };
...@@ -611,11 +615,12 @@ pub const Type = struct {...@@ -611,11 +615,12 @@ pub const Type = struct {
611 }615 }
612 }616 }
613617
614 const self = try comp.gpa().create(Int{618 const self = try comp.gpa().create(Int);
619 self.* = Int{
615 .base = undefined,620 .base = undefined,
616 .key = key,621 .key = key,
617 .garbage_node = undefined,622 .garbage_node = undefined,
618 });623 };
619 errdefer comp.gpa().destroy(self);624 errdefer comp.gpa().destroy(self);
620625
621 const u_or_i = "ui"[@boolToInt(key.is_signed)];626 const u_or_i = "ui"[@boolToInt(key.is_signed)];
...@@ -653,7 +658,7 @@ pub const Type = struct {...@@ -653,7 +658,7 @@ pub const Type = struct {
653 comp.gpa().destroy(self);658 comp.gpa().destroy(self);
654 }659 }
655660
656 pub fn getLlvmType(self: *Int, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef {661 pub fn getLlvmType(self: *Int, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
657 return llvm.IntTypeInContext(llvm_context, self.key.bit_count) orelse return error.OutOfMemory;662 return llvm.IntTypeInContext(llvm_context, self.key.bit_count) orelse return error.OutOfMemory;
658 }663 }
659 };664 };
...@@ -665,7 +670,7 @@ pub const Type = struct {...@@ -665,7 +670,7 @@ pub const Type = struct {
665 comp.gpa().destroy(self);670 comp.gpa().destroy(self);
666 }671 }
667672
668 pub fn getLlvmType(self: *Float, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {673 pub fn getLlvmType(self: *Float, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
669 @panic("TODO");674 @panic("TODO");
670 }675 }
671 };676 };
...@@ -777,17 +782,19 @@ pub const Type = struct {...@@ -777,17 +782,19 @@ pub const Type = struct {
777 }782 }
778 }783 }
779784
780 const self = try comp.gpa().create(Pointer{785 const self = try comp.gpa().create(Pointer);
786 self.* = Pointer{
781 .base = undefined,787 .base = undefined,
782 .key = normal_key,788 .key = normal_key,
783 .garbage_node = undefined,789 .garbage_node = undefined,
784 });790 };
785 errdefer comp.gpa().destroy(self);791 errdefer comp.gpa().destroy(self);
786792
787 const size_str = switch (self.key.size) {793 const size_str = switch (self.key.size) {
788 Size.One => "*",794 Size.One => "*",
789 Size.Many => "[*]",795 Size.Many => "[*]",
790 Size.Slice => "[]",796 Size.Slice => "[]",
797 Size.C => "[*c]",
791 };798 };
792 const mut_str = switch (self.key.mut) {799 const mut_str = switch (self.key.mut) {
793 Mut.Const => "const ",800 Mut.Const => "const ",
...@@ -829,7 +836,7 @@ pub const Type = struct {...@@ -829,7 +836,7 @@ pub const Type = struct {
829 return self;836 return self;
830 }837 }
831838
832 pub fn getLlvmType(self: *Pointer, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef {839 pub fn getLlvmType(self: *Pointer, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
833 const elem_llvm_type = try self.key.child_type.getLlvmType(allocator, llvm_context);840 const elem_llvm_type = try self.key.child_type.getLlvmType(allocator, llvm_context);
834 return llvm.PointerType(elem_llvm_type, 0) orelse return error.OutOfMemory;841 return llvm.PointerType(elem_llvm_type, 0) orelse return error.OutOfMemory;
835 }842 }
...@@ -875,11 +882,12 @@ pub const Type = struct {...@@ -875,11 +882,12 @@ pub const Type = struct {
875 }882 }
876 }883 }
877884
878 const self = try comp.gpa().create(Array{885 const self = try comp.gpa().create(Array);
886 self.* = Array{
879 .base = undefined,887 .base = undefined,
880 .key = key,888 .key = key,
881 .garbage_node = undefined,889 .garbage_node = undefined,
882 });890 };
883 errdefer comp.gpa().destroy(self);891 errdefer comp.gpa().destroy(self);
884892
885 const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", key.len, key.elem_type.name);893 const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", key.len, key.elem_type.name);
...@@ -896,12 +904,24 @@ pub const Type = struct {...@@ -896,12 +904,24 @@ pub const Type = struct {
896 return self;904 return self;
897 }905 }
898906
899 pub fn getLlvmType(self: *Array, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef {907 pub fn getLlvmType(self: *Array, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
900 const elem_llvm_type = try self.key.elem_type.getLlvmType(allocator, llvm_context);908 const elem_llvm_type = try self.key.elem_type.getLlvmType(allocator, llvm_context);
901 return llvm.ArrayType(elem_llvm_type, @intCast(c_uint, self.key.len)) orelse return error.OutOfMemory;909 return llvm.ArrayType(elem_llvm_type, @intCast(c_uint, self.key.len)) orelse return error.OutOfMemory;
902 }910 }
903 };911 };
904912
913 pub const Vector = struct {
914 base: Type,
915
916 pub fn destroy(self: *Vector, comp: *Compilation) void {
917 comp.gpa().destroy(self);
918 }
919
920 pub fn getLlvmType(self: *Vector, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
921 @panic("TODO");
922 }
923 };
924
905 pub const ComptimeFloat = struct {925 pub const ComptimeFloat = struct {
906 base: Type,926 base: Type,
907927
...@@ -947,7 +967,7 @@ pub const Type = struct {...@@ -947,7 +967,7 @@ pub const Type = struct {
947 comp.gpa().destroy(self);967 comp.gpa().destroy(self);
948 }968 }
949969
950 pub fn getLlvmType(self: *Optional, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {970 pub fn getLlvmType(self: *Optional, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
951 @panic("TODO");971 @panic("TODO");
952 }972 }
953 };973 };
...@@ -959,7 +979,7 @@ pub const Type = struct {...@@ -959,7 +979,7 @@ pub const Type = struct {
959 comp.gpa().destroy(self);979 comp.gpa().destroy(self);
960 }980 }
961981
962 pub fn getLlvmType(self: *ErrorUnion, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {982 pub fn getLlvmType(self: *ErrorUnion, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
963 @panic("TODO");983 @panic("TODO");
964 }984 }
965 };985 };
...@@ -971,7 +991,7 @@ pub const Type = struct {...@@ -971,7 +991,7 @@ pub const Type = struct {
971 comp.gpa().destroy(self);991 comp.gpa().destroy(self);
972 }992 }
973993
974 pub fn getLlvmType(self: *ErrorSet, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {994 pub fn getLlvmType(self: *ErrorSet, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
975 @panic("TODO");995 @panic("TODO");
976 }996 }
977 };997 };
...@@ -983,7 +1003,7 @@ pub const Type = struct {...@@ -983,7 +1003,7 @@ pub const Type = struct {
983 comp.gpa().destroy(self);1003 comp.gpa().destroy(self);
984 }1004 }
9851005
986 pub fn getLlvmType(self: *Enum, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {1006 pub fn getLlvmType(self: *Enum, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
987 @panic("TODO");1007 @panic("TODO");
988 }1008 }
989 };1009 };
...@@ -995,7 +1015,7 @@ pub const Type = struct {...@@ -995,7 +1015,7 @@ pub const Type = struct {
995 comp.gpa().destroy(self);1015 comp.gpa().destroy(self);
996 }1016 }
9971017
998 pub fn getLlvmType(self: *Union, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {1018 pub fn getLlvmType(self: *Union, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
999 @panic("TODO");1019 @panic("TODO");
1000 }1020 }
1001 };1021 };
...@@ -1015,7 +1035,7 @@ pub const Type = struct {...@@ -1015,7 +1035,7 @@ pub const Type = struct {
1015 comp.gpa().destroy(self);1035 comp.gpa().destroy(self);
1016 }1036 }
10171037
1018 pub fn getLlvmType(self: *BoundFn, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {1038 pub fn getLlvmType(self: *BoundFn, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
1019 @panic("TODO");1039 @panic("TODO");
1020 }1040 }
1021 };1041 };
...@@ -1035,7 +1055,7 @@ pub const Type = struct {...@@ -1035,7 +1055,7 @@ pub const Type = struct {
1035 comp.gpa().destroy(self);1055 comp.gpa().destroy(self);
1036 }1056 }
10371057
1038 pub fn getLlvmType(self: *Opaque, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {1058 pub fn getLlvmType(self: *Opaque, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
1039 @panic("TODO");1059 @panic("TODO");
1040 }1060 }
1041 };1061 };
...@@ -1047,7 +1067,7 @@ pub const Type = struct {...@@ -1047,7 +1067,7 @@ pub const Type = struct {
1047 comp.gpa().destroy(self);1067 comp.gpa().destroy(self);
1048 }1068 }
10491069
1050 pub fn getLlvmType(self: *Promise, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {1070 pub fn getLlvmType(self: *Promise, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
1051 @panic("TODO");1071 @panic("TODO");
1052 }1072 }
1053 };1073 };
...@@ -1069,6 +1089,7 @@ fn hashAny(x: var, comptime seed: u64) u32 {...@@ -1069,6 +1089,7 @@ fn hashAny(x: var, comptime seed: u64) u32 {
1069 builtin.TypeInfo.Pointer.Size.One => return hashAny(@ptrToInt(x), seed),1089 builtin.TypeInfo.Pointer.Size.One => return hashAny(@ptrToInt(x), seed),
1070 builtin.TypeInfo.Pointer.Size.Many => @compileError("implement hash function"),1090 builtin.TypeInfo.Pointer.Size.Many => @compileError("implement hash function"),
1071 builtin.TypeInfo.Pointer.Size.Slice => @compileError("implement hash function"),1091 builtin.TypeInfo.Pointer.Size.Slice => @compileError("implement hash function"),
1092 builtin.TypeInfo.Pointer.Size.C => unreachable,
1072 }1093 }
1073 },1094 },
1074 builtin.TypeId.Enum => return hashAny(@enumToInt(x), seed),1095 builtin.TypeId.Enum => return hashAny(@enumToInt(x), seed),
src-self-hosted/value.zig+30-23
...@@ -57,7 +57,7 @@ pub const Value = struct {...@@ -57,7 +57,7 @@ pub const Value = struct {
57 std.debug.warn("{}", @tagName(base.id));57 std.debug.warn("{}", @tagName(base.id));
58 }58 }
5959
60 pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?llvm.ValueRef) {60 pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?*llvm.Value) {
61 switch (base.id) {61 switch (base.id) {
62 Id.Type => unreachable,62 Id.Type => unreachable,
63 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile),63 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile),
...@@ -135,14 +135,15 @@ pub const Value = struct {...@@ -135,14 +135,15 @@ pub const Value = struct {
135 symbol_name: Buffer,135 symbol_name: Buffer,
136136
137 pub fn create(comp: *Compilation, fn_type: *Type.Fn, symbol_name: Buffer) !*FnProto {137 pub fn create(comp: *Compilation, fn_type: *Type.Fn, symbol_name: Buffer) !*FnProto {
138 const self = try comp.gpa().create(FnProto{138 const self = try comp.gpa().create(FnProto);
139 self.* = FnProto{
139 .base = Value{140 .base = Value{
140 .id = Value.Id.FnProto,141 .id = Value.Id.FnProto,
141 .typ = &fn_type.base,142 .typ = &fn_type.base,
142 .ref_count = std.atomic.Int(usize).init(1),143 .ref_count = std.atomic.Int(usize).init(1),
143 },144 },
144 .symbol_name = symbol_name,145 .symbol_name = symbol_name,
145 });146 };
146 fn_type.base.base.ref();147 fn_type.base.base.ref();
147 return self;148 return self;
148 }149 }
...@@ -152,7 +153,7 @@ pub const Value = struct {...@@ -152,7 +153,7 @@ pub const Value = struct {
152 comp.gpa().destroy(self);153 comp.gpa().destroy(self);
153 }154 }
154155
155 pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?llvm.ValueRef {156 pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?*llvm.Value {
156 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);157 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
157 const llvm_fn = llvm.AddFunction(158 const llvm_fn = llvm.AddFunction(
158 ofile.module,159 ofile.module,
...@@ -190,14 +191,16 @@ pub const Value = struct {...@@ -190,14 +191,16 @@ pub const Value = struct {
190 /// Creates a Fn value with 1 ref191 /// Creates a Fn value with 1 ref
191 /// Takes ownership of symbol_name192 /// Takes ownership of symbol_name
192 pub fn create(comp: *Compilation, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: Buffer) !*Fn {193 pub fn create(comp: *Compilation, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: Buffer) !*Fn {
193 const link_set_node = try comp.gpa().create(Compilation.FnLinkSet.Node{194 const link_set_node = try comp.gpa().create(Compilation.FnLinkSet.Node);
195 link_set_node.* = Compilation.FnLinkSet.Node{
194 .data = null,196 .data = null,
195 .next = undefined,197 .next = undefined,
196 .prev = undefined,198 .prev = undefined,
197 });199 };
198 errdefer comp.gpa().destroy(link_set_node);200 errdefer comp.gpa().destroy(link_set_node);
199201
200 const self = try comp.gpa().create(Fn{202 const self = try comp.gpa().create(Fn);
203 self.* = Fn{
201 .base = Value{204 .base = Value{
202 .id = Value.Id.Fn,205 .id = Value.Id.Fn,
203 .typ = &fn_type.base,206 .typ = &fn_type.base,
...@@ -209,7 +212,7 @@ pub const Value = struct {...@@ -209,7 +212,7 @@ pub const Value = struct {
209 .symbol_name = symbol_name,212 .symbol_name = symbol_name,
210 .containing_object = Buffer.initNull(comp.gpa()),213 .containing_object = Buffer.initNull(comp.gpa()),
211 .link_set_node = link_set_node,214 .link_set_node = link_set_node,
212 });215 };
213 fn_type.base.base.ref();216 fn_type.base.base.ref();
214 fndef_scope.fn_val = self;217 fndef_scope.fn_val = self;
215 fndef_scope.base.ref();218 fndef_scope.base.ref();
...@@ -235,7 +238,7 @@ pub const Value = struct {...@@ -235,7 +238,7 @@ pub const Value = struct {
235 /// We know that the function definition will end up in an .o file somewhere.238 /// We know that the function definition will end up in an .o file somewhere.
236 /// Here, all we have to do is generate a global prototype.239 /// Here, all we have to do is generate a global prototype.
237 /// TODO cache the prototype per ObjectFile240 /// TODO cache the prototype per ObjectFile
238 pub fn getLlvmConst(self: *Fn, ofile: *ObjectFile) !?llvm.ValueRef {241 pub fn getLlvmConst(self: *Fn, ofile: *ObjectFile) !?*llvm.Value {
239 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);242 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
240 const llvm_fn = llvm.AddFunction(243 const llvm_fn = llvm.AddFunction(
241 ofile.module,244 ofile.module,
...@@ -280,8 +283,8 @@ pub const Value = struct {...@@ -280,8 +283,8 @@ pub const Value = struct {
280 comp.gpa().destroy(self);283 comp.gpa().destroy(self);
281 }284 }
282285
283 pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) ?llvm.ValueRef {286 pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) !?*llvm.Value {
284 const llvm_type = llvm.Int1TypeInContext(ofile.context);287 const llvm_type = llvm.Int1TypeInContext(ofile.context) orelse return error.OutOfMemory;
285 if (self.x) {288 if (self.x) {
286 return llvm.ConstAllOnes(llvm_type);289 return llvm.ConstAllOnes(llvm_type);
287 } else {290 } else {
...@@ -353,7 +356,8 @@ pub const Value = struct {...@@ -353,7 +356,8 @@ pub const Value = struct {
353 var ptr_type_consumed = false;356 var ptr_type_consumed = false;
354 errdefer if (!ptr_type_consumed) ptr_type.base.base.deref(comp);357 errdefer if (!ptr_type_consumed) ptr_type.base.base.deref(comp);
355358
356 const self = try comp.gpa().create(Value.Ptr{359 const self = try comp.gpa().create(Value.Ptr);
360 self.* = Value.Ptr{
357 .base = Value{361 .base = Value{
358 .id = Value.Id.Ptr,362 .id = Value.Id.Ptr,
359 .typ = &ptr_type.base,363 .typ = &ptr_type.base,
...@@ -366,7 +370,7 @@ pub const Value = struct {...@@ -366,7 +370,7 @@ pub const Value = struct {
366 },370 },
367 },371 },
368 .mut = Mut.CompTimeConst,372 .mut = Mut.CompTimeConst,
369 });373 };
370 ptr_type_consumed = true;374 ptr_type_consumed = true;
371 errdefer comp.gpa().destroy(self);375 errdefer comp.gpa().destroy(self);
372376
...@@ -377,7 +381,7 @@ pub const Value = struct {...@@ -377,7 +381,7 @@ pub const Value = struct {
377 comp.gpa().destroy(self);381 comp.gpa().destroy(self);
378 }382 }
379383
380 pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?llvm.ValueRef {384 pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?*llvm.Value {
381 const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context);385 const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context);
382 // TODO carefully port the logic from codegen.cpp:gen_const_val_ptr386 // TODO carefully port the logic from codegen.cpp:gen_const_val_ptr
383 switch (self.special) {387 switch (self.special) {
...@@ -387,7 +391,7 @@ pub const Value = struct {...@@ -387,7 +391,7 @@ pub const Value = struct {
387 const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;391 const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;
388 const ptr_bit_count = ofile.comp.target_ptr_bits;392 const ptr_bit_count = ofile.comp.target_ptr_bits;
389 const usize_llvm_type = llvm.IntTypeInContext(ofile.context, ptr_bit_count) orelse return error.OutOfMemory;393 const usize_llvm_type = llvm.IntTypeInContext(ofile.context, ptr_bit_count) orelse return error.OutOfMemory;
390 const indices = []llvm.ValueRef{394 const indices = []*llvm.Value{
391 llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory,395 llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory,
392 llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory,396 llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory,
393 };397 };
...@@ -430,14 +434,15 @@ pub const Value = struct {...@@ -430,14 +434,15 @@ pub const Value = struct {
430 }) catch unreachable);434 }) catch unreachable);
431 errdefer array_type.base.base.deref(comp);435 errdefer array_type.base.base.deref(comp);
432436
433 const self = try comp.gpa().create(Value.Array{437 const self = try comp.gpa().create(Value.Array);
438 self.* = Value.Array{
434 .base = Value{439 .base = Value{
435 .id = Value.Id.Array,440 .id = Value.Id.Array,
436 .typ = &array_type.base,441 .typ = &array_type.base,
437 .ref_count = std.atomic.Int(usize).init(1),442 .ref_count = std.atomic.Int(usize).init(1),
438 },443 },
439 .special = Special{ .OwnedBuffer = buffer },444 .special = Special{ .OwnedBuffer = buffer },
440 });445 };
441 errdefer comp.gpa().destroy(self);446 errdefer comp.gpa().destroy(self);
442447
443 return self;448 return self;
...@@ -454,7 +459,7 @@ pub const Value = struct {...@@ -454,7 +459,7 @@ pub const Value = struct {
454 comp.gpa().destroy(self);459 comp.gpa().destroy(self);
455 }460 }
456461
457 pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?llvm.ValueRef {462 pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?*llvm.Value {
458 switch (self.special) {463 switch (self.special) {
459 Special.Undefined => {464 Special.Undefined => {
460 const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);465 const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
...@@ -509,14 +514,15 @@ pub const Value = struct {...@@ -509,14 +514,15 @@ pub const Value = struct {
509 big_int: std.math.big.Int,514 big_int: std.math.big.Int,
510515
511 pub fn createFromString(comp: *Compilation, typ: *Type, base: u8, value: []const u8) !*Int {516 pub fn createFromString(comp: *Compilation, typ: *Type, base: u8, value: []const u8) !*Int {
512 const self = try comp.gpa().create(Value.Int{517 const self = try comp.gpa().create(Value.Int);
518 self.* = Value.Int{
513 .base = Value{519 .base = Value{
514 .id = Value.Id.Int,520 .id = Value.Id.Int,
515 .typ = typ,521 .typ = typ,
516 .ref_count = std.atomic.Int(usize).init(1),522 .ref_count = std.atomic.Int(usize).init(1),
517 },523 },
518 .big_int = undefined,524 .big_int = undefined,
519 });525 };
520 typ.base.ref();526 typ.base.ref();
521 errdefer comp.gpa().destroy(self);527 errdefer comp.gpa().destroy(self);
522528
...@@ -528,7 +534,7 @@ pub const Value = struct {...@@ -528,7 +534,7 @@ pub const Value = struct {
528 return self;534 return self;
529 }535 }
530536
531 pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?llvm.ValueRef {537 pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?*llvm.Value {
532 switch (self.base.typ.id) {538 switch (self.base.typ.id) {
533 Type.Id.Int => {539 Type.Id.Int => {
534 const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);540 const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
...@@ -557,14 +563,15 @@ pub const Value = struct {...@@ -557,14 +563,15 @@ pub const Value = struct {
557 old.base.typ.base.ref();563 old.base.typ.base.ref();
558 errdefer old.base.typ.base.deref(comp);564 errdefer old.base.typ.base.deref(comp);
559565
560 const new = try comp.gpa().create(Value.Int{566 const new = try comp.gpa().create(Value.Int);
567 new.* = Value.Int{
561 .base = Value{568 .base = Value{
562 .id = Value.Id.Int,569 .id = Value.Id.Int,
563 .typ = old.base.typ,570 .typ = old.base.typ,
564 .ref_count = std.atomic.Int(usize).init(1),571 .ref_count = std.atomic.Int(usize).init(1),
565 },572 },
566 .big_int = undefined,573 .big_int = undefined,
567 });574 };
568 errdefer comp.gpa().destroy(new);575 errdefer comp.gpa().destroy(new);
569576
570 new.big_int = try old.big_int.clone();577 new.big_int = try old.big_int.clone();
src/all_types.hpp+212-61
...@@ -56,9 +56,6 @@ struct IrExecutable {...@@ -56,9 +56,6 @@ struct IrExecutable {
56 size_t next_debug_id;56 size_t next_debug_id;
57 size_t *backward_branch_count;57 size_t *backward_branch_count;
58 size_t backward_branch_quota;58 size_t backward_branch_quota;
59 bool invalid;
60 bool is_inline;
61 bool is_generic_instantiation;
62 ZigFn *fn_entry;59 ZigFn *fn_entry;
63 Buf *c_import_buf;60 Buf *c_import_buf;
64 AstNode *source_node;61 AstNode *source_node;
...@@ -78,6 +75,10 @@ struct IrExecutable {...@@ -78,6 +75,10 @@ struct IrExecutable {
78 IrBasicBlock *coro_suspend_block;75 IrBasicBlock *coro_suspend_block;
79 IrBasicBlock *coro_final_cleanup_block;76 IrBasicBlock *coro_final_cleanup_block;
80 ZigVar *coro_allocator_var;77 ZigVar *coro_allocator_var;
78
79 bool invalid;
80 bool is_inline;
81 bool is_generic_instantiation;
81};82};
8283
83enum OutType {84enum OutType {
...@@ -90,6 +91,9 @@ enum OutType {...@@ -90,6 +91,9 @@ enum OutType {
90enum ConstParentId {91enum ConstParentId {
91 ConstParentIdNone,92 ConstParentIdNone,
92 ConstParentIdStruct,93 ConstParentIdStruct,
94 ConstParentIdErrUnionCode,
95 ConstParentIdErrUnionPayload,
96 ConstParentIdOptionalPayload,
93 ConstParentIdArray,97 ConstParentIdArray,
94 ConstParentIdUnion,98 ConstParentIdUnion,
95 ConstParentIdScalar,99 ConstParentIdScalar,
...@@ -107,6 +111,15 @@ struct ConstParent {...@@ -107,6 +111,15 @@ struct ConstParent {
107 ConstExprValue *struct_val;111 ConstExprValue *struct_val;
108 size_t field_index;112 size_t field_index;
109 } p_struct;113 } p_struct;
114 struct {
115 ConstExprValue *err_union_val;
116 } p_err_union_code;
117 struct {
118 ConstExprValue *err_union_val;
119 } p_err_union_payload;
120 struct {
121 ConstExprValue *optional_val;
122 } p_optional_payload;
110 struct {123 struct {
111 ConstExprValue *union_val;124 ConstExprValue *union_val;
112 } p_union;125 } p_union;
...@@ -118,13 +131,11 @@ struct ConstParent {...@@ -118,13 +131,11 @@ struct ConstParent {
118131
119struct ConstStructValue {132struct ConstStructValue {
120 ConstExprValue *fields;133 ConstExprValue *fields;
121 ConstParent parent;
122};134};
123135
124struct ConstUnionValue {136struct ConstUnionValue {
125 BigInt tag;137 BigInt tag;
126 ConstExprValue *payload;138 ConstExprValue *payload;
127 ConstParent parent;
128};139};
129140
130enum ConstArraySpecial {141enum ConstArraySpecial {
...@@ -138,7 +149,6 @@ struct ConstArrayValue {...@@ -138,7 +149,6 @@ struct ConstArrayValue {
138 union {149 union {
139 struct {150 struct {
140 ConstExprValue *elements;151 ConstExprValue *elements;
141 ConstParent parent;
142 } s_none;152 } s_none;
143 Buf *s_buf;153 Buf *s_buf;
144 } data;154 } data;
...@@ -153,19 +163,29 @@ enum ConstPtrSpecial {...@@ -153,19 +163,29 @@ enum ConstPtrSpecial {
153 ConstPtrSpecialBaseArray,163 ConstPtrSpecialBaseArray,
154 // The pointer points to a field in an underlying struct.164 // The pointer points to a field in an underlying struct.
155 ConstPtrSpecialBaseStruct,165 ConstPtrSpecialBaseStruct,
166 // The pointer points to the error set field of an error union
167 ConstPtrSpecialBaseErrorUnionCode,
168 // The pointer points to the payload field of an error union
169 ConstPtrSpecialBaseErrorUnionPayload,
170 // The pointer points to the payload field of an optional
171 ConstPtrSpecialBaseOptionalPayload,
156 // This means that we did a compile-time pointer reinterpret and we cannot172 // This means that we did a compile-time pointer reinterpret and we cannot
157 // understand the value of pointee at compile time. However, we will still173 // understand the value of pointee at compile time. However, we will still
158 // emit a binary with a compile time known address.174 // emit a binary with a compile time known address.
159 // In this case index is the numeric address value.175 // In this case index is the numeric address value.
160 // We also use this for null pointer. We need the data layout for ConstCastOnly == true
161 // types to be the same, so all optionals of pointer types use x_ptr
162 // instead of x_optional
163 ConstPtrSpecialHardCodedAddr,176 ConstPtrSpecialHardCodedAddr,
164 // This means that the pointer represents memory of assigning to _.177 // This means that the pointer represents memory of assigning to _.
165 // That is, storing discards the data, and loading is invalid.178 // That is, storing discards the data, and loading is invalid.
166 ConstPtrSpecialDiscard,179 ConstPtrSpecialDiscard,
167 // This is actually a function.180 // This is actually a function.
168 ConstPtrSpecialFunction,181 ConstPtrSpecialFunction,
182 // This means the pointer is null. This is only allowed when the type is ?*T.
183 // We use this instead of ConstPtrSpecialHardCodedAddr because often we check
184 // for that value to avoid doing comptime work.
185 // We need the data layout for ConstCastOnly == true
186 // types to be the same, so all optionals of pointer types use x_ptr
187 // instead of x_optional.
188 ConstPtrSpecialNull,
169};189};
170190
171enum ConstPtrMut {191enum ConstPtrMut {
...@@ -199,6 +219,15 @@ struct ConstPtrValue {...@@ -199,6 +219,15 @@ struct ConstPtrValue {
199 ConstExprValue *struct_val;219 ConstExprValue *struct_val;
200 size_t field_index;220 size_t field_index;
201 } base_struct;221 } base_struct;
222 struct {
223 ConstExprValue *err_union_val;
224 } base_err_union_code;
225 struct {
226 ConstExprValue *err_union_val;
227 } base_err_union_payload;
228 struct {
229 ConstExprValue *optional_val;
230 } base_optional_payload;
202 struct {231 struct {
203 uint64_t addr;232 uint64_t addr;
204 } hard_coded_addr;233 } hard_coded_addr;
...@@ -209,7 +238,7 @@ struct ConstPtrValue {...@@ -209,7 +238,7 @@ struct ConstPtrValue {
209};238};
210239
211struct ConstErrValue {240struct ConstErrValue {
212 ErrorTableEntry *err;241 ConstExprValue *error_set;
213 ConstExprValue *payload;242 ConstExprValue *payload;
214};243};
215244
...@@ -265,6 +294,7 @@ struct ConstGlobalRefs {...@@ -265,6 +294,7 @@ struct ConstGlobalRefs {
265struct ConstExprValue {294struct ConstExprValue {
266 ZigType *type;295 ZigType *type;
267 ConstValSpecial special;296 ConstValSpecial special;
297 ConstParent parent;
268 ConstGlobalRefs *global_refs;298 ConstGlobalRefs *global_refs;
269299
270 union {300 union {
...@@ -433,7 +463,7 @@ enum NodeType {...@@ -433,7 +463,7 @@ enum NodeType {
433 NodeTypeArrayType,463 NodeTypeArrayType,
434 NodeTypeErrorType,464 NodeTypeErrorType,
435 NodeTypeIfErrorExpr,465 NodeTypeIfErrorExpr,
436 NodeTypeTestExpr,466 NodeTypeIfOptional,
437 NodeTypeErrorSetDecl,467 NodeTypeErrorSetDecl,
438 NodeTypeCancel,468 NodeTypeCancel,
439 NodeTypeResume,469 NodeTypeResume,
...@@ -514,12 +544,7 @@ struct AstNodeDefer {...@@ -514,12 +544,7 @@ struct AstNodeDefer {
514};544};
515545
516struct AstNodeVariableDeclaration {546struct AstNodeVariableDeclaration {
517 VisibMod visib_mod;
518 Buf *symbol;547 Buf *symbol;
519 bool is_const;
520 bool is_comptime;
521 bool is_export;
522 bool is_extern;
523 // one or both of type and expr will be non null548 // one or both of type and expr will be non null
524 AstNode *type;549 AstNode *type;
525 AstNode *expr;550 AstNode *expr;
...@@ -529,6 +554,13 @@ struct AstNodeVariableDeclaration {...@@ -529,6 +554,13 @@ struct AstNodeVariableDeclaration {
529 AstNode *align_expr;554 AstNode *align_expr;
530 // populated if the "section(S)" is present555 // populated if the "section(S)" is present
531 AstNode *section_expr;556 AstNode *section_expr;
557 Token *threadlocal_tok;
558
559 VisibMod visib_mod;
560 bool is_const;
561 bool is_comptime;
562 bool is_export;
563 bool is_extern;
532};564};
533565
534struct AstNodeTestDecl {566struct AstNodeTestDecl {
...@@ -605,7 +637,6 @@ enum CastOp {...@@ -605,7 +637,6 @@ enum CastOp {
605 CastOpFloatToInt,637 CastOpFloatToInt,
606 CastOpBoolToInt,638 CastOpBoolToInt,
607 CastOpResizeSlice,639 CastOpResizeSlice,
608 CastOpBytesToSlice,
609 CastOpNumLitToConcrete,640 CastOpNumLitToConcrete,
610 CastOpErrSet,641 CastOpErrSet,
611 CastOpBitCast,642 CastOpBitCast,
...@@ -660,15 +691,17 @@ struct AstNodePointerType {...@@ -660,15 +691,17 @@ struct AstNodePointerType {
660 AstNode *align_expr;691 AstNode *align_expr;
661 BigInt *bit_offset_start;692 BigInt *bit_offset_start;
662 BigInt *host_int_bytes;693 BigInt *host_int_bytes;
694 AstNode *op_expr;
695 Token *allow_zero_token;
663 bool is_const;696 bool is_const;
664 bool is_volatile;697 bool is_volatile;
665 AstNode *op_expr;
666};698};
667699
668struct AstNodeArrayType {700struct AstNodeArrayType {
669 AstNode *size;701 AstNode *size;
670 AstNode *child_type;702 AstNode *child_type;
671 AstNode *align_expr;703 AstNode *align_expr;
704 Token *allow_zero_token;
672 bool is_const;705 bool is_const;
673 bool is_volatile;706 bool is_volatile;
674};707};
...@@ -678,7 +711,7 @@ struct AstNodeUse {...@@ -678,7 +711,7 @@ struct AstNodeUse {
678 AstNode *expr;711 AstNode *expr;
679712
680 TldResolution resolution;713 TldResolution resolution;
681 IrInstruction *value;714 ConstExprValue *value;
682};715};
683716
684struct AstNodeIfBoolExpr {717struct AstNodeIfBoolExpr {
...@@ -1007,6 +1040,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);...@@ -1007,6 +1040,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
1007enum PtrLen {1040enum PtrLen {
1008 PtrLenUnknown,1041 PtrLenUnknown,
1009 PtrLenSingle,1042 PtrLenSingle,
1043 PtrLenC,
1010};1044};
10111045
1012struct ZigTypePointer {1046struct ZigTypePointer {
...@@ -1018,6 +1052,7 @@ struct ZigTypePointer {...@@ -1018,6 +1052,7 @@ struct ZigTypePointer {
1018 uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned1052 uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned
1019 bool is_const;1053 bool is_const;
1020 bool is_volatile;1054 bool is_volatile;
1055 bool allow_zero;
1021};1056};
10221057
1023struct ZigTypeInt {1058struct ZigTypeInt {
...@@ -1167,6 +1202,7 @@ struct ZigTypeFn {...@@ -1167,6 +1202,7 @@ struct ZigTypeFn {
1167 FnGenParamInfo *gen_param_info;1202 FnGenParamInfo *gen_param_info;
11681203
1169 LLVMTypeRef raw_type_ref;1204 LLVMTypeRef raw_type_ref;
1205 ZigLLVMDIType *raw_di_type;
11701206
1171 ZigType *bound_fn_parent;1207 ZigType *bound_fn_parent;
1172};1208};
...@@ -1180,6 +1216,12 @@ struct ZigTypePromise {...@@ -1180,6 +1216,12 @@ struct ZigTypePromise {
1180 ZigType *result_type;1216 ZigType *result_type;
1181};1217};
11821218
1219struct ZigTypeVector {
1220 // The type must be a pointer, integer, or float
1221 ZigType *elem_type;
1222 uint32_t len;
1223};
1224
1183enum ZigTypeId {1225enum ZigTypeId {
1184 ZigTypeIdInvalid,1226 ZigTypeIdInvalid,
1185 ZigTypeIdMetaType,1227 ZigTypeIdMetaType,
...@@ -1206,6 +1248,7 @@ enum ZigTypeId {...@@ -1206,6 +1248,7 @@ enum ZigTypeId {
1206 ZigTypeIdArgTuple,1248 ZigTypeIdArgTuple,
1207 ZigTypeIdOpaque,1249 ZigTypeIdOpaque,
1208 ZigTypeIdPromise,1250 ZigTypeIdPromise,
1251 ZigTypeIdVector,
1209};1252};
12101253
1211struct ZigType {1254struct ZigType {
...@@ -1232,6 +1275,7 @@ struct ZigType {...@@ -1232,6 +1275,7 @@ struct ZigType {
1232 ZigTypeFn fn;1275 ZigTypeFn fn;
1233 ZigTypeBoundFn bound_fn;1276 ZigTypeBoundFn bound_fn;
1234 ZigTypePromise promise;1277 ZigTypePromise promise;
1278 ZigTypeVector vector;
1235 } data;1279 } data;
12361280
1237 // use these fields to make sure we don't duplicate type table entries for the same type1281 // use these fields to make sure we don't duplicate type table entries for the same type
...@@ -1385,6 +1429,7 @@ enum BuiltinFnId {...@@ -1385,6 +1429,7 @@ enum BuiltinFnId {
1385 BuiltinFnIdEnumToInt,1429 BuiltinFnIdEnumToInt,
1386 BuiltinFnIdIntToEnum,1430 BuiltinFnIdIntToEnum,
1387 BuiltinFnIdIntType,1431 BuiltinFnIdIntType,
1432 BuiltinFnIdVectorType,
1388 BuiltinFnIdSetCold,1433 BuiltinFnIdSetCold,
1389 BuiltinFnIdSetRuntimeSafety,1434 BuiltinFnIdSetRuntimeSafety,
1390 BuiltinFnIdSetFloatMode,1435 BuiltinFnIdSetFloatMode,
...@@ -1415,6 +1460,8 @@ enum BuiltinFnId {...@@ -1415,6 +1460,8 @@ enum BuiltinFnId {
1415 BuiltinFnIdErrorReturnTrace,1460 BuiltinFnIdErrorReturnTrace,
1416 BuiltinFnIdAtomicRmw,1461 BuiltinFnIdAtomicRmw,
1417 BuiltinFnIdAtomicLoad,1462 BuiltinFnIdAtomicLoad,
1463 BuiltinFnIdBswap,
1464 BuiltinFnIdBitReverse,
1418};1465};
14191466
1420struct BuiltinFnEntry {1467struct BuiltinFnEntry {
...@@ -1441,6 +1488,7 @@ enum PanicMsgId {...@@ -1441,6 +1488,7 @@ enum PanicMsgId {
1441 PanicMsgIdBadUnionField,1488 PanicMsgIdBadUnionField,
1442 PanicMsgIdBadEnumValue,1489 PanicMsgIdBadEnumValue,
1443 PanicMsgIdFloatToInt,1490 PanicMsgIdFloatToInt,
1491 PanicMsgIdPtrCastNull,
14441492
1445 PanicMsgIdCount,1493 PanicMsgIdCount,
1446};1494};
...@@ -1455,11 +1503,12 @@ struct TypeId {...@@ -1455,11 +1503,12 @@ struct TypeId {
1455 struct {1503 struct {
1456 ZigType *child_type;1504 ZigType *child_type;
1457 PtrLen ptr_len;1505 PtrLen ptr_len;
1458 bool is_const;
1459 bool is_volatile;
1460 uint32_t alignment;1506 uint32_t alignment;
1461 uint32_t bit_offset_in_host;1507 uint32_t bit_offset_in_host;
1462 uint32_t host_int_bytes;1508 uint32_t host_int_bytes;
1509 bool is_const;
1510 bool is_volatile;
1511 bool allow_zero;
1463 } pointer;1512 } pointer;
1464 struct {1513 struct {
1465 ZigType *child_type;1514 ZigType *child_type;
...@@ -1473,6 +1522,10 @@ struct TypeId {...@@ -1473,6 +1522,10 @@ struct TypeId {
1473 ZigType *err_set_type;1522 ZigType *err_set_type;
1474 ZigType *payload_type;1523 ZigType *payload_type;
1475 } error_union;1524 } error_union;
1525 struct {
1526 ZigType *elem_type;
1527 uint32_t len;
1528 } vector;
1476 } data;1529 } data;
1477};1530};
14781531
...@@ -1487,8 +1540,12 @@ enum ZigLLVMFnId {...@@ -1487,8 +1540,12 @@ enum ZigLLVMFnId {
1487 ZigLLVMFnIdFloor,1540 ZigLLVMFnIdFloor,
1488 ZigLLVMFnIdCeil,1541 ZigLLVMFnIdCeil,
1489 ZigLLVMFnIdSqrt,1542 ZigLLVMFnIdSqrt,
1543 ZigLLVMFnIdBswap,
1544 ZigLLVMFnIdBitReverse,
1490};1545};
14911546
1547// There are a bunch of places in code that rely on these values being in
1548// exactly this order.
1492enum AddSubMul {1549enum AddSubMul {
1493 AddSubMulAdd = 0,1550 AddSubMulAdd = 0,
1494 AddSubMulSub = 1,1551 AddSubMulSub = 1,
...@@ -1514,8 +1571,15 @@ struct ZigLLVMFnKey {...@@ -1514,8 +1571,15 @@ struct ZigLLVMFnKey {
1514 struct {1571 struct {
1515 AddSubMul add_sub_mul;1572 AddSubMul add_sub_mul;
1516 uint32_t bit_count;1573 uint32_t bit_count;
1574 uint32_t vector_len; // 0 means not a vector
1517 bool is_signed;1575 bool is_signed;
1518 } overflow_arithmetic;1576 } overflow_arithmetic;
1577 struct {
1578 uint32_t bit_count;
1579 } bswap;
1580 struct {
1581 uint32_t bit_count;
1582 } bit_reverse;
1519 } data;1583 } data;
1520};1584};
15211585
...@@ -1600,7 +1664,7 @@ struct CodeGen {...@@ -1600,7 +1664,7 @@ struct CodeGen {
1600 HashMap<FnTypeId *, ZigType *, fn_type_id_hash, fn_type_id_eql> fn_type_table;1664 HashMap<FnTypeId *, ZigType *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
1601 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;1665 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
1602 HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;1666 HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;
1603 HashMap<Scope *, IrInstruction *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;1667 HashMap<Scope *, ConstExprValue *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;
1604 HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;1668 HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;
1605 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names;1669 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names;
1606 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;1670 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
...@@ -1694,6 +1758,7 @@ struct CodeGen {...@@ -1694,6 +1758,7 @@ struct CodeGen {
1694 ZigFn *cur_fn;1758 ZigFn *cur_fn;
1695 ZigFn *main_fn;1759 ZigFn *main_fn;
1696 ZigFn *panic_fn;1760 ZigFn *panic_fn;
1761 TldFn *panic_tld_fn;
1697 AstNode *root_export_decl;1762 AstNode *root_export_decl;
16981763
1699 CacheHash cache_hash;1764 CacheHash cache_hash;
...@@ -1746,12 +1811,12 @@ struct CodeGen {...@@ -1746,12 +1811,12 @@ struct CodeGen {
1746 BuildMode build_mode;1811 BuildMode build_mode;
1747 OutType out_type;1812 OutType out_type;
1748 ZigTarget zig_target;1813 ZigTarget zig_target;
1814 TargetSubsystem subsystem;
1749 bool is_static;1815 bool is_static;
1750 bool strip_debug_symbols;1816 bool strip_debug_symbols;
1751 bool is_test_build;1817 bool is_test_build;
1818 bool is_single_threaded;
1752 bool is_native_target;1819 bool is_native_target;
1753 bool windows_subsystem_windows;
1754 bool windows_subsystem_console;
1755 bool linker_rdynamic;1820 bool linker_rdynamic;
1756 bool no_rosegment_workaround;1821 bool no_rosegment_workaround;
1757 bool each_lib_rpath;1822 bool each_lib_rpath;
...@@ -1793,10 +1858,9 @@ enum VarLinkage {...@@ -1793,10 +1858,9 @@ enum VarLinkage {
17931858
1794struct ZigVar {1859struct ZigVar {
1795 Buf name;1860 Buf name;
1796 ConstExprValue *value;1861 ConstExprValue *const_value;
1862 ZigType *var_type;
1797 LLVMValueRef value_ref;1863 LLVMValueRef value_ref;
1798 bool src_is_const;
1799 bool gen_is_const;
1800 IrInstruction *is_comptime;1864 IrInstruction *is_comptime;
1801 // which node is the declaration of the variable1865 // which node is the declaration of the variable
1802 AstNode *decl_node;1866 AstNode *decl_node;
...@@ -1806,17 +1870,22 @@ struct ZigVar {...@@ -1806,17 +1870,22 @@ struct ZigVar {
1806 Scope *parent_scope;1870 Scope *parent_scope;
1807 Scope *child_scope;1871 Scope *child_scope;
1808 LLVMValueRef param_value_ref;1872 LLVMValueRef param_value_ref;
1809 bool shadowable;
1810 size_t mem_slot_index;1873 size_t mem_slot_index;
1811 IrExecutable *owner_exec;1874 IrExecutable *owner_exec;
1812 size_t ref_count;1875 size_t ref_count;
1813 VarLinkage linkage;
1814 uint32_t align_bytes;
18151876
1816 // In an inline loop, multiple variables may be created,1877 // In an inline loop, multiple variables may be created,
1817 // In this case, a reference to a variable should follow1878 // In this case, a reference to a variable should follow
1818 // this pointer to the redefined variable.1879 // this pointer to the redefined variable.
1819 ZigVar *next_var;1880 ZigVar *next_var;
1881
1882 uint32_t align_bytes;
1883 VarLinkage linkage;
1884
1885 bool shadowable;
1886 bool src_is_const;
1887 bool gen_is_const;
1888 bool is_thread_local;
1820};1889};
18211890
1822struct ErrorTableEntry {1891struct ErrorTableEntry {
...@@ -1882,10 +1951,11 @@ struct ScopeBlock {...@@ -1882,10 +1951,11 @@ struct ScopeBlock {
1882 ZigList<IrInstruction *> *incoming_values;1951 ZigList<IrInstruction *> *incoming_values;
1883 ZigList<IrBasicBlock *> *incoming_blocks;1952 ZigList<IrBasicBlock *> *incoming_blocks;
18841953
1885 bool safety_off;
1886 AstNode *safety_set_node;1954 AstNode *safety_set_node;
1887 bool fast_math_on;
1888 AstNode *fast_math_set_node;1955 AstNode *fast_math_set_node;
1956
1957 bool safety_off;
1958 bool fast_math_on;
1889};1959};
18901960
1891// This scope is created from every defer expression.1961// This scope is created from every defer expression.
...@@ -2021,8 +2091,19 @@ struct IrBasicBlock {...@@ -2021,8 +2091,19 @@ struct IrBasicBlock {
2021 IrInstruction *must_be_comptime_source_instr;2091 IrInstruction *must_be_comptime_source_instr;
2022};2092};
20232093
2094// These instructions are in transition to having "pass 1" instructions
2095// and "pass 2" instructions. The pass 1 instructions are suffixed with Src
2096// and pass 2 are suffixed with Gen.
2097// Once all instructions are separated in this way, they'll have different
2098// base types for better type safety.
2099// Src instructions are generated by ir_gen_* functions in ir.cpp from AST.
2100// ir_analyze_* functions consume Src instructions and produce Gen instructions.
2101// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR.
2102// Src instructions do not have type information; Gen instructions do.
2024enum IrInstructionId {2103enum IrInstructionId {
2025 IrInstructionIdInvalid,2104 IrInstructionIdInvalid,
2105 IrInstructionIdDeclVarSrc,
2106 IrInstructionIdDeclVarGen,
2026 IrInstructionIdBr,2107 IrInstructionIdBr,
2027 IrInstructionIdCondBr,2108 IrInstructionIdCondBr,
2028 IrInstructionIdSwitchBr,2109 IrInstructionIdSwitchBr,
...@@ -2031,7 +2112,6 @@ enum IrInstructionId {...@@ -2031,7 +2112,6 @@ enum IrInstructionId {
2031 IrInstructionIdPhi,2112 IrInstructionIdPhi,
2032 IrInstructionIdUnOp,2113 IrInstructionIdUnOp,
2033 IrInstructionIdBinOp,2114 IrInstructionIdBinOp,
2034 IrInstructionIdDeclVar,
2035 IrInstructionIdLoadPtr,2115 IrInstructionIdLoadPtr,
2036 IrInstructionIdStorePtr,2116 IrInstructionIdStorePtr,
2037 IrInstructionIdFieldPtr,2117 IrInstructionIdFieldPtr,
...@@ -2060,7 +2140,7 @@ enum IrInstructionId {...@@ -2060,7 +2140,7 @@ enum IrInstructionId {
2060 IrInstructionIdAsm,2140 IrInstructionIdAsm,
2061 IrInstructionIdSizeOf,2141 IrInstructionIdSizeOf,
2062 IrInstructionIdTestNonNull,2142 IrInstructionIdTestNonNull,
2063 IrInstructionIdUnwrapOptional,2143 IrInstructionIdOptionalUnwrapPtr,
2064 IrInstructionIdOptionalWrap,2144 IrInstructionIdOptionalWrap,
2065 IrInstructionIdUnionTag,2145 IrInstructionIdUnionTag,
2066 IrInstructionIdClz,2146 IrInstructionIdClz,
...@@ -2076,7 +2156,8 @@ enum IrInstructionId {...@@ -2076,7 +2156,8 @@ enum IrInstructionId {
2076 IrInstructionIdCompileLog,2156 IrInstructionIdCompileLog,
2077 IrInstructionIdErrName,2157 IrInstructionIdErrName,
2078 IrInstructionIdEmbedFile,2158 IrInstructionIdEmbedFile,
2079 IrInstructionIdCmpxchg,2159 IrInstructionIdCmpxchgSrc,
2160 IrInstructionIdCmpxchgGen,
2080 IrInstructionIdFence,2161 IrInstructionIdFence,
2081 IrInstructionIdTruncate,2162 IrInstructionIdTruncate,
2082 IrInstructionIdIntCast,2163 IrInstructionIdIntCast,
...@@ -2085,6 +2166,7 @@ enum IrInstructionId {...@@ -2085,6 +2166,7 @@ enum IrInstructionId {
2085 IrInstructionIdFloatToInt,2166 IrInstructionIdFloatToInt,
2086 IrInstructionIdBoolToInt,2167 IrInstructionIdBoolToInt,
2087 IrInstructionIdIntType,2168 IrInstructionIdIntType,
2169 IrInstructionIdVectorType,
2088 IrInstructionIdBoolNot,2170 IrInstructionIdBoolNot,
2089 IrInstructionIdMemset,2171 IrInstructionIdMemset,
2090 IrInstructionIdMemcpy,2172 IrInstructionIdMemcpy,
...@@ -2105,7 +2187,8 @@ enum IrInstructionId {...@@ -2105,7 +2187,8 @@ enum IrInstructionId {
2105 IrInstructionIdErrWrapPayload,2187 IrInstructionIdErrWrapPayload,
2106 IrInstructionIdFnProto,2188 IrInstructionIdFnProto,
2107 IrInstructionIdTestComptime,2189 IrInstructionIdTestComptime,
2108 IrInstructionIdPtrCast,2190 IrInstructionIdPtrCastSrc,
2191 IrInstructionIdPtrCastGen,
2109 IrInstructionIdBitCast,2192 IrInstructionIdBitCast,
2110 IrInstructionIdWidenOrShorten,2193 IrInstructionIdWidenOrShorten,
2111 IrInstructionIdIntToPtr,2194 IrInstructionIdIntToPtr,
...@@ -2158,10 +2241,15 @@ enum IrInstructionId {...@@ -2158,10 +2241,15 @@ enum IrInstructionId {
2158 IrInstructionIdMergeErrRetTraces,2241 IrInstructionIdMergeErrRetTraces,
2159 IrInstructionIdMarkErrRetTracePtr,2242 IrInstructionIdMarkErrRetTracePtr,
2160 IrInstructionIdSqrt,2243 IrInstructionIdSqrt,
2244 IrInstructionIdBswap,
2245 IrInstructionIdBitReverse,
2161 IrInstructionIdErrSetCast,2246 IrInstructionIdErrSetCast,
2162 IrInstructionIdToBytes,2247 IrInstructionIdToBytes,
2163 IrInstructionIdFromBytes,2248 IrInstructionIdFromBytes,
2164 IrInstructionIdCheckRuntimeScope,2249 IrInstructionIdCheckRuntimeScope,
2250 IrInstructionIdVectorToArray,
2251 IrInstructionIdArrayToVector,
2252 IrInstructionIdAssertZero,
2165};2253};
21662254
2167struct IrInstruction {2255struct IrInstruction {
...@@ -2183,6 +2271,22 @@ struct IrInstruction {...@@ -2183,6 +2271,22 @@ struct IrInstruction {
2183 bool is_gen;2271 bool is_gen;
2184};2272};
21852273
2274struct IrInstructionDeclVarSrc {
2275 IrInstruction base;
2276
2277 ZigVar *var;
2278 IrInstruction *var_type;
2279 IrInstruction *align_value;
2280 IrInstruction *init_value;
2281};
2282
2283struct IrInstructionDeclVarGen {
2284 IrInstruction base;
2285
2286 ZigVar *var;
2287 IrInstruction *init_value;
2288};
2289
2186struct IrInstructionCondBr {2290struct IrInstructionCondBr {
2187 IrInstruction base;2291 IrInstruction base;
21882292
...@@ -2291,20 +2395,11 @@ struct IrInstructionBinOp {...@@ -2291,20 +2395,11 @@ struct IrInstructionBinOp {
2291 IrInstruction base;2395 IrInstruction base;
22922396
2293 IrInstruction *op1;2397 IrInstruction *op1;
2294 IrBinOp op_id;
2295 IrInstruction *op2;2398 IrInstruction *op2;
2399 IrBinOp op_id;
2296 bool safety_check_on;2400 bool safety_check_on;
2297};2401};
22982402
2299struct IrInstructionDeclVar {
2300 IrInstruction base;
2301
2302 ZigVar *var;
2303 IrInstruction *var_type;
2304 IrInstruction *align_value;
2305 IrInstruction *init_value;
2306};
2307
2308struct IrInstructionLoadPtr {2403struct IrInstructionLoadPtr {
2309 IrInstruction base;2404 IrInstruction base;
23102405
...@@ -2324,7 +2419,6 @@ struct IrInstructionFieldPtr {...@@ -2324,7 +2419,6 @@ struct IrInstructionFieldPtr {
2324 IrInstruction *container_ptr;2419 IrInstruction *container_ptr;
2325 Buf *field_name_buffer;2420 Buf *field_name_buffer;
2326 IrInstruction *field_name_expr;2421 IrInstruction *field_name_expr;
2327 bool is_const;
2328};2422};
23292423
2330struct IrInstructionStructFieldPtr {2424struct IrInstructionStructFieldPtr {
...@@ -2367,13 +2461,13 @@ struct IrInstructionCall {...@@ -2367,13 +2461,13 @@ struct IrInstructionCall {
2367 ZigFn *fn_entry;2461 ZigFn *fn_entry;
2368 size_t arg_count;2462 size_t arg_count;
2369 IrInstruction **args;2463 IrInstruction **args;
2370 bool is_comptime;
2371 LLVMValueRef tmp_ptr;2464 LLVMValueRef tmp_ptr;
2372 FnInline fn_inline;
2373 bool is_async;
23742465
2375 IrInstruction *async_allocator;2466 IrInstruction *async_allocator;
2376 IrInstruction *new_stack;2467 IrInstruction *new_stack;
2468 FnInline fn_inline;
2469 bool is_async;
2470 bool is_comptime;
2377};2471};
23782472
2379struct IrInstructionConst {2473struct IrInstructionConst {
...@@ -2504,6 +2598,7 @@ struct IrInstructionPtrType {...@@ -2504,6 +2598,7 @@ struct IrInstructionPtrType {
2504 PtrLen ptr_len;2598 PtrLen ptr_len;
2505 bool is_const;2599 bool is_const;
2506 bool is_volatile;2600 bool is_volatile;
2601 bool allow_zero;
2507};2602};
25082603
2509struct IrInstructionPromiseType {2604struct IrInstructionPromiseType {
...@@ -2516,9 +2611,10 @@ struct IrInstructionSliceType {...@@ -2516,9 +2611,10 @@ struct IrInstructionSliceType {
2516 IrInstruction base;2611 IrInstruction base;
25172612
2518 IrInstruction *align_value;2613 IrInstruction *align_value;
2614 IrInstruction *child_type;
2519 bool is_const;2615 bool is_const;
2520 bool is_volatile;2616 bool is_volatile;
2521 IrInstruction *child_type;2617 bool allow_zero;
2522};2618};
25232619
2524struct IrInstructionAsm {2620struct IrInstructionAsm {
...@@ -2546,10 +2642,12 @@ struct IrInstructionTestNonNull {...@@ -2546,10 +2642,12 @@ struct IrInstructionTestNonNull {
2546 IrInstruction *value;2642 IrInstruction *value;
2547};2643};
25482644
2549struct IrInstructionUnwrapOptional {2645// Takes a pointer to an optional value, returns a pointer
2646// to the payload.
2647struct IrInstructionOptionalUnwrapPtr {
2550 IrInstruction base;2648 IrInstruction base;
25512649
2552 IrInstruction *value;2650 IrInstruction *base_ptr;
2553 bool safety_check_on;2651 bool safety_check_on;
2554};2652};
25552653
...@@ -2640,7 +2738,7 @@ struct IrInstructionEmbedFile {...@@ -2640,7 +2738,7 @@ struct IrInstructionEmbedFile {
2640 IrInstruction *name;2738 IrInstruction *name;
2641};2739};
26422740
2643struct IrInstructionCmpxchg {2741struct IrInstructionCmpxchgSrc {
2644 IrInstruction base;2742 IrInstruction base;
26452743
2646 IrInstruction *type_value;2744 IrInstruction *type_value;
...@@ -2650,14 +2748,19 @@ struct IrInstructionCmpxchg {...@@ -2650,14 +2748,19 @@ struct IrInstructionCmpxchg {
2650 IrInstruction *success_order_value;2748 IrInstruction *success_order_value;
2651 IrInstruction *failure_order_value;2749 IrInstruction *failure_order_value;
26522750
2653 // if this instruction gets to runtime then we know these values:
2654 ZigType *type;
2655 AtomicOrder success_order;
2656 AtomicOrder failure_order;
2657
2658 bool is_weak;2751 bool is_weak;
2752};
26592753
2754struct IrInstructionCmpxchgGen {
2755 IrInstruction base;
2756
2757 IrInstruction *ptr;
2758 IrInstruction *cmp_value;
2759 IrInstruction *new_value;
2660 LLVMValueRef tmp_ptr;2760 LLVMValueRef tmp_ptr;
2761 AtomicOrder success_order;
2762 AtomicOrder failure_order;
2763 bool is_weak;
2661};2764};
26622765
2663struct IrInstructionFence {2766struct IrInstructionFence {
...@@ -2737,6 +2840,13 @@ struct IrInstructionIntType {...@@ -2737,6 +2840,13 @@ struct IrInstructionIntType {
2737 IrInstruction *bit_count;2840 IrInstruction *bit_count;
2738};2841};
27392842
2843struct IrInstructionVectorType {
2844 IrInstruction base;
2845
2846 IrInstruction *len;
2847 IrInstruction *elem_type;
2848};
2849
2740struct IrInstructionBoolNot {2850struct IrInstructionBoolNot {
2741 IrInstruction base;2851 IrInstruction base;
27422852
...@@ -2840,7 +2950,7 @@ struct IrInstructionTestErr {...@@ -2840,7 +2950,7 @@ struct IrInstructionTestErr {
2840struct IrInstructionUnwrapErrCode {2950struct IrInstructionUnwrapErrCode {
2841 IrInstruction base;2951 IrInstruction base;
28422952
2843 IrInstruction *value;2953 IrInstruction *err_union;
2844};2954};
28452955
2846struct IrInstructionUnwrapErrPayload {2956struct IrInstructionUnwrapErrPayload {
...@@ -2888,11 +2998,19 @@ struct IrInstructionTestComptime {...@@ -2888,11 +2998,19 @@ struct IrInstructionTestComptime {
2888 IrInstruction *value;2998 IrInstruction *value;
2889};2999};
28903000
2891struct IrInstructionPtrCast {3001struct IrInstructionPtrCastSrc {
2892 IrInstruction base;3002 IrInstruction base;
28933003
2894 IrInstruction *dest_type;3004 IrInstruction *dest_type;
2895 IrInstruction *ptr;3005 IrInstruction *ptr;
3006 bool safety_check_on;
3007};
3008
3009struct IrInstructionPtrCastGen {
3010 IrInstruction base;
3011
3012 IrInstruction *ptr;
3013 bool safety_check_on;
2896};3014};
28973015
2898struct IrInstructionBitCast {3016struct IrInstructionBitCast {
...@@ -3251,6 +3369,39 @@ struct IrInstructionCheckRuntimeScope {...@@ -3251,6 +3369,39 @@ struct IrInstructionCheckRuntimeScope {
3251 IrInstruction *is_comptime;3369 IrInstruction *is_comptime;
3252};3370};
32533371
3372struct IrInstructionBswap {
3373 IrInstruction base;
3374
3375 IrInstruction *type;
3376 IrInstruction *op;
3377};
3378
3379struct IrInstructionBitReverse {
3380 IrInstruction base;
3381
3382 IrInstruction *type;
3383 IrInstruction *op;
3384};
3385
3386struct IrInstructionArrayToVector {
3387 IrInstruction base;
3388
3389 IrInstruction *array;
3390};
3391
3392struct IrInstructionVectorToArray {
3393 IrInstruction base;
3394
3395 IrInstruction *vector;
3396 LLVMValueRef tmp_ptr;
3397};
3398
3399struct IrInstructionAssertZero {
3400 IrInstruction base;
3401
3402 IrInstruction *target;
3403};
3404
3254static const size_t slice_ptr_index = 0;3405static const size_t slice_ptr_index = 0;
3255static const size_t slice_len_index = 1;3406static const size_t slice_len_index = 1;
32563407
src/analyze.cpp+651-268
...@@ -28,28 +28,10 @@ static Error ATTRIBUTE_MUST_USE resolve_enum_zero_bits(CodeGen *g, ZigType *enum...@@ -28,28 +28,10 @@ static Error ATTRIBUTE_MUST_USE resolve_enum_zero_bits(CodeGen *g, ZigType *enum
28static Error ATTRIBUTE_MUST_USE resolve_union_zero_bits(CodeGen *g, ZigType *union_type);28static Error ATTRIBUTE_MUST_USE resolve_union_zero_bits(CodeGen *g, ZigType *union_type);
29static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry);29static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry);
3030
31ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {31static ErrorMsg *add_error_note_token(CodeGen *g, ErrorMsg *parent_msg, ImportTableEntry *owner, Token *token,
32 if (node->owner->c_import_node != nullptr) {32 Buf *msg)
33 // if this happens, then translate_c generated code that33{
34 // failed semantic analysis, which isn't supposed to happen34 if (owner->c_import_node != nullptr) {
35 ErrorMsg *err = add_node_error(g, node->owner->c_import_node,
36 buf_sprintf("compiler bug: @cImport generated invalid zig code"));
37
38 add_error_note(g, err, node, msg);
39
40 g->errors.append(err);
41 return err;
42 }
43
44 ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column,
45 node->owner->source_code, node->owner->line_offsets, msg);
46
47 g->errors.append(err);
48 return err;
49}
50
51ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg) {
52 if (node->owner->c_import_node != nullptr) {
53 // if this happens, then translate_c generated code that35 // if this happens, then translate_c generated code that
54 // failed semantic analysis, which isn't supposed to happen36 // failed semantic analysis, which isn't supposed to happen
5537
...@@ -64,13 +46,46 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *m...@@ -64,13 +46,46 @@ ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *m
64 return note;46 return note;
65 }47 }
6648
67 ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column,49 ErrorMsg *err = err_msg_create_with_line(owner->path, token->start_line, token->start_column,
68 node->owner->source_code, node->owner->line_offsets, msg);50 owner->source_code, owner->line_offsets, msg);
6951
70 err_msg_add_note(parent_msg, err);52 err_msg_add_note(parent_msg, err);
71 return err;53 return err;
72}54}
7355
56ErrorMsg *add_token_error(CodeGen *g, ImportTableEntry *owner, Token *token, Buf *msg) {
57 if (owner->c_import_node != nullptr) {
58 // if this happens, then translate_c generated code that
59 // failed semantic analysis, which isn't supposed to happen
60 ErrorMsg *err = add_node_error(g, owner->c_import_node,
61 buf_sprintf("compiler bug: @cImport generated invalid zig code"));
62
63 add_error_note_token(g, err, owner, token, msg);
64
65 g->errors.append(err);
66 return err;
67 }
68 ErrorMsg *err = err_msg_create_with_line(owner->path, token->start_line, token->start_column,
69 owner->source_code, owner->line_offsets, msg);
70
71 g->errors.append(err);
72 return err;
73}
74
75ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
76 Token fake_token;
77 fake_token.start_line = node->line;
78 fake_token.start_column = node->column;
79 return add_token_error(g, node->owner, &fake_token, msg);
80}
81
82ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg) {
83 Token fake_token;
84 fake_token.start_line = node->line;
85 fake_token.start_column = node->column;
86 return add_error_note_token(g, parent_msg, node->owner, &fake_token, msg);
87}
88
74ZigType *new_type_table_entry(ZigTypeId id) {89ZigType *new_type_table_entry(ZigTypeId id) {
75 ZigType *entry = allocate<ZigType>(1);90 ZigType *entry = allocate<ZigType>(1);
76 entry->id = id;91 entry->id = id;
...@@ -250,6 +265,7 @@ AstNode *type_decl_node(ZigType *type_entry) {...@@ -250,6 +265,7 @@ AstNode *type_decl_node(ZigType *type_entry) {
250 case ZigTypeIdBoundFn:265 case ZigTypeIdBoundFn:
251 case ZigTypeIdArgTuple:266 case ZigTypeIdArgTuple:
252 case ZigTypeIdPromise:267 case ZigTypeIdPromise:
268 case ZigTypeIdVector:
253 return nullptr;269 return nullptr;
254 }270 }
255 zig_unreachable();271 zig_unreachable();
...@@ -311,6 +327,7 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {...@@ -311,6 +327,7 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
311 case ZigTypeIdBoundFn:327 case ZigTypeIdBoundFn:
312 case ZigTypeIdArgTuple:328 case ZigTypeIdArgTuple:
313 case ZigTypeIdPromise:329 case ZigTypeIdPromise:
330 case ZigTypeIdVector:
314 return true;331 return true;
315 }332 }
316 zig_unreachable();333 zig_unreachable();
...@@ -339,6 +356,28 @@ uint64_t type_size(CodeGen *g, ZigType *type_entry) {...@@ -339,6 +356,28 @@ uint64_t type_size(CodeGen *g, ZigType *type_entry) {
339 }356 }
340 }357 }
341358
359 return LLVMABISizeOfType(g->target_data_ref, type_entry->type_ref);
360}
361
362uint64_t type_size_store(CodeGen *g, ZigType *type_entry) {
363 assert(type_is_complete(type_entry));
364
365 if (!type_has_bits(type_entry))
366 return 0;
367
368 if (type_entry->id == ZigTypeIdStruct && type_entry->data.structure.layout == ContainerLayoutPacked) {
369 uint64_t size_in_bits = type_size_bits(g, type_entry);
370 return (size_in_bits + 7) / 8;
371 } else if (type_entry->id == ZigTypeIdArray) {
372 ZigType *child_type = type_entry->data.array.child_type;
373 if (child_type->id == ZigTypeIdStruct &&
374 child_type->data.structure.layout == ContainerLayoutPacked)
375 {
376 uint64_t size_in_bits = type_size_bits(g, type_entry);
377 return (size_in_bits + 7) / 8;
378 }
379 }
380
342 return LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);381 return LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
343}382}
344383
...@@ -400,9 +439,25 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {...@@ -400,9 +439,25 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {
400 return entry;439 return entry;
401}440}
402441
442static const char *ptr_len_to_star_str(PtrLen ptr_len) {
443 switch (ptr_len) {
444 case PtrLenSingle:
445 return "*";
446 case PtrLenUnknown:
447 return "[*]";
448 case PtrLenC:
449 return "[*c]";
450 }
451 zig_unreachable();
452}
453
403ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,454ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
404 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset_in_host, uint32_t host_int_bytes)455 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
456 uint32_t bit_offset_in_host, uint32_t host_int_bytes)
405{457{
458 // TODO when implementing https://github.com/ziglang/zig/issues/1953
459 // move this to a parameter
460 bool allow_zero = (ptr_len == PtrLenC);
406 assert(!type_is_invalid(child_type));461 assert(!type_is_invalid(child_type));
407 assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);462 assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
408463
...@@ -422,7 +477,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -422,7 +477,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
422477
423 TypeId type_id = {};478 TypeId type_id = {};
424 ZigType **parent_pointer = nullptr;479 ZigType **parent_pointer = nullptr;
425 if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) {480 if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || allow_zero) {
426 type_id.id = ZigTypeIdPointer;481 type_id.id = ZigTypeIdPointer;
427 type_id.data.pointer.child_type = child_type;482 type_id.data.pointer.child_type = child_type;
428 type_id.data.pointer.is_const = is_const;483 type_id.data.pointer.is_const = is_const;
...@@ -431,6 +486,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -431,6 +486,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
431 type_id.data.pointer.bit_offset_in_host = bit_offset_in_host;486 type_id.data.pointer.bit_offset_in_host = bit_offset_in_host;
432 type_id.data.pointer.host_int_bytes = host_int_bytes;487 type_id.data.pointer.host_int_bytes = host_int_bytes;
433 type_id.data.pointer.ptr_len = ptr_len;488 type_id.data.pointer.ptr_len = ptr_len;
489 type_id.data.pointer.allow_zero = allow_zero;
434490
435 auto existing_entry = g->type_table.maybe_get(type_id);491 auto existing_entry = g->type_table.maybe_get(type_id);
436 if (existing_entry)492 if (existing_entry)
...@@ -448,21 +504,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -448,21 +504,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
448504
449 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);505 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
450506
451 const char *star_str = ptr_len == PtrLenSingle ? "*" : "[*]";507 const char *star_str = ptr_len_to_star_str(ptr_len);
452 const char *const_str = is_const ? "const " : "";508 const char *const_str = is_const ? "const " : "";
453 const char *volatile_str = is_volatile ? "volatile " : "";509 const char *volatile_str = is_volatile ? "volatile " : "";
510 const char *allow_zero_str;
511 if (ptr_len == PtrLenC) {
512 assert(allow_zero);
513 allow_zero_str = "";
514 } else {
515 allow_zero_str = allow_zero ? "allowzero " : "";
516 }
454 buf_resize(&entry->name, 0);517 buf_resize(&entry->name, 0);
455 if (host_int_bytes == 0 && byte_alignment == 0) {518 if (host_int_bytes == 0 && byte_alignment == 0) {
456 buf_appendf(&entry->name, "%s%s%s%s", star_str, const_str, volatile_str, buf_ptr(&child_type->name));519 buf_appendf(&entry->name, "%s%s%s%s%s",
520 star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
457 } else if (host_int_bytes == 0) {521 } else if (host_int_bytes == 0) {
458 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment,522 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
459 const_str, volatile_str, buf_ptr(&child_type->name));523 const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
460 } else if (byte_alignment == 0) {524 } else if (byte_alignment == 0) {
461 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str,525 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str,
462 bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));526 bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
527 buf_ptr(&child_type->name));
463 } else {528 } else {
464 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment,529 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
465 bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));530 bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
531 buf_ptr(&child_type->name));
466 }532 }
467533
468 assert(child_type->id != ZigTypeIdInvalid);534 assert(child_type->id != ZigTypeIdInvalid);
...@@ -470,7 +536,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -470,7 +536,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
470 entry->zero_bits = !type_has_bits(child_type);536 entry->zero_bits = !type_has_bits(child_type);
471537
472 if (!entry->zero_bits) {538 if (!entry->zero_bits) {
473 if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || bit_offset_in_host != 0) {539 if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle ||
540 bit_offset_in_host != 0 || allow_zero)
541 {
474 ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false,542 ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false,
475 PtrLenSingle, 0, 0, host_int_bytes);543 PtrLenSingle, 0, 0, host_int_bytes);
476 entry->type_ref = peer_type->type_ref;544 entry->type_ref = peer_type->type_ref;
...@@ -504,6 +572,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -504,6 +572,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
504 entry->data.pointer.explicit_alignment = byte_alignment;572 entry->data.pointer.explicit_alignment = byte_alignment;
505 entry->data.pointer.bit_offset_in_host = bit_offset_in_host;573 entry->data.pointer.bit_offset_in_host = bit_offset_in_host;
506 entry->data.pointer.host_int_bytes = host_int_bytes;574 entry->data.pointer.host_int_bytes = host_int_bytes;
575 entry->data.pointer.allow_zero = allow_zero;
507576
508 if (parent_pointer) {577 if (parent_pointer) {
509 *parent_pointer = entry;578 *parent_pointer = entry;
...@@ -569,13 +638,16 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {...@@ -569,13 +638,16 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
569 if (child_type->zero_bits) {638 if (child_type->zero_bits) {
570 entry->type_ref = LLVMInt1Type();639 entry->type_ref = LLVMInt1Type();
571 entry->di_type = g->builtin_types.entry_bool->di_type;640 entry->di_type = g->builtin_types.entry_bool->di_type;
572 } else if (type_is_codegen_pointer(child_type)) {641 } else if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) {
573 assert(child_type->di_type);642 assert(child_type->di_type);
574 // this is an optimization but also is necessary for calling C643 // this is an optimization but also is necessary for calling C
575 // functions where all pointers are maybe pointers644 // functions where all pointers are maybe pointers
576 // function types are technically pointers645 // function types are technically pointers
577 entry->type_ref = child_type->type_ref;646 entry->type_ref = child_type->type_ref;
578 entry->di_type = child_type->di_type;647 entry->di_type = child_type->di_type;
648 if (entry->di_type == g->builtin_types.entry_global_error_set->di_type) {
649 g->error_di_types.append(&entry->di_type);
650 }
579 } else {651 } else {
580 assert(child_type->di_type);652 assert(child_type->di_type);
581 // create a struct with a boolean whether this is the null value653 // create a struct with a boolean whether this is the null value
...@@ -817,7 +889,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {...@@ -817,7 +889,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
817889
818 ZigType *child_type = ptr_type->data.pointer.child_type;890 ZigType *child_type = ptr_type->data.pointer.child_type;
819 if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||891 if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||
820 ptr_type->data.pointer.explicit_alignment != 0)892 ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero)
821 {893 {
822 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,894 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
823 PtrLenUnknown, 0, 0, 0);895 PtrLenUnknown, 0, 0, 0);
...@@ -840,7 +912,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {...@@ -840,7 +912,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
840 ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry;912 ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry;
841 assert(child_ptr_type->id == ZigTypeIdPointer);913 assert(child_ptr_type->id == ZigTypeIdPointer);
842 if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile ||914 if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile ||
843 child_ptr_type->data.pointer.explicit_alignment != 0)915 child_ptr_type->data.pointer.explicit_alignment != 0 || child_ptr_type->data.pointer.allow_zero)
844 {916 {
845 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;917 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
846 ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false,918 ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false,
...@@ -1054,11 +1126,7 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {...@@ -1054,11 +1126,7 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
1054 }1126 }
1055 if (g->zig_target.arch.arch == ZigLLVM_x86_64) {1127 if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
1056 X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);1128 X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);
1057 if (abi_class == X64CABIClass_MEMORY) {1129 return abi_class == X64CABIClass_MEMORY;
1058 return true;
1059 }
1060 zig_panic("TODO implement C ABI for x86_64 return types. type '%s'\nSee https://github.com/ziglang/zig/issues/1481",
1061 buf_ptr(&fn_type_id->return_type->name));
1062 } else if (target_is_arm(&g->zig_target)) {1130 } else if (target_is_arm(&g->zig_target)) {
1063 return type_size(g, fn_type_id->return_type) > 16;1131 return type_size(g, fn_type_id->return_type) > 16;
1064 }1132 }
...@@ -1219,7 +1287,10 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {...@@ -1219,7 +1287,10 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
1219 fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref,1287 fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref,
1220 gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args);1288 gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args);
1221 fn_type->type_ref = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0);1289 fn_type->type_ref = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0);
1222 fn_type->di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0);1290 fn_type->data.fn.raw_di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0);
1291 fn_type->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, fn_type->data.fn.raw_di_type,
1292 LLVMStoreSizeOfType(g->target_data_ref, fn_type->type_ref),
1293 LLVMABIAlignmentOfType(g->target_data_ref, fn_type->type_ref), "");
1223 }1294 }
12241295
1225 g->fn_type_table.put(&fn_type->data.fn.fn_type_id, fn_type);1296 g->fn_type_table.put(&fn_type->data.fn.fn_type_id, fn_type);
...@@ -1274,20 +1345,22 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind...@@ -1274,20 +1345,22 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
1274 return entry;1345 return entry;
1275}1346}
12761347
1277static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name) {1348static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
1349 Buf *type_name)
1350{
1278 size_t backward_branch_count = 0;1351 size_t backward_branch_count = 0;
1279 return ir_eval_const_value(g, scope, node, type_entry,1352 return ir_eval_const_value(g, scope, node, type_entry,
1280 &backward_branch_count, default_backward_branch_quota,1353 &backward_branch_count, default_backward_branch_quota,
1281 nullptr, nullptr, node, type_name, nullptr);1354 nullptr, nullptr, node, type_name, nullptr, nullptr);
1282}1355}
12831356
1284ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {1357ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
1285 IrInstruction *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);1358 ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
1286 if (result->value.type->id == ZigTypeIdInvalid)1359 if (type_is_invalid(result->type))
1287 return g->builtin_types.entry_invalid;1360 return g->builtin_types.entry_invalid;
12881361
1289 assert(result->value.special != ConstValSpecialRuntime);1362 assert(result->special != ConstValSpecialRuntime);
1290 return result->value.data.x_type;1363 return result->data.x_type;
1291}1364}
12921365
1293ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {1366ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
...@@ -1338,11 +1411,11 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou...@@ -1338,11 +1411,11 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou
1338}1411}
13391412
1340static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) {1413static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) {
1341 IrInstruction *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);1414 ConstExprValue *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);
1342 if (type_is_invalid(align_result->value.type))1415 if (type_is_invalid(align_result->type))
1343 return false;1416 return false;
13441417
1345 uint32_t align_bytes = bigint_as_unsigned(&align_result->value.data.x_bigint);1418 uint32_t align_bytes = bigint_as_unsigned(&align_result->data.x_bigint);
1346 if (align_bytes == 0) {1419 if (align_bytes == 0) {
1347 add_node_error(g, node, buf_sprintf("alignment must be >= 1"));1420 add_node_error(g, node, buf_sprintf("alignment must be >= 1"));
1348 return false;1421 return false;
...@@ -1360,12 +1433,12 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **...@@ -1360,12 +1433,12 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
1360 ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,1433 ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
1361 PtrLenUnknown, 0, 0, 0);1434 PtrLenUnknown, 0, 0, 0);
1362 ZigType *str_type = get_slice_type(g, ptr_type);1435 ZigType *str_type = get_slice_type(g, ptr_type);
1363 IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr);1436 ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr);
1364 if (type_is_invalid(instr->value.type))1437 if (type_is_invalid(result_val->type))
1365 return false;1438 return false;
13661439
1367 ConstExprValue *ptr_field = &instr->value.data.x_struct.fields[slice_ptr_index];1440 ConstExprValue *ptr_field = &result_val->data.x_struct.fields[slice_ptr_index];
1368 ConstExprValue *len_field = &instr->value.data.x_struct.fields[slice_len_index];1441 ConstExprValue *len_field = &result_val->data.x_struct.fields[slice_len_index];
13691442
1370 assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);1443 assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);
1371 ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val;1444 ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val;
...@@ -1418,6 +1491,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {...@@ -1418,6 +1491,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {
1418 case ZigTypeIdPointer:1491 case ZigTypeIdPointer:
1419 case ZigTypeIdArray:1492 case ZigTypeIdArray:
1420 case ZigTypeIdFn:1493 case ZigTypeIdFn:
1494 case ZigTypeIdVector:
1421 return true;1495 return true;
1422 case ZigTypeIdStruct:1496 case ZigTypeIdStruct:
1423 return type_entry->data.structure.layout == ContainerLayoutPacked;1497 return type_entry->data.structure.layout == ContainerLayoutPacked;
...@@ -1434,7 +1508,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {...@@ -1434,7 +1508,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {
1434 zig_unreachable();1508 zig_unreachable();
1435}1509}
14361510
1437static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {1511bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
1438 switch (type_entry->id) {1512 switch (type_entry->id) {
1439 case ZigTypeIdInvalid:1513 case ZigTypeIdInvalid:
1440 zig_unreachable();1514 zig_unreachable();
...@@ -1466,6 +1540,8 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {...@@ -1466,6 +1540,8 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
1466 default:1540 default:
1467 return false;1541 return false;
1468 }1542 }
1543 case ZigTypeIdVector:
1544 return type_allowed_in_extern(g, type_entry->data.vector.elem_type);
1469 case ZigTypeIdFloat:1545 case ZigTypeIdFloat:
1470 return true;1546 return true;
1471 case ZigTypeIdArray:1547 case ZigTypeIdArray:
...@@ -1619,6 +1695,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc...@@ -1619,6 +1695,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
1619 case ZigTypeIdUnion:1695 case ZigTypeIdUnion:
1620 case ZigTypeIdFn:1696 case ZigTypeIdFn:
1621 case ZigTypeIdPromise:1697 case ZigTypeIdPromise:
1698 case ZigTypeIdVector:
1622 switch (type_requires_comptime(g, type_entry)) {1699 switch (type_requires_comptime(g, type_entry)) {
1623 case ReqCompTimeNo:1700 case ReqCompTimeNo:
1624 break;1701 break;
...@@ -1714,6 +1791,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc...@@ -1714,6 +1791,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
1714 case ZigTypeIdUnion:1791 case ZigTypeIdUnion:
1715 case ZigTypeIdFn:1792 case ZigTypeIdFn:
1716 case ZigTypeIdPromise:1793 case ZigTypeIdPromise:
1794 case ZigTypeIdVector:
1717 switch (type_requires_comptime(g, fn_type_id.return_type)) {1795 switch (type_requires_comptime(g, fn_type_id.return_type)) {
1718 case ReqCompTimeInvalid:1796 case ReqCompTimeInvalid:
1719 return g->builtin_types.entry_invalid;1797 return g->builtin_types.entry_invalid;
...@@ -2500,20 +2578,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2500,20 +2578,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2500 // In this first pass we resolve explicit tag values.2578 // In this first pass we resolve explicit tag values.
2501 // In a second pass we will fill in the unspecified ones.2579 // In a second pass we will fill in the unspecified ones.
2502 if (tag_value != nullptr) {2580 if (tag_value != nullptr) {
2503 IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);2581 ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
2504 if (result_inst->value.type->id == ZigTypeIdInvalid) {2582 if (type_is_invalid(result->type)) {
2505 enum_type->data.enumeration.is_invalid = true;2583 enum_type->data.enumeration.is_invalid = true;
2506 continue;2584 continue;
2507 }2585 }
2508 assert(result_inst->value.special != ConstValSpecialRuntime);2586 assert(result->special != ConstValSpecialRuntime);
2509 assert(result_inst->value.type->id == ZigTypeIdInt ||2587 assert(result->type->id == ZigTypeIdInt ||
2510 result_inst->value.type->id == ZigTypeIdComptimeInt);2588 result->type->id == ZigTypeIdComptimeInt);
2511 auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);2589 auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
2512 if (entry == nullptr) {2590 if (entry == nullptr) {
2513 bigint_init_bigint(&type_enum_field->value, &result_inst->value.data.x_bigint);2591 bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint);
2514 } else {2592 } else {
2515 Buf *val_buf = buf_alloc();2593 Buf *val_buf = buf_alloc();
2516 bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10);2594 bigint_append_buf(val_buf, &result->data.x_bigint, 10);
25172595
2518 ErrorMsg *msg = add_node_error(g, tag_value,2596 ErrorMsg *msg = add_node_error(g, tag_value,
2519 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));2597 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
...@@ -2623,6 +2701,13 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2623,6 +2701,13 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2623 buf_sprintf("enums, not structs, support field assignment"));2701 buf_sprintf("enums, not structs, support field assignment"));
2624 }2702 }
26252703
2704 if (field_type->id == ZigTypeIdOpaque) {
2705 add_node_error(g, field_node->data.struct_field.type,
2706 buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs"));
2707 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2708 continue;
2709 }
2710
2626 switch (type_requires_comptime(g, field_type)) {2711 switch (type_requires_comptime(g, field_type)) {
2627 case ReqCompTimeYes:2712 case ReqCompTimeYes:
2628 struct_type->data.structure.requires_comptime = true;2713 struct_type->data.structure.requires_comptime = true;
...@@ -2680,39 +2765,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {...@@ -2680,39 +2765,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
2680 assert(decl_node->type == NodeTypeContainerDecl);2765 assert(decl_node->type == NodeTypeContainerDecl);
2681 assert(struct_type->di_type);2766 assert(struct_type->di_type);
26822767
2768 size_t field_count = struct_type->data.structure.src_field_count;
2683 if (struct_type->data.structure.layout == ContainerLayoutPacked) {2769 if (struct_type->data.structure.layout == ContainerLayoutPacked) {
2684 struct_type->data.structure.abi_alignment = 1;2770 struct_type->data.structure.abi_alignment = 1;
2685 }2771 for (size_t i = 0; i < field_count; i += 1) {
26862772 TypeStructField *field = &struct_type->data.structure.fields[i];
2687 size_t field_count = struct_type->data.structure.src_field_count;2773 if (field->type_entry != nullptr && type_is_invalid(field->type_entry)) {
2688 for (size_t i = 0; i < field_count; i += 1) {2774 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2689 TypeStructField *field = &struct_type->data.structure.fields[i];2775 break;
26902776 }
2691 // If this assertion trips, look up the call stack. Probably something is
2692 // calling type_resolve with ResolveStatusAlignmentKnown when it should only
2693 // be resolving ResolveStatusZeroBitsKnown
2694 assert(field->type_entry != nullptr);
2695
2696 if (type_is_invalid(field->type_entry)) {
2697 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2698 break;
2699 }2777 }
2778 } else for (size_t i = 0; i < field_count; i += 1) {
2779 TypeStructField *field = &struct_type->data.structure.fields[i];
2780 uint32_t this_field_align;
2781
2782 // TODO If we have no type_entry for the field, we've already failed to
2783 // compile the program correctly. This stage1 compiler needs a deeper
2784 // reworking to make this correct, or we can ignore the problem
2785 // and make sure it is fixed in stage2. This workaround is for when
2786 // there is a false positive of a dependency loop, of alignment depending
2787 // on itself. When this false positive happens we assume a pointer-aligned
2788 // field, which is usually fine but could be incorrectly over-aligned or
2789 // even under-aligned. See https://github.com/ziglang/zig/issues/1512
2790 if (field->type_entry == nullptr) {
2791 this_field_align = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0));
2792 } else {
2793 if (type_is_invalid(field->type_entry)) {
2794 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2795 break;
2796 }
27002797
2701 if (!type_has_bits(field->type_entry))2798 if (!type_has_bits(field->type_entry))
2702 continue;2799 continue;
27032800
2704 // alignment of structs is the alignment of the most-aligned field
2705 if (struct_type->data.structure.layout != ContainerLayoutPacked) {
2706 if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {2801 if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {
2707 struct_type->data.structure.resolve_status = ResolveStatusInvalid;2802 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2708 break;2803 break;
2709 }2804 }
27102805
2711 uint32_t this_field_align = get_abi_alignment(g, field->type_entry);2806 this_field_align = get_abi_alignment(g, field->type_entry);
2712 assert(this_field_align != 0);2807 assert(this_field_align != 0);
2713 if (this_field_align > struct_type->data.structure.abi_alignment) {2808 }
2714 struct_type->data.structure.abi_alignment = this_field_align;2809 // alignment of structs is the alignment of the most-aligned field
2715 }2810 if (this_field_align > struct_type->data.structure.abi_alignment) {
2811 struct_type->data.structure.abi_alignment = this_field_align;
2716 }2812 }
2717 }2813 }
27182814
...@@ -2790,7 +2886,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2790,7 +2886,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2790 union_type->data.unionation.have_explicit_tag_type = decl_node->data.container_decl.auto_enum ||2886 union_type->data.unionation.have_explicit_tag_type = decl_node->data.container_decl.auto_enum ||
2791 enum_type_node != nullptr;2887 enum_type_node != nullptr;
2792 bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto);2888 bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto);
2793 bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr);2889 bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr) && !(g->build_mode == BuildModeFastRelease || g->build_mode == BuildModeSmallRelease);
2794 ZigType *tag_type;2890 ZigType *tag_type;
2795 bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety);2891 bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety);
2796 bool *covered_enum_fields;2892 bool *covered_enum_fields;
...@@ -2896,6 +2992,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2896,6 +2992,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2896 }2992 }
2897 union_field->type_entry = field_type;2993 union_field->type_entry = field_type;
28982994
2995 if (field_type->id == ZigTypeIdOpaque) {
2996 add_node_error(g, field_node->data.struct_field.type,
2997 buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in unions"));
2998 union_type->data.unionation.is_invalid = true;
2999 continue;
3000 }
3001
2899 switch (type_requires_comptime(g, field_type)) {3002 switch (type_requires_comptime(g, field_type)) {
2900 case ReqCompTimeInvalid:3003 case ReqCompTimeInvalid:
2901 union_type->data.unionation.is_invalid = true;3004 union_type->data.unionation.is_invalid = true;
...@@ -2929,19 +3032,19 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2929,19 +3032,19 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2929 // In a second pass we will fill in the unspecified ones.3032 // In a second pass we will fill in the unspecified ones.
2930 if (tag_value != nullptr) {3033 if (tag_value != nullptr) {
2931 ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type;3034 ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type;
2932 IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);3035 ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
2933 if (result_inst->value.type->id == ZigTypeIdInvalid) {3036 if (type_is_invalid(result->type)) {
2934 union_type->data.unionation.is_invalid = true;3037 union_type->data.unionation.is_invalid = true;
2935 continue;3038 continue;
2936 }3039 }
2937 assert(result_inst->value.special != ConstValSpecialRuntime);3040 assert(result->special != ConstValSpecialRuntime);
2938 assert(result_inst->value.type->id == ZigTypeIdInt);3041 assert(result->type->id == ZigTypeIdInt);
2939 auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);3042 auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
2940 if (entry == nullptr) {3043 if (entry == nullptr) {
2941 bigint_init_bigint(&union_field->enum_field->value, &result_inst->value.data.x_bigint);3044 bigint_init_bigint(&union_field->enum_field->value, &result->data.x_bigint);
2942 } else {3045 } else {
2943 Buf *val_buf = buf_alloc();3046 Buf *val_buf = buf_alloc();
2944 bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10);3047 bigint_append_buf(val_buf, &result->data.x_bigint, 10);
29453048
2946 ErrorMsg *msg = add_node_error(g, tag_value,3049 ErrorMsg *msg = add_node_error(g, tag_value,
2947 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));3050 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
...@@ -3144,36 +3247,19 @@ static bool scope_is_root_decls(Scope *scope) {...@@ -3144,36 +3247,19 @@ static bool scope_is_root_decls(Scope *scope) {
3144 zig_unreachable();3247 zig_unreachable();
3145}3248}
31463249
3147static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, ZigType *fn_type) {3250void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn) {
3148 add_node_error(g, proto_node,3251 ConstExprValue *panic_fn_type_val = get_builtin_value(g, "PanicFn");
3149 buf_sprintf("expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found '%s'",3252 assert(panic_fn_type_val != nullptr);
3150 buf_ptr(&fn_type->name)));3253 assert(panic_fn_type_val->type->id == ZigTypeIdMetaType);
3151}3254 ZigType *panic_fn_type = panic_fn_type_val->data.x_type;
3152
3153static void typecheck_panic_fn(CodeGen *g, ZigFn *panic_fn) {
3154 AstNode *proto_node = panic_fn->proto_node;
3155 assert(proto_node->type == NodeTypeFnProto);
3156 ZigType *fn_type = panic_fn->type_entry;
3157 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
3158 if (fn_type_id->param_count != 2) {
3159 return wrong_panic_prototype(g, proto_node, fn_type);
3160 }
3161 ZigType *const_u8_ptr = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
3162 PtrLenUnknown, 0, 0, 0);
3163 ZigType *const_u8_slice = get_slice_type(g, const_u8_ptr);
3164 if (fn_type_id->param_info[0].type != const_u8_slice) {
3165 return wrong_panic_prototype(g, proto_node, fn_type);
3166 }
31673255
3168 ZigType *optional_ptr_to_stack_trace_type = get_optional_type(g, get_ptr_to_stack_trace_type(g));3256 AstNode *fake_decl = allocate<AstNode>(1);
3169 if (fn_type_id->param_info[1].type != optional_ptr_to_stack_trace_type) {3257 *fake_decl = *panic_fn->proto_node;
3170 return wrong_panic_prototype(g, proto_node, fn_type);3258 fake_decl->type = NodeTypeSymbol;
3171 }3259 fake_decl->data.symbol_expr.symbol = &panic_fn->symbol_name;
31723260
3173 ZigType *actual_return_type = fn_type_id->return_type;3261 // call this for the side effects of casting to panic_fn_type
3174 if (actual_return_type != g->builtin_types.entry_unreachable) {3262 analyze_const_value(g, tld_fn->base.parent_scope, fake_decl, panic_fn_type, nullptr);
3175 return wrong_panic_prototype(g, proto_node, fn_type);
3176 }
3177}3263}
31783264
3179ZigType *get_test_fn_type(CodeGen *g) {3265ZigType *get_test_fn_type(CodeGen *g) {
...@@ -3191,14 +3277,12 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi...@@ -3191,14 +3277,12 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi
3191 if (ccc) {3277 if (ccc) {
3192 if (buf_eql_str(symbol_name, "main") && g->libc_link_lib != nullptr) {3278 if (buf_eql_str(symbol_name, "main") && g->libc_link_lib != nullptr) {
3193 g->have_c_main = true;3279 g->have_c_main = true;
3194 g->windows_subsystem_windows = false;3280 g->subsystem = TargetSubsystemConsole;
3195 g->windows_subsystem_console = true;
3196 } else if (buf_eql_str(symbol_name, "WinMain") &&3281 } else if (buf_eql_str(symbol_name, "WinMain") &&
3197 g->zig_target.os == OsWindows)3282 g->zig_target.os == OsWindows)
3198 {3283 {
3199 g->have_winmain = true;3284 g->have_winmain = true;
3200 g->windows_subsystem_windows = true;3285 g->subsystem = TargetSubsystemWindows;
3201 g->windows_subsystem_console = false;
3202 } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") &&3286 } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") &&
3203 g->zig_target.os == OsWindows)3287 g->zig_target.os == OsWindows)
3204 {3288 {
...@@ -3209,6 +3293,7 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi...@@ -3209,6 +3293,7 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi
3209 g->have_dllmain_crt_startup = true;3293 g->have_dllmain_crt_startup = true;
3210 }3294 }
3211 }3295 }
3296
3212 FnExport *fn_export = fn_table_entry->export_list.add_one();3297 FnExport *fn_export = fn_table_entry->export_list.add_one();
3213 memset(fn_export, 0, sizeof(FnExport));3298 memset(fn_export, 0, sizeof(FnExport));
3214 buf_init_from_buf(&fn_export->name, symbol_name);3299 buf_init_from_buf(&fn_export->name, symbol_name);
...@@ -3269,18 +3354,18 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {...@@ -3269,18 +3354,18 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
3269 if (!fn_table_entry->type_entry->data.fn.is_generic) {3354 if (!fn_table_entry->type_entry->data.fn.is_generic) {
3270 if (fn_def_node)3355 if (fn_def_node)
3271 g->fn_defs.append(fn_table_entry);3356 g->fn_defs.append(fn_table_entry);
3357 }
32723358
3273 if (scope_is_root_decls(tld_fn->base.parent_scope) &&3359 if (scope_is_root_decls(tld_fn->base.parent_scope) &&
3274 (import == g->root_import || import->package == g->panic_package))3360 (import == g->root_import || import->package == g->panic_package))
3361 {
3362 if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) {
3363 g->main_fn = fn_table_entry;
3364 } else if ((import->package == g->panic_package || g->have_pub_panic) &&
3365 buf_eql_str(&fn_table_entry->symbol_name, "panic"))
3275 {3366 {
3276 if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) {3367 g->panic_fn = fn_table_entry;
3277 g->main_fn = fn_table_entry;3368 g->panic_tld_fn = tld_fn;
3278 } else if ((import->package == g->panic_package || g->have_pub_panic) &&
3279 buf_eql_str(&fn_table_entry->symbol_name, "panic"))
3280 {
3281 g->panic_fn = fn_table_entry;
3282 typecheck_panic_fn(g, fn_table_entry);
3283 }
3284 }3369 }
3285 }3370 }
3286 } else if (source_node->type == NodeTypeTestDecl) {3371 } else if (source_node->type == NodeTypeTestDecl) {
...@@ -3405,7 +3490,8 @@ void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) {...@@ -3405,7 +3490,8 @@ void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) {
3405 resolve_top_level_decl(g, tld, false, tld->source_node);3490 resolve_top_level_decl(g, tld, false, tld->source_node);
3406 assert(tld->id == TldIdVar);3491 assert(tld->id == TldIdVar);
3407 TldVar *tld_var = (TldVar *)tld;3492 TldVar *tld_var = (TldVar *)tld;
3408 tld_var->var->value = value;3493 tld_var->var->const_value = value;
3494 tld_var->var->var_type = value->type;
3409 tld_var->var->align_bytes = get_abi_alignment(g, value->type);3495 tld_var->var->align_bytes = get_abi_alignment(g, value->type);
3410}3496}
34113497
...@@ -3499,7 +3585,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {...@@ -3499,7 +3585,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
3499 case NodeTypeArrayType:3585 case NodeTypeArrayType:
3500 case NodeTypeErrorType:3586 case NodeTypeErrorType:
3501 case NodeTypeIfErrorExpr:3587 case NodeTypeIfErrorExpr:
3502 case NodeTypeTestExpr:3588 case NodeTypeIfOptional:
3503 case NodeTypeErrorSetDecl:3589 case NodeTypeErrorSetDecl:
3504 case NodeTypeCancel:3590 case NodeTypeCancel:
3505 case NodeTypeResume:3591 case NodeTypeResume:
...@@ -3560,6 +3646,7 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry...@@ -3560,6 +3646,7 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
3560 case ZigTypeIdFn:3646 case ZigTypeIdFn:
3561 case ZigTypeIdBoundFn:3647 case ZigTypeIdBoundFn:
3562 case ZigTypeIdPromise:3648 case ZigTypeIdPromise:
3649 case ZigTypeIdVector:
3563 return type_entry;3650 return type_entry;
3564 }3651 }
3565 zig_unreachable();3652 zig_unreachable();
...@@ -3568,13 +3655,15 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry...@@ -3568,13 +3655,15 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
3568// Set name to nullptr to make the variable anonymous (not visible to programmer).3655// Set name to nullptr to make the variable anonymous (not visible to programmer).
3569// TODO merge with definition of add_local_var in ir.cpp3656// TODO merge with definition of add_local_var in ir.cpp
3570ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,3657ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
3571 bool is_const, ConstExprValue *value, Tld *src_tld)3658 bool is_const, ConstExprValue *const_value, Tld *src_tld, ZigType *var_type)
3572{3659{
3573 Error err;3660 Error err;
3574 assert(value);3661 assert(const_value != nullptr);
3662 assert(var_type != nullptr);
35753663
3576 ZigVar *variable_entry = allocate<ZigVar>(1);3664 ZigVar *variable_entry = allocate<ZigVar>(1);
3577 variable_entry->value = value;3665 variable_entry->const_value = const_value;
3666 variable_entry->var_type = var_type;
3578 variable_entry->parent_scope = parent_scope;3667 variable_entry->parent_scope = parent_scope;
3579 variable_entry->shadowable = false;3668 variable_entry->shadowable = false;
3580 variable_entry->mem_slot_index = SIZE_MAX;3669 variable_entry->mem_slot_index = SIZE_MAX;
...@@ -3583,23 +3672,23 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf...@@ -3583,23 +3672,23 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
3583 assert(name);3672 assert(name);
3584 buf_init_from_buf(&variable_entry->name, name);3673 buf_init_from_buf(&variable_entry->name, name);
35853674
3586 if ((err = type_resolve(g, value->type, ResolveStatusAlignmentKnown))) {3675 if ((err = type_resolve(g, var_type, ResolveStatusAlignmentKnown))) {
3587 variable_entry->value->type = g->builtin_types.entry_invalid;3676 variable_entry->var_type = g->builtin_types.entry_invalid;
3588 } else {3677 } else {
3589 variable_entry->align_bytes = get_abi_alignment(g, value->type);3678 variable_entry->align_bytes = get_abi_alignment(g, var_type);
35903679
3591 ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr);3680 ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr);
3592 if (existing_var && !existing_var->shadowable) {3681 if (existing_var && !existing_var->shadowable) {
3593 ErrorMsg *msg = add_node_error(g, source_node,3682 ErrorMsg *msg = add_node_error(g, source_node,
3594 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));3683 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
3595 add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));3684 add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
3596 variable_entry->value->type = g->builtin_types.entry_invalid;3685 variable_entry->var_type = g->builtin_types.entry_invalid;
3597 } else {3686 } else {
3598 ZigType *type;3687 ZigType *type;
3599 if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) {3688 if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) {
3600 add_node_error(g, source_node,3689 add_node_error(g, source_node,
3601 buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));3690 buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));
3602 variable_entry->value->type = g->builtin_types.entry_invalid;3691 variable_entry->var_type = g->builtin_types.entry_invalid;
3603 } else {3692 } else {
3604 Scope *search_scope = nullptr;3693 Scope *search_scope = nullptr;
3605 if (src_tld == nullptr) {3694 if (src_tld == nullptr) {
...@@ -3613,7 +3702,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf...@@ -3613,7 +3702,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
3613 ErrorMsg *msg = add_node_error(g, source_node,3702 ErrorMsg *msg = add_node_error(g, source_node,
3614 buf_sprintf("redefinition of '%s'", buf_ptr(name)));3703 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
3615 add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here"));3704 add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here"));
3616 variable_entry->value->type = g->builtin_types.entry_invalid;3705 variable_entry->var_type = g->builtin_types.entry_invalid;
3617 }3706 }
3618 }3707 }
3619 }3708 }
...@@ -3645,6 +3734,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3645,6 +3734,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3645 bool is_const = var_decl->is_const;3734 bool is_const = var_decl->is_const;
3646 bool is_extern = var_decl->is_extern;3735 bool is_extern = var_decl->is_extern;
3647 bool is_export = var_decl->is_export;3736 bool is_export = var_decl->is_export;
3737 bool is_thread_local = var_decl->threadlocal_tok != nullptr;
36483738
3649 ZigType *explicit_type = nullptr;3739 ZigType *explicit_type = nullptr;
3650 if (var_decl->type) {3740 if (var_decl->type) {
...@@ -3663,7 +3753,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3663,7 +3753,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3663 linkage = VarLinkageInternal;3753 linkage = VarLinkageInternal;
3664 }3754 }
36653755
3666 IrInstruction *init_value = nullptr;3756 ConstExprValue *init_value = nullptr;
36673757
3668 // TODO more validation for types that can't be used for export/extern variables3758 // TODO more validation for types that can't be used for export/extern variables
3669 ZigType *implicit_type = nullptr;3759 ZigType *implicit_type = nullptr;
...@@ -3672,7 +3762,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3672,7 +3762,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3672 } else if (var_decl->expr) {3762 } else if (var_decl->expr) {
3673 init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol);3763 init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol);
3674 assert(init_value);3764 assert(init_value);
3675 implicit_type = init_value->value.type;3765 implicit_type = init_value->type;
36763766
3677 if (implicit_type->id == ZigTypeIdUnreachable) {3767 if (implicit_type->id == ZigTypeIdUnreachable) {
3678 add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));3768 add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));
...@@ -3690,7 +3780,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3690,7 +3780,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3690 add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant"));3780 add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant"));
3691 implicit_type = g->builtin_types.entry_invalid;3781 implicit_type = g->builtin_types.entry_invalid;
3692 }3782 }
3693 assert(implicit_type->id == ZigTypeIdInvalid || init_value->value.special != ConstValSpecialRuntime);3783 assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime);
3694 } else if (linkage != VarLinkageExternal) {3784 } else if (linkage != VarLinkageExternal) {
3695 add_node_error(g, source_node, buf_sprintf("variables must be initialized"));3785 add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
3696 implicit_type = g->builtin_types.entry_invalid;3786 implicit_type = g->builtin_types.entry_invalid;
...@@ -3699,19 +3789,20 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3699,19 +3789,20 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3699 ZigType *type = explicit_type ? explicit_type : implicit_type;3789 ZigType *type = explicit_type ? explicit_type : implicit_type;
3700 assert(type != nullptr); // should have been caught by the parser3790 assert(type != nullptr); // should have been caught by the parser
37013791
3702 ConstExprValue *init_val = init_value ? &init_value->value : create_const_runtime(type);3792 ConstExprValue *init_val = (init_value != nullptr) ? init_value : create_const_runtime(type);
37033793
3704 tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol,3794 tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol,
3705 is_const, init_val, &tld_var->base);3795 is_const, init_val, &tld_var->base, type);
3706 tld_var->var->linkage = linkage;3796 tld_var->var->linkage = linkage;
3797 tld_var->var->is_thread_local = is_thread_local;
37073798
3708 if (implicit_type != nullptr && type_is_invalid(implicit_type)) {3799 if (implicit_type != nullptr && type_is_invalid(implicit_type)) {
3709 tld_var->var->value->type = g->builtin_types.entry_invalid;3800 tld_var->var->var_type = g->builtin_types.entry_invalid;
3710 }3801 }
37113802
3712 if (var_decl->align_expr != nullptr) {3803 if (var_decl->align_expr != nullptr) {
3713 if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) {3804 if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) {
3714 tld_var->var->value->type = g->builtin_types.entry_invalid;3805 tld_var->var->var_type = g->builtin_types.entry_invalid;
3715 }3806 }
3716 }3807 }
37173808
...@@ -3724,6 +3815,10 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3724,6 +3815,10 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3724 }3815 }
3725 }3816 }
37263817
3818 if (is_thread_local && is_const) {
3819 add_node_error(g, source_node, buf_sprintf("threadlocal variable cannot be constant"));
3820 }
3821
3727 g->global_vars.append(tld_var);3822 g->global_vars.append(tld_var);
3728}3823}
37293824
...@@ -3924,6 +4019,7 @@ static bool is_container(ZigType *type_entry) {...@@ -3924,6 +4019,7 @@ static bool is_container(ZigType *type_entry) {
3924 case ZigTypeIdArgTuple:4019 case ZigTypeIdArgTuple:
3925 case ZigTypeIdOpaque:4020 case ZigTypeIdOpaque:
3926 case ZigTypeIdPromise:4021 case ZigTypeIdPromise:
4022 case ZigTypeIdVector:
3927 return false;4023 return false;
3928 }4024 }
3929 zig_unreachable();4025 zig_unreachable();
...@@ -3983,6 +4079,7 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) {...@@ -3983,6 +4079,7 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) {
3983 case ZigTypeIdArgTuple:4079 case ZigTypeIdArgTuple:
3984 case ZigTypeIdOpaque:4080 case ZigTypeIdOpaque:
3985 case ZigTypeIdPromise:4081 case ZigTypeIdPromise:
4082 case ZigTypeIdVector:
3986 zig_unreachable();4083 zig_unreachable();
3987 }4084 }
3988}4085}
...@@ -3992,7 +4089,9 @@ ZigType *get_src_ptr_type(ZigType *type) {...@@ -3992,7 +4089,9 @@ ZigType *get_src_ptr_type(ZigType *type) {
3992 if (type->id == ZigTypeIdFn) return type;4089 if (type->id == ZigTypeIdFn) return type;
3993 if (type->id == ZigTypeIdPromise) return type;4090 if (type->id == ZigTypeIdPromise) return type;
3994 if (type->id == ZigTypeIdOptional) {4091 if (type->id == ZigTypeIdOptional) {
3995 if (type->data.maybe.child_type->id == ZigTypeIdPointer) return type->data.maybe.child_type;4092 if (type->data.maybe.child_type->id == ZigTypeIdPointer) {
4093 return type->data.maybe.child_type->data.pointer.allow_zero ? nullptr : type->data.maybe.child_type;
4094 }
3996 if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type;4095 if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type;
3997 if (type->data.maybe.child_type->id == ZigTypeIdPromise) return type->data.maybe.child_type;4096 if (type->data.maybe.child_type->id == ZigTypeIdPromise) return type->data.maybe.child_type;
3998 }4097 }
...@@ -4006,6 +4105,10 @@ ZigType *get_codegen_ptr_type(ZigType *type) {...@@ -4006,6 +4105,10 @@ ZigType *get_codegen_ptr_type(ZigType *type) {
4006 return ty;4105 return ty;
4007}4106}
40084107
4108bool type_is_nonnull_ptr(ZigType *type) {
4109 return type_is_codegen_pointer(type) && !ptr_allows_addr_zero(type);
4110}
4111
4009bool type_is_codegen_pointer(ZigType *type) {4112bool type_is_codegen_pointer(ZigType *type) {
4010 return get_codegen_ptr_type(type) == type;4113 return get_codegen_ptr_type(type) == type;
4011}4114}
...@@ -4076,7 +4179,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {...@@ -4076,7 +4179,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {
4076 }4179 }
40774180
4078 ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope,4181 ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope,
4079 param_name, true, create_const_runtime(param_type), nullptr);4182 param_name, true, create_const_runtime(param_type), nullptr, param_type);
4080 var->src_arg_index = i;4183 var->src_arg_index = i;
4081 fn_table_entry->child_scope = var->child_scope;4184 fn_table_entry->child_scope = var->child_scope;
4082 var->shadowable = var->shadowable || is_var_args;4185 var->shadowable = var->shadowable || is_var_args;
...@@ -4214,18 +4317,17 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *...@@ -4214,18 +4317,17 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *
4214 preview_use_decl(g, src_use_node);4317 preview_use_decl(g, src_use_node);
4215 }4318 }
42164319
4217 IrInstruction *use_target_value = src_use_node->data.use.value;4320 ConstExprValue *use_target_value = src_use_node->data.use.value;
4218 if (use_target_value->value.type->id == ZigTypeIdInvalid) {4321 if (type_is_invalid(use_target_value->type)) {
4219 dst_use_node->owner->any_imports_failed = true;4322 dst_use_node->owner->any_imports_failed = true;
4220 return;4323 return;
4221 }4324 }
42224325
4223 dst_use_node->data.use.resolution = TldResolutionOk;4326 dst_use_node->data.use.resolution = TldResolutionOk;
42244327
4225 ConstExprValue *const_val = &use_target_value->value;4328 assert(use_target_value->special != ConstValSpecialRuntime);
4226 assert(const_val->special != ConstValSpecialRuntime);
42274329
4228 ImportTableEntry *target_import = const_val->data.x_import;4330 ImportTableEntry *target_import = use_target_value->data.x_import;
4229 assert(target_import);4331 assert(target_import);
42304332
4231 if (target_import->any_imports_failed) {4333 if (target_import->any_imports_failed) {
...@@ -4288,10 +4390,10 @@ void preview_use_decl(CodeGen *g, AstNode *node) {...@@ -4288,10 +4390,10 @@ void preview_use_decl(CodeGen *g, AstNode *node) {
4288 }4390 }
42894391
4290 node->data.use.resolution = TldResolutionResolving;4392 node->data.use.resolution = TldResolutionResolving;
4291 IrInstruction *result = analyze_const_value(g, &node->owner->decls_scope->base,4393 ConstExprValue *result = analyze_const_value(g, &node->owner->decls_scope->base,
4292 node->data.use.expr, g->builtin_types.entry_namespace, nullptr);4394 node->data.use.expr, g->builtin_types.entry_namespace, nullptr);
42934395
4294 if (result->value.type->id == ZigTypeIdInvalid)4396 if (type_is_invalid(result->type))
4295 node->owner->any_imports_failed = true;4397 node->owner->any_imports_failed = true;
42964398
4297 node->data.use.value = result;4399 node->data.use.value = result;
...@@ -4364,8 +4466,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *r...@@ -4364,8 +4466,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *r
4364 if (is_pub && ok_cc) {4466 if (is_pub && ok_cc) {
4365 if (buf_eql_str(proto_name, "main")) {4467 if (buf_eql_str(proto_name, "main")) {
4366 g->have_pub_main = true;4468 g->have_pub_main = true;
4367 g->windows_subsystem_windows = false;4469 g->subsystem = TargetSubsystemConsole;
4368 g->windows_subsystem_console = true;
4369 } else if (buf_eql_str(proto_name, "panic")) {4470 } else if (buf_eql_str(proto_name, "panic")) {
4370 g->have_pub_panic = true;4471 g->have_pub_panic = true;
4371 }4472 }
...@@ -4434,6 +4535,43 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {...@@ -4434,6 +4535,43 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
4434 return new_entry;4535 return new_entry;
4435}4536}
44364537
4538bool is_valid_vector_elem_type(ZigType *elem_type) {
4539 return elem_type->id == ZigTypeIdInt ||
4540 elem_type->id == ZigTypeIdFloat ||
4541 get_codegen_ptr_type(elem_type) != nullptr;
4542}
4543
4544ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) {
4545 assert(is_valid_vector_elem_type(elem_type));
4546
4547 TypeId type_id = {};
4548 type_id.id = ZigTypeIdVector;
4549 type_id.data.vector.len = len;
4550 type_id.data.vector.elem_type = elem_type;
4551
4552 {
4553 auto entry = g->type_table.maybe_get(type_id);
4554 if (entry)
4555 return entry->value;
4556 }
4557
4558 ZigType *entry = new_type_table_entry(ZigTypeIdVector);
4559 entry->zero_bits = (len == 0) || !type_has_bits(elem_type);
4560 entry->type_ref = entry->zero_bits ? LLVMVoidType() : LLVMVectorType(elem_type->type_ref, len);
4561 entry->data.vector.len = len;
4562 entry->data.vector.elem_type = elem_type;
4563
4564 buf_resize(&entry->name, 0);
4565 buf_appendf(&entry->name, "@Vector(%u, %s)", len, buf_ptr(&elem_type->name));
4566
4567 entry->di_type = ZigLLVMDIBuilderCreateVectorType(g->dbuilder,
4568 len * type_size_bits(g, elem_type),
4569 LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref), elem_type->di_type, len);
4570
4571 g->type_table.put(type_id, entry);
4572 return entry;
4573}
4574
4437ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) {4575ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) {
4438 return &g->builtin_types.entry_c_int[c_int_type];4576 return &g->builtin_types.entry_c_int[c_int_type];
4439}4577}
...@@ -4465,6 +4603,7 @@ bool handle_is_ptr(ZigType *type_entry) {...@@ -4465,6 +4603,7 @@ bool handle_is_ptr(ZigType *type_entry) {
4465 case ZigTypeIdFn:4603 case ZigTypeIdFn:
4466 case ZigTypeIdEnum:4604 case ZigTypeIdEnum:
4467 case ZigTypeIdPromise:4605 case ZigTypeIdPromise:
4606 case ZigTypeIdVector:
4468 return false;4607 return false;
4469 case ZigTypeIdArray:4608 case ZigTypeIdArray:
4470 case ZigTypeIdStruct:4609 case ZigTypeIdStruct:
...@@ -4473,7 +4612,8 @@ bool handle_is_ptr(ZigType *type_entry) {...@@ -4473,7 +4612,8 @@ bool handle_is_ptr(ZigType *type_entry) {
4473 return type_has_bits(type_entry->data.error_union.payload_type);4612 return type_has_bits(type_entry->data.error_union.payload_type);
4474 case ZigTypeIdOptional:4613 case ZigTypeIdOptional:
4475 return type_has_bits(type_entry->data.maybe.child_type) &&4614 return type_has_bits(type_entry->data.maybe.child_type) &&
4476 !type_is_codegen_pointer(type_entry->data.maybe.child_type);4615 !type_is_codegen_pointer(type_entry->data.maybe.child_type) &&
4616 type_entry->data.maybe.child_type->id != ZigTypeIdErrorSet;
4477 case ZigTypeIdUnion:4617 case ZigTypeIdUnion:
4478 assert(type_entry->data.unionation.zero_bits_known);4618 assert(type_entry->data.unionation.zero_bits_known);
4479 if (type_entry->data.unionation.gen_field_count == 0)4619 if (type_entry->data.unionation.gen_field_count == 0)
...@@ -4580,8 +4720,7 @@ static Buf *get_posix_libc_include_path(void) {...@@ -4580,8 +4720,7 @@ static Buf *get_posix_libc_include_path(void) {
4580void find_libc_include_path(CodeGen *g) {4720void find_libc_include_path(CodeGen *g) {
4581 if (g->libc_include_dir == nullptr) {4721 if (g->libc_include_dir == nullptr) {
4582 if (!g->is_native_target) {4722 if (!g->is_native_target) {
4583 fprintf(stderr, "Unable to determine libc include path. --libc-include-dir");4723 return;
4584 exit(1);
4585 }4724 }
45864725
4587 if (g->zig_target.os == OsWindows) {4726 if (g->zig_target.os == OsWindows) {
...@@ -4720,6 +4859,11 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {...@@ -4720,6 +4859,11 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {
4720 return true;4859 return true;
4721}4860}
47224861
4862static uint32_t hash_const_val_error_set(ConstExprValue *const_val) {
4863 assert(const_val->data.x_err_set != nullptr);
4864 return const_val->data.x_err_set->value ^ 2630160122;
4865}
4866
4723static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {4867static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
4724 uint32_t hash_val = 0;4868 uint32_t hash_val = 0;
4725 switch (const_val->data.x_ptr.mut) {4869 switch (const_val->data.x_ptr.mut) {
...@@ -4751,6 +4895,18 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {...@@ -4751,6 +4895,18 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
4751 hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val);4895 hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val);
4752 hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index);4896 hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index);
4753 return hash_val;4897 return hash_val;
4898 case ConstPtrSpecialBaseErrorUnionCode:
4899 hash_val += (uint32_t)2994743799;
4900 hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_code.err_union_val);
4901 return hash_val;
4902 case ConstPtrSpecialBaseErrorUnionPayload:
4903 hash_val += (uint32_t)3456080131;
4904 hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_payload.err_union_val);
4905 return hash_val;
4906 case ConstPtrSpecialBaseOptionalPayload:
4907 hash_val += (uint32_t)3163140517;
4908 hash_val += hash_ptr(const_val->data.x_ptr.data.base_optional_payload.optional_val);
4909 return hash_val;
4754 case ConstPtrSpecialHardCodedAddr:4910 case ConstPtrSpecialHardCodedAddr:
4755 hash_val += (uint32_t)4048518294;4911 hash_val += (uint32_t)4048518294;
4756 hash_val += hash_size(const_val->data.x_ptr.data.hard_coded_addr.addr);4912 hash_val += hash_size(const_val->data.x_ptr.data.hard_coded_addr.addr);
...@@ -4762,6 +4918,9 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {...@@ -4762,6 +4918,9 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
4762 hash_val += (uint32_t)2590901619;4918 hash_val += (uint32_t)2590901619;
4763 hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry);4919 hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry);
4764 return hash_val;4920 return hash_val;
4921 case ConstPtrSpecialNull:
4922 hash_val += (uint32_t)1486246455;
4923 return hash_val;
4765 }4924 }
4766 zig_unreachable();4925 zig_unreachable();
4767}4926}
...@@ -4860,7 +5019,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {...@@ -4860,7 +5019,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
4860 return 2709806591;5019 return 2709806591;
4861 case ZigTypeIdOptional:5020 case ZigTypeIdOptional:
4862 if (get_codegen_ptr_type(const_val->type) != nullptr) {5021 if (get_codegen_ptr_type(const_val->type) != nullptr) {
4863 return hash_const_val(const_val) * 1992916303;5022 return hash_const_val_ptr(const_val) * 1992916303;
5023 } else if (const_val->type->data.maybe.child_type->id == ZigTypeIdErrorSet) {
5024 return hash_const_val_error_set(const_val) * 3147031929;
4864 } else {5025 } else {
4865 if (const_val->data.x_optional) {5026 if (const_val->data.x_optional) {
4866 return hash_const_val(const_val->data.x_optional) * 1992916303;5027 return hash_const_val(const_val->data.x_optional) * 1992916303;
...@@ -4872,10 +5033,12 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {...@@ -4872,10 +5033,12 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
4872 // TODO better hashing algorithm5033 // TODO better hashing algorithm
4873 return 3415065496;5034 return 3415065496;
4874 case ZigTypeIdErrorSet:5035 case ZigTypeIdErrorSet:
4875 assert(const_val->data.x_err_set != nullptr);5036 return hash_const_val_error_set(const_val);
4876 return const_val->data.x_err_set->value ^ 2630160122;
4877 case ZigTypeIdNamespace:5037 case ZigTypeIdNamespace:
4878 return hash_ptr(const_val->data.x_import);5038 return hash_ptr(const_val->data.x_import);
5039 case ZigTypeIdVector:
5040 // TODO better hashing algorithm
5041 return 3647867726;
4879 case ZigTypeIdBoundFn:5042 case ZigTypeIdBoundFn:
4880 case ZigTypeIdInvalid:5043 case ZigTypeIdInvalid:
4881 case ZigTypeIdUnreachable:5044 case ZigTypeIdUnreachable:
...@@ -4928,6 +5091,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {...@@ -4928,6 +5091,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
4928 case ZigTypeIdBool:5091 case ZigTypeIdBool:
4929 case ZigTypeIdUnreachable:5092 case ZigTypeIdUnreachable:
4930 case ZigTypeIdInt:5093 case ZigTypeIdInt:
5094 case ZigTypeIdVector:
4931 case ZigTypeIdFloat:5095 case ZigTypeIdFloat:
4932 case ZigTypeIdComptimeFloat:5096 case ZigTypeIdComptimeFloat:
4933 case ZigTypeIdComptimeInt:5097 case ZigTypeIdComptimeInt:
...@@ -4975,7 +5139,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {...@@ -4975,7 +5139,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
4975 return can_mutate_comptime_var_state(value->data.x_optional);5139 return can_mutate_comptime_var_state(value->data.x_optional);
49765140
4977 case ZigTypeIdErrorUnion:5141 case ZigTypeIdErrorUnion:
4978 if (value->data.x_err_union.err != nullptr)5142 if (value->data.x_err_union.error_set->data.x_err_set != nullptr)
4979 return false;5143 return false;
4980 assert(value->data.x_err_union.payload != nullptr);5144 assert(value->data.x_err_union.payload != nullptr);
4981 return can_mutate_comptime_var_state(value->data.x_err_union.payload);5145 return can_mutate_comptime_var_state(value->data.x_err_union.payload);
...@@ -5011,6 +5175,7 @@ static bool return_type_is_cacheable(ZigType *return_type) {...@@ -5011,6 +5175,7 @@ static bool return_type_is_cacheable(ZigType *return_type) {
5011 case ZigTypeIdErrorSet:5175 case ZigTypeIdErrorSet:
5012 case ZigTypeIdEnum:5176 case ZigTypeIdEnum:
5013 case ZigTypeIdPointer:5177 case ZigTypeIdPointer:
5178 case ZigTypeIdVector:
5014 return true;5179 return true;
50155180
5016 case ZigTypeIdArray:5181 case ZigTypeIdArray:
...@@ -5036,9 +5201,9 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) {...@@ -5036,9 +5201,9 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) {
5036 while (scope) {5201 while (scope) {
5037 if (scope->id == ScopeIdVarDecl) {5202 if (scope->id == ScopeIdVarDecl) {
5038 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;5203 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
5039 if (type_is_invalid(var_scope->var->value->type))5204 if (type_is_invalid(var_scope->var->var_type))
5040 return false;5205 return false;
5041 if (can_mutate_comptime_var_state(var_scope->var->value))5206 if (can_mutate_comptime_var_state(var_scope->var->const_value))
5042 return false;5207 return false;
5043 } else if (scope->id == ScopeIdFnDef) {5208 } else if (scope->id == ScopeIdFnDef) {
5044 return true;5209 return true;
...@@ -5056,7 +5221,7 @@ uint32_t fn_eval_hash(Scope* scope) {...@@ -5056,7 +5221,7 @@ uint32_t fn_eval_hash(Scope* scope) {
5056 while (scope) {5221 while (scope) {
5057 if (scope->id == ScopeIdVarDecl) {5222 if (scope->id == ScopeIdVarDecl) {
5058 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;5223 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
5059 result += hash_const_val(var_scope->var->value);5224 result += hash_const_val(var_scope->var->const_value);
5060 } else if (scope->id == ScopeIdFnDef) {5225 } else if (scope->id == ScopeIdFnDef) {
5061 ScopeFnDef *fn_scope = (ScopeFnDef *)scope;5226 ScopeFnDef *fn_scope = (ScopeFnDef *)scope;
5062 result += hash_ptr(fn_scope->fn_entry);5227 result += hash_ptr(fn_scope->fn_entry);
...@@ -5080,10 +5245,16 @@ bool fn_eval_eql(Scope *a, Scope *b) {...@@ -5080,10 +5245,16 @@ bool fn_eval_eql(Scope *a, Scope *b) {
5080 if (a->id == ScopeIdVarDecl) {5245 if (a->id == ScopeIdVarDecl) {
5081 ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a;5246 ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a;
5082 ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b;5247 ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b;
5083 if (a_var_scope->var->value->type != b_var_scope->var->value->type)5248 if (a_var_scope->var->var_type != b_var_scope->var->var_type)
5084 return false;
5085 if (!const_values_equal(a->codegen, a_var_scope->var->value, b_var_scope->var->value))
5086 return false;5249 return false;
5250 if (a_var_scope->var->var_type == a_var_scope->var->const_value->type &&
5251 b_var_scope->var->var_type == b_var_scope->var->const_value->type)
5252 {
5253 if (!const_values_equal(a->codegen, a_var_scope->var->const_value, b_var_scope->var->const_value))
5254 return false;
5255 } else {
5256 zig_panic("TODO comptime ptr reinterpret for fn_eval_eql");
5257 }
5087 } else if (a->id == ScopeIdFnDef) {5258 } else if (a->id == ScopeIdFnDef) {
5088 ScopeFnDef *a_fn_scope = (ScopeFnDef *)a;5259 ScopeFnDef *a_fn_scope = (ScopeFnDef *)a;
5089 ScopeFnDef *b_fn_scope = (ScopeFnDef *)b;5260 ScopeFnDef *b_fn_scope = (ScopeFnDef *)b;
...@@ -5101,6 +5272,7 @@ bool fn_eval_eql(Scope *a, Scope *b) {...@@ -5101,6 +5272,7 @@ bool fn_eval_eql(Scope *a, Scope *b) {
5101 return false;5272 return false;
5102}5273}
51035274
5275// Whether the type has bits at runtime.
5104bool type_has_bits(ZigType *type_entry) {5276bool type_has_bits(ZigType *type_entry) {
5105 assert(type_entry);5277 assert(type_entry);
5106 assert(!type_is_invalid(type_entry));5278 assert(!type_is_invalid(type_entry));
...@@ -5108,6 +5280,66 @@ bool type_has_bits(ZigType *type_entry) {...@@ -5108,6 +5280,66 @@ bool type_has_bits(ZigType *type_entry) {
5108 return !type_entry->zero_bits;5280 return !type_entry->zero_bits;
5109}5281}
51105282
5283// Whether you can infer the value based solely on the type.
5284OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
5285 assert(type_entry != nullptr);
5286 Error err;
5287 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
5288 return OnePossibleValueInvalid;
5289 switch (type_entry->id) {
5290 case ZigTypeIdInvalid:
5291 zig_unreachable();
5292 case ZigTypeIdOpaque:
5293 case ZigTypeIdComptimeFloat:
5294 case ZigTypeIdComptimeInt:
5295 case ZigTypeIdMetaType:
5296 case ZigTypeIdNamespace:
5297 case ZigTypeIdBoundFn:
5298 case ZigTypeIdArgTuple:
5299 case ZigTypeIdOptional:
5300 case ZigTypeIdFn:
5301 case ZigTypeIdBool:
5302 case ZigTypeIdFloat:
5303 case ZigTypeIdPromise:
5304 case ZigTypeIdErrorUnion:
5305 return OnePossibleValueNo;
5306 case ZigTypeIdUndefined:
5307 case ZigTypeIdNull:
5308 case ZigTypeIdVoid:
5309 case ZigTypeIdUnreachable:
5310 return OnePossibleValueYes;
5311 case ZigTypeIdArray:
5312 if (type_entry->data.array.len == 0)
5313 return OnePossibleValueYes;
5314 return type_has_one_possible_value(g, type_entry->data.array.child_type);
5315 case ZigTypeIdStruct:
5316 for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
5317 TypeStructField *field = &type_entry->data.structure.fields[i];
5318 switch (type_has_one_possible_value(g, field->type_entry)) {
5319 case OnePossibleValueInvalid:
5320 return OnePossibleValueInvalid;
5321 case OnePossibleValueNo:
5322 return OnePossibleValueNo;
5323 case OnePossibleValueYes:
5324 continue;
5325 }
5326 }
5327 return OnePossibleValueYes;
5328 case ZigTypeIdErrorSet:
5329 case ZigTypeIdEnum:
5330 case ZigTypeIdInt:
5331 case ZigTypeIdVector:
5332 return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes;
5333 case ZigTypeIdPointer:
5334 return type_has_one_possible_value(g, type_entry->data.pointer.child_type);
5335 case ZigTypeIdUnion:
5336 if (type_entry->data.unionation.src_field_count > 1)
5337 return OnePossibleValueNo;
5338 return type_has_one_possible_value(g, type_entry->data.unionation.fields[0].type_entry);
5339 }
5340 zig_unreachable();
5341}
5342
5111ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {5343ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
5112 Error err;5344 Error err;
5113 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))5345 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
...@@ -5147,6 +5379,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {...@@ -5147,6 +5379,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
5147 case ZigTypeIdErrorSet:5379 case ZigTypeIdErrorSet:
5148 case ZigTypeIdBool:5380 case ZigTypeIdBool:
5149 case ZigTypeIdInt:5381 case ZigTypeIdInt:
5382 case ZigTypeIdVector:
5150 case ZigTypeIdFloat:5383 case ZigTypeIdFloat:
5151 case ZigTypeIdVoid:5384 case ZigTypeIdVoid:
5152 case ZigTypeIdUnreachable:5385 case ZigTypeIdUnreachable:
...@@ -5562,6 +5795,33 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {...@@ -5562,6 +5795,33 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
5562 if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index)5795 if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index)
5563 return false;5796 return false;
5564 return true;5797 return true;
5798 case ConstPtrSpecialBaseErrorUnionCode:
5799 if (a->data.x_ptr.data.base_err_union_code.err_union_val !=
5800 b->data.x_ptr.data.base_err_union_code.err_union_val &&
5801 a->data.x_ptr.data.base_err_union_code.err_union_val->global_refs !=
5802 b->data.x_ptr.data.base_err_union_code.err_union_val->global_refs)
5803 {
5804 return false;
5805 }
5806 return true;
5807 case ConstPtrSpecialBaseErrorUnionPayload:
5808 if (a->data.x_ptr.data.base_err_union_payload.err_union_val !=
5809 b->data.x_ptr.data.base_err_union_payload.err_union_val &&
5810 a->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs !=
5811 b->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs)
5812 {
5813 return false;
5814 }
5815 return true;
5816 case ConstPtrSpecialBaseOptionalPayload:
5817 if (a->data.x_ptr.data.base_optional_payload.optional_val !=
5818 b->data.x_ptr.data.base_optional_payload.optional_val &&
5819 a->data.x_ptr.data.base_optional_payload.optional_val->global_refs !=
5820 b->data.x_ptr.data.base_optional_payload.optional_val->global_refs)
5821 {
5822 return false;
5823 }
5824 return true;
5565 case ConstPtrSpecialHardCodedAddr:5825 case ConstPtrSpecialHardCodedAddr:
5566 if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr)5826 if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr)
5567 return false;5827 return false;
...@@ -5570,10 +5830,34 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {...@@ -5570,10 +5830,34 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
5570 return true;5830 return true;
5571 case ConstPtrSpecialFunction:5831 case ConstPtrSpecialFunction:
5572 return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry;5832 return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry;
5833 case ConstPtrSpecialNull:
5834 return true;
5573 }5835 }
5574 zig_unreachable();5836 zig_unreachable();
5575}5837}
55765838
5839static bool const_values_equal_array(CodeGen *g, ConstExprValue *a, ConstExprValue *b, size_t len) {
5840 assert(a->data.x_array.special != ConstArraySpecialUndef);
5841 assert(b->data.x_array.special != ConstArraySpecialUndef);
5842 if (a->data.x_array.special == ConstArraySpecialBuf &&
5843 b->data.x_array.special == ConstArraySpecialBuf)
5844 {
5845 return buf_eql_buf(a->data.x_array.data.s_buf, b->data.x_array.data.s_buf);
5846 }
5847 expand_undef_array(g, a);
5848 expand_undef_array(g, b);
5849
5850 ConstExprValue *a_elems = a->data.x_array.data.s_none.elements;
5851 ConstExprValue *b_elems = b->data.x_array.data.s_none.elements;
5852
5853 for (size_t i = 0; i < len; i += 1) {
5854 if (!const_values_equal(g, &a_elems[i], &b_elems[i]))
5855 return false;
5856 }
5857
5858 return true;
5859}
5860
5577bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {5861bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
5578 assert(a->type->id == b->type->id);5862 assert(a->type->id == b->type->id);
5579 assert(a->special == ConstValSpecialStatic);5863 assert(a->special == ConstValSpecialStatic);
...@@ -5628,28 +5912,12 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {...@@ -5628,28 +5912,12 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
5628 case ZigTypeIdPointer:5912 case ZigTypeIdPointer:
5629 case ZigTypeIdFn:5913 case ZigTypeIdFn:
5630 return const_values_equal_ptr(a, b);5914 return const_values_equal_ptr(a, b);
5915 case ZigTypeIdVector:
5916 assert(a->type->data.vector.len == b->type->data.vector.len);
5917 return const_values_equal_array(g, a, b, a->type->data.vector.len);
5631 case ZigTypeIdArray: {5918 case ZigTypeIdArray: {
5632 assert(a->type->data.array.len == b->type->data.array.len);5919 assert(a->type->data.array.len == b->type->data.array.len);
5633 assert(a->data.x_array.special != ConstArraySpecialUndef);5920 return const_values_equal_array(g, a, b, a->type->data.array.len);
5634 assert(b->data.x_array.special != ConstArraySpecialUndef);
5635 if (a->data.x_array.special == ConstArraySpecialBuf &&
5636 b->data.x_array.special == ConstArraySpecialBuf)
5637 {
5638 return buf_eql_buf(a->data.x_array.data.s_buf, b->data.x_array.data.s_buf);
5639 }
5640 expand_undef_array(g, a);
5641 expand_undef_array(g, b);
5642
5643 size_t len = a->type->data.array.len;
5644 ConstExprValue *a_elems = a->data.x_array.data.s_none.elements;
5645 ConstExprValue *b_elems = b->data.x_array.data.s_none.elements;
5646
5647 for (size_t i = 0; i < len; ++i) {
5648 if (!const_values_equal(g, &a_elems[i], &b_elems[i]))
5649 return false;
5650 }
5651
5652 return true;
5653 }5921 }
5654 case ZigTypeIdStruct:5922 case ZigTypeIdStruct:
5655 for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) {5923 for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) {
...@@ -5738,14 +6006,25 @@ void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_v...@@ -5738,14 +6006,25 @@ void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_v
5738 }6006 }
5739}6007}
57406008
5741void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {6009static void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {
6010 assert(type_entry->id == ZigTypeIdPointer);
6011
6012 if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) {
6013 buf_append_buf(buf, &type_entry->name);
6014 return;
6015 }
6016
5742 switch (const_val->data.x_ptr.special) {6017 switch (const_val->data.x_ptr.special) {
5743 case ConstPtrSpecialInvalid:6018 case ConstPtrSpecialInvalid:
5744 zig_unreachable();6019 zig_unreachable();
5745 case ConstPtrSpecialRef:6020 case ConstPtrSpecialRef:
5746 case ConstPtrSpecialBaseStruct:6021 case ConstPtrSpecialBaseStruct:
6022 case ConstPtrSpecialBaseErrorUnionCode:
6023 case ConstPtrSpecialBaseErrorUnionPayload:
6024 case ConstPtrSpecialBaseOptionalPayload:
5747 buf_appendf(buf, "*");6025 buf_appendf(buf, "*");
5748 render_const_value(g, buf, const_ptr_pointee(g, const_val));6026 // TODO we need a source node for const_ptr_pointee because it can generate compile errors
6027 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
5749 return;6028 return;
5750 case ConstPtrSpecialBaseArray:6029 case ConstPtrSpecialBaseArray:
5751 if (const_val->data.x_ptr.data.base_array.is_cstr) {6030 if (const_val->data.x_ptr.data.base_array.is_cstr) {
...@@ -5753,7 +6032,8 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy...@@ -5753,7 +6032,8 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy
5753 return;6032 return;
5754 } else {6033 } else {
5755 buf_appendf(buf, "*");6034 buf_appendf(buf, "*");
5756 render_const_value(g, buf, const_ptr_pointee(g, const_val));6035 // TODO we need a source node for const_ptr_pointee because it can generate compile errors
6036 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
5757 return;6037 return;
5758 }6038 }
5759 case ConstPtrSpecialHardCodedAddr:6039 case ConstPtrSpecialHardCodedAddr:
...@@ -5769,6 +6049,56 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy...@@ -5769,6 +6049,56 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy
5769 buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name));6049 buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name));
5770 return;6050 return;
5771 }6051 }
6052 case ConstPtrSpecialNull:
6053 buf_append_str(buf, "null");
6054 return;
6055 }
6056 zig_unreachable();
6057}
6058
6059static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {
6060 if (const_val->data.x_err_set == nullptr) {
6061 buf_append_str(buf, "null");
6062 } else {
6063 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name));
6064 }
6065}
6066
6067static void render_const_val_array(CodeGen *g, Buf *buf, Buf *type_name, ConstExprValue *const_val, uint64_t start, uint64_t len) {
6068 ConstArrayValue *array = &const_val->data.x_array;
6069 switch (array->special) {
6070 case ConstArraySpecialUndef:
6071 buf_append_str(buf, "undefined");
6072 return;
6073 case ConstArraySpecialBuf: {
6074 Buf *array_buf = array->data.s_buf;
6075 const char *base = &buf_ptr(array_buf)[start];
6076 assert(start + len <= buf_len(array_buf));
6077
6078 buf_append_char(buf, '"');
6079 for (size_t i = 0; i < len; i += 1) {
6080 uint8_t c = base[i];
6081 if (c == '"') {
6082 buf_append_str(buf, "\\\"");
6083 } else {
6084 buf_append_char(buf, c);
6085 }
6086 }
6087 buf_append_char(buf, '"');
6088 return;
6089 }
6090 case ConstArraySpecialNone: {
6091 ConstExprValue *base = &array->data.s_none.elements[start];
6092 assert(start + len <= const_val->type->data.array.len);
6093
6094 buf_appendf(buf, "%s{", buf_ptr(type_name));
6095 for (uint64_t i = 0; i < len; i += 1) {
6096 if (i != 0) buf_appendf(buf, ",");
6097 render_const_value(g, buf, &base[i]);
6098 }
6099 buf_appendf(buf, "}");
6100 return;
6101 }
5772 }6102 }
5773 zig_unreachable();6103 zig_unreachable();
5774}6104}
...@@ -5853,39 +6183,16 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -5853,39 +6183,16 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
5853 }6183 }
5854 case ZigTypeIdPointer:6184 case ZigTypeIdPointer:
5855 return render_const_val_ptr(g, buf, const_val, type_entry);6185 return render_const_val_ptr(g, buf, const_val, type_entry);
5856 case ZigTypeIdArray:6186 case ZigTypeIdArray: {
5857 switch (const_val->data.x_array.special) {6187 uint64_t len = type_entry->data.array.len;
5858 case ConstArraySpecialUndef:6188 render_const_val_array(g, buf, &type_entry->name, const_val, 0, len);
5859 buf_append_str(buf, "undefined");6189 return;
5860 return;6190 }
5861 case ConstArraySpecialBuf: {6191 case ZigTypeIdVector: {
5862 Buf *array_buf = const_val->data.x_array.data.s_buf;6192 uint32_t len = type_entry->data.vector.len;
5863 buf_append_char(buf, '"');6193 render_const_val_array(g, buf, &type_entry->name, const_val, 0, len);
5864 for (size_t i = 0; i < buf_len(array_buf); i += 1) {6194 return;
5865 uint8_t c = buf_ptr(array_buf)[i];6195 }
5866 if (c == '"') {
5867 buf_append_str(buf, "\\\"");
5868 } else {
5869 buf_append_char(buf, c);
5870 }
5871 }
5872 buf_append_char(buf, '"');
5873 return;
5874 }
5875 case ConstArraySpecialNone: {
5876 buf_appendf(buf, "%s{", buf_ptr(&type_entry->name));
5877 uint64_t len = type_entry->data.array.len;
5878 for (uint64_t i = 0; i < len; i += 1) {
5879 if (i != 0)
5880 buf_appendf(buf, ",");
5881 ConstExprValue *child_value = &const_val->data.x_array.data.s_none.elements[i];
5882 render_const_value(g, buf, child_value);
5883 }
5884 buf_appendf(buf, "}");
5885 return;
5886 }
5887 }
5888 zig_unreachable();
5889 case ZigTypeIdNull:6196 case ZigTypeIdNull:
5890 {6197 {
5891 buf_appendf(buf, "null");6198 buf_appendf(buf, "null");
...@@ -5900,6 +6207,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -5900,6 +6207,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
5900 {6207 {
5901 if (get_codegen_ptr_type(const_val->type) != nullptr)6208 if (get_codegen_ptr_type(const_val->type) != nullptr)
5902 return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type);6209 return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type);
6210 if (type_entry->data.maybe.child_type->id == ZigTypeIdErrorSet)
6211 return render_const_val_err_set(g, buf, const_val, type_entry->data.maybe.child_type);
5903 if (const_val->data.x_optional) {6212 if (const_val->data.x_optional) {
5904 render_const_value(g, buf, const_val->data.x_optional);6213 render_const_value(g, buf, const_val->data.x_optional);
5905 } else {6214 } else {
...@@ -5925,7 +6234,24 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -5925,7 +6234,24 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
5925 }6234 }
5926 case ZigTypeIdStruct:6235 case ZigTypeIdStruct:
5927 {6236 {
5928 buf_appendf(buf, "(struct %s constant)", buf_ptr(&type_entry->name));6237 if (is_slice(type_entry)) {
6238 ConstExprValue *len_val = &const_val->data.x_struct.fields[slice_len_index];
6239 size_t len = bigint_as_unsigned(&len_val->data.x_bigint);
6240
6241 ConstExprValue *ptr_val = &const_val->data.x_struct.fields[slice_ptr_index];
6242 if (ptr_val->special == ConstValSpecialUndef) {
6243 assert(len == 0);
6244 buf_appendf(buf, "((%s)(undefined))[0..0]", buf_ptr(&type_entry->name));
6245 return;
6246 }
6247 assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
6248 ConstExprValue *array = ptr_val->data.x_ptr.data.base_array.array_val;
6249 size_t start = ptr_val->data.x_ptr.data.base_array.elem_index;
6250
6251 render_const_val_array(g, buf, &type_entry->name, array, start, len);
6252 } else {
6253 buf_appendf(buf, "(struct %s constant)", buf_ptr(&type_entry->name));
6254 }
5929 return;6255 return;
5930 }6256 }
5931 case ZigTypeIdEnum:6257 case ZigTypeIdEnum:
...@@ -5937,11 +6263,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -5937,11 +6263,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
5937 case ZigTypeIdErrorUnion:6263 case ZigTypeIdErrorUnion:
5938 {6264 {
5939 buf_appendf(buf, "%s(", buf_ptr(&type_entry->name));6265 buf_appendf(buf, "%s(", buf_ptr(&type_entry->name));
5940 if (const_val->data.x_err_union.err == nullptr) {6266 ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
6267 if (err_set == nullptr) {
5941 render_const_value(g, buf, const_val->data.x_err_union.payload);6268 render_const_value(g, buf, const_val->data.x_err_union.payload);
5942 } else {6269 } else {
5943 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name),6270 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name),
5944 buf_ptr(&const_val->data.x_err_union.err->name));6271 buf_ptr(&err_set->name));
5945 }6272 }
5946 buf_appendf(buf, ")");6273 buf_appendf(buf, ")");
5947 return;6274 return;
...@@ -5956,10 +6283,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -5956,10 +6283,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
5956 return;6283 return;
5957 }6284 }
5958 case ZigTypeIdErrorSet:6285 case ZigTypeIdErrorSet:
5959 {6286 return render_const_val_err_set(g, buf, const_val, type_entry);
5960 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name));
5961 return;
5962 }
5963 case ZigTypeIdArgTuple:6287 case ZigTypeIdArgTuple:
5964 {6288 {
5965 buf_appendf(buf, "(args value)");6289 buf_appendf(buf, "(args value)");
...@@ -6035,6 +6359,7 @@ uint32_t type_id_hash(TypeId x) {...@@ -6035,6 +6359,7 @@ uint32_t type_id_hash(TypeId x) {
6035 ((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) +6359 ((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) +
6036 (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +6360 (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +
6037 (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) +6361 (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) +
6362 (x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) +
6038 (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +6363 (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +
6039 (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +6364 (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +
6040 (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);6365 (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);
...@@ -6044,6 +6369,8 @@ uint32_t type_id_hash(TypeId x) {...@@ -6044,6 +6369,8 @@ uint32_t type_id_hash(TypeId x) {
6044 case ZigTypeIdInt:6369 case ZigTypeIdInt:
6045 return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) +6370 return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) +
6046 (((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557);6371 (((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557);
6372 case ZigTypeIdVector:
6373 return hash_ptr(x.data.vector.elem_type) * (x.data.vector.len * 526582681);
6047 }6374 }
6048 zig_unreachable();6375 zig_unreachable();
6049}6376}
...@@ -6083,6 +6410,7 @@ bool type_id_eql(TypeId a, TypeId b) {...@@ -6083,6 +6410,7 @@ bool type_id_eql(TypeId a, TypeId b) {
6083 a.data.pointer.ptr_len == b.data.pointer.ptr_len &&6410 a.data.pointer.ptr_len == b.data.pointer.ptr_len &&
6084 a.data.pointer.is_const == b.data.pointer.is_const &&6411 a.data.pointer.is_const == b.data.pointer.is_const &&
6085 a.data.pointer.is_volatile == b.data.pointer.is_volatile &&6412 a.data.pointer.is_volatile == b.data.pointer.is_volatile &&
6413 a.data.pointer.allow_zero == b.data.pointer.allow_zero &&
6086 a.data.pointer.alignment == b.data.pointer.alignment &&6414 a.data.pointer.alignment == b.data.pointer.alignment &&
6087 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&6415 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&
6088 a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes;6416 a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes;
...@@ -6092,6 +6420,9 @@ bool type_id_eql(TypeId a, TypeId b) {...@@ -6092,6 +6420,9 @@ bool type_id_eql(TypeId a, TypeId b) {
6092 case ZigTypeIdInt:6420 case ZigTypeIdInt:
6093 return a.data.integer.is_signed == b.data.integer.is_signed &&6421 return a.data.integer.is_signed == b.data.integer.is_signed &&
6094 a.data.integer.bit_count == b.data.integer.bit_count;6422 a.data.integer.bit_count == b.data.integer.bit_count;
6423 case ZigTypeIdVector:
6424 return a.data.vector.elem_type == b.data.vector.elem_type &&
6425 a.data.vector.len == b.data.vector.len;
6095 }6426 }
6096 zig_unreachable();6427 zig_unreachable();
6097}6428}
...@@ -6110,10 +6441,15 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {...@@ -6110,10 +6441,15 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {
6110 return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089;6441 return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089;
6111 case ZigLLVMFnIdSqrt:6442 case ZigLLVMFnIdSqrt:
6112 return (uint32_t)(x.data.floating.bit_count) * (uint32_t)2225366385;6443 return (uint32_t)(x.data.floating.bit_count) * (uint32_t)2225366385;
6444 case ZigLLVMFnIdBswap:
6445 return (uint32_t)(x.data.bswap.bit_count) * (uint32_t)3661994335;
6446 case ZigLLVMFnIdBitReverse:
6447 return (uint32_t)(x.data.bit_reverse.bit_count) * (uint32_t)2621398431;
6113 case ZigLLVMFnIdOverflowArithmetic:6448 case ZigLLVMFnIdOverflowArithmetic:
6114 return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) +6449 return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) +
6115 ((uint32_t)(x.data.overflow_arithmetic.add_sub_mul) * 31640542) +6450 ((uint32_t)(x.data.overflow_arithmetic.add_sub_mul) * 31640542) +
6116 ((uint32_t)(x.data.overflow_arithmetic.is_signed) ? 1062315172 : 314955820);6451 ((uint32_t)(x.data.overflow_arithmetic.is_signed) ? 1062315172 : 314955820) +
6452 x.data.overflow_arithmetic.vector_len * 1435156945;
6117 }6453 }
6118 zig_unreachable();6454 zig_unreachable();
6119}6455}
...@@ -6128,6 +6464,10 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {...@@ -6128,6 +6464,10 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
6128 return a.data.clz.bit_count == b.data.clz.bit_count;6464 return a.data.clz.bit_count == b.data.clz.bit_count;
6129 case ZigLLVMFnIdPopCount:6465 case ZigLLVMFnIdPopCount:
6130 return a.data.pop_count.bit_count == b.data.pop_count.bit_count;6466 return a.data.pop_count.bit_count == b.data.pop_count.bit_count;
6467 case ZigLLVMFnIdBswap:
6468 return a.data.bswap.bit_count == b.data.bswap.bit_count;
6469 case ZigLLVMFnIdBitReverse:
6470 return a.data.bit_reverse.bit_count == b.data.bit_reverse.bit_count;
6131 case ZigLLVMFnIdFloor:6471 case ZigLLVMFnIdFloor:
6132 case ZigLLVMFnIdCeil:6472 case ZigLLVMFnIdCeil:
6133 case ZigLLVMFnIdSqrt:6473 case ZigLLVMFnIdSqrt:
...@@ -6135,31 +6475,42 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {...@@ -6135,31 +6475,42 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
6135 case ZigLLVMFnIdOverflowArithmetic:6475 case ZigLLVMFnIdOverflowArithmetic:
6136 return (a.data.overflow_arithmetic.bit_count == b.data.overflow_arithmetic.bit_count) &&6476 return (a.data.overflow_arithmetic.bit_count == b.data.overflow_arithmetic.bit_count) &&
6137 (a.data.overflow_arithmetic.add_sub_mul == b.data.overflow_arithmetic.add_sub_mul) &&6477 (a.data.overflow_arithmetic.add_sub_mul == b.data.overflow_arithmetic.add_sub_mul) &&
6138 (a.data.overflow_arithmetic.is_signed == b.data.overflow_arithmetic.is_signed);6478 (a.data.overflow_arithmetic.is_signed == b.data.overflow_arithmetic.is_signed) &&
6479 (a.data.overflow_arithmetic.vector_len == b.data.overflow_arithmetic.vector_len);
6139 }6480 }
6140 zig_unreachable();6481 zig_unreachable();
6141}6482}
61426483
6143// Canonicalize the array value as ConstArraySpecialNone6484// Canonicalize the array value as ConstArraySpecialNone
6144void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {6485void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
6145 assert(const_val->type->id == ZigTypeIdArray);6486 size_t elem_count;
6487 ZigType *elem_type;
6488 if (const_val->type->id == ZigTypeIdArray) {
6489 elem_count = const_val->type->data.array.len;
6490 elem_type = const_val->type->data.array.child_type;
6491 } else if (const_val->type->id == ZigTypeIdVector) {
6492 elem_count = const_val->type->data.vector.len;
6493 elem_type = const_val->type->data.vector.elem_type;
6494 } else {
6495 zig_unreachable();
6496 }
6497 if (const_val->special == ConstValSpecialUndef) {
6498 const_val->special = ConstValSpecialStatic;
6499 const_val->data.x_array.special = ConstArraySpecialUndef;
6500 }
6146 switch (const_val->data.x_array.special) {6501 switch (const_val->data.x_array.special) {
6147 case ConstArraySpecialNone:6502 case ConstArraySpecialNone:
6148 return;6503 return;
6149 case ConstArraySpecialUndef: {6504 case ConstArraySpecialUndef: {
6150 const_val->data.x_array.special = ConstArraySpecialNone;6505 const_val->data.x_array.special = ConstArraySpecialNone;
6151 size_t elem_count = const_val->type->data.array.len;
6152 const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count);6506 const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count);
6153 for (size_t i = 0; i < elem_count; i += 1) {6507 for (size_t i = 0; i < elem_count; i += 1) {
6154 ConstExprValue *element_val = &const_val->data.x_array.data.s_none.elements[i];6508 ConstExprValue *element_val = &const_val->data.x_array.data.s_none.elements[i];
6155 element_val->type = const_val->type->data.array.child_type;6509 element_val->type = elem_type;
6156 init_const_undefined(g, element_val);6510 init_const_undefined(g, element_val);
6157 ConstParent *parent = get_const_val_parent(g, element_val);6511 element_val->parent.id = ConstParentIdArray;
6158 if (parent != nullptr) {6512 element_val->parent.data.p_array.array_val = const_val;
6159 parent->id = ConstParentIdArray;6513 element_val->parent.data.p_array.elem_index = i;
6160 parent->data.p_array.array_val = const_val;
6161 parent->data.p_array.elem_index = i;
6162 }
6163 }6514 }
6164 return;6515 return;
6165 }6516 }
...@@ -6170,7 +6521,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {...@@ -6170,7 +6521,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
6170 g->string_literals_table.maybe_remove(buf);6521 g->string_literals_table.maybe_remove(buf);
61716522
6172 const_val->data.x_array.special = ConstArraySpecialNone;6523 const_val->data.x_array.special = ConstArraySpecialNone;
6173 size_t elem_count = const_val->type->data.array.len;
6174 assert(elem_count == buf_len(buf));6524 assert(elem_count == buf_len(buf));
6175 const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count);6525 const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count);
6176 for (size_t i = 0; i < elem_count; i += 1) {6526 for (size_t i = 0; i < elem_count; i += 1) {
...@@ -6178,6 +6528,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {...@@ -6178,6 +6528,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
6178 this_char->special = ConstValSpecialStatic;6528 this_char->special = ConstValSpecialStatic;
6179 this_char->type = g->builtin_types.entry_u8;6529 this_char->type = g->builtin_types.entry_u8;
6180 bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(buf)[i]);6530 bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(buf)[i]);
6531 this_char->parent.id = ConstParentIdArray;
6532 this_char->parent.data.p_array.array_val = const_val;
6533 this_char->parent.data.p_array.elem_index = i;
6181 }6534 }
6182 return;6535 return;
6183 }6536 }
...@@ -6185,18 +6538,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {...@@ -6185,18 +6538,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
6185 zig_unreachable();6538 zig_unreachable();
6186}6539}
61876540
6541// Deprecated. Reference the parent field directly.
6188ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {6542ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {
6189 assert(value->type);6543 return &value->parent;
6190 ZigType *type_entry = value->type;
6191 if (type_entry->id == ZigTypeIdArray) {
6192 expand_undef_array(g, value);
6193 return &value->data.x_array.data.s_none.parent;
6194 } else if (type_entry->id == ZigTypeIdStruct) {
6195 return &value->data.x_struct.parent;
6196 } else if (type_entry->id == ZigTypeIdUnion) {
6197 return &value->data.x_union.parent;
6198 }
6199 return nullptr;
6200}6544}
62016545
6202static const ZigTypeId all_type_ids[] = {6546static const ZigTypeId all_type_ids[] = {
...@@ -6224,6 +6568,7 @@ static const ZigTypeId all_type_ids[] = {...@@ -6224,6 +6568,7 @@ static const ZigTypeId all_type_ids[] = {
6224 ZigTypeIdArgTuple,6568 ZigTypeIdArgTuple,
6225 ZigTypeIdOpaque,6569 ZigTypeIdOpaque,
6226 ZigTypeIdPromise,6570 ZigTypeIdPromise,
6571 ZigTypeIdVector,
6227};6572};
62286573
6229ZigTypeId type_id_at_index(size_t index) {6574ZigTypeId type_id_at_index(size_t index) {
...@@ -6289,6 +6634,8 @@ size_t type_id_index(ZigType *entry) {...@@ -6289,6 +6634,8 @@ size_t type_id_index(ZigType *entry) {
6289 return 22;6634 return 22;
6290 case ZigTypeIdPromise:6635 case ZigTypeIdPromise:
6291 return 23;6636 return 23;
6637 case ZigTypeIdVector:
6638 return 24;
6292 }6639 }
6293 zig_unreachable();6640 zig_unreachable();
6294}6641}
...@@ -6345,6 +6692,8 @@ const char *type_id_name(ZigTypeId id) {...@@ -6345,6 +6692,8 @@ const char *type_id_name(ZigTypeId id) {
6345 return "Opaque";6692 return "Opaque";
6346 case ZigTypeIdPromise:6693 case ZigTypeIdPromise:
6347 return "Promise";6694 return "Promise";
6695 case ZigTypeIdVector:
6696 return "Vector";
6348 }6697 }
6349 zig_unreachable();6698 zig_unreachable();
6350}6699}
...@@ -6361,7 +6710,7 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {...@@ -6361,7 +6710,7 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {
6361 if (is_libc && g->libc_link_lib != nullptr)6710 if (is_libc && g->libc_link_lib != nullptr)
6362 return g->libc_link_lib;6711 return g->libc_link_lib;
63636712
6364 if (g->enable_cache && is_libc && g->zig_target.os != OsMacOSX && g->zig_target.os != OsIOS) {6713 if (g->enable_cache && is_libc && g->zig_target.os != OsMacOSX && g->zig_target.os != OsIOS && g->zig_target.os != OsFreeBSD) {
6365 fprintf(stderr, "TODO linking against libc is currently incompatible with `--cache on`.\n"6714 fprintf(stderr, "TODO linking against libc is currently incompatible with `--cache on`.\n"
6366 "Zig is not yet capable of determining whether the libc installation has changed on subsequent builds.\n");6715 "Zig is not yet capable of determining whether the libc installation has changed on subsequent builds.\n");
6367 exit(1);6716 exit(1);
...@@ -6424,7 +6773,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {...@@ -6424,7 +6773,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
6424 resolve_top_level_decl(codegen, tld, false, nullptr);6773 resolve_top_level_decl(codegen, tld, false, nullptr);
6425 assert(tld->id == TldIdVar);6774 assert(tld->id == TldIdVar);
6426 TldVar *tld_var = (TldVar *)tld;6775 TldVar *tld_var = (TldVar *)tld;
6427 ConstExprValue *var_value = tld_var->var->value;6776 ConstExprValue *var_value = tld_var->var->const_value;
6428 assert(var_value != nullptr);6777 assert(var_value != nullptr);
6429 return var_value;6778 return var_value;
6430}6779}
...@@ -6500,6 +6849,7 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {...@@ -6500,6 +6849,7 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {
6500 case ZigTypeIdBool:6849 case ZigTypeIdBool:
6501 return X64CABIClass_INTEGER;6850 return X64CABIClass_INTEGER;
6502 case ZigTypeIdFloat:6851 case ZigTypeIdFloat:
6852 case ZigTypeIdVector:
6503 return X64CABIClass_SSE;6853 return X64CABIClass_SSE;
6504 case ZigTypeIdStruct: {6854 case ZigTypeIdStruct: {
6505 // "If the size of an object is larger than four eightbytes, or it contains unaligned6855 // "If the size of an object is larger than four eightbytes, or it contains unaligned
...@@ -6579,3 +6929,36 @@ uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *f...@@ -6579,3 +6929,36 @@ uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *f
6579 LLVMTypeRef field_type = LLVMStructGetTypeAtIndex(struct_type->type_ref, field->gen_index);6929 LLVMTypeRef field_type = LLVMStructGetTypeAtIndex(struct_type->type_ref, field->gen_index);
6580 return LLVMStoreSizeOfType(g->target_data_ref, field_type);6930 return LLVMStoreSizeOfType(g->target_data_ref, field_type);
6581}6931}
6932
6933Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
6934 ConstExprValue *const_val, ZigType *wanted_type)
6935{
6936 ConstExprValue ptr_val = {};
6937 ptr_val.special = ConstValSpecialStatic;
6938 ptr_val.type = get_pointer_to_type(codegen, wanted_type, true);
6939 ptr_val.data.x_ptr.mut = ConstPtrMutComptimeConst;
6940 ptr_val.data.x_ptr.special = ConstPtrSpecialRef;
6941 ptr_val.data.x_ptr.data.ref.pointee = const_val;
6942 if (const_ptr_pointee(ira, codegen, &ptr_val, source_node) == nullptr)
6943 return ErrorSemanticAnalyzeFail;
6944
6945 return ErrorNone;
6946}
6947
6948const char *container_string(ContainerKind kind) {
6949 switch (kind) {
6950 case ContainerKindEnum: return "enum";
6951 case ContainerKindStruct: return "struct";
6952 case ContainerKindUnion: return "union";
6953 }
6954 zig_unreachable();
6955}
6956
6957bool ptr_allows_addr_zero(ZigType *ptr_type) {
6958 if (ptr_type->id == ZigTypeIdPointer) {
6959 return ptr_type->data.pointer.allow_zero;
6960 } else if (ptr_type->id == ZigTypeIdOptional) {
6961 return true;
6962 }
6963 return false;
6964}
src/analyze.hpp+20-2
...@@ -12,14 +12,17 @@...@@ -12,14 +12,17 @@
1212
13void semantic_analyze(CodeGen *g);13void semantic_analyze(CodeGen *g);
14ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);14ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);
15ErrorMsg *add_token_error(CodeGen *g, ImportTableEntry *owner, Token *token, Buf *msg);
15ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg);16ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg);
16ZigType *new_type_table_entry(ZigTypeId id);17ZigType *new_type_table_entry(ZigTypeId id);
17ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const);18ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const);
18ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,19ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
19 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count);20 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count);
20uint64_t type_size(CodeGen *g, ZigType *type_entry);21uint64_t type_size(CodeGen *g, ZigType *type_entry);
22uint64_t type_size_store(CodeGen *g, ZigType *type_entry);
21uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);23uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);
22ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);24ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
25ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type);
23ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);26ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
24ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type);27ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type);
25ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);28ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
...@@ -42,7 +45,9 @@ void find_libc_include_path(CodeGen *g);...@@ -42,7 +45,9 @@ void find_libc_include_path(CodeGen *g);
42void find_libc_lib_path(CodeGen *g);45void find_libc_lib_path(CodeGen *g);
4346
44bool type_has_bits(ZigType *type_entry);47bool type_has_bits(ZigType *type_entry);
4548bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry);
49bool ptr_allows_addr_zero(ZigType *ptr_type);
50bool type_is_nonnull_ptr(ZigType *type);
4651
47ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);52ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);
4853
...@@ -73,6 +78,7 @@ TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag);...@@ -73,6 +78,7 @@ TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag);
73bool is_ref(ZigType *type_entry);78bool is_ref(ZigType *type_entry);
74bool is_array_ref(ZigType *type_entry);79bool is_array_ref(ZigType *type_entry);
75bool is_container_ref(ZigType *type_entry);80bool is_container_ref(ZigType *type_entry);
81bool is_valid_vector_elem_type(ZigType *elem_type);
76void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);82void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
77void scan_import(CodeGen *g, ImportTableEntry *import);83void scan_import(CodeGen *g, ImportTableEntry *import);
78void preview_use_decl(CodeGen *g, AstNode *node);84void preview_use_decl(CodeGen *g, AstNode *node);
...@@ -81,7 +87,7 @@ ZigFn *scope_fn_entry(Scope *scope);...@@ -81,7 +87,7 @@ ZigFn *scope_fn_entry(Scope *scope);
81ImportTableEntry *get_scope_import(Scope *scope);87ImportTableEntry *get_scope_import(Scope *scope);
82void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope);88void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope);
83ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,89ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
84 bool is_const, ConstExprValue *init_value, Tld *src_tld);90 bool is_const, ConstExprValue *init_value, Tld *src_tld, ZigType *var_type);
85ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);91ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);
86ZigFn *create_fn(CodeGen *g, AstNode *proto_node);92ZigFn *create_fn(CodeGen *g, AstNode *proto_node);
87ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);93ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);
...@@ -212,6 +218,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);...@@ -212,6 +218,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);
212X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);218X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);
213bool type_is_c_abi_int(CodeGen *g, ZigType *ty);219bool type_is_c_abi_int(CodeGen *g, ZigType *ty);
214bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);220bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);
221const char *container_string(ContainerKind kind);
215222
216uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field);223uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field);
217224
...@@ -222,4 +229,15 @@ enum ReqCompTime {...@@ -222,4 +229,15 @@ enum ReqCompTime {
222};229};
223ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry);230ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry);
224231
232enum OnePossibleValue {
233 OnePossibleValueInvalid,
234 OnePossibleValueNo,
235 OnePossibleValueYes,
236};
237OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry);
238
239Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
240 ConstExprValue *const_val, ZigType *wanted_type);
241
242void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn);
225#endif243#endif
src/ast_render.cpp+24-18
...@@ -132,13 +132,23 @@ static const char *const_or_var_string(bool is_const) {...@@ -132,13 +132,23 @@ static const char *const_or_var_string(bool is_const) {
132 return is_const ? "const" : "var";132 return is_const ? "const" : "var";
133}133}
134134
135const char *container_string(ContainerKind kind) {135static const char *thread_local_string(Token *tok) {
136 switch (kind) {136 return (tok == nullptr) ? "" : "threadlocal ";
137 case ContainerKindEnum: return "enum";137}
138 case ContainerKindStruct: return "struct";138
139 case ContainerKindUnion: return "union";139static const char *token_to_ptr_len_str(Token *tok) {
140 assert(tok != nullptr);
141 switch (tok->id) {
142 case TokenIdStar:
143 case TokenIdStarStar:
144 return "*";
145 case TokenIdBracketStarBracket:
146 return "[*]";
147 case TokenIdBracketStarCBracket:
148 return "[*c]";
149 default:
150 zig_unreachable();
140 }151 }
141 zig_unreachable();
142}152}
143153
144static const char *node_type_str(NodeType node_type) {154static const char *node_type_str(NodeType node_type) {
...@@ -233,8 +243,8 @@ static const char *node_type_str(NodeType node_type) {...@@ -233,8 +243,8 @@ static const char *node_type_str(NodeType node_type) {
233 return "ErrorType";243 return "ErrorType";
234 case NodeTypeIfErrorExpr:244 case NodeTypeIfErrorExpr:
235 return "IfErrorExpr";245 return "IfErrorExpr";
236 case NodeTypeTestExpr:246 case NodeTypeIfOptional:
237 return "TestExpr";247 return "IfOptional";
238 case NodeTypeErrorSetDecl:248 case NodeTypeErrorSetDecl:
239 return "ErrorSetDecl";249 return "ErrorSetDecl";
240 case NodeTypeCancel:250 case NodeTypeCancel:
...@@ -387,7 +397,7 @@ static bool statement_terminates_without_semicolon(AstNode *node) {...@@ -387,7 +397,7 @@ static bool statement_terminates_without_semicolon(AstNode *node) {
387 if (node->data.if_err_expr.else_node)397 if (node->data.if_err_expr.else_node)
388 return statement_terminates_without_semicolon(node->data.if_err_expr.else_node);398 return statement_terminates_without_semicolon(node->data.if_err_expr.else_node);
389 return node->data.if_err_expr.then_node->type == NodeTypeBlock;399 return node->data.if_err_expr.then_node->type == NodeTypeBlock;
390 case NodeTypeTestExpr:400 case NodeTypeIfOptional:
391 if (node->data.test_expr.else_node)401 if (node->data.test_expr.else_node)
392 return statement_terminates_without_semicolon(node->data.test_expr.else_node);402 return statement_terminates_without_semicolon(node->data.test_expr.else_node);
393 return node->data.test_expr.then_node->type == NodeTypeBlock;403 return node->data.test_expr.then_node->type == NodeTypeBlock;
...@@ -554,8 +564,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -554,8 +564,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
554 {564 {
555 const char *pub_str = visib_mod_string(node->data.variable_declaration.visib_mod);565 const char *pub_str = visib_mod_string(node->data.variable_declaration.visib_mod);
556 const char *extern_str = extern_string(node->data.variable_declaration.is_extern);566 const char *extern_str = extern_string(node->data.variable_declaration.is_extern);
567 const char *thread_local_str = thread_local_string(node->data.variable_declaration.threadlocal_tok);
557 const char *const_or_var = const_or_var_string(node->data.variable_declaration.is_const);568 const char *const_or_var = const_or_var_string(node->data.variable_declaration.is_const);
558 fprintf(ar->f, "%s%s%s ", pub_str, extern_str, const_or_var);569 fprintf(ar->f, "%s%s%s%s ", pub_str, extern_str, thread_local_str, const_or_var);
559 print_symbol(ar, node->data.variable_declaration.symbol);570 print_symbol(ar, node->data.variable_declaration.symbol);
560571
561 if (node->data.variable_declaration.type) {572 if (node->data.variable_declaration.type) {
...@@ -639,13 +650,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -639,13 +650,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
639 case NodeTypePointerType:650 case NodeTypePointerType:
640 {651 {
641 if (!grouped) fprintf(ar->f, "(");652 if (!grouped) fprintf(ar->f, "(");
642 const char *star = "[*]";653 const char *ptr_len_str = token_to_ptr_len_str(node->data.pointer_type.star_token);
643 if (node->data.pointer_type.star_token != nullptr &&654 fprintf(ar->f, "%s", ptr_len_str);
644 (node->data.pointer_type.star_token->id == TokenIdStar || node->data.pointer_type.star_token->id == TokenIdStarStar))
645 {
646 star = "*";
647 }
648 fprintf(ar->f, "%s", star);
649 if (node->data.pointer_type.align_expr != nullptr) {655 if (node->data.pointer_type.align_expr != nullptr) {
650 fprintf(ar->f, "align(");656 fprintf(ar->f, "align(");
651 render_node_grouped(ar, node->data.pointer_type.align_expr);657 render_node_grouped(ar, node->data.pointer_type.align_expr);
...@@ -974,7 +980,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -974,7 +980,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
974 }980 }
975 break;981 break;
976 }982 }
977 case NodeTypeTestExpr:983 case NodeTypeIfOptional:
978 {984 {
979 fprintf(ar->f, "if (");985 fprintf(ar->f, "if (");
980 render_node_grouped(ar, node->data.test_expr.target_node);986 render_node_grouped(ar, node->data.test_expr.target_node);
src/ast_render.hpp-3
...@@ -17,7 +17,4 @@ void ast_print(FILE *f, AstNode *node, int indent);...@@ -17,7 +17,4 @@ void ast_print(FILE *f, AstNode *node, int indent);
1717
18void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size);18void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size);
1919
20const char *container_string(ContainerKind kind);
21
22#endif20#endif
23
src/bigint.cpp+1
...@@ -1722,3 +1722,4 @@ void bigint_incr(BigInt *x) {...@@ -1722,3 +1722,4 @@ void bigint_incr(BigInt *x) {
17221722
1723 bigint_add(x, &copy, &one);1723 bigint_add(x, &copy, &one);
1724}1724}
1725
src/cache_hash.cpp+3-13
...@@ -222,14 +222,9 @@ static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf, Buf *contents...@@ -222,14 +222,9 @@ static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf, Buf *contents
222 assert(chf->path != nullptr);222 assert(chf->path != nullptr);
223223
224 OsFile this_file;224 OsFile this_file;
225 if ((err = os_file_open_r(chf->path, &this_file)))225 if ((err = os_file_open_r(chf->path, &this_file, &chf->mtime)))
226 return err;226 return err;
227227
228 if ((err = os_file_mtime(this_file, &chf->mtime))) {
229 os_file_close(this_file);
230 return err;
231 }
232
233 if ((err = hash_file(chf->bin_digest, this_file, contents))) {228 if ((err = hash_file(chf->bin_digest, this_file, contents))) {
234 os_file_close(this_file);229 os_file_close(this_file);
235 return err;230 return err;
...@@ -351,17 +346,12 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {...@@ -351,17 +346,12 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
351346
352 // if the mtime matches we can trust the digest347 // if the mtime matches we can trust the digest
353 OsFile this_file;348 OsFile this_file;
354 if ((err = os_file_open_r(chf->path, &this_file))) {349 OsTimeStamp actual_mtime;
350 if ((err = os_file_open_r(chf->path, &this_file, &actual_mtime))) {
355 fprintf(stderr, "Unable to open %s\n: %s", buf_ptr(chf->path), err_str(err));351 fprintf(stderr, "Unable to open %s\n: %s", buf_ptr(chf->path), err_str(err));
356 os_file_close(ch->manifest_file);352 os_file_close(ch->manifest_file);
357 return ErrorCacheUnavailable;353 return ErrorCacheUnavailable;
358 }354 }
359 OsTimeStamp actual_mtime;
360 if ((err = os_file_mtime(this_file, &actual_mtime))) {
361 os_file_close(this_file);
362 os_file_close(ch->manifest_file);
363 return err;
364 }
365 if (chf->mtime.sec == actual_mtime.sec && chf->mtime.nsec == actual_mtime.nsec) {355 if (chf->mtime.sec == actual_mtime.sec && chf->mtime.nsec == actual_mtime.nsec) {
366 os_file_close(this_file);356 os_file_close(this_file);
367 } else {357 } else {
src/codegen.cpp+686-296
...@@ -88,7 +88,7 @@ static const char *symbols_that_llvm_depends_on[] = {...@@ -88,7 +88,7 @@ static const char *symbols_that_llvm_depends_on[] = {
88};88};
8989
90CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,90CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,
91 Buf *zig_lib_dir)91 Buf *zig_lib_dir, Buf *override_std_dir)
92{92{
93 CodeGen *g = allocate<CodeGen>(1);93 CodeGen *g = allocate<CodeGen>(1);
9494
...@@ -96,8 +96,12 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out...@@ -96,8 +96,12 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
9696
97 g->zig_lib_dir = zig_lib_dir;97 g->zig_lib_dir = zig_lib_dir;
9898
99 g->zig_std_dir = buf_alloc();99 if (override_std_dir == nullptr) {
100 os_path_join(zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir);100 g->zig_std_dir = buf_alloc();
101 os_path_join(zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir);
102 } else {
103 g->zig_std_dir = override_std_dir;
104 }
101105
102 g->zig_c_headers_dir = buf_alloc();106 g->zig_c_headers_dir = buf_alloc();
103 os_path_join(zig_lib_dir, buf_create_from_str("include"), g->zig_c_headers_dir);107 os_path_join(zig_lib_dir, buf_create_from_str("include"), g->zig_c_headers_dir);
...@@ -118,6 +122,7 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out...@@ -118,6 +122,7 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
118 g->string_literals_table.init(16);122 g->string_literals_table.init(16);
119 g->type_info_cache.init(32);123 g->type_info_cache.init(32);
120 g->is_test_build = false;124 g->is_test_build = false;
125 g->is_single_threaded = false;
121 buf_resize(&g->global_asm, 0);126 buf_resize(&g->global_asm, 0);
122127
123 for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) {128 for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) {
...@@ -178,7 +183,8 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out...@@ -178,7 +183,8 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
178183
179 // On Darwin/MacOS/iOS, we always link libSystem which contains libc.184 // On Darwin/MacOS/iOS, we always link libSystem which contains libc.
180 if (g->zig_target.os == OsMacOSX ||185 if (g->zig_target.os == OsMacOSX ||
181 g->zig_target.os == OsIOS)186 g->zig_target.os == OsIOS ||
187 g->zig_target.os == OsFreeBSD)
182 {188 {
183 g->libc_link_lib = create_link_lib(buf_create_from_str("c"));189 g->libc_link_lib = create_link_lib(buf_create_from_str("c"));
184 g->link_libs_list.append(g->libc_link_lib);190 g->link_libs_list.append(g->libc_link_lib);
...@@ -291,11 +297,6 @@ void codegen_add_framework(CodeGen *g, const char *framework) {...@@ -291,11 +297,6 @@ void codegen_add_framework(CodeGen *g, const char *framework) {
291 g->darwin_frameworks.append(buf_create_from_str(framework));297 g->darwin_frameworks.append(buf_create_from_str(framework));
292}298}
293299
294void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole) {
295 g->windows_subsystem_windows = mwindows;
296 g->windows_subsystem_console = mconsole;
297}
298
299void codegen_set_mmacosx_version_min(CodeGen *g, Buf *mmacosx_version_min) {300void codegen_set_mmacosx_version_min(CodeGen *g, Buf *mmacosx_version_min) {
300 g->mmacosx_version_min = mmacosx_version_min;301 g->mmacosx_version_min = mmacosx_version_min;
301}302}
...@@ -317,6 +318,8 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val, const char *...@@ -317,6 +318,8 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val, const char *
317static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name);318static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name);
318static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name);319static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name);
319static void generate_error_name_table(CodeGen *g);320static void generate_error_name_table(CodeGen *g);
321static bool value_is_all_undef(ConstExprValue *const_val);
322static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr);
320323
321static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) {324static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) {
322 unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));325 unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));
...@@ -465,6 +468,21 @@ static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkag...@@ -465,6 +468,21 @@ static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkag
465 }468 }
466}469}
467470
471static bool cc_want_sret_attr(CallingConvention cc) {
472 switch (cc) {
473 case CallingConventionNaked:
474 zig_unreachable();
475 case CallingConventionC:
476 case CallingConventionCold:
477 case CallingConventionStdcall:
478 return true;
479 case CallingConventionAsync:
480 case CallingConventionUnspecified:
481 return false;
482 }
483 zig_unreachable();
484}
485
468static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {486static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
469 if (fn_table_entry->llvm_value)487 if (fn_table_entry->llvm_value)
470 return fn_table_entry->llvm_value;488 return fn_table_entry->llvm_value;
...@@ -599,12 +617,13 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {...@@ -599,12 +617,13 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
599 unsigned init_gen_i = 0;617 unsigned init_gen_i = 0;
600 if (!type_has_bits(return_type)) {618 if (!type_has_bits(return_type)) {
601 // nothing to do619 // nothing to do
602 } else if (type_is_codegen_pointer(return_type)) {620 } else if (type_is_nonnull_ptr(return_type)) {
603 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");621 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
604 } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {622 } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {
605 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");623 // Sret pointers must not be address 0
606 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");624 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");
607 if (cc == CallingConventionC) {625 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
626 if (cc_want_sret_attr(cc)) {
608 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias");627 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias");
609 }628 }
610 init_gen_i = 1;629 init_gen_i = 1;
...@@ -619,6 +638,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {...@@ -619,6 +638,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
619638
620 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);639 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
621 if (err_ret_trace_arg_index != UINT32_MAX) {640 if (err_ret_trace_arg_index != UINT32_MAX) {
641 // Error return trace memory is in the stack, which is impossible to be at address 0
642 // on any architecture.
622 addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull");643 addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull");
623 }644 }
624645
...@@ -653,7 +674,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {...@@ -653,7 +674,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
653 ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder,674 ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder,
654 fn_di_scope, buf_ptr(&fn_table_entry->symbol_name), "",675 fn_di_scope, buf_ptr(&fn_table_entry->symbol_name), "",
655 import->di_file, line_number,676 import->di_file, line_number,
656 fn_table_entry->type_entry->di_type, is_internal_linkage,677 fn_table_entry->type_entry->data.fn.raw_di_type, is_internal_linkage,
657 is_definition, scope_line, flags, is_optimized, nullptr);678 is_definition, scope_line, flags, is_optimized, nullptr);
658679
659 scope->di_scope = ZigLLVMSubprogramToScope(subprogram);680 scope->di_scope = ZigLLVMSubprogramToScope(subprogram);
...@@ -697,38 +718,59 @@ static void clear_debug_source_node(CodeGen *g) {...@@ -697,38 +718,59 @@ static void clear_debug_source_node(CodeGen *g) {
697 ZigLLVMClearCurrentDebugLocation(g->builder);718 ZigLLVMClearCurrentDebugLocation(g->builder);
698}719}
699720
700static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, ZigType *type_entry,721static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, ZigType *operand_type,
701 const char *signed_name, const char *unsigned_name)722 const char *signed_name, const char *unsigned_name)
702{723{
724 ZigType *int_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
703 char fn_name[64];725 char fn_name[64];
704726
705 assert(type_entry->id == ZigTypeIdInt);727 assert(int_type->id == ZigTypeIdInt);
706 const char *signed_str = type_entry->data.integral.is_signed ? signed_name : unsigned_name;728 const char *signed_str = int_type->data.integral.is_signed ? signed_name : unsigned_name;
707 sprintf(fn_name, "llvm.%s.with.overflow.i%" PRIu32, signed_str, type_entry->data.integral.bit_count);
708729
709 LLVMTypeRef return_elem_types[] = {
710 type_entry->type_ref,
711 LLVMInt1Type(),
712 };
713 LLVMTypeRef param_types[] = {730 LLVMTypeRef param_types[] = {
714 type_entry->type_ref,731 operand_type->type_ref,
715 type_entry->type_ref,732 operand_type->type_ref,
716 };733 };
717 LLVMTypeRef return_struct_type = LLVMStructType(return_elem_types, 2, false);734
718 LLVMTypeRef fn_type = LLVMFunctionType(return_struct_type, param_types, 2, false);735 if (operand_type->id == ZigTypeIdVector) {
719 LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type);736 sprintf(fn_name, "llvm.%s.with.overflow.v%" PRIu32 "i%" PRIu32, signed_str,
720 assert(LLVMGetIntrinsicID(fn_val));737 operand_type->data.vector.len, int_type->data.integral.bit_count);
721 return fn_val;738
739 LLVMTypeRef return_elem_types[] = {
740 operand_type->type_ref,
741 LLVMVectorType(LLVMInt1Type(), operand_type->data.vector.len),
742 };
743 LLVMTypeRef return_struct_type = LLVMStructType(return_elem_types, 2, false);
744 LLVMTypeRef fn_type = LLVMFunctionType(return_struct_type, param_types, 2, false);
745 LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type);
746 assert(LLVMGetIntrinsicID(fn_val));
747 return fn_val;
748 } else {
749 sprintf(fn_name, "llvm.%s.with.overflow.i%" PRIu32, signed_str, int_type->data.integral.bit_count);
750
751 LLVMTypeRef return_elem_types[] = {
752 operand_type->type_ref,
753 LLVMInt1Type(),
754 };
755 LLVMTypeRef return_struct_type = LLVMStructType(return_elem_types, 2, false);
756 LLVMTypeRef fn_type = LLVMFunctionType(return_struct_type, param_types, 2, false);
757 LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type);
758 assert(LLVMGetIntrinsicID(fn_val));
759 return fn_val;
760 }
722}761}
723762
724static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *type_entry, AddSubMul add_sub_mul) {763static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *operand_type, AddSubMul add_sub_mul) {
725 assert(type_entry->id == ZigTypeIdInt);764 ZigType *int_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
765 assert(int_type->id == ZigTypeIdInt);
726766
727 ZigLLVMFnKey key = {};767 ZigLLVMFnKey key = {};
728 key.id = ZigLLVMFnIdOverflowArithmetic;768 key.id = ZigLLVMFnIdOverflowArithmetic;
729 key.data.overflow_arithmetic.is_signed = type_entry->data.integral.is_signed;769 key.data.overflow_arithmetic.is_signed = int_type->data.integral.is_signed;
730 key.data.overflow_arithmetic.add_sub_mul = add_sub_mul;770 key.data.overflow_arithmetic.add_sub_mul = add_sub_mul;
731 key.data.overflow_arithmetic.bit_count = (uint32_t)type_entry->data.integral.bit_count;771 key.data.overflow_arithmetic.bit_count = (uint32_t)int_type->data.integral.bit_count;
772 key.data.overflow_arithmetic.vector_len = (operand_type->id == ZigTypeIdVector) ?
773 operand_type->data.vector.len : 0;
732774
733 auto existing_entry = g->llvm_fn_table.maybe_get(key);775 auto existing_entry = g->llvm_fn_table.maybe_get(key);
734 if (existing_entry)776 if (existing_entry)
...@@ -737,13 +779,13 @@ static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *type_entry, AddSubM...@@ -737,13 +779,13 @@ static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *type_entry, AddSubM
737 LLVMValueRef fn_val;779 LLVMValueRef fn_val;
738 switch (add_sub_mul) {780 switch (add_sub_mul) {
739 case AddSubMulAdd:781 case AddSubMulAdd:
740 fn_val = get_arithmetic_overflow_fn(g, type_entry, "sadd", "uadd");782 fn_val = get_arithmetic_overflow_fn(g, operand_type, "sadd", "uadd");
741 break;783 break;
742 case AddSubMulSub:784 case AddSubMulSub:
743 fn_val = get_arithmetic_overflow_fn(g, type_entry, "ssub", "usub");785 fn_val = get_arithmetic_overflow_fn(g, operand_type, "ssub", "usub");
744 break;786 break;
745 case AddSubMulMul:787 case AddSubMulMul:
746 fn_val = get_arithmetic_overflow_fn(g, type_entry, "smul", "umul");788 fn_val = get_arithmetic_overflow_fn(g, operand_type, "smul", "umul");
747 break;789 break;
748 }790 }
749791
...@@ -911,6 +953,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {...@@ -911,6 +953,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
911 return buf_create_from_str("invalid enum value");953 return buf_create_from_str("invalid enum value");
912 case PanicMsgIdFloatToInt:954 case PanicMsgIdFloatToInt:
913 return buf_create_from_str("integer part of floating point value out of bounds");955 return buf_create_from_str("integer part of floating point value out of bounds");
956 case PanicMsgIdPtrCastNull:
957 return buf_create_from_str("cast causes pointer to be null");
914 }958 }
915 zig_unreachable();959 zig_unreachable();
916}960}
...@@ -1205,6 +1249,8 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {...@@ -1205,6 +1249,8 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {
1205 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));1249 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
1206 addLLVMFnAttr(fn_val, "nounwind");1250 addLLVMFnAttr(fn_val, "nounwind");
1207 add_uwtable_attr(g, fn_val);1251 add_uwtable_attr(g, fn_val);
1252 // Error return trace memory is in the stack, which is impossible to be at address 0
1253 // on any architecture.
1208 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");1254 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
1209 if (g->build_mode == BuildModeDebug) {1255 if (g->build_mode == BuildModeDebug) {
1210 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");1256 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");
...@@ -1279,9 +1325,13 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {...@@ -1279,9 +1325,13 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
1279 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));1325 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
1280 addLLVMFnAttr(fn_val, "nounwind");1326 addLLVMFnAttr(fn_val, "nounwind");
1281 add_uwtable_attr(g, fn_val);1327 add_uwtable_attr(g, fn_val);
1328 // Error return trace memory is in the stack, which is impossible to be at address 0
1329 // on any architecture.
1282 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");1330 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
1283 addLLVMArgAttr(fn_val, (unsigned)0, "noalias");1331 addLLVMArgAttr(fn_val, (unsigned)0, "noalias");
1284 addLLVMArgAttr(fn_val, (unsigned)0, "writeonly");1332 addLLVMArgAttr(fn_val, (unsigned)0, "writeonly");
1333 // Error return trace memory is in the stack, which is impossible to be at address 0
1334 // on any architecture.
1285 addLLVMArgAttr(fn_val, (unsigned)1, "nonnull");1335 addLLVMArgAttr(fn_val, (unsigned)1, "nonnull");
1286 addLLVMArgAttr(fn_val, (unsigned)1, "noalias");1336 addLLVMArgAttr(fn_val, (unsigned)1, "noalias");
1287 addLLVMArgAttr(fn_val, (unsigned)1, "readonly");1337 addLLVMArgAttr(fn_val, (unsigned)1, "readonly");
...@@ -1409,6 +1459,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {...@@ -1409,6 +1459,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
1409 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));1459 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
1410 addLLVMFnAttr(fn_val, "nounwind");1460 addLLVMFnAttr(fn_val, "nounwind");
1411 add_uwtable_attr(g, fn_val);1461 add_uwtable_attr(g, fn_val);
1462 // Error return trace memory is in the stack, which is impossible to be at address 0
1463 // on any architecture.
1412 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");1464 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
1413 if (g->build_mode == BuildModeDebug) {1465 if (g->build_mode == BuildModeDebug) {
1414 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");1466 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");
...@@ -1633,10 +1685,25 @@ static void add_bounds_check(CodeGen *g, LLVMValueRef target_val,...@@ -1633,10 +1685,25 @@ static void add_bounds_check(CodeGen *g, LLVMValueRef target_val,
1633 LLVMPositionBuilderAtEnd(g->builder, ok_block);1685 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1634}1686}
16351687
1688static LLVMValueRef gen_assert_zero(CodeGen *g, LLVMValueRef expr_val, ZigType *int_type) {
1689 LLVMValueRef zero = LLVMConstNull(int_type->type_ref);
1690 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, expr_val, zero, "");
1691 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenOk");
1692 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenFail");
1693 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
1694
1695 LLVMPositionBuilderAtEnd(g->builder, fail_block);
1696 gen_safety_crash(g, PanicMsgIdCastTruncatedData);
1697
1698 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1699 return nullptr;
1700}
1701
1636static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, ZigType *actual_type,1702static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, ZigType *actual_type,
1637 ZigType *wanted_type, LLVMValueRef expr_val)1703 ZigType *wanted_type, LLVMValueRef expr_val)
1638{1704{
1639 assert(actual_type->id == wanted_type->id);1705 assert(actual_type->id == wanted_type->id);
1706 assert(expr_val != nullptr);
16401707
1641 uint64_t actual_bits;1708 uint64_t actual_bits;
1642 uint64_t wanted_bits;1709 uint64_t wanted_bits;
...@@ -1689,17 +1756,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z...@@ -1689,17 +1756,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
1689 if (!want_runtime_safety)1756 if (!want_runtime_safety)
1690 return nullptr;1757 return nullptr;
16911758
1692 LLVMValueRef zero = LLVMConstNull(actual_type->type_ref);1759 return gen_assert_zero(g, expr_val, actual_type);
1693 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, expr_val, zero, "");
1694 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenOk");
1695 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenFail");
1696 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
1697
1698 LLVMPositionBuilderAtEnd(g->builder, fail_block);
1699 gen_safety_crash(g, PanicMsgIdCastTruncatedData);
1700
1701 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1702 return nullptr;
1703 }1760 }
1704 LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");1761 LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
1705 if (!want_runtime_safety) {1762 if (!want_runtime_safety) {
...@@ -1729,17 +1786,49 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z...@@ -1729,17 +1786,49 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
1729 }1786 }
1730}1787}
17311788
1732static LLVMValueRef gen_overflow_op(CodeGen *g, ZigType *type_entry, AddSubMul op,1789typedef LLVMValueRef (*BuildBinOpFunc)(LLVMBuilderRef, LLVMValueRef, LLVMValueRef, const char *);
1790// These are lookup table using the AddSubMul enum as the lookup.
1791// If AddSubMul ever changes, then these tables will be out of
1792// date.
1793static const BuildBinOpFunc float_op[3] = { LLVMBuildFAdd, LLVMBuildFSub, LLVMBuildFMul };
1794static const BuildBinOpFunc wrap_op[3] = { LLVMBuildAdd, LLVMBuildSub, LLVMBuildMul };
1795static const BuildBinOpFunc signed_op[3] = { LLVMBuildNSWAdd, LLVMBuildNSWSub, LLVMBuildNSWMul };
1796static const BuildBinOpFunc unsigned_op[3] = { LLVMBuildNUWAdd, LLVMBuildNUWSub, LLVMBuildNUWMul };
1797
1798static LLVMValueRef gen_overflow_op(CodeGen *g, ZigType *operand_type, AddSubMul op,
1733 LLVMValueRef val1, LLVMValueRef val2)1799 LLVMValueRef val1, LLVMValueRef val2)
1734{1800{
1735 LLVMValueRef fn_val = get_int_overflow_fn(g, type_entry, op);1801 LLVMValueRef overflow_bit;
1736 LLVMValueRef params[] = {1802 LLVMValueRef result;
1737 val1,1803
1738 val2,1804 if (operand_type->id == ZigTypeIdVector) {
1739 };1805 ZigType *int_type = operand_type->data.vector.elem_type;
1740 LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, "");1806 assert(int_type->id == ZigTypeIdInt);
1741 LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");1807 LLVMTypeRef one_more_bit_int = LLVMIntType(int_type->data.integral.bit_count + 1);
1742 LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");1808 LLVMTypeRef one_more_bit_int_vector = LLVMVectorType(one_more_bit_int, operand_type->data.vector.len);
1809 const auto buildExtFn = int_type->data.integral.is_signed ? LLVMBuildSExt : LLVMBuildZExt;
1810 LLVMValueRef extended1 = buildExtFn(g->builder, val1, one_more_bit_int_vector, "");
1811 LLVMValueRef extended2 = buildExtFn(g->builder, val2, one_more_bit_int_vector, "");
1812 LLVMValueRef extended_result = wrap_op[op](g->builder, extended1, extended2, "");
1813 result = LLVMBuildTrunc(g->builder, extended_result, operand_type->type_ref, "");
1814
1815 LLVMValueRef re_extended_result = buildExtFn(g->builder, result, one_more_bit_int_vector, "");
1816 LLVMValueRef overflow_vector = LLVMBuildICmp(g->builder, LLVMIntNE, extended_result, re_extended_result, "");
1817 LLVMTypeRef bitcast_int_type = LLVMIntType(operand_type->data.vector.len);
1818 LLVMValueRef bitcasted_overflow = LLVMBuildBitCast(g->builder, overflow_vector, bitcast_int_type, "");
1819 LLVMValueRef zero = LLVMConstNull(bitcast_int_type);
1820 overflow_bit = LLVMBuildICmp(g->builder, LLVMIntNE, bitcasted_overflow, zero, "");
1821 } else {
1822 LLVMValueRef fn_val = get_int_overflow_fn(g, operand_type, op);
1823 LLVMValueRef params[] = {
1824 val1,
1825 val2,
1826 };
1827 LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, "");
1828 result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");
1829 overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");
1830 }
1831
1743 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowFail");1832 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowFail");
1744 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowOk");1833 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowOk");
1745 LLVMBuildCondBr(g->builder, overflow_bit, fail_block, ok_block);1834 LLVMBuildCondBr(g->builder, overflow_bit, fail_block, ok_block);
...@@ -1907,9 +1996,8 @@ static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) {...@@ -1907,9 +1996,8 @@ static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) {
1907}1996}
19081997
1909static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) {1998static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) {
1910 assert(alignment > 0);
1911 LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name);1999 LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name);
1912 LLVMSetAlignment(result, alignment);2000 LLVMSetAlignment(result, (alignment == 0) ? get_abi_alignment(g, type_entry) : alignment);
1913 return result;2001 return result;
1914}2002}
19152003
...@@ -1967,14 +2055,14 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_...@@ -1967,14 +2055,14 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
1967 break;2055 break;
1968 }2056 }
19692057
1970 if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat ||2058 if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat || ty->id == ZigTypeIdVector ||
1971 ty->id == ZigTypeIdInt // TODO investigate if we need to change this2059 ty->id == ZigTypeIdInt // TODO investigate if we need to change this
1972 ) {2060 ) {
1973 switch (fn_walk->id) {2061 switch (fn_walk->id) {
1974 case FnWalkIdAttrs: {2062 case FnWalkIdAttrs: {
1975 ZigType *ptr_type = get_codegen_ptr_type(ty);2063 ZigType *ptr_type = get_codegen_ptr_type(ty);
1976 if (ptr_type != nullptr) {2064 if (ptr_type != nullptr) {
1977 if (ty->id != ZigTypeIdOptional) {2065 if (type_is_nonnull_ptr(ty)) {
1978 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");2066 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
1979 }2067 }
1980 if (ptr_type->data.pointer.is_const) {2068 if (ptr_type->data.pointer.is_const) {
...@@ -2018,6 +2106,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_...@@ -2018,6 +2106,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
2018 assert(handle_is_ptr(ty));2106 assert(handle_is_ptr(ty));
2019 switch (fn_walk->id) {2107 switch (fn_walk->id) {
2020 case FnWalkIdAttrs:2108 case FnWalkIdAttrs:
2109 // arrays passed to C ABI functions may not be at address 0
2021 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");2110 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
2022 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));2111 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
2023 fn_walk->data.attrs.gen_i += 1;2112 fn_walk->data.attrs.gen_i += 1;
...@@ -2057,6 +2146,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_...@@ -2057,6 +2146,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
2057 case FnWalkIdAttrs:2146 case FnWalkIdAttrs:
2058 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "byval");2147 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "byval");
2059 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));2148 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
2149 // Byvalue parameters must not have address 0
2060 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");2150 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
2061 fn_walk->data.attrs.gen_i += 1;2151 fn_walk->data.attrs.gen_i += 1;
2062 break;2152 break;
...@@ -2189,7 +2279,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {...@@ -2189,7 +2279,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
2189 if ((param_type->id == ZigTypeIdPointer && param_type->data.pointer.is_const) || is_byval) {2279 if ((param_type->id == ZigTypeIdPointer && param_type->data.pointer.is_const) || is_byval) {
2190 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "readonly");2280 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "readonly");
2191 }2281 }
2192 if (param_type->id == ZigTypeIdPointer) {2282 if (type_is_nonnull_ptr(param_type)) {
2193 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "nonnull");2283 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "nonnull");
2194 }2284 }
2195 break;2285 break;
...@@ -2204,10 +2294,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {...@@ -2204,10 +2294,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
2204 assert(variable);2294 assert(variable);
2205 assert(variable->value_ref);2295 assert(variable->value_ref);
22062296
2207 if (!handle_is_ptr(variable->value->type)) {2297 if (!handle_is_ptr(variable->var_type)) {
2208 clear_debug_source_node(g);2298 clear_debug_source_node(g);
2209 gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index), variable->value_ref,2299 gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index),
2210 variable->align_bytes, false);2300 variable->value_ref, variable->align_bytes, false);
2211 }2301 }
22122302
2213 if (variable->decl_node) {2303 if (variable->decl_node) {
...@@ -2582,9 +2672,10 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,...@@ -2582,9 +2672,10 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
2582 (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) ||2672 (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) ||
2583 (op1->value.type->id == ZigTypeIdPointer &&2673 (op1->value.type->id == ZigTypeIdPointer &&
2584 (op_id == IrBinOpAdd || op_id == IrBinOpSub) &&2674 (op_id == IrBinOpAdd || op_id == IrBinOpSub) &&
2585 op1->value.type->data.pointer.ptr_len == PtrLenUnknown)2675 op1->value.type->data.pointer.ptr_len != PtrLenSingle)
2586 );2676 );
2587 ZigType *type_entry = op1->value.type;2677 ZigType *operand_type = op1->value.type;
2678 ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
25882679
2589 bool want_runtime_safety = bin_op_instruction->safety_check_on &&2680 bool want_runtime_safety = bin_op_instruction->safety_check_on &&
2590 ir_want_runtime_safety(g, &bin_op_instruction->base);2681 ir_want_runtime_safety(g, &bin_op_instruction->base);
...@@ -2610,46 +2701,71 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,...@@ -2610,46 +2701,71 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
2610 case IrBinOpCmpGreaterThan:2701 case IrBinOpCmpGreaterThan:
2611 case IrBinOpCmpLessOrEq:2702 case IrBinOpCmpLessOrEq:
2612 case IrBinOpCmpGreaterOrEq:2703 case IrBinOpCmpGreaterOrEq:
2613 if (type_entry->id == ZigTypeIdFloat) {2704 if (scalar_type->id == ZigTypeIdFloat) {
2614 ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));2705 ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
2615 LLVMRealPredicate pred = cmp_op_to_real_predicate(op_id);2706 LLVMRealPredicate pred = cmp_op_to_real_predicate(op_id);
2616 return LLVMBuildFCmp(g->builder, pred, op1_value, op2_value, "");2707 return LLVMBuildFCmp(g->builder, pred, op1_value, op2_value, "");
2617 } else if (type_entry->id == ZigTypeIdInt) {2708 } else if (scalar_type->id == ZigTypeIdInt) {
2618 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, type_entry->data.integral.is_signed);2709 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, scalar_type->data.integral.is_signed);
2619 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");2710 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
2620 } else if (type_entry->id == ZigTypeIdEnum ||2711 } else if (scalar_type->id == ZigTypeIdEnum ||
2621 type_entry->id == ZigTypeIdErrorSet ||2712 scalar_type->id == ZigTypeIdErrorSet ||
2622 type_entry->id == ZigTypeIdBool ||2713 scalar_type->id == ZigTypeIdBool ||
2623 get_codegen_ptr_type(type_entry) != nullptr)2714 get_codegen_ptr_type(scalar_type) != nullptr)
2624 {2715 {
2625 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);2716 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
2626 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");2717 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
2627 } else {2718 } else {
2628 zig_unreachable();2719 zig_unreachable();
2629 }2720 }
2721 case IrBinOpMult:
2722 case IrBinOpMultWrap:
2630 case IrBinOpAdd:2723 case IrBinOpAdd:
2631 case IrBinOpAddWrap:2724 case IrBinOpAddWrap:
2632 if (type_entry->id == ZigTypeIdPointer) {2725 case IrBinOpSub:
2633 assert(type_entry->data.pointer.ptr_len == PtrLenUnknown);2726 case IrBinOpSubWrap: {
2727 bool is_wrapping = (op_id == IrBinOpSubWrap || op_id == IrBinOpAddWrap || op_id == IrBinOpMultWrap);
2728 AddSubMul add_sub_mul =
2729 op_id == IrBinOpAdd || op_id == IrBinOpAddWrap ? AddSubMulAdd :
2730 op_id == IrBinOpSub || op_id == IrBinOpSubWrap ? AddSubMulSub :
2731 AddSubMulMul;
2732
2733 if (scalar_type->id == ZigTypeIdPointer) {
2734 assert(scalar_type->data.pointer.ptr_len != PtrLenSingle);
2735 LLVMValueRef subscript_value;
2736 if (operand_type->id == ZigTypeIdVector)
2737 zig_panic("TODO: Implement vector operations on pointers.");
2738
2739 switch (add_sub_mul) {
2740 case AddSubMulAdd:
2741 subscript_value = op2_value;
2742 break;
2743 case AddSubMulSub:
2744 subscript_value = LLVMBuildNeg(g->builder, op2_value, "");
2745 break;
2746 case AddSubMulMul:
2747 zig_unreachable();
2748 }
2749
2634 // TODO runtime safety2750 // TODO runtime safety
2635 return LLVMBuildInBoundsGEP(g->builder, op1_value, &op2_value, 1, "");2751 return LLVMBuildInBoundsGEP(g->builder, op1_value, &subscript_value, 1, "");
2636 } else if (type_entry->id == ZigTypeIdFloat) {2752 } else if (scalar_type->id == ZigTypeIdFloat) {
2637 ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));2753 ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
2638 return LLVMBuildFAdd(g->builder, op1_value, op2_value, "");2754 return float_op[add_sub_mul](g->builder, op1_value, op2_value, "");
2639 } else if (type_entry->id == ZigTypeIdInt) {2755 } else if (scalar_type->id == ZigTypeIdInt) {
2640 bool is_wrapping = (op_id == IrBinOpAddWrap);
2641 if (is_wrapping) {2756 if (is_wrapping) {
2642 return LLVMBuildAdd(g->builder, op1_value, op2_value, "");2757 return wrap_op[add_sub_mul](g->builder, op1_value, op2_value, "");
2643 } else if (want_runtime_safety) {2758 } else if (want_runtime_safety) {
2644 return gen_overflow_op(g, type_entry, AddSubMulAdd, op1_value, op2_value);2759 return gen_overflow_op(g, operand_type, add_sub_mul, op1_value, op2_value);
2645 } else if (type_entry->data.integral.is_signed) {2760 } else if (scalar_type->data.integral.is_signed) {
2646 return LLVMBuildNSWAdd(g->builder, op1_value, op2_value, "");2761 return signed_op[add_sub_mul](g->builder, op1_value, op2_value, "");
2647 } else {2762 } else {
2648 return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, "");2763 return unsigned_op[add_sub_mul](g->builder, op1_value, op2_value, "");
2649 }2764 }
2650 } else {2765 } else {
2651 zig_unreachable();2766 zig_unreachable();
2652 }2767 }
2768 }
2653 case IrBinOpBinOr:2769 case IrBinOpBinOr:
2654 return LLVMBuildOr(g->builder, op1_value, op2_value, "");2770 return LLVMBuildOr(g->builder, op1_value, op2_value, "");
2655 case IrBinOpBinXor:2771 case IrBinOpBinXor:
...@@ -2659,15 +2775,14 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,...@@ -2659,15 +2775,14 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
2659 case IrBinOpBitShiftLeftLossy:2775 case IrBinOpBitShiftLeftLossy:
2660 case IrBinOpBitShiftLeftExact:2776 case IrBinOpBitShiftLeftExact:
2661 {2777 {
2662 assert(type_entry->id == ZigTypeIdInt);2778 assert(scalar_type->id == ZigTypeIdInt);
2663 LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type,2779 LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type, scalar_type, op2_value);
2664 type_entry, op2_value);
2665 bool is_sloppy = (op_id == IrBinOpBitShiftLeftLossy);2780 bool is_sloppy = (op_id == IrBinOpBitShiftLeftLossy);
2666 if (is_sloppy) {2781 if (is_sloppy) {
2667 return LLVMBuildShl(g->builder, op1_value, op2_casted, "");2782 return LLVMBuildShl(g->builder, op1_value, op2_casted, "");
2668 } else if (want_runtime_safety) {2783 } else if (want_runtime_safety) {
2669 return gen_overflow_shl_op(g, type_entry, op1_value, op2_casted);2784 return gen_overflow_shl_op(g, scalar_type, op1_value, op2_casted);
2670 } else if (type_entry->data.integral.is_signed) {2785 } else if (scalar_type->data.integral.is_signed) {
2671 return ZigLLVMBuildNSWShl(g->builder, op1_value, op2_casted, "");2786 return ZigLLVMBuildNSWShl(g->builder, op1_value, op2_casted, "");
2672 } else {2787 } else {
2673 return ZigLLVMBuildNUWShl(g->builder, op1_value, op2_casted, "");2788 return ZigLLVMBuildNUWShl(g->builder, op1_value, op2_casted, "");
...@@ -2676,85 +2791,41 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,...@@ -2676,85 +2791,41 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
2676 case IrBinOpBitShiftRightLossy:2791 case IrBinOpBitShiftRightLossy:
2677 case IrBinOpBitShiftRightExact:2792 case IrBinOpBitShiftRightExact:
2678 {2793 {
2679 assert(type_entry->id == ZigTypeIdInt);2794 assert(scalar_type->id == ZigTypeIdInt);
2680 LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type,2795 LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type, scalar_type, op2_value);
2681 type_entry, op2_value);
2682 bool is_sloppy = (op_id == IrBinOpBitShiftRightLossy);2796 bool is_sloppy = (op_id == IrBinOpBitShiftRightLossy);
2683 if (is_sloppy) {2797 if (is_sloppy) {
2684 if (type_entry->data.integral.is_signed) {2798 if (scalar_type->data.integral.is_signed) {
2685 return LLVMBuildAShr(g->builder, op1_value, op2_casted, "");2799 return LLVMBuildAShr(g->builder, op1_value, op2_casted, "");
2686 } else {2800 } else {
2687 return LLVMBuildLShr(g->builder, op1_value, op2_casted, "");2801 return LLVMBuildLShr(g->builder, op1_value, op2_casted, "");
2688 }2802 }
2689 } else if (want_runtime_safety) {2803 } else if (want_runtime_safety) {
2690 return gen_overflow_shr_op(g, type_entry, op1_value, op2_casted);2804 return gen_overflow_shr_op(g, scalar_type, op1_value, op2_casted);
2691 } else if (type_entry->data.integral.is_signed) {2805 } else if (scalar_type->data.integral.is_signed) {
2692 return ZigLLVMBuildAShrExact(g->builder, op1_value, op2_casted, "");2806 return ZigLLVMBuildAShrExact(g->builder, op1_value, op2_casted, "");
2693 } else {2807 } else {
2694 return ZigLLVMBuildLShrExact(g->builder, op1_value, op2_casted, "");2808 return ZigLLVMBuildLShrExact(g->builder, op1_value, op2_casted, "");
2695 }2809 }
2696 }2810 }
2697 case IrBinOpSub:
2698 case IrBinOpSubWrap:
2699 if (type_entry->id == ZigTypeIdPointer) {
2700 assert(type_entry->data.pointer.ptr_len == PtrLenUnknown);
2701 // TODO runtime safety
2702 LLVMValueRef subscript_value = LLVMBuildNeg(g->builder, op2_value, "");
2703 return LLVMBuildInBoundsGEP(g->builder, op1_value, &subscript_value, 1, "");
2704 } else if (type_entry->id == ZigTypeIdFloat) {
2705 ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
2706 return LLVMBuildFSub(g->builder, op1_value, op2_value, "");
2707 } else if (type_entry->id == ZigTypeIdInt) {
2708 bool is_wrapping = (op_id == IrBinOpSubWrap);
2709 if (is_wrapping) {
2710 return LLVMBuildSub(g->builder, op1_value, op2_value, "");
2711 } else if (want_runtime_safety) {
2712 return gen_overflow_op(g, type_entry, AddSubMulSub, op1_value, op2_value);
2713 } else if (type_entry->data.integral.is_signed) {
2714 return LLVMBuildNSWSub(g->builder, op1_value, op2_value, "");
2715 } else {
2716 return LLVMBuildNUWSub(g->builder, op1_value, op2_value, "");
2717 }
2718 } else {
2719 zig_unreachable();
2720 }
2721 case IrBinOpMult:
2722 case IrBinOpMultWrap:
2723 if (type_entry->id == ZigTypeIdFloat) {
2724 ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
2725 return LLVMBuildFMul(g->builder, op1_value, op2_value, "");
2726 } else if (type_entry->id == ZigTypeIdInt) {
2727 bool is_wrapping = (op_id == IrBinOpMultWrap);
2728 if (is_wrapping) {
2729 return LLVMBuildMul(g->builder, op1_value, op2_value, "");
2730 } else if (want_runtime_safety) {
2731 return gen_overflow_op(g, type_entry, AddSubMulMul, op1_value, op2_value);
2732 } else if (type_entry->data.integral.is_signed) {
2733 return LLVMBuildNSWMul(g->builder, op1_value, op2_value, "");
2734 } else {
2735 return LLVMBuildNUWMul(g->builder, op1_value, op2_value, "");
2736 }
2737 } else {
2738 zig_unreachable();
2739 }
2740 case IrBinOpDivUnspecified:2811 case IrBinOpDivUnspecified:
2741 return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),2812 return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
2742 op1_value, op2_value, type_entry, DivKindFloat);2813 op1_value, op2_value, scalar_type, DivKindFloat);
2743 case IrBinOpDivExact:2814 case IrBinOpDivExact:
2744 return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),2815 return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
2745 op1_value, op2_value, type_entry, DivKindExact);2816 op1_value, op2_value, scalar_type, DivKindExact);
2746 case IrBinOpDivTrunc:2817 case IrBinOpDivTrunc:
2747 return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),2818 return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
2748 op1_value, op2_value, type_entry, DivKindTrunc);2819 op1_value, op2_value, scalar_type, DivKindTrunc);
2749 case IrBinOpDivFloor:2820 case IrBinOpDivFloor:
2750 return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),2821 return gen_div(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
2751 op1_value, op2_value, type_entry, DivKindFloor);2822 op1_value, op2_value, scalar_type, DivKindFloor);
2752 case IrBinOpRemRem:2823 case IrBinOpRemRem:
2753 return gen_rem(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),2824 return gen_rem(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
2754 op1_value, op2_value, type_entry, RemKindRem);2825 op1_value, op2_value, scalar_type, RemKindRem);
2755 case IrBinOpRemMod:2826 case IrBinOpRemMod:
2756 return gen_rem(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),2827 return gen_rem(g, want_runtime_safety, ir_want_fast_math(g, &bin_op_instruction->base),
2757 op1_value, op2_value, type_entry, RemKindMod);2828 op1_value, op2_value, scalar_type, RemKindMod);
2758 }2829 }
2759 zig_unreachable();2830 zig_unreachable();
2760}2831}
...@@ -2882,32 +2953,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -2882,32 +2953,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
2882 gen_store_untyped(g, new_len, dest_len_ptr, 0, false);2953 gen_store_untyped(g, new_len, dest_len_ptr, 0, false);
28832954
28842955
2885 return cast_instruction->tmp_ptr;
2886 }
2887 case CastOpBytesToSlice:
2888 {
2889 assert(cast_instruction->tmp_ptr);
2890 assert(wanted_type->id == ZigTypeIdStruct);
2891 assert(wanted_type->data.structure.is_slice);
2892 assert(actual_type->id == ZigTypeIdArray);
2893
2894 ZigType *wanted_pointer_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
2895 ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
2896
2897
2898 size_t wanted_ptr_index = wanted_type->data.structure.fields[0].gen_index;
2899 LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
2900 (unsigned)wanted_ptr_index, "");
2901 LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, expr_val, wanted_pointer_type->type_ref, "");
2902 gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false);
2903
2904 size_t wanted_len_index = wanted_type->data.structure.fields[1].gen_index;
2905 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
2906 (unsigned)wanted_len_index, "");
2907 LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
2908 actual_type->data.array.len / type_size(g, wanted_child_type), false);
2909 gen_store_untyped(g, len_val, len_ptr, 0, false);
2910
2911 return cast_instruction->tmp_ptr;2956 return cast_instruction->tmp_ptr;
2912 }2957 }
2913 case CastOpIntToFloat:2958 case CastOpIntToFloat:
...@@ -2991,14 +3036,29 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -2991,14 +3036,29 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
2991}3036}
29923037
2993static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,3038static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
2994 IrInstructionPtrCast *instruction)3039 IrInstructionPtrCastGen *instruction)
2995{3040{
2996 ZigType *wanted_type = instruction->base.value.type;3041 ZigType *wanted_type = instruction->base.value.type;
2997 if (!type_has_bits(wanted_type)) {3042 if (!type_has_bits(wanted_type)) {
2998 return nullptr;3043 return nullptr;
2999 }3044 }
3000 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);3045 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
3001 return LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, "");3046 LLVMValueRef result_ptr = LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, "");
3047 bool want_safety_check = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);
3048 if (!want_safety_check || ptr_allows_addr_zero(wanted_type))
3049 return result_ptr;
3050
3051 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(result_ptr));
3052 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntNE, result_ptr, zero, "");
3053 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrCastFail");
3054 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrCastOk");
3055 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
3056
3057 LLVMPositionBuilderAtEnd(g->builder, fail_block);
3058 gen_safety_crash(g, PanicMsgIdPtrCastNull);
3059
3060 LLVMPositionBuilderAtEnd(g->builder, ok_block);
3061 return result_ptr;
3002}3062}
30033063
3004static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,3064static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,
...@@ -3179,11 +3239,11 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI...@@ -3179,11 +3239,11 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI
3179}3239}
31803240
3181static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,3241static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
3182 IrInstructionDeclVar *decl_var_instruction)3242 IrInstructionDeclVarGen *decl_var_instruction)
3183{3243{
3184 ZigVar *var = decl_var_instruction->var;3244 ZigVar *var = decl_var_instruction->var;
31853245
3186 if (!type_has_bits(var->value->type))3246 if (!type_has_bits(var->var_type))
3187 return nullptr;3247 return nullptr;
31883248
3189 if (var->ref_count == 0 && g->build_mode != BuildModeDebug)3249 if (var->ref_count == 0 && g->build_mode != BuildModeDebug)
...@@ -3191,34 +3251,16 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,...@@ -3191,34 +3251,16 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
31913251
3192 IrInstruction *init_value = decl_var_instruction->init_value;3252 IrInstruction *init_value = decl_var_instruction->init_value;
31933253
3194 bool have_init_expr = false;3254 bool have_init_expr = !value_is_all_undef(&init_value->value);
3195
3196 ConstExprValue *const_val = &init_value->value;
3197 if (const_val->special == ConstValSpecialRuntime || const_val->special == ConstValSpecialStatic)
3198 have_init_expr = true;
31993255
3200 if (have_init_expr) {3256 if (have_init_expr) {
3201 assert(var->value->type == init_value->value.type);3257 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->var_type, false, false,
3202 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,
3203 PtrLenSingle, var->align_bytes, 0, 0);3258 PtrLenSingle, var->align_bytes, 0, 0);
3204 LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);3259 LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);
3205 gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);3260 gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);
3206 } else {3261 } else if (ir_want_runtime_safety(g, &decl_var_instruction->base)) {
3207 bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);3262 uint32_t align_bytes = (var->align_bytes == 0) ? get_abi_alignment(g, var->var_type) : var->align_bytes;
3208 if (want_safe) {3263 gen_undef_init(g, align_bytes, var->var_type, var->value_ref);
3209 ZigType *usize = g->builtin_types.entry_usize;
3210 uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, var->value->type->type_ref);
3211 assert(size_bytes > 0);
3212
3213 assert(var->align_bytes > 0);
3214
3215 // memset uninitialized memory to 0xa
3216 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
3217 LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
3218 LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, var->value_ref, ptr_u8, "");
3219 LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
3220 ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, var->align_bytes, false);
3221 }
3222 }3264 }
32233265
3224 gen_var_debug_decl(g, var);3266 gen_var_debug_decl(g, var);
...@@ -3255,21 +3297,81 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI...@@ -3255,21 +3297,81 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
3255 return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, "");3297 return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, "");
3256}3298}
32573299
3258static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {3300static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) {
3259 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);3301 switch (const_val->data.x_array.special) {
3260 LLVMValueRef value = ir_llvm_value(g, instruction->value);3302 case ConstArraySpecialUndef:
3303 return true;
3304 case ConstArraySpecialBuf:
3305 return false;
3306 case ConstArraySpecialNone:
3307 for (size_t i = 0; i < len; i += 1) {
3308 if (!value_is_all_undef(&const_val->data.x_array.data.s_none.elements[i]))
3309 return false;
3310 }
3311 return true;
3312 }
3313 zig_unreachable();
3314}
32613315
3262 assert(instruction->ptr->value.type->id == ZigTypeIdPointer);3316static bool value_is_all_undef(ConstExprValue *const_val) {
3263 ZigType *ptr_type = instruction->ptr->value.type;3317 switch (const_val->special) {
3318 case ConstValSpecialRuntime:
3319 return false;
3320 case ConstValSpecialUndef:
3321 return true;
3322 case ConstValSpecialStatic:
3323 if (const_val->type->id == ZigTypeIdStruct) {
3324 for (size_t i = 0; i < const_val->type->data.structure.src_field_count; i += 1) {
3325 if (!value_is_all_undef(&const_val->data.x_struct.fields[i]))
3326 return false;
3327 }
3328 return true;
3329 } else if (const_val->type->id == ZigTypeIdArray) {
3330 return value_is_all_undef_array(const_val, const_val->type->data.array.len);
3331 } else if (const_val->type->id == ZigTypeIdVector) {
3332 return value_is_all_undef_array(const_val, const_val->type->data.vector.len);
3333 } else {
3334 return false;
3335 }
3336 }
3337 zig_unreachable();
3338}
32643339
3265 gen_assign_raw(g, ptr, ptr_type, value);3340static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) {
3341 assert(type_has_bits(value_type));
3342 uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, value_type->type_ref);
3343 assert(size_bytes > 0);
3344 assert(ptr_align_bytes > 0);
3345 // memset uninitialized memory to 0xaa
3346 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
3347 LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
3348 LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, ptr, ptr_u8, "");
3349 ZigType *usize = g->builtin_types.entry_usize;
3350 LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
3351 ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false);
3352}
32663353
3354static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {
3355 ZigType *ptr_type = instruction->ptr->value.type;
3356 assert(ptr_type->id == ZigTypeIdPointer);
3357 if (!type_has_bits(ptr_type))
3358 return nullptr;
3359
3360 bool have_init_expr = !value_is_all_undef(&instruction->value->value);
3361 if (have_init_expr) {
3362 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
3363 LLVMValueRef value = ir_llvm_value(g, instruction->value);
3364 gen_assign_raw(g, ptr, ptr_type, value);
3365 } else if (ir_want_runtime_safety(g, &instruction->base)) {
3366 gen_undef_init(g, get_ptr_align(g, ptr_type), instruction->value->value.type,
3367 ir_llvm_value(g, instruction->ptr));
3368 }
3267 return nullptr;3369 return nullptr;
3268}3370}
32693371
3270static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {3372static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {
3271 ZigVar *var = instruction->var;3373 ZigVar *var = instruction->var;
3272 if (type_has_bits(var->value->type)) {3374 if (type_has_bits(var->var_type)) {
3273 assert(var->value_ref);3375 assert(var->value_ref);
3274 return var->value_ref;3376 return var->value_ref;
3275 } else {3377 } else {
...@@ -3583,7 +3685,8 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab...@@ -3583,7 +3685,8 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
3583 LLVMPositionBuilderAtEnd(g->builder, ok_block);3685 LLVMPositionBuilderAtEnd(g->builder, ok_block);
3584 }3686 }
35853687
3586 LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_union_index, "");3688 LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr,
3689 union_type->data.unionation.gen_union_index, "");
3587 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, "");3690 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, "");
3588 return bitcasted_union_field_ptr;3691 return bitcasted_union_field_ptr;
3589}3692}
...@@ -3745,8 +3848,8 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR...@@ -3745,8 +3848,8 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR
3745 if (child_type->zero_bits) {3848 if (child_type->zero_bits) {
3746 return maybe_handle;3849 return maybe_handle;
3747 } else {3850 } else {
3748 bool maybe_is_ptr = type_is_codegen_pointer(child_type);3851 bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet;
3749 if (maybe_is_ptr) {3852 if (is_scalar) {
3750 return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), "");3853 return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), "");
3751 } else {3854 } else {
3752 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, "");3855 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, "");
...@@ -3761,17 +3864,17 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable...@@ -3761,17 +3864,17 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable
3761 return gen_non_null_bit(g, instruction->value->value.type, ir_llvm_value(g, instruction->value));3864 return gen_non_null_bit(g, instruction->value->value.type, ir_llvm_value(g, instruction->value));
3762}3865}
37633866
3764static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,3867static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *executable,
3765 IrInstructionUnwrapOptional *instruction)3868 IrInstructionOptionalUnwrapPtr *instruction)
3766{3869{
3767 ZigType *ptr_type = instruction->value->value.type;3870 ZigType *ptr_type = instruction->base_ptr->value.type;
3768 assert(ptr_type->id == ZigTypeIdPointer);3871 assert(ptr_type->id == ZigTypeIdPointer);
3769 ZigType *maybe_type = ptr_type->data.pointer.child_type;3872 ZigType *maybe_type = ptr_type->data.pointer.child_type;
3770 assert(maybe_type->id == ZigTypeIdOptional);3873 assert(maybe_type->id == ZigTypeIdOptional);
3771 ZigType *child_type = maybe_type->data.maybe.child_type;3874 ZigType *child_type = maybe_type->data.maybe.child_type;
3772 LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value);3875 LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->base_ptr);
3773 LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
3774 if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) {3876 if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) {
3877 LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
3775 LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);3878 LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);
3776 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");3879 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");
3777 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");3880 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");
...@@ -3785,8 +3888,8 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,...@@ -3785,8 +3888,8 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
3785 if (child_type->zero_bits) {3888 if (child_type->zero_bits) {
3786 return nullptr;3889 return nullptr;
3787 } else {3890 } else {
3788 bool maybe_is_ptr = type_is_codegen_pointer(child_type);3891 bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet;
3789 if (maybe_is_ptr) {3892 if (is_scalar) {
3790 return maybe_ptr;3893 return maybe_ptr;
3791 } else {3894 } else {
3792 LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);3895 LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
...@@ -3814,6 +3917,16 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI...@@ -3814,6 +3917,16 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI
3814 n_args = 1;3917 n_args = 1;
3815 key.id = ZigLLVMFnIdPopCount;3918 key.id = ZigLLVMFnIdPopCount;
3816 key.data.pop_count.bit_count = (uint32_t)int_type->data.integral.bit_count;3919 key.data.pop_count.bit_count = (uint32_t)int_type->data.integral.bit_count;
3920 } else if (fn_id == BuiltinFnIdBswap) {
3921 fn_name = "bswap";
3922 n_args = 1;
3923 key.id = ZigLLVMFnIdBswap;
3924 key.data.bswap.bit_count = (uint32_t)int_type->data.integral.bit_count;
3925 } else if (fn_id == BuiltinFnIdBitReverse) {
3926 fn_name = "bitreverse";
3927 n_args = 1;
3928 key.id = ZigLLVMFnIdBitReverse;
3929 key.data.bit_reverse.bit_count = (uint32_t)int_type->data.integral.bit_count;
3817 } else {3930 } else {
3818 zig_unreachable();3931 zig_unreachable();
3819 }3932 }
...@@ -4194,7 +4307,7 @@ static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed)...@@ -4194,7 +4307,7 @@ static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed)
4194 zig_unreachable();4307 zig_unreachable();
4195}4308}
41964309
4197static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchg *instruction) {4310static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchgGen *instruction) {
4198 LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr);4311 LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr);
4199 LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value);4312 LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value);
4200 LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value);4313 LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value);
...@@ -4209,18 +4322,18 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn...@@ -4209,18 +4322,18 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
4209 assert(maybe_type->id == ZigTypeIdOptional);4322 assert(maybe_type->id == ZigTypeIdOptional);
4210 ZigType *child_type = maybe_type->data.maybe.child_type;4323 ZigType *child_type = maybe_type->data.maybe.child_type;
42114324
4212 if (type_is_codegen_pointer(child_type)) {4325 if (!handle_is_ptr(maybe_type)) {
4213 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");4326 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
4214 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");4327 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
4215 return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(child_type->type_ref), payload_val, "");4328 return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(child_type->type_ref), payload_val, "");
4216 }4329 }
42174330
4218 assert(instruction->tmp_ptr != nullptr);4331 assert(instruction->tmp_ptr != nullptr);
4219 assert(type_has_bits(instruction->type));4332 assert(type_has_bits(child_type));
42204333
4221 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");4334 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
4222 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");4335 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");
4223 gen_assign_raw(g, val_ptr, get_pointer_to_type(g, instruction->type, false), payload_val);4336 gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
42244337
4225 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");4338 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
4226 LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, "");4339 LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, "");
...@@ -4371,6 +4484,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst...@@ -4371,6 +4484,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
4371 assert(array_type->data.structure.is_slice);4484 assert(array_type->data.structure.is_slice);
4372 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);4485 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
4373 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);4486 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
4487 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind);
43744488
4375 size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index;4489 size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index;
4376 assert(ptr_index != SIZE_MAX);4490 assert(ptr_index != SIZE_MAX);
...@@ -4560,12 +4674,14 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI...@@ -4560,12 +4674,14 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI
4560 return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, "");4674 return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, "");
4561}4675}
45624676
4563static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) {4677static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable,
4564 ZigType *ptr_type = instruction->value->value.type;4678 IrInstructionUnwrapErrCode *instruction)
4679{
4680 ZigType *ptr_type = instruction->err_union->value.type;
4565 assert(ptr_type->id == ZigTypeIdPointer);4681 assert(ptr_type->id == ZigTypeIdPointer);
4566 ZigType *err_union_type = ptr_type->data.pointer.child_type;4682 ZigType *err_union_type = ptr_type->data.pointer.child_type;
4567 ZigType *payload_type = err_union_type->data.error_union.payload_type;4683 ZigType *payload_type = err_union_type->data.error_union.payload_type;
4568 LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);4684 LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union);
4569 LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);4685 LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
45704686
4571 if (type_has_bits(payload_type)) {4687 if (type_has_bits(payload_type)) {
...@@ -4576,7 +4692,13 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab...@@ -4576,7 +4692,13 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab
4576 }4692 }
4577}4693}
45784694
4579static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) {4695static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable,
4696 IrInstructionUnwrapErrPayload *instruction)
4697{
4698 bool want_safety = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on &&
4699 g->errors_by_index.length > 1;
4700 if (!want_safety && !type_has_bits(instruction->base.value.type))
4701 return nullptr;
4580 ZigType *ptr_type = instruction->value->value.type;4702 ZigType *ptr_type = instruction->value->value.type;
4581 assert(ptr_type->id == ZigTypeIdPointer);4703 assert(ptr_type->id == ZigTypeIdPointer);
4582 ZigType *err_union_type = ptr_type->data.pointer.child_type;4704 ZigType *err_union_type = ptr_type->data.pointer.child_type;
...@@ -4588,7 +4710,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu...@@ -4588,7 +4710,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu
4588 return err_union_handle;4710 return err_union_handle;
4589 }4711 }
45904712
4591 if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->errors_by_index.length > 1) {4713 if (want_safety) {
4592 LLVMValueRef err_val;4714 LLVMValueRef err_val;
4593 if (type_has_bits(payload_type)) {4715 if (type_has_bits(payload_type)) {
4594 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");4716 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
...@@ -4627,7 +4749,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I...@@ -4627,7 +4749,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I
4627 }4749 }
46284750
4629 LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);4751 LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
4630 if (type_is_codegen_pointer(child_type)) {4752 if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) {
4631 return payload_val;4753 return payload_val;
4632 }4754 }
46334755
...@@ -5098,6 +5220,74 @@ static LLVMValueRef ir_render_sqrt(CodeGen *g, IrExecutable *executable, IrInstr...@@ -5098,6 +5220,74 @@ static LLVMValueRef ir_render_sqrt(CodeGen *g, IrExecutable *executable, IrInstr
5098 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");5220 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
5099}5221}
51005222
5223static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInstructionBswap *instruction) {
5224 LLVMValueRef op = ir_llvm_value(g, instruction->op);
5225 ZigType *int_type = instruction->base.value.type;
5226 assert(int_type->id == ZigTypeIdInt);
5227 if (int_type->data.integral.bit_count % 16 == 0) {
5228 LLVMValueRef fn_val = get_int_builtin_fn(g, instruction->base.value.type, BuiltinFnIdBswap);
5229 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
5230 }
5231 // Not an even number of bytes, so we zext 1 byte, then bswap, shift right 1 byte, truncate
5232 ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed,
5233 int_type->data.integral.bit_count + 8);
5234 // aabbcc
5235 LLVMValueRef extended = LLVMBuildZExt(g->builder, op, extended_type->type_ref, "");
5236 // 00aabbcc
5237 LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap);
5238 LLVMValueRef swapped = LLVMBuildCall(g->builder, fn_val, &extended, 1, "");
5239 // ccbbaa00
5240 LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped,
5241 LLVMConstInt(extended_type->type_ref, 8, false), "");
5242 // 00ccbbaa
5243 return LLVMBuildTrunc(g->builder, shifted, int_type->type_ref, "");
5244}
5245
5246static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutable *executable, IrInstructionBitReverse *instruction) {
5247 LLVMValueRef op = ir_llvm_value(g, instruction->op);
5248 ZigType *int_type = instruction->base.value.type;
5249 assert(int_type->id == ZigTypeIdInt);
5250 LLVMValueRef fn_val = get_int_builtin_fn(g, instruction->base.value.type, BuiltinFnIdBitReverse);
5251 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
5252}
5253
5254static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executable,
5255 IrInstructionVectorToArray *instruction)
5256{
5257 ZigType *array_type = instruction->base.value.type;
5258 assert(array_type->id == ZigTypeIdArray);
5259 assert(handle_is_ptr(array_type));
5260 assert(instruction->tmp_ptr);
5261 LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
5262 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr,
5263 LLVMPointerType(instruction->vector->value.type->type_ref, 0), "");
5264 gen_store_untyped(g, vector, casted_ptr, 0, false);
5265 return instruction->tmp_ptr;
5266}
5267
5268static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executable,
5269 IrInstructionArrayToVector *instruction)
5270{
5271 ZigType *vector_type = instruction->base.value.type;
5272 assert(vector_type->id == ZigTypeIdVector);
5273 assert(!handle_is_ptr(vector_type));
5274 LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array);
5275 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr,
5276 LLVMPointerType(vector_type->type_ref, 0), "");
5277 return gen_load_untyped(g, casted_ptr, 0, false, "");
5278}
5279
5280static LLVMValueRef ir_render_assert_zero(CodeGen *g, IrExecutable *executable,
5281 IrInstructionAssertZero *instruction)
5282{
5283 LLVMValueRef target = ir_llvm_value(g, instruction->target);
5284 ZigType *int_type = instruction->target->value.type;
5285 if (ir_want_runtime_safety(g, &instruction->base)) {
5286 return gen_assert_zero(g, target, int_type);
5287 }
5288 return nullptr;
5289}
5290
5101static void set_debug_location(CodeGen *g, IrInstruction *instruction) {5291static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
5102 AstNode *source_node = instruction->source_node;5292 AstNode *source_node = instruction->source_node;
5103 Scope *scope = instruction->scope;5293 Scope *scope = instruction->scope;
...@@ -5137,6 +5327,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5137,6 +5327,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5137 case IrInstructionIdCUndef:5327 case IrInstructionIdCUndef:
5138 case IrInstructionIdEmbedFile:5328 case IrInstructionIdEmbedFile:
5139 case IrInstructionIdIntType:5329 case IrInstructionIdIntType:
5330 case IrInstructionIdVectorType:
5140 case IrInstructionIdMemberCount:5331 case IrInstructionIdMemberCount:
5141 case IrInstructionIdMemberType:5332 case IrInstructionIdMemberType:
5142 case IrInstructionIdMemberName:5333 case IrInstructionIdMemberName:
...@@ -5173,12 +5364,15 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5173,12 +5364,15 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5173 case IrInstructionIdToBytes:5364 case IrInstructionIdToBytes:
5174 case IrInstructionIdEnumToInt:5365 case IrInstructionIdEnumToInt:
5175 case IrInstructionIdCheckRuntimeScope:5366 case IrInstructionIdCheckRuntimeScope:
5367 case IrInstructionIdDeclVarSrc:
5368 case IrInstructionIdPtrCastSrc:
5369 case IrInstructionIdCmpxchgSrc:
5176 zig_unreachable();5370 zig_unreachable();
51775371
5372 case IrInstructionIdDeclVarGen:
5373 return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction);
5178 case IrInstructionIdReturn:5374 case IrInstructionIdReturn:
5179 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);5375 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
5180 case IrInstructionIdDeclVar:
5181 return ir_render_decl_var(g, executable, (IrInstructionDeclVar *)instruction);
5182 case IrInstructionIdBinOp:5376 case IrInstructionIdBinOp:
5183 return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);5377 return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);
5184 case IrInstructionIdCast:5378 case IrInstructionIdCast:
...@@ -5209,8 +5403,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5209,8 +5403,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5209 return ir_render_asm(g, executable, (IrInstructionAsm *)instruction);5403 return ir_render_asm(g, executable, (IrInstructionAsm *)instruction);
5210 case IrInstructionIdTestNonNull:5404 case IrInstructionIdTestNonNull:
5211 return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction);5405 return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction);
5212 case IrInstructionIdUnwrapOptional:5406 case IrInstructionIdOptionalUnwrapPtr:
5213 return ir_render_unwrap_maybe(g, executable, (IrInstructionUnwrapOptional *)instruction);5407 return ir_render_optional_unwrap_ptr(g, executable, (IrInstructionOptionalUnwrapPtr *)instruction);
5214 case IrInstructionIdClz:5408 case IrInstructionIdClz:
5215 return ir_render_clz(g, executable, (IrInstructionClz *)instruction);5409 return ir_render_clz(g, executable, (IrInstructionClz *)instruction);
5216 case IrInstructionIdCtz:5410 case IrInstructionIdCtz:
...@@ -5225,8 +5419,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5225,8 +5419,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5225 return ir_render_ref(g, executable, (IrInstructionRef *)instruction);5419 return ir_render_ref(g, executable, (IrInstructionRef *)instruction);
5226 case IrInstructionIdErrName:5420 case IrInstructionIdErrName:
5227 return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction);5421 return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction);
5228 case IrInstructionIdCmpxchg:5422 case IrInstructionIdCmpxchgGen:
5229 return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchg *)instruction);5423 return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchgGen *)instruction);
5230 case IrInstructionIdFence:5424 case IrInstructionIdFence:
5231 return ir_render_fence(g, executable, (IrInstructionFence *)instruction);5425 return ir_render_fence(g, executable, (IrInstructionFence *)instruction);
5232 case IrInstructionIdTruncate:5426 case IrInstructionIdTruncate:
...@@ -5267,8 +5461,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5267,8 +5461,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5267 return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);5461 return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
5268 case IrInstructionIdUnionInit:5462 case IrInstructionIdUnionInit:
5269 return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);5463 return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
5270 case IrInstructionIdPtrCast:5464 case IrInstructionIdPtrCastGen:
5271 return ir_render_ptr_cast(g, executable, (IrInstructionPtrCast *)instruction);5465 return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction);
5272 case IrInstructionIdBitCast:5466 case IrInstructionIdBitCast:
5273 return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction);5467 return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction);
5274 case IrInstructionIdWidenOrShorten:5468 case IrInstructionIdWidenOrShorten:
...@@ -5335,6 +5529,16 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5335,6 +5529,16 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5335 return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction);5529 return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction);
5336 case IrInstructionIdSqrt:5530 case IrInstructionIdSqrt:
5337 return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction);5531 return ir_render_sqrt(g, executable, (IrInstructionSqrt *)instruction);
5532 case IrInstructionIdBswap:
5533 return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction);
5534 case IrInstructionIdBitReverse:
5535 return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction);
5536 case IrInstructionIdArrayToVector:
5537 return ir_render_array_to_vector(g, executable, (IrInstructionArrayToVector *)instruction);
5538 case IrInstructionIdVectorToArray:
5539 return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction);
5540 case IrInstructionIdAssertZero:
5541 return ir_render_assert_zero(g, executable, (IrInstructionAssertZero *)instruction);
5338 }5542 }
5339 zig_unreachable();5543 zig_unreachable();
5340}5544}
...@@ -5362,6 +5566,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {...@@ -5362,6 +5566,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
5362static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);5566static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);
5363static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);5567static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);
5364static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val);5568static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val);
5569static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val);
5570static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val);
5571static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val);
53655572
5366static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {5573static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {
5367 switch (parent->id) {5574 switch (parent->id) {
...@@ -5372,6 +5579,12 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent...@@ -5372,6 +5579,12 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
5372 case ConstParentIdStruct:5579 case ConstParentIdStruct:
5373 return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val,5580 return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val,
5374 parent->data.p_struct.field_index);5581 parent->data.p_struct.field_index);
5582 case ConstParentIdErrUnionCode:
5583 return gen_const_ptr_err_union_code_recursive(g, parent->data.p_err_union_code.err_union_val);
5584 case ConstParentIdErrUnionPayload:
5585 return gen_const_ptr_err_union_payload_recursive(g, parent->data.p_err_union_payload.err_union_val);
5586 case ConstParentIdOptionalPayload:
5587 return gen_const_ptr_optional_payload_recursive(g, parent->data.p_optional_payload.optional_val);
5375 case ConstParentIdArray:5588 case ConstParentIdArray:
5376 return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val,5589 return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val,
5377 parent->data.p_array.elem_index);5590 parent->data.p_array.elem_index);
...@@ -5387,7 +5600,7 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent...@@ -5387,7 +5600,7 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
53875600
5388static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) {5601static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) {
5389 expand_undef_array(g, array_const_val);5602 expand_undef_array(g, array_const_val);
5390 ConstParent *parent = &array_const_val->data.x_array.data.s_none.parent;5603 ConstParent *parent = &array_const_val->parent;
5391 LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);5604 LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);
53925605
5393 LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr)));5606 LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr)));
...@@ -5412,7 +5625,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar...@@ -5412,7 +5625,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
5412}5625}
54135626
5414static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) {5627static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) {
5415 ConstParent *parent = &struct_const_val->data.x_struct.parent;5628 ConstParent *parent = &struct_const_val->parent;
5416 LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent);5629 LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent);
54175630
5418 ZigType *u32 = g->builtin_types.entry_u32;5631 ZigType *u32 = g->builtin_types.entry_u32;
...@@ -5423,8 +5636,44 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s...@@ -5423,8 +5636,44 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s
5423 return LLVMConstInBoundsGEP(base_ptr, indices, 2);5636 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
5424}5637}
54255638
5639static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val) {
5640 ConstParent *parent = &err_union_const_val->parent;
5641 LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent);
5642
5643 ZigType *u32 = g->builtin_types.entry_u32;
5644 LLVMValueRef indices[] = {
5645 LLVMConstNull(u32->type_ref),
5646 LLVMConstInt(u32->type_ref, err_union_err_index, false),
5647 };
5648 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
5649}
5650
5651static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val) {
5652 ConstParent *parent = &err_union_const_val->parent;
5653 LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent);
5654
5655 ZigType *u32 = g->builtin_types.entry_u32;
5656 LLVMValueRef indices[] = {
5657 LLVMConstNull(u32->type_ref),
5658 LLVMConstInt(u32->type_ref, err_union_payload_index, false),
5659 };
5660 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
5661}
5662
5663static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val) {
5664 ConstParent *parent = &optional_const_val->parent;
5665 LLVMValueRef base_ptr = gen_parent_ptr(g, optional_const_val, parent);
5666
5667 ZigType *u32 = g->builtin_types.entry_u32;
5668 LLVMValueRef indices[] = {
5669 LLVMConstNull(u32->type_ref),
5670 LLVMConstInt(u32->type_ref, maybe_child_index, false),
5671 };
5672 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
5673}
5674
5426static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val) {5675static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val) {
5427 ConstParent *parent = &union_const_val->data.x_union.parent;5676 ConstParent *parent = &union_const_val->parent;
5428 LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent);5677 LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent);
54295678
5430 ZigType *u32 = g->builtin_types.entry_u32;5679 ZigType *u32 = g->builtin_types.entry_u32;
...@@ -5494,6 +5743,8 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con...@@ -5494,6 +5743,8 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
5494 }5743 }
5495 case ZigTypeIdArray:5744 case ZigTypeIdArray:
5496 zig_panic("TODO bit pack an array");5745 zig_panic("TODO bit pack an array");
5746 case ZigTypeIdVector:
5747 zig_panic("TODO bit pack a vector");
5497 case ZigTypeIdUnion:5748 case ZigTypeIdUnion:
5498 zig_panic("TODO bit pack a union");5749 zig_panic("TODO bit pack a union");
5499 case ZigTypeIdStruct:5750 case ZigTypeIdStruct:
...@@ -5541,76 +5792,127 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con...@@ -5541,76 +5792,127 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
5541 zig_unreachable();5792 zig_unreachable();
5542 case ConstPtrSpecialRef:5793 case ConstPtrSpecialRef:
5543 {5794 {
5544 render_const_val_global(g, const_val, name);5795 assert(const_val->global_refs != nullptr);
5545 ConstExprValue *pointee = const_val->data.x_ptr.data.ref.pointee;5796 ConstExprValue *pointee = const_val->data.x_ptr.data.ref.pointee;
5546 render_const_val(g, pointee, "");5797 render_const_val(g, pointee, "");
5547 render_const_val_global(g, pointee, "");5798 render_const_val_global(g, pointee, "");
5548 ConstExprValue *other_val = pointee;5799 const_val->global_refs->llvm_value = LLVMConstBitCast(pointee->global_refs->llvm_global, const_val->type->type_ref);
5549 const_val->global_refs->llvm_value = LLVMConstBitCast(other_val->global_refs->llvm_global, const_val->type->type_ref);
5550 render_const_val_global(g, const_val, "");
5551 return const_val->global_refs->llvm_value;5800 return const_val->global_refs->llvm_value;
5552 }5801 }
5553 case ConstPtrSpecialBaseArray:5802 case ConstPtrSpecialBaseArray:
5554 {5803 {
5555 render_const_val_global(g, const_val, name);5804 assert(const_val->global_refs != nullptr);
5556 ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;5805 ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
5557 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
5558 assert(array_const_val->type->id == ZigTypeIdArray);5806 assert(array_const_val->type->id == ZigTypeIdArray);
5559 if (array_const_val->type->zero_bits) {5807 if (!type_has_bits(array_const_val->type)) {
5560 // make this a null pointer5808 // make this a null pointer
5561 ZigType *usize = g->builtin_types.entry_usize;5809 ZigType *usize = g->builtin_types.entry_usize;
5562 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),5810 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
5563 const_val->type->type_ref);5811 const_val->type->type_ref);
5564 render_const_val_global(g, const_val, "");
5565 return const_val->global_refs->llvm_value;5812 return const_val->global_refs->llvm_value;
5566 }5813 }
5567 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val,5814 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
5568 elem_index);5815 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, elem_index);
5569 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);5816 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
5570 const_val->global_refs->llvm_value = ptr_val;5817 const_val->global_refs->llvm_value = ptr_val;
5571 render_const_val_global(g, const_val, "");
5572 return ptr_val;5818 return ptr_val;
5573 }5819 }
5574 case ConstPtrSpecialBaseStruct:5820 case ConstPtrSpecialBaseStruct:
5575 {5821 {
5576 render_const_val_global(g, const_val, name);5822 assert(const_val->global_refs != nullptr);
5577 ConstExprValue *struct_const_val = const_val->data.x_ptr.data.base_struct.struct_val;5823 ConstExprValue *struct_const_val = const_val->data.x_ptr.data.base_struct.struct_val;
5578 assert(struct_const_val->type->id == ZigTypeIdStruct);5824 assert(struct_const_val->type->id == ZigTypeIdStruct);
5579 if (struct_const_val->type->zero_bits) {5825 if (!type_has_bits(struct_const_val->type)) {
5580 // make this a null pointer5826 // make this a null pointer
5581 ZigType *usize = g->builtin_types.entry_usize;5827 ZigType *usize = g->builtin_types.entry_usize;
5582 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),5828 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
5583 const_val->type->type_ref);5829 const_val->type->type_ref);
5584 render_const_val_global(g, const_val, "");
5585 return const_val->global_refs->llvm_value;5830 return const_val->global_refs->llvm_value;
5586 }5831 }
5587 size_t src_field_index = const_val->data.x_ptr.data.base_struct.field_index;5832 size_t src_field_index = const_val->data.x_ptr.data.base_struct.field_index;
5588 size_t gen_field_index =5833 size_t gen_field_index = struct_const_val->type->data.structure.fields[src_field_index].gen_index;
5589 struct_const_val->type->data.structure.fields[src_field_index].gen_index;
5590 LLVMValueRef uncasted_ptr_val = gen_const_ptr_struct_recursive(g, struct_const_val,5834 LLVMValueRef uncasted_ptr_val = gen_const_ptr_struct_recursive(g, struct_const_val,
5591 gen_field_index);5835 gen_field_index);
5592 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);5836 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
5593 const_val->global_refs->llvm_value = ptr_val;5837 const_val->global_refs->llvm_value = ptr_val;
5594 render_const_val_global(g, const_val, "");5838 return ptr_val;
5839 }
5840 case ConstPtrSpecialBaseErrorUnionCode:
5841 {
5842 assert(const_val->global_refs != nullptr);
5843 ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_code.err_union_val;
5844 assert(err_union_const_val->type->id == ZigTypeIdErrorUnion);
5845 if (!type_has_bits(err_union_const_val->type)) {
5846 // make this a null pointer
5847 ZigType *usize = g->builtin_types.entry_usize;
5848 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
5849 const_val->type->type_ref);
5850 return const_val->global_refs->llvm_value;
5851 }
5852 LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_code_recursive(g, err_union_const_val);
5853 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
5854 const_val->global_refs->llvm_value = ptr_val;
5855 return ptr_val;
5856 }
5857 case ConstPtrSpecialBaseErrorUnionPayload:
5858 {
5859 assert(const_val->global_refs != nullptr);
5860 ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_payload.err_union_val;
5861 assert(err_union_const_val->type->id == ZigTypeIdErrorUnion);
5862 if (err_union_const_val->type->zero_bits) {
5863 // make this a null pointer
5864 ZigType *usize = g->builtin_types.entry_usize;
5865 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
5866 const_val->type->type_ref);
5867 return const_val->global_refs->llvm_value;
5868 }
5869 LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_payload_recursive(g, err_union_const_val);
5870 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
5871 const_val->global_refs->llvm_value = ptr_val;
5872 return ptr_val;
5873 }
5874 case ConstPtrSpecialBaseOptionalPayload:
5875 {
5876 assert(const_val->global_refs != nullptr);
5877 ConstExprValue *optional_const_val = const_val->data.x_ptr.data.base_optional_payload.optional_val;
5878 assert(optional_const_val->type->id == ZigTypeIdOptional);
5879 if (optional_const_val->type->zero_bits) {
5880 // make this a null pointer
5881 ZigType *usize = g->builtin_types.entry_usize;
5882 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
5883 const_val->type->type_ref);
5884 return const_val->global_refs->llvm_value;
5885 }
5886 LLVMValueRef uncasted_ptr_val = gen_const_ptr_optional_payload_recursive(g, optional_const_val);
5887 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
5888 const_val->global_refs->llvm_value = ptr_val;
5595 return ptr_val;5889 return ptr_val;
5596 }5890 }
5597 case ConstPtrSpecialHardCodedAddr:5891 case ConstPtrSpecialHardCodedAddr:
5598 {5892 {
5599 render_const_val_global(g, const_val, name);5893 assert(const_val->global_refs != nullptr);
5600 uint64_t addr_value = const_val->data.x_ptr.data.hard_coded_addr.addr;5894 uint64_t addr_value = const_val->data.x_ptr.data.hard_coded_addr.addr;
5601 ZigType *usize = g->builtin_types.entry_usize;5895 ZigType *usize = g->builtin_types.entry_usize;
5602 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, addr_value, false),5896 const_val->global_refs->llvm_value = LLVMConstIntToPtr(
5603 const_val->type->type_ref);5897 LLVMConstInt(usize->type_ref, addr_value, false), const_val->type->type_ref);
5604 render_const_val_global(g, const_val, "");
5605 return const_val->global_refs->llvm_value;5898 return const_val->global_refs->llvm_value;
5606 }5899 }
5607 case ConstPtrSpecialFunction:5900 case ConstPtrSpecialFunction:
5608 return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref);5901 return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref);
5902 case ConstPtrSpecialNull:
5903 return LLVMConstNull(const_val->type->type_ref);
5609 }5904 }
5610 zig_unreachable();5905 zig_unreachable();
5611}5906}
56125907
5908static LLVMValueRef gen_const_val_err_set(CodeGen *g, ConstExprValue *const_val, const char *name) {
5909 uint64_t value = (const_val->data.x_err_set == nullptr) ? 0 : const_val->data.x_err_set->value;
5910 return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref, value, false);
5911}
5912
5613static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) {5913static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) {
5914 Error err;
5915
5614 ZigType *type_entry = const_val->type;5916 ZigType *type_entry = const_val->type;
5615 assert(!type_entry->zero_bits);5917 assert(!type_entry->zero_bits);
56165918
...@@ -5627,9 +5929,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5627,9 +5929,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5627 case ZigTypeIdInt:5929 case ZigTypeIdInt:
5628 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);5930 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);
5629 case ZigTypeIdErrorSet:5931 case ZigTypeIdErrorSet:
5630 assert(const_val->data.x_err_set != nullptr);5932 return gen_const_val_err_set(g, const_val, name);
5631 return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref,
5632 const_val->data.x_err_set->value, false);
5633 case ZigTypeIdFloat:5933 case ZigTypeIdFloat:
5634 switch (type_entry->data.floating.bit_count) {5934 switch (type_entry->data.floating.bit_count) {
5635 case 16:5935 case 16:
...@@ -5663,6 +5963,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5663,6 +5963,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5663 return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false);5963 return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false);
5664 } else if (type_is_codegen_pointer(child_type)) {5964 } else if (type_is_codegen_pointer(child_type)) {
5665 return gen_const_val_ptr(g, const_val, name);5965 return gen_const_val_ptr(g, const_val, name);
5966 } else if (child_type->id == ZigTypeIdErrorSet) {
5967 return gen_const_val_err_set(g, const_val, name);
5666 } else {5968 } else {
5667 LLVMValueRef child_val;5969 LLVMValueRef child_val;
5668 LLVMValueRef maybe_val;5970 LLVMValueRef maybe_val;
...@@ -5754,6 +6056,12 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5754,6 +6056,12 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5754 }6056 }
5755 ConstExprValue *field_val = &const_val->data.x_struct.fields[i];6057 ConstExprValue *field_val = &const_val->data.x_struct.fields[i];
5756 assert(field_val->type != nullptr);6058 assert(field_val->type != nullptr);
6059 if ((err = ensure_const_val_repr(nullptr, g, nullptr, field_val,
6060 type_struct_field->type_entry)))
6061 {
6062 zig_unreachable();
6063 }
6064
5757 LLVMValueRef val = gen_const_val(g, field_val, "");6065 LLVMValueRef val = gen_const_val(g, field_val, "");
5758 fields[type_struct_field->gen_index] = val;6066 fields[type_struct_field->gen_index] = val;
5759 make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(field_val->type, val);6067 make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(field_val->type, val);
...@@ -5793,7 +6101,33 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5793,7 +6101,33 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5793 return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf), true);6101 return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf), true);
5794 }6102 }
5795 }6103 }
6104 zig_unreachable();
6105 }
6106 case ZigTypeIdVector: {
6107 uint32_t len = type_entry->data.vector.len;
6108 switch (const_val->data.x_array.special) {
6109 case ConstArraySpecialUndef:
6110 return LLVMGetUndef(type_entry->type_ref);
6111 case ConstArraySpecialNone: {
6112 LLVMValueRef *values = allocate<LLVMValueRef>(len);
6113 for (uint64_t i = 0; i < len; i += 1) {
6114 ConstExprValue *elem_value = &const_val->data.x_array.data.s_none.elements[i];
6115 values[i] = gen_const_val(g, elem_value, "");
6116 }
6117 return LLVMConstVector(values, len);
6118 }
6119 case ConstArraySpecialBuf: {
6120 Buf *buf = const_val->data.x_array.data.s_buf;
6121 assert(buf_len(buf) == len);
6122 LLVMValueRef *values = allocate<LLVMValueRef>(len);
6123 for (uint64_t i = 0; i < len; i += 1) {
6124 values[i] = LLVMConstInt(g->builtin_types.entry_u8->type_ref, buf_ptr(buf)[i], false);
6125 }
6126 return LLVMConstVector(values, len);
6127 }
5796 }6128 }
6129 zig_unreachable();
6130 }
5797 case ZigTypeIdUnion:6131 case ZigTypeIdUnion:
5798 {6132 {
5799 LLVMTypeRef union_type_ref = type_entry->data.unionation.union_type_ref;6133 LLVMTypeRef union_type_ref = type_entry->data.unionation.union_type_ref;
...@@ -5891,7 +6225,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5891,7 +6225,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5891 ZigType *err_set_type = type_entry->data.error_union.err_set_type;6225 ZigType *err_set_type = type_entry->data.error_union.err_set_type;
5892 if (!type_has_bits(payload_type)) {6226 if (!type_has_bits(payload_type)) {
5893 assert(type_has_bits(err_set_type));6227 assert(type_has_bits(err_set_type));
5894 uint64_t value = const_val->data.x_err_union.err ? const_val->data.x_err_union.err->value : 0;6228 ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
6229 uint64_t value = (err_set == nullptr) ? 0 : err_set->value;
5895 return LLVMConstInt(g->err_tag_type->type_ref, value, false);6230 return LLVMConstInt(g->err_tag_type->type_ref, value, false);
5896 } else if (!type_has_bits(err_set_type)) {6231 } else if (!type_has_bits(err_set_type)) {
5897 assert(type_has_bits(payload_type));6232 assert(type_has_bits(payload_type));
...@@ -5900,8 +6235,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5900,8 +6235,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5900 LLVMValueRef err_tag_value;6235 LLVMValueRef err_tag_value;
5901 LLVMValueRef err_payload_value;6236 LLVMValueRef err_payload_value;
5902 bool make_unnamed_struct;6237 bool make_unnamed_struct;
5903 if (const_val->data.x_err_union.err) {6238 ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
5904 err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false);6239 if (err_set != nullptr) {
6240 err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, err_set->value, false);
5905 err_payload_value = LLVMConstNull(payload_type->type_ref);6241 err_payload_value = LLVMConstNull(payload_type->type_ref);
5906 make_unnamed_struct = false;6242 make_unnamed_struct = false;
5907 } else {6243 } else {
...@@ -6075,6 +6411,12 @@ static void validate_inline_fns(CodeGen *g) {...@@ -6075,6 +6411,12 @@ static void validate_inline_fns(CodeGen *g) {
6075 report_errors_and_maybe_exit(g);6411 report_errors_and_maybe_exit(g);
6076}6412}
60776413
6414static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {
6415 if (var->is_thread_local && !g->is_single_threaded) {
6416 LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel);
6417 }
6418}
6419
6078static void do_code_gen(CodeGen *g) {6420static void do_code_gen(CodeGen *g) {
6079 assert(!g->errors.length);6421 assert(!g->errors.length);
60806422
...@@ -6107,10 +6449,13 @@ static void do_code_gen(CodeGen *g) {...@@ -6107,10 +6449,13 @@ static void do_code_gen(CodeGen *g) {
6107 TldVar *tld_var = g->global_vars.at(i);6449 TldVar *tld_var = g->global_vars.at(i);
6108 ZigVar *var = tld_var->var;6450 ZigVar *var = tld_var->var;
61096451
6110 if (var->value->type->id == ZigTypeIdComptimeFloat) {6452 if (var->var_type->id == ZigTypeIdComptimeFloat) {
6111 // Generate debug info for it but that's it.6453 // Generate debug info for it but that's it.
6112 ConstExprValue *const_val = var->value;6454 ConstExprValue *const_val = var->const_value;
6113 assert(const_val->special != ConstValSpecialRuntime);6455 assert(const_val->special != ConstValSpecialRuntime);
6456 if (const_val->type != var->var_type) {
6457 zig_panic("TODO debug info for var with ptr casted value");
6458 }
6114 ZigType *var_type = g->builtin_types.entry_f128;6459 ZigType *var_type = g->builtin_types.entry_f128;
6115 ConstExprValue coerced_value;6460 ConstExprValue coerced_value;
6116 coerced_value.special = ConstValSpecialStatic;6461 coerced_value.special = ConstValSpecialStatic;
...@@ -6121,10 +6466,13 @@ static void do_code_gen(CodeGen *g) {...@@ -6121,10 +6466,13 @@ static void do_code_gen(CodeGen *g) {
6121 continue;6466 continue;
6122 }6467 }
61236468
6124 if (var->value->type->id == ZigTypeIdComptimeInt) {6469 if (var->var_type->id == ZigTypeIdComptimeInt) {
6125 // Generate debug info for it but that's it.6470 // Generate debug info for it but that's it.
6126 ConstExprValue *const_val = var->value;6471 ConstExprValue *const_val = var->const_value;
6127 assert(const_val->special != ConstValSpecialRuntime);6472 assert(const_val->special != ConstValSpecialRuntime);
6473 if (const_val->type != var->var_type) {
6474 zig_panic("TODO debug info for var with ptr casted value");
6475 }
6128 size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint);6476 size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint);
6129 if (bits_needed < 8) {6477 if (bits_needed < 8) {
6130 bits_needed = 8;6478 bits_needed = 8;
...@@ -6135,7 +6483,7 @@ static void do_code_gen(CodeGen *g) {...@@ -6135,7 +6483,7 @@ static void do_code_gen(CodeGen *g) {
6135 continue;6483 continue;
6136 }6484 }
61376485
6138 if (!type_has_bits(var->value->type))6486 if (!type_has_bits(var->var_type))
6139 continue;6487 continue;
61406488
6141 assert(var->decl_node);6489 assert(var->decl_node);
...@@ -6144,22 +6492,23 @@ static void do_code_gen(CodeGen *g) {...@@ -6144,22 +6492,23 @@ static void do_code_gen(CodeGen *g) {
6144 if (var->linkage == VarLinkageExternal) {6492 if (var->linkage == VarLinkageExternal) {
6145 LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name));6493 LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name));
6146 if (existing_llvm_var) {6494 if (existing_llvm_var) {
6147 global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->value->type->type_ref, 0));6495 global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->var_type->type_ref, 0));
6148 } else {6496 } else {
6149 global_value = LLVMAddGlobal(g->module, var->value->type->type_ref, buf_ptr(&var->name));6497 global_value = LLVMAddGlobal(g->module, var->var_type->type_ref, buf_ptr(&var->name));
6150 // TODO debug info for the extern variable6498 // TODO debug info for the extern variable
61516499
6152 LLVMSetLinkage(global_value, LLVMExternalLinkage);6500 LLVMSetLinkage(global_value, LLVMExternalLinkage);
6153 maybe_import_dll(g, global_value, GlobalLinkageIdStrong);6501 maybe_import_dll(g, global_value, GlobalLinkageIdStrong);
6154 LLVMSetAlignment(global_value, var->align_bytes);6502 LLVMSetAlignment(global_value, var->align_bytes);
6155 LLVMSetGlobalConstant(global_value, var->gen_is_const);6503 LLVMSetGlobalConstant(global_value, var->gen_is_const);
6504 set_global_tls(g, var, global_value);
6156 }6505 }
6157 } else {6506 } else {
6158 bool exported = (var->linkage == VarLinkageExport);6507 bool exported = (var->linkage == VarLinkageExport);
6159 const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));6508 const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));
6160 render_const_val(g, var->value, mangled_name);6509 render_const_val(g, var->const_value, mangled_name);
6161 render_const_val_global(g, var->value, mangled_name);6510 render_const_val_global(g, var->const_value, mangled_name);
6162 global_value = var->value->global_refs->llvm_global;6511 global_value = var->const_value->global_refs->llvm_global;
61636512
6164 if (exported) {6513 if (exported) {
6165 LLVMSetLinkage(global_value, LLVMExternalLinkage);6514 LLVMSetLinkage(global_value, LLVMExternalLinkage);
...@@ -6171,11 +6520,14 @@ static void do_code_gen(CodeGen *g) {...@@ -6171,11 +6520,14 @@ static void do_code_gen(CodeGen *g) {
6171 LLVMSetAlignment(global_value, var->align_bytes);6520 LLVMSetAlignment(global_value, var->align_bytes);
61726521
6173 // TODO debug info for function pointers6522 // TODO debug info for function pointers
6174 if (var->gen_is_const && var->value->type->id != ZigTypeIdFn) {6523 // Here we use const_value->type because that's the type of the llvm global,
6175 gen_global_var(g, var, var->value->global_refs->llvm_value, var->value->type);6524 // which we const ptr cast upon use to whatever it needs to be.
6525 if (var->gen_is_const && var->const_value->type->id != ZigTypeIdFn) {
6526 gen_global_var(g, var, var->const_value->global_refs->llvm_value, var->const_value->type);
6176 }6527 }
61776528
6178 LLVMSetGlobalConstant(global_value, var->gen_is_const);6529 LLVMSetGlobalConstant(global_value, var->gen_is_const);
6530 set_global_tls(g, var, global_value);
6179 }6531 }
61806532
6181 var->value_ref = global_value;6533 var->value_ref = global_value;
...@@ -6226,6 +6578,7 @@ static void do_code_gen(CodeGen *g) {...@@ -6226,6 +6578,7 @@ static void do_code_gen(CodeGen *g) {
6226 IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i);6578 IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i);
6227 LLVMValueRef *slot;6579 LLVMValueRef *slot;
6228 ZigType *slot_type = instruction->value.type;6580 ZigType *slot_type = instruction->value.type;
6581 uint32_t alignment_bytes = 0;
6229 if (instruction->id == IrInstructionIdCast) {6582 if (instruction->id == IrInstructionIdCast) {
6230 IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction;6583 IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction;
6231 slot = &cast_instruction->tmp_ptr;6584 slot = &cast_instruction->tmp_ptr;
...@@ -6258,13 +6611,17 @@ static void do_code_gen(CodeGen *g) {...@@ -6258,13 +6611,17 @@ static void do_code_gen(CodeGen *g) {
6258 } else if (instruction->id == IrInstructionIdErrWrapCode) {6611 } else if (instruction->id == IrInstructionIdErrWrapCode) {
6259 IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;6612 IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
6260 slot = &err_wrap_code_instruction->tmp_ptr;6613 slot = &err_wrap_code_instruction->tmp_ptr;
6261 } else if (instruction->id == IrInstructionIdCmpxchg) {6614 } else if (instruction->id == IrInstructionIdCmpxchgGen) {
6262 IrInstructionCmpxchg *cmpxchg_instruction = (IrInstructionCmpxchg *)instruction;6615 IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;
6263 slot = &cmpxchg_instruction->tmp_ptr;6616 slot = &cmpxchg_instruction->tmp_ptr;
6617 } else if (instruction->id == IrInstructionIdVectorToArray) {
6618 IrInstructionVectorToArray *vector_to_array_instruction = (IrInstructionVectorToArray *)instruction;
6619 alignment_bytes = get_abi_alignment(g, vector_to_array_instruction->vector->value.type);
6620 slot = &vector_to_array_instruction->tmp_ptr;
6264 } else {6621 } else {
6265 zig_unreachable();6622 zig_unreachable();
6266 }6623 }
6267 *slot = build_alloca(g, slot_type, "", get_abi_alignment(g, slot_type));6624 *slot = build_alloca(g, slot_type, "", alignment_bytes);
6268 }6625 }
62696626
6270 ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base);6627 ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base);
...@@ -6281,12 +6638,12 @@ static void do_code_gen(CodeGen *g) {...@@ -6281,12 +6638,12 @@ static void do_code_gen(CodeGen *g) {
6281 for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {6638 for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {
6282 ZigVar *var = fn_table_entry->variable_list.at(var_i);6639 ZigVar *var = fn_table_entry->variable_list.at(var_i);
62836640
6284 if (!type_has_bits(var->value->type)) {6641 if (!type_has_bits(var->var_type)) {
6285 continue;6642 continue;
6286 }6643 }
6287 if (ir_get_var_is_comptime(var))6644 if (ir_get_var_is_comptime(var))
6288 continue;6645 continue;
6289 switch (type_requires_comptime(g, var->value->type)) {6646 switch (type_requires_comptime(g, var->var_type)) {
6290 case ReqCompTimeInvalid:6647 case ReqCompTimeInvalid:
6291 zig_unreachable();6648 zig_unreachable();
6292 case ReqCompTimeYes:6649 case ReqCompTimeYes:
...@@ -6296,11 +6653,11 @@ static void do_code_gen(CodeGen *g) {...@@ -6296,11 +6653,11 @@ static void do_code_gen(CodeGen *g) {
6296 }6653 }
62976654
6298 if (var->src_arg_index == SIZE_MAX) {6655 if (var->src_arg_index == SIZE_MAX) {
6299 var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);6656 var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
63006657
6301 var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),6658 var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
6302 buf_ptr(&var->name), import->di_file, (unsigned)(var->decl_node->line + 1),6659 buf_ptr(&var->name), import->di_file, (unsigned)(var->decl_node->line + 1),
6303 var->value->type->di_type, !g->strip_debug_symbols, 0);6660 var->var_type->di_type, !g->strip_debug_symbols, 0);
63046661
6305 } else if (is_c_abi) {6662 } else if (is_c_abi) {
6306 fn_walk_var.data.vars.var = var;6663 fn_walk_var.data.vars.var = var;
...@@ -6310,16 +6667,16 @@ static void do_code_gen(CodeGen *g) {...@@ -6310,16 +6667,16 @@ static void do_code_gen(CodeGen *g) {
6310 ZigType *gen_type;6667 ZigType *gen_type;
6311 FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index];6668 FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index];
63126669
6313 if (handle_is_ptr(var->value->type)) {6670 if (handle_is_ptr(var->var_type)) {
6314 if (gen_info->is_byval) {6671 if (gen_info->is_byval) {
6315 gen_type = var->value->type;6672 gen_type = var->var_type;
6316 } else {6673 } else {
6317 gen_type = gen_info->type;6674 gen_type = gen_info->type;
6318 }6675 }
6319 var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index);6676 var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index);
6320 } else {6677 } else {
6321 gen_type = var->value->type;6678 gen_type = var->var_type;
6322 var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);6679 var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
6323 }6680 }
6324 if (var->decl_node) {6681 if (var->decl_node) {
6325 var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),6682 var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
...@@ -6719,6 +7076,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -6719,6 +7076,7 @@ static void define_builtin_fns(CodeGen *g) {
6719 create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);7076 create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
6720 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);7077 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
6721 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int7078 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
7079 create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);
6722 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);7080 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);
6723 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);7081 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);
6724 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);7082 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);
...@@ -6757,6 +7115,8 @@ static void define_builtin_fns(CodeGen *g) {...@@ -6757,6 +7115,8 @@ static void define_builtin_fns(CodeGen *g) {
6757 create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);7115 create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);
6758 create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);7116 create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
6759 create_builtin_fn(g, BuiltinFnIdThis, "This", 0);7117 create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
7118 create_builtin_fn(g, BuiltinFnIdBswap, "bswap", 2);
7119 create_builtin_fn(g, BuiltinFnIdBitReverse, "bitreverse", 2);
6760}7120}
67617121
6762static const char *bool_to_str(bool b) {7122static const char *bool_to_str(bool b) {
...@@ -6784,6 +7144,8 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -6784,6 +7144,8 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
6784 " instruction_addresses: []usize,\n"7144 " instruction_addresses: []usize,\n"
6785 "};\n\n");7145 "};\n\n");
67867146
7147 buf_append_str(contents, "pub const PanicFn = fn([]const u8, ?*StackTrace) noreturn;\n\n");
7148
6787 const char *cur_os = nullptr;7149 const char *cur_os = nullptr;
6788 {7150 {
6789 buf_appendf(contents, "pub const Os = enum {\n");7151 buf_appendf(contents, "pub const Os = enum {\n");
...@@ -6942,6 +7304,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -6942,6 +7304,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
6942 " ArgTuple: void,\n"7304 " ArgTuple: void,\n"
6943 " Opaque: void,\n"7305 " Opaque: void,\n"
6944 " Promise: Promise,\n"7306 " Promise: Promise,\n"
7307 " Vector: Vector,\n"
6945 "\n\n"7308 "\n\n"
6946 " pub const Int = struct {\n"7309 " pub const Int = struct {\n"
6947 " is_signed: bool,\n"7310 " is_signed: bool,\n"
...@@ -6963,6 +7326,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -6963,6 +7326,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
6963 " One,\n"7326 " One,\n"
6964 " Many,\n"7327 " Many,\n"
6965 " Slice,\n"7328 " Slice,\n"
7329 " C,\n"
6966 " };\n"7330 " };\n"
6967 " };\n"7331 " };\n"
6968 "\n"7332 "\n"
...@@ -7060,6 +7424,11 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -7060,6 +7424,11 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
7060 " child: ?type,\n"7424 " child: ?type,\n"
7061 " };\n"7425 " };\n"
7062 "\n"7426 "\n"
7427 " pub const Vector = struct {\n"
7428 " len: u32,\n"
7429 " child: type,\n"
7430 " };\n"
7431 "\n"
7063 " pub const Definition = struct {\n"7432 " pub const Definition = struct {\n"
7064 " name: []const u8,\n"7433 " name: []const u8,\n"
7065 " is_pub: bool,\n"7434 " is_pub: bool,\n"
...@@ -7128,6 +7497,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -7128,6 +7497,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
7128 buf_appendf(contents, "pub const endian = %s;\n", endian_str);7497 buf_appendf(contents, "pub const endian = %s;\n", endian_str);
7129 }7498 }
7130 buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build));7499 buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build));
7500 buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));
7131 buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);7501 buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);
7132 buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);7502 buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);
7133 buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ);7503 buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ);
...@@ -7162,6 +7532,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {...@@ -7162,6 +7532,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
7162 cache_buf(&cache_hash, compiler_id);7532 cache_buf(&cache_hash, compiler_id);
7163 cache_int(&cache_hash, g->build_mode);7533 cache_int(&cache_hash, g->build_mode);
7164 cache_bool(&cache_hash, g->is_test_build);7534 cache_bool(&cache_hash, g->is_test_build);
7535 cache_bool(&cache_hash, g->is_single_threaded);
7165 cache_int(&cache_hash, g->zig_target.arch.arch);7536 cache_int(&cache_hash, g->zig_target.arch.arch);
7166 cache_int(&cache_hash, g->zig_target.arch.sub_arch);7537 cache_int(&cache_hash, g->zig_target.arch.sub_arch);
7167 cache_int(&cache_hash, g->zig_target.vendor);7538 cache_int(&cache_hash, g->zig_target.vendor);
...@@ -7210,6 +7581,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {...@@ -7210,6 +7581,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
7210 g->compile_var_package = new_package(buf_ptr(this_dir), builtin_zig_basename);7581 g->compile_var_package = new_package(buf_ptr(this_dir), builtin_zig_basename);
7211 g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);7582 g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
7212 g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);7583 g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
7584 g->std_package->package_table.put(buf_create_from_str("std"), g->std_package);
7213 g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents);7585 g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents);
7214 scan_import(g, g->compile_var_import);7586 scan_import(g, g->compile_var_import);
72157587
...@@ -7231,8 +7603,7 @@ static void init(CodeGen *g) {...@@ -7231,8 +7603,7 @@ static void init(CodeGen *g) {
7231 }7603 }
72327604
7233 if (g->is_test_build) {7605 if (g->is_test_build) {
7234 g->windows_subsystem_windows = false;7606 g->subsystem = TargetSubsystemConsole;
7235 g->windows_subsystem_console = true;
7236 }7607 }
72377608
7238 assert(g->root_out_name);7609 assert(g->root_out_name);
...@@ -7251,7 +7622,13 @@ static void init(CodeGen *g) {...@@ -7251,7 +7622,13 @@ static void init(CodeGen *g) {
7251 LLVMTargetRef target_ref;7622 LLVMTargetRef target_ref;
7252 char *err_msg = nullptr;7623 char *err_msg = nullptr;
7253 if (LLVMGetTargetFromTriple(buf_ptr(&g->triple_str), &target_ref, &err_msg)) {7624 if (LLVMGetTargetFromTriple(buf_ptr(&g->triple_str), &target_ref, &err_msg)) {
7254 zig_panic("unable to create target based on: %s", buf_ptr(&g->triple_str));7625 fprintf(stderr,
7626 "Zig is expecting LLVM to understand this target: '%s'\n"
7627 "However LLVM responded with: \"%s\"\n"
7628 "Zig is unable to continue. This is a bug in Zig:\n"
7629 "https://github.com/ziglang/zig/issues/438\n"
7630 , buf_ptr(&g->triple_str), err_msg);
7631 exit(1);
7255 }7632 }
72567633
7257 bool is_optimized = g->build_mode != BuildModeDebug;7634 bool is_optimized = g->build_mode != BuildModeDebug;
...@@ -7268,7 +7645,7 @@ static void init(CodeGen *g) {...@@ -7268,7 +7645,7 @@ static void init(CodeGen *g) {
7268 // LLVM creates invalid binaries on Windows sometimes.7645 // LLVM creates invalid binaries on Windows sometimes.
7269 // See https://github.com/ziglang/zig/issues/5087646 // See https://github.com/ziglang/zig/issues/508
7270 // As a workaround we do not use target native features on Windows.7647 // As a workaround we do not use target native features on Windows.
7271 if (g->zig_target.os == OsWindows) {7648 if (g->zig_target.os == OsWindows || g->zig_target.os == OsUefi) {
7272 target_specific_cpu_args = "";7649 target_specific_cpu_args = "";
7273 target_specific_features = "";7650 target_specific_features = "";
7274 } else {7651 } else {
...@@ -7434,9 +7811,9 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {...@@ -7434,9 +7811,9 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
7434 ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i];7811 ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i];
7435 this_val->special = ConstValSpecialStatic;7812 this_val->special = ConstValSpecialStatic;
7436 this_val->type = struct_type;7813 this_val->type = struct_type;
7437 this_val->data.x_struct.parent.id = ConstParentIdArray;7814 this_val->parent.id = ConstParentIdArray;
7438 this_val->data.x_struct.parent.data.p_array.array_val = test_fn_array;7815 this_val->parent.data.p_array.array_val = test_fn_array;
7439 this_val->data.x_struct.parent.data.p_array.elem_index = i;7816 this_val->parent.data.p_array.elem_index = i;
7440 this_val->data.x_struct.fields = create_const_vals(2);7817 this_val->data.x_struct.fields = create_const_vals(2);
74417818
7442 ConstExprValue *name_field = &this_val->data.x_struct.fields[0];7819 ConstExprValue *name_field = &this_val->data.x_struct.fields[0];
...@@ -7514,6 +7891,7 @@ static void gen_root_source(CodeGen *g) {...@@ -7514,6 +7891,7 @@ static void gen_root_source(CodeGen *g) {
7514 report_errors_and_maybe_exit(g);7891 report_errors_and_maybe_exit(g);
75157892
7516 if (!g->is_test_build && g->zig_target.os != OsFreestanding &&7893 if (!g->is_test_build && g->zig_target.os != OsFreestanding &&
7894 g->zig_target.os != OsUefi &&
7517 !g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup &&7895 !g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup &&
7518 ((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe))7896 ((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe))
7519 {7897 {
...@@ -7537,6 +7915,8 @@ static void gen_root_source(CodeGen *g) {...@@ -7537,6 +7915,8 @@ static void gen_root_source(CodeGen *g) {
7537 }7915 }
7538 }7916 }
75397917
7918 typecheck_panic_fn(g, g->panic_tld_fn, g->panic_fn);
7919
7540 report_errors_and_maybe_exit(g);7920 report_errors_and_maybe_exit(g);
75417921
7542}7922}
...@@ -7631,6 +8011,9 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e...@@ -7631,6 +8011,9 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e
7631 case ZigTypeIdArray:8011 case ZigTypeIdArray:
7632 prepend_c_type_to_decl_list(g, gen_h, type_entry->data.array.child_type);8012 prepend_c_type_to_decl_list(g, gen_h, type_entry->data.array.child_type);
7633 return;8013 return;
8014 case ZigTypeIdVector:
8015 prepend_c_type_to_decl_list(g, gen_h, type_entry->data.vector.elem_type);
8016 return;
7634 case ZigTypeIdOptional:8017 case ZigTypeIdOptional:
7635 prepend_c_type_to_decl_list(g, gen_h, type_entry->data.maybe.child_type);8018 prepend_c_type_to_decl_list(g, gen_h, type_entry->data.maybe.child_type);
7636 return;8019 return;
...@@ -7762,6 +8145,8 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu...@@ -7762,6 +8145,8 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu
7762 buf_appendf(out_buf, "%s", buf_ptr(child_buf));8145 buf_appendf(out_buf, "%s", buf_ptr(child_buf));
7763 return;8146 return;
7764 }8147 }
8148 case ZigTypeIdVector:
8149 zig_panic("TODO implement get_c_type for vector types");
7765 case ZigTypeIdErrorUnion:8150 case ZigTypeIdErrorUnion:
7766 case ZigTypeIdErrorSet:8151 case ZigTypeIdErrorSet:
7767 case ZigTypeIdFn:8152 case ZigTypeIdFn:
...@@ -7927,6 +8312,7 @@ static void gen_h_file(CodeGen *g) {...@@ -7927,6 +8312,7 @@ static void gen_h_file(CodeGen *g) {
7927 case ZigTypeIdOptional:8312 case ZigTypeIdOptional:
7928 case ZigTypeIdFn:8313 case ZigTypeIdFn:
7929 case ZigTypeIdPromise:8314 case ZigTypeIdPromise:
8315 case ZigTypeIdVector:
7930 zig_unreachable();8316 zig_unreachable();
7931 case ZigTypeIdEnum:8317 case ZigTypeIdEnum:
7932 if (type_entry->data.enumeration.layout == ContainerLayoutExtern) {8318 if (type_entry->data.enumeration.layout == ContainerLayoutExtern) {
...@@ -8033,8 +8419,12 @@ static void add_cache_pkg(CodeGen *g, CacheHash *ch, PackageTableEntry *pkg) {...@@ -8033,8 +8419,12 @@ static void add_cache_pkg(CodeGen *g, CacheHash *ch, PackageTableEntry *pkg) {
8033 if (!entry)8419 if (!entry)
8034 break;8420 break;
80358421
8036 cache_buf(ch, entry->key);8422 // TODO: I think we need a more sophisticated detection of
8037 add_cache_pkg(g, ch, entry->value);8423 // packages we have already seen
8424 if (entry->value != pkg) {
8425 cache_buf(ch, entry->key);
8426 add_cache_pkg(g, ch, entry->value);
8427 }
8038 }8428 }
8039}8429}
80408430
...@@ -8070,12 +8460,12 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {...@@ -8070,12 +8460,12 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
8070 cache_int(ch, g->zig_target.os);8460 cache_int(ch, g->zig_target.os);
8071 cache_int(ch, g->zig_target.env_type);8461 cache_int(ch, g->zig_target.env_type);
8072 cache_int(ch, g->zig_target.oformat);8462 cache_int(ch, g->zig_target.oformat);
8463 cache_int(ch, g->subsystem);
8073 cache_bool(ch, g->is_static);8464 cache_bool(ch, g->is_static);
8074 cache_bool(ch, g->strip_debug_symbols);8465 cache_bool(ch, g->strip_debug_symbols);
8075 cache_bool(ch, g->is_test_build);8466 cache_bool(ch, g->is_test_build);
8467 cache_bool(ch, g->is_single_threaded);
8076 cache_bool(ch, g->is_native_target);8468 cache_bool(ch, g->is_native_target);
8077 cache_bool(ch, g->windows_subsystem_windows);
8078 cache_bool(ch, g->windows_subsystem_console);
8079 cache_bool(ch, g->linker_rdynamic);8469 cache_bool(ch, g->linker_rdynamic);
8080 cache_bool(ch, g->no_rosegment_workaround);8470 cache_bool(ch, g->no_rosegment_workaround);
8081 cache_bool(ch, g->each_lib_rpath);8471 cache_bool(ch, g->each_lib_rpath);
src/codegen.hpp+1-2
...@@ -15,7 +15,7 @@...@@ -15,7 +15,7 @@
15#include <stdio.h>15#include <stdio.h>
1616
17CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,17CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,
18 Buf *zig_lib_dir);18 Buf *zig_lib_dir, Buf *override_std_dir);
1919
20void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);20void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
21void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);21void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);
...@@ -33,7 +33,6 @@ void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir);...@@ -33,7 +33,6 @@ void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir);
33void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir);33void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir);
34void codegen_set_kernel32_lib_dir(CodeGen *codegen, Buf *kernel32_lib_dir);34void codegen_set_kernel32_lib_dir(CodeGen *codegen, Buf *kernel32_lib_dir);
35void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker);35void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker);
36void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole);
37void codegen_add_lib_dir(CodeGen *codegen, const char *dir);36void codegen_add_lib_dir(CodeGen *codegen, const char *dir);
38void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib);37void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib);
39LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib);38LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib);
src/ir.cpp+2127-1051
...@@ -61,7 +61,7 @@ enum ConstCastResultId {...@@ -61,7 +61,7 @@ enum ConstCastResultId {
61 ConstCastResultIdType,61 ConstCastResultIdType,
62 ConstCastResultIdUnresolvedInferredErrSet,62 ConstCastResultIdUnresolvedInferredErrSet,
63 ConstCastResultIdAsyncAllocatorType,63 ConstCastResultIdAsyncAllocatorType,
64 ConstCastResultIdNullWrapPtr64 ConstCastResultIdBadAllowsZero,
65};65};
6666
67struct ConstCastOnly;67struct ConstCastOnly;
...@@ -83,6 +83,7 @@ struct ConstCastErrUnionErrSetMismatch;...@@ -83,6 +83,7 @@ struct ConstCastErrUnionErrSetMismatch;
83struct ConstCastErrUnionPayloadMismatch;83struct ConstCastErrUnionPayloadMismatch;
84struct ConstCastErrSetMismatch;84struct ConstCastErrSetMismatch;
85struct ConstCastTypeMismatch;85struct ConstCastTypeMismatch;
86struct ConstCastBadAllowsZero;
8687
87struct ConstCastOnly {88struct ConstCastOnly {
88 ConstCastResultId id;89 ConstCastResultId id;
...@@ -99,6 +100,7 @@ struct ConstCastOnly {...@@ -99,6 +100,7 @@ struct ConstCastOnly {
99 ConstCastOnly *null_wrap_ptr_child;100 ConstCastOnly *null_wrap_ptr_child;
100 ConstCastArg fn_arg;101 ConstCastArg fn_arg;
101 ConstCastArgNoAlias arg_no_alias;102 ConstCastArgNoAlias arg_no_alias;
103 ConstCastBadAllowsZero *bad_allows_zero;
102 } data;104 } data;
103};105};
104106
...@@ -141,6 +143,12 @@ struct ConstCastErrSetMismatch {...@@ -141,6 +143,12 @@ struct ConstCastErrSetMismatch {
141 ZigList<ErrorTableEntry *> missing_errors;143 ZigList<ErrorTableEntry *> missing_errors;
142};144};
143145
146struct ConstCastBadAllowsZero {
147 ZigType *wanted_type;
148 ZigType *actual_type;
149};
150
151
144enum UndefAllowed {152enum UndefAllowed {
145 UndefOk,153 UndefOk,
146 UndefBad,154 UndefBad,
...@@ -159,13 +167,20 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op...@@ -159,13 +167,20 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op
159static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval);167static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval);
160static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);168static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);
161static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);169static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align);
162static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);170static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val);
163static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);171static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val);
164static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,172static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
165 ConstExprValue *out_val, ConstExprValue *ptr_val);173 ConstExprValue *out_val, ConstExprValue *ptr_val);
166static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,174static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,
167 ZigType *dest_type, IrInstruction *dest_type_src);175 ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on);
168static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);176static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
177static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
178static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
179static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry);
180static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
181 ZigType *ptr_type);
182static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
183 ZigType *dest_type);
169184
170static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {185static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
171 assert(get_src_ptr_type(const_val->type) != nullptr);186 assert(get_src_ptr_type(const_val->type) != nullptr);
...@@ -177,15 +192,28 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c...@@ -177,15 +192,28 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
177 case ConstPtrSpecialRef:192 case ConstPtrSpecialRef:
178 result = const_val->data.x_ptr.data.ref.pointee;193 result = const_val->data.x_ptr.data.ref.pointee;
179 break;194 break;
180 case ConstPtrSpecialBaseArray:195 case ConstPtrSpecialBaseArray: {
181 expand_undef_array(g, const_val->data.x_ptr.data.base_array.array_val);196 ConstExprValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
182 result = &const_val->data.x_ptr.data.base_array.array_val->data.x_array.data.s_none.elements[197 expand_undef_array(g, array_val);
183 const_val->data.x_ptr.data.base_array.elem_index];198 result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];
184 break;199 break;
200 }
185 case ConstPtrSpecialBaseStruct:201 case ConstPtrSpecialBaseStruct:
186 result = &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[202 result = &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[
187 const_val->data.x_ptr.data.base_struct.field_index];203 const_val->data.x_ptr.data.base_struct.field_index];
188 break;204 break;
205 case ConstPtrSpecialBaseErrorUnionCode:
206 result = const_val->data.x_ptr.data.base_err_union_code.err_union_val->data.x_err_union.error_set;
207 break;
208 case ConstPtrSpecialBaseErrorUnionPayload:
209 result = const_val->data.x_ptr.data.base_err_union_payload.err_union_val->data.x_err_union.payload;
210 break;
211 case ConstPtrSpecialBaseOptionalPayload:
212 result = const_val->data.x_ptr.data.base_optional_payload.optional_val->data.x_optional;
213 break;
214 case ConstPtrSpecialNull:
215 result = const_val;
216 break;
189 case ConstPtrSpecialHardCodedAddr:217 case ConstPtrSpecialHardCodedAddr:
190 zig_unreachable();218 zig_unreachable();
191 case ConstPtrSpecialDiscard:219 case ConstPtrSpecialDiscard:
...@@ -197,6 +225,11 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c...@@ -197,6 +225,11 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
197 return result;225 return result;
198}226}
199227
228static bool is_opt_err_set(ZigType *ty) {
229 return ty->id == ZigTypeIdErrorSet ||
230 (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);
231}
232
200static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {233static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
201 if (a == b)234 if (a == b)
202 return true;235 return true;
...@@ -207,15 +240,10 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {...@@ -207,15 +240,10 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
207 if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr)240 if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr)
208 return true;241 return true;
209242
210 return false;243 if (is_opt_err_set(a) && is_opt_err_set(b))
211}244 return true;
212245
213ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {246 return false;
214 ConstExprValue *result = const_ptr_pointee_unchecked(g, const_val);
215 if (const_val->type->id == ZigTypeIdPointer) {
216 assert(types_have_same_zig_comptime_repr(const_val->type->data.pointer.child_type, result->type));
217 }
218 return result;
219}247}
220248
221static bool ir_should_inline(IrExecutable *exec, Scope *scope) {249static bool ir_should_inline(IrExecutable *exec, Scope *scope) {
...@@ -304,6 +332,14 @@ static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) {...@@ -304,6 +332,14 @@ static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) {
304 return new_bb;332 return new_bb;
305}333}
306334
335static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVarSrc *) {
336 return IrInstructionIdDeclVarSrc;
337}
338
339static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVarGen *) {
340 return IrInstructionIdDeclVarGen;
341}
342
307static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) {343static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) {
308 return IrInstructionIdCondBr;344 return IrInstructionIdCondBr;
309}345}
...@@ -336,10 +372,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) {...@@ -336,10 +372,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) {
336 return IrInstructionIdBinOp;372 return IrInstructionIdBinOp;
337}373}
338374
339static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVar *) {
340 return IrInstructionIdDeclVar;
341}
342
343static constexpr IrInstructionId ir_instruction_id(IrInstructionExport *) {375static constexpr IrInstructionId ir_instruction_id(IrInstructionExport *) {
344 return IrInstructionIdExport;376 return IrInstructionIdExport;
345}377}
...@@ -448,8 +480,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestNonNull *) {...@@ -448,8 +480,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestNonNull *) {
448 return IrInstructionIdTestNonNull;480 return IrInstructionIdTestNonNull;
449}481}
450482
451static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapOptional *) {483static constexpr IrInstructionId ir_instruction_id(IrInstructionOptionalUnwrapPtr *) {
452 return IrInstructionIdUnwrapOptional;484 return IrInstructionIdOptionalUnwrapPtr;
453}485}
454486
455static constexpr IrInstructionId ir_instruction_id(IrInstructionClz *) {487static constexpr IrInstructionId ir_instruction_id(IrInstructionClz *) {
...@@ -516,8 +548,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) {...@@ -516,8 +548,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) {
516 return IrInstructionIdEmbedFile;548 return IrInstructionIdEmbedFile;
517}549}
518550
519static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchg *) {551static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgSrc *) {
520 return IrInstructionIdCmpxchg;552 return IrInstructionIdCmpxchgSrc;
553}
554
555static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgGen *) {
556 return IrInstructionIdCmpxchgGen;
521}557}
522558
523static constexpr IrInstructionId ir_instruction_id(IrInstructionFence *) {559static constexpr IrInstructionId ir_instruction_id(IrInstructionFence *) {
...@@ -564,6 +600,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionIntType *) {...@@ -564,6 +600,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionIntType *) {
564 return IrInstructionIdIntType;600 return IrInstructionIdIntType;
565}601}
566602
603static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorType *) {
604 return IrInstructionIdVectorType;
605}
606
567static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) {607static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) {
568 return IrInstructionIdBoolNot;608 return IrInstructionIdBoolNot;
569}609}
...@@ -648,8 +688,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *)...@@ -648,8 +688,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *)
648 return IrInstructionIdTestComptime;688 return IrInstructionIdTestComptime;
649}689}
650690
651static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) {691static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastSrc *) {
652 return IrInstructionIdPtrCast;692 return IrInstructionIdPtrCastSrc;
693}
694
695static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastGen *) {
696 return IrInstructionIdPtrCastGen;
653}697}
654698
655static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {699static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {
...@@ -856,10 +900,30 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) {...@@ -856,10 +900,30 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) {
856 return IrInstructionIdSqrt;900 return IrInstructionIdSqrt;
857}901}
858902
903static constexpr IrInstructionId ir_instruction_id(IrInstructionBswap *) {
904 return IrInstructionIdBswap;
905}
906
907static constexpr IrInstructionId ir_instruction_id(IrInstructionBitReverse *) {
908 return IrInstructionIdBitReverse;
909}
910
859static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) {911static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) {
860 return IrInstructionIdCheckRuntimeScope;912 return IrInstructionIdCheckRuntimeScope;
861}913}
862914
915static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorToArray *) {
916 return IrInstructionIdVectorToArray;
917}
918
919static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayToVector *) {
920 return IrInstructionIdArrayToVector;
921}
922
923static constexpr IrInstructionId ir_instruction_id(IrInstructionAssertZero *) {
924 return IrInstructionIdAssertZero;
925}
926
863template<typename T>927template<typename T>
864static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {928static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
865 T *special_instruction = allocate<T>(1);929 T *special_instruction = allocate<T>(1);
...@@ -906,7 +970,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so...@@ -906,7 +970,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so
906 ir_ref_instruction(condition, irb->current_basic_block);970 ir_ref_instruction(condition, irb->current_basic_block);
907 ir_ref_bb(then_block);971 ir_ref_bb(then_block);
908 ir_ref_bb(else_block);972 ir_ref_bb(else_block);
909 if (is_comptime) ir_ref_instruction(is_comptime, irb->current_basic_block);973 if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block);
910974
911 return &cond_br_instruction->base;975 return &cond_br_instruction->base;
912}976}
...@@ -922,16 +986,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou...@@ -922,16 +986,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou
922 return &return_instruction->base;986 return &return_instruction->base;
923}987}
924988
925static IrInstruction *ir_create_const(IrBuilder *irb, Scope *scope, AstNode *source_node,
926 ZigType *type_entry)
927{
928 assert(type_entry);
929 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb, scope, source_node);
930 const_instruction->base.value.type = type_entry;
931 const_instruction->base.value.special = ConstValSpecialStatic;
932 return &const_instruction->base;
933}
934
935static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) {989static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) {
936 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);990 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
937 const_instruction->base.value.type = irb->codegen->builtin_types.entry_void;991 const_instruction->base.value.type = irb->codegen->builtin_types.entry_void;
...@@ -1179,14 +1233,11 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc...@@ -1179,14 +1233,11 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc
1179 call_instruction->async_allocator = async_allocator;1233 call_instruction->async_allocator = async_allocator;
1180 call_instruction->new_stack = new_stack;1234 call_instruction->new_stack = new_stack;
11811235
1182 if (fn_ref)1236 if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block);
1183 ir_ref_instruction(fn_ref, irb->current_basic_block);
1184 for (size_t i = 0; i < arg_count; i += 1)1237 for (size_t i = 0; i < arg_count; i += 1)
1185 ir_ref_instruction(args[i], irb->current_basic_block);1238 ir_ref_instruction(args[i], irb->current_basic_block);
1186 if (async_allocator)1239 if (async_allocator != nullptr) ir_ref_instruction(async_allocator, irb->current_basic_block);
1187 ir_ref_instruction(async_allocator, irb->current_basic_block);1240 if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block);
1188 if (new_stack != nullptr)
1189 ir_ref_instruction(new_stack, irb->current_basic_block);
11901241
1191 return &call_instruction->base;1242 return &call_instruction->base;
1192}1243}
...@@ -1271,7 +1322,7 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope,...@@ -1271,7 +1322,7 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope,
1271 container_init_list_instruction->item_count = item_count;1322 container_init_list_instruction->item_count = item_count;
1272 container_init_list_instruction->items = items;1323 container_init_list_instruction->items = items;
12731324
1274 ir_ref_instruction(container_type, irb->current_basic_block);1325 if (container_type != nullptr) ir_ref_instruction(container_type, irb->current_basic_block);
1275 for (size_t i = 0; i < item_count; i += 1) {1326 for (size_t i = 0; i < item_count; i += 1) {
1276 ir_ref_instruction(items[i], irb->current_basic_block);1327 ir_ref_instruction(items[i], irb->current_basic_block);
1277 }1328 }
...@@ -1346,10 +1397,10 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *...@@ -1346,10 +1397,10 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *
1346 return &instruction->base;1397 return &instruction->base;
1347}1398}
13481399
1349static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *source_node,1400static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
1350 ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value)1401 ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value)
1351{1402{
1352 IrInstructionDeclVar *decl_var_instruction = ir_build_instruction<IrInstructionDeclVar>(irb, scope, source_node);1403 IrInstructionDeclVarSrc *decl_var_instruction = ir_build_instruction<IrInstructionDeclVarSrc>(irb, scope, source_node);
1353 decl_var_instruction->base.value.special = ConstValSpecialStatic;1404 decl_var_instruction->base.value.special = ConstValSpecialStatic;
1354 decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void;1405 decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void;
1355 decl_var_instruction->var = var;1406 decl_var_instruction->var = var;
...@@ -1357,13 +1408,28 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1357,13 +1408,28 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *s
1357 decl_var_instruction->align_value = align_value;1408 decl_var_instruction->align_value = align_value;
1358 decl_var_instruction->init_value = init_value;1409 decl_var_instruction->init_value = init_value;
13591410
1360 if (var_type) ir_ref_instruction(var_type, irb->current_basic_block);1411 if (var_type != nullptr) ir_ref_instruction(var_type, irb->current_basic_block);
1361 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);1412 if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block);
1362 ir_ref_instruction(init_value, irb->current_basic_block);1413 ir_ref_instruction(init_value, irb->current_basic_block);
13631414
1364 return &decl_var_instruction->base;1415 return &decl_var_instruction->base;
1365}1416}
13661417
1418static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *source_instruction,
1419 ZigVar *var, IrInstruction *init_value)
1420{
1421 IrInstructionDeclVarGen *decl_var_instruction = ir_build_instruction<IrInstructionDeclVarGen>(&ira->new_irb,
1422 source_instruction->scope, source_instruction->source_node);
1423 decl_var_instruction->base.value.special = ConstValSpecialStatic;
1424 decl_var_instruction->base.value.type = ira->codegen->builtin_types.entry_void;
1425 decl_var_instruction->var = var;
1426 decl_var_instruction->init_value = init_value;
1427
1428 ir_ref_instruction(init_value, ira->new_irb.current_basic_block);
1429
1430 return &decl_var_instruction->base;
1431}
1432
1367static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node,1433static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node,
1368 IrInstruction *name, IrInstruction *target, IrInstruction *linkage)1434 IrInstruction *name, IrInstruction *target, IrInstruction *linkage)
1369{1435{
...@@ -1533,14 +1599,14 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod...@@ -1533,14 +1599,14 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod
1533 return &instruction->base;1599 return &instruction->base;
1534}1600}
15351601
1536static IrInstruction *ir_build_unwrap_maybe(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value,1602static IrInstruction *ir_build_optional_unwrap_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
1537 bool safety_check_on)1603 IrInstruction *base_ptr, bool safety_check_on)
1538{1604{
1539 IrInstructionUnwrapOptional *instruction = ir_build_instruction<IrInstructionUnwrapOptional>(irb, scope, source_node);1605 IrInstructionOptionalUnwrapPtr *instruction = ir_build_instruction<IrInstructionOptionalUnwrapPtr>(irb, scope, source_node);
1540 instruction->value = value;1606 instruction->base_ptr = base_ptr;
1541 instruction->safety_check_on = safety_check_on;1607 instruction->safety_check_on = safety_check_on;
15421608
1543 ir_ref_instruction(value, irb->current_basic_block);1609 ir_ref_instruction(base_ptr, irb->current_basic_block);
15441610
1545 return &instruction->base;1611 return &instruction->base;
1546}1612}
...@@ -1756,13 +1822,12 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode...@@ -1756,13 +1822,12 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode
1756 return &instruction->base;1822 return &instruction->base;
1757}1823}
17581824
1759static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value,1825static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
1760 IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,1826 IrInstruction *type_value, IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
1761 IrInstruction *success_order_value, IrInstruction *failure_order_value,1827 IrInstruction *success_order_value, IrInstruction *failure_order_value,
1762 bool is_weak,1828 bool is_weak)
1763 ZigType *type, AtomicOrder success_order, AtomicOrder failure_order)
1764{1829{
1765 IrInstructionCmpxchg *instruction = ir_build_instruction<IrInstructionCmpxchg>(irb, scope, source_node);1830 IrInstructionCmpxchgSrc *instruction = ir_build_instruction<IrInstructionCmpxchgSrc>(irb, scope, source_node);
1766 instruction->type_value = type_value;1831 instruction->type_value = type_value;
1767 instruction->ptr = ptr;1832 instruction->ptr = ptr;
1768 instruction->cmp_value = cmp_value;1833 instruction->cmp_value = cmp_value;
...@@ -1770,16 +1835,33 @@ static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *so...@@ -1770,16 +1835,33 @@ static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *so
1770 instruction->success_order_value = success_order_value;1835 instruction->success_order_value = success_order_value;
1771 instruction->failure_order_value = failure_order_value;1836 instruction->failure_order_value = failure_order_value;
1772 instruction->is_weak = is_weak;1837 instruction->is_weak = is_weak;
1773 instruction->type = type;
1774 instruction->success_order = success_order;
1775 instruction->failure_order = failure_order;
17761838
1777 if (type_value != nullptr) ir_ref_instruction(type_value, irb->current_basic_block);1839 ir_ref_instruction(type_value, irb->current_basic_block);
1778 ir_ref_instruction(ptr, irb->current_basic_block);1840 ir_ref_instruction(ptr, irb->current_basic_block);
1779 ir_ref_instruction(cmp_value, irb->current_basic_block);1841 ir_ref_instruction(cmp_value, irb->current_basic_block);
1780 ir_ref_instruction(new_value, irb->current_basic_block);1842 ir_ref_instruction(new_value, irb->current_basic_block);
1781 if (type_value != nullptr) ir_ref_instruction(success_order_value, irb->current_basic_block);1843 ir_ref_instruction(success_order_value, irb->current_basic_block);
1782 if (type_value != nullptr) ir_ref_instruction(failure_order_value, irb->current_basic_block);1844 ir_ref_instruction(failure_order_value, irb->current_basic_block);
1845
1846 return &instruction->base;
1847}
1848
1849static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction,
1850 IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
1851 AtomicOrder success_order, AtomicOrder failure_order, bool is_weak)
1852{
1853 IrInstructionCmpxchgGen *instruction = ir_build_instruction<IrInstructionCmpxchgGen>(&ira->new_irb,
1854 source_instruction->scope, source_instruction->source_node);
1855 instruction->ptr = ptr;
1856 instruction->cmp_value = cmp_value;
1857 instruction->new_value = new_value;
1858 instruction->success_order = success_order;
1859 instruction->failure_order = failure_order;
1860 instruction->is_weak = is_weak;
1861
1862 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
1863 ir_ref_instruction(cmp_value, ira->new_irb.current_basic_block);
1864 ir_ref_instruction(new_value, ira->new_irb.current_basic_block);
17831865
1784 return &instruction->base;1866 return &instruction->base;
1785}1867}
...@@ -1900,6 +1982,19 @@ static IrInstruction *ir_build_int_type(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1900,6 +1982,19 @@ static IrInstruction *ir_build_int_type(IrBuilder *irb, Scope *scope, AstNode *s
1900 return &instruction->base;1982 return &instruction->base;
1901}1983}
19021984
1985static IrInstruction *ir_build_vector_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *len,
1986 IrInstruction *elem_type)
1987{
1988 IrInstructionVectorType *instruction = ir_build_instruction<IrInstructionVectorType>(irb, scope, source_node);
1989 instruction->len = len;
1990 instruction->elem_type = elem_type;
1991
1992 ir_ref_instruction(len, irb->current_basic_block);
1993 ir_ref_instruction(elem_type, irb->current_basic_block);
1994
1995 return &instruction->base;
1996}
1997
1903static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {1998static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
1904 IrInstructionBoolNot *instruction = ir_build_instruction<IrInstructionBoolNot>(irb, scope, source_node);1999 IrInstructionBoolNot *instruction = ir_build_instruction<IrInstructionBoolNot>(irb, scope, source_node);
1905 instruction->value = value;2000 instruction->value = value;
...@@ -2051,12 +2146,12 @@ static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *s...@@ -2051,12 +2146,12 @@ static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *s
2051}2146}
20522147
2053static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node,2148static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node,
2054 IrInstruction *value)2149 IrInstruction *err_union)
2055{2150{
2056 IrInstructionUnwrapErrCode *instruction = ir_build_instruction<IrInstructionUnwrapErrCode>(irb, scope, source_node);2151 IrInstructionUnwrapErrCode *instruction = ir_build_instruction<IrInstructionUnwrapErrCode>(irb, scope, source_node);
2057 instruction->value = value;2152 instruction->err_union = err_union;
20582153
2059 ir_ref_instruction(value, irb->current_basic_block);2154 ir_ref_instruction(err_union, irb->current_basic_block);
20602155
2061 return &instruction->base;2156 return &instruction->base;
2062}2157}
...@@ -2106,20 +2201,35 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo...@@ -2106,20 +2201,35 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo
2106 return &instruction->base;2201 return &instruction->base;
2107}2202}
21082203
2109static IrInstruction *ir_build_ptr_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,2204static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
2110 IrInstruction *dest_type, IrInstruction *ptr)2205 IrInstruction *dest_type, IrInstruction *ptr, bool safety_check_on)
2111{2206{
2112 IrInstructionPtrCast *instruction = ir_build_instruction<IrInstructionPtrCast>(2207 IrInstructionPtrCastSrc *instruction = ir_build_instruction<IrInstructionPtrCastSrc>(
2113 irb, scope, source_node);2208 irb, scope, source_node);
2114 instruction->dest_type = dest_type;2209 instruction->dest_type = dest_type;
2115 instruction->ptr = ptr;2210 instruction->ptr = ptr;
2211 instruction->safety_check_on = safety_check_on;
21162212
2117 if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block);2213 ir_ref_instruction(dest_type, irb->current_basic_block);
2118 ir_ref_instruction(ptr, irb->current_basic_block);2214 ir_ref_instruction(ptr, irb->current_basic_block);
21192215
2120 return &instruction->base;2216 return &instruction->base;
2121}2217}
21222218
2219static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction,
2220 ZigType *ptr_type, IrInstruction *ptr, bool safety_check_on)
2221{
2222 IrInstructionPtrCastGen *instruction = ir_build_instruction<IrInstructionPtrCastGen>(
2223 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
2224 instruction->base.value.type = ptr_type;
2225 instruction->ptr = ptr;
2226 instruction->safety_check_on = safety_check_on;
2227
2228 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
2229
2230 return &instruction->base;
2231}
2232
2123static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,2233static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
2124 IrInstruction *dest_type, IrInstruction *value)2234 IrInstruction *dest_type, IrInstruction *value)
2125{2235{
...@@ -2362,7 +2472,7 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *...@@ -2362,7 +2472,7 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *
23622472
2363 ir_ref_instruction(type_value, irb->current_basic_block);2473 ir_ref_instruction(type_value, irb->current_basic_block);
23642474
2365 return &instruction->base; 2475 return &instruction->base;
2366}2476}
23672477
2368static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node,2478static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node,
...@@ -2705,6 +2815,28 @@ static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *sourc...@@ -2705,6 +2815,28 @@ static IrInstruction *ir_build_sqrt(IrBuilder *irb, Scope *scope, AstNode *sourc
2705 return &instruction->base;2815 return &instruction->base;
2706}2816}
27072817
2818static IrInstruction *ir_build_bswap(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) {
2819 IrInstructionBswap *instruction = ir_build_instruction<IrInstructionBswap>(irb, scope, source_node);
2820 instruction->type = type;
2821 instruction->op = op;
2822
2823 if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
2824 ir_ref_instruction(op, irb->current_basic_block);
2825
2826 return &instruction->base;
2827}
2828
2829static IrInstruction *ir_build_bit_reverse(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type, IrInstruction *op) {
2830 IrInstructionBitReverse *instruction = ir_build_instruction<IrInstructionBitReverse>(irb, scope, source_node);
2831 instruction->type = type;
2832 instruction->op = op;
2833
2834 if (type != nullptr) ir_ref_instruction(type, irb->current_basic_block);
2835 ir_ref_instruction(op, irb->current_basic_block);
2836
2837 return &instruction->base;
2838}
2839
2708static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) {2840static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) {
2709 IrInstructionCheckRuntimeScope *instruction = ir_build_instruction<IrInstructionCheckRuntimeScope>(irb, scope, source_node);2841 IrInstructionCheckRuntimeScope *instruction = ir_build_instruction<IrInstructionCheckRuntimeScope>(irb, scope, source_node);
2710 instruction->scope_is_comptime = scope_is_comptime;2842 instruction->scope_is_comptime = scope_is_comptime;
...@@ -2716,6 +2848,47 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope,...@@ -2716,6 +2848,47 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope,
2716 return &instruction->base;2848 return &instruction->base;
2717}2849}
27182850
2851static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *source_instruction,
2852 IrInstruction *vector, ZigType *result_type)
2853{
2854 IrInstructionVectorToArray *instruction = ir_build_instruction<IrInstructionVectorToArray>(&ira->new_irb,
2855 source_instruction->scope, source_instruction->source_node);
2856 instruction->base.value.type = result_type;
2857 instruction->vector = vector;
2858
2859 ir_ref_instruction(vector, ira->new_irb.current_basic_block);
2860
2861 ir_add_alloca(ira, &instruction->base, result_type);
2862
2863 return &instruction->base;
2864}
2865
2866static IrInstruction *ir_build_array_to_vector(IrAnalyze *ira, IrInstruction *source_instruction,
2867 IrInstruction *array, ZigType *result_type)
2868{
2869 IrInstructionArrayToVector *instruction = ir_build_instruction<IrInstructionArrayToVector>(&ira->new_irb,
2870 source_instruction->scope, source_instruction->source_node);
2871 instruction->base.value.type = result_type;
2872 instruction->array = array;
2873
2874 ir_ref_instruction(array, ira->new_irb.current_basic_block);
2875
2876 return &instruction->base;
2877}
2878
2879static IrInstruction *ir_build_assert_zero(IrAnalyze *ira, IrInstruction *source_instruction,
2880 IrInstruction *target)
2881{
2882 IrInstructionAssertZero *instruction = ir_build_instruction<IrInstructionAssertZero>(&ira->new_irb,
2883 source_instruction->scope, source_instruction->source_node);
2884 instruction->base.value.type = ira->codegen->builtin_types.entry_void;
2885 instruction->target = target;
2886
2887 ir_ref_instruction(target, ira->new_irb.current_basic_block);
2888
2889 return &instruction->base;
2890}
2891
2719static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {2892static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
2720 results[ReturnKindUnconditional] = 0;2893 results[ReturnKindUnconditional] = 0;
2721 results[ReturnKindError] = 0;2894 results[ReturnKindError] = 0;
...@@ -2776,10 +2949,13 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o...@@ -2776,10 +2949,13 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o
2776 Scope *defer_expr_scope = defer_node->data.defer.expr_scope;2949 Scope *defer_expr_scope = defer_node->data.defer.expr_scope;
2777 IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);2950 IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);
2778 if (defer_expr_value != irb->codegen->invalid_instruction) {2951 if (defer_expr_value != irb->codegen->invalid_instruction) {
2779 if (defer_expr_value->value.type != nullptr && defer_expr_value->value.type->id == ZigTypeIdUnreachable) {2952 if (defer_expr_value->value.type != nullptr &&
2953 defer_expr_value->value.type->id == ZigTypeIdUnreachable)
2954 {
2780 is_noreturn = true;2955 is_noreturn = true;
2781 } else {2956 } else {
2782 ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, defer_expr_value));2957 ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node,
2958 defer_expr_value));
2783 }2959 }
2784 }2960 }
2785 }2961 }
...@@ -3034,7 +3210,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s...@@ -3034,7 +3210,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
3034 variable_entry->mem_slot_index = SIZE_MAX;3210 variable_entry->mem_slot_index = SIZE_MAX;
3035 variable_entry->is_comptime = is_comptime;3211 variable_entry->is_comptime = is_comptime;
3036 variable_entry->src_arg_index = SIZE_MAX;3212 variable_entry->src_arg_index = SIZE_MAX;
3037 variable_entry->value = create_const_vals(1);3213 variable_entry->const_value = create_const_vals(1);
30383214
3039 if (is_comptime != nullptr) {3215 if (is_comptime != nullptr) {
3040 is_comptime->ref_count += 1;3216 is_comptime->ref_count += 1;
...@@ -3049,20 +3225,20 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s...@@ -3049,20 +3225,20 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
3049 ErrorMsg *msg = add_node_error(codegen, node,3225 ErrorMsg *msg = add_node_error(codegen, node,
3050 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));3226 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
3051 add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));3227 add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
3052 variable_entry->value->type = codegen->builtin_types.entry_invalid;3228 variable_entry->var_type = codegen->builtin_types.entry_invalid;
3053 } else {3229 } else {
3054 ZigType *type;3230 ZigType *type;
3055 if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) {3231 if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) {
3056 add_node_error(codegen, node,3232 add_node_error(codegen, node,
3057 buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));3233 buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));
3058 variable_entry->value->type = codegen->builtin_types.entry_invalid;3234 variable_entry->var_type = codegen->builtin_types.entry_invalid;
3059 } else {3235 } else {
3060 Tld *tld = find_decl(codegen, parent_scope, name);3236 Tld *tld = find_decl(codegen, parent_scope, name);
3061 if (tld != nullptr) {3237 if (tld != nullptr) {
3062 ErrorMsg *msg = add_node_error(codegen, node,3238 ErrorMsg *msg = add_node_error(codegen, node,
3063 buf_sprintf("redefinition of '%s'", buf_ptr(name)));3239 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
3064 add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here"));3240 add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here"));
3065 variable_entry->value->type = codegen->builtin_types.entry_invalid;3241 variable_entry->var_type = codegen->builtin_types.entry_invalid;
3066 }3242 }
3067 }3243 }
3068 }3244 }
...@@ -3125,7 +3301,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3125,7 +3301,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
3125 scope_block->incoming_blocks = &incoming_blocks;3301 scope_block->incoming_blocks = &incoming_blocks;
3126 scope_block->incoming_values = &incoming_values;3302 scope_block->incoming_values = &incoming_values;
3127 scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd");3303 scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd");
3128 scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, ir_should_inline(irb->exec, parent_scope));3304 scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node,
3305 ir_should_inline(irb->exec, parent_scope));
3129 }3306 }
31303307
3131 bool is_continuation_unreachable = false;3308 bool is_continuation_unreachable = false;
...@@ -3143,9 +3320,9 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3143,9 +3320,9 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
3143 // defer starts a new scope3320 // defer starts a new scope
3144 child_scope = statement_node->data.defer.child_scope;3321 child_scope = statement_node->data.defer.child_scope;
3145 assert(child_scope);3322 assert(child_scope);
3146 } else if (statement_value->id == IrInstructionIdDeclVar) {3323 } else if (statement_value->id == IrInstructionIdDeclVarSrc) {
3147 // variable declarations start a new scope3324 // variable declarations start a new scope
3148 IrInstructionDeclVar *decl_var_instruction = (IrInstructionDeclVar *)statement_value;3325 IrInstructionDeclVarSrc *decl_var_instruction = (IrInstructionDeclVarSrc *)statement_value;
3149 child_scope = decl_var_instruction->var->child_scope;3326 child_scope = decl_var_instruction->var->child_scope;
3150 } else if (statement_value != irb->codegen->invalid_instruction && !is_continuation_unreachable) {3327 } else if (statement_value != irb->codegen->invalid_instruction && !is_continuation_unreachable) {
3151 // this statement's value must be void3328 // this statement's value must be void
...@@ -3300,7 +3477,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -3300,7 +3477,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod
3300 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);3477 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
3301}3478}
33023479
3303static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) {3480static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
3304 assert(node->type == NodeTypeBinOpExpr);3481 assert(node->type == NodeTypeBinOpExpr);
33053482
3306 AstNode *op1_node = node->data.bin_op_expr.op1;3483 AstNode *op1_node = node->data.bin_op_expr.op1;
...@@ -3334,7 +3511,7 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As...@@ -3334,7 +3511,7 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As
3334 ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));3511 ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));
33353512
3336 ir_set_cursor_at_end_and_append_block(irb, ok_block);3513 ir_set_cursor_at_end_and_append_block(irb, ok_block);
3337 IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, parent_scope, node, maybe_ptr, false);3514 IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false);
3338 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);3515 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
3339 IrBasicBlock *after_ok_block = irb->current_basic_block;3516 IrBasicBlock *after_ok_block = irb->current_basic_block;
3340 ir_build_br(irb, parent_scope, node, end_block, is_comptime);3517 ir_build_br(irb, parent_scope, node, end_block, is_comptime);
...@@ -3452,7 +3629,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -3452,7 +3629,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node)
3452 case BinOpTypeMergeErrorSets:3629 case BinOpTypeMergeErrorSets:
3453 return ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets);3630 return ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets);
3454 case BinOpTypeUnwrapOptional:3631 case BinOpTypeUnwrapOptional:
3455 return ir_gen_maybe_ok_or(irb, scope, node);3632 return ir_gen_orelse(irb, scope, node);
3456 case BinOpTypeErrorUnion:3633 case BinOpTypeErrorUnion:
3457 return ir_gen_error_union(irb, scope, node);3634 return ir_gen_error_union(irb, scope, node);
3458 }3635 }
...@@ -3511,6 +3688,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3511,6 +3688,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
3511 buf_ptr(variable_name)));3688 buf_ptr(variable_name)));
3512 return irb->codegen->invalid_instruction;3689 return irb->codegen->invalid_instruction;
3513 }3690 }
3691 assert(err == ErrorPrimitiveTypeNotFound);
3514 } else {3692 } else {
3515 IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_type);3693 IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_type);
3516 if (lval == LValPtr) {3694 if (lval == LValPtr) {
...@@ -3630,7 +3808,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -3630,7 +3808,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
3630 Buf *name = fn_ref_expr->data.symbol_expr.symbol;3808 Buf *name = fn_ref_expr->data.symbol_expr.symbol;
3631 auto entry = irb->codegen->builtin_fn_table.maybe_get(name);3809 auto entry = irb->codegen->builtin_fn_table.maybe_get(name);
36323810
3633 if (!entry) {3811 if (!entry) { // new built in not found
3634 add_node_error(irb->codegen, node,3812 add_node_error(irb->codegen, node,
3635 buf_sprintf("invalid builtin function: '%s'", buf_ptr(name)));3813 buf_sprintf("invalid builtin function: '%s'", buf_ptr(name)));
3636 return irb->codegen->invalid_instruction;3814 return irb->codegen->invalid_instruction;
...@@ -3873,9 +4051,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -3873,9 +4051,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
3873 if (arg5_value == irb->codegen->invalid_instruction)4051 if (arg5_value == irb->codegen->invalid_instruction)
3874 return arg5_value;4052 return arg5_value;
38754053
3876 IrInstruction *cmpxchg = ir_build_cmpxchg(irb, scope, node, arg0_value, arg1_value,4054 IrInstruction *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value,
3877 arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak),4055 arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak));
3878 nullptr, AtomicOrderUnordered, AtomicOrderUnordered);
3879 return ir_lval_wrap(irb, scope, cmpxchg, lval);4056 return ir_lval_wrap(irb, scope, cmpxchg, lval);
3880 }4057 }
3881 case BuiltinFnIdFence:4058 case BuiltinFnIdFence:
...@@ -4138,6 +4315,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4138,6 +4315,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4138 IrInstruction *int_type = ir_build_int_type(irb, scope, node, arg0_value, arg1_value);4315 IrInstruction *int_type = ir_build_int_type(irb, scope, node, arg0_value, arg1_value);
4139 return ir_lval_wrap(irb, scope, int_type, lval);4316 return ir_lval_wrap(irb, scope, int_type, lval);
4140 }4317 }
4318 case BuiltinFnIdVectorType:
4319 {
4320 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4321 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4322 if (arg0_value == irb->codegen->invalid_instruction)
4323 return arg0_value;
4324
4325 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4326 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
4327 if (arg1_value == irb->codegen->invalid_instruction)
4328 return arg1_value;
4329
4330 IrInstruction *vector_type = ir_build_vector_type(irb, scope, node, arg0_value, arg1_value);
4331 return ir_lval_wrap(irb, scope, vector_type, lval);
4332 }
4141 case BuiltinFnIdMemcpy:4333 case BuiltinFnIdMemcpy:
4142 {4334 {
4143 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);4335 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
...@@ -4315,7 +4507,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4315,7 +4507,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4315 if (arg1_value == irb->codegen->invalid_instruction)4507 if (arg1_value == irb->codegen->invalid_instruction)
4316 return arg1_value;4508 return arg1_value;
43174509
4318 IrInstruction *ptr_cast = ir_build_ptr_cast(irb, scope, node, arg0_value, arg1_value);4510 IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value, true);
4319 return ir_lval_wrap(irb, scope, ptr_cast, lval);4511 return ir_lval_wrap(irb, scope, ptr_cast, lval);
4320 }4512 }
4321 case BuiltinFnIdBitCast:4513 case BuiltinFnIdBitCast:
...@@ -4689,6 +4881,36 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4689,6 +4881,36 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4689 IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value);4881 IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value);
4690 return ir_lval_wrap(irb, scope, result, lval);4882 return ir_lval_wrap(irb, scope, result, lval);
4691 }4883 }
4884 case BuiltinFnIdBswap:
4885 {
4886 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4887 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4888 if (arg0_value == irb->codegen->invalid_instruction)
4889 return arg0_value;
4890
4891 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4892 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
4893 if (arg1_value == irb->codegen->invalid_instruction)
4894 return arg1_value;
4895
4896 IrInstruction *result = ir_build_bswap(irb, scope, node, arg0_value, arg1_value);
4897 return ir_lval_wrap(irb, scope, result, lval);
4898 }
4899 case BuiltinFnIdBitReverse:
4900 {
4901 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4902 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4903 if (arg0_value == irb->codegen->invalid_instruction)
4904 return arg0_value;
4905
4906 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4907 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
4908 if (arg1_value == irb->codegen->invalid_instruction)
4909 return arg1_value;
4910
4911 IrInstruction *result = ir_build_bit_reverse(irb, scope, node, arg0_value, arg1_value);
4912 return ir_lval_wrap(irb, scope, result, lval);
4913 }
4692 }4914 }
4693 zig_unreachable();4915 zig_unreachable();
4694}4916}
...@@ -4723,7 +4945,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node...@@ -4723,7 +4945,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
4723 }4945 }
4724 }4946 }
47254947
4726 IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, is_async, async_allocator, nullptr);4948 IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto,
4949 is_async, async_allocator, nullptr);
4727 return ir_lval_wrap(irb, scope, fn_call, lval);4950 return ir_lval_wrap(irb, scope, fn_call, lval);
4728}4951}
47294952
...@@ -4732,7 +4955,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -4732,7 +4955,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
47324955
4733 IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope);4956 IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope);
4734 if (condition == irb->codegen->invalid_instruction)4957 if (condition == irb->codegen->invalid_instruction)
4735 return condition;4958 return irb->codegen->invalid_instruction;
47364959
4737 IrInstruction *is_comptime;4960 IrInstruction *is_comptime;
4738 if (ir_should_inline(irb->exec, scope)) {4961 if (ir_should_inline(irb->exec, scope)) {
...@@ -4755,7 +4978,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -4755,7 +4978,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
4755 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);4978 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
4756 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, subexpr_scope);4979 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, subexpr_scope);
4757 if (then_expr_result == irb->codegen->invalid_instruction)4980 if (then_expr_result == irb->codegen->invalid_instruction)
4758 return then_expr_result;4981 return irb->codegen->invalid_instruction;
4759 IrBasicBlock *after_then_block = irb->current_basic_block;4982 IrBasicBlock *after_then_block = irb->current_basic_block;
4760 if (!instr_is_unreachable(then_expr_result))4983 if (!instr_is_unreachable(then_expr_result))
4761 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));4984 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));
...@@ -4765,7 +4988,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -4765,7 +4988,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
4765 if (else_node) {4988 if (else_node) {
4766 else_expr_result = ir_gen_node(irb, else_node, subexpr_scope);4989 else_expr_result = ir_gen_node(irb, else_node, subexpr_scope);
4767 if (else_expr_result == irb->codegen->invalid_instruction)4990 if (else_expr_result == irb->codegen->invalid_instruction)
4768 return else_expr_result;4991 return irb->codegen->invalid_instruction;
4769 } else {4992 } else {
4770 else_expr_result = ir_build_const_void(irb, scope, node);4993 else_expr_result = ir_build_const_void(irb, scope, node);
4771 }4994 }
...@@ -4810,10 +5033,23 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *...@@ -4810,10 +5033,23 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *
4810 return ir_build_ref(irb, scope, value->source_node, value, false, false);5033 return ir_build_ref(irb, scope, value->source_node, value, false, false);
4811}5034}
48125035
5036static PtrLen star_token_to_ptr_len(TokenId token_id) {
5037 switch (token_id) {
5038 case TokenIdStar:
5039 case TokenIdStarStar:
5040 return PtrLenSingle;
5041 case TokenIdBracketStarBracket:
5042 return PtrLenUnknown;
5043 case TokenIdBracketStarCBracket:
5044 return PtrLenC;
5045 default:
5046 zig_unreachable();
5047 }
5048}
5049
4813static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {5050static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {
4814 assert(node->type == NodeTypePointerType);5051 assert(node->type == NodeTypePointerType);
4815 PtrLen ptr_len = (node->data.pointer_type.star_token->id == TokenIdStar ||5052 PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id);
4816 node->data.pointer_type.star_token->id == TokenIdStarStar) ? PtrLenSingle : PtrLenUnknown;
4817 bool is_const = node->data.pointer_type.is_const;5053 bool is_const = node->data.pointer_type.is_const;
4818 bool is_volatile = node->data.pointer_type.is_volatile;5054 bool is_volatile = node->data.pointer_type.is_volatile;
4819 AstNode *expr_node = node->data.pointer_type.op_expr;5055 AstNode *expr_node = node->data.pointer_type.op_expr;
...@@ -4866,7 +5102,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode...@@ -4866,7 +5102,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
4866 ptr_len, align_value, bit_offset_start, host_int_bytes);5102 ptr_len, align_value, bit_offset_start, host_int_bytes);
4867}5103}
48685104
4869static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node,5105static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node,
4870 LVal lval)5106 LVal lval)
4871{5107{
4872 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);5108 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);
...@@ -4992,11 +5228,11 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -4992,11 +5228,11 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
4992 ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime);5228 ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime);
4993 ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol,5229 ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol,
4994 is_const, is_const, is_shadowable, is_comptime);5230 is_const, is_const, is_shadowable, is_comptime);
4995 // we detect IrInstructionIdDeclVar in gen_block to make sure the next node5231 // we detect IrInstructionIdDeclVarSrc in gen_block to make sure the next node
4996 // is inside var->child_scope5232 // is inside var->child_scope
49975233
4998 if (!is_extern && !variable_declaration->expr) {5234 if (!is_extern && !variable_declaration->expr) {
4999 var->value->type = irb->codegen->builtin_types.entry_invalid;5235 var->var_type = irb->codegen->builtin_types.entry_invalid;
5000 add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized"));5236 add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized"));
5001 return irb->codegen->invalid_instruction;5237 return irb->codegen->invalid_instruction;
5002 }5238 }
...@@ -5012,6 +5248,10 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5012,6 +5248,10 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
5012 add_node_error(irb->codegen, variable_declaration->section_expr,5248 add_node_error(irb->codegen, variable_declaration->section_expr,
5013 buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol)));5249 buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol)));
5014 }5250 }
5251 if (variable_declaration->threadlocal_tok != nullptr) {
5252 add_token_error(irb->codegen, node->owner, variable_declaration->threadlocal_tok,
5253 buf_sprintf("function-local variable '%s' cannot be threadlocal", buf_ptr(variable_declaration->symbol)));
5254 }
50155255
5016 // Temporarily set the name of the IrExecutable to the VariableDeclaration5256 // Temporarily set the name of the IrExecutable to the VariableDeclaration
5017 // so that the struct or enum from the init expression inherits the name.5257 // so that the struct or enum from the init expression inherits the name.
...@@ -5023,7 +5263,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5023,7 +5263,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
5023 if (init_value == irb->codegen->invalid_instruction)5263 if (init_value == irb->codegen->invalid_instruction)
5024 return init_value;5264 return init_value;
50255265
5026 return ir_build_var_decl(irb, scope, node, var, type_instruction, align_value, init_value);5266 return ir_build_var_decl_src(irb, scope, node, var, type_instruction, align_value, init_value);
5027}5267}
50285268
5029static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) {5269static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
...@@ -5079,7 +5319,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5079,7 +5319,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5079 err_val_ptr, false);5319 err_val_ptr, false);
5080 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?5320 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
5081 var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value);5321 var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value);
5082 ir_build_var_decl(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value);5322 ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value);
5083 }5323 }
50845324
5085 ZigList<IrInstruction *> incoming_values = {0};5325 ZigList<IrInstruction *> incoming_values = {0};
...@@ -5119,7 +5359,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5119,7 +5359,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5119 true, false, false, is_comptime);5359 true, false, false, is_comptime);
5120 Scope *err_scope = err_var->child_scope;5360 Scope *err_scope = err_var->child_scope;
5121 IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);5361 IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);
5122 ir_build_var_decl(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value);5362 ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value);
51235363
5124 IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope);5364 IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope);
5125 if (else_result == irb->codegen->invalid_instruction)5365 if (else_result == irb->codegen->invalid_instruction)
...@@ -5159,10 +5399,10 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5159,10 +5399,10 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5159 }5399 }
51605400
5161 ir_set_cursor_at_end_and_append_block(irb, body_block);5401 ir_set_cursor_at_end_and_append_block(irb, body_block);
5162 IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, child_scope, symbol_node, maybe_val_ptr, false);5402 IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false);
5163 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?5403 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
5164 var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value);5404 var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value);
5165 ir_build_var_decl(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value);5405 ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value);
51665406
5167 ZigList<IrInstruction *> incoming_values = {0};5407 ZigList<IrInstruction *> incoming_values = {0};
5168 ZigList<IrBasicBlock *> incoming_blocks = {0};5408 ZigList<IrBasicBlock *> incoming_blocks = {0};
...@@ -5319,7 +5559,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -5319,7 +5559,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
5319 Scope *child_scope = elem_var->child_scope;5559 Scope *child_scope = elem_var->child_scope;
53205560
5321 IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node);5561 IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node);
5322 ir_build_var_decl(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value);5562 ir_build_var_decl_src(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value);
5323 IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var);5563 IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var);
53245564
5325 AstNode *index_var_source_node;5565 AstNode *index_var_source_node;
...@@ -5337,7 +5577,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -5337,7 +5577,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
5337 IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize);5577 IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize);
5338 IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0);5578 IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0);
5339 IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1);5579 IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1);
5340 ir_build_var_decl(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero);5580 ir_build_var_decl_src(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero);
5341 IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var);5581 IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var);
53425582
53435583
...@@ -5561,8 +5801,8 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5561,8 +5801,8 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod
5561 return ir_build_asm(irb, scope, node, input_list, output_types, output_vars, return_count, is_volatile);5801 return ir_build_asm(irb, scope, node, input_list, output_types, output_vars, return_count, is_volatile);
5562}5802}
55635803
5564static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *node) {5804static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
5565 assert(node->type == NodeTypeTestExpr);5805 assert(node->type == NodeTypeIfOptional);
55665806
5567 Buf *var_symbol = node->data.test_expr.var_symbol;5807 Buf *var_symbol = node->data.test_expr.var_symbol;
5568 AstNode *expr_node = node->data.test_expr.target_node;5808 AstNode *expr_node = node->data.test_expr.target_node;
...@@ -5600,9 +5840,9 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no...@@ -5600,9 +5840,9 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no
5600 ZigVar *var = ir_create_var(irb, node, subexpr_scope,5840 ZigVar *var = ir_create_var(irb, node, subexpr_scope,
5601 var_symbol, is_const, is_const, is_shadowable, is_comptime);5841 var_symbol, is_const, is_const, is_shadowable, is_comptime);
56025842
5603 IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, subexpr_scope, node, maybe_val_ptr, false);5843 IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false);
5604 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);5844 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);
5605 ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value);5845 ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
5606 var_scope = var->child_scope;5846 var_scope = var->child_scope;
5607 } else {5847 } else {
5608 var_scope = subexpr_scope;5848 var_scope = subexpr_scope;
...@@ -5677,7 +5917,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -5677,7 +5917,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
56775917
5678 IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false);5918 IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false);
5679 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);5919 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);
5680 ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value);5920 ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
5681 var_scope = var->child_scope;5921 var_scope = var->child_scope;
5682 } else {5922 } else {
5683 var_scope = subexpr_scope;5923 var_scope = subexpr_scope;
...@@ -5702,7 +5942,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -5702,7 +5942,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
5702 err_symbol, is_const, is_const, is_shadowable, is_comptime);5942 err_symbol, is_const, is_const, is_shadowable, is_comptime);
57035943
5704 IrInstruction *var_value = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr);5944 IrInstruction *var_value = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr);
5705 ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value);5945 ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
5706 err_var_scope = var->child_scope;5946 err_var_scope = var->child_scope;
5707 } else {5947 } else {
5708 err_var_scope = subexpr_scope;5948 err_var_scope = subexpr_scope;
...@@ -5757,7 +5997,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit...@@ -5757,7 +5997,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
5757 var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr);5997 var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr);
5758 }5998 }
5759 IrInstruction *var_type = nullptr; // infer the type5999 IrInstruction *var_type = nullptr; // infer the type
5760 ir_build_var_decl(irb, scope, var_symbol_node, var, var_type, nullptr, var_value);6000 ir_build_var_decl_src(irb, scope, var_symbol_node, var, var_type, nullptr, var_value);
5761 } else {6001 } else {
5762 child_scope = scope;6002 child_scope = scope;
5763 }6003 }
...@@ -6167,7 +6407,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -6167,7 +6407,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)
6167 return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true);6407 return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true);
6168}6408}
61696409
6170static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) {6410static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
6171 assert(node->type == NodeTypeUnwrapErrorExpr);6411 assert(node->type == NodeTypeUnwrapErrorExpr);
61726412
6173 AstNode *op1_node = node->data.unwrap_err_expr.op1;6413 AstNode *op1_node = node->data.unwrap_err_expr.op1;
...@@ -6181,7 +6421,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN...@@ -6181,7 +6421,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
6181 add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));6421 add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));
6182 return irb->codegen->invalid_instruction;6422 return irb->codegen->invalid_instruction;
6183 }6423 }
6184 return ir_gen_err_assert_ok(irb, parent_scope, node, op1_node, LValNone);6424 return ir_gen_catch_unreachable(irb, parent_scope, node, op1_node, LValNone);
6185 }6425 }
61866426
61876427
...@@ -6215,7 +6455,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN...@@ -6215,7 +6455,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
6215 is_const, is_const, is_shadowable, is_comptime);6455 is_const, is_const, is_shadowable, is_comptime);
6216 err_scope = var->child_scope;6456 err_scope = var->child_scope;
6217 IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);6457 IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);
6218 ir_build_var_decl(irb, err_scope, var_node, var, nullptr, nullptr, err_val);6458 ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, nullptr, err_val);
6219 } else {6459 } else {
6220 err_scope = parent_scope;6460 err_scope = parent_scope;
6221 }6461 }
...@@ -6251,7 +6491,8 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o...@@ -6251,7 +6491,8 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o
6251 ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope;6491 ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope;
6252 if (need_comma)6492 if (need_comma)
6253 buf_append_char(name, ',');6493 buf_append_char(name, ',');
6254 render_const_value(codegen, name, var_scope->var->value);6494 // TODO: const ptr reinterpret here to make the var type agree with the value?
6495 render_const_value(codegen, name, var_scope->var->const_value);
6255 return true;6496 return true;
6256}6497}
62576498
...@@ -6501,14 +6742,15 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode...@@ -6501,14 +6742,15 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
6501 IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b0106742 IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010
65026743
6503 // TODO relies on Zig not re-ordering fields6744 // TODO relies on Zig not re-ordering fields
6504 IrInstruction *casted_target_inst = ir_build_ptr_cast(irb, scope, node, promise_T_type_val, target_inst);6745 IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst,
6746 false);
6505 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);6747 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
6506 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);6748 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
6507 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,6749 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
6508 atomic_state_field_name);6750 atomic_state_field_name);
65096751
6510 // set the is_canceled bit6752 // set the is_canceled bit
6511 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, 6753 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
6512 usize_type_val, atomic_state_ptr, nullptr, is_canceled_mask, nullptr,6754 usize_type_val, atomic_state_ptr, nullptr, is_canceled_mask, nullptr,
6513 AtomicRmwOp_or, AtomicOrderSeqCst);6755 AtomicRmwOp_or, AtomicOrderSeqCst);
65146756
...@@ -6579,14 +6821,15 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode...@@ -6579,14 +6821,15 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode
6579 get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));6821 get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));
65806822
6581 // TODO relies on Zig not re-ordering fields6823 // TODO relies on Zig not re-ordering fields
6582 IrInstruction *casted_target_inst = ir_build_ptr_cast(irb, scope, node, promise_T_type_val, target_inst);6824 IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst,
6825 false);
6583 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);6826 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
6584 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);6827 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
6585 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,6828 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
6586 atomic_state_field_name);6829 atomic_state_field_name);
65876830
6588 // clear the is_suspended bit6831 // clear the is_suspended bit
6589 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, 6832 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
6590 usize_type_val, atomic_state_ptr, nullptr, and_mask, nullptr,6833 usize_type_val, atomic_state_ptr, nullptr, and_mask, nullptr,
6591 AtomicRmwOp_and, AtomicOrderSeqCst);6834 AtomicRmwOp_and, AtomicOrderSeqCst);
65926835
...@@ -6695,14 +6938,14 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6695,14 +6938,14 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
6695 IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst);6938 IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst);
6696 IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type);6939 IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type);
6697 ir_build_await_bookkeeping(irb, scope, node, promise_result_type);6940 ir_build_await_bookkeeping(irb, scope, node, promise_result_type);
6698 ir_build_var_decl(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value);6941 ir_build_var_decl_src(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value);
6699 IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var);6942 IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var);
6700 ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr);6943 ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr);
6701 IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle);6944 IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle);
67026945
6703 IrInstruction *coro_handle_addr = ir_build_ptr_to_int(irb, scope, node, irb->exec->coro_handle);6946 IrInstruction *coro_handle_addr = ir_build_ptr_to_int(irb, scope, node, irb->exec->coro_handle);
6704 IrInstruction *mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, coro_handle_addr, await_mask, false);6947 IrInstruction *mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, coro_handle_addr, await_mask, false);
6705 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, 6948 IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
6706 usize_type_val, atomic_state_ptr, nullptr, mask_bits, nullptr,6949 usize_type_val, atomic_state_ptr, nullptr, mask_bits, nullptr,
6707 AtomicRmwOp_or, AtomicOrderSeqCst);6950 AtomicRmwOp_or, AtomicOrderSeqCst);
67086951
...@@ -6745,7 +6988,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6745,7 +6988,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
67456988
67466989
6747 ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block);6990 ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block);
6748 IrInstruction *my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, 6991 IrInstruction *my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
6749 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, is_suspended_mask, nullptr,6992 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, is_suspended_mask, nullptr,
6750 AtomicRmwOp_or, AtomicOrderSeqCst);6993 AtomicRmwOp_or, AtomicOrderSeqCst);
6751 IrInstruction *my_is_suspended_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, my_prev_atomic_value, is_suspended_mask, false);6994 IrInstruction *my_is_suspended_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, my_prev_atomic_value, is_suspended_mask, false);
...@@ -6777,7 +7020,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6777,7 +7020,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
67777020
6778 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);7021 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
6779 IrInstruction *my_mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, ptr_mask, is_canceled_mask, false);7022 IrInstruction *my_mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, ptr_mask, is_canceled_mask, false);
6780 IrInstruction *b_my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node, 7023 IrInstruction *b_my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
6781 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, my_mask_bits, nullptr,7024 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, my_mask_bits, nullptr,
6782 AtomicRmwOp_or, AtomicOrderSeqCst);7025 AtomicRmwOp_or, AtomicOrderSeqCst);
6783 IrInstruction *my_await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, b_my_prev_atomic_value, ptr_mask, false);7026 IrInstruction *my_await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, b_my_prev_atomic_value, ptr_mask, false);
...@@ -6989,7 +7232,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -6989,7 +7232,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
6989 if (maybe_ptr == irb->codegen->invalid_instruction)7232 if (maybe_ptr == irb->codegen->invalid_instruction)
6990 return irb->codegen->invalid_instruction;7233 return irb->codegen->invalid_instruction;
69917234
6992 IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, maybe_ptr, true);7235 IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true);
6993 if (lval == LValPtr)7236 if (lval == LValPtr)
6994 return unwrapped_ptr;7237 return unwrapped_ptr;
69957238
...@@ -7013,8 +7256,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -7013,8 +7256,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
7013 return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);7256 return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);
7014 case NodeTypeIfErrorExpr:7257 case NodeTypeIfErrorExpr:
7015 return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval);7258 return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval);
7016 case NodeTypeTestExpr:7259 case NodeTypeIfOptional:
7017 return ir_lval_wrap(irb, scope, ir_gen_test_expr(irb, scope, node), lval);7260 return ir_lval_wrap(irb, scope, ir_gen_if_optional_expr(irb, scope, node), lval);
7018 case NodeTypeSwitchExpr:7261 case NodeTypeSwitchExpr:
7019 return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);7262 return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);
7020 case NodeTypeCompTime:7263 case NodeTypeCompTime:
...@@ -7032,7 +7275,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -7032,7 +7275,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
7032 case NodeTypeSliceExpr:7275 case NodeTypeSliceExpr:
7033 return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval);7276 return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval);
7034 case NodeTypeUnwrapErrorExpr:7277 case NodeTypeUnwrapErrorExpr:
7035 return ir_lval_wrap(irb, scope, ir_gen_err_ok_or(irb, scope, node), lval);7278 return ir_lval_wrap(irb, scope, ir_gen_catch(irb, scope, node), lval);
7036 case NodeTypeContainerDecl:7279 case NodeTypeContainerDecl:
7037 return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval);7280 return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval);
7038 case NodeTypeFnProto:7281 case NodeTypeFnProto:
...@@ -7091,6 +7334,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7091,6 +7334,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7091 ir_ref_bb(irb->current_basic_block);7334 ir_ref_bb(irb->current_basic_block);
70927335
7093 ZigFn *fn_entry = exec_fn_entry(irb->exec);7336 ZigFn *fn_entry = exec_fn_entry(irb->exec);
7337
7094 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;7338 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
7095 IrInstruction *coro_id;7339 IrInstruction *coro_id;
7096 IrInstruction *u8_ptr_type;7340 IrInstruction *u8_ptr_type;
...@@ -7111,27 +7355,28 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7111,27 +7355,28 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7111 ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);7355 ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);
7112 IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);7356 IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);
7113 // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa7357 // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa
7114 ir_build_var_decl(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef);7358 ir_build_var_decl_src(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef);
7115 coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var);7359 coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var);
71167360
7117 ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);7361 ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
7118 IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);7362 IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);
7119 IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,7363 IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,
7120 get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise));7364 get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
7121 ir_build_var_decl(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);7365 ir_build_var_decl_src(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);
7122 irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var);7366 irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var);
71237367
7124 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,7368 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
7125 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));7369 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));
7126 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr);7370 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type,
7371 coro_promise_ptr, false);
7127 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);7372 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);
7128 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);7373 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
7129 IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);7374 IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);
7130 ir_build_var_decl(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size);7375 ir_build_var_decl_src(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size);
7131 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node,7376 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node,
7132 ImplicitAllocatorIdArg);7377 ImplicitAllocatorIdArg);
7133 irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false);7378 irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false);
7134 ir_build_var_decl(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);7379 ir_build_var_decl_src(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);
7135 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);7380 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
7136 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, alloc_field_name);7381 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, alloc_field_name);
7137 IrInstruction *alloc_fn = ir_build_load_ptr(irb, coro_scope, node, alloc_fn_ptr);7382 IrInstruction *alloc_fn = ir_build_load_ptr(irb, coro_scope, node, alloc_fn_ptr);
...@@ -7147,7 +7392,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7147,7 +7392,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7147 ir_build_return(irb, coro_scope, node, undef);7392 ir_build_return(irb, coro_scope, node, undef);
71487393
7149 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);7394 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);
7150 IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr);7395 IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr,
7396 false);
7151 irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);7397 irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);
71527398
7153 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);7399 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
...@@ -7225,9 +7471,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7225,9 +7471,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7225 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,7471 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
7226 false, false, PtrLenUnknown, 0, 0, 0));7472 false, false, PtrLenUnknown, 0, 0, 0));
7227 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);7473 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
7228 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, result_ptr);7474 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
7229 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len,7475 result_ptr, false);
7230 irb->exec->coro_result_field_ptr);7476 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node,
7477 u8_ptr_type_unknown_len, irb->exec->coro_result_field_ptr, false);
7231 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,7478 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,
7232 fn_entry->type_entry->data.fn.fn_type_id.return_type);7479 fn_entry->type_entry->data.fn.fn_type_id.return_type);
7233 IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst);7480 IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst);
...@@ -7242,7 +7489,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7242,7 +7489,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7242 // Before we destroy the coroutine frame, we need to load the target promise into7489 // Before we destroy the coroutine frame, we need to load the target promise into
7243 // a register or local variable which does not get spilled into the frame,7490 // a register or local variable which does not get spilled into the frame,
7244 // otherwise llvm tries to access memory inside the destroyed frame.7491 // otherwise llvm tries to access memory inside the destroyed frame.
7245 IrInstruction *unwrapped_await_handle_ptr = ir_build_unwrap_maybe(irb, scope, node,7492 IrInstruction *unwrapped_await_handle_ptr = ir_build_optional_unwrap_ptr(irb, scope, node,
7246 irb->exec->await_handle_var_ptr, false);7493 irb->exec->await_handle_var_ptr, false);
7247 IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);7494 IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);
7248 ir_build_br(irb, scope, node, check_free_block, const_bool_false);7495 ir_build_br(irb, scope, node, check_free_block, const_bool_false);
...@@ -7277,7 +7524,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7277,7 +7524,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7277 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,7524 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
7278 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,7525 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
7279 false, false, PtrLenUnknown, 0, 0, 0));7526 false, false, PtrLenUnknown, 0, 0, 0));
7280 IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe);7527 IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
7528 coro_mem_ptr_maybe, false);
7281 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);7529 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
7282 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);7530 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
7283 IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);7531 IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);
...@@ -7330,24 +7578,51 @@ static ErrorMsg *ir_add_error_node(IrAnalyze *ira, AstNode *source_node, Buf *ms...@@ -7330,24 +7578,51 @@ static ErrorMsg *ir_add_error_node(IrAnalyze *ira, AstNode *source_node, Buf *ms
7330 return exec_add_error_node(ira->codegen, ira->new_irb.exec, source_node, msg);7578 return exec_add_error_node(ira->codegen, ira->new_irb.exec, source_node, msg);
7331}7579}
73327580
7581static ErrorMsg *opt_ir_add_error_node(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, Buf *msg) {
7582 if (ira != nullptr)
7583 return exec_add_error_node(codegen, ira->new_irb.exec, source_node, msg);
7584 else
7585 return add_node_error(codegen, source_node, msg);
7586}
7587
7333static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction, Buf *msg) {7588static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction, Buf *msg) {
7334 return ir_add_error_node(ira, source_instruction->source_node, msg);7589 return ir_add_error_node(ira, source_instruction->source_node, msg);
7335}7590}
73367591
7337static ConstExprValue *ir_const_ptr_pointee(IrAnalyze *ira, ConstExprValue *const_val, AstNode *source_node) {7592// This function takes a comptime ptr and makes the child const value conform to the type
7338 ConstExprValue *val = const_ptr_pointee_unchecked(ira->codegen, const_val);7593// described by the pointer.
7594static Error eval_comptime_ptr_reinterpret(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
7595 ConstExprValue *ptr_val)
7596{
7597 Error err;
7598 assert(ptr_val->type->id == ZigTypeIdPointer);
7599 ConstExprValue tmp = {};
7600 tmp.special = ConstValSpecialStatic;
7601 tmp.type = ptr_val->type->data.pointer.child_type;
7602 if ((err = ir_read_const_ptr(ira, codegen, source_node, &tmp, ptr_val)))
7603 return err;
7604 ConstExprValue *child_val = const_ptr_pointee_unchecked(codegen, ptr_val);
7605 copy_const_val(child_val, &tmp, false);
7606 return ErrorNone;
7607}
7608
7609ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprValue *const_val,
7610 AstNode *source_node)
7611{
7612 Error err;
7613 ConstExprValue *val = const_ptr_pointee_unchecked(codegen, const_val);
7339 assert(val != nullptr);7614 assert(val != nullptr);
7340 assert(const_val->type->id == ZigTypeIdPointer);7615 assert(const_val->type->id == ZigTypeIdPointer);
7341 ZigType *expected_type = const_val->type->data.pointer.child_type;7616 ZigType *expected_type = const_val->type->data.pointer.child_type;
7342 if (!types_have_same_zig_comptime_repr(val->type, expected_type)) {7617 if (!types_have_same_zig_comptime_repr(val->type, expected_type)) {
7343 ir_add_error_node(ira, source_node,7618 if ((err = eval_comptime_ptr_reinterpret(ira, codegen, source_node, const_val)))
7344 buf_sprintf("TODO handle comptime reinterpreted pointer. See https://github.com/ziglang/zig/issues/955"));7619 return nullptr;
7345 return nullptr;7620 return const_ptr_pointee_unchecked(codegen, const_val);
7346 }7621 }
7347 return val;7622 return val;
7348}7623}
73497624
7350static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) {7625static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) {
7351 IrBasicBlock *bb = exec->basic_block_list.at(0);7626 IrBasicBlock *bb = exec->basic_block_list.at(0);
7352 for (size_t i = 0; i < bb->instruction_list.length; i += 1) {7627 for (size_t i = 0; i < bb->instruction_list.length; i += 1) {
7353 IrInstruction *instruction = bb->instruction_list.at(i);7628 IrInstruction *instruction = bb->instruction_list.at(i);
...@@ -7357,16 +7632,16 @@ static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec)...@@ -7357,16 +7632,16 @@ static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec)
7357 if (value->value.special == ConstValSpecialRuntime) {7632 if (value->value.special == ConstValSpecialRuntime) {
7358 exec_add_error_node(codegen, exec, value->source_node,7633 exec_add_error_node(codegen, exec, value->source_node,
7359 buf_sprintf("unable to evaluate constant expression"));7634 buf_sprintf("unable to evaluate constant expression"));
7360 return codegen->invalid_instruction;7635 return &codegen->invalid_instruction->value;
7361 }7636 }
7362 return value;7637 return &value->value;
7363 } else if (ir_has_side_effects(instruction)) {7638 } else if (ir_has_side_effects(instruction)) {
7364 exec_add_error_node(codegen, exec, instruction->source_node,7639 exec_add_error_node(codegen, exec, instruction->source_node,
7365 buf_sprintf("unable to evaluate constant expression"));7640 buf_sprintf("unable to evaluate constant expression"));
7366 return codegen->invalid_instruction;7641 return &codegen->invalid_instruction->value;
7367 }7642 }
7368 }7643 }
7369 return codegen->invalid_instruction;7644 return &codegen->invalid_instruction->value;
7370}7645}
73717646
7372static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) {7647static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) {
...@@ -8086,6 +8361,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc...@@ -8086,6 +8361,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
80868361
8087 bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt);8362 bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt);
8088 bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || const_val->type->id == ZigTypeIdComptimeFloat);8363 bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || const_val->type->id == ZigTypeIdComptimeFloat);
8364 assert(const_val_is_int || const_val_is_float);
80898365
8090 if (other_type->id == ZigTypeIdFloat) {8366 if (other_type->id == ZigTypeIdFloat) {
8091 if (const_val->type->id == ZigTypeIdComptimeInt || const_val->type->id == ZigTypeIdComptimeFloat) {8367 if (const_val->type->id == ZigTypeIdComptimeInt || const_val->type->id == ZigTypeIdComptimeFloat) {
...@@ -8376,7 +8652,6 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp...@@ -8376,7 +8652,6 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp
8376 return err_set_type;8652 return err_set_type;
8377}8653}
83788654
8379
8380static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type,8655static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type,
8381 ZigType *actual_type, AstNode *source_node, bool wanted_is_mutable)8656 ZigType *actual_type, AstNode *source_node, bool wanted_is_mutable)
8382{8657{
...@@ -8389,53 +8664,63 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -8389,53 +8664,63 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
8389 if (wanted_type == actual_type)8664 if (wanted_type == actual_type)
8390 return result;8665 return result;
83918666
8392 // *T and [*]T may const-cast-only to ?*U and ?[*]U, respectively8667 // If pointers have the same representation in memory, they can be "const-casted".
8393 // but not if we want a mutable pointer8668 // `const` attribute can be gained
8394 // and not if the actual pointer has zero bits8669 // `volatile` attribute can be gained
8395 if (!wanted_is_mutable && wanted_type->id == ZigTypeIdOptional &&8670 // `allowzero` attribute can be gained (whether from explicit attribute, C pointer, or optional pointer)
8396 wanted_type->data.maybe.child_type->id == ZigTypeIdPointer &&8671 // but only if !wanted_is_mutable
8397 actual_type->id == ZigTypeIdPointer && type_has_bits(actual_type))8672 // alignment can be decreased
8398 {8673 // bit offset attributes must match exactly
8399 ConstCastOnly child = types_match_const_cast_only(ira,8674 // PtrLenSingle/PtrLenUnknown must match exactly, but PtrLenC matches either one
8400 wanted_type->data.maybe.child_type, actual_type, source_node, wanted_is_mutable);8675 ZigType *wanted_ptr_type = get_src_ptr_type(wanted_type);
8401 if (child.id == ConstCastResultIdInvalid)8676 ZigType *actual_ptr_type = get_src_ptr_type(actual_type);
8402 return child;8677 bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);
8403 if (child.id != ConstCastResultIdOk) {8678 bool actual_allows_zero = ptr_allows_addr_zero(actual_type);
8404 result.id = ConstCastResultIdNullWrapPtr;8679 bool wanted_is_c_ptr = wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC;
8405 result.data.null_wrap_ptr_child = allocate_nonzero<ConstCastOnly>(1);8680 bool actual_is_c_ptr = actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenC;
8406 *result.data.null_wrap_ptr_child = child;8681 bool wanted_opt_or_ptr = wanted_ptr_type != nullptr &&
8407 }8682 (wanted_type->id == ZigTypeIdPointer || wanted_type->id == ZigTypeIdOptional);
8408 return result;8683 bool actual_opt_or_ptr = actual_ptr_type != nullptr &&
8409 }8684 (actual_type->id == ZigTypeIdPointer || actual_type->id == ZigTypeIdOptional);
84108685 if (wanted_opt_or_ptr && actual_opt_or_ptr) {
8411 // pointer const8686 ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,
8412 if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) {8687 actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);
8413 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
8414 actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const);
8415 if (child.id == ConstCastResultIdInvalid)8688 if (child.id == ConstCastResultIdInvalid)
8416 return child;8689 return child;
8417 if (child.id != ConstCastResultIdOk) {8690 if (child.id != ConstCastResultIdOk) {
8418 result.id = ConstCastResultIdPointerChild;8691 result.id = ConstCastResultIdPointerChild;
8419 result.data.pointer_mismatch = allocate_nonzero<ConstCastPointerMismatch>(1);8692 result.data.pointer_mismatch = allocate_nonzero<ConstCastPointerMismatch>(1);
8420 result.data.pointer_mismatch->child = child;8693 result.data.pointer_mismatch->child = child;
8421 result.data.pointer_mismatch->wanted_child = wanted_type->data.pointer.child_type;8694 result.data.pointer_mismatch->wanted_child = wanted_ptr_type->data.pointer.child_type;
8422 result.data.pointer_mismatch->actual_child = actual_type->data.pointer.child_type;8695 result.data.pointer_mismatch->actual_child = actual_ptr_type->data.pointer.child_type;
8696 return result;
8697 }
8698 bool ok_allows_zero = (wanted_allows_zero &&
8699 (actual_allows_zero || !wanted_is_mutable)) ||
8700 (!wanted_allows_zero && !actual_allows_zero);
8701 if (!ok_allows_zero) {
8702 result.id = ConstCastResultIdBadAllowsZero;
8703 result.data.bad_allows_zero = allocate_nonzero<ConstCastBadAllowsZero>(1);
8704 result.data.bad_allows_zero->wanted_type = wanted_type;
8705 result.data.bad_allows_zero->actual_type = actual_type;
8423 return result;8706 return result;
8424 }8707 }
8425 if ((err = type_resolve(g, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {8708 if ((err = type_resolve(g, actual_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
8426 result.id = ConstCastResultIdInvalid;8709 result.id = ConstCastResultIdInvalid;
8427 return result;8710 return result;
8428 }8711 }
8429 if ((err = type_resolve(g, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {8712 if ((err = type_resolve(g, wanted_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
8430 result.id = ConstCastResultIdInvalid;8713 result.id = ConstCastResultIdInvalid;
8431 return result;8714 return result;
8432 }8715 }
8433 if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) &&8716 bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
8434 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&8717 if ((ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr) &&
8435 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) &&8718 type_has_bits(wanted_type) == type_has_bits(actual_type) &&
8436 actual_type->data.pointer.bit_offset_in_host == wanted_type->data.pointer.bit_offset_in_host &&8719 (!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&
8437 actual_type->data.pointer.host_int_bytes == wanted_type->data.pointer.host_int_bytes &&8720 (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) &&
8438 get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type))8721 actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host &&
8722 actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes &&
8723 get_ptr_align(ira->codegen, actual_ptr_type) >= get_ptr_align(ira->codegen, wanted_ptr_type))
8439 {8724 {
8440 return result;8725 return result;
8441 }8726 }
...@@ -8669,7 +8954,9 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t *...@@ -8669,7 +8954,9 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t *
8669 *errors = reallocate(*errors, old_errors_count, *errors_count);8954 *errors = reallocate(*errors, old_errors_count, *errors_count);
8670}8955}
86718956
8672static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type, IrInstruction **instructions, size_t instruction_count) {8957static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type,
8958 IrInstruction **instructions, size_t instruction_count)
8959{
8673 Error err;8960 Error err;
8674 assert(instruction_count >= 1);8961 assert(instruction_count >= 1);
8675 IrInstruction *prev_inst = instructions[0];8962 IrInstruction *prev_inst = instructions[0];
...@@ -8680,13 +8967,13 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -8680,13 +8967,13 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
8680 size_t errors_count = 0;8967 size_t errors_count = 0;
8681 ZigType *err_set_type = nullptr;8968 ZigType *err_set_type = nullptr;
8682 if (prev_inst->value.type->id == ZigTypeIdErrorSet) {8969 if (prev_inst->value.type->id == ZigTypeIdErrorSet) {
8970 if (!resolve_inferred_error_set(ira->codegen, prev_inst->value.type, prev_inst->source_node)) {
8971 return ira->codegen->builtin_types.entry_invalid;
8972 }
8683 if (type_is_global_error_set(prev_inst->value.type)) {8973 if (type_is_global_error_set(prev_inst->value.type)) {
8684 err_set_type = ira->codegen->builtin_types.entry_global_error_set;8974 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
8685 } else {8975 } else {
8686 err_set_type = prev_inst->value.type;8976 err_set_type = prev_inst->value.type;
8687 if (!resolve_inferred_error_set(ira->codegen, err_set_type, prev_inst->source_node)) {
8688 return ira->codegen->builtin_types.entry_invalid;
8689 }
8690 update_errors_helper(ira->codegen, &errors, &errors_count);8977 update_errors_helper(ira->codegen, &errors, &errors_count);
86918978
8692 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {8979 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
...@@ -8845,6 +9132,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -8845,6 +9132,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
8845 if (prev_type->id == ZigTypeIdArray) {9132 if (prev_type->id == ZigTypeIdArray) {
8846 convert_to_const_slice = true;9133 convert_to_const_slice = true;
8847 }9134 }
9135 if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
9136 return ira->codegen->builtin_types.entry_invalid;
9137 }
8848 if (type_is_global_error_set(cur_type)) {9138 if (type_is_global_error_set(cur_type)) {
8849 err_set_type = ira->codegen->builtin_types.entry_global_error_set;9139 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
8850 continue;9140 continue;
...@@ -8852,9 +9142,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -8852,9 +9142,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
8852 if (err_set_type != nullptr && type_is_global_error_set(err_set_type)) {9142 if (err_set_type != nullptr && type_is_global_error_set(err_set_type)) {
8853 continue;9143 continue;
8854 }9144 }
8855 if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
8856 return ira->codegen->builtin_types.entry_invalid;
8857 }
88589145
8859 update_errors_helper(ira->codegen, &errors, &errors_count);9146 update_errors_helper(ira->codegen, &errors, &errors_count);
88609147
...@@ -8986,6 +9273,37 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -8986,6 +9273,37 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
8986 continue;9273 continue;
8987 }9274 }
89889275
9276 if (prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenC &&
9277 (cur_type->id == ZigTypeIdComptimeInt || cur_type->id == ZigTypeIdInt))
9278 {
9279 continue;
9280 }
9281
9282 if (cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenC &&
9283 (prev_type->id == ZigTypeIdComptimeInt || prev_type->id == ZigTypeIdInt))
9284 {
9285 prev_inst = cur_inst;
9286 continue;
9287 }
9288
9289 if (prev_type->id == ZigTypeIdPointer && cur_type->id == ZigTypeIdPointer) {
9290 if (prev_type->data.pointer.ptr_len == PtrLenC &&
9291 types_match_const_cast_only(ira, prev_type->data.pointer.child_type,
9292 cur_type->data.pointer.child_type, source_node,
9293 !prev_type->data.pointer.is_const).id == ConstCastResultIdOk)
9294 {
9295 continue;
9296 }
9297 if (cur_type->data.pointer.ptr_len == PtrLenC &&
9298 types_match_const_cast_only(ira, cur_type->data.pointer.child_type,
9299 prev_type->data.pointer.child_type, source_node,
9300 !cur_type->data.pointer.is_const).id == ConstCastResultIdOk)
9301 {
9302 prev_inst = cur_inst;
9303 continue;
9304 }
9305 }
9306
8989 if (types_match_const_cast_only(ira, prev_type, cur_type, source_node, false).id == ConstCastResultIdOk) {9307 if (types_match_const_cast_only(ira, prev_type, cur_type, source_node, false).id == ConstCastResultIdOk) {
8990 continue;9308 continue;
8991 }9309 }
...@@ -9292,7 +9610,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_...@@ -9292,7 +9610,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
9292 const_val->type = new_type;9610 const_val->type = new_type;
9293 break;9611 break;
9294 case CastOpResizeSlice:9612 case CastOpResizeSlice:
9295 case CastOpBytesToSlice:
9296 // can't do it9613 // can't do it
9297 zig_unreachable();9614 zig_unreachable();
9298 case CastOpIntToFloat:9615 case CastOpIntToFloat:
...@@ -9345,14 +9662,23 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_...@@ -9345,14 +9662,23 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
9345 }9662 }
9346 return true;9663 return true;
9347}9664}
9348static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,9665
9349 ZigType *wanted_type, CastOp cast_op, bool need_alloca)9666static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) {
9350{9667 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
9668 old_instruction->scope, old_instruction->source_node);
9669 IrInstruction *new_instruction = &const_instruction->base;
9670 new_instruction->value.type = ty;
9671 new_instruction->value.special = ConstValSpecialStatic;
9672 return new_instruction;
9673}
9674
9675static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
9676 ZigType *wanted_type, CastOp cast_op, bool need_alloca)
9677{
9351 if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) &&9678 if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) &&
9352 cast_op != CastOpResizeSlice && cast_op != CastOpBytesToSlice)9679 cast_op != CastOpResizeSlice)
9353 {9680 {
9354 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,9681 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
9355 source_instr->source_node, wanted_type);
9356 if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type,9682 if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type,
9357 &result->value, wanted_type))9683 &result->value, wanted_type))
9358 {9684 {
...@@ -9385,13 +9711,11 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,...@@ -9385,13 +9711,11 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
9385 wanted_type = adjust_ptr_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type));9711 wanted_type = adjust_ptr_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type));
93869712
9387 if (instr_is_comptime(value)) {9713 if (instr_is_comptime(value)) {
9388 ConstExprValue *pointee = ir_const_ptr_pointee(ira, &value->value, source_instr->source_node);9714 ConstExprValue *pointee = const_ptr_pointee(ira, ira->codegen, &value->value, source_instr->source_node);
9389 if (pointee == nullptr)9715 if (pointee == nullptr)
9390 return ira->codegen->invalid_instruction;9716 return ira->codegen->invalid_instruction;
9391 if (pointee->special != ConstValSpecialRuntime) {9717 if (pointee->special != ConstValSpecialRuntime) {
9392 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,9718 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
9393 source_instr->source_node, wanted_type);
9394 result->value.type = wanted_type;
9395 result->value.data.x_ptr.special = ConstPtrSpecialBaseArray;9719 result->value.data.x_ptr.special = ConstPtrSpecialBaseArray;
9396 result->value.data.x_ptr.mut = value->value.data.x_ptr.mut;9720 result->value.data.x_ptr.mut = value->value.data.x_ptr.mut;
9397 result->value.data.x_ptr.data.base_array.array_val = pointee;9721 result->value.data.x_ptr.data.base_array.array_val = pointee;
...@@ -9421,7 +9745,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc...@@ -9421,7 +9745,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
9421 wanted_type = adjust_slice_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type));9745 wanted_type = adjust_slice_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type));
94229746
9423 if (instr_is_comptime(value)) {9747 if (instr_is_comptime(value)) {
9424 ConstExprValue *pointee = ir_const_ptr_pointee(ira, &value->value, source_instr->source_node);9748 ConstExprValue *pointee = const_ptr_pointee(ira, ira->codegen, &value->value, source_instr->source_node);
9425 if (pointee == nullptr)9749 if (pointee == nullptr)
9426 return ira->codegen->invalid_instruction;9750 return ira->codegen->invalid_instruction;
9427 if (pointee->special != ConstValSpecialRuntime) {9751 if (pointee->special != ConstValSpecialRuntime) {
...@@ -9430,8 +9754,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc...@@ -9430,8 +9754,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
9430 assert(is_slice(wanted_type));9754 assert(is_slice(wanted_type));
9431 bool is_const = wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;9755 bool is_const = wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;
94329756
9433 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,9757 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
9434 source_instr->source_node, wanted_type);
9435 init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const);9758 init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const);
9436 result->value.data.x_struct.fields[slice_ptr_index].data.x_ptr.mut =9759 result->value.data.x_struct.fields[slice_ptr_index].data.x_ptr.mut =
9437 value->value.data.x_ptr.mut;9760 value->value.data.x_ptr.mut;
...@@ -9566,15 +9889,6 @@ static IrInstruction *ir_finish_anal(IrAnalyze *ira, IrInstruction *instruction)...@@ -9566,15 +9889,6 @@ static IrInstruction *ir_finish_anal(IrAnalyze *ira, IrInstruction *instruction)
9566 return instruction;9889 return instruction;
9567}9890}
95689891
9569static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) {
9570 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
9571 old_instruction->scope, old_instruction->source_node);
9572 IrInstruction *new_instruction = &const_instruction->base;
9573 new_instruction->value.type = ty;
9574 new_instruction->value.special = ConstValSpecialStatic;
9575 return new_instruction;
9576}
9577
9578static IrInstruction *ir_const_type(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) {9892static IrInstruction *ir_const_type(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) {
9579 IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_type);9893 IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_type);
9580 result->value.data.x_type = ty;9894 result->value.data.x_type = ty;
...@@ -9625,20 +9939,20 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un...@@ -9625,20 +9939,20 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
9625 if (undef_allowed == UndefOk) {9939 if (undef_allowed == UndefOk) {
9626 return &value->value;9940 return &value->value;
9627 } else {9941 } else {
9628 ir_add_error(ira, value, buf_sprintf("use of undefined value"));9942 ir_add_error(ira, value, buf_sprintf("use of undefined value here causes undefined behavior"));
9629 return nullptr;9943 return nullptr;
9630 }9944 }
9631 }9945 }
9632 zig_unreachable();9946 zig_unreachable();
9633}9947}
96349948
9635IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,9949ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
9636 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,9950 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
9637 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,9951 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
9638 IrExecutable *parent_exec)9952 IrExecutable *parent_exec, AstNode *expected_type_source_node)
9639{9953{
9640 if (expected_type != nullptr && type_is_invalid(expected_type))9954 if (expected_type != nullptr && type_is_invalid(expected_type))
9641 return codegen->invalid_instruction;9955 return &codegen->invalid_instruction->value;
96429956
9643 IrExecutable *ir_executable = allocate<IrExecutable>(1);9957 IrExecutable *ir_executable = allocate<IrExecutable>(1);
9644 ir_executable->source_node = source_node;9958 ir_executable->source_node = source_node;
...@@ -9651,13 +9965,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node...@@ -9651,13 +9965,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node
9651 ir_gen(codegen, node, scope, ir_executable);9965 ir_gen(codegen, node, scope, ir_executable);
96529966
9653 if (ir_executable->invalid)9967 if (ir_executable->invalid)
9654 return codegen->invalid_instruction;9968 return &codegen->invalid_instruction->value;
96559969
9656 if (codegen->verbose_ir) {9970 if (codegen->verbose_ir) {
9657 fprintf(stderr, "\nSource: ");9971 fprintf(stderr, "\nSource: ");
9658 ast_render(codegen, stderr, node, 4);9972 ast_render(codegen, stderr, node, 4);
9659 fprintf(stderr, "\n{ // (IR)\n");9973 fprintf(stderr, "\n{ // (IR)\n");
9660 ir_print(codegen, stderr, ir_executable, 4);9974 ir_print(codegen, stderr, ir_executable, 2);
9661 fprintf(stderr, "}\n");9975 fprintf(stderr, "}\n");
9662 }9976 }
9663 IrExecutable *analyzed_executable = allocate<IrExecutable>(1);9977 IrExecutable *analyzed_executable = allocate<IrExecutable>(1);
...@@ -9671,13 +9985,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node...@@ -9671,13 +9985,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node
9671 analyzed_executable->backward_branch_count = backward_branch_count;9985 analyzed_executable->backward_branch_count = backward_branch_count;
9672 analyzed_executable->backward_branch_quota = backward_branch_quota;9986 analyzed_executable->backward_branch_quota = backward_branch_quota;
9673 analyzed_executable->begin_scope = scope;9987 analyzed_executable->begin_scope = scope;
9674 ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, node);9988 ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, expected_type_source_node);
9675 if (type_is_invalid(result_type))9989 if (type_is_invalid(result_type))
9676 return codegen->invalid_instruction;9990 return &codegen->invalid_instruction->value;
96779991
9678 if (codegen->verbose_ir) {9992 if (codegen->verbose_ir) {
9679 fprintf(stderr, "{ // (analyzed)\n");9993 fprintf(stderr, "{ // (analyzed)\n");
9680 ir_print(codegen, stderr, analyzed_executable, 4);9994 ir_print(codegen, stderr, analyzed_executable, 2);
9681 fprintf(stderr, "}\n");9995 fprintf(stderr, "}\n");
9682 }9996 }
96839997
...@@ -9702,6 +10016,34 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {...@@ -9702,6 +10016,34 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {
9702 return const_val->data.x_type;10016 return const_val->data.x_type;
9703}10017}
970410018
10019static ZigType *ir_resolve_error_set_type(IrAnalyze *ira, IrInstruction *op_source, IrInstruction *type_value) {
10020 if (type_is_invalid(type_value->value.type))
10021 return ira->codegen->builtin_types.entry_invalid;
10022
10023 if (type_value->value.type->id != ZigTypeIdMetaType) {
10024 ErrorMsg *msg = ir_add_error(ira, type_value,
10025 buf_sprintf("expected error set type, found '%s'", buf_ptr(&type_value->value.type->name)));
10026 add_error_note(ira->codegen, msg, op_source->source_node,
10027 buf_sprintf("`||` merges error sets; `or` performs boolean OR"));
10028 return ira->codegen->builtin_types.entry_invalid;
10029 }
10030
10031 ConstExprValue *const_val = ir_resolve_const(ira, type_value, UndefBad);
10032 if (!const_val)
10033 return ira->codegen->builtin_types.entry_invalid;
10034
10035 assert(const_val->data.x_type != nullptr);
10036 ZigType *result_type = const_val->data.x_type;
10037 if (result_type->id != ZigTypeIdErrorSet) {
10038 ErrorMsg *msg = ir_add_error(ira, type_value,
10039 buf_sprintf("expected error set type, found type '%s'", buf_ptr(&result_type->name)));
10040 add_error_note(ira->codegen, msg, op_source->source_node,
10041 buf_sprintf("`||` merges error sets; `or` performs boolean OR"));
10042 return ira->codegen->builtin_types.entry_invalid;
10043 }
10044 return result_type;
10045}
10046
9705static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {10047static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
9706 if (fn_value == ira->codegen->invalid_instruction)10048 if (fn_value == ira->codegen->invalid_instruction)
9707 return nullptr;10049 return nullptr;
...@@ -9723,7 +10065,9 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {...@@ -9723,7 +10065,9 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
9723 return const_val->data.x_ptr.data.fn.fn_entry;10065 return const_val->data.x_ptr.data.fn.fn_entry;
9724}10066}
972510067
9726static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *wanted_type) {10068static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
10069 ZigType *wanted_type)
10070{
9727 assert(wanted_type->id == ZigTypeIdOptional);10071 assert(wanted_type->id == ZigTypeIdOptional);
972810072
9729 if (instr_is_comptime(value)) {10073 if (instr_is_comptime(value)) {
...@@ -9739,7 +10083,7 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc...@@ -9739,7 +10083,7 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc
9739 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,10083 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
9740 source_instr->scope, source_instr->source_node);10084 source_instr->scope, source_instr->source_node);
9741 const_instruction->base.value.special = ConstValSpecialStatic;10085 const_instruction->base.value.special = ConstValSpecialStatic;
9742 if (get_codegen_ptr_type(wanted_type) != nullptr) {10086 if (types_have_same_zig_comptime_repr(wanted_type, payload_type)) {
9743 copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst);10087 copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst);
9744 } else {10088 } else {
9745 const_instruction->base.value.data.x_optional = val;10089 const_instruction->base.value.data.x_optional = val;
...@@ -9770,11 +10114,16 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction...@@ -9770,11 +10114,16 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
9770 if (!val)10114 if (!val)
9771 return ira->codegen->invalid_instruction;10115 return ira->codegen->invalid_instruction;
977210116
10117 ConstExprValue *err_set_val = create_const_vals(1);
10118 err_set_val->type = wanted_type->data.error_union.err_set_type;
10119 err_set_val->special = ConstValSpecialStatic;
10120 err_set_val->data.x_err_set = nullptr;
10121
9773 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,10122 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
9774 source_instr->scope, source_instr->source_node);10123 source_instr->scope, source_instr->source_node);
9775 const_instruction->base.value.type = wanted_type;10124 const_instruction->base.value.type = wanted_type;
9776 const_instruction->base.value.special = ConstValSpecialStatic;10125 const_instruction->base.value.special = ConstValSpecialStatic;
9777 const_instruction->base.value.data.x_err_union.err = nullptr;10126 const_instruction->base.value.data.x_err_union.error_set = err_set_val;
9778 const_instruction->base.value.data.x_err_union.payload = val;10127 const_instruction->base.value.data.x_err_union.payload = val;
9779 return &const_instruction->base;10128 return &const_instruction->base;
9780 }10129 }
...@@ -9839,11 +10188,16 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so...@@ -9839,11 +10188,16 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so
9839 if (!val)10188 if (!val)
9840 return ira->codegen->invalid_instruction;10189 return ira->codegen->invalid_instruction;
984110190
10191 ConstExprValue *err_set_val = create_const_vals(1);
10192 err_set_val->special = ConstValSpecialStatic;
10193 err_set_val->type = wanted_type->data.error_union.err_set_type;
10194 err_set_val->data.x_err_set = val->data.x_err_set;
10195
9842 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,10196 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
9843 source_instr->scope, source_instr->source_node);10197 source_instr->scope, source_instr->source_node);
9844 const_instruction->base.value.type = wanted_type;10198 const_instruction->base.value.type = wanted_type;
9845 const_instruction->base.value.special = ConstValSpecialStatic;10199 const_instruction->base.value.special = ConstValSpecialStatic;
9846 const_instruction->base.value.data.x_err_union.err = val->data.x_err_set;10200 const_instruction->base.value.data.x_err_union.error_set = err_set_val;
9847 const_instruction->base.value.data.x_err_union.payload = nullptr;10201 const_instruction->base.value.data.x_err_union.payload = nullptr;
9848 return &const_instruction->base;10202 return &const_instruction->base;
9849 }10203 }
...@@ -9865,8 +10219,9 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so...@@ -9865,8 +10219,9 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so
9865 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, source_instr->scope, source_instr->source_node);10219 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, source_instr->scope, source_instr->source_node);
9866 const_instruction->base.value.special = ConstValSpecialStatic;10220 const_instruction->base.value.special = ConstValSpecialStatic;
9867 if (get_codegen_ptr_type(wanted_type) != nullptr) {10221 if (get_codegen_ptr_type(wanted_type) != nullptr) {
9868 const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;10222 const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialNull;
9869 const_instruction->base.value.data.x_ptr.data.hard_coded_addr.addr = 0;10223 } else if (is_opt_err_set(wanted_type)) {
10224 const_instruction->base.value.data.x_err_set = nullptr;
9870 } else {10225 } else {
9871 const_instruction->base.value.data.x_optional = nullptr;10226 const_instruction->base.value.data.x_optional = nullptr;
9872 }10227 }
...@@ -9899,7 +10254,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi...@@ -9899,7 +10254,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
9899 source_instruction->source_node, value, is_const, is_volatile);10254 source_instruction->source_node, value, is_const, is_volatile);
9900 new_instruction->value.type = ptr_type;10255 new_instruction->value.type = ptr_type;
9901 new_instruction->value.data.rh_ptr = RuntimeHintPtrStack;10256 new_instruction->value.data.rh_ptr = RuntimeHintPtrStack;
9902 if (type_has_bits(ptr_type)) {10257 if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) {
9903 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);10258 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
9904 assert(fn_entry);10259 assert(fn_entry);
9905 fn_entry->alloca_list.append(new_instruction);10260 fn_entry->alloca_list.append(new_instruction);
...@@ -9925,20 +10280,17 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s...@@ -9925,20 +10280,17 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
9925 ZigType *array_type = array->value.type;10280 ZigType *array_type = array->value.type;
9926 assert(array_type->id == ZigTypeIdArray);10281 assert(array_type->id == ZigTypeIdArray);
992710282
9928 if (instr_is_comptime(array)) {10283 if (instr_is_comptime(array) || array_type->data.array.len == 0) {
9929 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10284 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
9930 source_instr->source_node, wanted_type);
9931 init_const_slice(ira->codegen, &result->value, &array->value, 0, array_type->data.array.len, true);10285 init_const_slice(ira->codegen, &result->value, &array->value, 0, array_type->data.array.len, true);
9932 result->value.type = wanted_type;10286 result->value.type = wanted_type;
9933 return result;10287 return result;
9934 }10288 }
993510289
9936 IrInstruction *start = ir_create_const(&ira->new_irb, source_instr->scope,10290 IrInstruction *start = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize);
9937 source_instr->source_node, ira->codegen->builtin_types.entry_usize);
9938 init_const_usize(ira->codegen, &start->value, 0);10291 init_const_usize(ira->codegen, &start->value, 0);
993910292
9940 IrInstruction *end = ir_create_const(&ira->new_irb, source_instr->scope,10293 IrInstruction *end = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize);
9941 source_instr->source_node, ira->codegen->builtin_types.entry_usize);
9942 init_const_usize(ira->codegen, &end->value, array_type->data.array.len);10294 init_const_usize(ira->codegen, &end->value, array_type->data.array.len);
994310295
9944 if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false);10296 if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false);
...@@ -9977,8 +10329,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour...@@ -9977,8 +10329,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
9977 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);10329 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
9978 if (!val)10330 if (!val)
9979 return ira->codegen->invalid_instruction;10331 return ira->codegen->invalid_instruction;
9980 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10332 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
9981 source_instr->source_node, wanted_type);
9982 init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag);10333 init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag);
9983 return result;10334 return result;
9984 }10335 }
...@@ -9988,8 +10339,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour...@@ -9988,8 +10339,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
9988 actual_type->data.enumeration.src_field_count == 1)10339 actual_type->data.enumeration.src_field_count == 1)
9989 {10340 {
9990 assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int);10341 assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int);
9991 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10342 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
9992 source_instr->source_node, wanted_type);
9993 init_const_bigint(&result->value, wanted_type,10343 init_const_bigint(&result->value, wanted_type,
9994 &actual_type->data.enumeration.fields[0].value);10344 &actual_type->data.enumeration.fields[0].value);
9995 return result;10345 return result;
...@@ -10012,8 +10362,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou...@@ -10012,8 +10362,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
10012 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);10362 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
10013 if (!val)10363 if (!val)
10014 return ira->codegen->invalid_instruction;10364 return ira->codegen->invalid_instruction;
10015 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10365 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10016 source_instr->source_node, wanted_type);
10017 result->value.special = ConstValSpecialStatic;10366 result->value.special = ConstValSpecialStatic;
10018 result->value.type = wanted_type;10367 result->value.type = wanted_type;
10019 bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_union.tag);10368 bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_union.tag);
...@@ -10024,8 +10373,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou...@@ -10024,8 +10373,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
10024 if (wanted_type->data.enumeration.layout == ContainerLayoutAuto &&10373 if (wanted_type->data.enumeration.layout == ContainerLayoutAuto &&
10025 wanted_type->data.enumeration.src_field_count == 1)10374 wanted_type->data.enumeration.src_field_count == 1)
10026 {10375 {
10027 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10376 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10028 source_instr->source_node, wanted_type);
10029 result->value.special = ConstValSpecialStatic;10377 result->value.special = ConstValSpecialStatic;
10030 result->value.type = wanted_type;10378 result->value.type = wanted_type;
10031 TypeEnumField *enum_field = target->value.type->data.unionation.fields[0].enum_field;10379 TypeEnumField *enum_field = target->value.type->data.unionation.fields[0].enum_field;
...@@ -10042,8 +10390,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou...@@ -10042,8 +10390,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
10042static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr,10390static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr,
10043 IrInstruction *target, ZigType *wanted_type)10391 IrInstruction *target, ZigType *wanted_type)
10044{10392{
10045 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10393 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10046 source_instr->source_node, wanted_type);
10047 init_const_undefined(ira->codegen, &result->value);10394 init_const_undefined(ira->codegen, &result->value);
10048 return result;10395 return result;
10049}10396}
...@@ -10075,8 +10422,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so...@@ -10075,8 +10422,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so
10075 buf_sprintf("field '%s' declared here", buf_ptr(union_field->name)));10422 buf_sprintf("field '%s' declared here", buf_ptr(union_field->name)));
10076 return ira->codegen->invalid_instruction;10423 return ira->codegen->invalid_instruction;
10077 }10424 }
10078 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10425 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10079 source_instr->source_node, wanted_type);
10080 result->value.special = ConstValSpecialStatic;10426 result->value.special = ConstValSpecialStatic;
10081 result->value.type = wanted_type;10427 result->value.type = wanted_type;
10082 bigint_init_bigint(&result->value.data.x_union.tag, &val->data.x_enum_tag);10428 bigint_init_bigint(&result->value.data.x_union.tag, &val->data.x_enum_tag);
...@@ -10131,8 +10477,7 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction...@@ -10131,8 +10477,7 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction
10131 return ira->codegen->invalid_instruction;10477 return ira->codegen->invalid_instruction;
10132 }10478 }
10133 }10479 }
10134 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10480 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10135 source_instr->source_node, wanted_type);
10136 result->value.type = wanted_type;10481 result->value.type = wanted_type;
10137 if (wanted_type->id == ZigTypeIdInt) {10482 if (wanted_type->id == ZigTypeIdInt) {
10138 bigint_init_bigint(&result->value.data.x_bigint, &val->data.x_bigint);10483 bigint_init_bigint(&result->value.data.x_bigint, &val->data.x_bigint);
...@@ -10142,6 +10487,18 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction...@@ -10142,6 +10487,18 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction
10142 return result;10487 return result;
10143 }10488 }
1014410489
10490 // If the destination integer type has no bits, then we can emit a comptime
10491 // zero. However, we still want to emit a runtime safety check to make sure
10492 // the target is zero.
10493 if (!type_has_bits(wanted_type)) {
10494 assert(wanted_type->id == ZigTypeIdInt);
10495 assert(type_has_bits(target->value.type));
10496 ir_build_assert_zero(ira, source_instr, target);
10497 IrInstruction *result = ir_const_unsigned(ira, source_instr, 0);
10498 result->value.type = wanted_type;
10499 return result;
10500 }
10501
10145 IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope,10502 IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope,
10146 source_instr->source_node, target);10503 source_instr->source_node, target);
10147 result->value.type = wanted_type;10504 result->value.type = wanted_type;
...@@ -10186,8 +10543,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour...@@ -10186,8 +10543,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
10186 return ira->codegen->invalid_instruction;10543 return ira->codegen->invalid_instruction;
10187 }10544 }
1018810545
10189 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10546 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10190 source_instr->source_node, wanted_type);
10191 bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_bigint);10547 bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_bigint);
10192 return result;10548 return result;
10193 }10549 }
...@@ -10205,8 +10561,7 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction...@@ -10205,8 +10561,7 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction
10205 if (!val)10561 if (!val)
10206 return ira->codegen->invalid_instruction;10562 return ira->codegen->invalid_instruction;
1020710563
10208 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10564 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10209 source_instr->source_node, wanted_type);
10210 if (wanted_type->id == ZigTypeIdComptimeFloat) {10565 if (wanted_type->id == ZigTypeIdComptimeFloat) {
10211 float_init_float(&result->value, val);10566 float_init_float(&result->value, val);
10212 } else if (wanted_type->id == ZigTypeIdComptimeInt) {10567 } else if (wanted_type->id == ZigTypeIdComptimeInt) {
...@@ -10229,8 +10584,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc...@@ -10229,8 +10584,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc
10229 if (!val)10584 if (!val)
10230 return ira->codegen->invalid_instruction;10585 return ira->codegen->invalid_instruction;
1023110586
10232 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10587 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10233 source_instr->source_node, wanted_type);
1023410588
10235 if (!resolve_inferred_error_set(ira->codegen, wanted_type, source_instr->source_node)) {10589 if (!resolve_inferred_error_set(ira->codegen, wanted_type, source_instr->source_node)) {
10236 return ira->codegen->invalid_instruction;10590 return ira->codegen->invalid_instruction;
...@@ -10294,12 +10648,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc...@@ -10294,12 +10648,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
10294 if (!val)10648 if (!val)
10295 return ira->codegen->invalid_instruction;10649 return ira->codegen->invalid_instruction;
1029610650
10297 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10651 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10298 source_instr->source_node, wanted_type);
1029910652
10300 ErrorTableEntry *err;10653 ErrorTableEntry *err;
10301 if (err_type->id == ZigTypeIdErrorUnion) {10654 if (err_type->id == ZigTypeIdErrorUnion) {
10302 err = val->data.x_err_union.err;10655 err = val->data.x_err_union.error_set->data.x_err_set;
10303 } else if (err_type->id == ZigTypeIdErrorSet) {10656 } else if (err_type->id == ZigTypeIdErrorSet) {
10304 err = val->data.x_err_set;10657 err = val->data.x_err_set;
10305 } else {10658 } else {
...@@ -10334,15 +10687,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc...@@ -10334,15 +10687,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
10334 return ira->codegen->invalid_instruction;10687 return ira->codegen->invalid_instruction;
10335 }10688 }
10336 if (err_set_type->data.error_set.err_count == 0) {10689 if (err_set_type->data.error_set.err_count == 0) {
10337 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10690 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10338 source_instr->source_node, wanted_type);
10339 result->value.type = wanted_type;
10340 bigint_init_unsigned(&result->value.data.x_bigint, 0);10691 bigint_init_unsigned(&result->value.data.x_bigint, 0);
10341 return result;10692 return result;
10342 } else if (err_set_type->data.error_set.err_count == 1) {10693 } else if (err_set_type->data.error_set.err_count == 1) {
10343 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10694 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10344 source_instr->source_node, wanted_type);
10345 result->value.type = wanted_type;
10346 ErrorTableEntry *err = err_set_type->data.error_set.errors[0];10695 ErrorTableEntry *err = err_set_type->data.error_set.errors[0];
10347 bigint_init_unsigned(&result->value.data.x_bigint, err->value);10696 bigint_init_unsigned(&result->value.data.x_bigint, err->value);
10348 return result;10697 return result;
...@@ -10380,7 +10729,7 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou...@@ -10380,7 +10729,7 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou
10380 return ira->codegen->invalid_instruction;10729 return ira->codegen->invalid_instruction;
1038110730
10382 assert(val->type->id == ZigTypeIdPointer);10731 assert(val->type->id == ZigTypeIdPointer);
10383 ConstExprValue *pointee = ir_const_ptr_pointee(ira, val, source_instr->source_node);10732 ConstExprValue *pointee = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node);
10384 if (pointee == nullptr)10733 if (pointee == nullptr)
10385 return ira->codegen->invalid_instruction;10734 return ira->codegen->invalid_instruction;
10386 if (pointee->special != ConstValSpecialRuntime) {10735 if (pointee->special != ConstValSpecialRuntime) {
...@@ -10389,8 +10738,8 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou...@@ -10389,8 +10738,8 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou
10389 array_val->type = array_type;10738 array_val->type = array_type;
10390 array_val->data.x_array.special = ConstArraySpecialNone;10739 array_val->data.x_array.special = ConstArraySpecialNone;
10391 array_val->data.x_array.data.s_none.elements = pointee;10740 array_val->data.x_array.data.s_none.elements = pointee;
10392 array_val->data.x_array.data.s_none.parent.id = ConstParentIdScalar;10741 array_val->parent.id = ConstParentIdScalar;
10393 array_val->data.x_array.data.s_none.parent.data.p_scalar.scalar_val = pointee;10742 array_val->parent.data.p_scalar.scalar_val = pointee;
1039410743
10395 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,10744 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
10396 source_instr->scope, source_instr->source_node);10745 source_instr->scope, source_instr->source_node);
...@@ -10496,21 +10845,100 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa...@@ -10496,21 +10845,100 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
10496 report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg);10845 report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg);
10497 break;10846 break;
10498 }10847 }
10848 case ConstCastResultIdBadAllowsZero: {
10849 ZigType *wanted_type = cast_result->data.bad_allows_zero->wanted_type;
10850 ZigType *actual_type = cast_result->data.bad_allows_zero->actual_type;
10851 bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);
10852 bool actual_allows_zero = ptr_allows_addr_zero(actual_type);
10853 if (actual_allows_zero && !wanted_allows_zero) {
10854 add_error_note(ira->codegen, parent_msg, source_node,
10855 buf_sprintf("'%s' could have null values which are illegal in type '%s'",
10856 buf_ptr(&actual_type->name),
10857 buf_ptr(&wanted_type->name)));
10858 } else {
10859 add_error_note(ira->codegen, parent_msg, source_node,
10860 buf_sprintf("mutable '%s' allows illegal null values stored to type '%s'",
10861 buf_ptr(&wanted_type->name),
10862 buf_ptr(&actual_type->name)));
10863 }
10864 break;
10865 }
10866 case ConstCastResultIdFnIsGeneric:
10867 add_error_note(ira->codegen, parent_msg, source_node,
10868 buf_sprintf("only one of the functions is generic"));
10869 break;
10499 case ConstCastResultIdFnAlign: // TODO10870 case ConstCastResultIdFnAlign: // TODO
10500 case ConstCastResultIdFnCC: // TODO10871 case ConstCastResultIdFnCC: // TODO
10501 case ConstCastResultIdFnVarArgs: // TODO10872 case ConstCastResultIdFnVarArgs: // TODO
10502 case ConstCastResultIdFnIsGeneric: // TODO
10503 case ConstCastResultIdFnReturnType: // TODO10873 case ConstCastResultIdFnReturnType: // TODO
10504 case ConstCastResultIdFnArgCount: // TODO10874 case ConstCastResultIdFnArgCount: // TODO
10505 case ConstCastResultIdFnGenericArgCount: // TODO10875 case ConstCastResultIdFnGenericArgCount: // TODO
10506 case ConstCastResultIdFnArgNoAlias: // TODO10876 case ConstCastResultIdFnArgNoAlias: // TODO
10507 case ConstCastResultIdUnresolvedInferredErrSet: // TODO10877 case ConstCastResultIdUnresolvedInferredErrSet: // TODO
10508 case ConstCastResultIdAsyncAllocatorType: // TODO10878 case ConstCastResultIdAsyncAllocatorType: // TODO
10509 case ConstCastResultIdNullWrapPtr: // TODO
10510 break;10879 break;
10511 }10880 }
10512}10881}
1051310882
10883static IrInstruction *ir_analyze_array_to_vector(IrAnalyze *ira, IrInstruction *source_instr,
10884 IrInstruction *array, ZigType *vector_type)
10885{
10886 if (instr_is_comptime(array)) {
10887 // arrays and vectors have the same ConstExprValue representation
10888 IrInstruction *result = ir_const(ira, source_instr, vector_type);
10889 copy_const_val(&result->value, &array->value, false);
10890 result->value.type = vector_type;
10891 return result;
10892 }
10893 return ir_build_array_to_vector(ira, source_instr, array, vector_type);
10894}
10895
10896static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *source_instr,
10897 IrInstruction *vector, ZigType *array_type)
10898{
10899 if (instr_is_comptime(vector)) {
10900 // arrays and vectors have the same ConstExprValue representation
10901 IrInstruction *result = ir_const(ira, source_instr, array_type);
10902 copy_const_val(&result->value, &vector->value, false);
10903 result->value.type = array_type;
10904 return result;
10905 }
10906 return ir_build_vector_to_array(ira, source_instr, vector, array_type);
10907}
10908
10909static IrInstruction *ir_analyze_int_to_c_ptr(IrAnalyze *ira, IrInstruction *source_instr,
10910 IrInstruction *integer, ZigType *dest_type)
10911{
10912 IrInstruction *unsigned_integer;
10913 if (instr_is_comptime(integer)) {
10914 unsigned_integer = integer;
10915 } else {
10916 assert(integer->value.type->id == ZigTypeIdInt);
10917
10918 if (integer->value.type->data.integral.bit_count >
10919 ira->codegen->builtin_types.entry_usize->data.integral.bit_count)
10920 {
10921 ir_add_error(ira, source_instr,
10922 buf_sprintf("integer type '%s' too big for implicit @intToPtr to type '%s'",
10923 buf_ptr(&integer->value.type->name),
10924 buf_ptr(&dest_type->name)));
10925 return ira->codegen->invalid_instruction;
10926 }
10927
10928 if (integer->value.type->data.integral.is_signed) {
10929 ZigType *unsigned_int_type = get_int_type(ira->codegen, false,
10930 integer->value.type->data.integral.bit_count);
10931 unsigned_integer = ir_analyze_bit_cast(ira, source_instr, integer, unsigned_int_type);
10932 if (type_is_invalid(unsigned_integer->value.type))
10933 return ira->codegen->invalid_instruction;
10934 } else {
10935 unsigned_integer = integer;
10936 }
10937 }
10938
10939 return ir_analyze_int_to_ptr(ira, source_instr, unsigned_integer, dest_type);
10940}
10941
10514static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,10942static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
10515 ZigType *wanted_type, IrInstruction *value)10943 ZigType *wanted_type, IrInstruction *value)
10516{10944{
...@@ -10538,12 +10966,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10538,12 +10966,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10538 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,10966 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,
10539 false).id == ConstCastResultIdOk)10967 false).id == ConstCastResultIdOk)
10540 {10968 {
10541 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);10969 return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type);
10542 } else if (actual_type->id == ZigTypeIdComptimeInt ||10970 } else if (actual_type->id == ZigTypeIdComptimeInt ||
10543 actual_type->id == ZigTypeIdComptimeFloat)10971 actual_type->id == ZigTypeIdComptimeFloat)
10544 {10972 {
10545 if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {10973 if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {
10546 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);10974 return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type);
10547 } else {10975 } else {
10548 return ira->codegen->invalid_instruction;10976 return ira->codegen->invalid_instruction;
10549 }10977 }
...@@ -10567,7 +10995,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10567,7 +10995,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10567 wanted_child_type);10995 wanted_child_type);
10568 if (type_is_invalid(cast1->value.type))10996 if (type_is_invalid(cast1->value.type))
10569 return ira->codegen->invalid_instruction;10997 return ira->codegen->invalid_instruction;
10570 return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type);10998 return ir_analyze_optional_wrap(ira, source_instr, cast1, wanted_type);
10571 }10999 }
10572 }11000 }
10573 }11001 }
...@@ -10620,6 +11048,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10620,6 +11048,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10620 (wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt ||11048 (wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt ||
10621 wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat))11049 wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat))
10622 {11050 {
11051 if (value->value.special == ConstValSpecialUndef) {
11052 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
11053 result->value.special = ConstValSpecialUndef;
11054 return result;
11055 }
10623 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {11056 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {
10624 if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) {11057 if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) {
10625 IrInstruction *result = ir_const(ira, source_instr, wanted_type);11058 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
...@@ -10673,6 +11106,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10673,6 +11106,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1067311106
1067411107
10675 // cast from [N]T to []const T11108 // cast from [N]T to []const T
11109 // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
10676 if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) {11110 if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) {
10677 ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;11111 ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
10678 assert(ptr_type->id == ZigTypeIdPointer);11112 assert(ptr_type->id == ZigTypeIdPointer);
...@@ -10685,6 +11119,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10685,6 +11119,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10685 }11119 }
1068611120
10687 // cast from [N]T to ?[]const T11121 // cast from [N]T to ?[]const T
11122 // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
10688 if (wanted_type->id == ZigTypeIdOptional &&11123 if (wanted_type->id == ZigTypeIdOptional &&
10689 is_slice(wanted_type->data.maybe.child_type) &&11124 is_slice(wanted_type->data.maybe.child_type) &&
10690 actual_type->id == ZigTypeIdArray)11125 actual_type->id == ZigTypeIdArray)
...@@ -10779,7 +11214,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10779,7 +11214,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10779 }11214 }
10780 }11215 }
1078111216
10782 // cast from error set to error union type11217 // cast from E to E!T
10783 if (wanted_type->id == ZigTypeIdErrorUnion &&11218 if (wanted_type->id == ZigTypeIdErrorUnion &&
10784 actual_type->id == ZigTypeIdErrorSet)11219 actual_type->id == ZigTypeIdErrorSet)
10785 {11220 {
...@@ -10875,7 +11310,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10875,7 +11310,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10875 actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes &&11310 actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes &&
10876 get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type))11311 get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type))
10877 {11312 {
10878 return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr);11313 return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr, true);
10879 }11314 }
10880 }11315 }
1088111316
...@@ -10892,6 +11327,40 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10892,6 +11327,40 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10892 }11327 }
10893 }11328 }
1089411329
11330 // cast from @Vector(N, T) to [N]T
11331 if (wanted_type->id == ZigTypeIdArray && actual_type->id == ZigTypeIdVector &&
11332 wanted_type->data.array.len == actual_type->data.vector.len &&
11333 types_match_const_cast_only(ira, wanted_type->data.array.child_type,
11334 actual_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk)
11335 {
11336 return ir_analyze_vector_to_array(ira, source_instr, value, wanted_type);
11337 }
11338
11339 // cast from [N]T to @Vector(N, T)
11340 if (actual_type->id == ZigTypeIdArray && wanted_type->id == ZigTypeIdVector &&
11341 actual_type->data.array.len == wanted_type->data.vector.len &&
11342 types_match_const_cast_only(ira, actual_type->data.array.child_type,
11343 wanted_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk)
11344 {
11345 return ir_analyze_array_to_vector(ira, source_instr, value, wanted_type);
11346 }
11347
11348 // casting between C pointers and normal pointers
11349 if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer &&
11350 (wanted_type->data.pointer.ptr_len == PtrLenC || actual_type->data.pointer.ptr_len == PtrLenC) &&
11351 types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
11352 actual_type->data.pointer.child_type, source_node,
11353 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
11354 {
11355 return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr, true);
11356 }
11357
11358 // cast from integer to C pointer
11359 if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC &&
11360 (actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt))
11361 {
11362 return ir_analyze_int_to_c_ptr(ira, source_instr, value, wanted_type);
11363 }
1089511364
10896 // cast from undefined to anything11365 // cast from undefined to anything
10897 if (actual_type->id == ZigTypeIdUndefined) {11366 if (actual_type->id == ZigTypeIdUndefined) {
...@@ -10931,8 +11400,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -10931,8 +11400,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
10931 ZigType *child_type = type_entry->data.pointer.child_type;11400 ZigType *child_type = type_entry->data.pointer.child_type;
10932 // dereferencing a *u0 is comptime known to be 011401 // dereferencing a *u0 is comptime known to be 0
10933 if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) {11402 if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) {
10934 IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,11403 IrInstruction *result = ir_const(ira, source_instruction, child_type);
10935 source_instruction->source_node, child_type);
10936 init_const_unsigned_negative(&result->value, child_type, 0, false);11404 init_const_unsigned_negative(&result->value, child_type, 0, false);
10937 return result;11405 return result;
10938 }11406 }
...@@ -10946,10 +11414,9 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -10946,10 +11414,9 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
10946 {11414 {
10947 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);11415 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
10948 if (pointee->special != ConstValSpecialRuntime) {11416 if (pointee->special != ConstValSpecialRuntime) {
10949 IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,11417 IrInstruction *result = ir_const(ira, source_instruction, child_type);
10950 source_instruction->source_node, child_type);
1095111418
10952 if ((err = ir_read_const_ptr(ira, source_instruction->source_node, &result->value,11419 if ((err = ir_read_const_ptr(ira, ira->codegen, source_instruction->source_node, &result->value,
10953 &ptr->value)))11420 &ptr->value)))
10954 {11421 {
10955 return ira->codegen->invalid_instruction;11422 return ira->codegen->invalid_instruction;
...@@ -10959,7 +11426,11 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -10959,7 +11426,11 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
10959 }11426 }
10960 }11427 }
10961 }11428 }
10962 // TODO if the instruction is a const ref instruction we can skip it11429 // if the instruction is a const ref instruction we can skip it
11430 if (ptr->id == IrInstructionIdRef) {
11431 IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr);
11432 return ref_inst->value;
11433 }
10963 IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,11434 IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,
10964 source_instruction->source_node, ptr);11435 source_instruction->source_node, ptr);
10965 load_ptr_instruction->value.type = child_type;11436 load_ptr_instruction->value.type = child_type;
...@@ -11184,10 +11655,13 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio...@@ -11184,10 +11655,13 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio
11184 return ir_unreach_error(ira);11655 return ir_unreach_error(ira);
1118511656
11186 IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->explicit_return_type);11657 IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->explicit_return_type);
11187 if (type_is_invalid(casted_value->value.type) && ira->explicit_return_type_source_node != nullptr) {11658 if (type_is_invalid(casted_value->value.type)) {
11188 ErrorMsg *msg = ira->codegen->errors.last();11659 AstNode *source_node = ira->explicit_return_type_source_node;
11189 add_error_note(ira->codegen, msg, ira->explicit_return_type_source_node,11660 if (source_node != nullptr) {
11190 buf_sprintf("return type declared here"));11661 ErrorMsg *msg = ira->codegen->errors.last();
11662 add_error_note(ira->codegen, msg, source_node,
11663 buf_sprintf("return type declared here"));
11664 }
11191 return ir_unreach_error(ira);11665 return ir_unreach_error(ira);
11192 }11666 }
1119311667
...@@ -11206,8 +11680,7 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio...@@ -11206,8 +11680,7 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio
1120611680
11207static IrInstruction *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *instruction) {11681static IrInstruction *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *instruction) {
11208 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);11682 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
11209 // TODO determine if we need to use copy_const_val here11683 copy_const_val(&result->value, &instruction->base.value, true);
11210 result->value = instruction->base.value;
11211 return result;11684 return result;
11212}11685}
1121311686
...@@ -11260,28 +11733,36 @@ static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp...@@ -11260,28 +11733,36 @@ static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
11260}11733}
1126111734
11262static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {11735static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {
11263 if (op_id == IrBinOpCmpEq) {11736 switch (op_id) {
11264 return cmp == CmpEQ;11737 case IrBinOpCmpEq:
11265 } else if (op_id == IrBinOpCmpNotEq) {11738 return cmp == CmpEQ;
11266 return cmp != CmpEQ;11739 case IrBinOpCmpNotEq:
11267 } else if (op_id == IrBinOpCmpLessThan) {11740 return cmp != CmpEQ;
11268 return cmp == CmpLT;11741 case IrBinOpCmpLessThan:
11269 } else if (op_id == IrBinOpCmpGreaterThan) {11742 return cmp == CmpLT;
11270 return cmp == CmpGT;11743 case IrBinOpCmpGreaterThan:
11271 } else if (op_id == IrBinOpCmpLessOrEq) {11744 return cmp == CmpGT;
11272 return cmp != CmpGT;11745 case IrBinOpCmpLessOrEq:
11273 } else if (op_id == IrBinOpCmpGreaterOrEq) {11746 return cmp != CmpGT;
11274 return cmp != CmpLT;11747 case IrBinOpCmpGreaterOrEq:
11275 } else {11748 return cmp != CmpLT;
11276 zig_unreachable();11749 default:
11750 zig_unreachable();
11277 }11751 }
11278}11752}
1127911753
11280static bool optional_value_is_null(ConstExprValue *val) {11754static bool optional_value_is_null(ConstExprValue *val) {
11281 assert(val->special == ConstValSpecialStatic);11755 assert(val->special == ConstValSpecialStatic);
11282 if (get_codegen_ptr_type(val->type) != nullptr) {11756 if (get_codegen_ptr_type(val->type) != nullptr) {
11283 return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&11757 if (val->data.x_ptr.special == ConstPtrSpecialNull) {
11284 val->data.x_ptr.data.hard_coded_addr.addr == 0;11758 return true;
11759 } else if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
11760 return val->data.x_ptr.data.hard_coded_addr.addr == 0;
11761 } else {
11762 return false;
11763 }
11764 } else if (is_opt_err_set(val->type)) {
11765 return val->data.x_err_set == nullptr;
11285 } else {11766 } else {
11286 return val->data.x_optional == nullptr;11767 return val->data.x_optional == nullptr;
11287 }11768 }
...@@ -11436,13 +11917,13 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11436,13 +11917,13 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11436 case ZigTypeIdComptimeInt:11917 case ZigTypeIdComptimeInt:
11437 case ZigTypeIdInt:11918 case ZigTypeIdInt:
11438 case ZigTypeIdFloat:11919 case ZigTypeIdFloat:
11920 case ZigTypeIdVector:
11439 operator_allowed = true;11921 operator_allowed = true;
11440 break;11922 break;
1144111923
11442 case ZigTypeIdBool:11924 case ZigTypeIdBool:
11443 case ZigTypeIdMetaType:11925 case ZigTypeIdMetaType:
11444 case ZigTypeIdVoid:11926 case ZigTypeIdVoid:
11445 case ZigTypeIdPointer:
11446 case ZigTypeIdErrorSet:11927 case ZigTypeIdErrorSet:
11447 case ZigTypeIdFn:11928 case ZigTypeIdFn:
11448 case ZigTypeIdOpaque:11929 case ZigTypeIdOpaque:
...@@ -11454,6 +11935,10 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11454,6 +11935,10 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11454 operator_allowed = is_equality_cmp;11935 operator_allowed = is_equality_cmp;
11455 break;11936 break;
1145611937
11938 case ZigTypeIdPointer:
11939 operator_allowed = is_equality_cmp || (resolved_type->data.pointer.ptr_len == PtrLenC);
11940 break;
11941
11457 case ZigTypeIdUnreachable:11942 case ZigTypeIdUnreachable:
11458 case ZigTypeIdArray:11943 case ZigTypeIdArray:
11459 case ZigTypeIdStruct:11944 case ZigTypeIdStruct:
...@@ -11481,19 +11966,18 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11481,19 +11966,18 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11481 if (casted_op2 == ira->codegen->invalid_instruction)11966 if (casted_op2 == ira->codegen->invalid_instruction)
11482 return ira->codegen->invalid_instruction;11967 return ira->codegen->invalid_instruction;
1148311968
11484 bool requires_comptime;11969 bool one_possible_value;
11485 switch (type_requires_comptime(ira->codegen, resolved_type)) {11970 switch (type_has_one_possible_value(ira->codegen, resolved_type)) {
11486 case ReqCompTimeYes:11971 case OnePossibleValueInvalid:
11487 requires_comptime = true;11972 return ira->codegen->invalid_instruction;
11973 case OnePossibleValueYes:
11974 one_possible_value = true;
11488 break;11975 break;
11489 case ReqCompTimeNo:11976 case OnePossibleValueNo:
11490 requires_comptime = false;11977 one_possible_value = false;
11491 break;11978 break;
11492 case ReqCompTimeInvalid:
11493 return ira->codegen->invalid_instruction;
11494 }11979 }
1149511980
11496 bool one_possible_value = !requires_comptime && !type_has_bits(resolved_type);
11497 if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {11981 if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {
11498 ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad);11982 ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad);
11499 if (op1_val == nullptr)11983 if (op1_val == nullptr)
...@@ -11502,15 +11986,38 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11502,15 +11986,38 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11502 if (op2_val == nullptr)11986 if (op2_val == nullptr)
11503 return ira->codegen->invalid_instruction;11987 return ira->codegen->invalid_instruction;
1150411988
11505 bool answer;
11506 if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) {11989 if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) {
11507 Cmp cmp_result = float_cmp(op1_val, op2_val);11990 Cmp cmp_result = float_cmp(op1_val, op2_val);
11508 answer = resolve_cmp_op_id(op_id, cmp_result);11991 bool answer = resolve_cmp_op_id(op_id, cmp_result);
11992 return ir_const_bool(ira, &bin_op_instruction->base, answer);
11509 } else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) {11993 } else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) {
11510 Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);11994 Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);
11511 answer = resolve_cmp_op_id(op_id, cmp_result);11995 bool answer = resolve_cmp_op_id(op_id, cmp_result);
11996 return ir_const_bool(ira, &bin_op_instruction->base, answer);
11997 } else if (resolved_type->id == ZigTypeIdPointer && op_id != IrBinOpCmpEq && op_id != IrBinOpCmpNotEq) {
11998 if ((op1_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
11999 op1_val->data.x_ptr.special == ConstPtrSpecialNull) &&
12000 (op2_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
12001 op2_val->data.x_ptr.special == ConstPtrSpecialNull))
12002 {
12003 uint64_t op1_addr = op1_val->data.x_ptr.special == ConstPtrSpecialNull ?
12004 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr;
12005 uint64_t op2_addr = op2_val->data.x_ptr.special == ConstPtrSpecialNull ?
12006 0 : op2_val->data.x_ptr.data.hard_coded_addr.addr;
12007 Cmp cmp_result;
12008 if (op1_addr > op2_addr) {
12009 cmp_result = CmpGT;
12010 } else if (op1_addr < op2_addr) {
12011 cmp_result = CmpLT;
12012 } else {
12013 cmp_result = CmpEQ;
12014 }
12015 bool answer = resolve_cmp_op_id(op_id, cmp_result);
12016 return ir_const_bool(ira, &bin_op_instruction->base, answer);
12017 }
11512 } else {12018 } else {
11513 bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val);12019 bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val);
12020 bool answer;
11514 if (op_id == IrBinOpCmpEq) {12021 if (op_id == IrBinOpCmpEq) {
11515 answer = are_equal;12022 answer = are_equal;
11516 } else if (op_id == IrBinOpCmpNotEq) {12023 } else if (op_id == IrBinOpCmpNotEq) {
...@@ -11518,9 +12025,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11518,9 +12025,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11518 } else {12025 } else {
11519 zig_unreachable();12026 zig_unreachable();
11520 }12027 }
12028 return ir_const_bool(ira, &bin_op_instruction->base, answer);
11521 }12029 }
11522
11523 return ir_const_bool(ira, &bin_op_instruction->base, answer);
11524 }12030 }
1152512031
11526 // some comparisons with unsigned numbers can be evaluated12032 // some comparisons with unsigned numbers can be evaluated
...@@ -11567,8 +12073,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11567,8 +12073,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11567 return result;12073 return result;
11568}12074}
1156912075
11570static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,12076static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, IrInstruction *source_instr, ZigType *type_entry,
11571 IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val)12077 ConstExprValue *op1_val, IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val)
11572{12078{
11573 bool is_int;12079 bool is_int;
11574 bool is_float;12080 bool is_float;
...@@ -11590,10 +12096,10 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,...@@ -11590,10 +12096,10 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
11590 if ((op_id == IrBinOpDivUnspecified || op_id == IrBinOpRemRem || op_id == IrBinOpRemMod ||12096 if ((op_id == IrBinOpDivUnspecified || op_id == IrBinOpRemRem || op_id == IrBinOpRemMod ||
11591 op_id == IrBinOpDivTrunc || op_id == IrBinOpDivFloor) && op2_zcmp == CmpEQ)12097 op_id == IrBinOpDivTrunc || op_id == IrBinOpDivFloor) && op2_zcmp == CmpEQ)
11592 {12098 {
11593 return ErrorDivByZero;12099 return ir_add_error(ira, source_instr, buf_sprintf("division by zero"));
11594 }12100 }
11595 if ((op_id == IrBinOpRemRem || op_id == IrBinOpRemMod) && op2_zcmp == CmpLT) {12101 if ((op_id == IrBinOpRemRem || op_id == IrBinOpRemMod) && op2_zcmp == CmpLT) {
11596 return ErrorNegativeDenominator;12102 return ir_add_error(ira, source_instr, buf_sprintf("negative denominator"));
11597 }12103 }
1159812104
11599 switch (op_id) {12105 switch (op_id) {
...@@ -11639,7 +12145,7 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,...@@ -11639,7 +12145,7 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
11639 BigInt orig_bigint;12145 BigInt orig_bigint;
11640 bigint_shl(&orig_bigint, &out_val->data.x_bigint, &op2_val->data.x_bigint);12146 bigint_shl(&orig_bigint, &out_val->data.x_bigint, &op2_val->data.x_bigint);
11641 if (bigint_cmp(&op1_val->data.x_bigint, &orig_bigint) != CmpEQ) {12147 if (bigint_cmp(&op1_val->data.x_bigint, &orig_bigint) != CmpEQ) {
11642 return ErrorShiftedOutOneBits;12148 return ir_add_error(ira, source_instr, buf_sprintf("exact shift shifted out 1 bits"));
11643 }12149 }
11644 break;12150 break;
11645 }12151 }
...@@ -11707,14 +12213,14 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,...@@ -11707,14 +12213,14 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
11707 BigInt remainder;12213 BigInt remainder;
11708 bigint_rem(&remainder, &op1_val->data.x_bigint, &op2_val->data.x_bigint);12214 bigint_rem(&remainder, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
11709 if (bigint_cmp_zero(&remainder) != CmpEQ) {12215 if (bigint_cmp_zero(&remainder) != CmpEQ) {
11710 return ErrorExactDivRemainder;12216 return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder"));
11711 }12217 }
11712 } else {12218 } else {
11713 float_div_trunc(out_val, op1_val, op2_val);12219 float_div_trunc(out_val, op1_val, op2_val);
11714 ConstExprValue remainder;12220 ConstExprValue remainder;
11715 float_rem(&remainder, op1_val, op2_val);12221 float_rem(&remainder, op1_val, op2_val);
11716 if (float_cmp_zero(&remainder) != CmpEQ) {12222 if (float_cmp_zero(&remainder) != CmpEQ) {
11717 return ErrorExactDivRemainder;12223 return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder"));
11718 }12224 }
11719 }12225 }
11720 break;12226 break;
...@@ -11738,13 +12244,51 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,...@@ -11738,13 +12244,51 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
11738 if (!bigint_fits_in_bits(&out_val->data.x_bigint, type_entry->data.integral.bit_count,12244 if (!bigint_fits_in_bits(&out_val->data.x_bigint, type_entry->data.integral.bit_count,
11739 type_entry->data.integral.is_signed))12245 type_entry->data.integral.is_signed))
11740 {12246 {
11741 return ErrorOverflow;12247 return ir_add_error(ira, source_instr, buf_sprintf("operation caused overflow"));
11742 }12248 }
11743 }12249 }
1174412250
11745 out_val->type = type_entry;12251 out_val->type = type_entry;
11746 out_val->special = ConstValSpecialStatic;12252 out_val->special = ConstValSpecialStatic;
11747 return 0;12253 return nullptr;
12254}
12255
12256// This works on operands that have already been checked to be comptime known.
12257static IrInstruction *ir_analyze_math_op(IrAnalyze *ira, IrInstruction *source_instr,
12258 ZigType *type_entry, ConstExprValue *op1_val, IrBinOp op_id, ConstExprValue *op2_val)
12259{
12260 IrInstruction *result_instruction = ir_const(ira, source_instr, type_entry);
12261 ConstExprValue *out_val = &result_instruction->value;
12262 if (type_entry->id == ZigTypeIdVector) {
12263 expand_undef_array(ira->codegen, op1_val);
12264 expand_undef_array(ira->codegen, op2_val);
12265 out_val->special = ConstValSpecialUndef;
12266 expand_undef_array(ira->codegen, out_val);
12267 size_t len = type_entry->data.vector.len;
12268 ZigType *scalar_type = type_entry->data.vector.elem_type;
12269 for (size_t i = 0; i < len; i += 1) {
12270 ConstExprValue *scalar_op1_val = &op1_val->data.x_array.data.s_none.elements[i];
12271 ConstExprValue *scalar_op2_val = &op2_val->data.x_array.data.s_none.elements[i];
12272 ConstExprValue *scalar_out_val = &out_val->data.x_array.data.s_none.elements[i];
12273 assert(scalar_op1_val->type == scalar_type);
12274 assert(scalar_op2_val->type == scalar_type);
12275 assert(scalar_out_val->type == scalar_type);
12276 ErrorMsg *msg = ir_eval_math_op_scalar(ira, source_instr, scalar_type,
12277 scalar_op1_val, op_id, scalar_op2_val, scalar_out_val);
12278 if (msg != nullptr) {
12279 add_error_note(ira->codegen, msg, source_instr->source_node,
12280 buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i));
12281 return ira->codegen->invalid_instruction;
12282 }
12283 }
12284 out_val->type = type_entry;
12285 out_val->special = ConstValSpecialStatic;
12286 } else {
12287 if (ir_eval_math_op_scalar(ira, source_instr, type_entry, op1_val, op_id, op2_val, out_val) != nullptr) {
12288 return ira->codegen->invalid_instruction;
12289 }
12290 }
12291 return ir_implicit_cast(ira, result_instruction, type_entry);
11748}12292}
1174912293
11750static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {12294static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
...@@ -11816,24 +12360,7 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b...@@ -11816,24 +12360,7 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b
11816 if (op2_val == nullptr)12360 if (op2_val == nullptr)
11817 return ira->codegen->invalid_instruction;12361 return ira->codegen->invalid_instruction;
1181812362
11819 IrInstruction *result_instruction = ir_const(ira, &bin_op_instruction->base, op1->value.type);12363 return ir_analyze_math_op(ira, &bin_op_instruction->base, op1->value.type, op1_val, op_id, op2_val);
11820
11821 int err;
11822 if ((err = ir_eval_math_op(op1->value.type, op1_val, op_id, op2_val, &result_instruction->value))) {
11823 if (err == ErrorOverflow) {
11824 ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("operation caused overflow"));
11825 return ira->codegen->invalid_instruction;
11826 } else if (err == ErrorShiftedOutOneBits) {
11827 ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("exact shift shifted out 1 bits"));
11828 return ira->codegen->invalid_instruction;
11829 } else {
11830 zig_unreachable();
11831 }
11832 return ira->codegen->invalid_instruction;
11833 }
11834
11835 ir_num_lit_fits_in_other_type(ira, result_instruction, op1->value.type, false);
11836 return result_instruction;
11837 } else if (op1->value.type->id == ZigTypeIdComptimeInt) {12364 } else if (op1->value.type->id == ZigTypeIdComptimeInt) {
11838 ir_add_error(ira, &bin_op_instruction->base,12365 ir_add_error(ira, &bin_op_instruction->base,
11839 buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known"));12366 buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known"));
...@@ -11852,7 +12379,71 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b...@@ -11852,7 +12379,71 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b
11852 return result;12379 return result;
11853}12380}
1185412381
12382static bool ok_float_op(IrBinOp op) {
12383 switch (op) {
12384 case IrBinOpInvalid:
12385 zig_unreachable();
12386 case IrBinOpAdd:
12387 case IrBinOpSub:
12388 case IrBinOpMult:
12389 case IrBinOpDivUnspecified:
12390 case IrBinOpDivTrunc:
12391 case IrBinOpDivFloor:
12392 case IrBinOpDivExact:
12393 case IrBinOpRemRem:
12394 case IrBinOpRemMod:
12395 return true;
12396
12397 case IrBinOpBoolOr:
12398 case IrBinOpBoolAnd:
12399 case IrBinOpCmpEq:
12400 case IrBinOpCmpNotEq:
12401 case IrBinOpCmpLessThan:
12402 case IrBinOpCmpGreaterThan:
12403 case IrBinOpCmpLessOrEq:
12404 case IrBinOpCmpGreaterOrEq:
12405 case IrBinOpBinOr:
12406 case IrBinOpBinXor:
12407 case IrBinOpBinAnd:
12408 case IrBinOpBitShiftLeftLossy:
12409 case IrBinOpBitShiftLeftExact:
12410 case IrBinOpBitShiftRightLossy:
12411 case IrBinOpBitShiftRightExact:
12412 case IrBinOpAddWrap:
12413 case IrBinOpSubWrap:
12414 case IrBinOpMultWrap:
12415 case IrBinOpRemUnspecified:
12416 case IrBinOpArrayCat:
12417 case IrBinOpArrayMult:
12418 case IrBinOpMergeErrorSets:
12419 return false;
12420 }
12421 zig_unreachable();
12422}
12423
12424static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) {
12425 if (lhs_type->id != ZigTypeIdPointer)
12426 return false;
12427 switch (op) {
12428 case IrBinOpAdd:
12429 case IrBinOpSub:
12430 break;
12431 default:
12432 return false;
12433 }
12434 switch (lhs_type->data.pointer.ptr_len) {
12435 case PtrLenSingle:
12436 return false;
12437 case PtrLenUnknown:
12438 case PtrLenC:
12439 break;
12440 }
12441 return true;
12442}
12443
11855static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {12444static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {
12445 Error err;
12446
11856 IrInstruction *op1 = instruction->op1->child;12447 IrInstruction *op1 = instruction->op1->child;
11857 if (type_is_invalid(op1->value.type))12448 if (type_is_invalid(op1->value.type))
11858 return ira->codegen->invalid_instruction;12449 return ira->codegen->invalid_instruction;
...@@ -11864,13 +12455,44 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -11864,13 +12455,44 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
11864 IrBinOp op_id = instruction->op_id;12455 IrBinOp op_id = instruction->op_id;
1186512456
11866 // look for pointer math12457 // look for pointer math
11867 if (op1->value.type->id == ZigTypeIdPointer && op1->value.type->data.pointer.ptr_len == PtrLenUnknown &&12458 if (is_pointer_arithmetic_allowed(op1->value.type, op_id)) {
11868 (op_id == IrBinOpAdd || op_id == IrBinOpSub))
11869 {
11870 IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize);12459 IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize);
11871 if (casted_op2 == ira->codegen->invalid_instruction)12460 if (type_is_invalid(casted_op2->value.type))
11872 return ira->codegen->invalid_instruction;12461 return ira->codegen->invalid_instruction;
1187312462
12463 if (op1->value.special == ConstValSpecialUndef || casted_op2->value.special == ConstValSpecialUndef) {
12464 IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type);
12465 result->value.special = ConstValSpecialUndef;
12466 return result;
12467 }
12468 if (casted_op2->value.special == ConstValSpecialStatic && op1->value.special == ConstValSpecialStatic &&
12469 (op1->value.data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
12470 op1->value.data.x_ptr.special == ConstPtrSpecialNull))
12471 {
12472 uint64_t start_addr = (op1->value.data.x_ptr.special == ConstPtrSpecialNull) ?
12473 0 : op1->value.data.x_ptr.data.hard_coded_addr.addr;
12474 uint64_t elem_offset;
12475 if (!ir_resolve_usize(ira, casted_op2, &elem_offset))
12476 return ira->codegen->invalid_instruction;
12477 ZigType *elem_type = op1->value.type->data.pointer.child_type;
12478 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
12479 return ira->codegen->invalid_instruction;
12480 uint64_t byte_offset = type_size(ira->codegen, elem_type) * elem_offset;
12481 uint64_t new_addr;
12482 if (op_id == IrBinOpAdd) {
12483 new_addr = start_addr + byte_offset;
12484 } else if (op_id == IrBinOpSub) {
12485 new_addr = start_addr - byte_offset;
12486 } else {
12487 zig_unreachable();
12488 }
12489 IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type);
12490 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
12491 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
12492 result->value.data.x_ptr.data.hard_coded_addr.addr = new_addr;
12493 return result;
12494 }
12495
11874 IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,12496 IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
11875 instruction->base.source_node, op_id, op1, casted_op2, true);12497 instruction->base.source_node, op_id, op1, casted_op2, true);
11876 result->value.type = op1->value.type;12498 result->value.type = op1->value.type;
...@@ -11989,21 +12611,20 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -11989,21 +12611,20 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
11989 op_id = IrBinOpRemRem;12611 op_id = IrBinOpRemRem;
11990 }12612 }
1199112613
12614 bool ok = false;
11992 if (is_int) {12615 if (is_int) {
11993 // int12616 ok = true;
11994 } else if (is_float &&12617 } else if (is_float && ok_float_op(op_id)) {
11995 (op_id == IrBinOpAdd ||12618 ok = true;
11996 op_id == IrBinOpSub ||12619 } else if (resolved_type->id == ZigTypeIdVector) {
11997 op_id == IrBinOpMult ||12620 ZigType *elem_type = resolved_type->data.vector.elem_type;
11998 op_id == IrBinOpDivUnspecified ||12621 if (elem_type->id == ZigTypeIdInt || elem_type->id == ZigTypeIdComptimeInt) {
11999 op_id == IrBinOpDivTrunc ||12622 ok = true;
12000 op_id == IrBinOpDivFloor ||12623 } else if ((elem_type->id == ZigTypeIdFloat || elem_type->id == ZigTypeIdComptimeFloat) && ok_float_op(op_id)) {
12001 op_id == IrBinOpDivExact ||12624 ok = true;
12002 op_id == IrBinOpRemRem ||12625 }
12003 op_id == IrBinOpRemMod))12626 }
12004 {12627 if (!ok) {
12005 // float
12006 } else {
12007 AstNode *source_node = instruction->base.source_node;12628 AstNode *source_node = instruction->base.source_node;
12008 ir_add_error_node(ira, source_node,12629 ir_add_error_node(ira, source_node,
12009 buf_sprintf("invalid operands to binary expression: '%s' and '%s'",12630 buf_sprintf("invalid operands to binary expression: '%s' and '%s'",
...@@ -12038,30 +12659,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -12038,30 +12659,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
12038 if (op2_val == nullptr)12659 if (op2_val == nullptr)
12039 return ira->codegen->invalid_instruction;12660 return ira->codegen->invalid_instruction;
1204012661
12041 IrInstruction *result_instruction = ir_const(ira, &instruction->base, resolved_type);12662 return ir_analyze_math_op(ira, &instruction->base, resolved_type, op1_val, op_id, op2_val);
12042
12043 int err;
12044 if ((err = ir_eval_math_op(resolved_type, op1_val, op_id, op2_val, &result_instruction->value))) {
12045 if (err == ErrorDivByZero) {
12046 ir_add_error(ira, &instruction->base, buf_sprintf("division by zero"));
12047 return ira->codegen->invalid_instruction;
12048 } else if (err == ErrorOverflow) {
12049 ir_add_error(ira, &instruction->base, buf_sprintf("operation caused overflow"));
12050 return ira->codegen->invalid_instruction;
12051 } else if (err == ErrorExactDivRemainder) {
12052 ir_add_error(ira, &instruction->base, buf_sprintf("exact division had a remainder"));
12053 return ira->codegen->invalid_instruction;
12054 } else if (err == ErrorNegativeDenominator) {
12055 ir_add_error(ira, &instruction->base, buf_sprintf("negative denominator"));
12056 return ira->codegen->invalid_instruction;
12057 } else {
12058 zig_unreachable();
12059 }
12060 return ira->codegen->invalid_instruction;
12061 }
12062
12063 ir_num_lit_fits_in_other_type(ira, result_instruction, resolved_type, false);
12064 return result_instruction;
12065 }12663 }
1206612664
12067 IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,12665 IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
...@@ -12115,7 +12713,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -12115,7 +12713,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
12115 op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val;12713 op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
12116 op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;12714 op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
12117 ConstExprValue *len_val = &op1_val->data.x_struct.fields[slice_len_index];12715 ConstExprValue *len_val = &op1_val->data.x_struct.fields[slice_len_index];
12118 op1_array_end = bigint_as_unsigned(&len_val->data.x_bigint);12716 op1_array_end = op1_array_index + bigint_as_unsigned(&len_val->data.x_bigint);
12119 } else {12717 } else {
12120 ir_add_error(ira, op1,12718 ir_add_error(ira, op1,
12121 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name)));12719 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name)));
...@@ -12125,13 +12723,9 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -12125,13 +12723,9 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
12125 ConstExprValue *op2_array_val;12723 ConstExprValue *op2_array_val;
12126 size_t op2_array_index;12724 size_t op2_array_index;
12127 size_t op2_array_end;12725 size_t op2_array_end;
12726 bool op2_type_valid;
12128 if (op2_type->id == ZigTypeIdArray) {12727 if (op2_type->id == ZigTypeIdArray) {
12129 if (op2_type->data.array.child_type != child_type) {12728 op2_type_valid = op2_type->data.array.child_type == child_type;
12130 ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
12131 buf_ptr(&child_type->name),
12132 buf_ptr(&op2->value.type->name)));
12133 return ira->codegen->invalid_instruction;
12134 }
12135 op2_array_val = op2_val;12729 op2_array_val = op2_val;
12136 op2_array_index = 0;12730 op2_array_index = 0;
12137 op2_array_end = op2_array_val->type->data.array.len;12731 op2_array_end = op2_array_val->type->data.array.len;
...@@ -12140,35 +12734,30 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -12140,35 +12734,30 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
12140 op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray &&12734 op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray &&
12141 op2_val->data.x_ptr.data.base_array.is_cstr)12735 op2_val->data.x_ptr.data.base_array.is_cstr)
12142 {12736 {
12143 if (child_type != ira->codegen->builtin_types.entry_u8) {12737 op2_type_valid = child_type == ira->codegen->builtin_types.entry_u8;
12144 ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
12145 buf_ptr(&child_type->name),
12146 buf_ptr(&op2->value.type->name)));
12147 return ira->codegen->invalid_instruction;
12148 }
12149 op2_array_val = op2_val->data.x_ptr.data.base_array.array_val;12738 op2_array_val = op2_val->data.x_ptr.data.base_array.array_val;
12150 op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index;12739 op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index;
12151 op2_array_end = op2_array_val->type->data.array.len - 1;12740 op2_array_end = op2_array_val->type->data.array.len - 1;
12152 } else if (is_slice(op2_type)) {12741 } else if (is_slice(op2_type)) {
12153 ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index].type_entry;12742 ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index].type_entry;
12154 if (ptr_type->data.pointer.child_type != child_type) {12743 op2_type_valid = ptr_type->data.pointer.child_type == child_type;
12155 ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
12156 buf_ptr(&child_type->name),
12157 buf_ptr(&op2->value.type->name)));
12158 return ira->codegen->invalid_instruction;
12159 }
12160 ConstExprValue *ptr_val = &op2_val->data.x_struct.fields[slice_ptr_index];12744 ConstExprValue *ptr_val = &op2_val->data.x_struct.fields[slice_ptr_index];
12161 assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);12745 assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
12162 op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val;12746 op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
12163 op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;12747 op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
12164 op2_array_end = op2_array_val->type->data.array.len;
12165 ConstExprValue *len_val = &op2_val->data.x_struct.fields[slice_len_index];12748 ConstExprValue *len_val = &op2_val->data.x_struct.fields[slice_len_index];
12166 op2_array_end = bigint_as_unsigned(&len_val->data.x_bigint);12749 op2_array_end = op2_array_index + bigint_as_unsigned(&len_val->data.x_bigint);
12167 } else {12750 } else {
12168 ir_add_error(ira, op2,12751 ir_add_error(ira, op2,
12169 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));12752 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));
12170 return ira->codegen->invalid_instruction;12753 return ira->codegen->invalid_instruction;
12171 }12754 }
12755 if (!op2_type_valid) {
12756 ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
12757 buf_ptr(&child_type->name),
12758 buf_ptr(&op2->value.type->name)));
12759 return ira->codegen->invalid_instruction;
12760 }
1217212761
12173 // The type of result is populated in the following if blocks12762 // The type of result is populated in the following if blocks
12174 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);12763 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
...@@ -12301,26 +12890,14 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *...@@ -12301,26 +12890,14 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
12301}12890}
1230212891
12303static IrInstruction *ir_analyze_merge_error_sets(IrAnalyze *ira, IrInstructionBinOp *instruction) {12892static IrInstruction *ir_analyze_merge_error_sets(IrAnalyze *ira, IrInstructionBinOp *instruction) {
12304 ZigType *op1_type = ir_resolve_type(ira, instruction->op1->child);12893 ZigType *op1_type = ir_resolve_error_set_type(ira, &instruction->base, instruction->op1->child);
12305 if (type_is_invalid(op1_type))12894 if (type_is_invalid(op1_type))
12306 return ira->codegen->invalid_instruction;12895 return ira->codegen->invalid_instruction;
1230712896
12308 if (op1_type->id != ZigTypeIdErrorSet) {12897 ZigType *op2_type = ir_resolve_error_set_type(ira, &instruction->base, instruction->op2->child);
12309 ir_add_error(ira, instruction->op1,
12310 buf_sprintf("expected error set type, found '%s'", buf_ptr(&op1_type->name)));
12311 return ira->codegen->invalid_instruction;
12312 }
12313
12314 ZigType *op2_type = ir_resolve_type(ira, instruction->op2->child);
12315 if (type_is_invalid(op2_type))12898 if (type_is_invalid(op2_type))
12316 return ira->codegen->invalid_instruction;12899 return ira->codegen->invalid_instruction;
1231712900
12318 if (op2_type->id != ZigTypeIdErrorSet) {
12319 ir_add_error(ira, instruction->op2,
12320 buf_sprintf("expected error set type, found '%s'", buf_ptr(&op2_type->name)));
12321 return ira->codegen->invalid_instruction;
12322 }
12323
12324 if (type_is_global_error_set(op1_type) ||12901 if (type_is_global_error_set(op1_type) ||
12325 type_is_global_error_set(op2_type))12902 type_is_global_error_set(op2_type))
12326 {12903 {
...@@ -12394,13 +12971,15 @@ static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructio...@@ -12394,13 +12971,15 @@ static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructio
12394 zig_unreachable();12971 zig_unreachable();
12395}12972}
1239612973
12397static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDeclVar *decl_var_instruction) {12974static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
12975 IrInstructionDeclVarSrc *decl_var_instruction)
12976{
12398 Error err;12977 Error err;
12399 ZigVar *var = decl_var_instruction->var;12978 ZigVar *var = decl_var_instruction->var;
1240012979
12401 IrInstruction *init_value = decl_var_instruction->init_value->child;12980 IrInstruction *init_value = decl_var_instruction->init_value->child;
12402 if (type_is_invalid(init_value->value.type)) {12981 if (type_is_invalid(init_value->value.type)) {
12403 var->value->type = ira->codegen->builtin_types.entry_invalid;12982 var->var_type = ira->codegen->builtin_types.entry_invalid;
12404 return ira->codegen->invalid_instruction;12983 return ira->codegen->invalid_instruction;
12405 }12984 }
1240612985
...@@ -12411,7 +12990,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12411,7 +12990,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12411 ZigType *proposed_type = ir_resolve_type(ira, var_type);12990 ZigType *proposed_type = ir_resolve_type(ira, var_type);
12412 explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type);12991 explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type);
12413 if (type_is_invalid(explicit_type)) {12992 if (type_is_invalid(explicit_type)) {
12414 var->value->type = ira->codegen->builtin_types.entry_invalid;12993 var->var_type = ira->codegen->builtin_types.entry_invalid;
12415 return ira->codegen->invalid_instruction;12994 return ira->codegen->invalid_instruction;
12416 }12995 }
12417 }12996 }
...@@ -12436,7 +13015,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12436,7 +13015,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12436 case ReqCompTimeInvalid:13015 case ReqCompTimeInvalid:
12437 result_type = ira->codegen->builtin_types.entry_invalid;13016 result_type = ira->codegen->builtin_types.entry_invalid;
12438 break;13017 break;
12439 case ReqCompTimeYes: {13018 case ReqCompTimeYes:
12440 var_class_requires_const = true;13019 var_class_requires_const = true;
12441 if (!var->gen_is_const && !is_comptime_var) {13020 if (!var->gen_is_const && !is_comptime_var) {
12442 ir_add_error_node(ira, source_node,13021 ir_add_error_node(ira, source_node,
...@@ -12445,10 +13024,10 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12445,10 +13024,10 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12445 result_type = ira->codegen->builtin_types.entry_invalid;13024 result_type = ira->codegen->builtin_types.entry_invalid;
12446 }13025 }
12447 break;13026 break;
12448 }
12449 case ReqCompTimeNo:13027 case ReqCompTimeNo:
12450 if (casted_init_value->value.special == ConstValSpecialStatic &&13028 if (casted_init_value->value.special == ConstValSpecialStatic &&
12451 casted_init_value->value.type->id == ZigTypeIdFn &&13029 casted_init_value->value.type->id == ZigTypeIdFn &&
13030 casted_init_value->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
12452 casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways)13031 casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways)
12453 {13032 {
12454 var_class_requires_const = true;13033 var_class_requires_const = true;
...@@ -12463,7 +13042,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12463,7 +13042,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12463 break;13042 break;
12464 }13043 }
1246513044
12466 if (var->value->type != nullptr && !is_comptime_var) {13045 if (var->var_type != nullptr && !is_comptime_var) {
12467 // This is at least the second time we've seen this variable declaration during analysis.13046 // This is at least the second time we've seen this variable declaration during analysis.
12468 // This means that this is actually a different variable due to, e.g. an inline while loop.13047 // This means that this is actually a different variable due to, e.g. an inline while loop.
12469 // We make a new variable so that it can hold a different type, and so the debug info can13048 // We make a new variable so that it can hold a different type, and so the debug info can
...@@ -12485,8 +13064,8 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12485,8 +13064,8 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12485 // This must be done after possibly creating a new variable above13064 // This must be done after possibly creating a new variable above
12486 var->ref_count = 0;13065 var->ref_count = 0;
1248713066
12488 var->value->type = result_type;13067 var->var_type = result_type;
12489 assert(var->value->type);13068 assert(var->var_type);
1249013069
12491 if (type_is_invalid(result_type)) {13070 if (type_is_invalid(result_type)) {
12492 return ir_const_void(ira, &decl_var_instruction->base);13071 return ir_const_void(ira, &decl_var_instruction->base);
...@@ -12494,13 +13073,13 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12494,13 +13073,13 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1249413073
12495 if (decl_var_instruction->align_value == nullptr) {13074 if (decl_var_instruction->align_value == nullptr) {
12496 if ((err = type_resolve(ira->codegen, result_type, ResolveStatusAlignmentKnown))) {13075 if ((err = type_resolve(ira->codegen, result_type, ResolveStatusAlignmentKnown))) {
12497 var->value->type = ira->codegen->builtin_types.entry_invalid;13076 var->var_type = ira->codegen->builtin_types.entry_invalid;
12498 return ir_const_void(ira, &decl_var_instruction->base);13077 return ir_const_void(ira, &decl_var_instruction->base);
12499 }13078 }
12500 var->align_bytes = get_abi_alignment(ira->codegen, result_type);13079 var->align_bytes = get_abi_alignment(ira->codegen, result_type);
12501 } else {13080 } else {
12502 if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, &var->align_bytes)) {13081 if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, &var->align_bytes)) {
12503 var->value->type = ira->codegen->builtin_types.entry_invalid;13082 var->var_type = ira->codegen->builtin_types.entry_invalid;
12504 }13083 }
12505 }13084 }
1250613085
...@@ -12517,7 +13096,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12517,7 +13096,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12517 } else if (is_comptime_var) {13096 } else if (is_comptime_var) {
12518 ir_add_error(ira, &decl_var_instruction->base,13097 ir_add_error(ira, &decl_var_instruction->base,
12519 buf_sprintf("cannot store runtime value in compile time variable"));13098 buf_sprintf("cannot store runtime value in compile time variable"));
12520 var->value->type = ira->codegen->builtin_types.entry_invalid;13099 var->var_type = ira->codegen->builtin_types.entry_invalid;
12521 return ira->codegen->invalid_instruction;13100 return ira->codegen->invalid_instruction;
12522 }13101 }
1252313102
...@@ -12525,11 +13104,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12525,11 +13104,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12525 if (fn_entry)13104 if (fn_entry)
12526 fn_entry->variable_list.append(var);13105 fn_entry->variable_list.append(var);
1252713106
12528 IrInstruction *result = ir_build_var_decl(&ira->new_irb,13107 return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value);
12529 decl_var_instruction->base.scope, decl_var_instruction->base.source_node,
12530 var, var_type, nullptr, casted_init_value);
12531 result->value.type = ira->codegen->builtin_types.entry_void;
12532 return result;
12533}13108}
1253413109
12535static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {13110static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {
...@@ -12651,6 +13226,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio...@@ -12651,6 +13226,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
12651 case ZigTypeIdPointer:13226 case ZigTypeIdPointer:
12652 case ZigTypeIdArray:13227 case ZigTypeIdArray:
12653 case ZigTypeIdBool:13228 case ZigTypeIdBool:
13229 case ZigTypeIdVector:
12654 break;13230 break;
12655 case ZigTypeIdMetaType:13231 case ZigTypeIdMetaType:
12656 case ZigTypeIdVoid:13232 case ZigTypeIdVoid:
...@@ -12685,6 +13261,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio...@@ -12685,6 +13261,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
12685 case ZigTypeIdOptional:13261 case ZigTypeIdOptional:
12686 case ZigTypeIdErrorUnion:13262 case ZigTypeIdErrorUnion:
12687 case ZigTypeIdErrorSet:13263 case ZigTypeIdErrorSet:
13264 case ZigTypeIdVector:
12688 zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name));13265 zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name));
12689 case ZigTypeIdNamespace:13266 case ZigTypeIdNamespace:
12690 case ZigTypeIdBoundFn:13267 case ZigTypeIdBoundFn:
...@@ -12859,7 +13436,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node...@@ -12859,7 +13436,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node
1285913436
12860 Buf *param_name = param_decl_node->data.param_decl.name;13437 Buf *param_name = param_decl_node->data.param_decl.name;
12861 ZigVar *var = add_variable(ira->codegen, param_decl_node,13438 ZigVar *var = add_variable(ira->codegen, param_decl_node,
12862 *exec_scope, param_name, true, arg_val, nullptr);13439 *exec_scope, param_name, true, arg_val, nullptr, arg_val->type);
12863 *exec_scope = var->child_scope;13440 *exec_scope = var->child_scope;
12864 *next_proto_i += 1;13441 *next_proto_i += 1;
1286513442
...@@ -12917,7 +13494,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod...@@ -12917,7 +13494,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
12917 if (!param_name) return false;13494 if (!param_name) return false;
12918 if (!is_var_args) {13495 if (!is_var_args) {
12919 ZigVar *var = add_variable(ira->codegen, param_decl_node,13496 ZigVar *var = add_variable(ira->codegen, param_decl_node,
12920 *child_scope, param_name, true, arg_val, nullptr);13497 *child_scope, param_name, true, arg_val, nullptr, arg_val->type);
12921 *child_scope = var->child_scope;13498 *child_scope = var->child_scope;
12922 var->shadowable = !comptime_arg;13499 var->shadowable = !comptime_arg;
1292313500
...@@ -12971,9 +13548,7 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) {...@@ -12971,9 +13548,7 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) {
12971 return fn_entry->variable_list.at(next_var_i);13548 return fn_entry->variable_list.at(next_var_i);
12972}13549}
1297313550
12974static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,13551static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var) {
12975 ZigVar *var)
12976{
12977 while (var->next_var != nullptr) {13552 while (var->next_var != nullptr) {
12978 var = var->next_var;13553 var = var->next_var;
12979 }13554 }
...@@ -12982,14 +13557,14 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,...@@ -12982,14 +13557,14 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
12982 assert(ira->codegen->errors.length != 0);13557 assert(ira->codegen->errors.length != 0);
12983 return ira->codegen->invalid_instruction;13558 return ira->codegen->invalid_instruction;
12984 }13559 }
12985 if (var->value->type == nullptr || type_is_invalid(var->value->type))13560 if (var->var_type == nullptr || type_is_invalid(var->var_type))
12986 return ira->codegen->invalid_instruction;13561 return ira->codegen->invalid_instruction;
1298713562
12988 bool comptime_var_mem = ir_get_var_is_comptime(var);13563 bool comptime_var_mem = ir_get_var_is_comptime(var);
1298913564
12990 ConstExprValue *mem_slot = nullptr;13565 ConstExprValue *mem_slot = nullptr;
12991 if (var->value->special == ConstValSpecialStatic) {13566 if (var->const_value->special == ConstValSpecialStatic) {
12992 mem_slot = var->value;13567 mem_slot = var->const_value;
12993 } else {13568 } else {
12994 if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) {13569 if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) {
12995 // find the relevant exec_context13570 // find the relevant exec_context
...@@ -13018,7 +13593,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,...@@ -13018,7 +13593,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
13018 assert(!comptime_var_mem);13593 assert(!comptime_var_mem);
13019 ptr_mut = ConstPtrMutRuntimeVar;13594 ptr_mut = ConstPtrMutRuntimeVar;
13020 }13595 }
13021 return ir_get_const_ptr(ira, instruction, mem_slot, var->value->type,13596 return ir_get_const_ptr(ira, instruction, mem_slot, var->var_type,
13022 ptr_mut, is_const, is_volatile, var->align_bytes);13597 ptr_mut, is_const, is_volatile, var->align_bytes);
13023 }13598 }
13024 }13599 }
...@@ -13029,7 +13604,7 @@ no_mem_slot:...@@ -13029,7 +13604,7 @@ no_mem_slot:
1302913604
13030 IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb,13605 IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb,
13031 instruction->scope, instruction->source_node, var);13606 instruction->scope, instruction->source_node, var);
13032 var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->value->type,13607 var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->var_type,
13033 var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0);13608 var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0);
1303413609
13035 bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);13610 bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);
...@@ -13038,6 +13613,96 @@ no_mem_slot:...@@ -13038,6 +13613,96 @@ no_mem_slot:
13038 return var_ptr_instruction;13613 return var_ptr_instruction;
13039}13614}
1304013615
13616static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
13617 IrInstruction *ptr, IrInstruction *uncasted_value)
13618{
13619 if (ptr->value.type->id != ZigTypeIdPointer) {
13620 ir_add_error(ira, ptr,
13621 buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name)));
13622 return ira->codegen->invalid_instruction;
13623 }
13624
13625 if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) {
13626 return ir_const_void(ira, source_instr);
13627 }
13628
13629 if (ptr->value.type->data.pointer.is_const && !source_instr->is_gen) {
13630 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
13631 return ira->codegen->invalid_instruction;
13632 }
13633
13634 ZigType *child_type = ptr->value.type->data.pointer.child_type;
13635 IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type);
13636 if (value == ira->codegen->invalid_instruction)
13637 return ira->codegen->invalid_instruction;
13638
13639 if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
13640 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {
13641 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
13642 return ira->codegen->invalid_instruction;
13643 }
13644 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) {
13645 if (instr_is_comptime(value)) {
13646 ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, source_instr->source_node);
13647 if (dest_val == nullptr)
13648 return ira->codegen->invalid_instruction;
13649 if (dest_val->special != ConstValSpecialRuntime) {
13650 // TODO this allows a value stored to have the original value modified and then
13651 // have that affect what should be a copy. We need some kind of advanced copy-on-write
13652 // system to make these two tests pass at the same time:
13653 // * "string literal used as comptime slice is memoized"
13654 // * "comptime modification of const struct field" - except modified to avoid
13655 // ConstPtrMutComptimeVar, thus defeating the logic below.
13656 bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar;
13657 copy_const_val(dest_val, &value->value, same_global_refs);
13658 if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
13659 switch (type_has_one_possible_value(ira->codegen, child_type)) {
13660 case OnePossibleValueInvalid:
13661 return ira->codegen->invalid_instruction;
13662 case OnePossibleValueNo:
13663 ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
13664 break;
13665 case OnePossibleValueYes:
13666 break;
13667 }
13668 }
13669 return ir_const_void(ira, source_instr);
13670 }
13671 }
13672 ir_add_error(ira, source_instr,
13673 buf_sprintf("cannot store runtime value in compile time variable"));
13674 ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
13675 dest_val->type = ira->codegen->builtin_types.entry_invalid;
13676
13677 return ira->codegen->invalid_instruction;
13678 }
13679 }
13680
13681 switch (type_requires_comptime(ira->codegen, child_type)) {
13682 case ReqCompTimeInvalid:
13683 return ira->codegen->invalid_instruction;
13684 case ReqCompTimeYes:
13685 switch (type_has_one_possible_value(ira->codegen, ptr->value.type)) {
13686 case OnePossibleValueInvalid:
13687 return ira->codegen->invalid_instruction;
13688 case OnePossibleValueNo:
13689 ir_add_error(ira, source_instr,
13690 buf_sprintf("cannot store runtime value in type '%s'", buf_ptr(&child_type->name)));
13691 return ira->codegen->invalid_instruction;
13692 case OnePossibleValueYes:
13693 return ir_const_void(ira, source_instr);
13694 }
13695 zig_unreachable();
13696 case ReqCompTimeNo:
13697 break;
13698 }
13699
13700 IrInstruction *result = ir_build_store_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node,
13701 ptr, value);
13702 result->value.type = ira->codegen->builtin_types.entry_void;
13703 return result;
13704}
13705
13041static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction,13706static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction,
13042 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,13707 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
13043 IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)13708 IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)
...@@ -13182,7 +13847,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13182,7 +13847,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13182 }13847 }
1318313848
13184 bool cacheable = fn_eval_cacheable(exec_scope, return_type);13849 bool cacheable = fn_eval_cacheable(exec_scope, return_type);
13185 IrInstruction *result = nullptr;13850 ConstExprValue *result = nullptr;
13186 if (cacheable) {13851 if (cacheable) {
13187 auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope);13852 auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope);
13188 if (entry)13853 if (entry)
...@@ -13194,22 +13859,23 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13194,22 +13859,23 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13194 AstNode *body_node = fn_entry->body_node;13859 AstNode *body_node = fn_entry->body_node;
13195 result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,13860 result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,
13196 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,13861 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,
13197 nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec);13862 nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node);
1319813863
13199 if (inferred_err_set_type != nullptr) {13864 if (inferred_err_set_type != nullptr) {
13200 inferred_err_set_type->data.error_set.infer_fn = nullptr;13865 inferred_err_set_type->data.error_set.infer_fn = nullptr;
13201 if (result->value.type->id == ZigTypeIdErrorUnion) {13866 if (result->type->id == ZigTypeIdErrorUnion) {
13202 if (result->value.data.x_err_union.err != nullptr) {13867 ErrorTableEntry *err = result->data.x_err_union.error_set->data.x_err_set;
13868 if (err != nullptr) {
13203 inferred_err_set_type->data.error_set.err_count = 1;13869 inferred_err_set_type->data.error_set.err_count = 1;
13204 inferred_err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(1);13870 inferred_err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(1);
13205 inferred_err_set_type->data.error_set.errors[0] = result->value.data.x_err_union.err;13871 inferred_err_set_type->data.error_set.errors[0] = err;
13206 }13872 }
13207 ZigType *fn_inferred_err_set_type = result->value.type->data.error_union.err_set_type;13873 ZigType *fn_inferred_err_set_type = result->type->data.error_union.err_set_type;
13208 inferred_err_set_type->data.error_set.err_count = fn_inferred_err_set_type->data.error_set.err_count;13874 inferred_err_set_type->data.error_set.err_count = fn_inferred_err_set_type->data.error_set.err_count;
13209 inferred_err_set_type->data.error_set.errors = fn_inferred_err_set_type->data.error_set.errors;13875 inferred_err_set_type->data.error_set.errors = fn_inferred_err_set_type->data.error_set.errors;
13210 } else if (result->value.type->id == ZigTypeIdErrorSet) {13876 } else if (result->type->id == ZigTypeIdErrorSet) {
13211 inferred_err_set_type->data.error_set.err_count = result->value.type->data.error_set.err_count;13877 inferred_err_set_type->data.error_set.err_count = result->type->data.error_set.err_count;
13212 inferred_err_set_type->data.error_set.errors = result->value.type->data.error_set.errors;13878 inferred_err_set_type->data.error_set.errors = result->type->data.error_set.errors;
13213 }13879 }
13214 }13880 }
1321513881
...@@ -13217,13 +13883,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13217,13 +13883,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13217 ira->codegen->memoized_fn_eval_table.put(exec_scope, result);13883 ira->codegen->memoized_fn_eval_table.put(exec_scope, result);
13218 }13884 }
1321913885
13220 if (type_is_invalid(result->value.type))13886 if (type_is_invalid(result->type))
13221 return ira->codegen->invalid_instruction;13887 return ira->codegen->invalid_instruction;
13222 }13888 }
1322313889
13224 IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->value.type);13890 IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->type);
13225 // TODO should we use copy_const_val?13891 copy_const_val(&new_instruction->value, result, true);
13226 new_instruction->value = result->value;
13227 new_instruction->value.type = return_type;13892 new_instruction->value.type = return_type;
13228 return ir_finish_anal(ira, new_instruction);13893 return ir_finish_anal(ira, new_instruction);
13229 }13894 }
...@@ -13382,18 +14047,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13382,18 +14047,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13382 ConstExprValue *var_args_val = create_const_arg_tuple(ira->codegen,14047 ConstExprValue *var_args_val = create_const_arg_tuple(ira->codegen,
13383 first_var_arg, inst_fn_type_id.param_count);14048 first_var_arg, inst_fn_type_id.param_count);
13384 ZigVar *var = add_variable(ira->codegen, param_decl_node,14049 ZigVar *var = add_variable(ira->codegen, param_decl_node,
13385 impl_fn->child_scope, param_name, true, var_args_val, nullptr);14050 impl_fn->child_scope, param_name, true, var_args_val, nullptr, var_args_val->type);
13386 impl_fn->child_scope = var->child_scope;14051 impl_fn->child_scope = var->child_scope;
13387 }14052 }
1338814053
13389 if (fn_proto_node->data.fn_proto.align_expr != nullptr) {14054 if (fn_proto_node->data.fn_proto.align_expr != nullptr) {
13390 IrInstruction *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,14055 ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,
13391 fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),14056 fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),
13392 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota,14057 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota,
13393 nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec);14058 nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr);
14059 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
14060 impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
14061 const_instruction->base.value = *align_result;
1339414062
13395 uint32_t align_bytes = 0;14063 uint32_t align_bytes = 0;
13396 ir_resolve_align(ira, align_result, &align_bytes);14064 ir_resolve_align(ira, &const_instruction->base, &align_bytes);
13397 impl_fn->align_bytes = align_bytes;14065 impl_fn->align_bytes = align_bytes;
13398 inst_fn_type_id.alignment = align_bytes;14066 inst_fn_type_id.alignment = align_bytes;
13399 }14067 }
...@@ -13471,12 +14139,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13471,12 +14139,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13471 ira->codegen->fn_defs.append(impl_fn);14139 ira->codegen->fn_defs.append(impl_fn);
13472 }14140 }
1347314141
13474 ZigType *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type;14142 FnTypeId *impl_fn_type_id = &impl_fn->type_entry->data.fn.fn_type_id;
13475 if (fn_type_can_fail(&impl_fn->type_entry->data.fn.fn_type_id)) {14143 if (fn_type_can_fail(impl_fn_type_id)) {
13476 parent_fn_entry->calls_or_awaits_errorable_fn = true;14144 parent_fn_entry->calls_or_awaits_errorable_fn = true;
13477 }14145 }
1347814146
13479 size_t impl_param_count = impl_fn->type_entry->data.fn.fn_type_id.param_count;14147 size_t impl_param_count = impl_fn_type_id->param_count;
13480 if (call_instruction->is_async) {14148 if (call_instruction->is_async) {
13481 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,14149 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,
13482 fn_ref, casted_args, impl_param_count, async_allocator_inst);14150 fn_ref, casted_args, impl_param_count, async_allocator_inst);
...@@ -13489,9 +14157,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13489,9 +14157,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13489 call_instruction->base.scope, call_instruction->base.source_node,14157 call_instruction->base.scope, call_instruction->base.source_node,
13490 impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline,14158 impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline,
13491 call_instruction->is_async, nullptr, casted_new_stack);14159 call_instruction->is_async, nullptr, casted_new_stack);
13492 new_call_instruction->value.type = return_type;14160 new_call_instruction->value.type = impl_fn_type_id->return_type;
1349314161
13494 ir_add_alloca(ira, new_call_instruction, return_type);14162 ir_add_alloca(ira, new_call_instruction, impl_fn_type_id->return_type);
1349514163
13496 return ir_finish_anal(ira, new_call_instruction);14164 return ir_finish_anal(ira, new_call_instruction);
13497 }14165 }
...@@ -13653,39 +14321,87 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC...@@ -13653,39 +14321,87 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC
1365314321
13654// out_val->type must be the type to read the pointer as14322// out_val->type must be the type to read the pointer as
13655// if the type is different than the actual type then it does a comptime byte reinterpretation14323// if the type is different than the actual type then it does a comptime byte reinterpretation
13656static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node,14324static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
13657 ConstExprValue *out_val, ConstExprValue *ptr_val)14325 ConstExprValue *out_val, ConstExprValue *ptr_val)
13658{14326{
13659 Error err;14327 Error err;
13660 assert(out_val->type != nullptr);14328 assert(out_val->type != nullptr);
1366114329
13662 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, ptr_val);14330 ConstExprValue *pointee = const_ptr_pointee_unchecked(codegen, ptr_val);
1366314331
13664 if ((err = type_resolve(ira->codegen, pointee->type, ResolveStatusSizeKnown)))14332 if ((err = type_resolve(codegen, pointee->type, ResolveStatusSizeKnown)))
13665 return ErrorSemanticAnalyzeFail;14333 return ErrorSemanticAnalyzeFail;
13666 if ((err = type_resolve(ira->codegen, out_val->type, ResolveStatusSizeKnown)))14334 if ((err = type_resolve(codegen, out_val->type, ResolveStatusSizeKnown)))
13667 return ErrorSemanticAnalyzeFail;14335 return ErrorSemanticAnalyzeFail;
1366814336
13669 size_t src_size = type_size(ira->codegen, pointee->type);14337 // We don't need to read the padding bytes, so we look at type_size_store bytes
13670 size_t dst_size = type_size(ira->codegen, out_val->type);14338 size_t src_size = type_size_store(codegen, pointee->type);
14339 size_t dst_size = type_size_store(codegen, out_val->type);
1367114340
13672 if (src_size == dst_size && types_have_same_zig_comptime_repr(pointee->type, out_val->type)) {14341 if (dst_size <= src_size) {
13673 copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut == ConstPtrMutComptimeConst);14342 if (types_have_same_zig_comptime_repr(pointee->type, out_val->type)) {
14343 copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut == ConstPtrMutComptimeConst);
14344 return ErrorNone;
14345 }
14346 Buf buf = BUF_INIT;
14347 buf_resize(&buf, src_size);
14348 buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf), pointee);
14349 if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
14350 return err;
13674 return ErrorNone;14351 return ErrorNone;
13675 }14352 }
1367614353
13677 if (dst_size > src_size) {14354 switch (ptr_val->data.x_ptr.special) {
13678 ir_add_error_node(ira, source_node,14355 case ConstPtrSpecialInvalid:
13679 buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",14356 zig_unreachable();
13680 dst_size, buf_ptr(&pointee->type->name), src_size));14357 case ConstPtrSpecialNull:
13681 return ErrorSemanticAnalyzeFail;14358 if (dst_size == 0)
14359 return ErrorNone;
14360 opt_ir_add_error_node(ira, codegen, source_node,
14361 buf_sprintf("attempt to read %zu bytes from null pointer",
14362 dst_size));
14363 return ErrorSemanticAnalyzeFail;
14364 case ConstPtrSpecialRef: {
14365 opt_ir_add_error_node(ira, codegen, source_node,
14366 buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",
14367 dst_size, buf_ptr(&pointee->type->name), src_size));
14368 return ErrorSemanticAnalyzeFail;
14369 }
14370 case ConstPtrSpecialBaseArray: {
14371 ConstExprValue *array_val = ptr_val->data.x_ptr.data.base_array.array_val;
14372 assert(array_val->type->id == ZigTypeIdArray);
14373 if (array_val->data.x_array.special != ConstArraySpecialNone)
14374 zig_panic("TODO");
14375 size_t elem_size = src_size;
14376 size_t elem_index = ptr_val->data.x_ptr.data.base_array.elem_index;
14377 src_size = elem_size * (array_val->type->data.array.len - elem_index);
14378 if (dst_size > src_size) {
14379 opt_ir_add_error_node(ira, codegen, source_node,
14380 buf_sprintf("attempt to read %zu bytes from %s at index %" ZIG_PRI_usize " which is %zu bytes",
14381 dst_size, buf_ptr(&array_val->type->name), elem_index, src_size));
14382 return ErrorSemanticAnalyzeFail;
14383 }
14384 size_t elem_count = (dst_size % elem_size == 0) ? (dst_size / elem_size) : (dst_size / elem_size + 1);
14385 Buf buf = BUF_INIT;
14386 buf_resize(&buf, elem_count * elem_size);
14387 for (size_t i = 0; i < elem_count; i += 1) {
14388 ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[elem_index + i];
14389 buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val);
14390 }
14391 if ((err = buf_read_value_bytes(ira, codegen, source_node, (uint8_t*)buf_ptr(&buf), out_val)))
14392 return err;
14393 return ErrorNone;
14394 }
14395 case ConstPtrSpecialBaseStruct:
14396 case ConstPtrSpecialBaseErrorUnionCode:
14397 case ConstPtrSpecialBaseErrorUnionPayload:
14398 case ConstPtrSpecialBaseOptionalPayload:
14399 case ConstPtrSpecialDiscard:
14400 case ConstPtrSpecialHardCodedAddr:
14401 case ConstPtrSpecialFunction:
14402 zig_panic("TODO");
13682 }14403 }
1368314404 zig_unreachable();
13684 Buf buf = BUF_INIT;
13685 buf_resize(&buf, src_size);
13686 buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee);
13687 buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val);
13688 return ErrorNone;
13689}14405}
1369014406
13691static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {14407static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
...@@ -13704,6 +14420,7 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_...@@ -13704,6 +14420,7 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_
13704 case ZigTypeIdVoid:14420 case ZigTypeIdVoid:
13705 case ZigTypeIdBool:14421 case ZigTypeIdBool:
13706 case ZigTypeIdInt:14422 case ZigTypeIdInt:
14423 case ZigTypeIdVector:
13707 case ZigTypeIdFloat:14424 case ZigTypeIdFloat:
13708 case ZigTypeIdPointer:14425 case ZigTypeIdPointer:
13709 case ZigTypeIdArray:14426 case ZigTypeIdArray:
...@@ -13875,9 +14592,14 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi...@@ -13875,9 +14592,14 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi
13875 if (!ir_resolve_comptime(ira, cond_br_instruction->is_comptime->child, &is_comptime))14592 if (!ir_resolve_comptime(ira, cond_br_instruction->is_comptime->child, &is_comptime))
13876 return ir_unreach_error(ira);14593 return ir_unreach_error(ira);
1387714594
13878 if (is_comptime || instr_is_comptime(condition)) {14595 ZigType *bool_type = ira->codegen->builtin_types.entry_bool;
14596 IrInstruction *casted_condition = ir_implicit_cast(ira, condition, bool_type);
14597 if (type_is_invalid(casted_condition->value.type))
14598 return ir_unreach_error(ira);
14599
14600 if (is_comptime || instr_is_comptime(casted_condition)) {
13879 bool cond_is_true;14601 bool cond_is_true;
13880 if (!ir_resolve_bool(ira, condition, &cond_is_true))14602 if (!ir_resolve_bool(ira, casted_condition, &cond_is_true))
13881 return ir_unreach_error(ira);14603 return ir_unreach_error(ira);
1388214604
13883 IrBasicBlock *old_dest_block = cond_is_true ?14605 IrBasicBlock *old_dest_block = cond_is_true ?
...@@ -13896,11 +14618,6 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi...@@ -13896,11 +14618,6 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi
13896 return ir_finish_anal(ira, result);14618 return ir_finish_anal(ira, result);
13897 }14619 }
1389814620
13899 ZigType *bool_type = ira->codegen->builtin_types.entry_bool;
13900 IrInstruction *casted_condition = ir_implicit_cast(ira, condition, bool_type);
13901 if (casted_condition == ira->codegen->invalid_instruction)
13902 return ir_unreach_error(ira);
13903
13904 assert(cond_br_instruction->then_block != cond_br_instruction->else_block);14621 assert(cond_br_instruction->then_block != cond_br_instruction->else_block);
13905 IrBasicBlock *new_then_block = ir_get_new_bb_runtime(ira, cond_br_instruction->then_block, &cond_br_instruction->base);14622 IrBasicBlock *new_then_block = ir_get_new_bb_runtime(ira, cond_br_instruction->then_block, &cond_br_instruction->base);
13906 if (new_then_block == nullptr)14623 if (new_then_block == nullptr)
...@@ -13939,8 +14656,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh...@@ -13939,8 +14656,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
1393914656
13940 if (value->value.special != ConstValSpecialRuntime) {14657 if (value->value.special != ConstValSpecialRuntime) {
13941 IrInstruction *result = ir_const(ira, &phi_instruction->base, nullptr);14658 IrInstruction *result = ir_const(ira, &phi_instruction->base, nullptr);
13942 // TODO use copy_const_val?14659 copy_const_val(&result->value, &value->value, true);
13943 result->value = value->value;
13944 return result;14660 return result;
13945 } else {14661 } else {
13946 return value;14662 return value;
...@@ -13989,14 +14705,24 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh...@@ -13989,14 +14705,24 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
13989 if (type_is_invalid(resolved_type))14705 if (type_is_invalid(resolved_type))
13990 return ira->codegen->invalid_instruction;14706 return ira->codegen->invalid_instruction;
1399114707
13992 if (resolved_type->id == ZigTypeIdComptimeFloat ||14708 switch (type_has_one_possible_value(ira->codegen, resolved_type)) {
13993 resolved_type->id == ZigTypeIdComptimeInt ||14709 case OnePossibleValueInvalid:
13994 resolved_type->id == ZigTypeIdNull ||14710 return ira->codegen->invalid_instruction;
13995 resolved_type->id == ZigTypeIdUndefined)14711 case OnePossibleValueYes:
13996 {14712 return ir_const(ira, &phi_instruction->base, resolved_type);
14713 case OnePossibleValueNo:
14714 break;
14715 }
14716
14717 switch (type_requires_comptime(ira->codegen, resolved_type)) {
14718 case ReqCompTimeInvalid:
14719 return ira->codegen->invalid_instruction;
14720 case ReqCompTimeYes:
13997 ir_add_error_node(ira, phi_instruction->base.source_node,14721 ir_add_error_node(ira, phi_instruction->base.source_node,
13998 buf_sprintf("unable to infer expression type"));14722 buf_sprintf("values of type '%s' must be comptime known", buf_ptr(&resolved_type->name)));
13999 return ira->codegen->invalid_instruction;14723 return ira->codegen->invalid_instruction;
14724 case ReqCompTimeNo:
14725 break;
14000 }14726 }
1400114727
14002 bool all_stack_ptrs = (resolved_type->id == ZigTypeIdPointer);14728 bool all_stack_ptrs = (resolved_type->id == ZigTypeIdPointer);
...@@ -14112,7 +14838,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -14112,7 +14838,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
14112 array_type = array_type->data.pointer.child_type;14838 array_type = array_type->data.pointer.child_type;
14113 ptr_type = ptr_type->data.pointer.child_type;14839 ptr_type = ptr_type->data.pointer.child_type;
14114 if (orig_array_ptr_val->special != ConstValSpecialRuntime) {14840 if (orig_array_ptr_val->special != ConstValSpecialRuntime) {
14115 orig_array_ptr_val = ir_const_ptr_pointee(ira, orig_array_ptr_val,14841 orig_array_ptr_val = const_ptr_pointee(ira, ira->codegen, orig_array_ptr_val,
14116 elem_ptr_instruction->base.source_node);14842 elem_ptr_instruction->base.source_node);
14117 if (orig_array_ptr_val == nullptr)14843 if (orig_array_ptr_val == nullptr)
14118 return ira->codegen->invalid_instruction;14844 return ira->codegen->invalid_instruction;
...@@ -14156,7 +14882,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -14156,7 +14882,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
14156 ConstExprValue *ptr_val = ir_resolve_const(ira, array_ptr, UndefBad);14882 ConstExprValue *ptr_val = ir_resolve_const(ira, array_ptr, UndefBad);
14157 if (!ptr_val)14883 if (!ptr_val)
14158 return ira->codegen->invalid_instruction;14884 return ira->codegen->invalid_instruction;
14159 ConstExprValue *args_val = ir_const_ptr_pointee(ira, ptr_val, elem_ptr_instruction->base.source_node);14885 ConstExprValue *args_val = const_ptr_pointee(ira, ira->codegen, ptr_val, elem_ptr_instruction->base.source_node);
14160 if (args_val == nullptr)14886 if (args_val == nullptr)
14161 return ira->codegen->invalid_instruction;14887 return ira->codegen->invalid_instruction;
14162 size_t start = args_val->data.x_arg_tuple.start_index;14888 size_t start = args_val->data.x_arg_tuple.start_index;
...@@ -14238,7 +14964,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -14238,7 +14964,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
14238 (orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar ||14964 (orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar ||
14239 array_type->id == ZigTypeIdArray))14965 array_type->id == ZigTypeIdArray))
14240 {14966 {
14241 ConstExprValue *array_ptr_val = ir_const_ptr_pointee(ira, orig_array_ptr_val,14967 ConstExprValue *array_ptr_val = const_ptr_pointee(ira, ira->codegen, orig_array_ptr_val,
14242 elem_ptr_instruction->base.source_node);14968 elem_ptr_instruction->base.source_node);
14243 if (array_ptr_val == nullptr)14969 if (array_ptr_val == nullptr)
14244 return ira->codegen->invalid_instruction;14970 return ira->codegen->invalid_instruction;
...@@ -14286,10 +15012,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -14286,10 +15012,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
14286 }15012 }
14287 case ConstPtrSpecialBaseStruct:15013 case ConstPtrSpecialBaseStruct:
14288 zig_panic("TODO elem ptr on a const inner struct");15014 zig_panic("TODO elem ptr on a const inner struct");
15015 case ConstPtrSpecialBaseErrorUnionCode:
15016 zig_panic("TODO elem ptr on a const inner error union code");
15017 case ConstPtrSpecialBaseErrorUnionPayload:
15018 zig_panic("TODO elem ptr on a const inner error union payload");
15019 case ConstPtrSpecialBaseOptionalPayload:
15020 zig_panic("TODO elem ptr on a const inner optional payload");
14289 case ConstPtrSpecialHardCodedAddr:15021 case ConstPtrSpecialHardCodedAddr:
14290 zig_unreachable();15022 zig_unreachable();
14291 case ConstPtrSpecialFunction:15023 case ConstPtrSpecialFunction:
14292 zig_panic("TODO element ptr of a function casted to a ptr");15024 zig_panic("TODO element ptr of a function casted to a ptr");
15025 case ConstPtrSpecialNull:
15026 zig_panic("TODO elem ptr on a null pointer");
14293 }15027 }
14294 if (new_index >= mem_size) {15028 if (new_index >= mem_size) {
14295 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,15029 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
...@@ -14339,10 +15073,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -14339,10 +15073,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
14339 }15073 }
14340 case ConstPtrSpecialBaseStruct:15074 case ConstPtrSpecialBaseStruct:
14341 zig_panic("TODO elem ptr on a slice backed by const inner struct");15075 zig_panic("TODO elem ptr on a slice backed by const inner struct");
15076 case ConstPtrSpecialBaseErrorUnionCode:
15077 zig_panic("TODO elem ptr on a slice backed by const inner error union code");
15078 case ConstPtrSpecialBaseErrorUnionPayload:
15079 zig_panic("TODO elem ptr on a slice backed by const inner error union payload");
15080 case ConstPtrSpecialBaseOptionalPayload:
15081 zig_panic("TODO elem ptr on a slice backed by const optional payload");
14342 case ConstPtrSpecialHardCodedAddr:15082 case ConstPtrSpecialHardCodedAddr:
14343 zig_unreachable();15083 zig_unreachable();
14344 case ConstPtrSpecialFunction:15084 case ConstPtrSpecialFunction:
14345 zig_panic("TODO elem ptr on a slice that was ptrcast from a function");15085 zig_panic("TODO elem ptr on a slice that was ptrcast from a function");
15086 case ConstPtrSpecialNull:
15087 zig_panic("TODO elem ptr on a slice has a null pointer");
14346 }15088 }
14347 return result;15089 return result;
14348 } else if (array_type->id == ZigTypeIdArray) {15090 } else if (array_type->id == ZigTypeIdArray) {
...@@ -14457,13 +15199,12 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_...@@ -14457,13 +15199,12 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
14457 return ira->codegen->invalid_instruction;15199 return ira->codegen->invalid_instruction;
1445815200
14459 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {15201 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
14460 ConstExprValue *struct_val = ir_const_ptr_pointee(ira, ptr_val, source_instr->source_node);15202 ConstExprValue *struct_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
14461 if (struct_val == nullptr)15203 if (struct_val == nullptr)
14462 return ira->codegen->invalid_instruction;15204 return ira->codegen->invalid_instruction;
14463 if (type_is_invalid(struct_val->type))15205 if (type_is_invalid(struct_val->type))
14464 return ira->codegen->invalid_instruction;15206 return ira->codegen->invalid_instruction;
14465 ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index];15207 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
14466 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_val->type,
14467 is_const, is_volatile, PtrLenSingle, align_bytes,15208 is_const, is_volatile, PtrLenSingle, align_bytes,
14468 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),15209 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
14469 (uint32_t)host_int_bytes_for_result_type);15210 (uint32_t)host_int_bytes_for_result_type);
...@@ -14500,7 +15241,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_...@@ -14500,7 +15241,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
14500 return ira->codegen->invalid_instruction;15241 return ira->codegen->invalid_instruction;
1450115242
14502 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {15243 if (ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
14503 ConstExprValue *union_val = ir_const_ptr_pointee(ira, ptr_val, source_instr->source_node);15244 ConstExprValue *union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, source_instr->source_node);
14504 if (union_val == nullptr)15245 if (union_val == nullptr)
14505 return ira->codegen->invalid_instruction;15246 return ira->codegen->invalid_instruction;
14506 if (type_is_invalid(union_val->type))15247 if (type_is_invalid(union_val->type))
...@@ -14697,7 +15438,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc...@@ -14697,7 +15438,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
14697 return ira->codegen->invalid_instruction;15438 return ira->codegen->invalid_instruction;
1469815439
14699 assert(container_ptr->value.type->id == ZigTypeIdPointer);15440 assert(container_ptr->value.type->id == ZigTypeIdPointer);
14700 ConstExprValue *child_val = ir_const_ptr_pointee(ira, container_ptr_val, source_node);15441 ConstExprValue *child_val = const_ptr_pointee(ira, ira->codegen, container_ptr_val, source_node);
14701 if (child_val == nullptr)15442 if (child_val == nullptr)
14702 return ira->codegen->invalid_instruction;15443 return ira->codegen->invalid_instruction;
1470315444
...@@ -14723,7 +15464,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc...@@ -14723,7 +15464,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
14723 return ira->codegen->invalid_instruction;15464 return ira->codegen->invalid_instruction;
1472415465
14725 assert(container_ptr->value.type->id == ZigTypeIdPointer);15466 assert(container_ptr->value.type->id == ZigTypeIdPointer);
14726 ConstExprValue *child_val = ir_const_ptr_pointee(ira, container_ptr_val, source_node);15467 ConstExprValue *child_val = const_ptr_pointee(ira, ira->codegen, container_ptr_val, source_node);
14727 if (child_val == nullptr)15468 if (child_val == nullptr)
14728 return ira->codegen->invalid_instruction;15469 return ira->codegen->invalid_instruction;
14729 ZigType *child_type = child_val->data.x_type;15470 ZigType *child_type = child_val->data.x_type;
...@@ -14998,7 +15739,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc...@@ -14998,7 +15739,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
14998 if (!container_ptr_val)15739 if (!container_ptr_val)
14999 return ira->codegen->invalid_instruction;15740 return ira->codegen->invalid_instruction;
1500015741
15001 ConstExprValue *namespace_val = ir_const_ptr_pointee(ira, container_ptr_val,15742 ConstExprValue *namespace_val = const_ptr_pointee(ira, ira->codegen, container_ptr_val,
15002 field_ptr_instruction->base.source_node);15743 field_ptr_instruction->base.source_node);
15003 if (namespace_val == nullptr)15744 if (namespace_val == nullptr)
15004 return ira->codegen->invalid_instruction;15745 return ira->codegen->invalid_instruction;
...@@ -15030,74 +15771,23 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc...@@ -15030,74 +15771,23 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
15030 }15771 }
15031}15772}
1503215773
15033static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) {15774static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *instruction) {
15034 IrInstruction *ptr = load_ptr_instruction->ptr->child;15775 IrInstruction *ptr = instruction->ptr->child;
15035 if (type_is_invalid(ptr->value.type))
15036 return ira->codegen->invalid_instruction;
15037 return ir_get_deref(ira, &load_ptr_instruction->base, ptr);
15038}
15039
15040static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *store_ptr_instruction) {
15041 IrInstruction *ptr = store_ptr_instruction->ptr->child;
15042 if (type_is_invalid(ptr->value.type))15776 if (type_is_invalid(ptr->value.type))
15043 return ira->codegen->invalid_instruction;15777 return ira->codegen->invalid_instruction;
1504415778
15045 IrInstruction *value = store_ptr_instruction->value->child;15779 IrInstruction *value = instruction->value->child;
15046 if (type_is_invalid(value->value.type))15780 if (type_is_invalid(value->value.type))
15047 return ira->codegen->invalid_instruction;15781 return ira->codegen->invalid_instruction;
1504815782
15049 if (ptr->value.type->id != ZigTypeIdPointer) {15783 return ir_analyze_store_ptr(ira, &instruction->base, ptr, value);
15050 ir_add_error(ira, ptr,15784}
15051 buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name)));
15052 return ira->codegen->invalid_instruction;
15053 }
15054
15055 if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) {
15056 return ir_const_void(ira, &store_ptr_instruction->base);
15057 }
15058
15059 if (ptr->value.type->data.pointer.is_const && !store_ptr_instruction->base.is_gen) {
15060 ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant"));
15061 return ira->codegen->invalid_instruction;
15062 }
1506315785
15064 ZigType *child_type = ptr->value.type->data.pointer.child_type;15786static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *instruction) {
15065 IrInstruction *casted_value = ir_implicit_cast(ira, value, child_type);15787 IrInstruction *ptr = instruction->ptr->child;
15066 if (casted_value == ira->codegen->invalid_instruction)15788 if (type_is_invalid(ptr->value.type))
15067 return ira->codegen->invalid_instruction;15789 return ira->codegen->invalid_instruction;
1506815790 return ir_get_deref(ira, &instruction->base, ptr);
15069 if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
15070 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {
15071 ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant"));
15072 return ira->codegen->invalid_instruction;
15073 }
15074 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) {
15075 if (instr_is_comptime(casted_value)) {
15076 ConstExprValue *dest_val = ir_const_ptr_pointee(ira, &ptr->value, store_ptr_instruction->base.source_node);
15077 if (dest_val == nullptr)
15078 return ira->codegen->invalid_instruction;
15079 if (dest_val->special != ConstValSpecialRuntime) {
15080 *dest_val = casted_value->value;
15081 if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
15082 ira->new_irb.current_basic_block->must_be_comptime_source_instr = &store_ptr_instruction->base;
15083 }
15084 return ir_const_void(ira, &store_ptr_instruction->base);
15085 }
15086 }
15087 ir_add_error(ira, &store_ptr_instruction->base,
15088 buf_sprintf("cannot store runtime value in compile time variable"));
15089 ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
15090 dest_val->type = ira->codegen->builtin_types.entry_invalid;
15091
15092 return ira->codegen->invalid_instruction;
15093 }
15094 }
15095
15096 IrInstruction *result = ir_build_store_ptr(&ira->new_irb,
15097 store_ptr_instruction->base.scope, store_ptr_instruction->base.source_node,
15098 ptr, casted_value);
15099 result->value.type = ira->codegen->builtin_types.entry_void;
15100 return result;
15101}15791}
1510215792
15103static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) {15793static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) {
...@@ -15105,42 +15795,14 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio...@@ -15105,42 +15795,14 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio
15105 ZigType *type_entry = expr_value->value.type;15795 ZigType *type_entry = expr_value->value.type;
15106 if (type_is_invalid(type_entry))15796 if (type_is_invalid(type_entry))
15107 return ira->codegen->invalid_instruction;15797 return ira->codegen->invalid_instruction;
15108 switch (type_entry->id) {15798 return ir_const_type(ira, &typeof_instruction->base, type_entry);
15109 case ZigTypeIdInvalid:
15110 zig_unreachable(); // handled above
15111 case ZigTypeIdComptimeFloat:
15112 case ZigTypeIdComptimeInt:
15113 case ZigTypeIdUndefined:
15114 case ZigTypeIdNull:
15115 case ZigTypeIdNamespace:
15116 case ZigTypeIdBoundFn:
15117 case ZigTypeIdMetaType:
15118 case ZigTypeIdVoid:
15119 case ZigTypeIdBool:
15120 case ZigTypeIdUnreachable:
15121 case ZigTypeIdInt:
15122 case ZigTypeIdFloat:
15123 case ZigTypeIdPointer:
15124 case ZigTypeIdArray:
15125 case ZigTypeIdStruct:
15126 case ZigTypeIdOptional:
15127 case ZigTypeIdErrorUnion:
15128 case ZigTypeIdErrorSet:
15129 case ZigTypeIdEnum:
15130 case ZigTypeIdUnion:
15131 case ZigTypeIdFn:
15132 case ZigTypeIdArgTuple:
15133 case ZigTypeIdOpaque:
15134 case ZigTypeIdPromise:
15135 return ir_const_type(ira, &typeof_instruction->base, type_entry);
15136 }
15137
15138 zig_unreachable();
15139}15799}
1514015800
15141static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,15801static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
15142 IrInstructionToPtrType *to_ptr_type_instruction)15802 IrInstructionToPtrType *to_ptr_type_instruction)
15143{15803{
15804 Error err;
15805
15144 IrInstruction *value = to_ptr_type_instruction->value->child;15806 IrInstruction *value = to_ptr_type_instruction->value->child;
15145 ZigType *type_entry = value->value.type;15807 ZigType *type_entry = value->value.type;
15146 if (type_is_invalid(type_entry))15808 if (type_is_invalid(type_entry))
...@@ -15156,7 +15818,17 @@ static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,...@@ -15156,7 +15818,17 @@ static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
15156 ptr_type = get_pointer_to_type(ira->codegen,15818 ptr_type = get_pointer_to_type(ira->codegen,
15157 type_entry->data.pointer.child_type->data.array.child_type, type_entry->data.pointer.is_const);15819 type_entry->data.pointer.child_type->data.array.child_type, type_entry->data.pointer.is_const);
15158 } else if (is_slice(type_entry)) {15820 } else if (is_slice(type_entry)) {
15159 ptr_type = adjust_ptr_len(ira->codegen, type_entry->data.structure.fields[0].type_entry, PtrLenSingle);15821 ZigType *slice_ptr_type = type_entry->data.structure.fields[0].type_entry;
15822 ptr_type = adjust_ptr_len(ira->codegen, slice_ptr_type, PtrLenSingle);
15823 // If the pointer is over-aligned, we may have to reduce it based on the alignment of the element type.
15824 if (slice_ptr_type->data.pointer.explicit_alignment != 0) {
15825 ZigType *elem_type = slice_ptr_type->data.pointer.child_type;
15826 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusAlignmentKnown)))
15827 return ira->codegen->invalid_instruction;
15828 uint32_t elem_align = get_abi_alignment(ira->codegen, elem_type);
15829 uint32_t reduced_align = min(elem_align, slice_ptr_type->data.pointer.explicit_alignment);
15830 ptr_type = adjust_ptr_align(ira->codegen, ptr_type, reduced_align);
15831 }
15160 } else if (type_entry->id == ZigTypeIdArgTuple) {15832 } else if (type_entry->id == ZigTypeIdArgTuple) {
15161 ConstExprValue *arg_tuple_val = ir_resolve_const(ira, value, UndefBad);15833 ConstExprValue *arg_tuple_val = ir_resolve_const(ira, value, UndefBad);
15162 if (!arg_tuple_val)15834 if (!arg_tuple_val)
...@@ -15374,6 +16046,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,...@@ -15374,6 +16046,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
15374 case ZigTypeIdNamespace:16046 case ZigTypeIdNamespace:
15375 case ZigTypeIdBoundFn:16047 case ZigTypeIdBoundFn:
15376 case ZigTypeIdPromise:16048 case ZigTypeIdPromise:
16049 case ZigTypeIdVector:
15377 {16050 {
15378 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))16051 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
15379 return ira->codegen->invalid_instruction;16052 return ira->codegen->invalid_instruction;
...@@ -15494,6 +16167,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,...@@ -15494,6 +16167,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
15494 case ZigTypeIdNamespace:16167 case ZigTypeIdNamespace:
15495 case ZigTypeIdBoundFn:16168 case ZigTypeIdBoundFn:
15496 case ZigTypeIdPromise:16169 case ZigTypeIdPromise:
16170 case ZigTypeIdVector:
15497 {16171 {
15498 if ((err = ensure_complete_type(ira->codegen, child_type)))16172 if ((err = ensure_complete_type(ira->codegen, child_type)))
15499 return ira->codegen->invalid_instruction;16173 return ira->codegen->invalid_instruction;
...@@ -15560,6 +16234,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,...@@ -15560,6 +16234,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
15560 case ZigTypeIdUnion:16234 case ZigTypeIdUnion:
15561 case ZigTypeIdFn:16235 case ZigTypeIdFn:
15562 case ZigTypeIdPromise:16236 case ZigTypeIdPromise:
16237 case ZigTypeIdVector:
15563 {16238 {
15564 uint64_t size_in_bytes = type_size(ira->codegen, type_entry);16239 uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
15565 return ir_const_unsigned(ira, &size_of_instruction->base, size_in_bytes);16240 return ir_const_unsigned(ira, &size_of_instruction->base, size_in_bytes);
...@@ -15568,11 +16243,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,...@@ -15568,11 +16243,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
15568 zig_unreachable();16243 zig_unreachable();
15569}16244}
1557016245
15571static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) {16246static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value) {
15572 IrInstruction *value = instruction->value->child;
15573 if (type_is_invalid(value->value.type))
15574 return ira->codegen->invalid_instruction;
15575
15576 ZigType *type_entry = value->value.type;16247 ZigType *type_entry = value->value.type;
1557716248
15578 if (type_entry->id == ZigTypeIdOptional) {16249 if (type_entry->id == ZigTypeIdOptional) {
...@@ -15581,60 +16252,66 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns...@@ -15581,60 +16252,66 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns
15581 if (!maybe_val)16252 if (!maybe_val)
15582 return ira->codegen->invalid_instruction;16253 return ira->codegen->invalid_instruction;
1558316254
15584 return ir_const_bool(ira, &instruction->base, !optional_value_is_null(maybe_val));16255 return ir_const_bool(ira, source_inst, !optional_value_is_null(maybe_val));
15585 }16256 }
1558616257
15587 IrInstruction *result = ir_build_test_nonnull(&ira->new_irb,16258 IrInstruction *result = ir_build_test_nonnull(&ira->new_irb,
15588 instruction->base.scope, instruction->base.source_node, value);16259 source_inst->scope, source_inst->source_node, value);
15589 result->value.type = ira->codegen->builtin_types.entry_bool;16260 result->value.type = ira->codegen->builtin_types.entry_bool;
15590 return result;16261 return result;
15591 } else if (type_entry->id == ZigTypeIdNull) {16262 } else if (type_entry->id == ZigTypeIdNull) {
15592 return ir_const_bool(ira, &instruction->base, false);16263 return ir_const_bool(ira, source_inst, false);
15593 } else {16264 } else {
15594 return ir_const_bool(ira, &instruction->base, true);16265 return ir_const_bool(ira, source_inst, true);
15595 }16266 }
15596}16267}
1559716268
15598static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,16269static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) {
15599 IrInstructionUnwrapOptional *unwrap_maybe_instruction)16270 IrInstruction *value = instruction->value->child;
15600{
15601 IrInstruction *value = unwrap_maybe_instruction->value->child;
15602 if (type_is_invalid(value->value.type))16271 if (type_is_invalid(value->value.type))
15603 return ira->codegen->invalid_instruction;16272 return ira->codegen->invalid_instruction;
1560416273
15605 ZigType *ptr_type = value->value.type;16274 return ir_analyze_test_non_null(ira, &instruction->base, value);
16275}
16276
16277static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
16278 IrInstruction *base_ptr, bool safety_check_on)
16279{
16280 ZigType *ptr_type = base_ptr->value.type;
15606 assert(ptr_type->id == ZigTypeIdPointer);16281 assert(ptr_type->id == ZigTypeIdPointer);
1560716282
15608 ZigType *type_entry = ptr_type->data.pointer.child_type;16283 ZigType *type_entry = ptr_type->data.pointer.child_type;
15609 if (type_is_invalid(type_entry)) {16284 if (type_is_invalid(type_entry))
15610 return ira->codegen->invalid_instruction;16285 return ira->codegen->invalid_instruction;
15611 } else if (type_entry->id != ZigTypeIdOptional) {16286
15612 ir_add_error_node(ira, unwrap_maybe_instruction->value->source_node,16287 if (type_entry->id != ZigTypeIdOptional) {
16288 ir_add_error_node(ira, base_ptr->source_node,
15613 buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name)));16289 buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name)));
15614 return ira->codegen->invalid_instruction;16290 return ira->codegen->invalid_instruction;
15615 }16291 }
16292
15616 ZigType *child_type = type_entry->data.maybe.child_type;16293 ZigType *child_type = type_entry->data.maybe.child_type;
15617 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,16294 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
15618 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0);16295 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0);
1561916296
15620 if (instr_is_comptime(value)) {16297 if (instr_is_comptime(base_ptr)) {
15621 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);16298 ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad);
15622 if (!val)16299 if (!val)
15623 return ira->codegen->invalid_instruction;16300 return ira->codegen->invalid_instruction;
15624 ConstExprValue *maybe_val = ir_const_ptr_pointee(ira, val, unwrap_maybe_instruction->base.source_node);16301 ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node);
15625 if (maybe_val == nullptr)16302 if (maybe_val == nullptr)
15626 return ira->codegen->invalid_instruction;16303 return ira->codegen->invalid_instruction;
1562716304
15628 if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {16305 if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
15629 if (optional_value_is_null(maybe_val)) {16306 if (optional_value_is_null(maybe_val)) {
15630 ir_add_error(ira, &unwrap_maybe_instruction->base, buf_sprintf("unable to unwrap null"));16307 ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null"));
15631 return ira->codegen->invalid_instruction;16308 return ira->codegen->invalid_instruction;
15632 }16309 }
15633 IrInstruction *result = ir_const(ira, &unwrap_maybe_instruction->base, result_type);16310 IrInstruction *result = ir_const(ira, source_instr, result_type);
15634 ConstExprValue *out_val = &result->value;16311 ConstExprValue *out_val = &result->value;
15635 out_val->data.x_ptr.special = ConstPtrSpecialRef;16312 out_val->data.x_ptr.special = ConstPtrSpecialRef;
15636 out_val->data.x_ptr.mut = val->data.x_ptr.mut;16313 out_val->data.x_ptr.mut = val->data.x_ptr.mut;
15637 if (type_is_codegen_pointer(child_type)) {16314 if (types_have_same_zig_comptime_repr(type_entry, child_type)) {
15638 out_val->data.x_ptr.data.ref.pointee = maybe_val;16315 out_val->data.x_ptr.data.ref.pointee = maybe_val;
15639 } else {16316 } else {
15640 out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_optional;16317 out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_optional;
...@@ -15643,13 +16320,22 @@ static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,...@@ -15643,13 +16320,22 @@ static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
15643 }16320 }
15644 }16321 }
1564516322
15646 IrInstruction *result = ir_build_unwrap_maybe(&ira->new_irb,16323 IrInstruction *result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope,
15647 unwrap_maybe_instruction->base.scope, unwrap_maybe_instruction->base.source_node,16324 source_instr->source_node, base_ptr, safety_check_on);
15648 value, unwrap_maybe_instruction->safety_check_on);
15649 result->value.type = result_type;16325 result->value.type = result_type;
15650 return result;16326 return result;
15651}16327}
1565216328
16329static IrInstruction *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira,
16330 IrInstructionOptionalUnwrapPtr *instruction)
16331{
16332 IrInstruction *base_ptr = instruction->base_ptr->child;
16333 if (type_is_invalid(base_ptr->value.type))
16334 return ira->codegen->invalid_instruction;
16335
16336 return ir_analyze_unwrap_optional_payload(ira, &instruction->base, base_ptr, instruction->safety_check_on);
16337}
16338
15653static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) {16339static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) {
15654 IrInstruction *value = ctz_instruction->value->child;16340 IrInstruction *value = ctz_instruction->value->child;
15655 if (type_is_invalid(value->value.type)) {16341 if (type_is_invalid(value->value.type)) {
...@@ -15918,10 +16604,10 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -15918,10 +16604,10 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
15918 ZigType *target_type = target_value_ptr->value.type->data.pointer.child_type;16604 ZigType *target_type = target_value_ptr->value.type->data.pointer.child_type;
15919 ConstExprValue *pointee_val = nullptr;16605 ConstExprValue *pointee_val = nullptr;
15920 if (instr_is_comptime(target_value_ptr)) {16606 if (instr_is_comptime(target_value_ptr)) {
15921 pointee_val = ir_const_ptr_pointee(ira, &target_value_ptr->value, target_value_ptr->source_node);16607 pointee_val = const_ptr_pointee(ira, ira->codegen, &target_value_ptr->value, target_value_ptr->source_node);
15922 if (pointee_val == nullptr)16608 if (pointee_val == nullptr)
15923 return ira->codegen->invalid_instruction;16609 return ira->codegen->invalid_instruction;
15924 16610
15925 if (pointee_val->special == ConstValSpecialRuntime)16611 if (pointee_val->special == ConstValSpecialRuntime)
15926 pointee_val = nullptr;16612 pointee_val = nullptr;
15927 }16613 }
...@@ -15950,9 +16636,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -15950,9 +16636,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
15950 return result;16636 return result;
15951 }16637 }
1595216638
15953 IrInstruction *result = ir_build_load_ptr(&ira->new_irb,16639 IrInstruction *result = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
15954 switch_target_instruction->base.scope, switch_target_instruction->base.source_node,
15955 target_value_ptr);
15956 result->value.type = target_type;16640 result->value.type = target_type;
15957 return result;16641 return result;
15958 }16642 }
...@@ -15982,8 +16666,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -15982,8 +16666,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
15982 return result;16666 return result;
15983 }16667 }
1598416668
15985 IrInstruction *union_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,16669 IrInstruction *union_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
15986 switch_target_instruction->base.source_node, target_value_ptr);
15987 union_value->value.type = target_type;16670 union_value->value.type = target_type;
1598816671
15989 IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope,16672 IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope,
...@@ -16007,8 +16690,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -16007,8 +16690,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
16007 return result;16690 return result;
16008 }16691 }
1600916692
16010 IrInstruction *enum_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,16693 IrInstruction *enum_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
16011 switch_target_instruction->base.source_node, target_value_ptr);
16012 enum_value->value.type = target_type;16694 enum_value->value.type = target_type;
16013 return enum_value;16695 return enum_value;
16014 }16696 }
...@@ -16022,6 +16704,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -16022,6 +16704,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
16022 case ZigTypeIdBoundFn:16704 case ZigTypeIdBoundFn:
16023 case ZigTypeIdArgTuple:16705 case ZigTypeIdArgTuple:
16024 case ZigTypeIdOpaque:16706 case ZigTypeIdOpaque:
16707 case ZigTypeIdVector:
16025 ir_add_error(ira, &switch_target_instruction->base,16708 ir_add_error(ira, &switch_target_instruction->base,
16026 buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name)));16709 buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name)));
16027 return ira->codegen->invalid_instruction;16710 return ira->codegen->invalid_instruction;
...@@ -16053,7 +16736,7 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru...@@ -16053,7 +16736,7 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru
16053 if (!target_value_ptr)16736 if (!target_value_ptr)
16054 return ira->codegen->invalid_instruction;16737 return ira->codegen->invalid_instruction;
1605516738
16056 ConstExprValue *pointee_val = ir_const_ptr_pointee(ira, target_val_ptr, instruction->base.source_node);16739 ConstExprValue *pointee_val = const_ptr_pointee(ira, ira->codegen, target_val_ptr, instruction->base.source_node);
16057 if (pointee_val == nullptr)16740 if (pointee_val == nullptr)
16058 return ira->codegen->invalid_instruction;16741 return ira->codegen->invalid_instruction;
1605916742
...@@ -16165,7 +16848,7 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI...@@ -16165,7 +16848,7 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
16165 Error err;16848 Error err;
16166 assert(container_type->id == ZigTypeIdUnion);16849 assert(container_type->id == ZigTypeIdUnion);
1616716850
16168 if ((err = ensure_complete_type(ira->codegen, container_type)))16851 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
16169 return ira->codegen->invalid_instruction;16852 return ira->codegen->invalid_instruction;
1617016853
16171 if (instr_field_count != 1) {16854 if (instr_field_count != 1) {
...@@ -16197,7 +16880,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI...@@ -16197,7 +16880,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
16197 if ((err = type_resolve(ira->codegen, casted_field_value->value.type, ResolveStatusZeroBitsKnown)))16880 if ((err = type_resolve(ira->codegen, casted_field_value->value.type, ResolveStatusZeroBitsKnown)))
16198 return ira->codegen->invalid_instruction;16881 return ira->codegen->invalid_instruction;
1619916882
16200 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope);16883 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
16884 || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
16201 if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime ||16885 if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime ||
16202 !type_has_bits(casted_field_value->value.type))16886 !type_has_bits(casted_field_value->value.type))
16203 {16887 {
...@@ -16209,12 +16893,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI...@@ -16209,12 +16893,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
16209 ConstExprValue *out_val = &result->value;16893 ConstExprValue *out_val = &result->value;
16210 out_val->data.x_union.payload = field_val;16894 out_val->data.x_union.payload = field_val;
16211 out_val->data.x_union.tag = type_field->enum_field->value;16895 out_val->data.x_union.tag = type_field->enum_field->value;
1621216896 out_val->parent.id = ConstParentIdUnion;
16213 ConstParent *parent = get_const_val_parent(ira->codegen, field_val);16897 out_val->parent.data.p_union.union_val = out_val;
16214 if (parent != nullptr) {
16215 parent->id = ConstParentIdUnion;
16216 parent->data.p_union.union_val = out_val;
16217 }
1621816898
16219 return result;16899 return result;
16220 }16900 }
...@@ -16241,7 +16921,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -16241,7 +16921,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
16241 return ira->codegen->invalid_instruction;16921 return ira->codegen->invalid_instruction;
16242 }16922 }
1624316923
16244 if ((err = ensure_complete_type(ira->codegen, container_type)))16924 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
16245 return ira->codegen->invalid_instruction;16925 return ira->codegen->invalid_instruction;
1624616926
16247 size_t actual_field_count = container_type->data.structure.src_field_count;16927 size_t actual_field_count = container_type->data.structure.src_field_count;
...@@ -16252,7 +16932,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -16252,7 +16932,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1625216932
16253 IrInstructionStructInitField *new_fields = allocate<IrInstructionStructInitField>(actual_field_count);16933 IrInstructionStructInitField *new_fields = allocate<IrInstructionStructInitField>(actual_field_count);
1625416934
16255 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope);16935 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
16936 || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
1625616937
16257 ConstExprValue const_val = {};16938 ConstExprValue const_val = {};
16258 const_val.special = ConstValSpecialStatic;16939 const_val.special = ConstValSpecialStatic;
...@@ -16320,9 +17001,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -16320,9 +17001,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
16320 if (const_val.special == ConstValSpecialStatic) {17001 if (const_val.special == ConstValSpecialStatic) {
16321 IrInstruction *result = ir_const(ira, instruction, nullptr);17002 IrInstruction *result = ir_const(ira, instruction, nullptr);
16322 ConstExprValue *out_val = &result->value;17003 ConstExprValue *out_val = &result->value;
16323 // TODO copy_const_val?17004 copy_const_val(out_val, &const_val, true);
16324 *out_val = const_val;17005 out_val->type = container_type;
16325 result->value.type = container_type;
1632617006
16327 for (size_t i = 0; i < instr_field_count; i += 1) {17007 for (size_t i = 0; i < instr_field_count; i += 1) {
16328 ConstExprValue *field_val = &out_val->data.x_struct.fields[i];17008 ConstExprValue *field_val = &out_val->data.x_struct.fields[i];
...@@ -16354,127 +17034,119 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -16354,127 +17034,119 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
16354static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,17034static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
16355 IrInstructionContainerInitList *instruction)17035 IrInstructionContainerInitList *instruction)
16356{17036{
16357 IrInstruction *container_type_value = instruction->container_type->child;17037 ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
16358 if (type_is_invalid(container_type_value->value.type))17038 if (type_is_invalid(container_type))
16359 return ira->codegen->invalid_instruction;17039 return ira->codegen->invalid_instruction;
1636017040
16361 size_t elem_count = instruction->item_count;17041 size_t elem_count = instruction->item_count;
16362 if (container_type_value->value.type->id == ZigTypeIdMetaType) {
16363 ZigType *container_type = ir_resolve_type(ira, container_type_value);
16364 if (type_is_invalid(container_type))
16365 return ira->codegen->invalid_instruction;
1636617042
16367 if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {17043 if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {
16368 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,17044 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
16369 0, nullptr);17045 0, nullptr);
16370 } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) {17046 } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) {
16371 // array is same as slice init but we make a compile error if the length is wrong17047 // array is same as slice init but we make a compile error if the length is wrong
16372 ZigType *child_type;17048 ZigType *child_type;
16373 if (container_type->id == ZigTypeIdArray) {17049 if (container_type->id == ZigTypeIdArray) {
16374 child_type = container_type->data.array.child_type;17050 child_type = container_type->data.array.child_type;
16375 if (container_type->data.array.len != elem_count) {17051 if (container_type->data.array.len != elem_count) {
16376 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);17052 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
1637717053
16378 ir_add_error(ira, &instruction->base,17054 ir_add_error(ira, &instruction->base,
16379 buf_sprintf("expected %s literal, found %s literal",17055 buf_sprintf("expected %s literal, found %s literal",
16380 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));17056 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
16381 return ira->codegen->invalid_instruction;17057 return ira->codegen->invalid_instruction;
16382 }
16383 } else {
16384 ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry;
16385 assert(pointer_type->id == ZigTypeIdPointer);
16386 child_type = pointer_type->data.pointer.child_type;
16387 }17058 }
17059 } else {
17060 ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry;
17061 assert(pointer_type->id == ZigTypeIdPointer);
17062 child_type = pointer_type->data.pointer.child_type;
17063 }
1638817064
16389 ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count);17065 ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count);
1639017066
16391 ConstExprValue const_val = {};17067 ConstExprValue const_val = {};
16392 const_val.special = ConstValSpecialStatic;17068 const_val.special = ConstValSpecialStatic;
16393 const_val.type = fixed_size_array_type;17069 const_val.type = fixed_size_array_type;
16394 const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);17070 const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);
1639517071
16396 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);17072 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
1639717073
16398 IrInstruction **new_items = allocate<IrInstruction *>(elem_count);17074 IrInstruction **new_items = allocate<IrInstruction *>(elem_count);
1639917075
16400 IrInstruction *first_non_const_instruction = nullptr;17076 IrInstruction *first_non_const_instruction = nullptr;
1640117077
16402 for (size_t i = 0; i < elem_count; i += 1) {17078 for (size_t i = 0; i < elem_count; i += 1) {
16403 IrInstruction *arg_value = instruction->items[i]->child;17079 IrInstruction *arg_value = instruction->items[i]->child;
16404 if (type_is_invalid(arg_value->value.type))17080 if (type_is_invalid(arg_value->value.type))
16405 return ira->codegen->invalid_instruction;17081 return ira->codegen->invalid_instruction;
1640617082
16407 IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);17083 IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);
16408 if (casted_arg == ira->codegen->invalid_instruction)17084 if (casted_arg == ira->codegen->invalid_instruction)
16409 return ira->codegen->invalid_instruction;17085 return ira->codegen->invalid_instruction;
1641017086
16411 new_items[i] = casted_arg;17087 new_items[i] = casted_arg;
1641217088
16413 if (const_val.special == ConstValSpecialStatic) {17089 if (const_val.special == ConstValSpecialStatic) {
16414 if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {17090 if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {
16415 ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);17091 ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);
16416 if (!elem_val)17092 if (!elem_val)
16417 return ira->codegen->invalid_instruction;17093 return ira->codegen->invalid_instruction;
1641817094
16419 copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);17095 copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);
16420 } else {17096 } else {
16421 first_non_const_instruction = casted_arg;17097 first_non_const_instruction = casted_arg;
16422 const_val.special = ConstValSpecialRuntime;17098 const_val.special = ConstValSpecialRuntime;
16423 }
16424 }17099 }
16425 }17100 }
17101 }
1642617102
16427 if (const_val.special == ConstValSpecialStatic) {17103 if (const_val.special == ConstValSpecialStatic) {
16428 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);17104 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
16429 ConstExprValue *out_val = &result->value;17105 ConstExprValue *out_val = &result->value;
16430 // TODO copy_const_val?17106 copy_const_val(out_val, &const_val, true);
16431 *out_val = const_val;17107 result->value.type = fixed_size_array_type;
16432 result->value.type = fixed_size_array_type;17108 for (size_t i = 0; i < elem_count; i += 1) {
16433 for (size_t i = 0; i < elem_count; i += 1) {17109 ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];
16434 ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];17110 ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);
16435 ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);17111 if (parent != nullptr) {
16436 if (parent != nullptr) {17112 parent->id = ConstParentIdArray;
16437 parent->id = ConstParentIdArray;17113 parent->data.p_array.array_val = out_val;
16438 parent->data.p_array.array_val = out_val;17114 parent->data.p_array.elem_index = i;
16439 parent->data.p_array.elem_index = i;
16440 }
16441 }17115 }
16442 return result;
16443 }17116 }
17117 return result;
17118 }
1644417119
16445 if (is_comptime) {17120 if (is_comptime) {
16446 ir_add_error_node(ira, first_non_const_instruction->source_node,17121 ir_add_error_node(ira, first_non_const_instruction->source_node,
16447 buf_sprintf("unable to evaluate constant expression"));17122 buf_sprintf("unable to evaluate constant expression"));
16448 return ira->codegen->invalid_instruction;17123 return ira->codegen->invalid_instruction;
16449 }17124 }
1645017125
16451 IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,17126 IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,
16452 instruction->base.scope, instruction->base.source_node,17127 instruction->base.scope, instruction->base.source_node,
16453 container_type_value, elem_count, new_items);17128 nullptr, elem_count, new_items);
16454 new_instruction->value.type = fixed_size_array_type;17129 new_instruction->value.type = fixed_size_array_type;
16455 ir_add_alloca(ira, new_instruction, fixed_size_array_type);17130 ir_add_alloca(ira, new_instruction, fixed_size_array_type);
16456 return new_instruction;17131 return new_instruction;
16457 } else if (container_type->id == ZigTypeIdVoid) {17132 } else if (container_type->id == ZigTypeIdVoid) {
16458 if (elem_count != 0) {17133 if (elem_count != 0) {
16459 ir_add_error_node(ira, instruction->base.source_node,
16460 buf_sprintf("void expression expects no arguments"));
16461 return ira->codegen->invalid_instruction;
16462 }
16463 return ir_const_void(ira, &instruction->base);
16464 } else {
16465 ir_add_error_node(ira, instruction->base.source_node,17134 ir_add_error_node(ira, instruction->base.source_node,
16466 buf_sprintf("type '%s' does not support array initialization",17135 buf_sprintf("void expression expects no arguments"));
16467 buf_ptr(&container_type->name)));
16468 return ira->codegen->invalid_instruction;17136 return ira->codegen->invalid_instruction;
16469 }17137 }
17138 return ir_const_void(ira, &instruction->base);
16470 } else {17139 } else {
16471 ir_add_error(ira, container_type_value,17140 ir_add_error_node(ira, instruction->base.source_node,
16472 buf_sprintf("expected type, found '%s' value", buf_ptr(&container_type_value->value.type->name)));17141 buf_sprintf("type '%s' does not support array initialization",
17142 buf_ptr(&container_type->name)));
16473 return ira->codegen->invalid_instruction;17143 return ira->codegen->invalid_instruction;
16474 }17144 }
16475}17145}
1647617146
16477static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, IrInstructionContainerInitFields *instruction) {17147static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira,
17148 IrInstructionContainerInitFields *instruction)
17149{
16478 IrInstruction *container_type_value = instruction->container_type->child;17150 IrInstruction *container_type_value = instruction->container_type->child;
16479 ZigType *container_type = ir_resolve_type(ira, container_type_value);17151 ZigType *container_type = ir_resolve_type(ira, container_type_value);
16480 if (type_is_invalid(container_type))17152 if (type_is_invalid(container_type))
...@@ -16534,7 +17206,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct...@@ -16534,7 +17206,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct
16534 if (type_is_invalid(value->value.type))17206 if (type_is_invalid(value->value.type))
16535 return ira->codegen->invalid_instruction;17207 return ira->codegen->invalid_instruction;
1653617208
16537 IrInstruction *casted_value = ir_implicit_cast(ira, value, value->value.type);17209 IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->codegen->builtin_types.entry_global_error_set);
16538 if (type_is_invalid(casted_value->value.type))17210 if (type_is_invalid(casted_value->value.type))
16539 return ira->codegen->invalid_instruction;17211 return ira->codegen->invalid_instruction;
1654017212
...@@ -16685,7 +17357,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,...@@ -16685,7 +17357,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
16685static TypeStructField *validate_byte_offset(IrAnalyze *ira,17357static TypeStructField *validate_byte_offset(IrAnalyze *ira,
16686 IrInstruction *type_value,17358 IrInstruction *type_value,
16687 IrInstruction *field_name_value,17359 IrInstruction *field_name_value,
16688 size_t *byte_offset) 17360 size_t *byte_offset)
16689{17361{
16690 ZigType *container_type = ir_resolve_type(ira, type_value);17362 ZigType *container_type = ir_resolve_type(ira, type_value);
16691 if (type_is_invalid(container_type))17363 if (type_is_invalid(container_type))
...@@ -16768,16 +17440,12 @@ static void ensure_field_index(ZigType *type, const char *field_name, size_t ind...@@ -16768,16 +17440,12 @@ static void ensure_field_index(ZigType *type, const char *field_name, size_t ind
1676817440
16769static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, ZigType *root) {17441static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, ZigType *root) {
16770 Error err;17442 Error err;
16771 static ConstExprValue *type_info_var = nullptr; // TODO oops this global variable made it past code review17443 ConstExprValue *type_info_var = get_builtin_value(ira->codegen, "TypeInfo");
16772 static ZigType *type_info_type = nullptr; // TODO oops this global variable made it past code review17444 assert(type_info_var->type->id == ZigTypeIdMetaType);
16773 if (type_info_var == nullptr) {17445 assertNoError(ensure_complete_type(ira->codegen, type_info_var->data.x_type));
16774 type_info_var = get_builtin_value(ira->codegen, "TypeInfo");
16775 assert(type_info_var->type->id == ZigTypeIdMetaType);
1677617446
16777 assertNoError(ensure_complete_type(ira->codegen, type_info_var->data.x_type));17447 ZigType *type_info_type = type_info_var->data.x_type;
16778 type_info_type = type_info_var->data.x_type;17448 assert(type_info_type->id == ZigTypeIdUnion);
16779 assert(type_info_type->id == ZigTypeIdUnion);
16780 }
1678117449
16782 if (type_name == nullptr && root == nullptr)17450 if (type_name == nullptr && root == nullptr)
16783 return type_info_type;17451 return type_info_type;
...@@ -16799,10 +17467,11 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig...@@ -16799,10 +17467,11 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig
1679917467
16800 ZigVar *var = tld->var;17468 ZigVar *var = tld->var;
1680117469
16802 if ((err = ensure_complete_type(ira->codegen, var->value->type)))17470 if ((err = ensure_complete_type(ira->codegen, var->const_value->type)))
16803 return ira->codegen->builtin_types.entry_invalid;17471 return ira->codegen->builtin_types.entry_invalid;
16804 assert(var->value->type->id == ZigTypeIdMetaType);17472
16805 return var->value->data.x_type;17473 assert(var->const_value->type->id == ZigTypeIdMetaType);
17474 return var->const_value->data.x_type;
16806}17475}
1680717476
16808static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, ScopeDecls *decls_scope) {17477static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, ScopeDecls *decls_scope) {
...@@ -16857,13 +17526,12 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco...@@ -16857,13 +17526,12 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
16857 definition_array->special = ConstValSpecialStatic;17526 definition_array->special = ConstValSpecialStatic;
16858 definition_array->type = get_array_type(ira->codegen, type_info_definition_type, definition_count);17527 definition_array->type = get_array_type(ira->codegen, type_info_definition_type, definition_count);
16859 definition_array->data.x_array.special = ConstArraySpecialNone;17528 definition_array->data.x_array.special = ConstArraySpecialNone;
16860 definition_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
16861 definition_array->data.x_array.data.s_none.elements = create_const_vals(definition_count);17529 definition_array->data.x_array.data.s_none.elements = create_const_vals(definition_count);
16862 init_const_slice(ira->codegen, out_val, definition_array, 0, definition_count, false);17530 init_const_slice(ira->codegen, out_val, definition_array, 0, definition_count, false);
1686317531
16864 // Loop through the definitions and generate info.17532 // Loop through the definitions and generate info.
16865 decl_it = decls_scope->decl_table.entry_iterator();17533 decl_it = decls_scope->decl_table.entry_iterator();
16866 curr_entry = nullptr; 17534 curr_entry = nullptr;
16867 int definition_index = 0;17535 int definition_index = 0;
16868 while ((curr_entry = decl_it.next()) != nullptr) {17536 while ((curr_entry = decl_it.next()) != nullptr) {
16869 // Skip comptime blocks and test functions.17537 // Skip comptime blocks and test functions.
...@@ -16888,33 +17556,30 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco...@@ -16888,33 +17556,30 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
16888 inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub;17556 inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub;
16889 inner_fields[2].special = ConstValSpecialStatic;17557 inner_fields[2].special = ConstValSpecialStatic;
16890 inner_fields[2].type = type_info_definition_data_type;17558 inner_fields[2].type = type_info_definition_data_type;
16891 inner_fields[2].data.x_union.parent.id = ConstParentIdStruct;17559 inner_fields[2].parent.id = ConstParentIdStruct;
16892 inner_fields[2].data.x_union.parent.data.p_struct.struct_val = definition_val;17560 inner_fields[2].parent.data.p_struct.struct_val = definition_val;
16893 inner_fields[2].data.x_union.parent.data.p_struct.field_index = 1;17561 inner_fields[2].parent.data.p_struct.field_index = 1;
1689417562
16895 switch (curr_entry->value->id) {17563 switch (curr_entry->value->id) {
16896 case TldIdVar:17564 case TldIdVar:
16897 {17565 {
16898 ZigVar *var = ((TldVar *)curr_entry->value)->var;17566 ZigVar *var = ((TldVar *)curr_entry->value)->var;
16899 if ((err = ensure_complete_type(ira->codegen, var->value->type)))17567 if ((err = ensure_complete_type(ira->codegen, var->const_value->type)))
16900 return ErrorSemanticAnalyzeFail;17568 return ErrorSemanticAnalyzeFail;
1690117569
16902 if (var->value->type->id == ZigTypeIdMetaType)17570 if (var->const_value->type->id == ZigTypeIdMetaType) {
16903 {
16904 // We have a variable of type 'type', so it's actually a type definition.17571 // We have a variable of type 'type', so it's actually a type definition.
16905 // 0: Data.Type: type17572 // 0: Data.Type: type
16906 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0);17573 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0);
16907 inner_fields[2].data.x_union.payload = var->value;17574 inner_fields[2].data.x_union.payload = var->const_value;
16908 }17575 } else {
16909 else
16910 {
16911 // We have a variable of another type, so we store the type of the variable.17576 // We have a variable of another type, so we store the type of the variable.
16912 // 1: Data.Var: type17577 // 1: Data.Var: type
16913 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 1);17578 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 1);
1691417579
16915 ConstExprValue *payload = create_const_vals(1);17580 ConstExprValue *payload = create_const_vals(1);
16916 payload->type = ira->codegen->builtin_types.entry_type;17581 payload->type = ira->codegen->builtin_types.entry_type;
16917 payload->data.x_type = var->value->type;17582 payload->data.x_type = var->const_value->type;
1691817583
16919 inner_fields[2].data.x_union.payload = payload;17584 inner_fields[2].data.x_union.payload = payload;
16920 }17585 }
...@@ -16934,8 +17599,8 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco...@@ -16934,8 +17599,8 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
16934 ConstExprValue *fn_def_val = create_const_vals(1);17599 ConstExprValue *fn_def_val = create_const_vals(1);
16935 fn_def_val->special = ConstValSpecialStatic;17600 fn_def_val->special = ConstValSpecialStatic;
16936 fn_def_val->type = type_info_fn_def_type;17601 fn_def_val->type = type_info_fn_def_type;
16937 fn_def_val->data.x_struct.parent.id = ConstParentIdUnion;17602 fn_def_val->parent.id = ConstParentIdUnion;
16938 fn_def_val->data.x_struct.parent.data.p_union.union_val = &inner_fields[2];17603 fn_def_val->parent.data.p_union.union_val = &inner_fields[2];
1693917604
16940 ConstExprValue *fn_def_fields = create_const_vals(9);17605 ConstExprValue *fn_def_fields = create_const_vals(9);
16941 fn_def_val->data.x_struct.fields = fn_def_fields;17606 fn_def_val->data.x_struct.fields = fn_def_fields;
...@@ -16990,12 +17655,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco...@@ -16990,12 +17655,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
16990 ensure_field_index(fn_def_val->type, "return_type", 7);17655 ensure_field_index(fn_def_val->type, "return_type", 7);
16991 fn_def_fields[7].special = ConstValSpecialStatic;17656 fn_def_fields[7].special = ConstValSpecialStatic;
16992 fn_def_fields[7].type = ira->codegen->builtin_types.entry_type;17657 fn_def_fields[7].type = ira->codegen->builtin_types.entry_type;
16993 if (fn_entry->src_implicit_return_type != nullptr)17658 fn_def_fields[7].data.x_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
16994 fn_def_fields[7].data.x_type = fn_entry->src_implicit_return_type;
16995 else if (fn_entry->type_entry->data.fn.gen_return_type != nullptr)
16996 fn_def_fields[7].data.x_type = fn_entry->type_entry->data.fn.gen_return_type;
16997 else
16998 fn_def_fields[7].data.x_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
16999 // arg_names: [][] const u817659 // arg_names: [][] const u8
17000 ensure_field_index(fn_def_val->type, "arg_names", 8);17660 ensure_field_index(fn_def_val->type, "arg_names", 8);
17001 size_t fn_arg_count = fn_entry->variable_list.length;17661 size_t fn_arg_count = fn_entry->variable_list.length;
...@@ -17004,20 +17664,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco...@@ -17004,20 +17664,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
17004 fn_arg_name_array->type = get_array_type(ira->codegen,17664 fn_arg_name_array->type = get_array_type(ira->codegen,
17005 get_slice_type(ira->codegen, u8_ptr), fn_arg_count);17665 get_slice_type(ira->codegen, u8_ptr), fn_arg_count);
17006 fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;17666 fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;
17007 fn_arg_name_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
17008 fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);17667 fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
1700917668
17010 init_const_slice(ira->codegen, &fn_def_fields[8], fn_arg_name_array, 0, fn_arg_count, false);17669 init_const_slice(ira->codegen, &fn_def_fields[8], fn_arg_name_array, 0, fn_arg_count, false);
1701117670
17012 for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++)17671 for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) {
17013 {
17014 ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index);17672 ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index);
17015 ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index];17673 ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index];
17016 ConstExprValue *arg_name = create_const_str_lit(ira->codegen, &arg_var->name);17674 ConstExprValue *arg_name = create_const_str_lit(ira->codegen, &arg_var->name);
17017 init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, buf_len(&arg_var->name), true);17675 init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, buf_len(&arg_var->name), true);
17018 fn_arg_name_val->data.x_struct.parent.id = ConstParentIdArray;17676 fn_arg_name_val->parent.id = ConstParentIdArray;
17019 fn_arg_name_val->data.x_struct.parent.data.p_array.array_val = fn_arg_name_array;17677 fn_arg_name_val->parent.data.p_array.array_val = fn_arg_name_array;
17020 fn_arg_name_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index;17678 fn_arg_name_val->parent.data.p_array.elem_index = fn_arg_index;
17021 }17679 }
1702217680
17023 inner_fields[2].data.x_union.payload = fn_def_val;17681 inner_fields[2].data.x_union.payload = fn_def_val;
...@@ -17052,6 +17710,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco...@@ -17052,6 +17710,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
17052 return ErrorNone;17710 return ErrorNone;
17053}17711}
1705417712
17713static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) {
17714 switch (ptr_len) {
17715 case PtrLenSingle:
17716 return 0;
17717 case PtrLenUnknown:
17718 return 1;
17719 case PtrLenC:
17720 return 3;
17721 }
17722 zig_unreachable();
17723}
17724
17055static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) {17725static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) {
17056 Error err;17726 Error err;
17057 ZigType *attrs_type;17727 ZigType *attrs_type;
...@@ -17061,7 +17731,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty...@@ -17061,7 +17731,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
17061 size_enum_index = 2;17731 size_enum_index = 2;
17062 } else if (ptr_type_entry->id == ZigTypeIdPointer) {17732 } else if (ptr_type_entry->id == ZigTypeIdPointer) {
17063 attrs_type = ptr_type_entry;17733 attrs_type = ptr_type_entry;
17064 size_enum_index = (ptr_type_entry->data.pointer.ptr_len == PtrLenSingle) ? 0 : 1;17734 size_enum_index = ptr_len_to_size_enum_index(ptr_type_entry->data.pointer.ptr_len);
17065 } else {17735 } else {
17066 zig_unreachable();17736 zig_unreachable();
17067 }17737 }
...@@ -17129,21 +17799,16 @@ static void make_enum_field_val(IrAnalyze *ira, ConstExprValue *enum_field_val,...@@ -17129,21 +17799,16 @@ static void make_enum_field_val(IrAnalyze *ira, ConstExprValue *enum_field_val,
17129 enum_field_val->data.x_struct.fields = inner_fields;17799 enum_field_val->data.x_struct.fields = inner_fields;
17130}17800}
1713117801
17132static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstExprValue **out) {17802static Error ir_make_type_info_value(IrAnalyze *ira, AstNode *source_node, ZigType *type_entry, ConstExprValue **out) {
17133 Error err;17803 Error err;
17134 assert(type_entry != nullptr);17804 assert(type_entry != nullptr);
17135 assert(!type_is_invalid(type_entry));17805 assert(!type_is_invalid(type_entry));
1713617806
17137 if ((err = ensure_complete_type(ira->codegen, type_entry)))17807 if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusSizeKnown)))
17138 return err;17808 return err;
1713917809
17140 if (type_entry == ira->codegen->builtin_types.entry_global_error_set) {
17141 zig_panic("TODO implement @typeInfo for global error set");
17142 }
17143
17144 ConstExprValue *result = nullptr;17810 ConstExprValue *result = nullptr;
17145 switch (type_entry->id)17811 switch (type_entry->id) {
17146 {
17147 case ZigTypeIdInvalid:17812 case ZigTypeIdInvalid:
17148 zig_unreachable();17813 zig_unreachable();
17149 case ZigTypeIdMetaType:17814 case ZigTypeIdMetaType:
...@@ -17238,6 +17903,27 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17238,6 +17903,27 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1723817903
17239 break;17904 break;
17240 }17905 }
17906 case ZigTypeIdVector: {
17907 result = create_const_vals(1);
17908 result->special = ConstValSpecialStatic;
17909 result->type = ir_type_info_get_type(ira, "Vector", nullptr);
17910
17911 ConstExprValue *fields = create_const_vals(2);
17912 result->data.x_struct.fields = fields;
17913
17914 // len: usize
17915 ensure_field_index(result->type, "len", 0);
17916 fields[0].special = ConstValSpecialStatic;
17917 fields[0].type = ira->codegen->builtin_types.entry_u32;
17918 bigint_init_unsigned(&fields[0].data.x_bigint, type_entry->data.vector.len);
17919 // child: type
17920 ensure_field_index(result->type, "child", 1);
17921 fields[1].special = ConstValSpecialStatic;
17922 fields[1].type = ira->codegen->builtin_types.entry_type;
17923 fields[1].data.x_type = type_entry->data.vector.elem_type;
17924
17925 break;
17926 }
17241 case ZigTypeIdOptional:17927 case ZigTypeIdOptional:
17242 {17928 {
17243 result = create_const_vals(1);17929 result = create_const_vals(1);
...@@ -17310,7 +17996,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17310,7 +17996,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17310 enum_field_array->special = ConstValSpecialStatic;17996 enum_field_array->special = ConstValSpecialStatic;
17311 enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count);17997 enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count);
17312 enum_field_array->data.x_array.special = ConstArraySpecialNone;17998 enum_field_array->data.x_array.special = ConstArraySpecialNone;
17313 enum_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
17314 enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count);17999 enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count);
1731518000
17316 init_const_slice(ira->codegen, &fields[2], enum_field_array, 0, enum_field_count, false);18001 init_const_slice(ira->codegen, &fields[2], enum_field_array, 0, enum_field_count, false);
...@@ -17320,9 +18005,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17320,9 +18005,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17320 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index];18005 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index];
17321 ConstExprValue *enum_field_val = &enum_field_array->data.x_array.data.s_none.elements[enum_field_index];18006 ConstExprValue *enum_field_val = &enum_field_array->data.x_array.data.s_none.elements[enum_field_index];
17322 make_enum_field_val(ira, enum_field_val, enum_field, type_info_enum_field_type);18007 make_enum_field_val(ira, enum_field_val, enum_field, type_info_enum_field_type);
17323 enum_field_val->data.x_struct.parent.id = ConstParentIdArray;18008 enum_field_val->parent.id = ConstParentIdArray;
17324 enum_field_val->data.x_struct.parent.data.p_array.array_val = enum_field_array;18009 enum_field_val->parent.data.p_array.array_val = enum_field_array;
17325 enum_field_val->data.x_struct.parent.data.p_array.elem_index = enum_field_index;18010 enum_field_val->parent.data.p_array.elem_index = enum_field_index;
17326 }18011 }
17327 // defs: []TypeInfo.Definition18012 // defs: []TypeInfo.Definition
17328 ensure_field_index(result->type, "defs", 3);18013 ensure_field_index(result->type, "defs", 3);
...@@ -17344,12 +18029,20 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17344,12 +18029,20 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17344 ensure_field_index(result->type, "errors", 0);18029 ensure_field_index(result->type, "errors", 0);
1734518030
17346 ZigType *type_info_error_type = ir_type_info_get_type(ira, "Error", nullptr);18031 ZigType *type_info_error_type = ir_type_info_get_type(ira, "Error", nullptr);
18032 if (!resolve_inferred_error_set(ira->codegen, type_entry, source_node)) {
18033 return ErrorSemanticAnalyzeFail;
18034 }
18035 if (type_is_global_error_set(type_entry)) {
18036 ir_add_error_node(ira, source_node,
18037 buf_sprintf("TODO: compiler bug: implement @typeInfo support for anyerror. https://github.com/ziglang/zig/issues/1936"));
18038 return ErrorSemanticAnalyzeFail;
18039 }
18040
17347 uint32_t error_count = type_entry->data.error_set.err_count;18041 uint32_t error_count = type_entry->data.error_set.err_count;
17348 ConstExprValue *error_array = create_const_vals(1);18042 ConstExprValue *error_array = create_const_vals(1);
17349 error_array->special = ConstValSpecialStatic;18043 error_array->special = ConstValSpecialStatic;
17350 error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count);18044 error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count);
17351 error_array->data.x_array.special = ConstArraySpecialNone;18045 error_array->data.x_array.special = ConstArraySpecialNone;
17352 error_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
17353 error_array->data.x_array.data.s_none.elements = create_const_vals(error_count);18046 error_array->data.x_array.data.s_none.elements = create_const_vals(error_count);
1735418047
17355 init_const_slice(ira->codegen, &fields[0], error_array, 0, error_count, false);18048 init_const_slice(ira->codegen, &fields[0], error_array, 0, error_count, false);
...@@ -17373,9 +18066,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17373,9 +18066,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17373 bigint_init_unsigned(&inner_fields[1].data.x_bigint, error->value);18066 bigint_init_unsigned(&inner_fields[1].data.x_bigint, error->value);
1737418067
17375 error_val->data.x_struct.fields = inner_fields;18068 error_val->data.x_struct.fields = inner_fields;
17376 error_val->data.x_struct.parent.id = ConstParentIdArray;18069 error_val->parent.id = ConstParentIdArray;
17377 error_val->data.x_struct.parent.data.p_array.array_val = error_array;18070 error_val->parent.data.p_array.array_val = error_array;
17378 error_val->data.x_struct.parent.data.p_array.elem_index = error_index;18071 error_val->parent.data.p_array.elem_index = error_index;
17379 }18072 }
1738018073
17381 break;18074 break;
...@@ -17444,7 +18137,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17444,7 +18137,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17444 union_field_array->special = ConstValSpecialStatic;18137 union_field_array->special = ConstValSpecialStatic;
17445 union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count);18138 union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count);
17446 union_field_array->data.x_array.special = ConstArraySpecialNone;18139 union_field_array->data.x_array.special = ConstArraySpecialNone;
17447 union_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
17448 union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count);18140 union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count);
1744918141
17450 init_const_slice(ira->codegen, &fields[2], union_field_array, 0, union_field_count, false);18142 init_const_slice(ira->codegen, &fields[2], union_field_array, 0, union_field_count, false);
...@@ -17477,9 +18169,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17477,9 +18169,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17477 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true);18169 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true);
1747818170
17479 union_field_val->data.x_struct.fields = inner_fields;18171 union_field_val->data.x_struct.fields = inner_fields;
17480 union_field_val->data.x_struct.parent.id = ConstParentIdArray;18172 union_field_val->parent.id = ConstParentIdArray;
17481 union_field_val->data.x_struct.parent.data.p_array.array_val = union_field_array;18173 union_field_val->parent.data.p_array.array_val = union_field_array;
17482 union_field_val->data.x_struct.parent.data.p_array.elem_index = union_field_index;18174 union_field_val->parent.data.p_array.elem_index = union_field_index;
17483 }18175 }
17484 // defs: []TypeInfo.Definition18176 // defs: []TypeInfo.Definition
17485 ensure_field_index(result->type, "defs", 3);18177 ensure_field_index(result->type, "defs", 3);
...@@ -17519,7 +18211,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17519,7 +18211,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17519 struct_field_array->special = ConstValSpecialStatic;18211 struct_field_array->special = ConstValSpecialStatic;
17520 struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count);18212 struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count);
17521 struct_field_array->data.x_array.special = ConstArraySpecialNone;18213 struct_field_array->data.x_array.special = ConstArraySpecialNone;
17522 struct_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
17523 struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count);18214 struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count);
1752418215
17525 init_const_slice(ira->codegen, &fields[1], struct_field_array, 0, struct_field_count, false);18216 init_const_slice(ira->codegen, &fields[1], struct_field_array, 0, struct_field_count, false);
...@@ -17553,9 +18244,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17553,9 +18244,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17553 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(struct_field->name), true);18244 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(struct_field->name), true);
1755418245
17555 struct_field_val->data.x_struct.fields = inner_fields;18246 struct_field_val->data.x_struct.fields = inner_fields;
17556 struct_field_val->data.x_struct.parent.id = ConstParentIdArray;18247 struct_field_val->parent.id = ConstParentIdArray;
17557 struct_field_val->data.x_struct.parent.data.p_array.array_val = struct_field_array;18248 struct_field_val->parent.data.p_array.array_val = struct_field_array;
17558 struct_field_val->data.x_struct.parent.data.p_array.elem_index = struct_field_index;18249 struct_field_val->parent.data.p_array.elem_index = struct_field_index;
17559 }18250 }
17560 // defs: []TypeInfo.Definition18251 // defs: []TypeInfo.Definition
17561 ensure_field_index(result->type, "defs", 2);18252 ensure_field_index(result->type, "defs", 2);
...@@ -17625,7 +18316,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17625,7 +18316,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17625 fn_arg_array->special = ConstValSpecialStatic;18316 fn_arg_array->special = ConstValSpecialStatic;
17626 fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count);18317 fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count);
17627 fn_arg_array->data.x_array.special = ConstArraySpecialNone;18318 fn_arg_array->data.x_array.special = ConstArraySpecialNone;
17628 fn_arg_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
17629 fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);18319 fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
1763018320
17631 init_const_slice(ira->codegen, &fields[5], fn_arg_array, 0, fn_arg_count, false);18321 init_const_slice(ira->codegen, &fields[5], fn_arg_array, 0, fn_arg_count, false);
...@@ -17662,9 +18352,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17662,9 +18352,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17662 }18352 }
1766318353
17664 fn_arg_val->data.x_struct.fields = inner_fields;18354 fn_arg_val->data.x_struct.fields = inner_fields;
17665 fn_arg_val->data.x_struct.parent.id = ConstParentIdArray;18355 fn_arg_val->parent.id = ConstParentIdArray;
17666 fn_arg_val->data.x_struct.parent.data.p_array.array_val = fn_arg_array;18356 fn_arg_val->parent.data.p_array.array_val = fn_arg_array;
17667 fn_arg_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index;18357 fn_arg_val->parent.data.p_array.elem_index = fn_arg_index;
17668 }18358 }
1766918359
17670 break;18360 break;
...@@ -17673,7 +18363,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17673,7 +18363,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17673 {18363 {
17674 ZigType *fn_type = type_entry->data.bound_fn.fn_type;18364 ZigType *fn_type = type_entry->data.bound_fn.fn_type;
17675 assert(fn_type->id == ZigTypeIdFn);18365 assert(fn_type->id == ZigTypeIdFn);
17676 if ((err = ir_make_type_info_value(ira, fn_type, &result)))18366 if ((err = ir_make_type_info_value(ira, source_node, fn_type, &result)))
17677 return err;18367 return err;
1767818368
17679 break;18369 break;
...@@ -17698,7 +18388,7 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira,...@@ -17698,7 +18388,7 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira,
17698 ZigType *result_type = ir_type_info_get_type(ira, nullptr, nullptr);18388 ZigType *result_type = ir_type_info_get_type(ira, nullptr, nullptr);
1769918389
17700 ConstExprValue *payload;18390 ConstExprValue *payload;
17701 if ((err = ir_make_type_info_value(ira, type_entry, &payload)))18391 if ((err = ir_make_type_info_value(ira, instruction->base.source_node, type_entry, &payload)))
17702 return ira->codegen->invalid_instruction;18392 return ira->codegen->invalid_instruction;
1770318393
17704 IrInstruction *result = ir_const(ira, &instruction->base, result_type);18394 IrInstruction *result = ir_const(ira, &instruction->base, result_type);
...@@ -17708,8 +18398,8 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira,...@@ -17708,8 +18398,8 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira,
1770818398
17709 if (payload != nullptr) {18399 if (payload != nullptr) {
17710 assert(payload->type->id == ZigTypeIdStruct);18400 assert(payload->type->id == ZigTypeIdStruct);
17711 payload->data.x_struct.parent.id = ConstParentIdUnion;18401 payload->parent.id = ConstParentIdUnion;
17712 payload->data.x_struct.parent.data.p_union.union_val = out_val;18402 payload->parent.data.p_union.union_val = out_val;
17713 }18403 }
1771418404
17715 return result;18405 return result;
...@@ -17735,12 +18425,6 @@ static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira,...@@ -17735,12 +18425,6 @@ static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira,
17735static IrInstruction *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira,18425static IrInstruction *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira,
17736 IrInstructionSetEvalBranchQuota *instruction)18426 IrInstructionSetEvalBranchQuota *instruction)
17737{18427{
17738 if (ira->new_irb.exec->parent_exec != nullptr && !ira->new_irb.exec->is_generic_instantiation) {
17739 ir_add_error(ira, &instruction->base,
17740 buf_sprintf("@setEvalBranchQuota must be called from the top of the comptime stack"));
17741 return ira->codegen->invalid_instruction;
17742 }
17743
17744 uint64_t new_quota;18428 uint64_t new_quota;
17745 if (!ir_resolve_usize(ira, instruction->new_quota->child, &new_quota))18429 if (!ir_resolve_usize(ira, instruction->new_quota->child, &new_quota))
17746 return ira->codegen->invalid_instruction;18430 return ira->codegen->invalid_instruction;
...@@ -17781,10 +18465,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct...@@ -17781,10 +18465,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
1778118465
17782 // Execute the C import block like an inline function18466 // Execute the C import block like an inline function
17783 ZigType *void_type = ira->codegen->builtin_types.entry_void;18467 ZigType *void_type = ira->codegen->builtin_types.entry_void;
17784 IrInstruction *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,18468 ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
17785 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,18469 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,
17786 &cimport_scope->buf, block_node, nullptr, nullptr);18470 &cimport_scope->buf, block_node, nullptr, nullptr, nullptr);
17787 if (type_is_invalid(cimport_result->value.type))18471 if (type_is_invalid(cimport_result->type))
17788 return ira->codegen->invalid_instruction;18472 return ira->codegen->invalid_instruction;
1778918473
17790 find_libc_include_path(ira->codegen);18474 find_libc_include_path(ira->codegen);
...@@ -17934,7 +18618,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru...@@ -17934,7 +18618,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru
17934 return result;18618 return result;
17935}18619}
1793618620
17937static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchg *instruction) {18621static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchgSrc *instruction) {
17938 ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child);18622 ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child);
17939 if (type_is_invalid(operand_type))18623 if (type_is_invalid(operand_type))
17940 return ira->codegen->invalid_instruction;18624 return ira->codegen->invalid_instruction;
...@@ -18006,9 +18690,9 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi...@@ -18006,9 +18690,9 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi
18006 zig_panic("TODO compile-time execution of cmpxchg");18690 zig_panic("TODO compile-time execution of cmpxchg");
18007 }18691 }
1800818692
18009 IrInstruction *result = ir_build_cmpxchg(&ira->new_irb, instruction->base.scope, instruction->base.source_node,18693 IrInstruction *result = ir_build_cmpxchg_gen(ira, &instruction->base,
18010 nullptr, casted_ptr, casted_cmp_value, casted_new_value, nullptr, nullptr, instruction->is_weak,18694 casted_ptr, casted_cmp_value, casted_new_value,
18011 operand_type, success_order, failure_order);18695 success_order, failure_order, instruction->is_weak);
18012 result->value.type = get_optional_type(ira->codegen, operand_type);18696 result->value.type = get_optional_type(ira->codegen, operand_type);
18013 ir_add_alloca(ira, result, result->value.type);18697 ir_add_alloca(ira, result, result->value.type);
18014 return result;18698 return result;
...@@ -18054,6 +18738,27 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct...@@ -18054,6 +18738,27 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct
18054 return ira->codegen->invalid_instruction;18738 return ira->codegen->invalid_instruction;
18055 }18739 }
1805618740
18741 if (dest_type->id == ZigTypeIdComptimeInt) {
18742 return ir_implicit_cast(ira, target, dest_type);
18743 }
18744
18745 if (instr_is_comptime(target)) {
18746 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
18747 if (val == nullptr)
18748 return ira->codegen->invalid_instruction;
18749
18750 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
18751 bigint_truncate(&result->value.data.x_bigint, &val->data.x_bigint,
18752 dest_type->data.integral.bit_count, dest_type->data.integral.is_signed);
18753 return result;
18754 }
18755
18756 if (src_type->data.integral.bit_count == 0 || dest_type->data.integral.bit_count == 0) {
18757 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
18758 bigint_init_unsigned(&result->value.data.x_bigint, 0);
18759 return result;
18760 }
18761
18057 if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) {18762 if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) {
18058 const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned";18763 const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned";
18059 ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name)));18764 ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name)));
...@@ -18064,13 +18769,6 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct...@@ -18064,13 +18769,6 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct
18064 return ira->codegen->invalid_instruction;18769 return ira->codegen->invalid_instruction;
18065 }18770 }
1806618771
18067 if (target->value.special == ConstValSpecialStatic) {
18068 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
18069 bigint_truncate(&result->value.data.x_bigint, &target->value.data.x_bigint,
18070 dest_type->data.integral.bit_count, dest_type->data.integral.is_signed);
18071 return result;
18072 }
18073
18074 IrInstruction *new_instruction = ir_build_truncate(&ira->new_irb, instruction->base.scope,18772 IrInstruction *new_instruction = ir_build_truncate(&ira->new_irb, instruction->base.scope,
18075 instruction->base.source_node, dest_type_value, target);18773 instruction->base.source_node, dest_type_value, target);
18076 new_instruction->value.type = dest_type;18774 new_instruction->value.type = dest_type;
...@@ -18174,18 +18872,6 @@ static IrInstruction *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInst...@@ -18174,18 +18872,6 @@ static IrInstruction *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInst
18174 return ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type);18872 return ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type);
18175}18873}
1817618874
18177static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
18178 Error err;
18179
18180 if (ty->id == ZigTypeIdPointer) {
18181 if ((err = type_resolve(ira->codegen, ty->data.pointer.child_type, ResolveStatusAlignmentKnown)))
18182 return err;
18183 }
18184
18185 *result_align = get_ptr_align(ira->codegen, ty);
18186 return ErrorNone;
18187}
18188
18189static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {18875static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {
18190 Error err;18876 Error err;
1819118877
...@@ -18304,6 +18990,20 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct...@@ -18304,6 +18990,20 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct
18304 return ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);18990 return ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);
18305}18991}
1830618992
18993static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
18994 Error err;
18995
18996 ZigType *ptr_type = get_src_ptr_type(ty);
18997 assert(ptr_type != nullptr);
18998 if (ptr_type->id == ZigTypeIdPointer) {
18999 if ((err = type_resolve(ira->codegen, ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
19000 return err;
19001 }
19002
19003 *result_align = get_ptr_align(ira->codegen, ty);
19004 return ErrorNone;
19005}
19006
18307static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) {19007static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) {
18308 ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);19008 ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
18309 if (type_is_invalid(dest_type))19009 if (type_is_invalid(dest_type))
...@@ -18410,6 +19110,27 @@ static IrInstruction *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstruct...@@ -18410,6 +19110,27 @@ static IrInstruction *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstruct
18410 return ir_const_type(ira, &instruction->base, get_int_type(ira->codegen, is_signed, (uint32_t)bit_count));19110 return ir_const_type(ira, &instruction->base, get_int_type(ira->codegen, is_signed, (uint32_t)bit_count));
18411}19111}
1841219112
19113static IrInstruction *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstructionVectorType *instruction) {
19114 uint64_t len;
19115 if (!ir_resolve_unsigned(ira, instruction->len->child, ira->codegen->builtin_types.entry_u32, &len))
19116 return ira->codegen->invalid_instruction;
19117
19118 ZigType *elem_type = ir_resolve_type(ira, instruction->elem_type->child);
19119 if (type_is_invalid(elem_type))
19120 return ira->codegen->invalid_instruction;
19121
19122 if (!is_valid_vector_elem_type(elem_type)) {
19123 ir_add_error(ira, instruction->elem_type,
19124 buf_sprintf("vector element type must be integer, float, or pointer; '%s' is invalid",
19125 buf_ptr(&elem_type->name)));
19126 return ira->codegen->invalid_instruction;
19127 }
19128
19129 ZigType *vector_type = get_vector_type(ira->codegen, len, elem_type);
19130
19131 return ir_const_type(ira, &instruction->base, vector_type);
19132}
19133
18413static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {19134static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {
18414 IrInstruction *value = instruction->value->child;19135 IrInstruction *value = instruction->value->child;
18415 if (type_is_invalid(value->value.type))19136 if (type_is_invalid(value->value.type))
...@@ -18508,10 +19229,18 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio...@@ -18508,10 +19229,18 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio
18508 }19229 }
18509 case ConstPtrSpecialBaseStruct:19230 case ConstPtrSpecialBaseStruct:
18510 zig_panic("TODO memset on const inner struct");19231 zig_panic("TODO memset on const inner struct");
19232 case ConstPtrSpecialBaseErrorUnionCode:
19233 zig_panic("TODO memset on const inner error union code");
19234 case ConstPtrSpecialBaseErrorUnionPayload:
19235 zig_panic("TODO memset on const inner error union payload");
19236 case ConstPtrSpecialBaseOptionalPayload:
19237 zig_panic("TODO memset on const inner optional payload");
18511 case ConstPtrSpecialHardCodedAddr:19238 case ConstPtrSpecialHardCodedAddr:
18512 zig_unreachable();19239 zig_unreachable();
18513 case ConstPtrSpecialFunction:19240 case ConstPtrSpecialFunction:
18514 zig_panic("TODO memset on ptr cast from function");19241 zig_panic("TODO memset on ptr cast from function");
19242 case ConstPtrSpecialNull:
19243 zig_panic("TODO memset on null ptr");
18515 }19244 }
1851619245
18517 size_t count = bigint_as_unsigned(&casted_count->value.data.x_bigint);19246 size_t count = bigint_as_unsigned(&casted_count->value.data.x_bigint);
...@@ -18623,10 +19352,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio...@@ -18623,10 +19352,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
18623 }19352 }
18624 case ConstPtrSpecialBaseStruct:19353 case ConstPtrSpecialBaseStruct:
18625 zig_panic("TODO memcpy on const inner struct");19354 zig_panic("TODO memcpy on const inner struct");
19355 case ConstPtrSpecialBaseErrorUnionCode:
19356 zig_panic("TODO memcpy on const inner error union code");
19357 case ConstPtrSpecialBaseErrorUnionPayload:
19358 zig_panic("TODO memcpy on const inner error union payload");
19359 case ConstPtrSpecialBaseOptionalPayload:
19360 zig_panic("TODO memcpy on const inner optional payload");
18626 case ConstPtrSpecialHardCodedAddr:19361 case ConstPtrSpecialHardCodedAddr:
18627 zig_unreachable();19362 zig_unreachable();
18628 case ConstPtrSpecialFunction:19363 case ConstPtrSpecialFunction:
18629 zig_panic("TODO memcpy on ptr cast from function");19364 zig_panic("TODO memcpy on ptr cast from function");
19365 case ConstPtrSpecialNull:
19366 zig_panic("TODO memcpy on null ptr");
18630 }19367 }
1863119368
18632 if (dest_start + count > dest_end) {19369 if (dest_start + count > dest_end) {
...@@ -18659,10 +19396,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio...@@ -18659,10 +19396,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
18659 }19396 }
18660 case ConstPtrSpecialBaseStruct:19397 case ConstPtrSpecialBaseStruct:
18661 zig_panic("TODO memcpy on const inner struct");19398 zig_panic("TODO memcpy on const inner struct");
19399 case ConstPtrSpecialBaseErrorUnionCode:
19400 zig_panic("TODO memcpy on const inner error union code");
19401 case ConstPtrSpecialBaseErrorUnionPayload:
19402 zig_panic("TODO memcpy on const inner error union payload");
19403 case ConstPtrSpecialBaseOptionalPayload:
19404 zig_panic("TODO memcpy on const inner optional payload");
18662 case ConstPtrSpecialHardCodedAddr:19405 case ConstPtrSpecialHardCodedAddr:
18663 zig_unreachable();19406 zig_unreachable();
18664 case ConstPtrSpecialFunction:19407 case ConstPtrSpecialFunction:
18665 zig_panic("TODO memcpy on ptr cast from function");19408 zig_panic("TODO memcpy on ptr cast from function");
19409 case ConstPtrSpecialNull:
19410 zig_panic("TODO memcpy on null ptr");
18666 }19411 }
1866719412
18668 if (src_start + count > src_end) {19413 if (src_start + count > src_end) {
...@@ -18690,9 +19435,9 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18690,9 +19435,9 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18690 if (type_is_invalid(ptr_ptr->value.type))19435 if (type_is_invalid(ptr_ptr->value.type))
18691 return ira->codegen->invalid_instruction;19436 return ira->codegen->invalid_instruction;
1869219437
18693 ZigType *ptr_type = ptr_ptr->value.type;19438 ZigType *ptr_ptr_type = ptr_ptr->value.type;
18694 assert(ptr_type->id == ZigTypeIdPointer);19439 assert(ptr_ptr_type->id == ZigTypeIdPointer);
18695 ZigType *array_type = ptr_type->data.pointer.child_type;19440 ZigType *array_type = ptr_ptr_type->data.pointer.child_type;
1869619441
18697 IrInstruction *start = instruction->start->child;19442 IrInstruction *start = instruction->start->child;
18698 if (type_is_invalid(start->value.type))19443 if (type_is_invalid(start->value.type))
...@@ -18721,10 +19466,10 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18721,10 +19466,10 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18721 bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic &&19466 bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic &&
18722 ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst;19467 ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst;
18723 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type,19468 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type,
18724 ptr_type->data.pointer.is_const || is_comptime_const,19469 ptr_ptr_type->data.pointer.is_const || is_comptime_const,
18725 ptr_type->data.pointer.is_volatile,19470 ptr_ptr_type->data.pointer.is_volatile,
18726 PtrLenUnknown,19471 PtrLenUnknown,
18727 ptr_type->data.pointer.explicit_alignment, 0, 0);19472 ptr_ptr_type->data.pointer.explicit_alignment, 0, 0);
18728 return_type = get_slice_type(ira->codegen, slice_ptr_type);19473 return_type = get_slice_type(ira->codegen, slice_ptr_type);
18729 } else if (array_type->id == ZigTypeIdPointer) {19474 } else if (array_type->id == ZigTypeIdPointer) {
18730 if (array_type->data.pointer.ptr_len == PtrLenSingle) {19475 if (array_type->data.pointer.ptr_len == PtrLenSingle) {
...@@ -18771,18 +19516,18 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18771,18 +19516,18 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18771 if (array_type->id == ZigTypeIdPointer) {19516 if (array_type->id == ZigTypeIdPointer) {
18772 ZigType *child_array_type = array_type->data.pointer.child_type;19517 ZigType *child_array_type = array_type->data.pointer.child_type;
18773 assert(child_array_type->id == ZigTypeIdArray);19518 assert(child_array_type->id == ZigTypeIdArray);
18774 parent_ptr = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node);19519 parent_ptr = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node);
18775 if (parent_ptr == nullptr)19520 if (parent_ptr == nullptr)
18776 return ira->codegen->invalid_instruction;19521 return ira->codegen->invalid_instruction;
1877719522
18778 array_val = ir_const_ptr_pointee(ira, parent_ptr, instruction->base.source_node);19523 array_val = const_ptr_pointee(ira, ira->codegen, parent_ptr, instruction->base.source_node);
18779 if (array_val == nullptr)19524 if (array_val == nullptr)
18780 return ira->codegen->invalid_instruction;19525 return ira->codegen->invalid_instruction;
1878119526
18782 rel_end = child_array_type->data.array.len;19527 rel_end = child_array_type->data.array.len;
18783 abs_offset = 0;19528 abs_offset = 0;
18784 } else {19529 } else {
18785 array_val = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node);19530 array_val = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node);
18786 if (array_val == nullptr)19531 if (array_val == nullptr)
18787 return ira->codegen->invalid_instruction;19532 return ira->codegen->invalid_instruction;
18788 rel_end = array_type->data.array.len;19533 rel_end = array_type->data.array.len;
...@@ -18791,7 +19536,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18791,7 +19536,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18791 }19536 }
18792 } else if (array_type->id == ZigTypeIdPointer) {19537 } else if (array_type->id == ZigTypeIdPointer) {
18793 assert(array_type->data.pointer.ptr_len == PtrLenUnknown);19538 assert(array_type->data.pointer.ptr_len == PtrLenUnknown);
18794 parent_ptr = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node);19539 parent_ptr = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node);
18795 if (parent_ptr == nullptr)19540 if (parent_ptr == nullptr)
18796 return ira->codegen->invalid_instruction;19541 return ira->codegen->invalid_instruction;
1879719542
...@@ -18822,6 +19567,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18822,6 +19567,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18822 break;19567 break;
18823 case ConstPtrSpecialBaseStruct:19568 case ConstPtrSpecialBaseStruct:
18824 zig_panic("TODO slice const inner struct");19569 zig_panic("TODO slice const inner struct");
19570 case ConstPtrSpecialBaseErrorUnionCode:
19571 zig_panic("TODO slice const inner error union code");
19572 case ConstPtrSpecialBaseErrorUnionPayload:
19573 zig_panic("TODO slice const inner error union payload");
19574 case ConstPtrSpecialBaseOptionalPayload:
19575 zig_panic("TODO slice const inner optional payload");
18825 case ConstPtrSpecialHardCodedAddr:19576 case ConstPtrSpecialHardCodedAddr:
18826 array_val = nullptr;19577 array_val = nullptr;
18827 abs_offset = 0;19578 abs_offset = 0;
...@@ -18829,9 +19580,11 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18829,9 +19580,11 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18829 break;19580 break;
18830 case ConstPtrSpecialFunction:19581 case ConstPtrSpecialFunction:
18831 zig_panic("TODO slice of ptr cast from function");19582 zig_panic("TODO slice of ptr cast from function");
19583 case ConstPtrSpecialNull:
19584 zig_panic("TODO slice of null ptr");
18832 }19585 }
18833 } else if (is_slice(array_type)) {19586 } else if (is_slice(array_type)) {
18834 ConstExprValue *slice_ptr = ir_const_ptr_pointee(ira, &ptr_ptr->value, instruction->base.source_node);19587 ConstExprValue *slice_ptr = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node);
18835 if (slice_ptr == nullptr)19588 if (slice_ptr == nullptr)
18836 return ira->codegen->invalid_instruction;19589 return ira->codegen->invalid_instruction;
1883719590
...@@ -18859,6 +19612,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18859,6 +19612,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18859 break;19612 break;
18860 case ConstPtrSpecialBaseStruct:19613 case ConstPtrSpecialBaseStruct:
18861 zig_panic("TODO slice const inner struct");19614 zig_panic("TODO slice const inner struct");
19615 case ConstPtrSpecialBaseErrorUnionCode:
19616 zig_panic("TODO slice const inner error union code");
19617 case ConstPtrSpecialBaseErrorUnionPayload:
19618 zig_panic("TODO slice const inner error union payload");
19619 case ConstPtrSpecialBaseOptionalPayload:
19620 zig_panic("TODO slice const inner optional payload");
18862 case ConstPtrSpecialHardCodedAddr:19621 case ConstPtrSpecialHardCodedAddr:
18863 array_val = nullptr;19622 array_val = nullptr;
18864 abs_offset = 0;19623 abs_offset = 0;
...@@ -18866,6 +19625,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18866,6 +19625,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18866 break;19625 break;
18867 case ConstPtrSpecialFunction:19626 case ConstPtrSpecialFunction:
18868 zig_panic("TODO slice of slice cast from function");19627 zig_panic("TODO slice of slice cast from function");
19628 case ConstPtrSpecialNull:
19629 zig_panic("TODO slice of null");
18869 }19630 }
18870 } else {19631 } else {
18871 zig_unreachable();19632 zig_unreachable();
...@@ -18931,6 +19692,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18931,6 +19692,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18931 zig_unreachable();19692 zig_unreachable();
18932 case ConstPtrSpecialBaseStruct:19693 case ConstPtrSpecialBaseStruct:
18933 zig_panic("TODO");19694 zig_panic("TODO");
19695 case ConstPtrSpecialBaseErrorUnionCode:
19696 zig_panic("TODO");
19697 case ConstPtrSpecialBaseErrorUnionPayload:
19698 zig_panic("TODO");
19699 case ConstPtrSpecialBaseOptionalPayload:
19700 zig_panic("TODO");
18934 case ConstPtrSpecialHardCodedAddr:19701 case ConstPtrSpecialHardCodedAddr:
18935 init_const_ptr_hard_coded_addr(ira->codegen, ptr_val,19702 init_const_ptr_hard_coded_addr(ira->codegen, ptr_val,
18936 parent_ptr->type->data.pointer.child_type,19703 parent_ptr->type->data.pointer.child_type,
...@@ -18939,6 +19706,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18939,6 +19706,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18939 break;19706 break;
18940 case ConstPtrSpecialFunction:19707 case ConstPtrSpecialFunction:
18941 zig_panic("TODO");19708 zig_panic("TODO");
19709 case ConstPtrSpecialNull:
19710 zig_panic("TODO");
18942 }19711 }
1894319712
18944 ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index];19713 ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index];
...@@ -19165,6 +19934,7 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct...@@ -19165,6 +19934,7 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct
19165 case ZigTypeIdEnum:19934 case ZigTypeIdEnum:
19166 case ZigTypeIdUnion:19935 case ZigTypeIdUnion:
19167 case ZigTypeIdFn:19936 case ZigTypeIdFn:
19937 case ZigTypeIdVector:
19168 {19938 {
19169 uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry);19939 uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry);
19170 return ir_const_unsigned(ira, &instruction->base, align_in_bytes);19940 return ir_const_unsigned(ira, &instruction->base, align_in_bytes);
...@@ -19240,7 +20010,7 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr...@@ -19240,7 +20010,7 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr
19240 {20010 {
19241 BigInt *op1_bigint = &casted_op1->value.data.x_bigint;20011 BigInt *op1_bigint = &casted_op1->value.data.x_bigint;
19242 BigInt *op2_bigint = &casted_op2->value.data.x_bigint;20012 BigInt *op2_bigint = &casted_op2->value.data.x_bigint;
19243 ConstExprValue *pointee_val = ir_const_ptr_pointee(ira, &casted_result_ptr->value, casted_result_ptr->source_node);20013 ConstExprValue *pointee_val = const_ptr_pointee(ira, ira->codegen, &casted_result_ptr->value, casted_result_ptr->source_node);
19244 if (pointee_val == nullptr)20014 if (pointee_val == nullptr)
19245 return ira->codegen->invalid_instruction;20015 return ira->codegen->invalid_instruction;
19246 BigInt *dest_bigint = &pointee_val->data.x_bigint;20016 BigInt *dest_bigint = &pointee_val->data.x_bigint;
...@@ -19294,7 +20064,8 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct...@@ -19294,7 +20064,8 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
19294 return ira->codegen->invalid_instruction;20064 return ira->codegen->invalid_instruction;
1929520065
19296 if (err_union_val->special != ConstValSpecialRuntime) {20066 if (err_union_val->special != ConstValSpecialRuntime) {
19297 return ir_const_bool(ira, &instruction->base, (err_union_val->data.x_err_union.err != nullptr));20067 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
20068 return ir_const_bool(ira, &instruction->base, (err != nullptr));
19298 }20069 }
19299 }20070 }
1930020071
...@@ -19320,48 +20091,47 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct...@@ -19320,48 +20091,47 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
19320 }20091 }
19321}20092}
1932220093
19323static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,20094static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrInstructionUnwrapErrCode *instruction) {
19324 IrInstructionUnwrapErrCode *instruction)20095 IrInstruction *base_ptr = instruction->err_union->child;
19325{20096 if (type_is_invalid(base_ptr->value.type))
19326 IrInstruction *value = instruction->value->child;
19327 if (type_is_invalid(value->value.type))
19328 return ira->codegen->invalid_instruction;20097 return ira->codegen->invalid_instruction;
19329 ZigType *ptr_type = value->value.type;20098 ZigType *ptr_type = base_ptr->value.type;
1933020099
19331 // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.20100 // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
19332 assert(ptr_type->id == ZigTypeIdPointer);20101 assert(ptr_type->id == ZigTypeIdPointer);
1933320102
19334 ZigType *type_entry = ptr_type->data.pointer.child_type;20103 ZigType *type_entry = ptr_type->data.pointer.child_type;
19335 if (type_is_invalid(type_entry)) {20104 if (type_is_invalid(type_entry))
19336 return ira->codegen->invalid_instruction;20105 return ira->codegen->invalid_instruction;
19337 } else if (type_entry->id == ZigTypeIdErrorUnion) {
19338 if (instr_is_comptime(value)) {
19339 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
19340 if (!ptr_val)
19341 return ira->codegen->invalid_instruction;
19342 ConstExprValue *err_union_val = ir_const_ptr_pointee(ira, ptr_val, instruction->base.source_node);
19343 if (err_union_val == nullptr)
19344 return ira->codegen->invalid_instruction;
19345 if (err_union_val->special != ConstValSpecialRuntime) {
19346 ErrorTableEntry *err = err_union_val->data.x_err_union.err;
19347 assert(err);
1934820106
19349 IrInstruction *result = ir_const(ira, &instruction->base,20107 if (type_entry->id != ZigTypeIdErrorUnion) {
19350 type_entry->data.error_union.err_set_type);20108 ir_add_error(ira, base_ptr,
19351 result->value.data.x_err_set = err;
19352 return result;
19353 }
19354 }
19355
19356 IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb,
19357 instruction->base.scope, instruction->base.source_node, value);
19358 result->value.type = type_entry->data.error_union.err_set_type;
19359 return result;
19360 } else {
19361 ir_add_error(ira, value,
19362 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));20109 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
19363 return ira->codegen->invalid_instruction;20110 return ira->codegen->invalid_instruction;
19364 }20111 }
20112
20113 if (instr_is_comptime(base_ptr)) {
20114 ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
20115 if (!ptr_val)
20116 return ira->codegen->invalid_instruction;
20117 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
20118 if (err_union_val == nullptr)
20119 return ira->codegen->invalid_instruction;
20120 if (err_union_val->special != ConstValSpecialRuntime) {
20121 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
20122 assert(err);
20123
20124 IrInstruction *result = ir_const(ira, &instruction->base,
20125 type_entry->data.error_union.err_set_type);
20126 result->value.data.x_err_set = err;
20127 return result;
20128 }
20129 }
20130
20131 IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb,
20132 instruction->base.scope, instruction->base.source_node, base_ptr);
20133 result->value.type = type_entry->data.error_union.err_set_type;
20134 return result;
19365}20135}
1936620136
19367static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,20137static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
...@@ -19377,48 +20147,48 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,...@@ -19377,48 +20147,48 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
19377 assert(ptr_type->id == ZigTypeIdPointer);20147 assert(ptr_type->id == ZigTypeIdPointer);
1937820148
19379 ZigType *type_entry = ptr_type->data.pointer.child_type;20149 ZigType *type_entry = ptr_type->data.pointer.child_type;
19380 if (type_is_invalid(type_entry)) {20150 if (type_is_invalid(type_entry))
19381 return ira->codegen->invalid_instruction;20151 return ira->codegen->invalid_instruction;
19382 } else if (type_entry->id == ZigTypeIdErrorUnion) {
19383 ZigType *payload_type = type_entry->data.error_union.payload_type;
19384 if (type_is_invalid(payload_type)) {
19385 return ira->codegen->invalid_instruction;
19386 }
19387 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
19388 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
19389 PtrLenSingle, 0, 0, 0);
19390 if (instr_is_comptime(value)) {
19391 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
19392 if (!ptr_val)
19393 return ira->codegen->invalid_instruction;
19394 ConstExprValue *err_union_val = ir_const_ptr_pointee(ira, ptr_val, instruction->base.source_node);
19395 if (err_union_val == nullptr)
19396 return ira->codegen->invalid_instruction;
19397 if (err_union_val->special != ConstValSpecialRuntime) {
19398 ErrorTableEntry *err = err_union_val->data.x_err_union.err;
19399 if (err != nullptr) {
19400 ir_add_error(ira, &instruction->base,
19401 buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name)));
19402 return ira->codegen->invalid_instruction;
19403 }
1940420152
19405 IrInstruction *result = ir_const(ira, &instruction->base, result_type);20153 if (type_entry->id != ZigTypeIdErrorUnion) {
19406 result->value.data.x_ptr.special = ConstPtrSpecialRef;
19407 result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;
19408 return result;
19409 }
19410 }
19411
19412 IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb,
19413 instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on);
19414 result->value.type = result_type;
19415 return result;
19416 } else {
19417 ir_add_error(ira, value,20154 ir_add_error(ira, value,
19418 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));20155 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
19419 return ira->codegen->invalid_instruction;20156 return ira->codegen->invalid_instruction;
19420 }20157 }
1942120158
20159 ZigType *payload_type = type_entry->data.error_union.payload_type;
20160 if (type_is_invalid(payload_type))
20161 return ira->codegen->invalid_instruction;
20162
20163 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
20164 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
20165 PtrLenSingle, 0, 0, 0);
20166 if (instr_is_comptime(value)) {
20167 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
20168 if (!ptr_val)
20169 return ira->codegen->invalid_instruction;
20170 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
20171 if (err_union_val == nullptr)
20172 return ira->codegen->invalid_instruction;
20173 if (err_union_val->special != ConstValSpecialRuntime) {
20174 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
20175 if (err != nullptr) {
20176 ir_add_error(ira, &instruction->base,
20177 buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name)));
20178 return ira->codegen->invalid_instruction;
20179 }
20180
20181 IrInstruction *result = ir_const(ira, &instruction->base, result_type);
20182 result->value.data.x_ptr.special = ConstPtrSpecialRef;
20183 result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;
20184 return result;
20185 }
20186 }
20187
20188 IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb,
20189 instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on);
20190 result->value.type = result_type;
20191 return result;
19422}20192}
1942320193
19424static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {20194static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {
...@@ -19696,6 +20466,39 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,...@@ -19696,6 +20466,39 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
19696 return ira->codegen->invalid_instruction;20466 return ira->codegen->invalid_instruction;
19697 }20467 }
19698 }20468 }
20469 } else if (switch_type->id == ZigTypeIdBool) {
20470 int seenTrue = 0;
20471 int seenFalse = 0;
20472 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
20473 IrInstructionCheckSwitchProngsRange *range = &instruction->ranges[range_i];
20474
20475 IrInstruction *value = range->start->child;
20476
20477 IrInstruction *casted_value = ir_implicit_cast(ira, value, switch_type);
20478 if (type_is_invalid(casted_value->value.type))
20479 return ira->codegen->invalid_instruction;
20480
20481 ConstExprValue *const_expr_val = ir_resolve_const(ira, casted_value, UndefBad);
20482 if (!const_expr_val)
20483 return ira->codegen->invalid_instruction;
20484
20485 assert(const_expr_val->type->id == ZigTypeIdBool);
20486
20487 if (const_expr_val->data.x_bool == true) {
20488 seenTrue += 1;
20489 } else {
20490 seenFalse += 1;
20491 }
20492
20493 if ((seenTrue > 1) || (seenFalse > 1)) {
20494 ir_add_error(ira, value, buf_sprintf("duplicate switch value"));
20495 return ira->codegen->invalid_instruction;
20496 }
20497 }
20498 if (((seenTrue < 1) || (seenFalse < 1)) && !instruction->have_else_prong) {
20499 ir_add_error(ira, &instruction->base, buf_sprintf("switch must handle all possibilities"));
20500 return ira->codegen->invalid_instruction;
20501 }
19699 } else if (!instruction->have_else_prong) {20502 } else if (!instruction->have_else_prong) {
19700 ir_add_error(ira, &instruction->base,20503 ir_add_error(ira, &instruction->base,
19701 buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name)));20504 buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name)));
...@@ -19802,7 +20605,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3...@@ -19802,7 +20605,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
19802 return ira->codegen->invalid_instruction;20605 return ira->codegen->invalid_instruction;
19803 }20606 }
1980420607
19805 IrInstruction *result = ir_create_const(&ira->new_irb, target->scope, target->source_node, result_type);20608 IrInstruction *result = ir_const(ira, target, result_type);
19806 copy_const_val(&result->value, val, false);20609 copy_const_val(&result->value, val, false);
19807 result->value.type = result_type;20610 result->value.type = result_type;
19808 return result;20611 return result;
...@@ -19819,7 +20622,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3...@@ -19819,7 +20622,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
19819}20622}
1982020623
19821static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,20624static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,
19822 ZigType *dest_type, IrInstruction *dest_type_src)20625 ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on)
19823{20626{
19824 Error err;20627 Error err;
1982520628
...@@ -19829,12 +20632,14 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -19829,12 +20632,14 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
19829 // We have a check for zero bits later so we use get_src_ptr_type to20632 // We have a check for zero bits later so we use get_src_ptr_type to
19830 // validate src_type and dest_type.20633 // validate src_type and dest_type.
1983120634
19832 if (get_src_ptr_type(src_type) == nullptr) {20635 ZigType *src_ptr_type = get_src_ptr_type(src_type);
20636 if (src_ptr_type == nullptr) {
19833 ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));20637 ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));
19834 return ira->codegen->invalid_instruction;20638 return ira->codegen->invalid_instruction;
19835 }20639 }
1983620640
19837 if (get_src_ptr_type(dest_type) == nullptr) {20641 ZigType *dest_ptr_type = get_src_ptr_type(dest_type);
20642 if (dest_ptr_type == nullptr) {
19838 ir_add_error(ira, dest_type_src,20643 ir_add_error(ira, dest_type_src,
19839 buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));20644 buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
19840 return ira->codegen->invalid_instruction;20645 return ira->codegen->invalid_instruction;
...@@ -19846,12 +20651,24 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -19846,12 +20651,24 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
19846 }20651 }
1984720652
19848 if (instr_is_comptime(ptr)) {20653 if (instr_is_comptime(ptr)) {
19849 ConstExprValue *val = ir_resolve_const(ira, ptr, UndefOk);20654 bool dest_allows_addr_zero = ptr_allows_addr_zero(dest_type);
20655 UndefAllowed is_undef_allowed = dest_allows_addr_zero ? UndefOk : UndefBad;
20656 ConstExprValue *val = ir_resolve_const(ira, ptr, is_undef_allowed);
19850 if (!val)20657 if (!val)
19851 return ira->codegen->invalid_instruction;20658 return ira->codegen->invalid_instruction;
1985220659
19853 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, source_instr->source_node,20660 if (val->special == ConstValSpecialStatic) {
19854 dest_type);20661 bool is_addr_zero = val->data.x_ptr.special == ConstPtrSpecialNull ||
20662 (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
20663 val->data.x_ptr.data.hard_coded_addr.addr == 0);
20664 if (is_addr_zero && !dest_allows_addr_zero) {
20665 ir_add_error(ira, source_instr,
20666 buf_sprintf("null pointer casted to type '%s'", buf_ptr(&dest_type->name)));
20667 return ira->codegen->invalid_instruction;
20668 }
20669 }
20670
20671 IrInstruction *result = ir_const(ira, source_instr, dest_type);
19855 copy_const_val(&result->value, val, false);20672 copy_const_val(&result->value, val, false);
19856 result->value.type = dest_type;20673 result->value.type = dest_type;
19857 return result;20674 return result;
...@@ -19874,9 +20691,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -19874,9 +20691,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
19874 return ira->codegen->invalid_instruction;20691 return ira->codegen->invalid_instruction;
19875 }20692 }
1987620693
19877 IrInstruction *casted_ptr = ir_build_ptr_cast(&ira->new_irb, source_instr->scope,20694 IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on);
19878 source_instr->source_node, nullptr, ptr);
19879 casted_ptr->value.type = dest_type;
1988020695
19881 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {20696 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
19882 ErrorMsg *msg = ir_add_error(ira, source_instr,20697 ErrorMsg *msg = ir_add_error(ira, source_instr,
...@@ -19902,7 +20717,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -19902,7 +20717,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
19902 return result;20717 return result;
19903}20718}
1990420719
19905static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCast *instruction) {20720static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCastSrc *instruction) {
19906 IrInstruction *dest_type_value = instruction->dest_type->child;20721 IrInstruction *dest_type_value = instruction->dest_type->child;
19907 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);20722 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
19908 if (type_is_invalid(dest_type))20723 if (type_is_invalid(dest_type))
...@@ -19913,10 +20728,24 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct...@@ -19913,10 +20728,24 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct
19913 if (type_is_invalid(src_type))20728 if (type_is_invalid(src_type))
19914 return ira->codegen->invalid_instruction;20729 return ira->codegen->invalid_instruction;
1991520730
19916 return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value);20731 return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value,
20732 instruction->safety_check_on);
20733}
20734
20735static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ConstExprValue *val, size_t len) {
20736 size_t buf_i = 0;
20737 // TODO optimize the buf case
20738 expand_undef_array(codegen, val);
20739 for (size_t elem_i = 0; elem_i < val->type->data.array.len; elem_i += 1) {
20740 ConstExprValue *elem = &val->data.x_array.data.s_none.elements[elem_i];
20741 buf_write_value_bytes(codegen, &buf[buf_i], elem);
20742 buf_i += type_size(codegen, elem->type);
20743 }
19917}20744}
1991820745
19919static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {20746static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {
20747 if (val->special == ConstValSpecialUndef)
20748 val->special = ConstValSpecialStatic;
19920 assert(val->special == ConstValSpecialStatic);20749 assert(val->special == ConstValSpecialStatic);
19921 switch (val->type->id) {20750 switch (val->type->id) {
19922 case ZigTypeIdInvalid:20751 case ZigTypeIdInvalid:
...@@ -19959,17 +20788,9 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -19959,17 +20788,9 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
19959 zig_unreachable();20788 zig_unreachable();
19960 }20789 }
19961 case ZigTypeIdArray:20790 case ZigTypeIdArray:
19962 {20791 return buf_write_value_bytes_array(codegen, buf, val, val->type->data.array.len);
19963 size_t buf_i = 0;20792 case ZigTypeIdVector:
19964 // TODO optimize the buf case20793 return buf_write_value_bytes_array(codegen, buf, val, val->type->data.vector.len);
19965 expand_undef_array(codegen, val);
19966 for (size_t elem_i = 0; elem_i < val->type->data.array.len; elem_i += 1) {
19967 ConstExprValue *elem = &val->data.x_array.data.s_none.elements[elem_i];
19968 buf_write_value_bytes(codegen, &buf[buf_i], elem);
19969 buf_i += type_size(codegen, elem->type);
19970 }
19971 }
19972 return;
19973 case ZigTypeIdStruct:20794 case ZigTypeIdStruct:
19974 zig_panic("TODO buf_write_value_bytes struct type");20795 zig_panic("TODO buf_write_value_bytes struct type");
19975 case ZigTypeIdOptional:20796 case ZigTypeIdOptional:
...@@ -19986,7 +20807,33 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -19986,7 +20807,33 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
19986 zig_unreachable();20807 zig_unreachable();
19987}20808}
1998820809
19989static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {20810static Error buf_read_value_bytes_array(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf,
20811 ConstExprValue *val, ZigType *elem_type, size_t len)
20812{
20813 Error err;
20814 uint64_t elem_size = type_size(codegen, elem_type);
20815
20816 switch (val->data.x_array.special) {
20817 case ConstArraySpecialNone:
20818 val->data.x_array.data.s_none.elements = create_const_vals(len);
20819 for (size_t i = 0; i < len; i++) {
20820 ConstExprValue *elem = &val->data.x_array.data.s_none.elements[i];
20821 elem->special = ConstValSpecialStatic;
20822 elem->type = elem_type;
20823 if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem)))
20824 return err;
20825 }
20826 return ErrorNone;
20827 case ConstArraySpecialUndef:
20828 zig_panic("TODO buf_read_value_bytes ConstArraySpecialUndef array type");
20829 case ConstArraySpecialBuf:
20830 zig_panic("TODO buf_read_value_bytes ConstArraySpecialBuf array type");
20831 }
20832 zig_unreachable();
20833}
20834
20835static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val) {
20836 Error err;
19990 assert(val->special == ConstValSpecialStatic);20837 assert(val->special == ConstValSpecialStatic);
19991 switch (val->type->id) {20838 switch (val->type->id) {
19992 case ZigTypeIdInvalid:20839 case ZigTypeIdInvalid:
...@@ -20003,17 +20850,17 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -20003,17 +20850,17 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
20003 case ZigTypeIdPromise:20850 case ZigTypeIdPromise:
20004 zig_unreachable();20851 zig_unreachable();
20005 case ZigTypeIdVoid:20852 case ZigTypeIdVoid:
20006 return;20853 return ErrorNone;
20007 case ZigTypeIdBool:20854 case ZigTypeIdBool:
20008 val->data.x_bool = (buf[0] != 0);20855 val->data.x_bool = (buf[0] != 0);
20009 return;20856 return ErrorNone;
20010 case ZigTypeIdInt:20857 case ZigTypeIdInt:
20011 bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,20858 bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,
20012 codegen->is_big_endian, val->type->data.integral.is_signed);20859 codegen->is_big_endian, val->type->data.integral.is_signed);
20013 return;20860 return ErrorNone;
20014 case ZigTypeIdFloat:20861 case ZigTypeIdFloat:
20015 float_read_ieee597(val, buf, codegen->is_big_endian);20862 float_read_ieee597(val, buf, codegen->is_big_endian);
20016 return;20863 return ErrorNone;
20017 case ZigTypeIdPointer:20864 case ZigTypeIdPointer:
20018 {20865 {
20019 val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;20866 val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
...@@ -20021,20 +20868,67 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -20021,20 +20868,67 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
20021 bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count,20868 bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count,
20022 codegen->is_big_endian, false);20869 codegen->is_big_endian, false);
20023 val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);20870 val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);
20024 return;20871 return ErrorNone;
20025 }20872 }
20026 case ZigTypeIdArray:20873 case ZigTypeIdArray:
20027 zig_panic("TODO buf_read_value_bytes array type");20874 return buf_read_value_bytes_array(ira, codegen, source_node, buf, val, val->type->data.array.child_type,
20875 val->type->data.array.len);
20876 case ZigTypeIdVector:
20877 return buf_read_value_bytes_array(ira, codegen, source_node, buf, val, val->type->data.vector.elem_type,
20878 val->type->data.vector.len);
20879 case ZigTypeIdEnum:
20880 switch (val->type->data.enumeration.layout) {
20881 case ContainerLayoutAuto:
20882 zig_panic("TODO buf_read_value_bytes enum auto");
20883 case ContainerLayoutPacked:
20884 zig_panic("TODO buf_read_value_bytes enum packed");
20885 case ContainerLayoutExtern: {
20886 ZigType *tag_int_type = val->type->data.enumeration.tag_int_type;
20887 assert(tag_int_type->id == ZigTypeIdInt);
20888 bigint_read_twos_complement(&val->data.x_enum_tag, buf, tag_int_type->data.integral.bit_count,
20889 codegen->is_big_endian, tag_int_type->data.integral.is_signed);
20890 return ErrorNone;
20891 }
20892 }
20893 zig_unreachable();
20028 case ZigTypeIdStruct:20894 case ZigTypeIdStruct:
20029 zig_panic("TODO buf_read_value_bytes struct type");20895 switch (val->type->data.structure.layout) {
20896 case ContainerLayoutAuto: {
20897 ErrorMsg *msg = opt_ir_add_error_node(ira, codegen, source_node,
20898 buf_sprintf("non-extern, non-packed struct '%s' cannot have its bytes reinterpreted",
20899 buf_ptr(&val->type->name)));
20900 add_error_note(codegen, msg, val->type->data.structure.decl_node,
20901 buf_sprintf("declared here"));
20902 return ErrorSemanticAnalyzeFail;
20903 }
20904 case ContainerLayoutExtern: {
20905 size_t src_field_count = val->type->data.structure.src_field_count;
20906 val->data.x_struct.fields = create_const_vals(src_field_count);
20907 for (size_t field_i = 0; field_i < src_field_count; field_i += 1) {
20908 ConstExprValue *field_val = &val->data.x_struct.fields[field_i];
20909 field_val->special = ConstValSpecialStatic;
20910 TypeStructField *type_field = &val->type->data.structure.fields[field_i];
20911 field_val->type = type_field->type_entry;
20912 if (type_field->gen_index == SIZE_MAX)
20913 continue;
20914 size_t offset = LLVMOffsetOfElement(codegen->target_data_ref, val->type->type_ref,
20915 type_field->gen_index);
20916 uint8_t *new_buf = buf + offset;
20917 if ((err = buf_read_value_bytes(ira, codegen, source_node, new_buf, field_val)))
20918 return err;
20919 }
20920 return ErrorNone;
20921 }
20922 case ContainerLayoutPacked:
20923 zig_panic("TODO buf_read_value_bytes packed struct");
20924 }
20925 zig_unreachable();
20030 case ZigTypeIdOptional:20926 case ZigTypeIdOptional:
20031 zig_panic("TODO buf_read_value_bytes maybe type");20927 zig_panic("TODO buf_read_value_bytes maybe type");
20032 case ZigTypeIdErrorUnion:20928 case ZigTypeIdErrorUnion:
20033 zig_panic("TODO buf_read_value_bytes error union");20929 zig_panic("TODO buf_read_value_bytes error union");
20034 case ZigTypeIdErrorSet:20930 case ZigTypeIdErrorSet:
20035 zig_panic("TODO buf_read_value_bytes pure error type");20931 zig_panic("TODO buf_read_value_bytes pure error type");
20036 case ZigTypeIdEnum:
20037 zig_panic("TODO buf_read_value_bytes enum type");
20038 case ZigTypeIdFn:20932 case ZigTypeIdFn:
20039 zig_panic("TODO buf_read_value_bytes fn type");20933 zig_panic("TODO buf_read_value_bytes fn type");
20040 case ZigTypeIdUnion:20934 case ZigTypeIdUnion:
...@@ -20043,32 +20937,10 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -20043,32 +20937,10 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
20043 zig_unreachable();20937 zig_unreachable();
20044}20938}
2004520939
20046static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {20940static bool type_can_bit_cast(ZigType *t) {
20047 Error err;20941 switch (t->id) {
20048 IrInstruction *dest_type_value = instruction->dest_type->child;
20049 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
20050 if (type_is_invalid(dest_type))
20051 return ira->codegen->invalid_instruction;
20052
20053 IrInstruction *value = instruction->value->child;
20054 ZigType *src_type = value->value.type;
20055 if (type_is_invalid(src_type))
20056 return ira->codegen->invalid_instruction;
20057
20058 if ((err = ensure_complete_type(ira->codegen, dest_type)))
20059 return ira->codegen->invalid_instruction;
20060
20061 if ((err = ensure_complete_type(ira->codegen, src_type)))
20062 return ira->codegen->invalid_instruction;
20063
20064 if (get_codegen_ptr_type(src_type) != nullptr) {
20065 ir_add_error(ira, value,
20066 buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name)));
20067 return ira->codegen->invalid_instruction;
20068 }
20069
20070 switch (src_type->id) {
20071 case ZigTypeIdInvalid:20942 case ZigTypeIdInvalid:
20943 zig_unreachable();
20072 case ZigTypeIdMetaType:20944 case ZigTypeIdMetaType:
20073 case ZigTypeIdOpaque:20945 case ZigTypeIdOpaque:
20074 case ZigTypeIdBoundFn:20946 case ZigTypeIdBoundFn:
...@@ -20079,90 +20951,114 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct...@@ -20079,90 +20951,114 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
20079 case ZigTypeIdComptimeInt:20951 case ZigTypeIdComptimeInt:
20080 case ZigTypeIdUndefined:20952 case ZigTypeIdUndefined:
20081 case ZigTypeIdNull:20953 case ZigTypeIdNull:
20082 ir_add_error(ira, dest_type_value,20954 case ZigTypeIdPointer:
20083 buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));20955 return false;
20084 return ira->codegen->invalid_instruction;
20085 default:20956 default:
20086 break;20957 // TODO list these types out explicitly, there are probably some other invalid ones here
20958 return true;
20087 }20959 }
20960}
2008820961
20089 if (get_codegen_ptr_type(dest_type) != nullptr) {20962static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
20090 ir_add_error(ira, dest_type_value,20963 ZigType *dest_type)
20091 buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));20964{
20965 Error err;
20966
20967 ZigType *src_type = value->value.type;
20968 assert(get_codegen_ptr_type(src_type) == nullptr);
20969 assert(type_can_bit_cast(src_type));
20970 assert(get_codegen_ptr_type(dest_type) == nullptr);
20971 assert(type_can_bit_cast(dest_type));
20972
20973 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown)))
20974 return ira->codegen->invalid_instruction;
20975
20976 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown)))
20092 return ira->codegen->invalid_instruction;20977 return ira->codegen->invalid_instruction;
20093 }
2009420978
20095 switch (dest_type->id) {
20096 case ZigTypeIdInvalid:
20097 case ZigTypeIdMetaType:
20098 case ZigTypeIdOpaque:
20099 case ZigTypeIdBoundFn:
20100 case ZigTypeIdArgTuple:
20101 case ZigTypeIdNamespace:
20102 case ZigTypeIdUnreachable:
20103 case ZigTypeIdComptimeFloat:
20104 case ZigTypeIdComptimeInt:
20105 case ZigTypeIdUndefined:
20106 case ZigTypeIdNull:
20107 ir_add_error(ira, dest_type_value,
20108 buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
20109 return ira->codegen->invalid_instruction;
20110 default:
20111 break;
20112 }
2011320979
20114 uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);20980 uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);
20115 uint64_t src_size_bytes = type_size(ira->codegen, src_type);20981 uint64_t src_size_bytes = type_size(ira->codegen, src_type);
20116 if (dest_size_bytes != src_size_bytes) {20982 if (dest_size_bytes != src_size_bytes) {
20117 ir_add_error(ira, &instruction->base,20983 ir_add_error(ira, source_instr,
20118 buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,20984 buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,
20119 buf_ptr(&dest_type->name), dest_size_bytes,20985 buf_ptr(&dest_type->name), dest_size_bytes,
20120 buf_ptr(&src_type->name), src_size_bytes));20986 buf_ptr(&src_type->name), src_size_bytes));
20121 return ira->codegen->invalid_instruction;20987 return ira->codegen->invalid_instruction;
20122 }20988 }
2012320989
20990 uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);
20991 uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);
20992 if (dest_size_bits != src_size_bits) {
20993 ir_add_error(ira, source_instr,
20994 buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits",
20995 buf_ptr(&dest_type->name), dest_size_bits,
20996 buf_ptr(&src_type->name), src_size_bits));
20997 return ira->codegen->invalid_instruction;
20998 }
20999
20124 if (instr_is_comptime(value)) {21000 if (instr_is_comptime(value)) {
20125 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);21001 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
20126 if (!val)21002 if (!val)
20127 return ira->codegen->invalid_instruction;21003 return ira->codegen->invalid_instruction;
2012821004
20129 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);21005 IrInstruction *result = ir_const(ira, source_instr, dest_type);
20130 uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);21006 uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);
20131 buf_write_value_bytes(ira->codegen, buf, val);21007 buf_write_value_bytes(ira->codegen, buf, val);
20132 buf_read_value_bytes(ira->codegen, buf, &result->value);21008 if ((err = buf_read_value_bytes(ira, ira->codegen, source_instr->source_node, buf, &result->value)))
21009 return ira->codegen->invalid_instruction;
20133 return result;21010 return result;
20134 }21011 }
2013521012
20136 IrInstruction *result = ir_build_bit_cast(&ira->new_irb, instruction->base.scope,21013 IrInstruction *result = ir_build_bit_cast(&ira->new_irb, source_instr->scope,
20137 instruction->base.source_node, nullptr, value);21014 source_instr->source_node, nullptr, value);
20138 result->value.type = dest_type;21015 result->value.type = dest_type;
20139 return result;21016 return result;
20140}21017}
2014121018
20142static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) {21019static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
20143 Error err;
20144 IrInstruction *dest_type_value = instruction->dest_type->child;21020 IrInstruction *dest_type_value = instruction->dest_type->child;
20145 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);21021 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
20146 if (type_is_invalid(dest_type))21022 if (type_is_invalid(dest_type))
20147 return ira->codegen->invalid_instruction;21023 return ira->codegen->invalid_instruction;
2014821024
20149 // We explicitly check for the size, so we can use get_src_ptr_type21025 IrInstruction *value = instruction->value->child;
20150 if (get_src_ptr_type(dest_type) == nullptr) {21026 ZigType *src_type = value->value.type;
20151 ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));21027 if (type_is_invalid(src_type))
21028 return ira->codegen->invalid_instruction;
21029
21030 if (get_codegen_ptr_type(src_type) != nullptr) {
21031 ir_add_error(ira, value,
21032 buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name)));
20152 return ira->codegen->invalid_instruction;21033 return ira->codegen->invalid_instruction;
20153 }21034 }
2015421035
20155 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))21036 if (!type_can_bit_cast(src_type)) {
21037 ir_add_error(ira, dest_type_value,
21038 buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
20156 return ira->codegen->invalid_instruction;21039 return ira->codegen->invalid_instruction;
20157 if (!type_has_bits(dest_type)) {21040 }
21041
21042 if (get_codegen_ptr_type(dest_type) != nullptr) {
20158 ir_add_error(ira, dest_type_value,21043 ir_add_error(ira, dest_type_value,
20159 buf_sprintf("type '%s' has 0 bits and cannot store information", buf_ptr(&dest_type->name)));21044 buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
20160 return ira->codegen->invalid_instruction;21045 return ira->codegen->invalid_instruction;
20161 }21046 }
2016221047
20163 IrInstruction *target = instruction->target->child;21048 if (!type_can_bit_cast(dest_type)) {
20164 if (type_is_invalid(target->value.type))21049 ir_add_error(ira, dest_type_value,
21050 buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
20165 return ira->codegen->invalid_instruction;21051 return ira->codegen->invalid_instruction;
21052 }
21053
21054 return ir_analyze_bit_cast(ira, &instruction->base, value, dest_type);
21055}
21056
21057static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
21058 ZigType *ptr_type)
21059{
21060 assert(get_src_ptr_type(ptr_type) != nullptr);
21061 assert(type_has_bits(ptr_type));
2016621062
20167 IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);21063 IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);
20168 if (type_is_invalid(casted_int->value.type))21064 if (type_is_invalid(casted_int->value.type))
...@@ -20173,18 +21069,48 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru...@@ -20173,18 +21069,48 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru
20173 if (!val)21069 if (!val)
20174 return ira->codegen->invalid_instruction;21070 return ira->codegen->invalid_instruction;
2017521071
20176 IrInstruction *result = ir_const(ira, &instruction->base, dest_type);21072 IrInstruction *result = ir_const(ira, source_instr, ptr_type);
20177 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;21073 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
21074 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
20178 result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);21075 result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);
20179 return result;21076 return result;
20180 }21077 }
2018121078
20182 IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, instruction->base.scope,21079 IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, source_instr->scope,
20183 instruction->base.source_node, nullptr, casted_int);21080 source_instr->source_node, nullptr, casted_int);
20184 result->value.type = dest_type;21081 result->value.type = ptr_type;
20185 return result;21082 return result;
20186}21083}
2018721084
21085static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) {
21086 Error err;
21087 IrInstruction *dest_type_value = instruction->dest_type->child;
21088 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
21089 if (type_is_invalid(dest_type))
21090 return ira->codegen->invalid_instruction;
21091
21092 // We explicitly check for the size, so we can use get_src_ptr_type
21093 if (get_src_ptr_type(dest_type) == nullptr) {
21094 ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
21095 return ira->codegen->invalid_instruction;
21096 }
21097
21098 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
21099 return ira->codegen->invalid_instruction;
21100 if (!type_has_bits(dest_type)) {
21101 ir_add_error(ira, dest_type_value,
21102 buf_sprintf("type '%s' has 0 bits and cannot store information", buf_ptr(&dest_type->name)));
21103 return ira->codegen->invalid_instruction;
21104 }
21105
21106
21107 IrInstruction *target = instruction->target->child;
21108 if (type_is_invalid(target->value.type))
21109 return ira->codegen->invalid_instruction;
21110
21111 return ir_analyze_int_to_ptr(ira, &instruction->base, target, dest_type);
21112}
21113
20188static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,21114static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
20189 IrInstructionDeclRef *instruction)21115 IrInstructionDeclRef *instruction)
20190{21116{
...@@ -20199,8 +21125,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,...@@ -20199,8 +21125,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
20199 case TldIdContainer:21125 case TldIdContainer:
20200 case TldIdCompTime:21126 case TldIdCompTime:
20201 zig_unreachable();21127 zig_unreachable();
20202 case TldIdVar:21128 case TldIdVar: {
20203 {
20204 TldVar *tld_var = (TldVar *)tld;21129 TldVar *tld_var = (TldVar *)tld;
20205 ZigVar *var = tld_var->var;21130 ZigVar *var = tld_var->var;
2020621131
...@@ -20218,8 +21143,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,...@@ -20218,8 +21143,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
20218 return ir_get_deref(ira, &instruction->base, var_ptr);21143 return ir_get_deref(ira, &instruction->base, var_ptr);
20219 }21144 }
20220 }21145 }
20221 case TldIdFn:21146 case TldIdFn: {
20222 {
20223 TldFn *tld_fn = (TldFn *)tld;21147 TldFn *tld_fn = (TldFn *)tld;
20224 ZigFn *fn_entry = tld_fn->fn_entry;21148 ZigFn *fn_entry = tld_fn->fn_entry;
20225 assert(fn_entry->type_entry);21149 assert(fn_entry->type_entry);
...@@ -20265,8 +21189,7 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru...@@ -20265,8 +21189,7 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru
20265 if (!val)21189 if (!val)
20266 return ira->codegen->invalid_instruction;21190 return ira->codegen->invalid_instruction;
20267 if (val->type->id == ZigTypeIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {21191 if (val->type->id == ZigTypeIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
20268 IrInstruction *result = ir_create_const(&ira->new_irb, instruction->base.scope,21192 IrInstruction *result = ir_const(ira, &instruction->base, usize);
20269 instruction->base.source_node, usize);
20270 bigint_init_unsigned(&result->value.data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr);21193 bigint_init_unsigned(&result->value.data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr);
20271 result->value.type = usize;21194 result->value.type = usize;
20272 return result;21195 return result;
...@@ -20291,6 +21214,15 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct...@@ -20291,6 +21214,15 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
20291 } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) {21214 } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) {
20292 ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque"));21215 ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque"));
20293 return ira->codegen->invalid_instruction;21216 return ira->codegen->invalid_instruction;
21217 } else if (instruction->ptr_len == PtrLenC) {
21218 if (!type_allowed_in_extern(ira->codegen, child_type)) {
21219 ir_add_error(ira, &instruction->base,
21220 buf_sprintf("C pointers cannot point to non-C-ABI-compatible type '%s'", buf_ptr(&child_type->name)));
21221 return ira->codegen->invalid_instruction;
21222 } else if (child_type->id == ZigTypeIdOpaque) {
21223 ir_add_error(ira, &instruction->base, buf_sprintf("C pointers cannot point opaque types"));
21224 return ira->codegen->invalid_instruction;
21225 }
20294 }21226 }
2029521227
20296 uint32_t align_bytes;21228 uint32_t align_bytes;
...@@ -20299,6 +21231,9 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct...@@ -20299,6 +21231,9 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
20299 return ira->codegen->invalid_instruction;21231 return ira->codegen->invalid_instruction;
20300 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown)))21232 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown)))
20301 return ira->codegen->invalid_instruction;21233 return ira->codegen->invalid_instruction;
21234 if (!type_has_bits(child_type)) {
21235 align_bytes = 0;
21236 }
20302 } else {21237 } else {
20303 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))21238 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
20304 return ira->codegen->invalid_instruction;21239 return ira->codegen->invalid_instruction;
...@@ -20898,6 +21833,126 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS...@@ -20898,6 +21833,126 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS
20898 return result;21833 return result;
20899}21834}
2090021835
21836static IrInstruction *ir_analyze_instruction_bswap(IrAnalyze *ira, IrInstructionBswap *instruction) {
21837 ZigType *int_type = ir_resolve_type(ira, instruction->type->child);
21838 if (type_is_invalid(int_type))
21839 return ira->codegen->invalid_instruction;
21840
21841 IrInstruction *op = instruction->op->child;
21842 if (type_is_invalid(op->value.type))
21843 return ira->codegen->invalid_instruction;
21844
21845 if (int_type->id != ZigTypeIdInt) {
21846 ir_add_error(ira, instruction->type,
21847 buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name)));
21848 return ira->codegen->invalid_instruction;
21849 }
21850
21851 if (int_type->data.integral.bit_count % 8 != 0) {
21852 ir_add_error(ira, instruction->type,
21853 buf_sprintf("@bswap integer type '%s' has %" PRIu32 " bits which is not evenly divisible by 8",
21854 buf_ptr(&int_type->name), int_type->data.integral.bit_count));
21855 return ira->codegen->invalid_instruction;
21856 }
21857
21858 IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type);
21859 if (type_is_invalid(casted_op->value.type))
21860 return ira->codegen->invalid_instruction;
21861
21862 if (int_type->data.integral.bit_count == 0) {
21863 IrInstruction *result = ir_const(ira, &instruction->base, int_type);
21864 bigint_init_unsigned(&result->value.data.x_bigint, 0);
21865 return result;
21866 }
21867
21868 if (int_type->data.integral.bit_count == 8) {
21869 return casted_op;
21870 }
21871
21872 if (instr_is_comptime(casted_op)) {
21873 ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad);
21874 if (!val)
21875 return ira->codegen->invalid_instruction;
21876
21877 IrInstruction *result = ir_const(ira, &instruction->base, int_type);
21878 size_t buf_size = int_type->data.integral.bit_count / 8;
21879 uint8_t *buf = allocate_nonzero<uint8_t>(buf_size);
21880 bigint_write_twos_complement(&val->data.x_bigint, buf, int_type->data.integral.bit_count, true);
21881 bigint_read_twos_complement(&result->value.data.x_bigint, buf, int_type->data.integral.bit_count, false,
21882 int_type->data.integral.is_signed);
21883 return result;
21884 }
21885
21886 IrInstruction *result = ir_build_bswap(&ira->new_irb, instruction->base.scope,
21887 instruction->base.source_node, nullptr, casted_op);
21888 result->value.type = int_type;
21889 return result;
21890}
21891
21892static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstructionBitReverse *instruction) {
21893 ZigType *int_type = ir_resolve_type(ira, instruction->type->child);
21894 if (type_is_invalid(int_type))
21895 return ira->codegen->invalid_instruction;
21896
21897 IrInstruction *op = instruction->op->child;
21898 if (type_is_invalid(op->value.type))
21899 return ira->codegen->invalid_instruction;
21900
21901 if (int_type->id != ZigTypeIdInt) {
21902 ir_add_error(ira, instruction->type,
21903 buf_sprintf("expected integer type, found '%s'", buf_ptr(&int_type->name)));
21904 return ira->codegen->invalid_instruction;
21905 }
21906
21907 IrInstruction *casted_op = ir_implicit_cast(ira, op, int_type);
21908 if (type_is_invalid(casted_op->value.type))
21909 return ira->codegen->invalid_instruction;
21910
21911 if (int_type->data.integral.bit_count == 0) {
21912 IrInstruction *result = ir_const(ira, &instruction->base, int_type);
21913 bigint_init_unsigned(&result->value.data.x_bigint, 0);
21914 return result;
21915 }
21916
21917 if (instr_is_comptime(casted_op)) {
21918 ConstExprValue *val = ir_resolve_const(ira, casted_op, UndefBad);
21919 if (!val)
21920 return ira->codegen->invalid_instruction;
21921
21922 IrInstruction *result = ir_const(ira, &instruction->base, int_type);
21923 size_t num_bits = int_type->data.integral.bit_count;
21924 size_t buf_size = (num_bits + 7) / 8;
21925 uint8_t *comptime_buf = allocate_nonzero<uint8_t>(buf_size);
21926 uint8_t *result_buf = allocate_nonzero<uint8_t>(buf_size);
21927 memset(comptime_buf,0,buf_size);
21928 memset(result_buf,0,buf_size);
21929
21930 bigint_write_twos_complement(&val->data.x_bigint,comptime_buf,num_bits,ira->codegen->is_big_endian);
21931
21932 size_t bit_i = 0;
21933 size_t bit_rev_i = num_bits - 1;
21934 for (; bit_i < num_bits; bit_i++, bit_rev_i--) {
21935 if (comptime_buf[bit_i / 8] & (1 << (bit_i % 8))) {
21936 result_buf[bit_rev_i / 8] |= (1 << (bit_rev_i % 8));
21937 }
21938 }
21939
21940 bigint_read_twos_complement(&result->value.data.x_bigint,
21941 result_buf,
21942 int_type->data.integral.bit_count,
21943 ira->codegen->is_big_endian,
21944 int_type->data.integral.is_signed);
21945
21946 return result;
21947 }
21948
21949 IrInstruction *result = ir_build_bit_reverse(&ira->new_irb, instruction->base.scope,
21950 instruction->base.source_node, nullptr, casted_op);
21951 result->value.type = int_type;
21952 return result;
21953}
21954
21955
20901static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {21956static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {
20902 Error err;21957 Error err;
20903 IrInstruction *target = instruction->target->child;21958 IrInstruction *target = instruction->target->child;
...@@ -20981,6 +22036,12 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -20981,6 +22036,12 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
20981 case IrInstructionIdErrWrapCode:22036 case IrInstructionIdErrWrapCode:
20982 case IrInstructionIdErrWrapPayload:22037 case IrInstructionIdErrWrapPayload:
20983 case IrInstructionIdCast:22038 case IrInstructionIdCast:
22039 case IrInstructionIdDeclVarGen:
22040 case IrInstructionIdPtrCastGen:
22041 case IrInstructionIdCmpxchgGen:
22042 case IrInstructionIdArrayToVector:
22043 case IrInstructionIdVectorToArray:
22044 case IrInstructionIdAssertZero:
20984 zig_unreachable();22045 zig_unreachable();
2098522046
20986 case IrInstructionIdReturn:22047 case IrInstructionIdReturn:
...@@ -20991,8 +22052,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -20991,8 +22052,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
20991 return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction);22052 return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction);
20992 case IrInstructionIdBinOp:22053 case IrInstructionIdBinOp:
20993 return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction);22054 return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction);
20994 case IrInstructionIdDeclVar:22055 case IrInstructionIdDeclVarSrc:
20995 return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVar *)instruction);22056 return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVarSrc *)instruction);
20996 case IrInstructionIdLoadPtr:22057 case IrInstructionIdLoadPtr:
20997 return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction);22058 return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction);
20998 case IrInstructionIdStorePtr:22059 case IrInstructionIdStorePtr:
...@@ -21037,8 +22098,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -21037,8 +22098,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21037 return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction);22098 return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction);
21038 case IrInstructionIdTestNonNull:22099 case IrInstructionIdTestNonNull:
21039 return ir_analyze_instruction_test_non_null(ira, (IrInstructionTestNonNull *)instruction);22100 return ir_analyze_instruction_test_non_null(ira, (IrInstructionTestNonNull *)instruction);
21040 case IrInstructionIdUnwrapOptional:22101 case IrInstructionIdOptionalUnwrapPtr:
21041 return ir_analyze_instruction_unwrap_maybe(ira, (IrInstructionUnwrapOptional *)instruction);22102 return ir_analyze_instruction_optional_unwrap_ptr(ira, (IrInstructionOptionalUnwrapPtr *)instruction);
21042 case IrInstructionIdClz:22103 case IrInstructionIdClz:
21043 return ir_analyze_instruction_clz(ira, (IrInstructionClz *)instruction);22104 return ir_analyze_instruction_clz(ira, (IrInstructionClz *)instruction);
21044 case IrInstructionIdCtz:22105 case IrInstructionIdCtz:
...@@ -21079,8 +22140,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -21079,8 +22140,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21079 return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction);22140 return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction);
21080 case IrInstructionIdEmbedFile:22141 case IrInstructionIdEmbedFile:
21081 return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction);22142 return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction);
21082 case IrInstructionIdCmpxchg:22143 case IrInstructionIdCmpxchgSrc:
21083 return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchg *)instruction);22144 return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchgSrc *)instruction);
21084 case IrInstructionIdFence:22145 case IrInstructionIdFence:
21085 return ir_analyze_instruction_fence(ira, (IrInstructionFence *)instruction);22146 return ir_analyze_instruction_fence(ira, (IrInstructionFence *)instruction);
21086 case IrInstructionIdTruncate:22147 case IrInstructionIdTruncate:
...@@ -21103,6 +22164,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -21103,6 +22164,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21103 return ir_analyze_instruction_bool_to_int(ira, (IrInstructionBoolToInt *)instruction);22164 return ir_analyze_instruction_bool_to_int(ira, (IrInstructionBoolToInt *)instruction);
21104 case IrInstructionIdIntType:22165 case IrInstructionIdIntType:
21105 return ir_analyze_instruction_int_type(ira, (IrInstructionIntType *)instruction);22166 return ir_analyze_instruction_int_type(ira, (IrInstructionIntType *)instruction);
22167 case IrInstructionIdVectorType:
22168 return ir_analyze_instruction_vector_type(ira, (IrInstructionVectorType *)instruction);
21106 case IrInstructionIdBoolNot:22169 case IrInstructionIdBoolNot:
21107 return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction);22170 return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction);
21108 case IrInstructionIdMemset:22171 case IrInstructionIdMemset:
...@@ -21147,8 +22210,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -21147,8 +22210,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21147 return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction);22210 return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction);
21148 case IrInstructionIdPanic:22211 case IrInstructionIdPanic:
21149 return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);22212 return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);
21150 case IrInstructionIdPtrCast:22213 case IrInstructionIdPtrCastSrc:
21151 return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCast *)instruction);22214 return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCastSrc *)instruction);
21152 case IrInstructionIdBitCast:22215 case IrInstructionIdBitCast:
21153 return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction);22216 return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction);
21154 case IrInstructionIdIntToPtr:22217 case IrInstructionIdIntToPtr:
...@@ -21233,6 +22296,10 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -21233,6 +22296,10 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21233 return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);22296 return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);
21234 case IrInstructionIdSqrt:22297 case IrInstructionIdSqrt:
21235 return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction);22298 return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction);
22299 case IrInstructionIdBswap:
22300 return ir_analyze_instruction_bswap(ira, (IrInstructionBswap *)instruction);
22301 case IrInstructionIdBitReverse:
22302 return ir_analyze_instruction_bit_reverse(ira, (IrInstructionBitReverse *)instruction);
21236 case IrInstructionIdIntToErr:22303 case IrInstructionIdIntToErr:
21237 return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);22304 return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);
21238 case IrInstructionIdErrToInt:22305 case IrInstructionIdErrToInt:
...@@ -21328,7 +22395,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21328,7 +22395,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21328 case IrInstructionIdBr:22395 case IrInstructionIdBr:
21329 case IrInstructionIdCondBr:22396 case IrInstructionIdCondBr:
21330 case IrInstructionIdSwitchBr:22397 case IrInstructionIdSwitchBr:
21331 case IrInstructionIdDeclVar:22398 case IrInstructionIdDeclVarSrc:
22399 case IrInstructionIdDeclVarGen:
21332 case IrInstructionIdStorePtr:22400 case IrInstructionIdStorePtr:
21333 case IrInstructionIdCall:22401 case IrInstructionIdCall:
21334 case IrInstructionIdReturn:22402 case IrInstructionIdReturn:
...@@ -21343,7 +22411,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21343,7 +22411,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21343 case IrInstructionIdCInclude:22411 case IrInstructionIdCInclude:
21344 case IrInstructionIdCDefine:22412 case IrInstructionIdCDefine:
21345 case IrInstructionIdCUndef:22413 case IrInstructionIdCUndef:
21346 case IrInstructionIdCmpxchg:
21347 case IrInstructionIdFence:22414 case IrInstructionIdFence:
21348 case IrInstructionIdMemset:22415 case IrInstructionIdMemset:
21349 case IrInstructionIdMemcpy:22416 case IrInstructionIdMemcpy:
...@@ -21371,6 +22438,9 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21371,6 +22438,9 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21371 case IrInstructionIdMergeErrRetTraces:22438 case IrInstructionIdMergeErrRetTraces:
21372 case IrInstructionIdMarkErrRetTracePtr:22439 case IrInstructionIdMarkErrRetTracePtr:
21373 case IrInstructionIdAtomicRmw:22440 case IrInstructionIdAtomicRmw:
22441 case IrInstructionIdCmpxchgGen:
22442 case IrInstructionIdCmpxchgSrc:
22443 case IrInstructionIdAssertZero:
21374 return true;22444 return true;
2137522445
21376 case IrInstructionIdPhi:22446 case IrInstructionIdPhi:
...@@ -21396,7 +22466,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21396,7 +22466,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21396 case IrInstructionIdSliceType:22466 case IrInstructionIdSliceType:
21397 case IrInstructionIdSizeOf:22467 case IrInstructionIdSizeOf:
21398 case IrInstructionIdTestNonNull:22468 case IrInstructionIdTestNonNull:
21399 case IrInstructionIdUnwrapOptional:22469 case IrInstructionIdOptionalUnwrapPtr:
21400 case IrInstructionIdClz:22470 case IrInstructionIdClz:
21401 case IrInstructionIdCtz:22471 case IrInstructionIdCtz:
21402 case IrInstructionIdPopCount:22472 case IrInstructionIdPopCount:
...@@ -21407,6 +22477,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21407,6 +22477,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21407 case IrInstructionIdEmbedFile:22477 case IrInstructionIdEmbedFile:
21408 case IrInstructionIdTruncate:22478 case IrInstructionIdTruncate:
21409 case IrInstructionIdIntType:22479 case IrInstructionIdIntType:
22480 case IrInstructionIdVectorType:
21410 case IrInstructionIdBoolNot:22481 case IrInstructionIdBoolNot:
21411 case IrInstructionIdSlice:22482 case IrInstructionIdSlice:
21412 case IrInstructionIdMemberCount:22483 case IrInstructionIdMemberCount:
...@@ -21423,7 +22494,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21423,7 +22494,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21423 case IrInstructionIdErrWrapPayload:22494 case IrInstructionIdErrWrapPayload:
21424 case IrInstructionIdFnProto:22495 case IrInstructionIdFnProto:
21425 case IrInstructionIdTestComptime:22496 case IrInstructionIdTestComptime:
21426 case IrInstructionIdPtrCast:22497 case IrInstructionIdPtrCastSrc:
22498 case IrInstructionIdPtrCastGen:
21427 case IrInstructionIdBitCast:22499 case IrInstructionIdBitCast:
21428 case IrInstructionIdWidenOrShorten:22500 case IrInstructionIdWidenOrShorten:
21429 case IrInstructionIdPtrToInt:22501 case IrInstructionIdPtrToInt:
...@@ -21454,6 +22526,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21454,6 +22526,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21454 case IrInstructionIdCoroPromise:22526 case IrInstructionIdCoroPromise:
21455 case IrInstructionIdPromiseResultType:22527 case IrInstructionIdPromiseResultType:
21456 case IrInstructionIdSqrt:22528 case IrInstructionIdSqrt:
22529 case IrInstructionIdBswap:
22530 case IrInstructionIdBitReverse:
21457 case IrInstructionIdAtomicLoad:22531 case IrInstructionIdAtomicLoad:
21458 case IrInstructionIdIntCast:22532 case IrInstructionIdIntCast:
21459 case IrInstructionIdFloatCast:22533 case IrInstructionIdFloatCast:
...@@ -21464,6 +22538,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21464,6 +22538,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21464 case IrInstructionIdFromBytes:22538 case IrInstructionIdFromBytes:
21465 case IrInstructionIdToBytes:22539 case IrInstructionIdToBytes:
21466 case IrInstructionIdEnumToInt:22540 case IrInstructionIdEnumToInt:
22541 case IrInstructionIdVectorToArray:
22542 case IrInstructionIdArrayToVector:
21467 return false;22543 return false;
2146822544
21469 case IrInstructionIdAsm:22545 case IrInstructionIdAsm:
src/ir.hpp+6-3
...@@ -13,15 +13,18 @@...@@ -13,15 +13,18 @@
13bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable);13bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable);
14bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);14bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
1515
16IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,16ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
17 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,17 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
18 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,18 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
19 IrExecutable *parent_exec);19 IrExecutable *parent_exec, AstNode *expected_type_source_node);
2020
21ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,21ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
22 ZigType *expected_type, AstNode *expected_type_source_node);22 ZigType *expected_type, AstNode *expected_type_source_node);
2323
24bool ir_has_side_effects(IrInstruction *instruction);24bool ir_has_side_effects(IrInstruction *instruction);
25ConstExprValue *const_ptr_pointee(CodeGen *codegen, ConstExprValue *const_val);25
26struct IrAnalyze;
27ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprValue *const_val,
28 AstNode *source_node);
2629
27#endif30#endif
src/ir_print.cpp+129-22
...@@ -172,7 +172,7 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction...@@ -172,7 +172,7 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction
172 }172 }
173}173}
174174
175static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instruction) {175static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_var_instruction) {
176 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";176 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
177 const char *name = buf_ptr(&decl_var_instruction->var->name);177 const char *name = buf_ptr(&decl_var_instruction->var->name);
178 if (decl_var_instruction->var_type) {178 if (decl_var_instruction->var_type) {
...@@ -332,8 +332,8 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {...@@ -332,8 +332,8 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {
332}332}
333333
334static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {334static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
335 fprintf(irp->f, "*");
336 ir_print_other_instruction(irp, instruction->ptr);335 ir_print_other_instruction(irp, instruction->ptr);
336 fprintf(irp->f, ".*");
337}337}
338338
339static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {339static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {
...@@ -479,15 +479,15 @@ static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) {...@@ -479,15 +479,15 @@ static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) {
479 fprintf(irp->f, ")");479 fprintf(irp->f, ")");
480}480}
481481
482static void ir_print_test_null(IrPrint *irp, IrInstructionTestNonNull *instruction) {482static void ir_print_test_non_null(IrPrint *irp, IrInstructionTestNonNull *instruction) {
483 fprintf(irp->f, "*");
484 ir_print_other_instruction(irp, instruction->value);483 ir_print_other_instruction(irp, instruction->value);
485 fprintf(irp->f, " != null");484 fprintf(irp->f, " != null");
486}485}
487486
488static void ir_print_unwrap_maybe(IrPrint *irp, IrInstructionUnwrapOptional *instruction) {487static void ir_print_optional_unwrap_ptr(IrPrint *irp, IrInstructionOptionalUnwrapPtr *instruction) {
489 fprintf(irp->f, "&??*");488 fprintf(irp->f, "&");
490 ir_print_other_instruction(irp, instruction->value);489 ir_print_other_instruction(irp, instruction->base_ptr);
490 fprintf(irp->f, ".*.?");
491 if (!instruction->safety_check_on) {491 if (!instruction->safety_check_on) {
492 fprintf(irp->f, " // no safety");492 fprintf(irp->f, " // no safety");
493 }493 }
...@@ -613,7 +613,7 @@ static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instructio...@@ -613,7 +613,7 @@ static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instructio
613 fprintf(irp->f, ")");613 fprintf(irp->f, ")");
614}614}
615615
616static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {616static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruction) {
617 fprintf(irp->f, "@cmpxchg(");617 fprintf(irp->f, "@cmpxchg(");
618 ir_print_other_instruction(irp, instruction->ptr);618 ir_print_other_instruction(irp, instruction->ptr);
619 fprintf(irp->f, ", ");619 fprintf(irp->f, ", ");
...@@ -627,6 +627,16 @@ static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {...@@ -627,6 +627,16 @@ static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {
627 fprintf(irp->f, ")");627 fprintf(irp->f, ")");
628}628}
629629
630static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruction) {
631 fprintf(irp->f, "@cmpxchg(");
632 ir_print_other_instruction(irp, instruction->ptr);
633 fprintf(irp->f, ", ");
634 ir_print_other_instruction(irp, instruction->cmp_value);
635 fprintf(irp->f, ", ");
636 ir_print_other_instruction(irp, instruction->new_value);
637 fprintf(irp->f, ", TODO print atomic orders)");
638}
639
630static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) {640static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) {
631 fprintf(irp->f, "@fence(");641 fprintf(irp->f, "@fence(");
632 ir_print_other_instruction(irp, instruction->order_value);642 ir_print_other_instruction(irp, instruction->order_value);
...@@ -709,6 +719,14 @@ static void ir_print_int_type(IrPrint *irp, IrInstructionIntType *instruction) {...@@ -709,6 +719,14 @@ static void ir_print_int_type(IrPrint *irp, IrInstructionIntType *instruction) {
709 fprintf(irp->f, ")");719 fprintf(irp->f, ")");
710}720}
711721
722static void ir_print_vector_type(IrPrint *irp, IrInstructionVectorType *instruction) {
723 fprintf(irp->f, "@Vector(");
724 ir_print_other_instruction(irp, instruction->len);
725 fprintf(irp->f, ", ");
726 ir_print_other_instruction(irp, instruction->elem_type);
727 fprintf(irp->f, ")");
728}
729
712static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) {730static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) {
713 fprintf(irp->f, "! ");731 fprintf(irp->f, "! ");
714 ir_print_other_instruction(irp, instruction->value);732 ir_print_other_instruction(irp, instruction->value);
...@@ -820,13 +838,13 @@ static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) {...@@ -820,13 +838,13 @@ static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) {
820}838}
821839
822static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) {840static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) {
823 fprintf(irp->f, "@unwrapErrorCode(");841 fprintf(irp->f, "UnwrapErrorCode(");
824 ir_print_other_instruction(irp, instruction->value);842 ir_print_other_instruction(irp, instruction->err_union);
825 fprintf(irp->f, ")");843 fprintf(irp->f, ")");
826}844}
827845
828static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) {846static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) {
829 fprintf(irp->f, "@unwrapErrorPayload(");847 fprintf(irp->f, "ErrorUnionFieldPayload(");
830 ir_print_other_instruction(irp, instruction->value);848 ir_print_other_instruction(irp, instruction->value);
831 fprintf(irp->f, ")");849 fprintf(irp->f, ")");
832 if (!instruction->safety_check_on) {850 if (!instruction->safety_check_on) {
...@@ -879,7 +897,7 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst...@@ -879,7 +897,7 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst
879 fprintf(irp->f, ")");897 fprintf(irp->f, ")");
880}898}
881899
882static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {900static void ir_print_ptr_cast_src(IrPrint *irp, IrInstructionPtrCastSrc *instruction) {
883 fprintf(irp->f, "@ptrCast(");901 fprintf(irp->f, "@ptrCast(");
884 if (instruction->dest_type) {902 if (instruction->dest_type) {
885 ir_print_other_instruction(irp, instruction->dest_type);903 ir_print_other_instruction(irp, instruction->dest_type);
...@@ -889,6 +907,12 @@ static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {...@@ -889,6 +907,12 @@ static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {
889 fprintf(irp->f, ")");907 fprintf(irp->f, ")");
890}908}
891909
910static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruction) {
911 fprintf(irp->f, "@ptrCast(");
912 ir_print_other_instruction(irp, instruction->ptr);
913 fprintf(irp->f, ")");
914}
915
892static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {916static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
893 fprintf(irp->f, "@bitCast(");917 fprintf(irp->f, "@bitCast(");
894 if (instruction->dest_type) {918 if (instruction->dest_type) {
...@@ -900,7 +924,7 @@ static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {...@@ -900,7 +924,7 @@ static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
900}924}
901925
902static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) {926static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) {
903 fprintf(irp->f, "@widenOrShorten(");927 fprintf(irp->f, "WidenOrShorten(");
904 ir_print_other_instruction(irp, instruction->target);928 ir_print_other_instruction(irp, instruction->target);
905 fprintf(irp->f, ")");929 fprintf(irp->f, ")");
906}930}
...@@ -948,6 +972,24 @@ static void ir_print_check_runtime_scope(IrPrint *irp, IrInstructionCheckRuntime...@@ -948,6 +972,24 @@ static void ir_print_check_runtime_scope(IrPrint *irp, IrInstructionCheckRuntime
948 fprintf(irp->f, ")");972 fprintf(irp->f, ")");
949}973}
950974
975static void ir_print_array_to_vector(IrPrint *irp, IrInstructionArrayToVector *instruction) {
976 fprintf(irp->f, "ArrayToVector(");
977 ir_print_other_instruction(irp, instruction->array);
978 fprintf(irp->f, ")");
979}
980
981static void ir_print_vector_to_array(IrPrint *irp, IrInstructionVectorToArray *instruction) {
982 fprintf(irp->f, "VectorToArray(");
983 ir_print_other_instruction(irp, instruction->vector);
984 fprintf(irp->f, ")");
985}
986
987static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruction) {
988 fprintf(irp->f, "AssertZero(");
989 ir_print_other_instruction(irp, instruction->target);
990 fprintf(irp->f, ")");
991}
992
951static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {993static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {
952 fprintf(irp->f, "inttoerr ");994 fprintf(irp->f, "inttoerr ");
953 ir_print_other_instruction(irp, instruction->target);995 ir_print_other_instruction(irp, instruction->target);
...@@ -1323,6 +1365,44 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) {...@@ -1323,6 +1365,44 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) {
1323 fprintf(irp->f, ")");1365 fprintf(irp->f, ")");
1324}1366}
13251367
1368static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_var_instruction) {
1369 ZigVar *var = decl_var_instruction->var;
1370 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
1371 const char *name = buf_ptr(&decl_var_instruction->var->name);
1372 fprintf(irp->f, "%s %s: %s align(%u) = ", var_or_const, name, buf_ptr(&var->var_type->name),
1373 var->align_bytes);
1374
1375 ir_print_other_instruction(irp, decl_var_instruction->init_value);
1376 if (decl_var_instruction->var->is_comptime != nullptr) {
1377 fprintf(irp->f, " // comptime = ");
1378 ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime);
1379 }
1380}
1381
1382static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) {
1383 fprintf(irp->f, "@bswap(");
1384 if (instruction->type != nullptr) {
1385 ir_print_other_instruction(irp, instruction->type);
1386 } else {
1387 fprintf(irp->f, "null");
1388 }
1389 fprintf(irp->f, ",");
1390 ir_print_other_instruction(irp, instruction->op);
1391 fprintf(irp->f, ")");
1392}
1393
1394static void ir_print_bit_reverse(IrPrint *irp, IrInstructionBitReverse *instruction) {
1395 fprintf(irp->f, "@bitreverse(");
1396 if (instruction->type != nullptr) {
1397 ir_print_other_instruction(irp, instruction->type);
1398 } else {
1399 fprintf(irp->f, "null");
1400 }
1401 fprintf(irp->f, ",");
1402 ir_print_other_instruction(irp, instruction->op);
1403 fprintf(irp->f, ")");
1404}
1405
1326static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {1406static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1327 ir_print_prefix(irp, instruction);1407 ir_print_prefix(irp, instruction);
1328 switch (instruction->id) {1408 switch (instruction->id) {
...@@ -1337,8 +1417,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1337,8 +1417,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1337 case IrInstructionIdBinOp:1417 case IrInstructionIdBinOp:
1338 ir_print_bin_op(irp, (IrInstructionBinOp *)instruction);1418 ir_print_bin_op(irp, (IrInstructionBinOp *)instruction);
1339 break;1419 break;
1340 case IrInstructionIdDeclVar:1420 case IrInstructionIdDeclVarSrc:
1341 ir_print_decl_var(irp, (IrInstructionDeclVar *)instruction);1421 ir_print_decl_var_src(irp, (IrInstructionDeclVarSrc *)instruction);
1342 break;1422 break;
1343 case IrInstructionIdCast:1423 case IrInstructionIdCast:
1344 ir_print_cast(irp, (IrInstructionCast *)instruction);1424 ir_print_cast(irp, (IrInstructionCast *)instruction);
...@@ -1428,10 +1508,10 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1428,10 +1508,10 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1428 ir_print_size_of(irp, (IrInstructionSizeOf *)instruction);1508 ir_print_size_of(irp, (IrInstructionSizeOf *)instruction);
1429 break;1509 break;
1430 case IrInstructionIdTestNonNull:1510 case IrInstructionIdTestNonNull:
1431 ir_print_test_null(irp, (IrInstructionTestNonNull *)instruction);1511 ir_print_test_non_null(irp, (IrInstructionTestNonNull *)instruction);
1432 break;1512 break;
1433 case IrInstructionIdUnwrapOptional:1513 case IrInstructionIdOptionalUnwrapPtr:
1434 ir_print_unwrap_maybe(irp, (IrInstructionUnwrapOptional *)instruction);1514 ir_print_optional_unwrap_ptr(irp, (IrInstructionOptionalUnwrapPtr *)instruction);
1435 break;1515 break;
1436 case IrInstructionIdCtz:1516 case IrInstructionIdCtz:
1437 ir_print_ctz(irp, (IrInstructionCtz *)instruction);1517 ir_print_ctz(irp, (IrInstructionCtz *)instruction);
...@@ -1484,8 +1564,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1484,8 +1564,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1484 case IrInstructionIdEmbedFile:1564 case IrInstructionIdEmbedFile:
1485 ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction);1565 ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction);
1486 break;1566 break;
1487 case IrInstructionIdCmpxchg:1567 case IrInstructionIdCmpxchgSrc:
1488 ir_print_cmpxchg(irp, (IrInstructionCmpxchg *)instruction);1568 ir_print_cmpxchg_src(irp, (IrInstructionCmpxchgSrc *)instruction);
1569 break;
1570 case IrInstructionIdCmpxchgGen:
1571 ir_print_cmpxchg_gen(irp, (IrInstructionCmpxchgGen *)instruction);
1489 break;1572 break;
1490 case IrInstructionIdFence:1573 case IrInstructionIdFence:
1491 ir_print_fence(irp, (IrInstructionFence *)instruction);1574 ir_print_fence(irp, (IrInstructionFence *)instruction);
...@@ -1520,6 +1603,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1520,6 +1603,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1520 case IrInstructionIdIntType:1603 case IrInstructionIdIntType:
1521 ir_print_int_type(irp, (IrInstructionIntType *)instruction);1604 ir_print_int_type(irp, (IrInstructionIntType *)instruction);
1522 break;1605 break;
1606 case IrInstructionIdVectorType:
1607 ir_print_vector_type(irp, (IrInstructionVectorType *)instruction);
1608 break;
1523 case IrInstructionIdBoolNot:1609 case IrInstructionIdBoolNot:
1524 ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction);1610 ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction);
1525 break;1611 break;
...@@ -1583,8 +1669,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1583,8 +1669,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1583 case IrInstructionIdTestComptime:1669 case IrInstructionIdTestComptime:
1584 ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction);1670 ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction);
1585 break;1671 break;
1586 case IrInstructionIdPtrCast:1672 case IrInstructionIdPtrCastSrc:
1587 ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction);1673 ir_print_ptr_cast_src(irp, (IrInstructionPtrCastSrc *)instruction);
1674 break;
1675 case IrInstructionIdPtrCastGen:
1676 ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction);
1588 break;1677 break;
1589 case IrInstructionIdBitCast:1678 case IrInstructionIdBitCast:
1590 ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);1679 ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);
...@@ -1736,6 +1825,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1736,6 +1825,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1736 case IrInstructionIdSqrt:1825 case IrInstructionIdSqrt:
1737 ir_print_sqrt(irp, (IrInstructionSqrt *)instruction);1826 ir_print_sqrt(irp, (IrInstructionSqrt *)instruction);
1738 break;1827 break;
1828 case IrInstructionIdBswap:
1829 ir_print_bswap(irp, (IrInstructionBswap *)instruction);
1830 break;
1831 case IrInstructionIdBitReverse:
1832 ir_print_bit_reverse(irp, (IrInstructionBitReverse *)instruction);
1833 break;
1739 case IrInstructionIdAtomicLoad:1834 case IrInstructionIdAtomicLoad:
1740 ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);1835 ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);
1741 break;1836 break;
...@@ -1745,6 +1840,18 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1745,6 +1840,18 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1745 case IrInstructionIdCheckRuntimeScope:1840 case IrInstructionIdCheckRuntimeScope:
1746 ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction);1841 ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction);
1747 break;1842 break;
1843 case IrInstructionIdDeclVarGen:
1844 ir_print_decl_var_gen(irp, (IrInstructionDeclVarGen *)instruction);
1845 break;
1846 case IrInstructionIdArrayToVector:
1847 ir_print_array_to_vector(irp, (IrInstructionArrayToVector *)instruction);
1848 break;
1849 case IrInstructionIdVectorToArray:
1850 ir_print_vector_to_array(irp, (IrInstructionVectorToArray *)instruction);
1851 break;
1852 case IrInstructionIdAssertZero:
1853 ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction);
1854 break;
1748 }1855 }
1749 fprintf(irp->f, "\n");1856 fprintf(irp->f, "\n");
1750}1857}
src/link.cpp+178-128
...@@ -42,7 +42,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path)...@@ -42,7 +42,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path)
42 }42 }
4343
44 CodeGen *child_gen = codegen_create(full_path, child_target, child_out_type,44 CodeGen *child_gen = codegen_create(full_path, child_target, child_out_type,
45 parent_gen->build_mode, parent_gen->zig_lib_dir);45 parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir);
4646
47 child_gen->out_h_path = nullptr;47 child_gen->out_h_path = nullptr;
48 child_gen->verbose_tokenize = parent_gen->verbose_tokenize;48 child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
...@@ -444,72 +444,19 @@ static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, si...@@ -444,72 +444,19 @@ static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, si
444 return ZigLLDLink(oformat, args, arg_count, link_diag_callback, diag);444 return ZigLLDLink(oformat, args, arg_count, link_diag_callback, diag);
445}445}
446446
447static void construct_linker_job_coff(LinkJob *lj) {447static void add_uefi_link_args(LinkJob *lj) {
448 CodeGen *g = lj->codegen;448 lj->args.append("/BASE:0");
449449 lj->args.append("/ENTRY:EfiMain");
450 lj->args.append("/ERRORLIMIT:0");450 lj->args.append("/OPT:REF");
451451 lj->args.append("/SAFESEH:NO");
452 if (g->libc_link_lib != nullptr) {452 lj->args.append("/MERGE:.rdata=.data");
453 find_libc_lib_path(g);453 lj->args.append("/ALIGN:32");
454 }454 lj->args.append("/NODEFAULTLIB");
455455 lj->args.append("/SECTION:.xdata,D");
456 lj->args.append("-NOLOGO");456}
457
458 if (!g->strip_debug_symbols) {
459 lj->args.append("-DEBUG");
460 }
461
462 if (g->out_type == OutTypeExe) {
463 // TODO compile time stack upper bound detection
464 lj->args.append("/STACK:16777216");
465 }
466
467 coff_append_machine_arg(g, &lj->args);
468
469 if (g->windows_subsystem_windows) {
470 lj->args.append("/SUBSYSTEM:windows");
471 } else if (g->windows_subsystem_console) {
472 lj->args.append("/SUBSYSTEM:console");
473 }
474 // The commented out stuff is from when we linked with MinGW
475 // Now that we're linking with LLD it remains to be determined
476 // how to handle --target-environ gnu
477 // These comments are a clue
478
479 bool is_library = g->out_type == OutTypeLib;
480 //bool dll = g->out_type == OutTypeLib;
481 //bool shared = !g->is_static && dll;
482 //if (g->is_static) {
483 // lj->args.append("-Bstatic");
484 //} else {
485 // if (dll) {
486 // lj->args.append("--dll");
487 // } else if (shared) {
488 // lj->args.append("--shared");
489 // }
490 // lj->args.append("-Bdynamic");
491 // if (dll || shared) {
492 // lj->args.append("-e");
493 // if (g->zig_target.arch.arch == ZigLLVM_x86) {
494 // lj->args.append("_DllMainCRTStartup@12");
495 // } else {
496 // lj->args.append("DllMainCRTStartup");
497 // }
498 // lj->args.append("--enable-auto-image-base");
499 // }
500 //}
501
502 lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
503
504 if (g->libc_link_lib != nullptr) {
505 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir))));
506 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->kernel32_lib_dir))));
507457
508 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir))));458static void add_nt_link_args(LinkJob *lj, bool is_library) {
509 if (g->libc_static_lib_dir != nullptr) {459 CodeGen *g = lj->codegen;
510 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_lib_dir))));
511 }
512 }
513460
514 if (lj->link_in_crt) {461 if (lj->link_in_crt) {
515 const char *lib_str = g->is_static ? "lib" : "";462 const char *lib_str = g->is_static ? "lib" : "";
...@@ -533,29 +480,180 @@ static void construct_linker_job_coff(LinkJob *lj) {...@@ -533,29 +480,180 @@ static void construct_linker_job_coff(LinkJob *lj) {
533 //https://msdn.microsoft.com/en-us/library/bb531344.aspx480 //https://msdn.microsoft.com/en-us/library/bb531344.aspx
534 lj->args.append("legacy_stdio_definitions.lib");481 lj->args.append("legacy_stdio_definitions.lib");
535482
536 //if (shared || dll) {
537 // lj->args.append(get_libc_file(g, "dllcrt2.o"));
538 //} else {
539 // if (g->windows_linker_unicode) {
540 // lj->args.append(get_libc_file(g, "crt2u.o"));
541 // } else {
542 // lj->args.append(get_libc_file(g, "crt2.o"));
543 // }
544 //}
545 //lj->args.append(get_libc_static_file(g, "crtbegin.o"));
546
547 // msvcrt depends on kernel32483 // msvcrt depends on kernel32
548 lj->args.append("kernel32.lib");484 lj->args.append("kernel32.lib");
549 } else {485 } else {
550 lj->args.append("-NODEFAULTLIB");486 lj->args.append("/NODEFAULTLIB");
551 if (!is_library) {487 if (!is_library) {
552 if (g->have_winmain) {488 if (g->have_winmain) {
553 lj->args.append("-ENTRY:WinMain");489 lj->args.append("/ENTRY:WinMain");
554 } else {490 } else {
555 lj->args.append("-ENTRY:WinMainCRTStartup");491 lj->args.append("/ENTRY:WinMainCRTStartup");
556 }492 }
557 }493 }
558 }494 }
495}
496
497// These are n actual command lines from LINK.EXE UEFI builds (app & driver) to be used as guidance cleaning
498// up a bit for building the COFF linker args:
499// /OUT:"J:\coding\nebulae\k\x64\Release\k.efi" /LTCG:incremental /Driver /PDB:"J:\coding\nebulae\k\x64\Release\k.pdb" "UefiApplicationEntryPoint.lib" "UefiRuntimeLib.lib" "UefiHiiLib.lib" "UefiHiiServicesLib.lib" "UefiSortLib.lib" "UefiShellLib.lib" "GlueLib.lib" "BaseLib.lib" "BaseDebugPrintErrorLevelLib.lib" "BasePrintLib.lib" "UefiLib.lib" "UefiBootServicesTableLib.lib" "UefiRuntimeServicesTableLib.lib" "UefiDevicePathLibDevicePathProtocol.lib" "UefiDebugLibConOut.lib" "UefiMemoryLib.lib" "UefiMemoryAllocationLib.lib" "BaseSynchronizationLib.lib" "UefiFileHandleLib.lib" /IMPLIB:"J:\coding\nebulae\k\x64\Release\k.lib" /DEBUG:FASTLINK /BASE:"0" /MACHINE:X64 /ENTRY:"EfiMain" /OPT:REF /SAFESEH:NO /SUBSYSTEM:EFI_APPLICATION /MERGE:".rdata=.data" /NOLOGO /ALIGN:32 /NODEFAULTLIB /SECTION:".xdata,D"
500// /OUT:"J:\coding\VisualUefi\samples\x64\Release\UefiDriver.efi" /LTCG:incremental /Driver /PDB:"J:\coding\VisualUefi\samples\x64\Release\UefiDriver.pdb" "UefiDriverEntryPoint.lib" "UefiHiiLib.lib" "UefiHiiServicesLib.lib" "UefiSortLib.lib" "UefiShellLib.lib" "GlueLib.lib" "BaseLib.lib" "BaseDebugPrintErrorLevelLib.lib" "BasePrintLib.lib" "UefiLib.lib" "UefiBootServicesTableLib.lib" "UefiRuntimeServicesTableLib.lib" "UefiDevicePathLibDevicePathProtocol.lib" "UefiDebugLibConOut.lib" "UefiMemoryLib.lib" "UefiMemoryAllocationLib.lib" "BaseSynchronizationLib.lib" "UefiFileHandleLib.lib" /IMPLIB:"J:\coding\VisualUefi\samples\x64\Release\UefiDriver.lib" /DEBUG:FASTLINK /BASE:"0" /MACHINE:X64 /ENTRY:"EfiMain" /OPT:REF /SAFESEH:NO /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MERGE:".rdata=.data" /NOLOGO /ALIGN:32 /NODEFAULTLIB /SECTION:".xdata,D"
501// This commented out stuff is from when we linked with MinGW
502// Now that we're linking with LLD it remains to be determined
503// how to handle --target-environ gnu
504// These comments are a clue
505//bool dll = g->out_type == OutTypeLib;
506//bool shared = !g->is_static && dll;
507//if (g->is_static) {
508// lj->args.append("-Bstatic");
509//} else {
510// if (dll) {
511// lj->args.append("--dll");
512// } else if (shared) {
513// lj->args.append("--shared");
514// }
515// lj->args.append("-Bdynamic");
516// if (dll || shared) {
517// lj->args.append("-e");
518// if (g->zig_target.arch.arch == ZigLLVM_x86) {
519// lj->args.append("_DllMainCRTStartup@12");
520// } else {
521// lj->args.append("DllMainCRTStartup");
522// }
523// lj->args.append("--enable-auto-image-base");
524// }
525//}
526//if (shared || dll) {
527// lj->args.append(get_libc_file(g, "dllcrt2.o"));
528//} else {
529// if (g->windows_linker_unicode) {
530// lj->args.append(get_libc_file(g, "crt2u.o"));
531// } else {
532// lj->args.append(get_libc_file(g, "crt2.o"));
533// }
534//}
535//lj->args.append(get_libc_static_file(g, "crtbegin.o"));
536//if (g->libc_link_lib != nullptr) {
537//if (g->is_static) {
538// lj->args.append("--start-group");
539//}
540
541//lj->args.append("-lmingw32");
542
543//lj->args.append("-lgcc");
544//bool is_android = (g->zig_target.env_type == ZigLLVM_Android);
545//bool is_cyg_ming = is_target_cyg_mingw(&g->zig_target);
546//if (!g->is_static && !is_android) {
547// if (!is_cyg_ming) {
548// lj->args.append("--as-needed");
549// }
550// //lj->args.append("-lgcc_s");
551// if (!is_cyg_ming) {
552// lj->args.append("--no-as-needed");
553// }
554//}
555//if (g->is_static && !is_android) {
556// //lj->args.append("-lgcc_eh");
557//}
558//if (is_android && !g->is_static) {
559// lj->args.append("-ldl");
560//}
561
562//lj->args.append("-lmoldname");
563//lj->args.append("-lmingwex");
564//lj->args.append("-lmsvcrt");
565
566
567//if (g->windows_subsystem_windows) {
568// lj->args.append("-lgdi32");
569// lj->args.append("-lcomdlg32");
570//}
571//lj->args.append("-ladvapi32");
572//lj->args.append("-lshell32");
573//lj->args.append("-luser32");
574//lj->args.append("-lkernel32");
575
576//if (g->is_static) {
577// lj->args.append("--end-group");
578//}
579
580//if (lj->link_in_crt) {
581// lj->args.append(get_libc_static_file(g, "crtend.o"));
582//}
583//}
584
585
586static void construct_linker_job_coff(LinkJob *lj) {
587 CodeGen *g = lj->codegen;
588
589 lj->args.append("/ERRORLIMIT:0");
590
591 if (g->libc_link_lib != nullptr) {
592 find_libc_lib_path(g);
593 }
594
595 lj->args.append("/NOLOGO");
596
597 if (!g->strip_debug_symbols) {
598 lj->args.append("/DEBUG");
599 }
600
601 if (g->out_type == OutTypeExe) {
602 // TODO compile time stack upper bound detection
603 lj->args.append("/STACK:16777216");
604 }
605
606 coff_append_machine_arg(g, &lj->args);
607
608 bool is_library = g->out_type == OutTypeLib;
609 switch (g->subsystem) {
610 case TargetSubsystemAuto:
611 break;
612 case TargetSubsystemConsole:
613 lj->args.append("/SUBSYSTEM:console");
614 add_nt_link_args(lj, is_library);
615 break;
616 case TargetSubsystemEfiApplication:
617 lj->args.append("/SUBSYSTEM:efi_application");
618 add_uefi_link_args(lj);
619 break;
620 case TargetSubsystemEfiBootServiceDriver:
621 lj->args.append("/SUBSYSTEM:efi_boot_service_driver");
622 add_uefi_link_args(lj);
623 break;
624 case TargetSubsystemEfiRom:
625 lj->args.append("/SUBSYSTEM:efi_rom");
626 add_uefi_link_args(lj);
627 break;
628 case TargetSubsystemEfiRuntimeDriver:
629 lj->args.append("/SUBSYSTEM:efi_runtime_driver");
630 add_uefi_link_args(lj);
631 break;
632 case TargetSubsystemNative:
633 lj->args.append("/SUBSYSTEM:native");
634 add_nt_link_args(lj, is_library);
635 break;
636 case TargetSubsystemPosix:
637 lj->args.append("/SUBSYSTEM:posix");
638 add_nt_link_args(lj, is_library);
639 break;
640 case TargetSubsystemWindows:
641 lj->args.append("/SUBSYSTEM:windows");
642 add_nt_link_args(lj, is_library);
643 break;
644 }
645
646 lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
647
648 if (g->libc_link_lib != nullptr) {
649 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir))));
650 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->kernel32_lib_dir))));
651
652 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir))));
653 if (g->libc_static_lib_dir != nullptr) {
654 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_lib_dir))));
655 }
656 }
559657
560 if (is_library && !g->is_static) {658 if (is_library && !g->is_static) {
561 lj->args.append("-DLL");659 lj->args.append("-DLL");
...@@ -627,54 +725,6 @@ static void construct_linker_job_coff(LinkJob *lj) {...@@ -627,54 +725,6 @@ static void construct_linker_job_coff(LinkJob *lj) {
627 }725 }
628 }726 }
629727
630 //if (g->libc_link_lib != nullptr) {
631 //if (g->is_static) {
632 // lj->args.append("--start-group");
633 //}
634
635 //lj->args.append("-lmingw32");
636
637 //lj->args.append("-lgcc");
638 //bool is_android = (g->zig_target.env_type == ZigLLVM_Android);
639 //bool is_cyg_ming = is_target_cyg_mingw(&g->zig_target);
640 //if (!g->is_static && !is_android) {
641 // if (!is_cyg_ming) {
642 // lj->args.append("--as-needed");
643 // }
644 // //lj->args.append("-lgcc_s");
645 // if (!is_cyg_ming) {
646 // lj->args.append("--no-as-needed");
647 // }
648 //}
649 //if (g->is_static && !is_android) {
650 // //lj->args.append("-lgcc_eh");
651 //}
652 //if (is_android && !g->is_static) {
653 // lj->args.append("-ldl");
654 //}
655
656 //lj->args.append("-lmoldname");
657 //lj->args.append("-lmingwex");
658 //lj->args.append("-lmsvcrt");
659
660
661 //if (g->windows_subsystem_windows) {
662 // lj->args.append("-lgdi32");
663 // lj->args.append("-lcomdlg32");
664 //}
665 //lj->args.append("-ladvapi32");
666 //lj->args.append("-lshell32");
667 //lj->args.append("-luser32");
668 //lj->args.append("-lkernel32");
669
670 //if (g->is_static) {
671 // lj->args.append("--end-group");
672 //}
673
674 //if (lj->link_in_crt) {
675 // lj->args.append(get_libc_static_file(g, "crtend.o"));
676 //}
677 //}
678}728}
679729
680730
src/main.cpp+82-16
...@@ -21,8 +21,8 @@ static int print_error_usage(const char *arg0) {...@@ -21,8 +21,8 @@ static int print_error_usage(const char *arg0) {
21 return EXIT_FAILURE;21 return EXIT_FAILURE;
22}22}
2323
24static int print_full_usage(const char *arg0) {24static int print_full_usage(const char *arg0, FILE *file, int return_code) {
25 fprintf(stdout,25 fprintf(file,
26 "Usage: %s [command] [options]\n"26 "Usage: %s [command] [options]\n"
27 "\n"27 "\n"
28 "Commands:\n"28 "Commands:\n"
...@@ -31,6 +31,7 @@ static int print_full_usage(const char *arg0) {...@@ -31,6 +31,7 @@ static int print_full_usage(const char *arg0) {
31 " build-lib [source] create library from source or object files\n"31 " build-lib [source] create library from source or object files\n"
32 " build-obj [source] create object from source or assembly\n"32 " build-obj [source] create object from source or assembly\n"
33 " builtin show the source code of that @import(\"builtin\")\n"33 " builtin show the source code of that @import(\"builtin\")\n"
34 " fmt parse files and render in canonical zig format\n"
34 " help show this usage information\n"35 " help show this usage information\n"
35 " id print the base64-encoded compiler id\n"36 " id print the base64-encoded compiler id\n"
36 " init-exe initialize a `zig build` application in the cwd\n"37 " init-exe initialize a `zig build` application in the cwd\n"
...@@ -59,6 +60,7 @@ static int print_full_usage(const char *arg0) {...@@ -59,6 +60,7 @@ static int print_full_usage(const char *arg0) {
59 " --release-fast build with optimizations on and safety off\n"60 " --release-fast build with optimizations on and safety off\n"
60 " --release-safe build with optimizations on and safety on\n"61 " --release-safe build with optimizations on and safety on\n"
61 " --release-small build with size optimizations on and safety off\n"62 " --release-small build with size optimizations on and safety off\n"
63 " --single-threaded source may assume it is only used single-threaded\n"
62 " --static output will be statically linked\n"64 " --static output will be statically linked\n"
63 " --strip exclude debug symbols\n"65 " --strip exclude debug symbols\n"
64 " --target-arch [name] specify target architecture\n"66 " --target-arch [name] specify target architecture\n"
...@@ -73,6 +75,7 @@ static int print_full_usage(const char *arg0) {...@@ -73,6 +75,7 @@ static int print_full_usage(const char *arg0) {
73 " -dirafter [dir] same as -isystem but do it last\n"75 " -dirafter [dir] same as -isystem but do it last\n"
74 " -isystem [dir] add additional search path for other .h files\n"76 " -isystem [dir] add additional search path for other .h files\n"
75 " -mllvm [arg] forward an arg to LLVM's option processing\n"77 " -mllvm [arg] forward an arg to LLVM's option processing\n"
78 " --override-std-dir [arg] use an alternate Zig standard library\n"
76 "\n"79 "\n"
77 "Link Options:\n"80 "Link Options:\n"
78 " --dynamic-linker [path] set the path to ld.so\n"81 " --dynamic-linker [path] set the path to ld.so\n"
...@@ -90,8 +93,7 @@ static int print_full_usage(const char *arg0) {...@@ -90,8 +93,7 @@ static int print_full_usage(const char *arg0) {
90 " -rdynamic add all symbols to the dynamic symbol table\n"93 " -rdynamic add all symbols to the dynamic symbol table\n"
91 " -rpath [path] add directory to the runtime library search path\n"94 " -rpath [path] add directory to the runtime library search path\n"
92 " --no-rosegment compromise security to workaround valgrind bug\n"95 " --no-rosegment compromise security to workaround valgrind bug\n"
93 " -mconsole (windows) --subsystem console to the linker\n"96 " --subsystem [subsystem] (windows) /SUBSYSTEM:<subsystem> to the linker\n"
94 " -mwindows (windows) --subsystem windows to the linker\n"
95 " -framework [name] (darwin) link against framework\n"97 " -framework [name] (darwin) link against framework\n"
96 " -mios-version-min [ver] (darwin) set iOS deployment target\n"98 " -mios-version-min [ver] (darwin) set iOS deployment target\n"
97 " -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target\n"99 " -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target\n"
...@@ -105,7 +107,7 @@ static int print_full_usage(const char *arg0) {...@@ -105,7 +107,7 @@ static int print_full_usage(const char *arg0) {
105 " --test-cmd [arg] specify test execution command one arg at a time\n"107 " --test-cmd [arg] specify test execution command one arg at a time\n"
106 " --test-cmd-bin appends test binary path to test cmd args\n"108 " --test-cmd-bin appends test binary path to test cmd args\n"
107 , arg0);109 , arg0);
108 return EXIT_SUCCESS;110 return return_code;
109}111}
110112
111static const char *ZIG_ZEN = "\n"113static const char *ZIG_ZEN = "\n"
...@@ -371,8 +373,6 @@ int main(int argc, char **argv) {...@@ -371,8 +373,6 @@ int main(int argc, char **argv) {
371 const char *target_arch = nullptr;373 const char *target_arch = nullptr;
372 const char *target_os = nullptr;374 const char *target_os = nullptr;
373 const char *target_environ = nullptr;375 const char *target_environ = nullptr;
374 bool mwindows = false;
375 bool mconsole = false;
376 bool rdynamic = false;376 bool rdynamic = false;
377 const char *mmacosx_version_min = nullptr;377 const char *mmacosx_version_min = nullptr;
378 const char *mios_version_min = nullptr;378 const char *mios_version_min = nullptr;
...@@ -395,6 +395,9 @@ int main(int argc, char **argv) {...@@ -395,6 +395,9 @@ int main(int argc, char **argv) {
395 int runtime_args_start = -1;395 int runtime_args_start = -1;
396 bool no_rosegment_workaround = false;396 bool no_rosegment_workaround = false;
397 bool system_linker_hack = false;397 bool system_linker_hack = false;
398 TargetSubsystem subsystem = TargetSubsystemAuto;
399 bool is_single_threaded = false;
400 Buf *override_std_dir = nullptr;
398401
399 if (argc >= 2 && strcmp(argv[1], "build") == 0) {402 if (argc >= 2 && strcmp(argv[1], "build") == 0) {
400 Buf zig_exe_path_buf = BUF_INIT;403 Buf zig_exe_path_buf = BUF_INIT;
...@@ -430,7 +433,8 @@ int main(int argc, char **argv) {...@@ -430,7 +433,8 @@ int main(int argc, char **argv) {
430 Buf *build_runner_path = buf_alloc();433 Buf *build_runner_path = buf_alloc();
431 os_path_join(get_zig_special_dir(), buf_create_from_str("build_runner.zig"), build_runner_path);434 os_path_join(get_zig_special_dir(), buf_create_from_str("build_runner.zig"), build_runner_path);
432435
433 CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir());436 CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir(),
437 override_std_dir);
434 g->enable_time_report = timing_info;438 g->enable_time_report = timing_info;
435 buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);439 buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
436 codegen_set_out_name(g, buf_create_from_str("build"));440 codegen_set_out_name(g, buf_create_from_str("build"));
...@@ -512,6 +516,31 @@ int main(int argc, char **argv) {...@@ -512,6 +516,31 @@ int main(int argc, char **argv) {
512 fprintf(stderr, "\n");516 fprintf(stderr, "\n");
513 }517 }
514 return (term.how == TerminationIdClean) ? term.code : -1;518 return (term.how == TerminationIdClean) ? term.code : -1;
519 } else if (argc >= 2 && strcmp(argv[1], "fmt") == 0) {
520 init_all_targets();
521 Buf *fmt_runner_path = buf_alloc();
522 os_path_join(get_zig_special_dir(), buf_create_from_str("fmt_runner.zig"), fmt_runner_path);
523 CodeGen *g = codegen_create(fmt_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir(),
524 nullptr);
525 g->is_single_threaded = true;
526 codegen_set_out_name(g, buf_create_from_str("fmt"));
527 g->enable_cache = true;
528
529 codegen_build_and_link(g);
530
531 ZigList<const char*> args = {0};
532 for (int i = 2; i < argc; i += 1) {
533 args.append(argv[i]);
534 }
535 args.append(nullptr);
536 const char *exec_path = buf_ptr(&g->output_file_path);
537
538 os_execv(exec_path, args.items);
539
540 args.pop();
541 Termination term;
542 os_spawn_process(exec_path, args, &term);
543 return term.code;
515 }544 }
516545
517 for (int i = 1; i < argc; i += 1) {546 for (int i = 1; i < argc; i += 1) {
...@@ -524,6 +553,8 @@ int main(int argc, char **argv) {...@@ -524,6 +553,8 @@ int main(int argc, char **argv) {
524 build_mode = BuildModeSafeRelease;553 build_mode = BuildModeSafeRelease;
525 } else if (strcmp(arg, "--release-small") == 0) {554 } else if (strcmp(arg, "--release-small") == 0) {
526 build_mode = BuildModeSmallRelease;555 build_mode = BuildModeSmallRelease;
556 } else if (strcmp(arg, "--help") == 0) {
557 return print_full_usage(arg0, stderr, EXIT_FAILURE);
527 } else if (strcmp(arg, "--strip") == 0) {558 } else if (strcmp(arg, "--strip") == 0) {
528 strip = true;559 strip = true;
529 } else if (strcmp(arg, "--static") == 0) {560 } else if (strcmp(arg, "--static") == 0) {
...@@ -540,10 +571,6 @@ int main(int argc, char **argv) {...@@ -540,10 +571,6 @@ int main(int argc, char **argv) {
540 verbose_llvm_ir = true;571 verbose_llvm_ir = true;
541 } else if (strcmp(arg, "--verbose-cimport") == 0) {572 } else if (strcmp(arg, "--verbose-cimport") == 0) {
542 verbose_cimport = true;573 verbose_cimport = true;
543 } else if (strcmp(arg, "-mwindows") == 0) {
544 mwindows = true;
545 } else if (strcmp(arg, "-mconsole") == 0) {
546 mconsole = true;
547 } else if (strcmp(arg, "-rdynamic") == 0) {574 } else if (strcmp(arg, "-rdynamic") == 0) {
548 rdynamic = true;575 rdynamic = true;
549 } else if (strcmp(arg, "--no-rosegment") == 0) {576 } else if (strcmp(arg, "--no-rosegment") == 0) {
...@@ -556,6 +583,8 @@ int main(int argc, char **argv) {...@@ -556,6 +583,8 @@ int main(int argc, char **argv) {
556 disable_pic = true;583 disable_pic = true;
557 } else if (strcmp(arg, "--system-linker-hack") == 0) {584 } else if (strcmp(arg, "--system-linker-hack") == 0) {
558 system_linker_hack = true;585 system_linker_hack = true;
586 } else if (strcmp(arg, "--single-threaded") == 0) {
587 is_single_threaded = true;
559 } else if (strcmp(arg, "--test-cmd-bin") == 0) {588 } else if (strcmp(arg, "--test-cmd-bin") == 0) {
560 test_exec_args.append(nullptr);589 test_exec_args.append(nullptr);
561 } else if (arg[1] == 'L' && arg[2] != 0) {590 } else if (arg[1] == 'L' && arg[2] != 0) {
...@@ -647,6 +676,8 @@ int main(int argc, char **argv) {...@@ -647,6 +676,8 @@ int main(int argc, char **argv) {
647 clang_argv.append(argv[i]);676 clang_argv.append(argv[i]);
648677
649 llvm_argv.append(argv[i]);678 llvm_argv.append(argv[i]);
679 } else if (strcmp(arg, "--override-std-dir") == 0) {
680 override_std_dir = buf_create_from_str(argv[i]);
650 } else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) {681 } else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) {
651 lib_dirs.append(argv[i]);682 lib_dirs.append(argv[i]);
652 } else if (strcmp(arg, "--library") == 0) {683 } else if (strcmp(arg, "--library") == 0) {
...@@ -687,6 +718,37 @@ int main(int argc, char **argv) {...@@ -687,6 +718,37 @@ int main(int argc, char **argv) {
687 ver_patch = atoi(argv[i]);718 ver_patch = atoi(argv[i]);
688 } else if (strcmp(arg, "--test-cmd") == 0) {719 } else if (strcmp(arg, "--test-cmd") == 0) {
689 test_exec_args.append(argv[i]);720 test_exec_args.append(argv[i]);
721 } else if (strcmp(arg, "--subsystem") == 0) {
722 if (strcmp(argv[i], "console") == 0) {
723 subsystem = TargetSubsystemConsole;
724 } else if (strcmp(argv[i], "windows") == 0) {
725 subsystem = TargetSubsystemWindows;
726 } else if (strcmp(argv[i], "posix") == 0) {
727 subsystem = TargetSubsystemPosix;
728 } else if (strcmp(argv[i], "native") == 0) {
729 subsystem = TargetSubsystemNative;
730 } else if (strcmp(argv[i], "efi_application") == 0) {
731 subsystem = TargetSubsystemEfiApplication;
732 } else if (strcmp(argv[i], "efi_boot_service_driver") == 0) {
733 subsystem = TargetSubsystemEfiBootServiceDriver;
734 } else if (strcmp(argv[i], "efi_rom") == 0) {
735 subsystem = TargetSubsystemEfiRom;
736 } else if (strcmp(argv[i], "efi_runtime_driver") == 0) {
737 subsystem = TargetSubsystemEfiRuntimeDriver;
738 } else {
739 fprintf(stderr, "invalid: --subsystem %s\n"
740 "Options are:\n"
741 " console\n"
742 " windows\n"
743 " posix\n"
744 " native\n"
745 " efi_application\n"
746 " efi_boot_service_driver\n"
747 " efi_rom\n"
748 " efi_runtime_driver\n"
749 , argv[i]);
750 return EXIT_FAILURE;
751 }
690 } else {752 } else {
691 fprintf(stderr, "Invalid argument: %s\n", arg);753 fprintf(stderr, "Invalid argument: %s\n", arg);
692 return print_error_usage(arg0);754 return print_error_usage(arg0);
...@@ -790,7 +852,8 @@ int main(int argc, char **argv) {...@@ -790,7 +852,8 @@ int main(int argc, char **argv) {
790852
791 switch (cmd) {853 switch (cmd) {
792 case CmdBuiltin: {854 case CmdBuiltin: {
793 CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, get_zig_lib_dir());855 CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, get_zig_lib_dir(), override_std_dir);
856 g->is_single_threaded = is_single_threaded;
794 Buf *builtin_source = codegen_generate_builtin_source(g);857 Buf *builtin_source = codegen_generate_builtin_source(g);
795 if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {858 if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {
796 fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));859 fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));
...@@ -848,7 +911,10 @@ int main(int argc, char **argv) {...@@ -848,7 +911,10 @@ int main(int argc, char **argv) {
848 if (cmd == CmdRun && buf_out_name == nullptr) {911 if (cmd == CmdRun && buf_out_name == nullptr) {
849 buf_out_name = buf_create_from_str("run");912 buf_out_name = buf_create_from_str("run");
850 }913 }
851 CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir());914 CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir(),
915 override_std_dir);
916 g->subsystem = subsystem;
917
852 if (disable_pic) {918 if (disable_pic) {
853 if (out_type != OutTypeLib || !is_static) {919 if (out_type != OutTypeLib || !is_static) {
854 fprintf(stderr, "--disable-pic only applies to static libraries");920 fprintf(stderr, "--disable-pic only applies to static libraries");
...@@ -862,6 +928,7 @@ int main(int argc, char **argv) {...@@ -862,6 +928,7 @@ int main(int argc, char **argv) {
862 codegen_set_out_name(g, buf_out_name);928 codegen_set_out_name(g, buf_out_name);
863 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);929 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
864 codegen_set_is_test(g, cmd == CmdTest);930 codegen_set_is_test(g, cmd == CmdTest);
931 g->is_single_threaded = is_single_threaded;
865 codegen_set_linker_script(g, linker_script);932 codegen_set_linker_script(g, linker_script);
866 if (each_lib_rpath)933 if (each_lib_rpath)
867 codegen_set_each_lib_rpath(g, each_lib_rpath);934 codegen_set_each_lib_rpath(g, each_lib_rpath);
...@@ -909,7 +976,6 @@ int main(int argc, char **argv) {...@@ -909,7 +976,6 @@ int main(int argc, char **argv) {
909 codegen_add_rpath(g, rpath_list.at(i));976 codegen_add_rpath(g, rpath_list.at(i));
910 }977 }
911978
912 codegen_set_windows_subsystem(g, mwindows, mconsole);
913 codegen_set_rdynamic(g, rdynamic);979 codegen_set_rdynamic(g, rdynamic);
914 g->no_rosegment_workaround = no_rosegment_workaround;980 g->no_rosegment_workaround = no_rosegment_workaround;
915 if (mmacosx_version_min && mios_version_min) {981 if (mmacosx_version_min && mios_version_min) {
...@@ -1042,7 +1108,7 @@ int main(int argc, char **argv) {...@@ -1042,7 +1108,7 @@ int main(int argc, char **argv) {
1042 }1108 }
1043 }1109 }
1044 case CmdHelp:1110 case CmdHelp:
1045 return print_full_usage(arg0);1111 return print_full_usage(arg0, stdout, EXIT_SUCCESS);
1046 case CmdVersion:1112 case CmdVersion:
1047 printf("%s\n", ZIG_VERSION_STRING);1113 printf("%s\n", ZIG_VERSION_STRING);
1048 return EXIT_SUCCESS;1114 return EXIT_SUCCESS;
src/os.cpp+32-32
...@@ -1456,7 +1456,7 @@ Error os_self_exe_path(Buf *out_path) {...@@ -1456,7 +1456,7 @@ Error os_self_exe_path(Buf *out_path) {
1456 if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) {1456 if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) {
1457 return ErrorUnexpected;1457 return ErrorUnexpected;
1458 }1458 }
1459 buf_resize(out_path, cb);1459 buf_resize(out_path, cb - 1);
1460 return ErrorNone;1460 return ErrorNone;
1461#endif1461#endif
1462 return ErrorFileNotFound;1462 return ErrorFileNotFound;
...@@ -1808,7 +1808,7 @@ Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {...@@ -1808,7 +1808,7 @@ Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {
1808#endif1808#endif
1809}1809}
18101810
1811Error os_file_open_r(Buf *full_path, OsFile *out_file) {1811Error os_file_open_r(Buf *full_path, OsFile *out_file, OsTimeStamp *mtime) {
1812#if defined(ZIG_OS_WINDOWS)1812#if defined(ZIG_OS_WINDOWS)
1813 // TODO use CreateFileW1813 // TODO use CreateFileW
1814 HANDLE result = CreateFileA(buf_ptr(full_path), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);1814 HANDLE result = CreateFileA(buf_ptr(full_path), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
...@@ -1834,8 +1834,18 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) {...@@ -1834,8 +1834,18 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) {
1834 return ErrorUnexpected;1834 return ErrorUnexpected;
1835 }1835 }
1836 }1836 }
1837
1838 *out_file = result;1837 *out_file = result;
1838
1839 if (mtime != nullptr) {
1840 FILETIME last_write_time;
1841 if (!GetFileTime(result, nullptr, nullptr, &last_write_time)) {
1842 CloseHandle(result);
1843 return ErrorUnexpected;
1844 }
1845 mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime;
1846 mtime->nsec = 0;
1847 }
1848
1839 return ErrorNone;1849 return ErrorNone;
1840#else1850#else
1841 for (;;) {1851 for (;;) {
...@@ -1858,7 +1868,26 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) {...@@ -1858,7 +1868,26 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) {
1858 return ErrorFileSystem;1868 return ErrorFileSystem;
1859 }1869 }
1860 }1870 }
1871 struct stat statbuf;
1872 if (fstat(fd, &statbuf) == -1) {
1873 close(fd);
1874 return ErrorFileSystem;
1875 }
1876 if (S_ISDIR(statbuf.st_mode)) {
1877 close(fd);
1878 return ErrorIsDir;
1879 }
1861 *out_file = fd;1880 *out_file = fd;
1881
1882 if (mtime != nullptr) {
1883#if defined(ZIG_OS_DARWIN)
1884 mtime->sec = statbuf.st_mtimespec.tv_sec;
1885 mtime->nsec = statbuf.st_mtimespec.tv_nsec;
1886#else
1887 mtime->sec = statbuf.st_mtim.tv_sec;
1888 mtime->nsec = statbuf.st_mtim.tv_nsec;
1889#endif
1890 }
1862 return ErrorNone;1891 return ErrorNone;
1863 }1892 }
1864#endif1893#endif
...@@ -1948,35 +1977,6 @@ Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {...@@ -1948,35 +1977,6 @@ Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {
1948#endif1977#endif
1949}1978}
19501979
1951Error os_file_mtime(OsFile file, OsTimeStamp *mtime) {
1952#if defined(ZIG_OS_WINDOWS)
1953 FILETIME last_write_time;
1954 if (!GetFileTime(file, nullptr, nullptr, &last_write_time))
1955 return ErrorUnexpected;
1956 mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime;
1957 mtime->nsec = 0;
1958 return ErrorNone;
1959#elif defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD)
1960 struct stat statbuf;
1961 if (fstat(file, &statbuf) == -1)
1962 return ErrorFileSystem;
1963
1964 mtime->sec = statbuf.st_mtim.tv_sec;
1965 mtime->nsec = statbuf.st_mtim.tv_nsec;
1966 return ErrorNone;
1967#elif defined(ZIG_OS_DARWIN)
1968 struct stat statbuf;
1969 if (fstat(file, &statbuf) == -1)
1970 return ErrorFileSystem;
1971
1972 mtime->sec = statbuf.st_mtimespec.tv_sec;
1973 mtime->nsec = statbuf.st_mtimespec.tv_nsec;
1974 return ErrorNone;
1975#else
1976#error unimplemented
1977#endif
1978}
1979
1980Error os_file_read(OsFile file, void *ptr, size_t *len) {1980Error os_file_read(OsFile file, void *ptr, size_t *len) {
1981#if defined(ZIG_OS_WINDOWS)1981#if defined(ZIG_OS_WINDOWS)
1982 DWORD amt_read;1982 DWORD amt_read;
src/os.hpp+1-2
...@@ -101,9 +101,8 @@ bool os_path_is_absolute(Buf *path);...@@ -101,9 +101,8 @@ bool os_path_is_absolute(Buf *path);
101Error ATTRIBUTE_MUST_USE os_make_path(Buf *path);101Error ATTRIBUTE_MUST_USE os_make_path(Buf *path);
102Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path);102Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path);
103103
104Error ATTRIBUTE_MUST_USE os_file_open_r(Buf *full_path, OsFile *out_file);104Error ATTRIBUTE_MUST_USE os_file_open_r(Buf *full_path, OsFile *out_file, OsTimeStamp *mtime);
105Error ATTRIBUTE_MUST_USE os_file_open_lock_rw(Buf *full_path, OsFile *out_file);105Error ATTRIBUTE_MUST_USE os_file_open_lock_rw(Buf *full_path, OsFile *out_file);
106Error ATTRIBUTE_MUST_USE os_file_mtime(OsFile file, OsTimeStamp *mtime);
107Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len);106Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len);
108Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents);107Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents);
109Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents);108Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents);
src/parser.cpp+27-13
...@@ -381,7 +381,7 @@ static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parse...@@ -381,7 +381,7 @@ static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parse
381 else_body = ast_expect(pc, body_parser);381 else_body = ast_expect(pc, body_parser);
382 }382 }
383383
384 assert(res->type == NodeTypeTestExpr);384 assert(res->type == NodeTypeIfOptional);
385 if (err_payload != nullptr) {385 if (err_payload != nullptr) {
386 AstNodeTestExpr old = res->data.test_expr;386 AstNodeTestExpr old = res->data.test_expr;
387 res->type = NodeTypeIfErrorExpr;387 res->type = NodeTypeIfErrorExpr;
...@@ -844,12 +844,17 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {...@@ -844,12 +844,17 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {
844844
845// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON845// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON
846static AstNode *ast_parse_var_decl(ParseContext *pc) {846static AstNode *ast_parse_var_decl(ParseContext *pc) {
847 Token *first = eat_token_if(pc, TokenIdKeywordConst);847 Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal);
848 if (first == nullptr)848 Token *mut_kw = eat_token_if(pc, TokenIdKeywordConst);
849 first = eat_token_if(pc, TokenIdKeywordVar);849 if (mut_kw == nullptr)
850 if (first == nullptr)850 mut_kw = eat_token_if(pc, TokenIdKeywordVar);
851 return nullptr;851 if (mut_kw == nullptr) {
852852 if (thread_local_kw == nullptr) {
853 return nullptr;
854 } else {
855 ast_invalid_token_error(pc, peek_token(pc));
856 }
857 }
853 Token *identifier = expect_token(pc, TokenIdSymbol);858 Token *identifier = expect_token(pc, TokenIdSymbol);
854 AstNode *type_expr = nullptr;859 AstNode *type_expr = nullptr;
855 if (eat_token_if(pc, TokenIdColon) != nullptr)860 if (eat_token_if(pc, TokenIdColon) != nullptr)
...@@ -863,8 +868,9 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) {...@@ -863,8 +868,9 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) {
863868
864 expect_token(pc, TokenIdSemicolon);869 expect_token(pc, TokenIdSemicolon);
865870
866 AstNode *res = ast_create_node(pc, NodeTypeVariableDeclaration, first);871 AstNode *res = ast_create_node(pc, NodeTypeVariableDeclaration, mut_kw);
867 res->data.variable_declaration.is_const = first->id == TokenIdKeywordConst;872 res->data.variable_declaration.threadlocal_tok = thread_local_kw;
873 res->data.variable_declaration.is_const = mut_kw->id == TokenIdKeywordConst;
868 res->data.variable_declaration.symbol = token_buf(identifier);874 res->data.variable_declaration.symbol = token_buf(identifier);
869 res->data.variable_declaration.type = type_expr;875 res->data.variable_declaration.type = type_expr;
870 res->data.variable_declaration.align_expr = align_expr;876 res->data.variable_declaration.align_expr = align_expr;
...@@ -990,7 +996,7 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) {...@@ -990,7 +996,7 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) {
990 if (requires_semi && else_body == nullptr)996 if (requires_semi && else_body == nullptr)
991 expect_token(pc, TokenIdSemicolon);997 expect_token(pc, TokenIdSemicolon);
992998
993 assert(res->type == NodeTypeTestExpr);999 assert(res->type == NodeTypeIfOptional);
994 if (err_payload != nullptr) {1000 if (err_payload != nullptr) {
995 AstNodeTestExpr old = res->data.test_expr;1001 AstNodeTestExpr old = res->data.test_expr;
996 res->type = NodeTypeIfErrorExpr;1002 res->type = NodeTypeIfErrorExpr;
...@@ -2204,7 +2210,7 @@ static AstNode *ast_parse_if_prefix(ParseContext *pc) {...@@ -2204,7 +2210,7 @@ static AstNode *ast_parse_if_prefix(ParseContext *pc) {
2204 Optional<PtrPayload> opt_payload = ast_parse_ptr_payload(pc);2210 Optional<PtrPayload> opt_payload = ast_parse_ptr_payload(pc);
22052211
2206 PtrPayload payload;2212 PtrPayload payload;
2207 AstNode *res = ast_create_node(pc, NodeTypeTestExpr, first);2213 AstNode *res = ast_create_node(pc, NodeTypeIfOptional, first);
2208 res->data.test_expr.target_node = condition;2214 res->data.test_expr.target_node = condition;
2209 if (opt_payload.unwrap(&payload)) {2215 if (opt_payload.unwrap(&payload)) {
2210 res->data.test_expr.var_symbol = token_buf(payload.payload);2216 res->data.test_expr.var_symbol = token_buf(payload.payload);
...@@ -2772,7 +2778,8 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {...@@ -2772,7 +2778,8 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {
2772// PtrTypeStart2778// PtrTypeStart
2773// <- ASTERISK2779// <- ASTERISK
2774// / ASTERISK22780// / ASTERISK2
2775// / LBRACKET ASTERISK RBRACKET2781// / PTRUNKNOWN
2782// / PTRC
2776static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {2783static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
2777 Token *asterisk = eat_token_if(pc, TokenIdStar);2784 Token *asterisk = eat_token_if(pc, TokenIdStar);
2778 if (asterisk != nullptr) {2785 if (asterisk != nullptr) {
...@@ -2798,6 +2805,13 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {...@@ -2798,6 +2805,13 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
2798 return res;2805 return res;
2799 }2806 }
28002807
2808 Token *cptr = eat_token_if(pc, TokenIdBracketStarCBracket);
2809 if (cptr != nullptr) {
2810 AstNode *res = ast_create_node(pc, NodeTypePointerType, cptr);
2811 res->data.pointer_type.star_token = cptr;
2812 return res;
2813 }
2814
2801 return nullptr;2815 return nullptr;
2802}2816}
28032817
...@@ -2999,7 +3013,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -2999,7 +3013,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
2999 visit_field(&node->data.if_err_expr.then_node, visit, context);3013 visit_field(&node->data.if_err_expr.then_node, visit, context);
3000 visit_field(&node->data.if_err_expr.else_node, visit, context);3014 visit_field(&node->data.if_err_expr.else_node, visit, context);
3001 break;3015 break;
3002 case NodeTypeTestExpr:3016 case NodeTypeIfOptional:
3003 visit_field(&node->data.test_expr.target_node, visit, context);3017 visit_field(&node->data.test_expr.target_node, visit, context);
3004 visit_field(&node->data.test_expr.then_node, visit, context);3018 visit_field(&node->data.test_expr.then_node, visit, context);
3005 visit_field(&node->data.test_expr.else_node, visit, context);3019 visit_field(&node->data.test_expr.else_node, visit, context);
src/target.cpp+13-2
...@@ -174,6 +174,7 @@ static const Os os_list[] = {...@@ -174,6 +174,7 @@ static const Os os_list[] = {
174 OsContiki,174 OsContiki,
175 OsAMDPAL,175 OsAMDPAL,
176 OsZen,176 OsZen,
177 OsUefi,
177};178};
178179
179// Coordinate with zig_llvm.h180// Coordinate with zig_llvm.h
...@@ -282,6 +283,7 @@ ZigLLVM_OSType get_llvm_os_type(Os os_type) {...@@ -282,6 +283,7 @@ ZigLLVM_OSType get_llvm_os_type(Os os_type) {
282 case OsSolaris:283 case OsSolaris:
283 return ZigLLVM_Solaris;284 return ZigLLVM_Solaris;
284 case OsWindows:285 case OsWindows:
286 case OsUefi:
285 return ZigLLVM_Win32;287 return ZigLLVM_Win32;
286 case OsHaiku:288 case OsHaiku:
287 return ZigLLVM_Haiku;289 return ZigLLVM_Haiku;
...@@ -394,6 +396,8 @@ const char *get_target_os_name(Os os_type) {...@@ -394,6 +396,8 @@ const char *get_target_os_name(Os os_type) {
394 return "freestanding";396 return "freestanding";
395 case OsZen:397 case OsZen:
396 return "zen";398 return "zen";
399 case OsUefi:
400 return "uefi";
397 case OsAnanas:401 case OsAnanas:
398 case OsCloudABI:402 case OsCloudABI:
399 case OsDragonFly:403 case OsDragonFly:
...@@ -756,6 +760,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {...@@ -756,6 +760,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
756 case CIntTypeCount:760 case CIntTypeCount:
757 zig_unreachable();761 zig_unreachable();
758 }762 }
763 case OsUefi:
759 case OsWindows:764 case OsWindows:
760 switch (id) {765 switch (id) {
761 case CIntTypeShort:766 case CIntTypeShort:
...@@ -802,8 +807,12 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {...@@ -802,8 +807,12 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
802 zig_unreachable();807 zig_unreachable();
803}808}
804809
810bool target_allows_addr_zero(const ZigTarget *target) {
811 return target->os == OsFreestanding;
812}
813
805const char *target_o_file_ext(ZigTarget *target) {814const char *target_o_file_ext(ZigTarget *target) {
806 if (target->env_type == ZigLLVM_MSVC || target->os == OsWindows) {815 if (target->env_type == ZigLLVM_MSVC || target->os == OsWindows || target->os == OsUefi) {
807 return ".obj";816 return ".obj";
808 } else {817 } else {
809 return ".o";818 return ".o";
...@@ -821,13 +830,15 @@ const char *target_llvm_ir_file_ext(ZigTarget *target) {...@@ -821,13 +830,15 @@ const char *target_llvm_ir_file_ext(ZigTarget *target) {
821const char *target_exe_file_ext(ZigTarget *target) {830const char *target_exe_file_ext(ZigTarget *target) {
822 if (target->os == OsWindows) {831 if (target->os == OsWindows) {
823 return ".exe";832 return ".exe";
833 } else if (target->os == OsUefi) {
834 return ".efi";
824 } else {835 } else {
825 return "";836 return "";
826 }837 }
827}838}
828839
829const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch) {840const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch) {
830 if (target->os == OsWindows) {841 if (target->os == OsWindows || target->os == OsUefi) {
831 if (is_static) {842 if (is_static) {
832 return ".lib";843 return ".lib";
833 } else {844 } else {
src/target.hpp+14
...@@ -51,6 +51,19 @@ enum Os {...@@ -51,6 +51,19 @@ enum Os {
51 OsContiki,51 OsContiki,
52 OsAMDPAL,52 OsAMDPAL,
53 OsZen,53 OsZen,
54 OsUefi,
55};
56
57enum TargetSubsystem {
58 TargetSubsystemAuto, // Zig should infer the subsystem
59 TargetSubsystemConsole,
60 TargetSubsystemWindows,
61 TargetSubsystemPosix,
62 TargetSubsystemNative,
63 TargetSubsystemEfiApplication,
64 TargetSubsystemEfiBootServiceDriver,
65 TargetSubsystemEfiRom,
66 TargetSubsystemEfiRuntimeDriver,
54};67};
5568
56struct ZigTarget {69struct ZigTarget {
...@@ -122,5 +135,6 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target...@@ -122,5 +135,6 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target
122ZigLLVM_OSType get_llvm_os_type(Os os_type);135ZigLLVM_OSType get_llvm_os_type(Os os_type);
123136
124bool target_is_arm(const ZigTarget *target);137bool target_is_arm(const ZigTarget *target);
138bool target_allows_addr_zero(const ZigTarget *target);
125139
126#endif140#endif
src/tokenizer.cpp+25-8
...@@ -146,6 +146,7 @@ static const struct ZigKeyword zig_keywords[] = {...@@ -146,6 +146,7 @@ static const struct ZigKeyword zig_keywords[] = {
146 {"suspend", TokenIdKeywordSuspend},146 {"suspend", TokenIdKeywordSuspend},
147 {"switch", TokenIdKeywordSwitch},147 {"switch", TokenIdKeywordSwitch},
148 {"test", TokenIdKeywordTest},148 {"test", TokenIdKeywordTest},
149 {"threadlocal", TokenIdKeywordThreadLocal},
149 {"true", TokenIdKeywordTrue},150 {"true", TokenIdKeywordTrue},
150 {"try", TokenIdKeywordTry},151 {"try", TokenIdKeywordTry},
151 {"undefined", TokenIdKeywordUndefined},152 {"undefined", TokenIdKeywordUndefined},
...@@ -220,6 +221,7 @@ enum TokenizeState {...@@ -220,6 +221,7 @@ enum TokenizeState {
220 TokenizeStateError,221 TokenizeStateError,
221 TokenizeStateLBracket,222 TokenizeStateLBracket,
222 TokenizeStateLBracketStar,223 TokenizeStateLBracketStar,
224 TokenizeStateLBracketStarC,
223};225};
224226
225227
...@@ -248,13 +250,8 @@ ATTRIBUTE_PRINTF(2, 3)...@@ -248,13 +250,8 @@ ATTRIBUTE_PRINTF(2, 3)
248static void tokenize_error(Tokenize *t, const char *format, ...) {250static void tokenize_error(Tokenize *t, const char *format, ...) {
249 t->state = TokenizeStateError;251 t->state = TokenizeStateError;
250252
251 if (t->cur_tok) {253 t->out->err_line = t->line;
252 t->out->err_line = t->cur_tok->start_line;254 t->out->err_column = t->column;
253 t->out->err_column = t->cur_tok->start_column;
254 } else {
255 t->out->err_line = t->line;
256 t->out->err_column = t->column;
257 }
258255
259 va_list ap;256 va_list ap;
260 va_start(ap, format);257 va_start(ap, format);
...@@ -850,7 +847,6 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -850,7 +847,6 @@ void tokenize(Buf *buf, Tokenization *out) {
850 switch (c) {847 switch (c) {
851 case '*':848 case '*':
852 t.state = TokenizeStateLBracketStar;849 t.state = TokenizeStateLBracketStar;
853 set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket);
854 break;850 break;
855 default:851 default:
856 // reinterpret as just an lbracket852 // reinterpret as just an lbracket
...@@ -861,6 +857,21 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -861,6 +857,21 @@ void tokenize(Buf *buf, Tokenization *out) {
861 }857 }
862 break;858 break;
863 case TokenizeStateLBracketStar:859 case TokenizeStateLBracketStar:
860 switch (c) {
861 case 'c':
862 t.state = TokenizeStateLBracketStarC;
863 set_token_id(&t, t.cur_tok, TokenIdBracketStarCBracket);
864 break;
865 case ']':
866 set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket);
867 end_token(&t);
868 t.state = TokenizeStateStart;
869 break;
870 default:
871 invalid_char_error(&t, c);
872 }
873 break;
874 case TokenizeStateLBracketStarC:
864 switch (c) {875 switch (c) {
865 case ']':876 case ']':
866 end_token(&t);877 end_token(&t);
...@@ -886,6 +897,9 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -886,6 +897,9 @@ void tokenize(Buf *buf, Tokenization *out) {
886 break;897 break;
887 case TokenizeStateSawAmpersand:898 case TokenizeStateSawAmpersand:
888 switch (c) {899 switch (c) {
900 case '&':
901 tokenize_error(&t, "`&&` is invalid. Note that `and` is boolean AND.");
902 break;
889 case '=':903 case '=':
890 set_token_id(&t, t.cur_tok, TokenIdBitAndEq);904 set_token_id(&t, t.cur_tok, TokenIdBitAndEq);
891 end_token(&t);905 end_token(&t);
...@@ -1492,6 +1506,7 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1492,6 +1506,7 @@ void tokenize(Buf *buf, Tokenization *out) {
1492 case TokenizeStateLineStringContinue:1506 case TokenizeStateLineStringContinue:
1493 case TokenizeStateLineStringContinueC:1507 case TokenizeStateLineStringContinueC:
1494 case TokenizeStateLBracketStar:1508 case TokenizeStateLBracketStar:
1509 case TokenizeStateLBracketStarC:
1495 tokenize_error(&t, "unexpected EOF");1510 tokenize_error(&t, "unexpected EOF");
1496 break;1511 break;
1497 case TokenizeStateLineComment:1512 case TokenizeStateLineComment:
...@@ -1529,6 +1544,7 @@ const char * token_name(TokenId id) {...@@ -1529,6 +1544,7 @@ const char * token_name(TokenId id) {
1529 case TokenIdBitShiftRightEq: return ">>=";1544 case TokenIdBitShiftRightEq: return ">>=";
1530 case TokenIdBitXorEq: return "^=";1545 case TokenIdBitXorEq: return "^=";
1531 case TokenIdBracketStarBracket: return "[*]";1546 case TokenIdBracketStarBracket: return "[*]";
1547 case TokenIdBracketStarCBracket: return "[*c]";
1532 case TokenIdCharLiteral: return "CharLiteral";1548 case TokenIdCharLiteral: return "CharLiteral";
1533 case TokenIdCmpEq: return "==";1549 case TokenIdCmpEq: return "==";
1534 case TokenIdCmpGreaterOrEq: return ">=";1550 case TokenIdCmpGreaterOrEq: return ">=";
...@@ -1588,6 +1604,7 @@ const char * token_name(TokenId id) {...@@ -1588,6 +1604,7 @@ const char * token_name(TokenId id) {
1588 case TokenIdKeywordStruct: return "struct";1604 case TokenIdKeywordStruct: return "struct";
1589 case TokenIdKeywordSwitch: return "switch";1605 case TokenIdKeywordSwitch: return "switch";
1590 case TokenIdKeywordTest: return "test";1606 case TokenIdKeywordTest: return "test";
1607 case TokenIdKeywordThreadLocal: return "threadlocal";
1591 case TokenIdKeywordTrue: return "true";1608 case TokenIdKeywordTrue: return "true";
1592 case TokenIdKeywordTry: return "try";1609 case TokenIdKeywordTry: return "try";
1593 case TokenIdKeywordUndefined: return "undefined";1610 case TokenIdKeywordUndefined: return "undefined";
src/tokenizer.hpp+2
...@@ -29,6 +29,7 @@ enum TokenId {...@@ -29,6 +29,7 @@ enum TokenId {
29 TokenIdBitShiftRightEq,29 TokenIdBitShiftRightEq,
30 TokenIdBitXorEq,30 TokenIdBitXorEq,
31 TokenIdBracketStarBracket,31 TokenIdBracketStarBracket,
32 TokenIdBracketStarCBracket,
32 TokenIdCharLiteral,33 TokenIdCharLiteral,
33 TokenIdCmpEq,34 TokenIdCmpEq,
34 TokenIdCmpGreaterOrEq,35 TokenIdCmpGreaterOrEq,
...@@ -88,6 +89,7 @@ enum TokenId {...@@ -88,6 +89,7 @@ enum TokenId {
88 TokenIdKeywordSuspend,89 TokenIdKeywordSuspend,
89 TokenIdKeywordSwitch,90 TokenIdKeywordSwitch,
90 TokenIdKeywordTest,91 TokenIdKeywordTest,
92 TokenIdKeywordThreadLocal,
91 TokenIdKeywordTrue,93 TokenIdKeywordTrue,
92 TokenIdKeywordTry,94 TokenIdKeywordTry,
93 TokenIdKeywordUndefined,95 TokenIdKeywordUndefined,
src/translate_c.cpp+1226-1173
...@@ -4,7 +4,6 @@...@@ -4,7 +4,6 @@
4 * This file is part of zig, which is MIT licensed.4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT5 * See http://opensource.org/licenses/MIT
6 */6 */
7
8#include "all_types.hpp"7#include "all_types.hpp"
9#include "analyze.hpp"8#include "analyze.hpp"
10#include "c_tokenizer.hpp"9#include "c_tokenizer.hpp"
...@@ -13,7 +12,7 @@...@@ -13,7 +12,7 @@
13#include "os.hpp"12#include "os.hpp"
14#include "translate_c.hpp"13#include "translate_c.hpp"
15#include "parser.hpp"14#include "parser.hpp"
1615#include "zig_clang.h"
1716
18#if __GNUC__ >= 817#if __GNUC__ >= 8
19#pragma GCC diagnostic push18#pragma GCC diagnostic push
...@@ -30,8 +29,6 @@...@@ -30,8 +29,6 @@
3029
31#include <string.h>30#include <string.h>
3231
33using namespace clang;
34
35struct Alias {32struct Alias {
36 Buf *new_name;33 Buf *new_name;
37 Buf *canon_name;34 Buf *canon_name;
...@@ -87,13 +84,13 @@ struct Context {...@@ -87,13 +84,13 @@ struct Context {
87 HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;84 HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;
88 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;85 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
89 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;86 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;
90 SourceManager *source_manager;87 ZigClangSourceManager *source_manager;
91 ZigList<Alias> aliases;88 ZigList<Alias> aliases;
92 AstNode *source_node;89 AstNode *source_node;
93 bool warnings_on;90 bool warnings_on;
9491
95 CodeGen *codegen;92 CodeGen *codegen;
96 ASTContext *ctx;93 ZigClangASTContext *ctx;
9794
98 TransScopeRoot *global_scope;95 TransScopeRoot *global_scope;
99 HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params;96 HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params;
...@@ -117,21 +114,37 @@ static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *paren...@@ -117,21 +114,37 @@ static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *paren
117114
118static TransScopeBlock *trans_scope_block_find(TransScope *scope);115static TransScopeBlock *trans_scope_block_find(TransScope *scope);
119116
120static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl);117static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl);
121static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl);118static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl);
122static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl);119static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl);
123120
124static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,121static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *stmt,
125 ResultUsed result_used, TransLRValue lrval,122 ResultUsed result_used, TransLRValue lrval,
126 AstNode **out_node, TransScope **out_child_scope,123 AstNode **out_node, TransScope **out_child_scope,
127 TransScope **out_node_scope);124 TransScope **out_node_scope);
128static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node);125static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node);
129static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);126static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval);
130static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);127static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc);
131static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);128static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval);
129
130static ZigClangSourceLocation bitcast(clang::SourceLocation src) {
131 ZigClangSourceLocation dest;
132 memcpy(&dest, &src, sizeof(ZigClangSourceLocation));
133 return dest;
134}
135static ZigClangQualType bitcast(clang::QualType src) {
136 ZigClangQualType dest;
137 memcpy(&dest, &src, sizeof(ZigClangQualType));
138 return dest;
139}
140static clang::QualType bitcast(ZigClangQualType src) {
141 clang::QualType dest;
142 memcpy(&dest, &src, sizeof(ZigClangQualType));
143 return dest;
144}
132145
133ATTRIBUTE_PRINTF(3, 4)146ATTRIBUTE_PRINTF(3, 4)
134static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) {147static void emit_warning(Context *c, const clang::SourceLocation &clang_sl, const char *format, ...) {
135 if (!c->warnings_on) {148 if (!c->warnings_on) {
136 return;149 return;
137 }150 }
...@@ -141,16 +154,17 @@ static void emit_warning(Context *c, const SourceLocation &sl, const char *forma...@@ -141,16 +154,17 @@ static void emit_warning(Context *c, const SourceLocation &sl, const char *forma
141 Buf *msg = buf_vprintf(format, ap);154 Buf *msg = buf_vprintf(format, ap);
142 va_end(ap);155 va_end(ap);
143156
144 StringRef filename = c->source_manager->getFilename(c->source_manager->getSpellingLoc(sl));157 ZigClangSourceLocation sl = bitcast(clang_sl);
145 const char *filename_bytes = (const char *)filename.bytes_begin();158 const char *filename_bytes = ZigClangSourceManager_getFilename(c->source_manager,
159 ZigClangSourceManager_getSpellingLoc(c->source_manager, sl));
146 Buf *path;160 Buf *path;
147 if (filename_bytes) {161 if (filename_bytes) {
148 path = buf_create_from_str(filename_bytes);162 path = buf_create_from_str(filename_bytes);
149 } else {163 } else {
150 path = buf_sprintf("(no file)");164 path = buf_sprintf("(no file)");
151 }165 }
152 unsigned line = c->source_manager->getSpellingLineNumber(sl);166 unsigned line = ZigClangSourceManager_getSpellingLineNumber(c->source_manager, sl);
153 unsigned column = c->source_manager->getSpellingColumnNumber(sl);167 unsigned column = ZigClangSourceManager_getSpellingColumnNumber(c->source_manager, sl);
154 fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg));168 fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg));
155}169}
156170
...@@ -291,11 +305,22 @@ static AstNode *maybe_suppress_result(Context *c, ResultUsed result_used, AstNod...@@ -291,11 +305,22 @@ static AstNode *maybe_suppress_result(Context *c, ResultUsed result_used, AstNod
291 node);305 node);
292}306}
293307
308static TokenId ptr_len_to_token_id(PtrLen ptr_len) {
309 switch (ptr_len) {
310 case PtrLenSingle:
311 return TokenIdStar;
312 case PtrLenUnknown:
313 return TokenIdBracketStarBracket;
314 case PtrLenC:
315 return TokenIdBracketStarCBracket;
316 }
317 zig_unreachable();
318}
319
294static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_volatile, AstNode *child_node, PtrLen ptr_len) {320static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_volatile, AstNode *child_node, PtrLen ptr_len) {
295 AstNode *node = trans_create_node(c, NodeTypePointerType);321 AstNode *node = trans_create_node(c, NodeTypePointerType);
296 node->data.pointer_type.star_token = allocate<ZigToken>(1);322 node->data.pointer_type.star_token = allocate<ZigToken>(1);
297 node->data.pointer_type.star_token->id = (ptr_len == PtrLenSingle) ? TokenIdStar: TokenIdBracketStarBracket;323 node->data.pointer_type.star_token->id = ptr_len_to_token_id(ptr_len);
298 node->data.pointer_type.is_const = is_const;
299 node->data.pointer_type.is_const = is_const;324 node->data.pointer_type.is_const = is_const;
300 node->data.pointer_type.is_volatile = is_volatile;325 node->data.pointer_type.is_volatile = is_volatile;
301 node->data.pointer_type.op_expr = child_node;326 node->data.pointer_type.op_expr = child_node;
...@@ -460,15 +485,15 @@ static Buf *string_ref_to_buf(StringRef string_ref) {...@@ -460,15 +485,15 @@ static Buf *string_ref_to_buf(StringRef string_ref) {
460 return buf_create_from_mem((const char *)string_ref.bytes_begin(), string_ref.size());485 return buf_create_from_mem((const char *)string_ref.bytes_begin(), string_ref.size());
461}486}
462487
463static const char *decl_name(const Decl *decl) {488static const char *decl_name(const clang::Decl *decl) {
464 const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl);489 const clang::NamedDecl *named_decl = static_cast<const clang::NamedDecl *>(decl);
465 return (const char *)named_decl->getName().bytes_begin();490 return (const char *)named_decl->getName().bytes_begin();
466}491}
467492
468static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) {493static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) {
469 AstNode *node = trans_create_node(c, NodeTypeIntLiteral);494 AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
470 node->data.int_literal.bigint = allocate<BigInt>(1);495 node->data.int_literal.bigint = allocate<BigInt>(1);
471 bool is_negative = aps_int.isNegative(); 496 bool is_negative = aps_int.isSigned() && aps_int.isNegative();
472 if (!is_negative) {497 if (!is_negative) {
473 bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), false);498 bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), false);
474 return node;499 return node;
...@@ -479,41 +504,41 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int)...@@ -479,41 +504,41 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int)
479504
480}505}
481506
482static const Type *qual_type_canon(QualType qt) {507static const clang::Type *qual_type_canon(clang::QualType qt) {
483 return qt.getCanonicalType().getTypePtr();508 return qt.getCanonicalType().getTypePtr();
484}509}
485510
486static QualType get_expr_qual_type(Context *c, const Expr *expr) {511static clang::QualType get_expr_qual_type(Context *c, const clang::Expr *expr) {
487 // String literals in C are `char *` but they should really be `const char *`.512 // String literals in C are `char *` but they should really be `const char *`.
488 if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) {513 if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
489 const ImplicitCastExpr *cast_expr = static_cast<const ImplicitCastExpr *>(expr);514 const clang::ImplicitCastExpr *cast_expr = static_cast<const clang::ImplicitCastExpr *>(expr);
490 if (cast_expr->getCastKind() == CK_ArrayToPointerDecay) {515 if (cast_expr->getCastKind() == clang::CK_ArrayToPointerDecay) {
491 const Expr *sub_expr = cast_expr->getSubExpr();516 const clang::Expr *sub_expr = cast_expr->getSubExpr();
492 if (sub_expr->getStmtClass() == Stmt::StringLiteralClass) {517 if (sub_expr->getStmtClass() == clang::Stmt::StringLiteralClass) {
493 QualType array_qt = sub_expr->getType();518 clang::QualType array_qt = sub_expr->getType();
494 const ArrayType *array_type = static_cast<const ArrayType *>(array_qt.getTypePtr());519 const clang::ArrayType *array_type = static_cast<const clang::ArrayType *>(array_qt.getTypePtr());
495 QualType pointee_qt = array_type->getElementType();520 clang::QualType pointee_qt = array_type->getElementType();
496 pointee_qt.addConst();521 pointee_qt.addConst();
497 return c->ctx->getPointerType(pointee_qt);522 return bitcast(ZigClangASTContext_getPointerType(c->ctx, bitcast(pointee_qt)));
498 }523 }
499 }524 }
500 }525 }
501 return expr->getType();526 return expr->getType();
502}527}
503528
504static QualType get_expr_qual_type_before_implicit_cast(Context *c, const Expr *expr) {529static clang::QualType get_expr_qual_type_before_implicit_cast(Context *c, const clang::Expr *expr) {
505 if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) {530 if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
506 const ImplicitCastExpr *cast_expr = static_cast<const ImplicitCastExpr *>(expr);531 const clang::ImplicitCastExpr *cast_expr = static_cast<const clang::ImplicitCastExpr *>(expr);
507 return get_expr_qual_type(c, cast_expr->getSubExpr());532 return get_expr_qual_type(c, cast_expr->getSubExpr());
508 }533 }
509 return expr->getType();534 return expr->getType();
510}535}
511536
512static AstNode *get_expr_type(Context *c, const Expr *expr) {537static AstNode *get_expr_type(Context *c, const clang::Expr *expr) {
513 return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getLocStart());538 return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getLocStart());
514}539}
515540
516static bool qual_types_equal(QualType t1, QualType t2) {541static bool qual_types_equal(clang::QualType t1, clang::QualType t2) {
517 if (t1.isConstQualified() != t2.isConstQualified()) {542 if (t1.isConstQualified() != t2.isConstQualified()) {
518 return false;543 return false;
519 }544 }
...@@ -530,37 +555,37 @@ static bool is_c_void_type(AstNode *node) {...@@ -530,37 +555,37 @@ static bool is_c_void_type(AstNode *node) {
530 return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));555 return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));
531}556}
532557
533static bool expr_types_equal(Context *c, const Expr *expr1, const Expr *expr2) {558static bool expr_types_equal(Context *c, const clang::Expr *expr1, const clang::Expr *expr2) {
534 QualType t1 = get_expr_qual_type(c, expr1);559 clang::QualType t1 = get_expr_qual_type(c, expr1);
535 QualType t2 = get_expr_qual_type(c, expr2);560 clang::QualType t2 = get_expr_qual_type(c, expr2);
536561
537 return qual_types_equal(t1, t2);562 return qual_types_equal(t1, t2);
538}563}
539564
540static bool qual_type_is_ptr(QualType qt) {565static bool qual_type_is_ptr(clang::QualType qt) {
541 const Type *ty = qual_type_canon(qt);566 const clang::Type *ty = qual_type_canon(qt);
542 return ty->getTypeClass() == Type::Pointer;567 return ty->getTypeClass() == clang::Type::Pointer;
543}568}
544569
545static const FunctionProtoType *qual_type_get_fn_proto(QualType qt, bool *is_ptr) {570static const clang::FunctionProtoType *qual_type_get_fn_proto(clang::QualType qt, bool *is_ptr) {
546 const Type *ty = qual_type_canon(qt);571 const clang::Type *ty = qual_type_canon(qt);
547 *is_ptr = false;572 *is_ptr = false;
548573
549 if (ty->getTypeClass() == Type::Pointer) {574 if (ty->getTypeClass() == clang::Type::Pointer) {
550 *is_ptr = true;575 *is_ptr = true;
551 const PointerType *pointer_ty = static_cast<const PointerType*>(ty);576 const clang::PointerType *pointer_ty = static_cast<const clang::PointerType*>(ty);
552 QualType child_qt = pointer_ty->getPointeeType();577 clang::QualType child_qt = pointer_ty->getPointeeType();
553 ty = child_qt.getTypePtr();578 ty = child_qt.getTypePtr();
554 }579 }
555580
556 if (ty->getTypeClass() == Type::FunctionProto) {581 if (ty->getTypeClass() == clang::Type::FunctionProto) {
557 return static_cast<const FunctionProtoType*>(ty);582 return static_cast<const clang::FunctionProtoType*>(ty);
558 }583 }
559584
560 return nullptr;585 return nullptr;
561}586}
562587
563static bool qual_type_is_fn_ptr(QualType qt) {588static bool qual_type_is_fn_ptr(clang::QualType qt) {
564 bool is_ptr;589 bool is_ptr;
565 if (qual_type_get_fn_proto(qt, &is_ptr)) {590 if (qual_type_get_fn_proto(qt, &is_ptr)) {
566 return is_ptr;591 return is_ptr;
...@@ -569,30 +594,30 @@ static bool qual_type_is_fn_ptr(QualType qt) {...@@ -569,30 +594,30 @@ static bool qual_type_is_fn_ptr(QualType qt) {
569 return false;594 return false;
570}595}
571596
572static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) {597static uint32_t qual_type_int_bit_width(Context *c, const clang::QualType &qt, const clang::SourceLocation &source_loc) {
573 const Type *ty = qt.getTypePtr();598 const clang::Type *ty = qt.getTypePtr();
574 switch (ty->getTypeClass()) {599 switch (ty->getTypeClass()) {
575 case Type::Builtin:600 case clang::Type::Builtin:
576 {601 {
577 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);602 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);
578 switch (builtin_ty->getKind()) {603 switch (builtin_ty->getKind()) {
579 case BuiltinType::Char_U:604 case clang::BuiltinType::Char_U:
580 case BuiltinType::UChar:605 case clang::BuiltinType::UChar:
581 case BuiltinType::Char_S:606 case clang::BuiltinType::Char_S:
582 case BuiltinType::SChar:607 case clang::BuiltinType::SChar:
583 return 8;608 return 8;
584 case BuiltinType::UInt128:609 case clang::BuiltinType::UInt128:
585 case BuiltinType::Int128:610 case clang::BuiltinType::Int128:
586 return 128;611 return 128;
587 default:612 default:
588 return 0;613 return 0;
589 }614 }
590 zig_unreachable();615 zig_unreachable();
591 }616 }
592 case Type::Typedef:617 case clang::Type::Typedef:
593 {618 {
594 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);619 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
595 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();620 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
596 const char *type_name = decl_name(typedef_decl);621 const char *type_name = decl_name(typedef_decl);
597 if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) {622 if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) {
598 return 8;623 return 8;
...@@ -613,8 +638,8 @@ static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const So...@@ -613,8 +638,8 @@ static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const So
613}638}
614639
615640
616static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,641static AstNode *qual_type_to_log2_int_ref(Context *c, const clang::QualType &qt,
617 const SourceLocation &source_loc)642 const clang::SourceLocation &source_loc)
618{643{
619 uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc);644 uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc);
620 if (int_bit_width != 0) {645 if (int_bit_width != 0) {
...@@ -632,7 +657,7 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,...@@ -632,7 +657,7 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
632// FieldAccess657// FieldAccess
633// FnCall (.builtin = true)658// FnCall (.builtin = true)
634// Symbol "import"659// Symbol "import"
635// StringLiteral "std"660// clang::StringLiteral "std"
636// Symbol "math"661// Symbol "math"
637// Symbol "Log2Int"662// Symbol "Log2Int"
638// zig_type_node663// zig_type_node
...@@ -646,21 +671,21 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,...@@ -646,21 +671,21 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
646 return log2int_fn_call;671 return log2int_fn_call;
647}672}
648673
649static bool qual_type_child_is_fn_proto(const QualType &qt) {674static bool qual_type_child_is_fn_proto(const clang::QualType &qt) {
650 if (qt.getTypePtr()->getTypeClass() == Type::Paren) {675 if (qt.getTypePtr()->getTypeClass() == clang::Type::Paren) {
651 const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr());676 const clang::ParenType *paren_type = static_cast<const clang::ParenType *>(qt.getTypePtr());
652 if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) {677 if (paren_type->getInnerType()->getTypeClass() == clang::Type::FunctionProto) {
653 return true;678 return true;
654 }679 }
655 } else if (qt.getTypePtr()->getTypeClass() == Type::Attributed) {680 } else if (qt.getTypePtr()->getTypeClass() == clang::Type::Attributed) {
656 const AttributedType *attr_type = static_cast<const AttributedType *>(qt.getTypePtr());681 const clang::AttributedType *attr_type = static_cast<const clang::AttributedType *>(qt.getTypePtr());
657 return qual_type_child_is_fn_proto(attr_type->getEquivalentType());682 return qual_type_child_is_fn_proto(attr_type->getEquivalentType());
658 }683 }
659 return false;684 return false;
660}685}
661686
662static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, QualType dest_type,687static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_location, clang::QualType dest_type,
663 QualType src_type, AstNode *expr)688 clang::QualType src_type, AstNode *expr)
664{689{
665 if (qual_types_equal(dest_type, src_type)) {690 if (qual_types_equal(dest_type, src_type)) {
666 return expr;691 return expr;
...@@ -677,72 +702,72 @@ static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location,...@@ -677,72 +702,72 @@ static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location,
677 return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr);702 return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr);
678}703}
679704
680static bool c_is_signed_integer(Context *c, QualType qt) {705static bool c_is_signed_integer(Context *c, clang::QualType qt) {
681 const Type *c_type = qual_type_canon(qt);706 const clang::Type *c_type = qual_type_canon(qt);
682 if (c_type->getTypeClass() != Type::Builtin)707 if (c_type->getTypeClass() != clang::Type::Builtin)
683 return false;708 return false;
684 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);709 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type);
685 switch (builtin_ty->getKind()) {710 switch (builtin_ty->getKind()) {
686 case BuiltinType::SChar:711 case clang::BuiltinType::SChar:
687 case BuiltinType::Short:712 case clang::BuiltinType::Short:
688 case BuiltinType::Int:713 case clang::BuiltinType::Int:
689 case BuiltinType::Long:714 case clang::BuiltinType::Long:
690 case BuiltinType::LongLong:715 case clang::BuiltinType::LongLong:
691 case BuiltinType::Int128:716 case clang::BuiltinType::Int128:
692 case BuiltinType::WChar_S:717 case clang::BuiltinType::WChar_S:
693 return true;718 return true;
694 default:719 default:
695 return false;720 return false;
696 }721 }
697}722}
698723
699static bool c_is_unsigned_integer(Context *c, QualType qt) {724static bool c_is_unsigned_integer(Context *c, clang::QualType qt) {
700 const Type *c_type = qual_type_canon(qt);725 const clang::Type *c_type = qual_type_canon(qt);
701 if (c_type->getTypeClass() != Type::Builtin)726 if (c_type->getTypeClass() != clang::Type::Builtin)
702 return false;727 return false;
703 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);728 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type);
704 switch (builtin_ty->getKind()) {729 switch (builtin_ty->getKind()) {
705 case BuiltinType::Char_U:730 case clang::BuiltinType::Char_U:
706 case BuiltinType::UChar:731 case clang::BuiltinType::UChar:
707 case BuiltinType::Char_S:732 case clang::BuiltinType::Char_S:
708 case BuiltinType::UShort:733 case clang::BuiltinType::UShort:
709 case BuiltinType::UInt:734 case clang::BuiltinType::UInt:
710 case BuiltinType::ULong:735 case clang::BuiltinType::ULong:
711 case BuiltinType::ULongLong:736 case clang::BuiltinType::ULongLong:
712 case BuiltinType::UInt128:737 case clang::BuiltinType::UInt128:
713 case BuiltinType::WChar_U:738 case clang::BuiltinType::WChar_U:
714 return true;739 return true;
715 default:740 default:
716 return false;741 return false;
717 }742 }
718}743}
719744
720static bool c_is_builtin_type(Context *c, QualType qt, BuiltinType::Kind kind) {745static bool c_is_builtin_type(Context *c, clang::QualType qt, clang::BuiltinType::Kind kind) {
721 const Type *c_type = qual_type_canon(qt);746 const clang::Type *c_type = qual_type_canon(qt);
722 if (c_type->getTypeClass() != Type::Builtin)747 if (c_type->getTypeClass() != clang::Type::Builtin)
723 return false;748 return false;
724 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);749 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type);
725 return builtin_ty->getKind() == kind;750 return builtin_ty->getKind() == kind;
726}751}
727752
728static bool c_is_float(Context *c, QualType qt) {753static bool c_is_float(Context *c, clang::QualType qt) {
729 const Type *c_type = qt.getTypePtr();754 const clang::Type *c_type = qt.getTypePtr();
730 if (c_type->getTypeClass() != Type::Builtin)755 if (c_type->getTypeClass() != clang::Type::Builtin)
731 return false;756 return false;
732 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);757 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(c_type);
733 switch (builtin_ty->getKind()) {758 switch (builtin_ty->getKind()) {
734 case BuiltinType::Half:759 case clang::BuiltinType::Half:
735 case BuiltinType::Float:760 case clang::BuiltinType::Float:
736 case BuiltinType::Double:761 case clang::BuiltinType::Double:
737 case BuiltinType::Float128:762 case clang::BuiltinType::Float128:
738 case BuiltinType::LongDouble:763 case clang::BuiltinType::LongDouble:
739 return true;764 return true;
740 default:765 default:
741 return false;766 return false;
742 }767 }
743}768}
744769
745static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {770static bool qual_type_has_wrapping_overflow(Context *c, clang::QualType qt) {
746 if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) {771 if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) {
747 // float and signed integer overflow is undefined behavior.772 // float and signed integer overflow is undefined behavior.
748 return false;773 return false;
...@@ -752,23 +777,23 @@ static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {...@@ -752,23 +777,23 @@ static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
752 }777 }
753}778}
754779
755static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &source_loc) {780static bool type_is_opaque(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) {
756 switch (ty->getTypeClass()) {781 switch (ty->getTypeClass()) {
757 case Type::Builtin: {782 case clang::Type::Builtin: {
758 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);783 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);
759 return builtin_ty->getKind() == BuiltinType::Void;784 return builtin_ty->getKind() == clang::BuiltinType::Void;
760 }785 }
761 case Type::Record: {786 case clang::Type::Record: {
762 const RecordType *record_ty = static_cast<const RecordType*>(ty);787 const clang::RecordType *record_ty = static_cast<const clang::RecordType*>(ty);
763 return record_ty->getDecl()->getDefinition() == nullptr;788 return record_ty->getDecl()->getDefinition() == nullptr;
764 }789 }
765 case Type::Elaborated: {790 case clang::Type::Elaborated: {
766 const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);791 const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty);
767 return type_is_opaque(c, elaborated_ty->getNamedType().getTypePtr(), source_loc);792 return type_is_opaque(c, elaborated_ty->getNamedType().getTypePtr(), source_loc);
768 }793 }
769 case Type::Typedef: {794 case clang::Type::Typedef: {
770 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);795 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
771 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();796 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
772 return type_is_opaque(c, typedef_decl->getUnderlyingType().getTypePtr(), source_loc);797 return type_is_opaque(c, typedef_decl->getUnderlyingType().getTypePtr(), source_loc);
773 }798 }
774 default:799 default:
...@@ -776,145 +801,145 @@ static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &sou...@@ -776,145 +801,145 @@ static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &sou
776 }801 }
777}802}
778803
779static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) {804static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) {
780 switch (ty->getTypeClass()) {805 switch (ty->getTypeClass()) {
781 case Type::Builtin:806 case clang::Type::Builtin:
782 {807 {
783 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);808 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);
784 switch (builtin_ty->getKind()) {809 switch (builtin_ty->getKind()) {
785 case BuiltinType::Void:810 case clang::BuiltinType::Void:
786 return trans_create_node_symbol_str(c, "c_void");811 return trans_create_node_symbol_str(c, "c_void");
787 case BuiltinType::Bool:812 case clang::BuiltinType::Bool:
788 return trans_create_node_symbol_str(c, "bool");813 return trans_create_node_symbol_str(c, "bool");
789 case BuiltinType::Char_U:814 case clang::BuiltinType::Char_U:
790 case BuiltinType::UChar:815 case clang::BuiltinType::UChar:
791 case BuiltinType::Char_S:816 case clang::BuiltinType::Char_S:
792 case BuiltinType::Char8:817 case clang::BuiltinType::Char8:
793 return trans_create_node_symbol_str(c, "u8");818 return trans_create_node_symbol_str(c, "u8");
794 case BuiltinType::SChar:819 case clang::BuiltinType::SChar:
795 return trans_create_node_symbol_str(c, "i8");820 return trans_create_node_symbol_str(c, "i8");
796 case BuiltinType::UShort:821 case clang::BuiltinType::UShort:
797 return trans_create_node_symbol_str(c, "c_ushort");822 return trans_create_node_symbol_str(c, "c_ushort");
798 case BuiltinType::UInt:823 case clang::BuiltinType::UInt:
799 return trans_create_node_symbol_str(c, "c_uint");824 return trans_create_node_symbol_str(c, "c_uint");
800 case BuiltinType::ULong:825 case clang::BuiltinType::ULong:
801 return trans_create_node_symbol_str(c, "c_ulong");826 return trans_create_node_symbol_str(c, "c_ulong");
802 case BuiltinType::ULongLong:827 case clang::BuiltinType::ULongLong:
803 return trans_create_node_symbol_str(c, "c_ulonglong");828 return trans_create_node_symbol_str(c, "c_ulonglong");
804 case BuiltinType::Short:829 case clang::BuiltinType::Short:
805 return trans_create_node_symbol_str(c, "c_short");830 return trans_create_node_symbol_str(c, "c_short");
806 case BuiltinType::Int:831 case clang::BuiltinType::Int:
807 return trans_create_node_symbol_str(c, "c_int");832 return trans_create_node_symbol_str(c, "c_int");
808 case BuiltinType::Long:833 case clang::BuiltinType::Long:
809 return trans_create_node_symbol_str(c, "c_long");834 return trans_create_node_symbol_str(c, "c_long");
810 case BuiltinType::LongLong:835 case clang::BuiltinType::LongLong:
811 return trans_create_node_symbol_str(c, "c_longlong");836 return trans_create_node_symbol_str(c, "c_longlong");
812 case BuiltinType::UInt128:837 case clang::BuiltinType::UInt128:
813 return trans_create_node_symbol_str(c, "u128");838 return trans_create_node_symbol_str(c, "u128");
814 case BuiltinType::Int128:839 case clang::BuiltinType::Int128:
815 return trans_create_node_symbol_str(c, "i128");840 return trans_create_node_symbol_str(c, "i128");
816 case BuiltinType::Float:841 case clang::BuiltinType::Float:
817 return trans_create_node_symbol_str(c, "f32");842 return trans_create_node_symbol_str(c, "f32");
818 case BuiltinType::Double:843 case clang::BuiltinType::Double:
819 return trans_create_node_symbol_str(c, "f64");844 return trans_create_node_symbol_str(c, "f64");
820 case BuiltinType::Float128:845 case clang::BuiltinType::Float128:
821 return trans_create_node_symbol_str(c, "f128");846 return trans_create_node_symbol_str(c, "f128");
822 case BuiltinType::Float16:847 case clang::BuiltinType::Float16:
823 return trans_create_node_symbol_str(c, "f16");848 return trans_create_node_symbol_str(c, "f16");
824 case BuiltinType::LongDouble:849 case clang::BuiltinType::LongDouble:
825 return trans_create_node_symbol_str(c, "c_longdouble");850 return trans_create_node_symbol_str(c, "c_longdouble");
826 case BuiltinType::WChar_U:851 case clang::BuiltinType::WChar_U:
827 case BuiltinType::Char16:852 case clang::BuiltinType::Char16:
828 case BuiltinType::Char32:853 case clang::BuiltinType::Char32:
829 case BuiltinType::WChar_S:854 case clang::BuiltinType::WChar_S:
830 case BuiltinType::Half:855 case clang::BuiltinType::Half:
831 case BuiltinType::NullPtr:856 case clang::BuiltinType::NullPtr:
832 case BuiltinType::ObjCId:857 case clang::BuiltinType::ObjCId:
833 case BuiltinType::ObjCClass:858 case clang::BuiltinType::ObjCClass:
834 case BuiltinType::ObjCSel:859 case clang::BuiltinType::ObjCSel:
835 case BuiltinType::OMPArraySection:860 case clang::BuiltinType::OMPArraySection:
836 case BuiltinType::Dependent:861 case clang::BuiltinType::Dependent:
837 case BuiltinType::Overload:862 case clang::BuiltinType::Overload:
838 case BuiltinType::BoundMember:863 case clang::BuiltinType::BoundMember:
839 case BuiltinType::PseudoObject:864 case clang::BuiltinType::PseudoObject:
840 case BuiltinType::UnknownAny:865 case clang::BuiltinType::UnknownAny:
841 case BuiltinType::BuiltinFn:866 case clang::BuiltinType::BuiltinFn:
842 case BuiltinType::ARCUnbridgedCast:867 case clang::BuiltinType::ARCUnbridgedCast:
843 case BuiltinType::ShortAccum:868 case clang::BuiltinType::ShortAccum:
844 case BuiltinType::Accum:869 case clang::BuiltinType::Accum:
845 case BuiltinType::LongAccum:870 case clang::BuiltinType::LongAccum:
846 case BuiltinType::UShortAccum:871 case clang::BuiltinType::UShortAccum:
847 case BuiltinType::UAccum:872 case clang::BuiltinType::UAccum:
848 case BuiltinType::ULongAccum:873 case clang::BuiltinType::ULongAccum:
849874
850 case BuiltinType::OCLImage1dRO:875 case clang::BuiltinType::OCLImage1dRO:
851 case BuiltinType::OCLImage1dArrayRO:876 case clang::BuiltinType::OCLImage1dArrayRO:
852 case BuiltinType::OCLImage1dBufferRO:877 case clang::BuiltinType::OCLImage1dBufferRO:
853 case BuiltinType::OCLImage2dRO:878 case clang::BuiltinType::OCLImage2dRO:
854 case BuiltinType::OCLImage2dArrayRO:879 case clang::BuiltinType::OCLImage2dArrayRO:
855 case BuiltinType::OCLImage2dDepthRO:880 case clang::BuiltinType::OCLImage2dDepthRO:
856 case BuiltinType::OCLImage2dArrayDepthRO:881 case clang::BuiltinType::OCLImage2dArrayDepthRO:
857 case BuiltinType::OCLImage2dMSAARO:882 case clang::BuiltinType::OCLImage2dMSAARO:
858 case BuiltinType::OCLImage2dArrayMSAARO:883 case clang::BuiltinType::OCLImage2dArrayMSAARO:
859 case BuiltinType::OCLImage2dMSAADepthRO:884 case clang::BuiltinType::OCLImage2dMSAADepthRO:
860 case BuiltinType::OCLImage2dArrayMSAADepthRO:885 case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:
861 case BuiltinType::OCLImage3dRO:886 case clang::BuiltinType::OCLImage3dRO:
862 case BuiltinType::OCLImage1dWO:887 case clang::BuiltinType::OCLImage1dWO:
863 case BuiltinType::OCLImage1dArrayWO:888 case clang::BuiltinType::OCLImage1dArrayWO:
864 case BuiltinType::OCLImage1dBufferWO:889 case clang::BuiltinType::OCLImage1dBufferWO:
865 case BuiltinType::OCLImage2dWO:890 case clang::BuiltinType::OCLImage2dWO:
866 case BuiltinType::OCLImage2dArrayWO:891 case clang::BuiltinType::OCLImage2dArrayWO:
867 case BuiltinType::OCLImage2dDepthWO:892 case clang::BuiltinType::OCLImage2dDepthWO:
868 case BuiltinType::OCLImage2dArrayDepthWO:893 case clang::BuiltinType::OCLImage2dArrayDepthWO:
869 case BuiltinType::OCLImage2dMSAAWO:894 case clang::BuiltinType::OCLImage2dMSAAWO:
870 case BuiltinType::OCLImage2dArrayMSAAWO:895 case clang::BuiltinType::OCLImage2dArrayMSAAWO:
871 case BuiltinType::OCLImage2dMSAADepthWO:896 case clang::BuiltinType::OCLImage2dMSAADepthWO:
872 case BuiltinType::OCLImage2dArrayMSAADepthWO:897 case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:
873 case BuiltinType::OCLImage3dWO:898 case clang::BuiltinType::OCLImage3dWO:
874 case BuiltinType::OCLImage1dRW:899 case clang::BuiltinType::OCLImage1dRW:
875 case BuiltinType::OCLImage1dArrayRW:900 case clang::BuiltinType::OCLImage1dArrayRW:
876 case BuiltinType::OCLImage1dBufferRW:901 case clang::BuiltinType::OCLImage1dBufferRW:
877 case BuiltinType::OCLImage2dRW:902 case clang::BuiltinType::OCLImage2dRW:
878 case BuiltinType::OCLImage2dArrayRW:903 case clang::BuiltinType::OCLImage2dArrayRW:
879 case BuiltinType::OCLImage2dDepthRW:904 case clang::BuiltinType::OCLImage2dDepthRW:
880 case BuiltinType::OCLImage2dArrayDepthRW:905 case clang::BuiltinType::OCLImage2dArrayDepthRW:
881 case BuiltinType::OCLImage2dMSAARW:906 case clang::BuiltinType::OCLImage2dMSAARW:
882 case BuiltinType::OCLImage2dArrayMSAARW:907 case clang::BuiltinType::OCLImage2dArrayMSAARW:
883 case BuiltinType::OCLImage2dMSAADepthRW:908 case clang::BuiltinType::OCLImage2dMSAADepthRW:
884 case BuiltinType::OCLImage2dArrayMSAADepthRW:909 case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:
885 case BuiltinType::OCLImage3dRW:910 case clang::BuiltinType::OCLImage3dRW:
886 case BuiltinType::OCLSampler:911 case clang::BuiltinType::OCLSampler:
887 case BuiltinType::OCLEvent:912 case clang::BuiltinType::OCLEvent:
888 case BuiltinType::OCLClkEvent:913 case clang::BuiltinType::OCLClkEvent:
889 case BuiltinType::OCLQueue:914 case clang::BuiltinType::OCLQueue:
890 case BuiltinType::OCLReserveID:915 case clang::BuiltinType::OCLReserveID:
891 case BuiltinType::ShortFract:916 case clang::BuiltinType::ShortFract:
892 case BuiltinType::Fract:917 case clang::BuiltinType::Fract:
893 case BuiltinType::LongFract:918 case clang::BuiltinType::LongFract:
894 case BuiltinType::UShortFract:919 case clang::BuiltinType::UShortFract:
895 case BuiltinType::UFract:920 case clang::BuiltinType::UFract:
896 case BuiltinType::ULongFract:921 case clang::BuiltinType::ULongFract:
897 case BuiltinType::SatShortAccum:922 case clang::BuiltinType::SatShortAccum:
898 case BuiltinType::SatAccum:923 case clang::BuiltinType::SatAccum:
899 case BuiltinType::SatLongAccum:924 case clang::BuiltinType::SatLongAccum:
900 case BuiltinType::SatUShortAccum:925 case clang::BuiltinType::SatUShortAccum:
901 case BuiltinType::SatUAccum:926 case clang::BuiltinType::SatUAccum:
902 case BuiltinType::SatULongAccum:927 case clang::BuiltinType::SatULongAccum:
903 case BuiltinType::SatShortFract:928 case clang::BuiltinType::SatShortFract:
904 case BuiltinType::SatFract:929 case clang::BuiltinType::SatFract:
905 case BuiltinType::SatLongFract:930 case clang::BuiltinType::SatLongFract:
906 case BuiltinType::SatUShortFract:931 case clang::BuiltinType::SatUShortFract:
907 case BuiltinType::SatUFract:932 case clang::BuiltinType::SatUFract:
908 case BuiltinType::SatULongFract:933 case clang::BuiltinType::SatULongFract:
909 emit_warning(c, source_loc, "unsupported builtin type");934 emit_warning(c, source_loc, "unsupported builtin type");
910 return nullptr;935 return nullptr;
911 }936 }
912 break;937 break;
913 }938 }
914 case Type::Pointer:939 case clang::Type::Pointer:
915 {940 {
916 const PointerType *pointer_ty = static_cast<const PointerType*>(ty);941 const clang::PointerType *pointer_ty = static_cast<const clang::PointerType*>(ty);
917 QualType child_qt = pointer_ty->getPointeeType();942 clang::QualType child_qt = pointer_ty->getPointeeType();
918 AstNode *child_node = trans_qual_type(c, child_qt, source_loc);943 AstNode *child_node = trans_qual_type(c, child_qt, source_loc);
919 if (child_node == nullptr) {944 if (child_node == nullptr) {
920 emit_warning(c, source_loc, "pointer to unsupported type");945 emit_warning(c, source_loc, "pointer to unsupported type");
...@@ -925,90 +950,93 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou...@@ -925,90 +950,93 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
925 return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);950 return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
926 }951 }
927952
928 PtrLen ptr_len = type_is_opaque(c, child_qt.getTypePtr(), source_loc) ? PtrLenSingle : PtrLenUnknown;953 if (type_is_opaque(c, child_qt.getTypePtr(), source_loc)) {
929954 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
930 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),955 child_qt.isVolatileQualified(), child_node, PtrLenSingle);
931 child_qt.isVolatileQualified(), child_node, ptr_len);956 return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);
932 return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);957 } else {
958 return trans_create_node_ptr_type(c, child_qt.isConstQualified(),
959 child_qt.isVolatileQualified(), child_node, PtrLenC);
960 }
933 }961 }
934 case Type::Typedef:962 case clang::Type::Typedef:
935 {963 {
936 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);964 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
937 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();965 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
938 return resolve_typedef_decl(c, typedef_decl);966 return resolve_typedef_decl(c, typedef_decl);
939 }967 }
940 case Type::Elaborated:968 case clang::Type::Elaborated:
941 {969 {
942 const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);970 const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty);
943 switch (elaborated_ty->getKeyword()) {971 switch (elaborated_ty->getKeyword()) {
944 case ETK_Struct:972 case clang::ETK_Struct:
945 case ETK_Enum:973 case clang::ETK_Enum:
946 case ETK_Union:974 case clang::ETK_Union:
947 return trans_qual_type(c, elaborated_ty->getNamedType(), source_loc);975 return trans_qual_type(c, elaborated_ty->getNamedType(), source_loc);
948 case ETK_Interface:976 case clang::ETK_Interface:
949 case ETK_Class:977 case clang::ETK_Class:
950 case ETK_Typename:978 case clang::ETK_Typename:
951 case ETK_None:979 case clang::ETK_None:
952 emit_warning(c, source_loc, "unsupported elaborated type");980 emit_warning(c, source_loc, "unsupported elaborated type");
953 return nullptr;981 return nullptr;
954 }982 }
955 }983 }
956 case Type::FunctionProto:984 case clang::Type::FunctionProto:
957 {985 {
958 const FunctionProtoType *fn_proto_ty = static_cast<const FunctionProtoType*>(ty);986 const clang::FunctionProtoType *fn_proto_ty = static_cast<const clang::FunctionProtoType*>(ty);
959987
960 AstNode *proto_node = trans_create_node(c, NodeTypeFnProto);988 AstNode *proto_node = trans_create_node(c, NodeTypeFnProto);
961 switch (fn_proto_ty->getCallConv()) {989 switch (fn_proto_ty->getCallConv()) {
962 case CC_C: // __attribute__((cdecl))990 case clang::CC_C: // __attribute__((cdecl))
963 proto_node->data.fn_proto.cc = CallingConventionC;991 proto_node->data.fn_proto.cc = CallingConventionC;
964 proto_node->data.fn_proto.is_extern = true;992 proto_node->data.fn_proto.is_extern = true;
965 break;993 break;
966 case CC_X86StdCall: // __attribute__((stdcall))994 case clang::CC_X86StdCall: // __attribute__((stdcall))
967 proto_node->data.fn_proto.cc = CallingConventionStdcall;995 proto_node->data.fn_proto.cc = CallingConventionStdcall;
968 break;996 break;
969 case CC_X86FastCall: // __attribute__((fastcall))997 case clang::CC_X86FastCall: // __attribute__((fastcall))
970 emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall");998 emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall");
971 return nullptr;999 return nullptr;
972 case CC_X86ThisCall: // __attribute__((thiscall))1000 case clang::CC_X86ThisCall: // __attribute__((thiscall))
973 emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall");1001 emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall");
974 return nullptr;1002 return nullptr;
975 case CC_X86VectorCall: // __attribute__((vectorcall))1003 case clang::CC_X86VectorCall: // __attribute__((vectorcall))
976 emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall");1004 emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall");
977 return nullptr;1005 return nullptr;
978 case CC_X86Pascal: // __attribute__((pascal))1006 case clang::CC_X86Pascal: // __attribute__((pascal))
979 emit_warning(c, source_loc, "unsupported calling convention: x86 pascal");1007 emit_warning(c, source_loc, "unsupported calling convention: x86 pascal");
980 return nullptr;1008 return nullptr;
981 case CC_Win64: // __attribute__((ms_abi))1009 case clang::CC_Win64: // __attribute__((ms_abi))
982 emit_warning(c, source_loc, "unsupported calling convention: win64");1010 emit_warning(c, source_loc, "unsupported calling convention: win64");
983 return nullptr;1011 return nullptr;
984 case CC_X86_64SysV: // __attribute__((sysv_abi))1012 case clang::CC_X86_64SysV: // __attribute__((sysv_abi))
985 emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv");1013 emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv");
986 return nullptr;1014 return nullptr;
987 case CC_X86RegCall:1015 case clang::CC_X86RegCall:
988 emit_warning(c, source_loc, "unsupported calling convention: x86 reg");1016 emit_warning(c, source_loc, "unsupported calling convention: x86 reg");
989 return nullptr;1017 return nullptr;
990 case CC_AAPCS: // __attribute__((pcs("aapcs")))1018 case clang::CC_AAPCS: // __attribute__((pcs("aapcs")))
991 emit_warning(c, source_loc, "unsupported calling convention: aapcs");1019 emit_warning(c, source_loc, "unsupported calling convention: aapcs");
992 return nullptr;1020 return nullptr;
993 case CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))1021 case clang::CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
994 emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp");1022 emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp");
995 return nullptr;1023 return nullptr;
996 case CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))1024 case clang::CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))
997 emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc");1025 emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc");
998 return nullptr;1026 return nullptr;
999 case CC_SpirFunction: // default for OpenCL functions on SPIR target1027 case clang::CC_SpirFunction: // default for OpenCL functions on SPIR target
1000 emit_warning(c, source_loc, "unsupported calling convention: SPIR function");1028 emit_warning(c, source_loc, "unsupported calling convention: SPIR function");
1001 return nullptr;1029 return nullptr;
1002 case CC_OpenCLKernel:1030 case clang::CC_OpenCLKernel:
1003 emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel");1031 emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel");
1004 return nullptr;1032 return nullptr;
1005 case CC_Swift:1033 case clang::CC_Swift:
1006 emit_warning(c, source_loc, "unsupported calling convention: Swift");1034 emit_warning(c, source_loc, "unsupported calling convention: Swift");
1007 return nullptr;1035 return nullptr;
1008 case CC_PreserveMost:1036 case clang::CC_PreserveMost:
1009 emit_warning(c, source_loc, "unsupported calling convention: PreserveMost");1037 emit_warning(c, source_loc, "unsupported calling convention: PreserveMost");
1010 return nullptr;1038 return nullptr;
1011 case CC_PreserveAll:1039 case clang::CC_PreserveAll:
1012 emit_warning(c, source_loc, "unsupported calling convention: PreserveAll");1040 emit_warning(c, source_loc, "unsupported calling convention: PreserveAll");
1013 return nullptr;1041 return nullptr;
1014 }1042 }
...@@ -1026,7 +1054,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou...@@ -1026,7 +1054,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
1026 return nullptr;1054 return nullptr;
1027 }1055 }
1028 // convert c_void to actual void (only for return type)1056 // convert c_void to actual void (only for return type)
1029 // we do want to look at the AstNode instead of QualType, because1057 // we do want to look at the AstNode instead of clang::QualType, because
1030 // if they do something like:1058 // if they do something like:
1031 // typedef Foo void;1059 // typedef Foo void;
1032 // void foo(void) -> Foo;1060 // void foo(void) -> Foo;
...@@ -1043,7 +1071,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou...@@ -1043,7 +1071,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
1043 }1071 }
10441072
1045 for (size_t i = 0; i < param_count; i += 1) {1073 for (size_t i = 0; i < param_count; i += 1) {
1046 QualType qt = fn_proto_ty->getParamType(i);1074 clang::QualType qt = fn_proto_ty->getParamType(i);
1047 AstNode *param_type_node = trans_qual_type(c, qt, source_loc);1075 AstNode *param_type_node = trans_qual_type(c, qt, source_loc);
10481076
1049 if (param_type_node == nullptr) {1077 if (param_type_node == nullptr) {
...@@ -1066,19 +1094,19 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou...@@ -1066,19 +1094,19 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
10661094
1067 return proto_node;1095 return proto_node;
1068 }1096 }
1069 case Type::Record:1097 case clang::Type::Record:
1070 {1098 {
1071 const RecordType *record_ty = static_cast<const RecordType*>(ty);1099 const clang::RecordType *record_ty = static_cast<const clang::RecordType*>(ty);
1072 return resolve_record_decl(c, record_ty->getDecl());1100 return resolve_record_decl(c, record_ty->getDecl());
1073 }1101 }
1074 case Type::Enum:1102 case clang::Type::Enum:
1075 {1103 {
1076 const EnumType *enum_ty = static_cast<const EnumType*>(ty);1104 const clang::EnumType *enum_ty = static_cast<const clang::EnumType*>(ty);
1077 return resolve_enum_decl(c, enum_ty->getDecl());1105 return resolve_enum_decl(c, enum_ty->getDecl());
1078 }1106 }
1079 case Type::ConstantArray:1107 case clang::Type::ConstantArray:
1080 {1108 {
1081 const ConstantArrayType *const_arr_ty = static_cast<const ConstantArrayType *>(ty);1109 const clang::ConstantArrayType *const_arr_ty = static_cast<const clang::ConstantArrayType *>(ty);
1082 AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc);1110 AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc);
1083 if (child_type_node == nullptr) {1111 if (child_type_node == nullptr) {
1084 emit_warning(c, source_loc, "unresolved array element type");1112 emit_warning(c, source_loc, "unresolved array element type");
...@@ -1088,84 +1116,84 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou...@@ -1088,84 +1116,84 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
1088 AstNode *size_node = trans_create_node_unsigned(c, size);1116 AstNode *size_node = trans_create_node_unsigned(c, size);
1089 return trans_create_node_array_type(c, size_node, child_type_node);1117 return trans_create_node_array_type(c, size_node, child_type_node);
1090 }1118 }
1091 case Type::Paren:1119 case clang::Type::Paren:
1092 {1120 {
1093 const ParenType *paren_ty = static_cast<const ParenType *>(ty);1121 const clang::ParenType *paren_ty = static_cast<const clang::ParenType *>(ty);
1094 return trans_qual_type(c, paren_ty->getInnerType(), source_loc);1122 return trans_qual_type(c, paren_ty->getInnerType(), source_loc);
1095 }1123 }
1096 case Type::Decayed:1124 case clang::Type::Decayed:
1097 {1125 {
1098 const DecayedType *decayed_ty = static_cast<const DecayedType *>(ty);1126 const clang::DecayedType *decayed_ty = static_cast<const clang::DecayedType *>(ty);
1099 return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc);1127 return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc);
1100 }1128 }
1101 case Type::Attributed:1129 case clang::Type::Attributed:
1102 {1130 {
1103 const AttributedType *attributed_ty = static_cast<const AttributedType *>(ty);1131 const clang::AttributedType *attributed_ty = static_cast<const clang::AttributedType *>(ty);
1104 return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc);1132 return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc);
1105 }1133 }
1106 case Type::IncompleteArray:1134 case clang::Type::IncompleteArray:
1107 {1135 {
1108 const IncompleteArrayType *incomplete_array_ty = static_cast<const IncompleteArrayType *>(ty);1136 const clang::IncompleteArrayType *incomplete_array_ty = static_cast<const clang::IncompleteArrayType *>(ty);
1109 QualType child_qt = incomplete_array_ty->getElementType();1137 clang::QualType child_qt = incomplete_array_ty->getElementType();
1110 AstNode *child_type_node = trans_qual_type(c, child_qt, source_loc);1138 AstNode *child_type_node = trans_qual_type(c, child_qt, source_loc);
1111 if (child_type_node == nullptr) {1139 if (child_type_node == nullptr) {
1112 emit_warning(c, source_loc, "unresolved array element type");1140 emit_warning(c, source_loc, "unresolved array element type");
1113 return nullptr;1141 return nullptr;
1114 }1142 }
1115 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),1143 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
1116 child_qt.isVolatileQualified(), child_type_node, PtrLenUnknown);1144 child_qt.isVolatileQualified(), child_type_node, PtrLenC);
1117 return pointer_node;1145 return pointer_node;
1118 }1146 }
1119 case Type::BlockPointer:1147 case clang::Type::BlockPointer:
1120 case Type::LValueReference:1148 case clang::Type::LValueReference:
1121 case Type::RValueReference:1149 case clang::Type::RValueReference:
1122 case Type::MemberPointer:1150 case clang::Type::MemberPointer:
1123 case Type::VariableArray:1151 case clang::Type::VariableArray:
1124 case Type::DependentSizedArray:1152 case clang::Type::DependentSizedArray:
1125 case Type::DependentSizedExtVector:1153 case clang::Type::DependentSizedExtVector:
1126 case Type::Vector:1154 case clang::Type::Vector:
1127 case Type::ExtVector:1155 case clang::Type::ExtVector:
1128 case Type::FunctionNoProto:1156 case clang::Type::FunctionNoProto:
1129 case Type::UnresolvedUsing:1157 case clang::Type::UnresolvedUsing:
1130 case Type::Adjusted:1158 case clang::Type::Adjusted:
1131 case Type::TypeOfExpr:1159 case clang::Type::TypeOfExpr:
1132 case Type::TypeOf:1160 case clang::Type::TypeOf:
1133 case Type::Decltype:1161 case clang::Type::Decltype:
1134 case Type::UnaryTransform:1162 case clang::Type::UnaryTransform:
1135 case Type::TemplateTypeParm:1163 case clang::Type::TemplateTypeParm:
1136 case Type::SubstTemplateTypeParm:1164 case clang::Type::SubstTemplateTypeParm:
1137 case Type::SubstTemplateTypeParmPack:1165 case clang::Type::SubstTemplateTypeParmPack:
1138 case Type::TemplateSpecialization:1166 case clang::Type::TemplateSpecialization:
1139 case Type::Auto:1167 case clang::Type::Auto:
1140 case Type::InjectedClassName:1168 case clang::Type::InjectedClassName:
1141 case Type::DependentName:1169 case clang::Type::DependentName:
1142 case Type::DependentTemplateSpecialization:1170 case clang::Type::DependentTemplateSpecialization:
1143 case Type::PackExpansion:1171 case clang::Type::PackExpansion:
1144 case Type::ObjCObject:1172 case clang::Type::ObjCObject:
1145 case Type::ObjCInterface:1173 case clang::Type::ObjCInterface:
1146 case Type::Complex:1174 case clang::Type::Complex:
1147 case Type::ObjCObjectPointer:1175 case clang::Type::ObjCObjectPointer:
1148 case Type::Atomic:1176 case clang::Type::Atomic:
1149 case Type::Pipe:1177 case clang::Type::Pipe:
1150 case Type::ObjCTypeParam:1178 case clang::Type::ObjCTypeParam:
1151 case Type::DeducedTemplateSpecialization:1179 case clang::Type::DeducedTemplateSpecialization:
1152 case Type::DependentAddressSpace:1180 case clang::Type::DependentAddressSpace:
1153 case Type::DependentVector:1181 case clang::Type::DependentVector:
1154 emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName());1182 emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName());
1155 return nullptr;1183 return nullptr;
1156 }1184 }
1157 zig_unreachable();1185 zig_unreachable();
1158}1186}
11591187
1160static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc) {1188static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc) {
1161 return trans_type(c, qt.getTypePtr(), source_loc);1189 return trans_type(c, qt.getTypePtr(), source_loc);
1162}1190}
11631191
1164static int trans_compound_stmt_inline(Context *c, TransScope *scope, const CompoundStmt *stmt,1192static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang::CompoundStmt *stmt,
1165 AstNode *block_node, TransScope **out_node_scope)1193 AstNode *block_node, TransScope **out_node_scope)
1166{1194{
1167 assert(block_node->type == NodeTypeBlock);1195 assert(block_node->type == NodeTypeBlock);
1168 for (CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) {1196 for (clang::CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) {
1169 AstNode *child_node;1197 AstNode *child_node;
1170 scope = trans_stmt(c, scope, *it, &child_node);1198 scope = trans_stmt(c, scope, *it, &child_node);
1171 if (scope == nullptr)1199 if (scope == nullptr)
...@@ -1179,7 +1207,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const Compo...@@ -1179,7 +1207,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const Compo
1179 return ErrorNone;1207 return ErrorNone;
1180}1208}
11811209
1182static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const CompoundStmt *stmt,1210static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang::CompoundStmt *stmt,
1183 TransScope **out_node_scope)1211 TransScope **out_node_scope)
1184{1212{
1185 TransScopeBlock *child_scope_block = trans_scope_block_create(c, scope);1213 TransScopeBlock *child_scope_block = trans_scope_block_create(c, scope);
...@@ -1188,8 +1216,8 @@ static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const Compoun...@@ -1188,8 +1216,8 @@ static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const Compoun
1188 return child_scope_block->node;1216 return child_scope_block->node;
1189}1217}
11901218
1191static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStmt *stmt) {1219static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::ReturnStmt *stmt) {
1192 const Expr *value_expr = stmt->getRetValue();1220 const clang::Expr *value_expr = stmt->getRetValue();
1193 if (value_expr == nullptr) {1221 if (value_expr == nullptr) {
1194 return trans_create_node(c, NodeTypeReturnExpr);1222 return trans_create_node(c, NodeTypeReturnExpr);
1195 } else {1223 } else {
...@@ -1201,9 +1229,9 @@ static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStm...@@ -1201,9 +1229,9 @@ static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStm
1201 }1229 }
1202}1230}
12031231
1204static AstNode *trans_integer_literal(Context *c, const IntegerLiteral *stmt) {1232static AstNode *trans_integer_literal(Context *c, const clang::IntegerLiteral *stmt) {
1205 llvm::APSInt result;1233 llvm::APSInt result;
1206 if (!stmt->EvaluateAsInt(result, *c->ctx)) {1234 if (!stmt->EvaluateAsInt(result, *reinterpret_cast<clang::ASTContext *>(c->ctx))) {
1207 emit_warning(c, stmt->getLocStart(), "invalid integer literal");1235 emit_warning(c, stmt->getLocStart(), "invalid integer literal");
1208 return nullptr;1236 return nullptr;
1209 }1237 }
...@@ -1211,13 +1239,13 @@ static AstNode *trans_integer_literal(Context *c, const IntegerLiteral *stmt) {...@@ -1211,13 +1239,13 @@ static AstNode *trans_integer_literal(Context *c, const IntegerLiteral *stmt) {
1211}1239}
12121240
1213static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, TransScope *scope,1241static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, TransScope *scope,
1214 const ConditionalOperator *stmt)1242 const clang::ConditionalOperator *stmt)
1215{1243{
1216 AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr);1244 AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr);
12171245
1218 Expr *cond_expr = stmt->getCond();1246 clang::Expr *cond_expr = stmt->getCond();
1219 Expr *true_expr = stmt->getTrueExpr();1247 clang::Expr *true_expr = stmt->getTrueExpr();
1220 Expr *false_expr = stmt->getFalseExpr();1248 clang::Expr *false_expr = stmt->getFalseExpr();
12211249
1222 node->data.if_bool_expr.condition = trans_expr(c, ResultUsedYes, scope, cond_expr, TransRValue);1250 node->data.if_bool_expr.condition = trans_expr(c, ResultUsedYes, scope, cond_expr, TransRValue);
1223 if (node->data.if_bool_expr.condition == nullptr)1251 if (node->data.if_bool_expr.condition == nullptr)
...@@ -1234,7 +1262,7 @@ static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, T...@@ -1234,7 +1262,7 @@ static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, T
1234 return maybe_suppress_result(c, result_used, node);1262 return maybe_suppress_result(c, result_used, node);
1235}1263}
12361264
1237static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, BinOpType bin_op, Expr *rhs) {1265static AstNode *trans_create_bin_op(Context *c, TransScope *scope, clang::Expr *lhs, BinOpType bin_op, clang::Expr *rhs) {
1238 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);1266 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
1239 node->data.bin_op_expr.bin_op = bin_op;1267 node->data.bin_op_expr.bin_op = bin_op;
12401268
...@@ -1249,7 +1277,7 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, Bi...@@ -1249,7 +1277,7 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, Bi
1249 return node;1277 return node;
1250}1278}
12511279
1252static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, Expr *lhs, BinOpType bin_op, Expr *rhs) {1280static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, clang::Expr *lhs, BinOpType bin_op, clang::Expr *rhs) {
1253 assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr);1281 assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr);
1254 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);1282 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
1255 node->data.bin_op_expr.bin_op = bin_op;1283 node->data.bin_op_expr.bin_op = bin_op;
...@@ -1265,7 +1293,7 @@ static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, Expr *lh...@@ -1265,7 +1293,7 @@ static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, Expr *lh
1265 return node;1293 return node;
1266}1294}
12671295
1268static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, Expr *lhs, Expr *rhs) {1296static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, clang::Expr *lhs, clang::Expr *rhs) {
1269 if (result_used == ResultUsedNo) {1297 if (result_used == ResultUsedNo) {
1270 // common case1298 // common case
1271 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);1299 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
...@@ -1316,10 +1344,10 @@ static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransSco...@@ -1316,10 +1344,10 @@ static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransSco
1316 }1344 }
1317}1345}
13181346
1319static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType result_type,1347static AstNode *trans_create_shift_op(Context *c, TransScope *scope, clang::QualType result_type,
1320 Expr *lhs_expr, BinOpType bin_op, Expr *rhs_expr)1348 clang::Expr *lhs_expr, BinOpType bin_op, clang::Expr *rhs_expr)
1321{1349{
1322 const SourceLocation &rhs_location = rhs_expr->getLocStart();1350 const clang::SourceLocation &rhs_location = rhs_expr->getLocStart();
1323 AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location);1351 AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location);
1324 // lhs >> u5(rh)1352 // lhs >> u5(rh)
13251353
...@@ -1333,22 +1361,22 @@ static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType re...@@ -1333,22 +1361,22 @@ static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType re
1333 return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs);1361 return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs);
1334}1362}
13351363
1336static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const BinaryOperator *stmt) {1364static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::BinaryOperator *stmt) {
1337 switch (stmt->getOpcode()) {1365 switch (stmt->getOpcode()) {
1338 case BO_PtrMemD:1366 case clang::BO_PtrMemD:
1339 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemD");1367 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: clang::BO_PtrMemD");
1340 return nullptr;1368 return nullptr;
1341 case BO_PtrMemI:1369 case clang::BO_PtrMemI:
1342 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemI");1370 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: clang::BO_PtrMemI");
1343 return nullptr;1371 return nullptr;
1344 case BO_Cmp:1372 case clang::BO_Cmp:
1345 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Cmp");1373 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: clang::BO_Cmp");
1346 return nullptr;1374 return nullptr;
1347 case BO_Mul:1375 case clang::BO_Mul:
1348 return trans_create_bin_op(c, scope, stmt->getLHS(),1376 return trans_create_bin_op(c, scope, stmt->getLHS(),
1349 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult,1377 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult,
1350 stmt->getRHS());1378 stmt->getRHS());
1351 case BO_Div:1379 case clang::BO_Div:
1352 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {1380 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
1353 // unsigned/float division uses the operator1381 // unsigned/float division uses the operator
1354 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS());1382 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS());
...@@ -1363,7 +1391,7 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS...@@ -1363,7 +1391,7 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
1363 fn_call->data.fn_call_expr.params.append(rhs);1391 fn_call->data.fn_call_expr.params.append(rhs);
1364 return fn_call;1392 return fn_call;
1365 }1393 }
1366 case BO_Rem:1394 case clang::BO_Rem:
1367 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {1395 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
1368 // unsigned/float division uses the operator1396 // unsigned/float division uses the operator
1369 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeMod, stmt->getRHS());1397 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeMod, stmt->getRHS());
...@@ -1378,43 +1406,43 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS...@@ -1378,43 +1406,43 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
1378 fn_call->data.fn_call_expr.params.append(rhs);1406 fn_call->data.fn_call_expr.params.append(rhs);
1379 return fn_call;1407 return fn_call;
1380 }1408 }
1381 case BO_Add:1409 case clang::BO_Add:
1382 return trans_create_bin_op(c, scope, stmt->getLHS(),1410 return trans_create_bin_op(c, scope, stmt->getLHS(),
1383 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd,1411 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd,
1384 stmt->getRHS());1412 stmt->getRHS());
1385 case BO_Sub:1413 case clang::BO_Sub:
1386 return trans_create_bin_op(c, scope, stmt->getLHS(),1414 return trans_create_bin_op(c, scope, stmt->getLHS(),
1387 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub,1415 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub,
1388 stmt->getRHS());1416 stmt->getRHS());
1389 case BO_Shl:1417 case clang::BO_Shl:
1390 return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS());1418 return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS());
1391 case BO_Shr:1419 case clang::BO_Shr:
1392 return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS());1420 return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS());
1393 case BO_LT:1421 case clang::BO_LT:
1394 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS());1422 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS());
1395 case BO_GT:1423 case clang::BO_GT:
1396 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS());1424 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS());
1397 case BO_LE:1425 case clang::BO_LE:
1398 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS());1426 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS());
1399 case BO_GE:1427 case clang::BO_GE:
1400 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS());1428 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS());
1401 case BO_EQ:1429 case clang::BO_EQ:
1402 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS());1430 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS());
1403 case BO_NE:1431 case clang::BO_NE:
1404 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS());1432 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS());
1405 case BO_And:1433 case clang::BO_And:
1406 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS());1434 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS());
1407 case BO_Xor:1435 case clang::BO_Xor:
1408 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS());1436 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS());
1409 case BO_Or:1437 case clang::BO_Or:
1410 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());1438 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());
1411 case BO_LAnd:1439 case clang::BO_LAnd:
1412 return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());1440 return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());
1413 case BO_LOr:1441 case clang::BO_LOr:
1414 return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());1442 return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());
1415 case BO_Assign:1443 case clang::BO_Assign:
1416 return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS());1444 return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS());
1417 case BO_Comma:1445 case clang::BO_Comma:
1418 {1446 {
1419 TransScopeBlock *scope_block = trans_scope_block_create(c, scope);1447 TransScopeBlock *scope_block = trans_scope_block_create(c, scope);
1420 Buf *label_name = buf_create_from_str("x");1448 Buf *label_name = buf_create_from_str("x");
...@@ -1431,16 +1459,16 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS...@@ -1431,16 +1459,16 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
1431 scope_block->node->data.block.statements.append(trans_create_node_break(c, label_name, maybe_suppress_result(c, result_used, rhs)));1459 scope_block->node->data.block.statements.append(trans_create_node_break(c, label_name, maybe_suppress_result(c, result_used, rhs)));
1432 return scope_block->node;1460 return scope_block->node;
1433 }1461 }
1434 case BO_MulAssign:1462 case clang::BO_MulAssign:
1435 case BO_DivAssign:1463 case clang::BO_DivAssign:
1436 case BO_RemAssign:1464 case clang::BO_RemAssign:
1437 case BO_AddAssign:1465 case clang::BO_AddAssign:
1438 case BO_SubAssign:1466 case clang::BO_SubAssign:
1439 case BO_ShlAssign:1467 case clang::BO_ShlAssign:
1440 case BO_ShrAssign:1468 case clang::BO_ShrAssign:
1441 case BO_AndAssign:1469 case clang::BO_AndAssign:
1442 case BO_XorAssign:1470 case clang::BO_XorAssign:
1443 case BO_OrAssign:1471 case clang::BO_OrAssign:
1444 zig_unreachable();1472 zig_unreachable();
1445 }1473 }
14461474
...@@ -1448,9 +1476,9 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS...@@ -1448,9 +1476,9 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
1448}1476}
14491477
1450static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result_used, TransScope *scope,1478static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result_used, TransScope *scope,
1451 const CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op)1479 const clang::CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op)
1452{1480{
1453 const SourceLocation &rhs_location = stmt->getRHS()->getLocStart();1481 const clang::SourceLocation &rhs_location = stmt->getRHS()->getLocStart();
1454 AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location);1482 AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location);
14551483
1456 bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr();1484 bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr();
...@@ -1530,7 +1558,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result...@@ -1530,7 +1558,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result
1530}1558}
15311559
1532static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, TransScope *scope,1560static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, TransScope *scope,
1533 const CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op)1561 const clang::CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op)
1534{1562{
1535 if (result_used == ResultUsedNo) {1563 if (result_used == ResultUsedNo) {
1536 // simple common case, where the C and Zig are identical:1564 // simple common case, where the C and Zig are identical:
...@@ -1590,76 +1618,76 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,...@@ -1590,76 +1618,76 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,
15901618
15911619
1592static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_used, TransScope *scope,1620static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_used, TransScope *scope,
1593 const CompoundAssignOperator *stmt)1621 const clang::CompoundAssignOperator *stmt)
1594{1622{
1595 switch (stmt->getOpcode()) {1623 switch (stmt->getOpcode()) {
1596 case BO_MulAssign:1624 case clang::BO_MulAssign:
1597 if (qual_type_has_wrapping_overflow(c, stmt->getType()))1625 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1598 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap);1626 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap);
1599 else1627 else
1600 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult);1628 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult);
1601 case BO_DivAssign:1629 case clang::BO_DivAssign:
1602 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_DivAssign");1630 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: clang::BO_DivAssign");
1603 return nullptr;1631 return nullptr;
1604 case BO_RemAssign:1632 case clang::BO_RemAssign:
1605 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_RemAssign");1633 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: clang::BO_RemAssign");
1606 return nullptr;1634 return nullptr;
1607 case BO_Cmp:1635 case clang::BO_Cmp:
1608 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_Cmp");1636 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: clang::BO_Cmp");
1609 return nullptr;1637 return nullptr;
1610 case BO_AddAssign:1638 case clang::BO_AddAssign:
1611 if (qual_type_has_wrapping_overflow(c, stmt->getType()))1639 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1612 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap);1640 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap);
1613 else1641 else
1614 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlus, BinOpTypeAdd);1642 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlus, BinOpTypeAdd);
1615 case BO_SubAssign:1643 case clang::BO_SubAssign:
1616 if (qual_type_has_wrapping_overflow(c, stmt->getType()))1644 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1617 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap);1645 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap);
1618 else1646 else
1619 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinus, BinOpTypeSub);1647 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinus, BinOpTypeSub);
1620 case BO_ShlAssign:1648 case clang::BO_ShlAssign:
1621 return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft);1649 return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft);
1622 case BO_ShrAssign:1650 case clang::BO_ShrAssign:
1623 return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight);1651 return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight);
1624 case BO_AndAssign:1652 case clang::BO_AndAssign:
1625 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd);1653 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd);
1626 case BO_XorAssign:1654 case clang::BO_XorAssign:
1627 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor);1655 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor);
1628 case BO_OrAssign:1656 case clang::BO_OrAssign:
1629 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr);1657 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr);
1630 case BO_PtrMemD:1658 case clang::BO_PtrMemD:
1631 case BO_PtrMemI:1659 case clang::BO_PtrMemI:
1632 case BO_Assign:1660 case clang::BO_Assign:
1633 case BO_Mul:1661 case clang::BO_Mul:
1634 case BO_Div:1662 case clang::BO_Div:
1635 case BO_Rem:1663 case clang::BO_Rem:
1636 case BO_Add:1664 case clang::BO_Add:
1637 case BO_Sub:1665 case clang::BO_Sub:
1638 case BO_Shl:1666 case clang::BO_Shl:
1639 case BO_Shr:1667 case clang::BO_Shr:
1640 case BO_LT:1668 case clang::BO_LT:
1641 case BO_GT:1669 case clang::BO_GT:
1642 case BO_LE:1670 case clang::BO_LE:
1643 case BO_GE:1671 case clang::BO_GE:
1644 case BO_EQ:1672 case clang::BO_EQ:
1645 case BO_NE:1673 case clang::BO_NE:
1646 case BO_And:1674 case clang::BO_And:
1647 case BO_Xor:1675 case clang::BO_Xor:
1648 case BO_Or:1676 case clang::BO_Or:
1649 case BO_LAnd:1677 case clang::BO_LAnd:
1650 case BO_LOr:1678 case clang::BO_LOr:
1651 case BO_Comma:1679 case clang::BO_Comma:
1652 zig_unreachable();1680 zig_unreachable();
1653 }1681 }
16541682
1655 zig_unreachable();1683 zig_unreachable();
1656}1684}
16571685
1658static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const ImplicitCastExpr *stmt) {1686static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const clang::ImplicitCastExpr *stmt) {
1659 switch (stmt->getCastKind()) {1687 switch (stmt->getCastKind()) {
1660 case CK_LValueToRValue:1688 case clang::CK_LValueToRValue:
1661 return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);1689 return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
1662 case CK_IntegralCast:1690 case clang::CK_IntegralCast:
1663 {1691 {
1664 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);1692 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
1665 if (target_node == nullptr)1693 if (target_node == nullptr)
...@@ -1667,15 +1695,15 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im...@@ -1667,15 +1695,15 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im
1667 return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(),1695 return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(),
1668 stmt->getSubExpr()->getType(), target_node);1696 stmt->getSubExpr()->getType(), target_node);
1669 }1697 }
1670 case CK_FunctionToPointerDecay:1698 case clang::CK_FunctionToPointerDecay:
1671 case CK_ArrayToPointerDecay:1699 case clang::CK_ArrayToPointerDecay:
1672 {1700 {
1673 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);1701 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
1674 if (target_node == nullptr)1702 if (target_node == nullptr)
1675 return nullptr;1703 return nullptr;
1676 return target_node;1704 return target_node;
1677 }1705 }
1678 case CK_BitCast:1706 case clang::CK_BitCast:
1679 {1707 {
1680 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);1708 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
1681 if (target_node == nullptr)1709 if (target_node == nullptr)
...@@ -1692,170 +1720,170 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im...@@ -1692,170 +1720,170 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im
1692 node->data.fn_call_expr.params.append(target_node);1720 node->data.fn_call_expr.params.append(target_node);
1693 return node;1721 return node;
1694 }1722 }
1695 case CK_NullToPointer:1723 case clang::CK_NullToPointer:
1696 return trans_create_node(c, NodeTypeNullLiteral);1724 return trans_create_node_unsigned(c, 0);
1697 case CK_Dependent:1725 case clang::CK_Dependent:
1698 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent");1726 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_Dependent");
1699 return nullptr;1727 return nullptr;
1700 case CK_LValueBitCast:1728 case clang::CK_LValueBitCast:
1701 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_LValueBitCast");1729 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_LValueBitCast");
1702 return nullptr;1730 return nullptr;
1703 case CK_NoOp:1731 case clang::CK_NoOp:
1704 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NoOp");1732 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_NoOp");
1705 return nullptr;1733 return nullptr;
1706 case CK_BaseToDerived:1734 case clang::CK_BaseToDerived:
1707 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BaseToDerived");1735 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BaseToDerived");
1708 return nullptr;1736 return nullptr;
1709 case CK_DerivedToBase:1737 case clang::CK_DerivedToBase:
1710 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_DerivedToBase");1738 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_DerivedToBase");
1711 return nullptr;1739 return nullptr;
1712 case CK_UncheckedDerivedToBase:1740 case clang::CK_UncheckedDerivedToBase:
1713 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_UncheckedDerivedToBase");1741 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_UncheckedDerivedToBase");
1714 return nullptr;1742 return nullptr;
1715 case CK_Dynamic:1743 case clang::CK_Dynamic:
1716 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dynamic");1744 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_Dynamic");
1717 return nullptr;1745 return nullptr;
1718 case CK_ToUnion:1746 case clang::CK_ToUnion:
1719 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ToUnion");1747 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ToUnion");
1720 return nullptr;1748 return nullptr;
1721 case CK_NullToMemberPointer:1749 case clang::CK_NullToMemberPointer:
1722 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NullToMemberPointer");1750 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_NullToMemberPointer");
1723 return nullptr;1751 return nullptr;
1724 case CK_BaseToDerivedMemberPointer:1752 case clang::CK_BaseToDerivedMemberPointer:
1725 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BaseToDerivedMemberPointer");1753 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BaseToDerivedMemberPointer");
1726 return nullptr;1754 return nullptr;
1727 case CK_DerivedToBaseMemberPointer:1755 case clang::CK_DerivedToBaseMemberPointer:
1728 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_DerivedToBaseMemberPointer");1756 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_DerivedToBaseMemberPointer");
1729 return nullptr;1757 return nullptr;
1730 case CK_MemberPointerToBoolean:1758 case clang::CK_MemberPointerToBoolean:
1731 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_MemberPointerToBoolean");1759 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_MemberPointerToBoolean");
1732 return nullptr;1760 return nullptr;
1733 case CK_ReinterpretMemberPointer:1761 case clang::CK_ReinterpretMemberPointer:
1734 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ReinterpretMemberPointer");1762 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ReinterpretMemberPointer");
1735 return nullptr;1763 return nullptr;
1736 case CK_UserDefinedConversion:1764 case clang::CK_UserDefinedConversion:
1737 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_UserDefinedConversion");1765 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_UserDefinedConversion");
1738 return nullptr;1766 return nullptr;
1739 case CK_ConstructorConversion:1767 case clang::CK_ConstructorConversion:
1740 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ConstructorConversion");1768 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ConstructorConversion");
1741 return nullptr;1769 return nullptr;
1742 case CK_IntegralToPointer:1770 case clang::CK_IntegralToPointer:
1743 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralToPointer");1771 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralToPointer");
1744 return nullptr;1772 return nullptr;
1745 case CK_PointerToIntegral:1773 case clang::CK_PointerToIntegral:
1746 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_PointerToIntegral");1774 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_PointerToIntegral");
1747 return nullptr;1775 return nullptr;
1748 case CK_PointerToBoolean:1776 case clang::CK_PointerToBoolean:
1749 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_PointerToBoolean");1777 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_PointerToBoolean");
1750 return nullptr;1778 return nullptr;
1751 case CK_ToVoid:1779 case clang::CK_ToVoid:
1752 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ToVoid");1780 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ToVoid");
1753 return nullptr;1781 return nullptr;
1754 case CK_VectorSplat:1782 case clang::CK_VectorSplat:
1755 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_VectorSplat");1783 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_VectorSplat");
1756 return nullptr;1784 return nullptr;
1757 case CK_IntegralToBoolean:1785 case clang::CK_IntegralToBoolean:
1758 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralToBoolean");1786 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralToBoolean");
1759 return nullptr;1787 return nullptr;
1760 case CK_IntegralToFloating:1788 case clang::CK_IntegralToFloating:
1761 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralToFloating");1789 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralToFloating");
1762 return nullptr;1790 return nullptr;
1763 case CK_FloatingToIntegral:1791 case clang::CK_FloatingToIntegral:
1764 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingToIntegral");1792 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingToIntegral");
1765 return nullptr;1793 return nullptr;
1766 case CK_FloatingToBoolean:1794 case clang::CK_FloatingToBoolean:
1767 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingToBoolean");1795 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingToBoolean");
1768 return nullptr;1796 return nullptr;
1769 case CK_BooleanToSignedIntegral:1797 case clang::CK_BooleanToSignedIntegral:
1770 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BooleanToSignedIntegral");1798 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BooleanToSignedIntegral");
1771 return nullptr;1799 return nullptr;
1772 case CK_FloatingCast:1800 case clang::CK_FloatingCast:
1773 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingCast");1801 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingCast");
1774 return nullptr;1802 return nullptr;
1775 case CK_CPointerToObjCPointerCast:1803 case clang::CK_CPointerToObjCPointerCast:
1776 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_CPointerToObjCPointerCast");1804 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_CPointerToObjCPointerCast");
1777 return nullptr;1805 return nullptr;
1778 case CK_BlockPointerToObjCPointerCast:1806 case clang::CK_BlockPointerToObjCPointerCast:
1779 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BlockPointerToObjCPointerCast");1807 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BlockPointerToObjCPointerCast");
1780 return nullptr;1808 return nullptr;
1781 case CK_AnyPointerToBlockPointerCast:1809 case clang::CK_AnyPointerToBlockPointerCast:
1782 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_AnyPointerToBlockPointerCast");1810 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_AnyPointerToBlockPointerCast");
1783 return nullptr;1811 return nullptr;
1784 case CK_ObjCObjectLValueCast:1812 case clang::CK_ObjCObjectLValueCast:
1785 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ObjCObjectLValueCast");1813 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ObjCObjectLValueCast");
1786 return nullptr;1814 return nullptr;
1787 case CK_FloatingRealToComplex:1815 case clang::CK_FloatingRealToComplex:
1788 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingRealToComplex");1816 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingRealToComplex");
1789 return nullptr;1817 return nullptr;
1790 case CK_FloatingComplexToReal:1818 case clang::CK_FloatingComplexToReal:
1791 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexToReal");1819 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingComplexToReal");
1792 return nullptr;1820 return nullptr;
1793 case CK_FloatingComplexToBoolean:1821 case clang::CK_FloatingComplexToBoolean:
1794 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexToBoolean");1822 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingComplexToBoolean");
1795 return nullptr;1823 return nullptr;
1796 case CK_FloatingComplexCast:1824 case clang::CK_FloatingComplexCast:
1797 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexCast");1825 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingComplexCast");
1798 return nullptr;1826 return nullptr;
1799 case CK_FloatingComplexToIntegralComplex:1827 case clang::CK_FloatingComplexToIntegralComplex:
1800 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexToIntegralComplex");1828 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingComplexToIntegralComplex");
1801 return nullptr;1829 return nullptr;
1802 case CK_IntegralRealToComplex:1830 case clang::CK_IntegralRealToComplex:
1803 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralRealToComplex");1831 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralRealToComplex");
1804 return nullptr;1832 return nullptr;
1805 case CK_IntegralComplexToReal:1833 case clang::CK_IntegralComplexToReal:
1806 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexToReal");1834 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralComplexToReal");
1807 return nullptr;1835 return nullptr;
1808 case CK_IntegralComplexToBoolean:1836 case clang::CK_IntegralComplexToBoolean:
1809 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexToBoolean");1837 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralComplexToBoolean");
1810 return nullptr;1838 return nullptr;
1811 case CK_IntegralComplexCast:1839 case clang::CK_IntegralComplexCast:
1812 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexCast");1840 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralComplexCast");
1813 return nullptr;1841 return nullptr;
1814 case CK_IntegralComplexToFloatingComplex:1842 case clang::CK_IntegralComplexToFloatingComplex:
1815 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexToFloatingComplex");1843 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralComplexToFloatingComplex");
1816 return nullptr;1844 return nullptr;
1817 case CK_ARCProduceObject:1845 case clang::CK_ARCProduceObject:
1818 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCProduceObject");1846 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ARCProduceObject");
1819 return nullptr;1847 return nullptr;
1820 case CK_ARCConsumeObject:1848 case clang::CK_ARCConsumeObject:
1821 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCConsumeObject");1849 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ARCConsumeObject");
1822 return nullptr;1850 return nullptr;
1823 case CK_ARCReclaimReturnedObject:1851 case clang::CK_ARCReclaimReturnedObject:
1824 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCReclaimReturnedObject");1852 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ARCReclaimReturnedObject");
1825 return nullptr;1853 return nullptr;
1826 case CK_ARCExtendBlockObject:1854 case clang::CK_ARCExtendBlockObject:
1827 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCExtendBlockObject");1855 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ARCExtendBlockObject");
1828 return nullptr;1856 return nullptr;
1829 case CK_AtomicToNonAtomic:1857 case clang::CK_AtomicToNonAtomic:
1830 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_AtomicToNonAtomic");1858 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_AtomicToNonAtomic");
1831 return nullptr;1859 return nullptr;
1832 case CK_NonAtomicToAtomic:1860 case clang::CK_NonAtomicToAtomic:
1833 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NonAtomicToAtomic");1861 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_NonAtomicToAtomic");
1834 return nullptr;1862 return nullptr;
1835 case CK_CopyAndAutoreleaseBlockObject:1863 case clang::CK_CopyAndAutoreleaseBlockObject:
1836 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_CopyAndAutoreleaseBlockObject");1864 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_CopyAndAutoreleaseBlockObject");
1837 return nullptr;1865 return nullptr;
1838 case CK_BuiltinFnToFnPtr:1866 case clang::CK_BuiltinFnToFnPtr:
1839 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BuiltinFnToFnPtr");1867 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BuiltinFnToFnPtr");
1840 return nullptr;1868 return nullptr;
1841 case CK_ZeroToOCLEvent:1869 case clang::CK_ZeroToOCLEvent:
1842 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ZeroToOCLEvent");1870 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ZeroToOCLEvent");
1843 return nullptr;1871 return nullptr;
1844 case CK_ZeroToOCLQueue:1872 case clang::CK_ZeroToOCLQueue:
1845 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ZeroToOCLQueue");1873 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ZeroToOCLQueue");
1846 return nullptr;1874 return nullptr;
1847 case CK_AddressSpaceConversion:1875 case clang::CK_AddressSpaceConversion:
1848 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_AddressSpaceConversion");1876 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_AddressSpaceConversion");
1849 return nullptr;1877 return nullptr;
1850 case CK_IntToOCLSampler:1878 case clang::CK_IntToOCLSampler:
1851 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntToOCLSampler");1879 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntToOCLSampler");
1852 return nullptr;1880 return nullptr;
1853 }1881 }
1854 zig_unreachable();1882 zig_unreachable();
1855}1883}
18561884
1857static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRefExpr *stmt, TransLRValue lrval) {1885static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const clang::DeclRefExpr *stmt, TransLRValue lrval) {
1858 const ValueDecl *value_decl = stmt->getDecl();1886 const clang::ValueDecl *value_decl = stmt->getDecl();
1859 Buf *c_symbol_name = buf_create_from_str(decl_name(value_decl));1887 Buf *c_symbol_name = buf_create_from_str(decl_name(value_decl));
1860 Buf *zig_symbol_name = trans_lookup_zig_symbol(c, scope, c_symbol_name);1888 Buf *zig_symbol_name = trans_lookup_zig_symbol(c, scope, c_symbol_name);
1861 if (lrval == TransLValue) {1889 if (lrval == TransLValue) {
...@@ -1865,9 +1893,9 @@ static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRef...@@ -1865,9 +1893,9 @@ static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRef
1865}1893}
18661894
1867static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, TransScope *scope,1895static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, TransScope *scope,
1868 const UnaryOperator *stmt, BinOpType assign_op)1896 const clang::UnaryOperator *stmt, BinOpType assign_op)
1869{1897{
1870 Expr *op_expr = stmt->getSubExpr();1898 clang::Expr *op_expr = stmt->getSubExpr();
18711899
1872 if (result_used == ResultUsedNo) {1900 if (result_used == ResultUsedNo) {
1873 // common case1901 // common case
...@@ -1921,9 +1949,9 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr...@@ -1921,9 +1949,9 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr
1921}1949}
19221950
1923static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, TransScope *scope,1951static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, TransScope *scope,
1924 const UnaryOperator *stmt, BinOpType assign_op)1952 const clang::UnaryOperator *stmt, BinOpType assign_op)
1925{1953{
1926 Expr *op_expr = stmt->getSubExpr();1954 clang::Expr *op_expr = stmt->getSubExpr();
19271955
1928 if (result_used == ResultUsedNo) {1956 if (result_used == ResultUsedNo) {
1929 // common case1957 // common case
...@@ -1970,36 +1998,36 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra...@@ -1970,36 +1998,36 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra
1970 return child_scope->node;1998 return child_scope->node;
1971}1999}
19722000
1973static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope, const UnaryOperator *stmt) {2001static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::UnaryOperator *stmt) {
1974 switch (stmt->getOpcode()) {2002 switch (stmt->getOpcode()) {
1975 case UO_PostInc:2003 case clang::UO_PostInc:
1976 if (qual_type_has_wrapping_overflow(c, stmt->getType()))2004 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1977 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);2005 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);
1978 else2006 else
1979 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);2007 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);
1980 case UO_PostDec:2008 case clang::UO_PostDec:
1981 if (qual_type_has_wrapping_overflow(c, stmt->getType()))2009 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1982 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);2010 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);
1983 else2011 else
1984 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);2012 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);
1985 case UO_PreInc:2013 case clang::UO_PreInc:
1986 if (qual_type_has_wrapping_overflow(c, stmt->getType()))2014 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1987 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);2015 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);
1988 else2016 else
1989 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);2017 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);
1990 case UO_PreDec:2018 case clang::UO_PreDec:
1991 if (qual_type_has_wrapping_overflow(c, stmt->getType()))2019 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1992 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);2020 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);
1993 else2021 else
1994 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);2022 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);
1995 case UO_AddrOf:2023 case clang::UO_AddrOf:
1996 {2024 {
1997 AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue);2025 AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue);
1998 if (value_node == nullptr)2026 if (value_node == nullptr)
1999 return value_node;2027 return value_node;
2000 return trans_create_node_addr_of(c, value_node);2028 return trans_create_node_addr_of(c, value_node);
2001 }2029 }
2002 case UO_Deref:2030 case clang::UO_Deref:
2003 {2031 {
2004 AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue);2032 AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue);
2005 if (value_node == nullptr)2033 if (value_node == nullptr)
...@@ -2010,12 +2038,12 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc...@@ -2010,12 +2038,12 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
2010 AstNode *unwrapped = trans_create_node_unwrap_null(c, value_node);2038 AstNode *unwrapped = trans_create_node_unwrap_null(c, value_node);
2011 return trans_create_node_ptr_deref(c, unwrapped);2039 return trans_create_node_ptr_deref(c, unwrapped);
2012 }2040 }
2013 case UO_Plus:2041 case clang::UO_Plus:
2014 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Plus");2042 emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Plus");
2015 return nullptr;2043 return nullptr;
2016 case UO_Minus:2044 case clang::UO_Minus:
2017 {2045 {
2018 Expr *op_expr = stmt->getSubExpr();2046 clang::Expr *op_expr = stmt->getSubExpr();
2019 if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) {2047 if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) {
2020 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);2048 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
2021 node->data.prefix_op_expr.prefix_op = PrefixOpNegation;2049 node->data.prefix_op_expr.prefix_op = PrefixOpNegation;
...@@ -2041,41 +2069,41 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc...@@ -2041,41 +2069,41 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
2041 return nullptr;2069 return nullptr;
2042 }2070 }
2043 }2071 }
2044 case UO_Not:2072 case clang::UO_Not:
2045 {2073 {
2046 Expr *op_expr = stmt->getSubExpr();2074 clang::Expr *op_expr = stmt->getSubExpr();
2047 AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue);2075 AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
2048 if (sub_node == nullptr)2076 if (sub_node == nullptr)
2049 return nullptr;2077 return nullptr;
20502078
2051 return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node);2079 return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node);
2052 }2080 }
2053 case UO_LNot:2081 case clang::UO_LNot:
2054 {2082 {
2055 Expr *op_expr = stmt->getSubExpr();2083 clang::Expr *op_expr = stmt->getSubExpr();
2056 AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue);2084 AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
2057 if (sub_node == nullptr)2085 if (sub_node == nullptr)
2058 return nullptr;2086 return nullptr;
20592087
2060 return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node);2088 return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node);
2061 }2089 }
2062 case UO_Real:2090 case clang::UO_Real:
2063 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Real");2091 emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Real");
2064 return nullptr;2092 return nullptr;
2065 case UO_Imag:2093 case clang::UO_Imag:
2066 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Imag");2094 emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Imag");
2067 return nullptr;2095 return nullptr;
2068 case UO_Extension:2096 case clang::UO_Extension:
2069 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Extension");2097 emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Extension");
2070 return nullptr;2098 return nullptr;
2071 case UO_Coawait:2099 case clang::UO_Coawait:
2072 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Coawait");2100 emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Coawait");
2073 return nullptr;2101 return nullptr;
2074 }2102 }
2075 zig_unreachable();2103 zig_unreachable();
2076}2104}
20772105
2078static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt *stmt,2106static int trans_local_declaration(Context *c, TransScope *scope, const clang::DeclStmt *stmt,
2079 AstNode **out_node, TransScope **out_scope)2107 AstNode **out_node, TransScope **out_scope)
2080{2108{
2081 // declarations are added via the scope2109 // declarations are added via the scope
...@@ -2085,11 +2113,11 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt...@@ -2085,11 +2113,11 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt
2085 assert(scope_block != nullptr);2113 assert(scope_block != nullptr);
20862114
2087 for (auto iter = stmt->decl_begin(); iter != stmt->decl_end(); iter++) {2115 for (auto iter = stmt->decl_begin(); iter != stmt->decl_end(); iter++) {
2088 Decl *decl = *iter;2116 clang::Decl *decl = *iter;
2089 switch (decl->getKind()) {2117 switch (decl->getKind()) {
2090 case Decl::Var: {2118 case clang::Decl::Var: {
2091 VarDecl *var_decl = (VarDecl *)decl;2119 clang::VarDecl *var_decl = (clang::VarDecl *)decl;
2092 QualType qual_type = var_decl->getTypeSourceInfo()->getType();2120 clang::QualType qual_type = var_decl->getTypeSourceInfo()->getType();
2093 AstNode *init_node = nullptr;2121 AstNode *init_node = nullptr;
2094 if (var_decl->hasInit()) {2122 if (var_decl->hasInit()) {
2095 init_node = trans_expr(c, ResultUsedYes, scope, var_decl->getInit(), TransRValue);2123 init_node = trans_expr(c, ResultUsedYes, scope, var_decl->getInit(), TransRValue);
...@@ -2114,220 +2142,220 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt...@@ -2114,220 +2142,220 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt
2114 scope_block->node->data.block.statements.append(node);2142 scope_block->node->data.block.statements.append(node);
2115 continue;2143 continue;
2116 }2144 }
2117 case Decl::AccessSpec:2145 case clang::Decl::AccessSpec:
2118 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind AccessSpec");2146 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind AccessSpec");
2119 return ErrorUnexpected;2147 return ErrorUnexpected;
2120 case Decl::Block:2148 case clang::Decl::Block:
2121 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Block");2149 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Block");
2122 return ErrorUnexpected;2150 return ErrorUnexpected;
2123 case Decl::Captured:2151 case clang::Decl::Captured:
2124 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Captured");2152 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Captured");
2125 return ErrorUnexpected;2153 return ErrorUnexpected;
2126 case Decl::ClassScopeFunctionSpecialization:2154 case clang::Decl::ClassScopeFunctionSpecialization:
2127 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassScopeFunctionSpecialization");2155 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassScopeFunctionSpecialization");
2128 return ErrorUnexpected;2156 return ErrorUnexpected;
2129 case Decl::Empty:2157 case clang::Decl::Empty:
2130 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Empty");2158 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Empty");
2131 return ErrorUnexpected;2159 return ErrorUnexpected;
2132 case Decl::Export:2160 case clang::Decl::Export:
2133 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Export");2161 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Export");
2134 return ErrorUnexpected;2162 return ErrorUnexpected;
2135 case Decl::ExternCContext:2163 case clang::Decl::ExternCContext:
2136 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ExternCContext");2164 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ExternCContext");
2137 return ErrorUnexpected;2165 return ErrorUnexpected;
2138 case Decl::FileScopeAsm:2166 case clang::Decl::FileScopeAsm:
2139 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FileScopeAsm");2167 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FileScopeAsm");
2140 return ErrorUnexpected;2168 return ErrorUnexpected;
2141 case Decl::Friend:2169 case clang::Decl::Friend:
2142 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Friend");2170 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Friend");
2143 return ErrorUnexpected;2171 return ErrorUnexpected;
2144 case Decl::FriendTemplate:2172 case clang::Decl::FriendTemplate:
2145 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FriendTemplate");2173 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FriendTemplate");
2146 return ErrorUnexpected;2174 return ErrorUnexpected;
2147 case Decl::Import:2175 case clang::Decl::Import:
2148 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Import");2176 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Import");
2149 return ErrorUnexpected;2177 return ErrorUnexpected;
2150 case Decl::LinkageSpec:2178 case clang::Decl::LinkageSpec:
2151 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind LinkageSpec");2179 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind LinkageSpec");
2152 return ErrorUnexpected;2180 return ErrorUnexpected;
2153 case Decl::Label:2181 case clang::Decl::Label:
2154 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Label");2182 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Label");
2155 return ErrorUnexpected;2183 return ErrorUnexpected;
2156 case Decl::Namespace:2184 case clang::Decl::Namespace:
2157 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Namespace");2185 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Namespace");
2158 return ErrorUnexpected;2186 return ErrorUnexpected;
2159 case Decl::NamespaceAlias:2187 case clang::Decl::NamespaceAlias:
2160 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind NamespaceAlias");2188 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind NamespaceAlias");
2161 return ErrorUnexpected;2189 return ErrorUnexpected;
2162 case Decl::ObjCCompatibleAlias:2190 case clang::Decl::ObjCCompatibleAlias:
2163 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCompatibleAlias");2191 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCompatibleAlias");
2164 return ErrorUnexpected;2192 return ErrorUnexpected;
2165 case Decl::ObjCCategory:2193 case clang::Decl::ObjCCategory:
2166 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCategory");2194 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCategory");
2167 return ErrorUnexpected;2195 return ErrorUnexpected;
2168 case Decl::ObjCCategoryImpl:2196 case clang::Decl::ObjCCategoryImpl:
2169 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCategoryImpl");2197 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCategoryImpl");
2170 return ErrorUnexpected;2198 return ErrorUnexpected;
2171 case Decl::ObjCImplementation:2199 case clang::Decl::ObjCImplementation:
2172 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCImplementation");2200 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCImplementation");
2173 return ErrorUnexpected;2201 return ErrorUnexpected;
2174 case Decl::ObjCInterface:2202 case clang::Decl::ObjCInterface:
2175 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCInterface");2203 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCInterface");
2176 return ErrorUnexpected;2204 return ErrorUnexpected;
2177 case Decl::ObjCProtocol:2205 case clang::Decl::ObjCProtocol:
2178 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCProtocol");2206 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCProtocol");
2179 return ErrorUnexpected;2207 return ErrorUnexpected;
2180 case Decl::ObjCMethod:2208 case clang::Decl::ObjCMethod:
2181 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCMethod");2209 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCMethod");
2182 return ErrorUnexpected;2210 return ErrorUnexpected;
2183 case Decl::ObjCProperty:2211 case clang::Decl::ObjCProperty:
2184 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCProperty");2212 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCProperty");
2185 return ErrorUnexpected;2213 return ErrorUnexpected;
2186 case Decl::BuiltinTemplate:2214 case clang::Decl::BuiltinTemplate:
2187 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind BuiltinTemplate");2215 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind BuiltinTemplate");
2188 return ErrorUnexpected;2216 return ErrorUnexpected;
2189 case Decl::ClassTemplate:2217 case clang::Decl::ClassTemplate:
2190 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplate");2218 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplate");
2191 return ErrorUnexpected;2219 return ErrorUnexpected;
2192 case Decl::FunctionTemplate:2220 case clang::Decl::FunctionTemplate:
2193 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FunctionTemplate");2221 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FunctionTemplate");
2194 return ErrorUnexpected;2222 return ErrorUnexpected;
2195 case Decl::TypeAliasTemplate:2223 case clang::Decl::TypeAliasTemplate:
2196 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TypeAliasTemplate");2224 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TypeAliasTemplate");
2197 return ErrorUnexpected;2225 return ErrorUnexpected;
2198 case Decl::VarTemplate:2226 case clang::Decl::VarTemplate:
2199 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplate");2227 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplate");
2200 return ErrorUnexpected;2228 return ErrorUnexpected;
2201 case Decl::TemplateTemplateParm:2229 case clang::Decl::TemplateTemplateParm:
2202 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TemplateTemplateParm");2230 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TemplateTemplateParm");
2203 return ErrorUnexpected;2231 return ErrorUnexpected;
2204 case Decl::Enum:2232 case clang::Decl::Enum:
2205 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Enum");2233 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Enum");
2206 return ErrorUnexpected;2234 return ErrorUnexpected;
2207 case Decl::Record:2235 case clang::Decl::Record:
2208 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Record");2236 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Record");
2209 return ErrorUnexpected;2237 return ErrorUnexpected;
2210 case Decl::CXXRecord:2238 case clang::Decl::CXXRecord:
2211 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXRecord");2239 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXRecord");
2212 return ErrorUnexpected;2240 return ErrorUnexpected;
2213 case Decl::ClassTemplateSpecialization:2241 case clang::Decl::ClassTemplateSpecialization:
2214 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplateSpecialization");2242 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplateSpecialization");
2215 return ErrorUnexpected;2243 return ErrorUnexpected;
2216 case Decl::ClassTemplatePartialSpecialization:2244 case clang::Decl::ClassTemplatePartialSpecialization:
2217 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplatePartialSpecialization");2245 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplatePartialSpecialization");
2218 return ErrorUnexpected;2246 return ErrorUnexpected;
2219 case Decl::TemplateTypeParm:2247 case clang::Decl::TemplateTypeParm:
2220 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TemplateTypeParm");2248 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TemplateTypeParm");
2221 return ErrorUnexpected;2249 return ErrorUnexpected;
2222 case Decl::ObjCTypeParam:2250 case clang::Decl::ObjCTypeParam:
2223 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCTypeParam");2251 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCTypeParam");
2224 return ErrorUnexpected;2252 return ErrorUnexpected;
2225 case Decl::TypeAlias:2253 case clang::Decl::TypeAlias:
2226 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TypeAlias");2254 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TypeAlias");
2227 return ErrorUnexpected;2255 return ErrorUnexpected;
2228 case Decl::Typedef:2256 case clang::Decl::Typedef:
2229 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Typedef");2257 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Typedef");
2230 return ErrorUnexpected;2258 return ErrorUnexpected;
2231 case Decl::UnresolvedUsingTypename:2259 case clang::Decl::UnresolvedUsingTypename:
2232 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UnresolvedUsingTypename");2260 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UnresolvedUsingTypename");
2233 return ErrorUnexpected;2261 return ErrorUnexpected;
2234 case Decl::Using:2262 case clang::Decl::Using:
2235 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Using");2263 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Using");
2236 return ErrorUnexpected;2264 return ErrorUnexpected;
2237 case Decl::UsingDirective:2265 case clang::Decl::UsingDirective:
2238 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingDirective");2266 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingDirective");
2239 return ErrorUnexpected;2267 return ErrorUnexpected;
2240 case Decl::UsingPack:2268 case clang::Decl::UsingPack:
2241 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingPack");2269 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingPack");
2242 return ErrorUnexpected;2270 return ErrorUnexpected;
2243 case Decl::UsingShadow:2271 case clang::Decl::UsingShadow:
2244 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingShadow");2272 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingShadow");
2245 return ErrorUnexpected;2273 return ErrorUnexpected;
2246 case Decl::ConstructorUsingShadow:2274 case clang::Decl::ConstructorUsingShadow:
2247 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ConstructorUsingShadow");2275 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ConstructorUsingShadow");
2248 return ErrorUnexpected;2276 return ErrorUnexpected;
2249 case Decl::Binding:2277 case clang::Decl::Binding:
2250 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Binding");2278 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Binding");
2251 return ErrorUnexpected;2279 return ErrorUnexpected;
2252 case Decl::Field:2280 case clang::Decl::Field:
2253 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Field");2281 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Field");
2254 return ErrorUnexpected;2282 return ErrorUnexpected;
2255 case Decl::ObjCAtDefsField:2283 case clang::Decl::ObjCAtDefsField:
2256 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCAtDefsField");2284 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCAtDefsField");
2257 return ErrorUnexpected;2285 return ErrorUnexpected;
2258 case Decl::ObjCIvar:2286 case clang::Decl::ObjCIvar:
2259 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCIvar");2287 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCIvar");
2260 return ErrorUnexpected;2288 return ErrorUnexpected;
2261 case Decl::Function:2289 case clang::Decl::Function:
2262 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Function");2290 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Function");
2263 return ErrorUnexpected;2291 return ErrorUnexpected;
2264 case Decl::CXXDeductionGuide:2292 case clang::Decl::CXXDeductionGuide:
2265 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXDeductionGuide");2293 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXDeductionGuide");
2266 return ErrorUnexpected;2294 return ErrorUnexpected;
2267 case Decl::CXXMethod:2295 case clang::Decl::CXXMethod:
2268 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXMethod");2296 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXMethod");
2269 return ErrorUnexpected;2297 return ErrorUnexpected;
2270 case Decl::CXXConstructor:2298 case clang::Decl::CXXConstructor:
2271 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXConstructor");2299 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXConstructor");
2272 return ErrorUnexpected;2300 return ErrorUnexpected;
2273 case Decl::CXXConversion:2301 case clang::Decl::CXXConversion:
2274 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXConversion");2302 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXConversion");
2275 return ErrorUnexpected;2303 return ErrorUnexpected;
2276 case Decl::CXXDestructor:2304 case clang::Decl::CXXDestructor:
2277 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXDestructor");2305 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXDestructor");
2278 return ErrorUnexpected;2306 return ErrorUnexpected;
2279 case Decl::MSProperty:2307 case clang::Decl::MSProperty:
2280 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind MSProperty");2308 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind MSProperty");
2281 return ErrorUnexpected;2309 return ErrorUnexpected;
2282 case Decl::NonTypeTemplateParm:2310 case clang::Decl::NonTypeTemplateParm:
2283 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind NonTypeTemplateParm");2311 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind NonTypeTemplateParm");
2284 return ErrorUnexpected;2312 return ErrorUnexpected;
2285 case Decl::Decomposition:2313 case clang::Decl::Decomposition:
2286 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Decomposition");2314 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Decomposition");
2287 return ErrorUnexpected;2315 return ErrorUnexpected;
2288 case Decl::ImplicitParam:2316 case clang::Decl::ImplicitParam:
2289 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ImplicitParam");2317 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ImplicitParam");
2290 return ErrorUnexpected;2318 return ErrorUnexpected;
2291 case Decl::OMPCapturedExpr:2319 case clang::Decl::OMPCapturedExpr:
2292 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPCapturedExpr");2320 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPCapturedExpr");
2293 return ErrorUnexpected;2321 return ErrorUnexpected;
2294 case Decl::ParmVar:2322 case clang::Decl::ParmVar:
2295 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ParmVar");2323 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ParmVar");
2296 return ErrorUnexpected;2324 return ErrorUnexpected;
2297 case Decl::VarTemplateSpecialization:2325 case clang::Decl::VarTemplateSpecialization:
2298 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplateSpecialization");2326 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplateSpecialization");
2299 return ErrorUnexpected;2327 return ErrorUnexpected;
2300 case Decl::VarTemplatePartialSpecialization:2328 case clang::Decl::VarTemplatePartialSpecialization:
2301 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplatePartialSpecialization");2329 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplatePartialSpecialization");
2302 return ErrorUnexpected;2330 return ErrorUnexpected;
2303 case Decl::EnumConstant:2331 case clang::Decl::EnumConstant:
2304 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind EnumConstant");2332 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind EnumConstant");
2305 return ErrorUnexpected;2333 return ErrorUnexpected;
2306 case Decl::IndirectField:2334 case clang::Decl::IndirectField:
2307 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind IndirectField");2335 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind IndirectField");
2308 return ErrorUnexpected;2336 return ErrorUnexpected;
2309 case Decl::OMPDeclareReduction:2337 case clang::Decl::OMPDeclareReduction:
2310 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPDeclareReduction");2338 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPDeclareReduction");
2311 return ErrorUnexpected;2339 return ErrorUnexpected;
2312 case Decl::UnresolvedUsingValue:2340 case clang::Decl::UnresolvedUsingValue:
2313 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UnresolvedUsingValue");2341 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UnresolvedUsingValue");
2314 return ErrorUnexpected;2342 return ErrorUnexpected;
2315 case Decl::OMPThreadPrivate:2343 case clang::Decl::OMPThreadPrivate:
2316 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPThreadPrivate");2344 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPThreadPrivate");
2317 return ErrorUnexpected;2345 return ErrorUnexpected;
2318 case Decl::ObjCPropertyImpl:2346 case clang::Decl::ObjCPropertyImpl:
2319 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCPropertyImpl");2347 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCPropertyImpl");
2320 return ErrorUnexpected;2348 return ErrorUnexpected;
2321 case Decl::PragmaComment:2349 case clang::Decl::PragmaComment:
2322 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind PragmaComment");2350 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind PragmaComment");
2323 return ErrorUnexpected;2351 return ErrorUnexpected;
2324 case Decl::PragmaDetectMismatch:2352 case clang::Decl::PragmaDetectMismatch:
2325 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind PragmaDetectMismatch");2353 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind PragmaDetectMismatch");
2326 return ErrorUnexpected;2354 return ErrorUnexpected;
2327 case Decl::StaticAssert:2355 case clang::Decl::StaticAssert:
2328 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind StaticAssert");2356 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind StaticAssert");
2329 return ErrorUnexpected;2357 return ErrorUnexpected;
2330 case Decl::TranslationUnit:2358 case clang::Decl::TranslationUnit:
2331 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TranslationUnit");2359 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TranslationUnit");
2332 return ErrorUnexpected;2360 return ErrorUnexpected;
2333 }2361 }
...@@ -2354,7 +2382,7 @@ static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type)...@@ -2354,7 +2382,7 @@ static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type)
2354 return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast);2382 return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast);
2355}2383}
23562384
2357static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval) {2385static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval) {
2358 AstNode *res = trans_expr(c, result_used, scope, expr, lrval);2386 AstNode *res = trans_expr(c, result_used, scope, expr, lrval);
2359 if (res == nullptr)2387 if (res == nullptr)
2360 return nullptr;2388 return nullptr;
...@@ -2391,131 +2419,133 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *...@@ -2391,131 +2419,133 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
2391 }2419 }
23922420
23932421
2394 const Type *ty = get_expr_qual_type_before_implicit_cast(c, expr).getTypePtr();2422 const clang::Type *ty = get_expr_qual_type_before_implicit_cast(c, expr).getTypePtr();
2395 auto classs = ty->getTypeClass();2423 auto classs = ty->getTypeClass();
2396 switch (classs) {2424 switch (classs) {
2397 case Type::Builtin:2425 case clang::Type::Builtin:
2398 {2426 {
2399 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);2427 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);
2400 switch (builtin_ty->getKind()) {2428 switch (builtin_ty->getKind()) {
2401 case BuiltinType::Bool:2429 case clang::BuiltinType::Bool:
2402 case BuiltinType::Char_U:2430 case clang::BuiltinType::Char_U:
2403 case BuiltinType::UChar:2431 case clang::BuiltinType::UChar:
2404 case BuiltinType::Char_S:2432 case clang::BuiltinType::Char_S:
2405 case BuiltinType::SChar:2433 case clang::BuiltinType::SChar:
2406 case BuiltinType::UShort:2434 case clang::BuiltinType::UShort:
2407 case BuiltinType::UInt:2435 case clang::BuiltinType::UInt:
2408 case BuiltinType::ULong:2436 case clang::BuiltinType::ULong:
2409 case BuiltinType::ULongLong:2437 case clang::BuiltinType::ULongLong:
2410 case BuiltinType::Short:2438 case clang::BuiltinType::Short:
2411 case BuiltinType::Int:2439 case clang::BuiltinType::Int:
2412 case BuiltinType::Long:2440 case clang::BuiltinType::Long:
2413 case BuiltinType::LongLong:2441 case clang::BuiltinType::LongLong:
2414 case BuiltinType::UInt128:2442 case clang::BuiltinType::UInt128:
2415 case BuiltinType::Int128:2443 case clang::BuiltinType::Int128:
2416 case BuiltinType::Float:2444 case clang::BuiltinType::Float:
2417 case BuiltinType::Double:2445 case clang::BuiltinType::Double:
2418 case BuiltinType::Float128:2446 case clang::BuiltinType::Float128:
2419 case BuiltinType::LongDouble:2447 case clang::BuiltinType::LongDouble:
2420 case BuiltinType::WChar_U:2448 case clang::BuiltinType::WChar_U:
2421 case BuiltinType::Char8:2449 case clang::BuiltinType::Char8:
2422 case BuiltinType::Char16:2450 case clang::BuiltinType::Char16:
2423 case BuiltinType::Char32:2451 case clang::BuiltinType::Char32:
2424 case BuiltinType::WChar_S:2452 case clang::BuiltinType::WChar_S:
2425 case BuiltinType::Float16:2453 case clang::BuiltinType::Float16:
2426 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));2454 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
2427 case BuiltinType::NullPtr:2455 case clang::BuiltinType::NullPtr:
2428 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));2456 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,
24292457 trans_create_node_unsigned(c, 0));
2430 case BuiltinType::Void:2458
2431 case BuiltinType::Half:2459 case clang::BuiltinType::Void:
2432 case BuiltinType::ObjCId:2460 case clang::BuiltinType::Half:
2433 case BuiltinType::ObjCClass:2461 case clang::BuiltinType::ObjCId:
2434 case BuiltinType::ObjCSel:2462 case clang::BuiltinType::ObjCClass:
2435 case BuiltinType::OMPArraySection:2463 case clang::BuiltinType::ObjCSel:
2436 case BuiltinType::Dependent:2464 case clang::BuiltinType::OMPArraySection:
2437 case BuiltinType::Overload:2465 case clang::BuiltinType::Dependent:
2438 case BuiltinType::BoundMember:2466 case clang::BuiltinType::Overload:
2439 case BuiltinType::PseudoObject:2467 case clang::BuiltinType::BoundMember:
2440 case BuiltinType::UnknownAny:2468 case clang::BuiltinType::PseudoObject:
2441 case BuiltinType::BuiltinFn:2469 case clang::BuiltinType::UnknownAny:
2442 case BuiltinType::ARCUnbridgedCast:2470 case clang::BuiltinType::BuiltinFn:
2443 case BuiltinType::OCLImage1dRO:2471 case clang::BuiltinType::ARCUnbridgedCast:
2444 case BuiltinType::OCLImage1dArrayRO:2472 case clang::BuiltinType::OCLImage1dRO:
2445 case BuiltinType::OCLImage1dBufferRO:2473 case clang::BuiltinType::OCLImage1dArrayRO:
2446 case BuiltinType::OCLImage2dRO:2474 case clang::BuiltinType::OCLImage1dBufferRO:
2447 case BuiltinType::OCLImage2dArrayRO:2475 case clang::BuiltinType::OCLImage2dRO:
2448 case BuiltinType::OCLImage2dDepthRO:2476 case clang::BuiltinType::OCLImage2dArrayRO:
2449 case BuiltinType::OCLImage2dArrayDepthRO:2477 case clang::BuiltinType::OCLImage2dDepthRO:
2450 case BuiltinType::OCLImage2dMSAARO:2478 case clang::BuiltinType::OCLImage2dArrayDepthRO:
2451 case BuiltinType::OCLImage2dArrayMSAARO:2479 case clang::BuiltinType::OCLImage2dMSAARO:
2452 case BuiltinType::OCLImage2dMSAADepthRO:2480 case clang::BuiltinType::OCLImage2dArrayMSAARO:
2453 case BuiltinType::OCLImage2dArrayMSAADepthRO:2481 case clang::BuiltinType::OCLImage2dMSAADepthRO:
2454 case BuiltinType::OCLImage3dRO:2482 case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:
2455 case BuiltinType::OCLImage1dWO:2483 case clang::BuiltinType::OCLImage3dRO:
2456 case BuiltinType::OCLImage1dArrayWO:2484 case clang::BuiltinType::OCLImage1dWO:
2457 case BuiltinType::OCLImage1dBufferWO:2485 case clang::BuiltinType::OCLImage1dArrayWO:
2458 case BuiltinType::OCLImage2dWO:2486 case clang::BuiltinType::OCLImage1dBufferWO:
2459 case BuiltinType::OCLImage2dArrayWO:2487 case clang::BuiltinType::OCLImage2dWO:
2460 case BuiltinType::OCLImage2dDepthWO:2488 case clang::BuiltinType::OCLImage2dArrayWO:
2461 case BuiltinType::OCLImage2dArrayDepthWO:2489 case clang::BuiltinType::OCLImage2dDepthWO:
2462 case BuiltinType::OCLImage2dMSAAWO:2490 case clang::BuiltinType::OCLImage2dArrayDepthWO:
2463 case BuiltinType::OCLImage2dArrayMSAAWO:2491 case clang::BuiltinType::OCLImage2dMSAAWO:
2464 case BuiltinType::OCLImage2dMSAADepthWO:2492 case clang::BuiltinType::OCLImage2dArrayMSAAWO:
2465 case BuiltinType::OCLImage2dArrayMSAADepthWO:2493 case clang::BuiltinType::OCLImage2dMSAADepthWO:
2466 case BuiltinType::OCLImage3dWO:2494 case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:
2467 case BuiltinType::OCLImage1dRW:2495 case clang::BuiltinType::OCLImage3dWO:
2468 case BuiltinType::OCLImage1dArrayRW:2496 case clang::BuiltinType::OCLImage1dRW:
2469 case BuiltinType::OCLImage1dBufferRW:2497 case clang::BuiltinType::OCLImage1dArrayRW:
2470 case BuiltinType::OCLImage2dRW:2498 case clang::BuiltinType::OCLImage1dBufferRW:
2471 case BuiltinType::OCLImage2dArrayRW:2499 case clang::BuiltinType::OCLImage2dRW:
2472 case BuiltinType::OCLImage2dDepthRW:2500 case clang::BuiltinType::OCLImage2dArrayRW:
2473 case BuiltinType::OCLImage2dArrayDepthRW:2501 case clang::BuiltinType::OCLImage2dDepthRW:
2474 case BuiltinType::OCLImage2dMSAARW:2502 case clang::BuiltinType::OCLImage2dArrayDepthRW:
2475 case BuiltinType::OCLImage2dArrayMSAARW:2503 case clang::BuiltinType::OCLImage2dMSAARW:
2476 case BuiltinType::OCLImage2dMSAADepthRW:2504 case clang::BuiltinType::OCLImage2dArrayMSAARW:
2477 case BuiltinType::OCLImage2dArrayMSAADepthRW:2505 case clang::BuiltinType::OCLImage2dMSAADepthRW:
2478 case BuiltinType::OCLImage3dRW:2506 case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:
2479 case BuiltinType::OCLSampler:2507 case clang::BuiltinType::OCLImage3dRW:
2480 case BuiltinType::OCLEvent:2508 case clang::BuiltinType::OCLSampler:
2481 case BuiltinType::OCLClkEvent:2509 case clang::BuiltinType::OCLEvent:
2482 case BuiltinType::OCLQueue:2510 case clang::BuiltinType::OCLClkEvent:
2483 case BuiltinType::OCLReserveID:2511 case clang::BuiltinType::OCLQueue:
2484 case BuiltinType::ShortAccum:2512 case clang::BuiltinType::OCLReserveID:
2485 case BuiltinType::Accum:2513 case clang::BuiltinType::ShortAccum:
2486 case BuiltinType::LongAccum:2514 case clang::BuiltinType::Accum:
2487 case BuiltinType::UShortAccum:2515 case clang::BuiltinType::LongAccum:
2488 case BuiltinType::UAccum:2516 case clang::BuiltinType::UShortAccum:
2489 case BuiltinType::ULongAccum:2517 case clang::BuiltinType::UAccum:
2490 case BuiltinType::ShortFract:2518 case clang::BuiltinType::ULongAccum:
2491 case BuiltinType::Fract:2519 case clang::BuiltinType::ShortFract:
2492 case BuiltinType::LongFract:2520 case clang::BuiltinType::Fract:
2493 case BuiltinType::UShortFract:2521 case clang::BuiltinType::LongFract:
2494 case BuiltinType::UFract:2522 case clang::BuiltinType::UShortFract:
2495 case BuiltinType::ULongFract:2523 case clang::BuiltinType::UFract:
2496 case BuiltinType::SatShortAccum:2524 case clang::BuiltinType::ULongFract:
2497 case BuiltinType::SatAccum:2525 case clang::BuiltinType::SatShortAccum:
2498 case BuiltinType::SatLongAccum:2526 case clang::BuiltinType::SatAccum:
2499 case BuiltinType::SatUShortAccum:2527 case clang::BuiltinType::SatLongAccum:
2500 case BuiltinType::SatUAccum:2528 case clang::BuiltinType::SatUShortAccum:
2501 case BuiltinType::SatULongAccum:2529 case clang::BuiltinType::SatUAccum:
2502 case BuiltinType::SatShortFract:2530 case clang::BuiltinType::SatULongAccum:
2503 case BuiltinType::SatFract:2531 case clang::BuiltinType::SatShortFract:
2504 case BuiltinType::SatLongFract:2532 case clang::BuiltinType::SatFract:
2505 case BuiltinType::SatUShortFract:2533 case clang::BuiltinType::SatLongFract:
2506 case BuiltinType::SatUFract:2534 case clang::BuiltinType::SatUShortFract:
2507 case BuiltinType::SatULongFract:2535 case clang::BuiltinType::SatUFract:
2536 case clang::BuiltinType::SatULongFract:
2508 return res;2537 return res;
2509 }2538 }
2510 break;2539 break;
2511 }2540 }
2512 case Type::Pointer:2541 case clang::Type::Pointer:
2513 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));2542 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,
2543 trans_create_node_unsigned(c, 0));
25142544
2515 case Type::Typedef:2545 case clang::Type::Typedef:
2516 {2546 {
2517 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);2547 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
2518 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();2548 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
2519 auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());2549 auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());
2520 if (existing_entry) {2550 if (existing_entry) {
2521 return existing_entry->value;2551 return existing_entry->value;
...@@ -2524,79 +2554,79 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *...@@ -2524,79 +2554,79 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
2524 return res;2554 return res;
2525 }2555 }
25262556
2527 case Type::Enum:2557 case clang::Type::Enum:
2528 {2558 {
2529 const EnumType *enum_ty = static_cast<const EnumType*>(ty);2559 const clang::EnumType *enum_ty = static_cast<const clang::EnumType*>(ty);
2530 AstNode *enum_type = resolve_enum_decl(c, enum_ty->getDecl());2560 AstNode *enum_type = resolve_enum_decl(c, enum_ty->getDecl());
2531 return to_enum_zero_cmp(c, res, enum_type);2561 return to_enum_zero_cmp(c, res, enum_type);
2532 }2562 }
25332563
2534 case Type::Elaborated:2564 case clang::Type::Elaborated:
2535 {2565 {
2536 const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);2566 const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty);
2537 switch (elaborated_ty->getKeyword()) {2567 switch (elaborated_ty->getKeyword()) {
2538 case ETK_Enum: {2568 case clang::ETK_Enum: {
2539 AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getLocStart());2569 AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getLocStart());
2540 return to_enum_zero_cmp(c, res, enum_type);2570 return to_enum_zero_cmp(c, res, enum_type);
2541 }2571 }
2542 case ETK_Struct:2572 case clang::ETK_Struct:
2543 case ETK_Union:2573 case clang::ETK_Union:
2544 case ETK_Interface:2574 case clang::ETK_Interface:
2545 case ETK_Class:2575 case clang::ETK_Class:
2546 case ETK_Typename:2576 case clang::ETK_Typename:
2547 case ETK_None:2577 case clang::ETK_None:
2548 return res;2578 return res;
2549 }2579 }
2550 }2580 }
25512581
2552 case Type::FunctionProto:2582 case clang::Type::FunctionProto:
2553 case Type::Record:2583 case clang::Type::Record:
2554 case Type::ConstantArray:2584 case clang::Type::ConstantArray:
2555 case Type::Paren:2585 case clang::Type::Paren:
2556 case Type::Decayed:2586 case clang::Type::Decayed:
2557 case Type::Attributed:2587 case clang::Type::Attributed:
2558 case Type::IncompleteArray:2588 case clang::Type::IncompleteArray:
2559 case Type::BlockPointer:2589 case clang::Type::BlockPointer:
2560 case Type::LValueReference:2590 case clang::Type::LValueReference:
2561 case Type::RValueReference:2591 case clang::Type::RValueReference:
2562 case Type::MemberPointer:2592 case clang::Type::MemberPointer:
2563 case Type::VariableArray:2593 case clang::Type::VariableArray:
2564 case Type::DependentSizedArray:2594 case clang::Type::DependentSizedArray:
2565 case Type::DependentSizedExtVector:2595 case clang::Type::DependentSizedExtVector:
2566 case Type::Vector:2596 case clang::Type::Vector:
2567 case Type::ExtVector:2597 case clang::Type::ExtVector:
2568 case Type::FunctionNoProto:2598 case clang::Type::FunctionNoProto:
2569 case Type::UnresolvedUsing:2599 case clang::Type::UnresolvedUsing:
2570 case Type::Adjusted:2600 case clang::Type::Adjusted:
2571 case Type::TypeOfExpr:2601 case clang::Type::TypeOfExpr:
2572 case Type::TypeOf:2602 case clang::Type::TypeOf:
2573 case Type::Decltype:2603 case clang::Type::Decltype:
2574 case Type::UnaryTransform:2604 case clang::Type::UnaryTransform:
2575 case Type::TemplateTypeParm:2605 case clang::Type::TemplateTypeParm:
2576 case Type::SubstTemplateTypeParm:2606 case clang::Type::SubstTemplateTypeParm:
2577 case Type::SubstTemplateTypeParmPack:2607 case clang::Type::SubstTemplateTypeParmPack:
2578 case Type::TemplateSpecialization:2608 case clang::Type::TemplateSpecialization:
2579 case Type::Auto:2609 case clang::Type::Auto:
2580 case Type::InjectedClassName:2610 case clang::Type::InjectedClassName:
2581 case Type::DependentName:2611 case clang::Type::DependentName:
2582 case Type::DependentTemplateSpecialization:2612 case clang::Type::DependentTemplateSpecialization:
2583 case Type::PackExpansion:2613 case clang::Type::PackExpansion:
2584 case Type::ObjCObject:2614 case clang::Type::ObjCObject:
2585 case Type::ObjCInterface:2615 case clang::Type::ObjCInterface:
2586 case Type::Complex:2616 case clang::Type::Complex:
2587 case Type::ObjCObjectPointer:2617 case clang::Type::ObjCObjectPointer:
2588 case Type::Atomic:2618 case clang::Type::Atomic:
2589 case Type::Pipe:2619 case clang::Type::Pipe:
2590 case Type::ObjCTypeParam:2620 case clang::Type::ObjCTypeParam:
2591 case Type::DeducedTemplateSpecialization:2621 case clang::Type::DeducedTemplateSpecialization:
2592 case Type::DependentAddressSpace:2622 case clang::Type::DependentAddressSpace:
2593 case Type::DependentVector:2623 case clang::Type::DependentVector:
2594 return res;2624 return res;
2595 }2625 }
2596 zig_unreachable();2626 zig_unreachable();
2597}2627}
25982628
2599static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) {2629static AstNode *trans_while_loop(Context *c, TransScope *scope, const clang::WhileStmt *stmt) {
2600 TransScopeWhile *while_scope = trans_scope_while_create(c, scope);2630 TransScopeWhile *while_scope = trans_scope_while_create(c, scope);
26012631
2602 while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);2632 while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
...@@ -2611,7 +2641,7 @@ static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt...@@ -2611,7 +2641,7 @@ static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt
2611 return while_scope->node;2641 return while_scope->node;
2612}2642}
26132643
2614static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *stmt) {2644static AstNode *trans_if_statement(Context *c, TransScope *scope, const clang::IfStmt *stmt) {
2615 // if (c) t2645 // if (c) t
2616 // if (c) t else e2646 // if (c) t else e
2617 AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);2647 AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);
...@@ -2633,7 +2663,7 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *...@@ -2633,7 +2663,7 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
2633 return if_node;2663 return if_node;
2634}2664}
26352665
2636static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) {2666static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::CallExpr *stmt) {
2637 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);2667 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
26382668
2639 AstNode *callee_raw_node = trans_expr(c, ResultUsedYes, scope, stmt->getCallee(), TransRValue);2669 AstNode *callee_raw_node = trans_expr(c, ResultUsedYes, scope, stmt->getCallee(), TransRValue);
...@@ -2641,16 +2671,16 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *...@@ -2641,16 +2671,16 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
2641 return nullptr;2671 return nullptr;
26422672
2643 bool is_ptr = false;2673 bool is_ptr = false;
2644 const FunctionProtoType *fn_ty = qual_type_get_fn_proto(stmt->getCallee()->getType(), &is_ptr);2674 const clang::FunctionProtoType *fn_ty = qual_type_get_fn_proto(stmt->getCallee()->getType(), &is_ptr);
2645 AstNode *callee_node = nullptr;2675 AstNode *callee_node = nullptr;
2646 if (is_ptr && fn_ty) {2676 if (is_ptr && fn_ty) {
2647 if (stmt->getCallee()->getStmtClass() == Stmt::ImplicitCastExprClass) {2677 if (stmt->getCallee()->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
2648 const ImplicitCastExpr *implicit_cast = static_cast<const ImplicitCastExpr *>(stmt->getCallee());2678 const clang::ImplicitCastExpr *implicit_cast = static_cast<const clang::ImplicitCastExpr *>(stmt->getCallee());
2649 if (implicit_cast->getCastKind() == CK_FunctionToPointerDecay) {2679 if (implicit_cast->getCastKind() == clang::CK_FunctionToPointerDecay) {
2650 if (implicit_cast->getSubExpr()->getStmtClass() == Stmt::DeclRefExprClass) {2680 if (implicit_cast->getSubExpr()->getStmtClass() == clang::Stmt::DeclRefExprClass) {
2651 const DeclRefExpr *decl_ref = static_cast<const DeclRefExpr *>(implicit_cast->getSubExpr());2681 const clang::DeclRefExpr *decl_ref = static_cast<const clang::DeclRefExpr *>(implicit_cast->getSubExpr());
2652 const Decl *decl = decl_ref->getFoundDecl();2682 const clang::Decl *decl = decl_ref->getFoundDecl();
2653 if (decl->getKind() == Decl::Function) {2683 if (decl->getKind() == clang::Decl::Function) {
2654 callee_node = callee_raw_node;2684 callee_node = callee_raw_node;
2655 }2685 }
2656 }2686 }
...@@ -2666,7 +2696,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *...@@ -2666,7 +2696,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
2666 node->data.fn_call_expr.fn_ref_expr = callee_node;2696 node->data.fn_call_expr.fn_ref_expr = callee_node;
26672697
2668 unsigned num_args = stmt->getNumArgs();2698 unsigned num_args = stmt->getNumArgs();
2669 const Expr * const* args = stmt->getArgs();2699 const clang::Expr * const* args = stmt->getArgs();
2670 for (unsigned i = 0; i < num_args; i += 1) {2700 for (unsigned i = 0; i < num_args; i += 1) {
2671 AstNode *arg_node = trans_expr(c, ResultUsedYes, scope, args[i], TransRValue);2701 AstNode *arg_node = trans_expr(c, ResultUsedYes, scope, args[i], TransRValue);
2672 if (arg_node == nullptr)2702 if (arg_node == nullptr)
...@@ -2682,7 +2712,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *...@@ -2682,7 +2712,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
2682 return node;2712 return node;
2683}2713}
26842714
2685static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExpr *stmt) {2715static AstNode *trans_member_expr(Context *c, TransScope *scope, const clang::MemberExpr *stmt) {
2686 AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);2716 AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);
2687 if (container_node == nullptr)2717 if (container_node == nullptr)
2688 return nullptr;2718 return nullptr;
...@@ -2697,7 +2727,7 @@ static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExp...@@ -2697,7 +2727,7 @@ static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExp
2697 return node;2727 return node;
2698}2728}
26992729
2700static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const ArraySubscriptExpr *stmt) {2730static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const clang::ArraySubscriptExpr *stmt) {
2701 AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);2731 AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);
2702 if (container_node == nullptr)2732 if (container_node == nullptr)
2703 return nullptr;2733 return nullptr;
...@@ -2714,7 +2744,7 @@ static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const...@@ -2714,7 +2744,7 @@ static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const
2714}2744}
27152745
2716static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, TransScope *scope,2746static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, TransScope *scope,
2717 const CStyleCastExpr *stmt, TransLRValue lrvalue)2747 const clang::CStyleCastExpr *stmt, TransLRValue lrvalue)
2718{2748{
2719 AstNode *sub_expr_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), lrvalue);2749 AstNode *sub_expr_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), lrvalue);
2720 if (sub_expr_node == nullptr)2750 if (sub_expr_node == nullptr)
...@@ -2724,7 +2754,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran...@@ -2724,7 +2754,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran
2724}2754}
27252755
2726static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope,2756static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope,
2727 const UnaryExprOrTypeTraitExpr *stmt)2757 const clang::UnaryExprOrTypeTraitExpr *stmt)
2728{2758{
2729 AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getLocStart());2759 AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getLocStart());
2730 if (type_node == nullptr)2760 if (type_node == nullptr)
...@@ -2735,14 +2765,14 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scop...@@ -2735,14 +2765,14 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scop
2735 return node;2765 return node;
2736}2766}
27372767
2738static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt *stmt) {2768static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang::DoStmt *stmt) {
2739 TransScopeWhile *while_scope = trans_scope_while_create(c, parent_scope);2769 TransScopeWhile *while_scope = trans_scope_while_create(c, parent_scope);
27402770
2741 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);2771 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
27422772
2743 AstNode *body_node;2773 AstNode *body_node;
2744 TransScope *child_scope;2774 TransScope *child_scope;
2745 if (stmt->getBody()->getStmtClass() == Stmt::CompoundStmtClass) {2775 if (stmt->getBody()->getStmtClass() == clang::Stmt::CompoundStmtClass) {
2746 // there's already a block in C, so we'll append our condition to it.2776 // there's already a block in C, so we'll append our condition to it.
2747 // c: do {2777 // c: do {
2748 // c: a;2778 // c: a;
...@@ -2795,11 +2825,11 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt...@@ -2795,11 +2825,11 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt
2795 return while_scope->node;2825 return while_scope->node;
2796}2826}
27972827
2798static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForStmt *stmt) {2828static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const clang::ForStmt *stmt) {
2799 AstNode *loop_block_node;2829 AstNode *loop_block_node;
2800 TransScopeWhile *while_scope;2830 TransScopeWhile *while_scope;
2801 TransScope *cond_scope;2831 TransScope *cond_scope;
2802 const Stmt *init_stmt = stmt->getInit();2832 const clang::Stmt *init_stmt = stmt->getInit();
2803 if (init_stmt == nullptr) {2833 if (init_stmt == nullptr) {
2804 while_scope = trans_scope_while_create(c, parent_scope);2834 while_scope = trans_scope_while_create(c, parent_scope);
2805 loop_block_node = while_scope->node;2835 loop_block_node = while_scope->node;
...@@ -2820,12 +2850,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt...@@ -2820,12 +2850,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
2820 child_scope->node->data.block.statements.append(while_scope->node);2850 child_scope->node->data.block.statements.append(while_scope->node);
2821 }2851 }
28222852
2823 const Stmt *cond_stmt = stmt->getCond();2853 const clang::Stmt *cond_stmt = stmt->getCond();
2824 if (cond_stmt == nullptr) {2854 if (cond_stmt == nullptr) {
2825 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);2855 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
2826 } else {2856 } else {
2827 if (Expr::classof(cond_stmt)) {2857 if (clang::Expr::classof(cond_stmt)) {
2828 const Expr *cond_expr = static_cast<const Expr*>(cond_stmt);2858 const clang::Expr *cond_expr = static_cast<const clang::Expr*>(cond_stmt);
2829 while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, cond_expr, TransRValue);2859 while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, cond_expr, TransRValue);
28302860
2831 if (while_scope->node->data.while_expr.condition == nullptr)2861 if (while_scope->node->data.while_expr.condition == nullptr)
...@@ -2838,7 +2868,7 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt...@@ -2838,7 +2868,7 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
2838 }2868 }
2839 }2869 }
28402870
2841 const Stmt *inc_stmt = stmt->getInc();2871 const clang::Stmt *inc_stmt = stmt->getInc();
2842 if (inc_stmt != nullptr) {2872 if (inc_stmt != nullptr) {
2843 AstNode *inc_node;2873 AstNode *inc_node;
2844 TransScope *inc_scope = trans_stmt(c, cond_scope, inc_stmt, &inc_node);2874 TransScope *inc_scope = trans_stmt(c, cond_scope, inc_stmt, &inc_node);
...@@ -2861,12 +2891,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt...@@ -2861,12 +2891,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
2861 return loop_block_node;2891 return loop_block_node;
2862}2892}
28632893
2864static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const SwitchStmt *stmt) {2894static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const clang::SwitchStmt *stmt) {
2865 TransScopeBlock *block_scope = trans_scope_block_create(c, parent_scope);2895 TransScopeBlock *block_scope = trans_scope_block_create(c, parent_scope);
28662896
2867 TransScopeSwitch *switch_scope;2897 TransScopeSwitch *switch_scope;
28682898
2869 const DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt();2899 const clang::DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt();
2870 if (var_decl_stmt == nullptr) {2900 if (var_decl_stmt == nullptr) {
2871 switch_scope = trans_scope_switch_create(c, &block_scope->base);2901 switch_scope = trans_scope_switch_create(c, &block_scope->base);
2872 } else {2902 } else {
...@@ -2885,7 +2915,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw...@@ -2885,7 +2915,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw
2885 switch_scope->end_label_name = end_label_name;2915 switch_scope->end_label_name = end_label_name;
2886 block_scope->node->data.block.name = end_label_name;2916 block_scope->node->data.block.name = end_label_name;
28872917
2888 const Expr *cond_expr = stmt->getCond();2918 const clang::Expr *cond_expr = stmt->getCond();
2889 assert(cond_expr != nullptr);2919 assert(cond_expr != nullptr);
28902920
2891 AstNode *expr_node = trans_expr(c, ResultUsedYes, &block_scope->base, cond_expr, TransRValue);2921 AstNode *expr_node = trans_expr(c, ResultUsedYes, &block_scope->base, cond_expr, TransRValue);
...@@ -2894,9 +2924,9 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw...@@ -2894,9 +2924,9 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw
2894 switch_scope->switch_node->data.switch_expr.expr = expr_node;2924 switch_scope->switch_node->data.switch_expr.expr = expr_node;
28952925
2896 AstNode *body_node;2926 AstNode *body_node;
2897 const Stmt *body_stmt = stmt->getBody();2927 const clang::Stmt *body_stmt = stmt->getBody();
2898 if (body_stmt->getStmtClass() == Stmt::CompoundStmtClass) {2928 if (body_stmt->getStmtClass() == clang::Stmt::CompoundStmtClass) {
2899 if (trans_compound_stmt_inline(c, &switch_scope->base, (const CompoundStmt *)body_stmt,2929 if (trans_compound_stmt_inline(c, &switch_scope->base, (const clang::CompoundStmt *)body_stmt,
2900 block_scope->node, nullptr))2930 block_scope->node, nullptr))
2901 {2931 {
2902 return nullptr;2932 return nullptr;
...@@ -2928,7 +2958,7 @@ static TransScopeSwitch *trans_scope_switch_find(TransScope *scope) {...@@ -2928,7 +2958,7 @@ static TransScopeSwitch *trans_scope_switch_find(TransScope *scope) {
2928 return nullptr;2958 return nullptr;
2929}2959}
29302960
2931static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStmt *stmt, AstNode **out_node,2961static int trans_switch_case(Context *c, TransScope *parent_scope, const clang::CaseStmt *stmt, AstNode **out_node,
2932 TransScope **out_scope) {2962 TransScope **out_scope) {
2933 *out_node = nullptr;2963 *out_node = nullptr;
29342964
...@@ -2973,7 +3003,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStm...@@ -2973,7 +3003,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStm
2973 return ErrorNone;3003 return ErrorNone;
2974}3004}
29753005
2976static int trans_switch_default(Context *c, TransScope *parent_scope, const DefaultStmt *stmt, AstNode **out_node,3006static int trans_switch_default(Context *c, TransScope *parent_scope, const clang::DefaultStmt *stmt, AstNode **out_node,
2977 TransScope **out_scope)3007 TransScope **out_scope)
2978{3008{
2979 *out_node = nullptr;3009 *out_node = nullptr;
...@@ -3010,25 +3040,25 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const Defa...@@ -3010,25 +3040,25 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const Defa
3010 return ErrorNone;3040 return ErrorNone;
3011}3041}
30123042
3013static AstNode *trans_string_literal(Context *c, TransScope *scope, const StringLiteral *stmt) {3043static AstNode *trans_string_literal(Context *c, TransScope *scope, const clang::StringLiteral *stmt) {
3014 switch (stmt->getKind()) {3044 switch (stmt->getKind()) {
3015 case StringLiteral::Ascii:3045 case clang::StringLiteral::Ascii:
3016 case StringLiteral::UTF8:3046 case clang::StringLiteral::UTF8:
3017 return trans_create_node_str_lit_c(c, string_ref_to_buf(stmt->getString()));3047 return trans_create_node_str_lit_c(c, string_ref_to_buf(stmt->getString()));
3018 case StringLiteral::UTF16:3048 case clang::StringLiteral::UTF16:
3019 emit_warning(c, stmt->getLocStart(), "TODO support UTF16 string literals");3049 emit_warning(c, stmt->getLocStart(), "TODO support UTF16 string literals");
3020 return nullptr;3050 return nullptr;
3021 case StringLiteral::UTF32:3051 case clang::StringLiteral::UTF32:
3022 emit_warning(c, stmt->getLocStart(), "TODO support UTF32 string literals");3052 emit_warning(c, stmt->getLocStart(), "TODO support UTF32 string literals");
3023 return nullptr;3053 return nullptr;
3024 case StringLiteral::Wide:3054 case clang::StringLiteral::Wide:
3025 emit_warning(c, stmt->getLocStart(), "TODO support wide string literals");3055 emit_warning(c, stmt->getLocStart(), "TODO support wide string literals");
3026 return nullptr;3056 return nullptr;
3027 }3057 }
3028 zig_unreachable();3058 zig_unreachable();
3029}3059}
30303060
3031static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt *stmt) {3061static AstNode *trans_break_stmt(Context *c, TransScope *scope, const clang::BreakStmt *stmt) {
3032 TransScope *cur_scope = scope;3062 TransScope *cur_scope = scope;
3033 while (cur_scope != nullptr) {3063 while (cur_scope != nullptr) {
3034 if (cur_scope->id == TransScopeIdWhile) {3064 if (cur_scope->id == TransScopeIdWhile) {
...@@ -3042,7 +3072,7 @@ static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt...@@ -3042,7 +3072,7 @@ static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt
3042 zig_unreachable();3072 zig_unreachable();
3043}3073}
30443074
3045static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const ContinueStmt *stmt) {3075static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const clang::ContinueStmt *stmt) {
3046 return trans_create_node(c, NodeTypeContinue);3076 return trans_create_node(c, NodeTypeContinue);
3047}3077}
30483078
...@@ -3055,47 +3085,47 @@ static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_...@@ -3055,47 +3085,47 @@ static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_
3055 return ErrorNone;3085 return ErrorNone;
3056}3086}
30573087
3058static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,3088static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *stmt,
3059 ResultUsed result_used, TransLRValue lrvalue,3089 ResultUsed result_used, TransLRValue lrvalue,
3060 AstNode **out_node, TransScope **out_child_scope,3090 AstNode **out_node, TransScope **out_child_scope,
3061 TransScope **out_node_scope)3091 TransScope **out_node_scope)
3062{3092{
3063 Stmt::StmtClass sc = stmt->getStmtClass();3093 clang::Stmt::StmtClass sc = stmt->getStmtClass();
3064 switch (sc) {3094 switch (sc) {
3065 case Stmt::ReturnStmtClass:3095 case clang::Stmt::ReturnStmtClass:
3066 return wrap_stmt(out_node, out_child_scope, scope,3096 return wrap_stmt(out_node, out_child_scope, scope,
3067 trans_return_stmt(c, scope, (const ReturnStmt *)stmt));3097 trans_return_stmt(c, scope, (const clang::ReturnStmt *)stmt));
3068 case Stmt::CompoundStmtClass:3098 case clang::Stmt::CompoundStmtClass:
3069 return wrap_stmt(out_node, out_child_scope, scope,3099 return wrap_stmt(out_node, out_child_scope, scope,
3070 trans_compound_stmt(c, scope, (const CompoundStmt *)stmt, out_node_scope));3100 trans_compound_stmt(c, scope, (const clang::CompoundStmt *)stmt, out_node_scope));
3071 case Stmt::IntegerLiteralClass:3101 case clang::Stmt::IntegerLiteralClass:
3072 return wrap_stmt(out_node, out_child_scope, scope,3102 return wrap_stmt(out_node, out_child_scope, scope,
3073 trans_integer_literal(c, (const IntegerLiteral *)stmt));3103 trans_integer_literal(c, (const clang::IntegerLiteral *)stmt));
3074 case Stmt::ConditionalOperatorClass:3104 case clang::Stmt::ConditionalOperatorClass:
3075 return wrap_stmt(out_node, out_child_scope, scope,3105 return wrap_stmt(out_node, out_child_scope, scope,
3076 trans_conditional_operator(c, result_used, scope, (const ConditionalOperator *)stmt));3106 trans_conditional_operator(c, result_used, scope, (const clang::ConditionalOperator *)stmt));
3077 case Stmt::BinaryOperatorClass:3107 case clang::Stmt::BinaryOperatorClass:
3078 return wrap_stmt(out_node, out_child_scope, scope,3108 return wrap_stmt(out_node, out_child_scope, scope,
3079 trans_binary_operator(c, result_used, scope, (const BinaryOperator *)stmt));3109 trans_binary_operator(c, result_used, scope, (const clang::BinaryOperator *)stmt));
3080 case Stmt::CompoundAssignOperatorClass:3110 case clang::Stmt::CompoundAssignOperatorClass:
3081 return wrap_stmt(out_node, out_child_scope, scope,3111 return wrap_stmt(out_node, out_child_scope, scope,
3082 trans_compound_assign_operator(c, result_used, scope, (const CompoundAssignOperator *)stmt));3112 trans_compound_assign_operator(c, result_used, scope, (const clang::CompoundAssignOperator *)stmt));
3083 case Stmt::ImplicitCastExprClass:3113 case clang::Stmt::ImplicitCastExprClass:
3084 return wrap_stmt(out_node, out_child_scope, scope,3114 return wrap_stmt(out_node, out_child_scope, scope,
3085 trans_implicit_cast_expr(c, scope, (const ImplicitCastExpr *)stmt));3115 trans_implicit_cast_expr(c, scope, (const clang::ImplicitCastExpr *)stmt));
3086 case Stmt::DeclRefExprClass:3116 case clang::Stmt::DeclRefExprClass:
3087 return wrap_stmt(out_node, out_child_scope, scope,3117 return wrap_stmt(out_node, out_child_scope, scope,
3088 trans_decl_ref_expr(c, scope, (const DeclRefExpr *)stmt, lrvalue));3118 trans_decl_ref_expr(c, scope, (const clang::DeclRefExpr *)stmt, lrvalue));
3089 case Stmt::UnaryOperatorClass:3119 case clang::Stmt::UnaryOperatorClass:
3090 return wrap_stmt(out_node, out_child_scope, scope,3120 return wrap_stmt(out_node, out_child_scope, scope,
3091 trans_unary_operator(c, result_used, scope, (const UnaryOperator *)stmt));3121 trans_unary_operator(c, result_used, scope, (const clang::UnaryOperator *)stmt));
3092 case Stmt::DeclStmtClass:3122 case clang::Stmt::DeclStmtClass:
3093 return trans_local_declaration(c, scope, (const DeclStmt *)stmt, out_node, out_child_scope);3123 return trans_local_declaration(c, scope, (const clang::DeclStmt *)stmt, out_node, out_child_scope);
3094 case Stmt::DoStmtClass:3124 case clang::Stmt::DoStmtClass:
3095 case Stmt::WhileStmtClass: {3125 case clang::Stmt::WhileStmtClass: {
3096 AstNode *while_node = sc == Stmt::DoStmtClass3126 AstNode *while_node = sc == clang::Stmt::DoStmtClass
3097 ? trans_do_loop(c, scope, (const DoStmt *)stmt)3127 ? trans_do_loop(c, scope, (const clang::DoStmt *)stmt)
3098 : trans_while_loop(c, scope, (const WhileStmt *)stmt);3128 : trans_while_loop(c, scope, (const clang::WhileStmt *)stmt);
30993129
3100 if (while_node == nullptr)3130 if (while_node == nullptr)
3101 return ErrorUnexpected;3131 return ErrorUnexpected;
...@@ -3106,556 +3136,556 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,...@@ -3106,556 +3136,556 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,
31063136
3107 return wrap_stmt(out_node, out_child_scope, scope, while_node);3137 return wrap_stmt(out_node, out_child_scope, scope, while_node);
3108 }3138 }
3109 case Stmt::IfStmtClass:3139 case clang::Stmt::IfStmtClass:
3110 return wrap_stmt(out_node, out_child_scope, scope,3140 return wrap_stmt(out_node, out_child_scope, scope,
3111 trans_if_statement(c, scope, (const IfStmt *)stmt));3141 trans_if_statement(c, scope, (const clang::IfStmt *)stmt));
3112 case Stmt::CallExprClass:3142 case clang::Stmt::CallExprClass:
3113 return wrap_stmt(out_node, out_child_scope, scope,3143 return wrap_stmt(out_node, out_child_scope, scope,
3114 trans_call_expr(c, result_used, scope, (const CallExpr *)stmt));3144 trans_call_expr(c, result_used, scope, (const clang::CallExpr *)stmt));
3115 case Stmt::NullStmtClass:3145 case clang::Stmt::NullStmtClass:
3116 *out_node = nullptr;3146 *out_node = nullptr;
3117 *out_child_scope = scope;3147 *out_child_scope = scope;
3118 return ErrorNone;3148 return ErrorNone;
3119 case Stmt::MemberExprClass:3149 case clang::Stmt::MemberExprClass:
3120 return wrap_stmt(out_node, out_child_scope, scope,3150 return wrap_stmt(out_node, out_child_scope, scope,
3121 trans_member_expr(c, scope, (const MemberExpr *)stmt));3151 trans_member_expr(c, scope, (const clang::MemberExpr *)stmt));
3122 case Stmt::ArraySubscriptExprClass:3152 case clang::Stmt::ArraySubscriptExprClass:
3123 return wrap_stmt(out_node, out_child_scope, scope,3153 return wrap_stmt(out_node, out_child_scope, scope,
3124 trans_array_subscript_expr(c, scope, (const ArraySubscriptExpr *)stmt));3154 trans_array_subscript_expr(c, scope, (const clang::ArraySubscriptExpr *)stmt));
3125 case Stmt::CStyleCastExprClass:3155 case clang::Stmt::CStyleCastExprClass:
3126 return wrap_stmt(out_node, out_child_scope, scope,3156 return wrap_stmt(out_node, out_child_scope, scope,
3127 trans_c_style_cast_expr(c, result_used, scope, (const CStyleCastExpr *)stmt, lrvalue));3157 trans_c_style_cast_expr(c, result_used, scope, (const clang::CStyleCastExpr *)stmt, lrvalue));
3128 case Stmt::UnaryExprOrTypeTraitExprClass:3158 case clang::Stmt::UnaryExprOrTypeTraitExprClass:
3129 return wrap_stmt(out_node, out_child_scope, scope,3159 return wrap_stmt(out_node, out_child_scope, scope,
3130 trans_unary_expr_or_type_trait_expr(c, scope, (const UnaryExprOrTypeTraitExpr *)stmt));3160 trans_unary_expr_or_type_trait_expr(c, scope, (const clang::UnaryExprOrTypeTraitExpr *)stmt));
3131 case Stmt::ForStmtClass: {3161 case clang::Stmt::ForStmtClass: {
3132 AstNode *node = trans_for_loop(c, scope, (const ForStmt *)stmt);3162 AstNode *node = trans_for_loop(c, scope, (const clang::ForStmt *)stmt);
3133 return wrap_stmt(out_node, out_child_scope, scope, node);3163 return wrap_stmt(out_node, out_child_scope, scope, node);
3134 }3164 }
3135 case Stmt::StringLiteralClass:3165 case clang::Stmt::StringLiteralClass:
3136 return wrap_stmt(out_node, out_child_scope, scope,3166 return wrap_stmt(out_node, out_child_scope, scope,
3137 trans_string_literal(c, scope, (const StringLiteral *)stmt));3167 trans_string_literal(c, scope, (const clang::StringLiteral *)stmt));
3138 case Stmt::BreakStmtClass:3168 case clang::Stmt::BreakStmtClass:
3139 return wrap_stmt(out_node, out_child_scope, scope,3169 return wrap_stmt(out_node, out_child_scope, scope,
3140 trans_break_stmt(c, scope, (const BreakStmt *)stmt));3170 trans_break_stmt(c, scope, (const clang::BreakStmt *)stmt));
3141 case Stmt::ContinueStmtClass:3171 case clang::Stmt::ContinueStmtClass:
3142 return wrap_stmt(out_node, out_child_scope, scope,3172 return wrap_stmt(out_node, out_child_scope, scope,
3143 trans_continue_stmt(c, scope, (const ContinueStmt *)stmt));3173 trans_continue_stmt(c, scope, (const clang::ContinueStmt *)stmt));
3144 case Stmt::ParenExprClass:3174 case clang::Stmt::ParenExprClass:
3145 return wrap_stmt(out_node, out_child_scope, scope,3175 return wrap_stmt(out_node, out_child_scope, scope,
3146 trans_expr(c, result_used, scope, ((const ParenExpr*)stmt)->getSubExpr(), lrvalue));3176 trans_expr(c, result_used, scope, ((const clang::ParenExpr*)stmt)->getSubExpr(), lrvalue));
3147 case Stmt::SwitchStmtClass:3177 case clang::Stmt::SwitchStmtClass:
3148 return wrap_stmt(out_node, out_child_scope, scope,3178 return wrap_stmt(out_node, out_child_scope, scope,
3149 trans_switch_stmt(c, scope, (const SwitchStmt *)stmt));3179 trans_switch_stmt(c, scope, (const clang::SwitchStmt *)stmt));
3150 case Stmt::CaseStmtClass:3180 case clang::Stmt::CaseStmtClass:
3151 return trans_switch_case(c, scope, (const CaseStmt *)stmt, out_node, out_child_scope);3181 return trans_switch_case(c, scope, (const clang::CaseStmt *)stmt, out_node, out_child_scope);
3152 case Stmt::DefaultStmtClass:3182 case clang::Stmt::DefaultStmtClass:
3153 return trans_switch_default(c, scope, (const DefaultStmt *)stmt, out_node, out_child_scope);3183 return trans_switch_default(c, scope, (const clang::DefaultStmt *)stmt, out_node, out_child_scope);
3154 case Stmt::NoStmtClass:3184 case clang::Stmt::NoStmtClass:
3155 emit_warning(c, stmt->getLocStart(), "TODO handle C NoStmtClass");3185 emit_warning(c, stmt->getLocStart(), "TODO handle C NoStmtClass");
3156 return ErrorUnexpected;3186 return ErrorUnexpected;
3157 case Stmt::GCCAsmStmtClass:3187 case clang::Stmt::GCCAsmStmtClass:
3158 emit_warning(c, stmt->getLocStart(), "TODO handle C GCCAsmStmtClass");3188 emit_warning(c, stmt->getLocStart(), "TODO handle C GCCAsmStmtClass");
3159 return ErrorUnexpected;3189 return ErrorUnexpected;
3160 case Stmt::MSAsmStmtClass:3190 case clang::Stmt::MSAsmStmtClass:
3161 emit_warning(c, stmt->getLocStart(), "TODO handle C MSAsmStmtClass");3191 emit_warning(c, stmt->getLocStart(), "TODO handle C MSAsmStmtClass");
3162 return ErrorUnexpected;3192 return ErrorUnexpected;
3163 case Stmt::AttributedStmtClass:3193 case clang::Stmt::AttributedStmtClass:
3164 emit_warning(c, stmt->getLocStart(), "TODO handle C AttributedStmtClass");3194 emit_warning(c, stmt->getLocStart(), "TODO handle C AttributedStmtClass");
3165 return ErrorUnexpected;3195 return ErrorUnexpected;
3166 case Stmt::CXXCatchStmtClass:3196 case clang::Stmt::CXXCatchStmtClass:
3167 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXCatchStmtClass");3197 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXCatchStmtClass");
3168 return ErrorUnexpected;3198 return ErrorUnexpected;
3169 case Stmt::CXXForRangeStmtClass:3199 case clang::Stmt::CXXForRangeStmtClass:
3170 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXForRangeStmtClass");3200 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXForRangeStmtClass");
3171 return ErrorUnexpected;3201 return ErrorUnexpected;
3172 case Stmt::CXXTryStmtClass:3202 case clang::Stmt::CXXTryStmtClass:
3173 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTryStmtClass");3203 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTryStmtClass");
3174 return ErrorUnexpected;3204 return ErrorUnexpected;
3175 case Stmt::CapturedStmtClass:3205 case clang::Stmt::CapturedStmtClass:
3176 emit_warning(c, stmt->getLocStart(), "TODO handle C CapturedStmtClass");3206 emit_warning(c, stmt->getLocStart(), "TODO handle C CapturedStmtClass");
3177 return ErrorUnexpected;3207 return ErrorUnexpected;
3178 case Stmt::CoreturnStmtClass:3208 case clang::Stmt::CoreturnStmtClass:
3179 emit_warning(c, stmt->getLocStart(), "TODO handle C CoreturnStmtClass");3209 emit_warning(c, stmt->getLocStart(), "TODO handle C CoreturnStmtClass");
3180 return ErrorUnexpected;3210 return ErrorUnexpected;
3181 case Stmt::CoroutineBodyStmtClass:3211 case clang::Stmt::CoroutineBodyStmtClass:
3182 emit_warning(c, stmt->getLocStart(), "TODO handle C CoroutineBodyStmtClass");3212 emit_warning(c, stmt->getLocStart(), "TODO handle C CoroutineBodyStmtClass");
3183 return ErrorUnexpected;3213 return ErrorUnexpected;
3184 case Stmt::BinaryConditionalOperatorClass:3214 case clang::Stmt::BinaryConditionalOperatorClass:
3185 emit_warning(c, stmt->getLocStart(), "TODO handle C BinaryConditionalOperatorClass");3215 emit_warning(c, stmt->getLocStart(), "TODO handle C BinaryConditionalOperatorClass");
3186 return ErrorUnexpected;3216 return ErrorUnexpected;
3187 case Stmt::AddrLabelExprClass:3217 case clang::Stmt::AddrLabelExprClass:
3188 emit_warning(c, stmt->getLocStart(), "TODO handle C AddrLabelExprClass");3218 emit_warning(c, stmt->getLocStart(), "TODO handle C AddrLabelExprClass");
3189 return ErrorUnexpected;3219 return ErrorUnexpected;
3190 case Stmt::ArrayInitIndexExprClass:3220 case clang::Stmt::ArrayInitIndexExprClass:
3191 emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitIndexExprClass");3221 emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitIndexExprClass");
3192 return ErrorUnexpected;3222 return ErrorUnexpected;
3193 case Stmt::ArrayInitLoopExprClass:3223 case clang::Stmt::ArrayInitLoopExprClass:
3194 emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitLoopExprClass");3224 emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitLoopExprClass");
3195 return ErrorUnexpected;3225 return ErrorUnexpected;
3196 case Stmt::ArrayTypeTraitExprClass:3226 case clang::Stmt::ArrayTypeTraitExprClass:
3197 emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayTypeTraitExprClass");3227 emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayTypeTraitExprClass");
3198 return ErrorUnexpected;3228 return ErrorUnexpected;
3199 case Stmt::AsTypeExprClass:3229 case clang::Stmt::AsTypeExprClass:
3200 emit_warning(c, stmt->getLocStart(), "TODO handle C AsTypeExprClass");3230 emit_warning(c, stmt->getLocStart(), "TODO handle C AsTypeExprClass");
3201 return ErrorUnexpected;3231 return ErrorUnexpected;
3202 case Stmt::AtomicExprClass:3232 case clang::Stmt::AtomicExprClass:
3203 emit_warning(c, stmt->getLocStart(), "TODO handle C AtomicExprClass");3233 emit_warning(c, stmt->getLocStart(), "TODO handle C AtomicExprClass");
3204 return ErrorUnexpected;3234 return ErrorUnexpected;
3205 case Stmt::BlockExprClass:3235 case clang::Stmt::BlockExprClass:
3206 emit_warning(c, stmt->getLocStart(), "TODO handle C BlockExprClass");3236 emit_warning(c, stmt->getLocStart(), "TODO handle C BlockExprClass");
3207 return ErrorUnexpected;3237 return ErrorUnexpected;
3208 case Stmt::CXXBindTemporaryExprClass:3238 case clang::Stmt::CXXBindTemporaryExprClass:
3209 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXBindTemporaryExprClass");3239 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXBindTemporaryExprClass");
3210 return ErrorUnexpected;3240 return ErrorUnexpected;
3211 case Stmt::CXXBoolLiteralExprClass:3241 case clang::Stmt::CXXBoolLiteralExprClass:
3212 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXBoolLiteralExprClass");3242 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXBoolLiteralExprClass");
3213 return ErrorUnexpected;3243 return ErrorUnexpected;
3214 case Stmt::CXXConstructExprClass:3244 case clang::Stmt::CXXConstructExprClass:
3215 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXConstructExprClass");3245 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXConstructExprClass");
3216 return ErrorUnexpected;3246 return ErrorUnexpected;
3217 case Stmt::CXXTemporaryObjectExprClass:3247 case clang::Stmt::CXXTemporaryObjectExprClass:
3218 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTemporaryObjectExprClass");3248 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTemporaryObjectExprClass");
3219 return ErrorUnexpected;3249 return ErrorUnexpected;
3220 case Stmt::CXXDefaultArgExprClass:3250 case clang::Stmt::CXXDefaultArgExprClass:
3221 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDefaultArgExprClass");3251 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDefaultArgExprClass");
3222 return ErrorUnexpected;3252 return ErrorUnexpected;
3223 case Stmt::CXXDefaultInitExprClass:3253 case clang::Stmt::CXXDefaultInitExprClass:
3224 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDefaultInitExprClass");3254 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDefaultInitExprClass");
3225 return ErrorUnexpected;3255 return ErrorUnexpected;
3226 case Stmt::CXXDeleteExprClass:3256 case clang::Stmt::CXXDeleteExprClass:
3227 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDeleteExprClass");3257 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDeleteExprClass");
3228 return ErrorUnexpected;3258 return ErrorUnexpected;
3229 case Stmt::CXXDependentScopeMemberExprClass:3259 case clang::Stmt::CXXDependentScopeMemberExprClass:
3230 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDependentScopeMemberExprClass");3260 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDependentScopeMemberExprClass");
3231 return ErrorUnexpected;3261 return ErrorUnexpected;
3232 case Stmt::CXXFoldExprClass:3262 case clang::Stmt::CXXFoldExprClass:
3233 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFoldExprClass");3263 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFoldExprClass");
3234 return ErrorUnexpected;3264 return ErrorUnexpected;
3235 case Stmt::CXXInheritedCtorInitExprClass:3265 case clang::Stmt::CXXInheritedCtorInitExprClass:
3236 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXInheritedCtorInitExprClass");3266 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXInheritedCtorInitExprClass");
3237 return ErrorUnexpected;3267 return ErrorUnexpected;
3238 case Stmt::CXXNewExprClass:3268 case clang::Stmt::CXXNewExprClass:
3239 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNewExprClass");3269 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNewExprClass");
3240 return ErrorUnexpected;3270 return ErrorUnexpected;
3241 case Stmt::CXXNoexceptExprClass:3271 case clang::Stmt::CXXNoexceptExprClass:
3242 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNoexceptExprClass");3272 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNoexceptExprClass");
3243 return ErrorUnexpected;3273 return ErrorUnexpected;
3244 case Stmt::CXXNullPtrLiteralExprClass:3274 case clang::Stmt::CXXNullPtrLiteralExprClass:
3245 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNullPtrLiteralExprClass");3275 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNullPtrLiteralExprClass");
3246 return ErrorUnexpected;3276 return ErrorUnexpected;
3247 case Stmt::CXXPseudoDestructorExprClass:3277 case clang::Stmt::CXXPseudoDestructorExprClass:
3248 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXPseudoDestructorExprClass");3278 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXPseudoDestructorExprClass");
3249 return ErrorUnexpected;3279 return ErrorUnexpected;
3250 case Stmt::CXXScalarValueInitExprClass:3280 case clang::Stmt::CXXScalarValueInitExprClass:
3251 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXScalarValueInitExprClass");3281 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXScalarValueInitExprClass");
3252 return ErrorUnexpected;3282 return ErrorUnexpected;
3253 case Stmt::CXXStdInitializerListExprClass:3283 case clang::Stmt::CXXStdInitializerListExprClass:
3254 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXStdInitializerListExprClass");3284 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXStdInitializerListExprClass");
3255 return ErrorUnexpected;3285 return ErrorUnexpected;
3256 case Stmt::CXXThisExprClass:3286 case clang::Stmt::CXXThisExprClass:
3257 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXThisExprClass");3287 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXThisExprClass");
3258 return ErrorUnexpected;3288 return ErrorUnexpected;
3259 case Stmt::CXXThrowExprClass:3289 case clang::Stmt::CXXThrowExprClass:
3260 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXThrowExprClass");3290 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXThrowExprClass");
3261 return ErrorUnexpected;3291 return ErrorUnexpected;
3262 case Stmt::CXXTypeidExprClass:3292 case clang::Stmt::CXXTypeidExprClass:
3263 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTypeidExprClass");3293 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTypeidExprClass");
3264 return ErrorUnexpected;3294 return ErrorUnexpected;
3265 case Stmt::CXXUnresolvedConstructExprClass:3295 case clang::Stmt::CXXUnresolvedConstructExprClass:
3266 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUnresolvedConstructExprClass");3296 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUnresolvedConstructExprClass");
3267 return ErrorUnexpected;3297 return ErrorUnexpected;
3268 case Stmt::CXXUuidofExprClass:3298 case clang::Stmt::CXXUuidofExprClass:
3269 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUuidofExprClass");3299 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUuidofExprClass");
3270 return ErrorUnexpected;3300 return ErrorUnexpected;
3271 case Stmt::CUDAKernelCallExprClass:3301 case clang::Stmt::CUDAKernelCallExprClass:
3272 emit_warning(c, stmt->getLocStart(), "TODO handle C CUDAKernelCallExprClass");3302 emit_warning(c, stmt->getLocStart(), "TODO handle C CUDAKernelCallExprClass");
3273 return ErrorUnexpected;3303 return ErrorUnexpected;
3274 case Stmt::CXXMemberCallExprClass:3304 case clang::Stmt::CXXMemberCallExprClass:
3275 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXMemberCallExprClass");3305 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXMemberCallExprClass");
3276 return ErrorUnexpected;3306 return ErrorUnexpected;
3277 case Stmt::CXXOperatorCallExprClass:3307 case clang::Stmt::CXXOperatorCallExprClass:
3278 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXOperatorCallExprClass");3308 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXOperatorCallExprClass");
3279 return ErrorUnexpected;3309 return ErrorUnexpected;
3280 case Stmt::UserDefinedLiteralClass:3310 case clang::Stmt::UserDefinedLiteralClass:
3281 emit_warning(c, stmt->getLocStart(), "TODO handle C UserDefinedLiteralClass");3311 emit_warning(c, stmt->getLocStart(), "TODO handle C UserDefinedLiteralClass");
3282 return ErrorUnexpected;3312 return ErrorUnexpected;
3283 case Stmt::CXXFunctionalCastExprClass:3313 case clang::Stmt::CXXFunctionalCastExprClass:
3284 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFunctionalCastExprClass");3314 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFunctionalCastExprClass");
3285 return ErrorUnexpected;3315 return ErrorUnexpected;
3286 case Stmt::CXXConstCastExprClass:3316 case clang::Stmt::CXXConstCastExprClass:
3287 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXConstCastExprClass");3317 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXConstCastExprClass");
3288 return ErrorUnexpected;3318 return ErrorUnexpected;
3289 case Stmt::CXXDynamicCastExprClass:3319 case clang::Stmt::CXXDynamicCastExprClass:
3290 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDynamicCastExprClass");3320 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDynamicCastExprClass");
3291 return ErrorUnexpected;3321 return ErrorUnexpected;
3292 case Stmt::CXXReinterpretCastExprClass:3322 case clang::Stmt::CXXReinterpretCastExprClass:
3293 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXReinterpretCastExprClass");3323 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXReinterpretCastExprClass");
3294 return ErrorUnexpected;3324 return ErrorUnexpected;
3295 case Stmt::CXXStaticCastExprClass:3325 case clang::Stmt::CXXStaticCastExprClass:
3296 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXStaticCastExprClass");3326 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXStaticCastExprClass");
3297 return ErrorUnexpected;3327 return ErrorUnexpected;
3298 case Stmt::ObjCBridgedCastExprClass:3328 case clang::Stmt::ObjCBridgedCastExprClass:
3299 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBridgedCastExprClass");3329 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBridgedCastExprClass");
3300 return ErrorUnexpected;3330 return ErrorUnexpected;
3301 case Stmt::CharacterLiteralClass:3331 case clang::Stmt::CharacterLiteralClass:
3302 emit_warning(c, stmt->getLocStart(), "TODO handle C CharacterLiteralClass");3332 emit_warning(c, stmt->getLocStart(), "TODO handle C CharacterLiteralClass");
3303 return ErrorUnexpected;3333 return ErrorUnexpected;
3304 case Stmt::ChooseExprClass:3334 case clang::Stmt::ChooseExprClass:
3305 emit_warning(c, stmt->getLocStart(), "TODO handle C ChooseExprClass");3335 emit_warning(c, stmt->getLocStart(), "TODO handle C ChooseExprClass");
3306 return ErrorUnexpected;3336 return ErrorUnexpected;
3307 case Stmt::CompoundLiteralExprClass:3337 case clang::Stmt::CompoundLiteralExprClass:
3308 emit_warning(c, stmt->getLocStart(), "TODO handle C CompoundLiteralExprClass");3338 emit_warning(c, stmt->getLocStart(), "TODO handle C CompoundLiteralExprClass");
3309 return ErrorUnexpected;3339 return ErrorUnexpected;
3310 case Stmt::ConvertVectorExprClass:3340 case clang::Stmt::ConvertVectorExprClass:
3311 emit_warning(c, stmt->getLocStart(), "TODO handle C ConvertVectorExprClass");3341 emit_warning(c, stmt->getLocStart(), "TODO handle C ConvertVectorExprClass");
3312 return ErrorUnexpected;3342 return ErrorUnexpected;
3313 case Stmt::CoawaitExprClass:3343 case clang::Stmt::CoawaitExprClass:
3314 emit_warning(c, stmt->getLocStart(), "TODO handle C CoawaitExprClass");3344 emit_warning(c, stmt->getLocStart(), "TODO handle C CoawaitExprClass");
3315 return ErrorUnexpected;3345 return ErrorUnexpected;
3316 case Stmt::CoyieldExprClass:3346 case clang::Stmt::CoyieldExprClass:
3317 emit_warning(c, stmt->getLocStart(), "TODO handle C CoyieldExprClass");3347 emit_warning(c, stmt->getLocStart(), "TODO handle C CoyieldExprClass");
3318 return ErrorUnexpected;3348 return ErrorUnexpected;
3319 case Stmt::DependentCoawaitExprClass:3349 case clang::Stmt::DependentCoawaitExprClass:
3320 emit_warning(c, stmt->getLocStart(), "TODO handle C DependentCoawaitExprClass");3350 emit_warning(c, stmt->getLocStart(), "TODO handle C DependentCoawaitExprClass");
3321 return ErrorUnexpected;3351 return ErrorUnexpected;
3322 case Stmt::DependentScopeDeclRefExprClass:3352 case clang::Stmt::DependentScopeDeclRefExprClass:
3323 emit_warning(c, stmt->getLocStart(), "TODO handle C DependentScopeDeclRefExprClass");3353 emit_warning(c, stmt->getLocStart(), "TODO handle C DependentScopeDeclRefExprClass");
3324 return ErrorUnexpected;3354 return ErrorUnexpected;
3325 case Stmt::DesignatedInitExprClass:3355 case clang::Stmt::DesignatedInitExprClass:
3326 emit_warning(c, stmt->getLocStart(), "TODO handle C DesignatedInitExprClass");3356 emit_warning(c, stmt->getLocStart(), "TODO handle C DesignatedInitExprClass");
3327 return ErrorUnexpected;3357 return ErrorUnexpected;
3328 case Stmt::DesignatedInitUpdateExprClass:3358 case clang::Stmt::DesignatedInitUpdateExprClass:
3329 emit_warning(c, stmt->getLocStart(), "TODO handle C DesignatedInitUpdateExprClass");3359 emit_warning(c, stmt->getLocStart(), "TODO handle C DesignatedInitUpdateExprClass");
3330 return ErrorUnexpected;3360 return ErrorUnexpected;
3331 case Stmt::ExprWithCleanupsClass:3361 case clang::Stmt::ExprWithCleanupsClass:
3332 emit_warning(c, stmt->getLocStart(), "TODO handle C ExprWithCleanupsClass");3362 emit_warning(c, stmt->getLocStart(), "TODO handle C ExprWithCleanupsClass");
3333 return ErrorUnexpected;3363 return ErrorUnexpected;
3334 case Stmt::ExpressionTraitExprClass:3364 case clang::Stmt::ExpressionTraitExprClass:
3335 emit_warning(c, stmt->getLocStart(), "TODO handle C ExpressionTraitExprClass");3365 emit_warning(c, stmt->getLocStart(), "TODO handle C ExpressionTraitExprClass");
3336 return ErrorUnexpected;3366 return ErrorUnexpected;
3337 case Stmt::ExtVectorElementExprClass:3367 case clang::Stmt::ExtVectorElementExprClass:
3338 emit_warning(c, stmt->getLocStart(), "TODO handle C ExtVectorElementExprClass");3368 emit_warning(c, stmt->getLocStart(), "TODO handle C ExtVectorElementExprClass");
3339 return ErrorUnexpected;3369 return ErrorUnexpected;
3340 case Stmt::FloatingLiteralClass:3370 case clang::Stmt::FloatingLiteralClass:
3341 emit_warning(c, stmt->getLocStart(), "TODO handle C FloatingLiteralClass");3371 emit_warning(c, stmt->getLocStart(), "TODO handle C FloatingLiteralClass");
3342 return ErrorUnexpected;3372 return ErrorUnexpected;
3343 case Stmt::FunctionParmPackExprClass:3373 case clang::Stmt::FunctionParmPackExprClass:
3344 emit_warning(c, stmt->getLocStart(), "TODO handle C FunctionParmPackExprClass");3374 emit_warning(c, stmt->getLocStart(), "TODO handle C FunctionParmPackExprClass");
3345 return ErrorUnexpected;3375 return ErrorUnexpected;
3346 case Stmt::GNUNullExprClass:3376 case clang::Stmt::GNUNullExprClass:
3347 emit_warning(c, stmt->getLocStart(), "TODO handle C GNUNullExprClass");3377 emit_warning(c, stmt->getLocStart(), "TODO handle C GNUNullExprClass");
3348 return ErrorUnexpected;3378 return ErrorUnexpected;
3349 case Stmt::GenericSelectionExprClass:3379 case clang::Stmt::GenericSelectionExprClass:
3350 emit_warning(c, stmt->getLocStart(), "TODO handle C GenericSelectionExprClass");3380 emit_warning(c, stmt->getLocStart(), "TODO handle C GenericSelectionExprClass");
3351 return ErrorUnexpected;3381 return ErrorUnexpected;
3352 case Stmt::ImaginaryLiteralClass:3382 case clang::Stmt::ImaginaryLiteralClass:
3353 emit_warning(c, stmt->getLocStart(), "TODO handle C ImaginaryLiteralClass");3383 emit_warning(c, stmt->getLocStart(), "TODO handle C ImaginaryLiteralClass");
3354 return ErrorUnexpected;3384 return ErrorUnexpected;
3355 case Stmt::ImplicitValueInitExprClass:3385 case clang::Stmt::ImplicitValueInitExprClass:
3356 emit_warning(c, stmt->getLocStart(), "TODO handle C ImplicitValueInitExprClass");3386 emit_warning(c, stmt->getLocStart(), "TODO handle C ImplicitValueInitExprClass");
3357 return ErrorUnexpected;3387 return ErrorUnexpected;
3358 case Stmt::InitListExprClass:3388 case clang::Stmt::InitListExprClass:
3359 emit_warning(c, stmt->getLocStart(), "TODO handle C InitListExprClass");3389 emit_warning(c, stmt->getLocStart(), "TODO handle C InitListExprClass");
3360 return ErrorUnexpected;3390 return ErrorUnexpected;
3361 case Stmt::LambdaExprClass:3391 case clang::Stmt::LambdaExprClass:
3362 emit_warning(c, stmt->getLocStart(), "TODO handle C LambdaExprClass");3392 emit_warning(c, stmt->getLocStart(), "TODO handle C LambdaExprClass");
3363 return ErrorUnexpected;3393 return ErrorUnexpected;
3364 case Stmt::MSPropertyRefExprClass:3394 case clang::Stmt::MSPropertyRefExprClass:
3365 emit_warning(c, stmt->getLocStart(), "TODO handle C MSPropertyRefExprClass");3395 emit_warning(c, stmt->getLocStart(), "TODO handle C MSPropertyRefExprClass");
3366 return ErrorUnexpected;3396 return ErrorUnexpected;
3367 case Stmt::MSPropertySubscriptExprClass:3397 case clang::Stmt::MSPropertySubscriptExprClass:
3368 emit_warning(c, stmt->getLocStart(), "TODO handle C MSPropertySubscriptExprClass");3398 emit_warning(c, stmt->getLocStart(), "TODO handle C MSPropertySubscriptExprClass");
3369 return ErrorUnexpected;3399 return ErrorUnexpected;
3370 case Stmt::MaterializeTemporaryExprClass:3400 case clang::Stmt::MaterializeTemporaryExprClass:
3371 emit_warning(c, stmt->getLocStart(), "TODO handle C MaterializeTemporaryExprClass");3401 emit_warning(c, stmt->getLocStart(), "TODO handle C MaterializeTemporaryExprClass");
3372 return ErrorUnexpected;3402 return ErrorUnexpected;
3373 case Stmt::NoInitExprClass:3403 case clang::Stmt::NoInitExprClass:
3374 emit_warning(c, stmt->getLocStart(), "TODO handle C NoInitExprClass");3404 emit_warning(c, stmt->getLocStart(), "TODO handle C NoInitExprClass");
3375 return ErrorUnexpected;3405 return ErrorUnexpected;
3376 case Stmt::OMPArraySectionExprClass:3406 case clang::Stmt::OMPArraySectionExprClass:
3377 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPArraySectionExprClass");3407 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPArraySectionExprClass");
3378 return ErrorUnexpected;3408 return ErrorUnexpected;
3379 case Stmt::ObjCArrayLiteralClass:3409 case clang::Stmt::ObjCArrayLiteralClass:
3380 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCArrayLiteralClass");3410 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCArrayLiteralClass");
3381 return ErrorUnexpected;3411 return ErrorUnexpected;
3382 case Stmt::ObjCAvailabilityCheckExprClass:3412 case clang::Stmt::ObjCAvailabilityCheckExprClass:
3383 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAvailabilityCheckExprClass");3413 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAvailabilityCheckExprClass");
3384 return ErrorUnexpected;3414 return ErrorUnexpected;
3385 case Stmt::ObjCBoolLiteralExprClass:3415 case clang::Stmt::ObjCBoolLiteralExprClass:
3386 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBoolLiteralExprClass");3416 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBoolLiteralExprClass");
3387 return ErrorUnexpected;3417 return ErrorUnexpected;
3388 case Stmt::ObjCBoxedExprClass:3418 case clang::Stmt::ObjCBoxedExprClass:
3389 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBoxedExprClass");3419 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBoxedExprClass");
3390 return ErrorUnexpected;3420 return ErrorUnexpected;
3391 case Stmt::ObjCDictionaryLiteralClass:3421 case clang::Stmt::ObjCDictionaryLiteralClass:
3392 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCDictionaryLiteralClass");3422 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCDictionaryLiteralClass");
3393 return ErrorUnexpected;3423 return ErrorUnexpected;
3394 case Stmt::ObjCEncodeExprClass:3424 case clang::Stmt::ObjCEncodeExprClass:
3395 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCEncodeExprClass");3425 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCEncodeExprClass");
3396 return ErrorUnexpected;3426 return ErrorUnexpected;
3397 case Stmt::ObjCIndirectCopyRestoreExprClass:3427 case clang::Stmt::ObjCIndirectCopyRestoreExprClass:
3398 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIndirectCopyRestoreExprClass");3428 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIndirectCopyRestoreExprClass");
3399 return ErrorUnexpected;3429 return ErrorUnexpected;
3400 case Stmt::ObjCIsaExprClass:3430 case clang::Stmt::ObjCIsaExprClass:
3401 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIsaExprClass");3431 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIsaExprClass");
3402 return ErrorUnexpected;3432 return ErrorUnexpected;
3403 case Stmt::ObjCIvarRefExprClass:3433 case clang::Stmt::ObjCIvarRefExprClass:
3404 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIvarRefExprClass");3434 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIvarRefExprClass");
3405 return ErrorUnexpected;3435 return ErrorUnexpected;
3406 case Stmt::ObjCMessageExprClass:3436 case clang::Stmt::ObjCMessageExprClass:
3407 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCMessageExprClass");3437 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCMessageExprClass");
3408 return ErrorUnexpected;3438 return ErrorUnexpected;
3409 case Stmt::ObjCPropertyRefExprClass:3439 case clang::Stmt::ObjCPropertyRefExprClass:
3410 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCPropertyRefExprClass");3440 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCPropertyRefExprClass");
3411 return ErrorUnexpected;3441 return ErrorUnexpected;
3412 case Stmt::ObjCProtocolExprClass:3442 case clang::Stmt::ObjCProtocolExprClass:
3413 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCProtocolExprClass");3443 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCProtocolExprClass");
3414 return ErrorUnexpected;3444 return ErrorUnexpected;
3415 case Stmt::ObjCSelectorExprClass:3445 case clang::Stmt::ObjCSelectorExprClass:
3416 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCSelectorExprClass");3446 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCSelectorExprClass");
3417 return ErrorUnexpected;3447 return ErrorUnexpected;
3418 case Stmt::ObjCStringLiteralClass:3448 case clang::Stmt::ObjCStringLiteralClass:
3419 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCStringLiteralClass");3449 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCStringLiteralClass");
3420 return ErrorUnexpected;3450 return ErrorUnexpected;
3421 case Stmt::ObjCSubscriptRefExprClass:3451 case clang::Stmt::ObjCSubscriptRefExprClass:
3422 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCSubscriptRefExprClass");3452 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCSubscriptRefExprClass");
3423 return ErrorUnexpected;3453 return ErrorUnexpected;
3424 case Stmt::OffsetOfExprClass:3454 case clang::Stmt::OffsetOfExprClass:
3425 emit_warning(c, stmt->getLocStart(), "TODO handle C OffsetOfExprClass");3455 emit_warning(c, stmt->getLocStart(), "TODO handle C OffsetOfExprClass");
3426 return ErrorUnexpected;3456 return ErrorUnexpected;
3427 case Stmt::OpaqueValueExprClass:3457 case clang::Stmt::OpaqueValueExprClass:
3428 emit_warning(c, stmt->getLocStart(), "TODO handle C OpaqueValueExprClass");3458 emit_warning(c, stmt->getLocStart(), "TODO handle C OpaqueValueExprClass");
3429 return ErrorUnexpected;3459 return ErrorUnexpected;
3430 case Stmt::UnresolvedLookupExprClass:3460 case clang::Stmt::UnresolvedLookupExprClass:
3431 emit_warning(c, stmt->getLocStart(), "TODO handle C UnresolvedLookupExprClass");3461 emit_warning(c, stmt->getLocStart(), "TODO handle C UnresolvedLookupExprClass");
3432 return ErrorUnexpected;3462 return ErrorUnexpected;
3433 case Stmt::UnresolvedMemberExprClass:3463 case clang::Stmt::UnresolvedMemberExprClass:
3434 emit_warning(c, stmt->getLocStart(), "TODO handle C UnresolvedMemberExprClass");3464 emit_warning(c, stmt->getLocStart(), "TODO handle C UnresolvedMemberExprClass");
3435 return ErrorUnexpected;3465 return ErrorUnexpected;
3436 case Stmt::PackExpansionExprClass:3466 case clang::Stmt::PackExpansionExprClass:
3437 emit_warning(c, stmt->getLocStart(), "TODO handle C PackExpansionExprClass");3467 emit_warning(c, stmt->getLocStart(), "TODO handle C PackExpansionExprClass");
3438 return ErrorUnexpected;3468 return ErrorUnexpected;
3439 case Stmt::ParenListExprClass:3469 case clang::Stmt::ParenListExprClass:
3440 emit_warning(c, stmt->getLocStart(), "TODO handle C ParenListExprClass");3470 emit_warning(c, stmt->getLocStart(), "TODO handle C ParenListExprClass");
3441 return ErrorUnexpected;3471 return ErrorUnexpected;
3442 case Stmt::PredefinedExprClass:3472 case clang::Stmt::PredefinedExprClass:
3443 emit_warning(c, stmt->getLocStart(), "TODO handle C PredefinedExprClass");3473 emit_warning(c, stmt->getLocStart(), "TODO handle C PredefinedExprClass");
3444 return ErrorUnexpected;3474 return ErrorUnexpected;
3445 case Stmt::PseudoObjectExprClass:3475 case clang::Stmt::PseudoObjectExprClass:
3446 emit_warning(c, stmt->getLocStart(), "TODO handle C PseudoObjectExprClass");3476 emit_warning(c, stmt->getLocStart(), "TODO handle C PseudoObjectExprClass");
3447 return ErrorUnexpected;3477 return ErrorUnexpected;
3448 case Stmt::ShuffleVectorExprClass:3478 case clang::Stmt::ShuffleVectorExprClass:
3449 emit_warning(c, stmt->getLocStart(), "TODO handle C ShuffleVectorExprClass");3479 emit_warning(c, stmt->getLocStart(), "TODO handle C ShuffleVectorExprClass");
3450 return ErrorUnexpected;3480 return ErrorUnexpected;
3451 case Stmt::SizeOfPackExprClass:3481 case clang::Stmt::SizeOfPackExprClass:
3452 emit_warning(c, stmt->getLocStart(), "TODO handle C SizeOfPackExprClass");3482 emit_warning(c, stmt->getLocStart(), "TODO handle C SizeOfPackExprClass");
3453 return ErrorUnexpected;3483 return ErrorUnexpected;
3454 case Stmt::StmtExprClass:3484 case clang::Stmt::StmtExprClass:
3455 emit_warning(c, stmt->getLocStart(), "TODO handle C StmtExprClass");3485 emit_warning(c, stmt->getLocStart(), "TODO handle C StmtExprClass");
3456 return ErrorUnexpected;3486 return ErrorUnexpected;
3457 case Stmt::SubstNonTypeTemplateParmExprClass:3487 case clang::Stmt::SubstNonTypeTemplateParmExprClass:
3458 emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmExprClass");3488 emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmExprClass");
3459 return ErrorUnexpected;3489 return ErrorUnexpected;
3460 case Stmt::SubstNonTypeTemplateParmPackExprClass:3490 case clang::Stmt::SubstNonTypeTemplateParmPackExprClass:
3461 emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmPackExprClass");3491 emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmPackExprClass");
3462 return ErrorUnexpected;3492 return ErrorUnexpected;
3463 case Stmt::TypeTraitExprClass:3493 case clang::Stmt::TypeTraitExprClass:
3464 emit_warning(c, stmt->getLocStart(), "TODO handle C TypeTraitExprClass");3494 emit_warning(c, stmt->getLocStart(), "TODO handle C TypeTraitExprClass");
3465 return ErrorUnexpected;3495 return ErrorUnexpected;
3466 case Stmt::TypoExprClass:3496 case clang::Stmt::TypoExprClass:
3467 emit_warning(c, stmt->getLocStart(), "TODO handle C TypoExprClass");3497 emit_warning(c, stmt->getLocStart(), "TODO handle C TypoExprClass");
3468 return ErrorUnexpected;3498 return ErrorUnexpected;
3469 case Stmt::VAArgExprClass:3499 case clang::Stmt::VAArgExprClass:
3470 emit_warning(c, stmt->getLocStart(), "TODO handle C VAArgExprClass");3500 emit_warning(c, stmt->getLocStart(), "TODO handle C VAArgExprClass");
3471 return ErrorUnexpected;3501 return ErrorUnexpected;
3472 case Stmt::GotoStmtClass:3502 case clang::Stmt::GotoStmtClass:
3473 emit_warning(c, stmt->getLocStart(), "TODO handle C GotoStmtClass");3503 emit_warning(c, stmt->getLocStart(), "TODO handle C GotoStmtClass");
3474 return ErrorUnexpected;3504 return ErrorUnexpected;
3475 case Stmt::IndirectGotoStmtClass:3505 case clang::Stmt::IndirectGotoStmtClass:
3476 emit_warning(c, stmt->getLocStart(), "TODO handle C IndirectGotoStmtClass");3506 emit_warning(c, stmt->getLocStart(), "TODO handle C IndirectGotoStmtClass");
3477 return ErrorUnexpected;3507 return ErrorUnexpected;
3478 case Stmt::LabelStmtClass:3508 case clang::Stmt::LabelStmtClass:
3479 emit_warning(c, stmt->getLocStart(), "TODO handle C LabelStmtClass");3509 emit_warning(c, stmt->getLocStart(), "TODO handle C LabelStmtClass");
3480 return ErrorUnexpected;3510 return ErrorUnexpected;
3481 case Stmt::MSDependentExistsStmtClass:3511 case clang::Stmt::MSDependentExistsStmtClass:
3482 emit_warning(c, stmt->getLocStart(), "TODO handle C MSDependentExistsStmtClass");3512 emit_warning(c, stmt->getLocStart(), "TODO handle C MSDependentExistsStmtClass");
3483 return ErrorUnexpected;3513 return ErrorUnexpected;
3484 case Stmt::OMPAtomicDirectiveClass:3514 case clang::Stmt::OMPAtomicDirectiveClass:
3485 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPAtomicDirectiveClass");3515 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPAtomicDirectiveClass");
3486 return ErrorUnexpected;3516 return ErrorUnexpected;
3487 case Stmt::OMPBarrierDirectiveClass:3517 case clang::Stmt::OMPBarrierDirectiveClass:
3488 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPBarrierDirectiveClass");3518 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPBarrierDirectiveClass");
3489 return ErrorUnexpected;3519 return ErrorUnexpected;
3490 case Stmt::OMPCancelDirectiveClass:3520 case clang::Stmt::OMPCancelDirectiveClass:
3491 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCancelDirectiveClass");3521 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCancelDirectiveClass");
3492 return ErrorUnexpected;3522 return ErrorUnexpected;
3493 case Stmt::OMPCancellationPointDirectiveClass:3523 case clang::Stmt::OMPCancellationPointDirectiveClass:
3494 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCancellationPointDirectiveClass");3524 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCancellationPointDirectiveClass");
3495 return ErrorUnexpected;3525 return ErrorUnexpected;
3496 case Stmt::OMPCriticalDirectiveClass:3526 case clang::Stmt::OMPCriticalDirectiveClass:
3497 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCriticalDirectiveClass");3527 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCriticalDirectiveClass");
3498 return ErrorUnexpected;3528 return ErrorUnexpected;
3499 case Stmt::OMPFlushDirectiveClass:3529 case clang::Stmt::OMPFlushDirectiveClass:
3500 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPFlushDirectiveClass");3530 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPFlushDirectiveClass");
3501 return ErrorUnexpected;3531 return ErrorUnexpected;
3502 case Stmt::OMPDistributeDirectiveClass:3532 case clang::Stmt::OMPDistributeDirectiveClass:
3503 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeDirectiveClass");3533 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeDirectiveClass");
3504 return ErrorUnexpected;3534 return ErrorUnexpected;
3505 case Stmt::OMPDistributeParallelForDirectiveClass:3535 case clang::Stmt::OMPDistributeParallelForDirectiveClass:
3506 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeParallelForDirectiveClass");3536 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeParallelForDirectiveClass");
3507 return ErrorUnexpected;3537 return ErrorUnexpected;
3508 case Stmt::OMPDistributeParallelForSimdDirectiveClass:3538 case clang::Stmt::OMPDistributeParallelForSimdDirectiveClass:
3509 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeParallelForSimdDirectiveClass");3539 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeParallelForSimdDirectiveClass");
3510 return ErrorUnexpected;3540 return ErrorUnexpected;
3511 case Stmt::OMPDistributeSimdDirectiveClass:3541 case clang::Stmt::OMPDistributeSimdDirectiveClass:
3512 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeSimdDirectiveClass");3542 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeSimdDirectiveClass");
3513 return ErrorUnexpected;3543 return ErrorUnexpected;
3514 case Stmt::OMPForDirectiveClass:3544 case clang::Stmt::OMPForDirectiveClass:
3515 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPForDirectiveClass");3545 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPForDirectiveClass");
3516 return ErrorUnexpected;3546 return ErrorUnexpected;
3517 case Stmt::OMPForSimdDirectiveClass:3547 case clang::Stmt::OMPForSimdDirectiveClass:
3518 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPForSimdDirectiveClass");3548 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPForSimdDirectiveClass");
3519 return ErrorUnexpected;3549 return ErrorUnexpected;
3520 case Stmt::OMPParallelForDirectiveClass:3550 case clang::Stmt::OMPParallelForDirectiveClass:
3521 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelForDirectiveClass");3551 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelForDirectiveClass");
3522 return ErrorUnexpected;3552 return ErrorUnexpected;
3523 case Stmt::OMPParallelForSimdDirectiveClass:3553 case clang::Stmt::OMPParallelForSimdDirectiveClass:
3524 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelForSimdDirectiveClass");3554 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelForSimdDirectiveClass");
3525 return ErrorUnexpected;3555 return ErrorUnexpected;
3526 case Stmt::OMPSimdDirectiveClass:3556 case clang::Stmt::OMPSimdDirectiveClass:
3527 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSimdDirectiveClass");3557 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSimdDirectiveClass");
3528 return ErrorUnexpected;3558 return ErrorUnexpected;
3529 case Stmt::OMPTargetParallelForSimdDirectiveClass:3559 case clang::Stmt::OMPTargetParallelForSimdDirectiveClass:
3530 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelForSimdDirectiveClass");3560 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelForSimdDirectiveClass");
3531 return ErrorUnexpected;3561 return ErrorUnexpected;
3532 case Stmt::OMPTargetSimdDirectiveClass:3562 case clang::Stmt::OMPTargetSimdDirectiveClass:
3533 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetSimdDirectiveClass");3563 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetSimdDirectiveClass");
3534 return ErrorUnexpected;3564 return ErrorUnexpected;
3535 case Stmt::OMPTargetTeamsDistributeDirectiveClass:3565 case clang::Stmt::OMPTargetTeamsDistributeDirectiveClass:
3536 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeDirectiveClass");3566 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeDirectiveClass");
3537 return ErrorUnexpected;3567 return ErrorUnexpected;
3538 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:3568 case clang::Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
3539 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass");3569 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass");
3540 return ErrorUnexpected;3570 return ErrorUnexpected;
3541 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:3571 case clang::Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
3542 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass");3572 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass");
3543 return ErrorUnexpected;3573 return ErrorUnexpected;
3544 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:3574 case clang::Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
3545 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass");3575 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass");
3546 return ErrorUnexpected;3576 return ErrorUnexpected;
3547 case Stmt::OMPTaskLoopDirectiveClass:3577 case clang::Stmt::OMPTaskLoopDirectiveClass:
3548 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskLoopDirectiveClass");3578 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskLoopDirectiveClass");
3549 return ErrorUnexpected;3579 return ErrorUnexpected;
3550 case Stmt::OMPTaskLoopSimdDirectiveClass:3580 case clang::Stmt::OMPTaskLoopSimdDirectiveClass:
3551 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskLoopSimdDirectiveClass");3581 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskLoopSimdDirectiveClass");
3552 return ErrorUnexpected;3582 return ErrorUnexpected;
3553 case Stmt::OMPTeamsDistributeDirectiveClass:3583 case clang::Stmt::OMPTeamsDistributeDirectiveClass:
3554 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeDirectiveClass");3584 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeDirectiveClass");
3555 return ErrorUnexpected;3585 return ErrorUnexpected;
3556 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:3586 case clang::Stmt::OMPTeamsDistributeParallelForDirectiveClass:
3557 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass");3587 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass");
3558 return ErrorUnexpected;3588 return ErrorUnexpected;
3559 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:3589 case clang::Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
3560 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass");3590 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass");
3561 return ErrorUnexpected;3591 return ErrorUnexpected;
3562 case Stmt::OMPTeamsDistributeSimdDirectiveClass:3592 case clang::Stmt::OMPTeamsDistributeSimdDirectiveClass:
3563 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeSimdDirectiveClass");3593 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeSimdDirectiveClass");
3564 return ErrorUnexpected;3594 return ErrorUnexpected;
3565 case Stmt::OMPMasterDirectiveClass:3595 case clang::Stmt::OMPMasterDirectiveClass:
3566 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPMasterDirectiveClass");3596 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPMasterDirectiveClass");
3567 return ErrorUnexpected;3597 return ErrorUnexpected;
3568 case Stmt::OMPOrderedDirectiveClass:3598 case clang::Stmt::OMPOrderedDirectiveClass:
3569 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPOrderedDirectiveClass");3599 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPOrderedDirectiveClass");
3570 return ErrorUnexpected;3600 return ErrorUnexpected;
3571 case Stmt::OMPParallelDirectiveClass:3601 case clang::Stmt::OMPParallelDirectiveClass:
3572 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelDirectiveClass");3602 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelDirectiveClass");
3573 return ErrorUnexpected;3603 return ErrorUnexpected;
3574 case Stmt::OMPParallelSectionsDirectiveClass:3604 case clang::Stmt::OMPParallelSectionsDirectiveClass:
3575 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelSectionsDirectiveClass");3605 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelSectionsDirectiveClass");
3576 return ErrorUnexpected;3606 return ErrorUnexpected;
3577 case Stmt::OMPSectionDirectiveClass:3607 case clang::Stmt::OMPSectionDirectiveClass:
3578 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSectionDirectiveClass");3608 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSectionDirectiveClass");
3579 return ErrorUnexpected;3609 return ErrorUnexpected;
3580 case Stmt::OMPSectionsDirectiveClass:3610 case clang::Stmt::OMPSectionsDirectiveClass:
3581 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSectionsDirectiveClass");3611 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSectionsDirectiveClass");
3582 return ErrorUnexpected;3612 return ErrorUnexpected;
3583 case Stmt::OMPSingleDirectiveClass:3613 case clang::Stmt::OMPSingleDirectiveClass:
3584 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSingleDirectiveClass");3614 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSingleDirectiveClass");
3585 return ErrorUnexpected;3615 return ErrorUnexpected;
3586 case Stmt::OMPTargetDataDirectiveClass:3616 case clang::Stmt::OMPTargetDataDirectiveClass:
3587 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetDataDirectiveClass");3617 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetDataDirectiveClass");
3588 return ErrorUnexpected;3618 return ErrorUnexpected;
3589 case Stmt::OMPTargetDirectiveClass:3619 case clang::Stmt::OMPTargetDirectiveClass:
3590 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetDirectiveClass");3620 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetDirectiveClass");
3591 return ErrorUnexpected;3621 return ErrorUnexpected;
3592 case Stmt::OMPTargetEnterDataDirectiveClass:3622 case clang::Stmt::OMPTargetEnterDataDirectiveClass:
3593 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetEnterDataDirectiveClass");3623 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetEnterDataDirectiveClass");
3594 return ErrorUnexpected;3624 return ErrorUnexpected;
3595 case Stmt::OMPTargetExitDataDirectiveClass:3625 case clang::Stmt::OMPTargetExitDataDirectiveClass:
3596 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetExitDataDirectiveClass");3626 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetExitDataDirectiveClass");
3597 return ErrorUnexpected;3627 return ErrorUnexpected;
3598 case Stmt::OMPTargetParallelDirectiveClass:3628 case clang::Stmt::OMPTargetParallelDirectiveClass:
3599 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelDirectiveClass");3629 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelDirectiveClass");
3600 return ErrorUnexpected;3630 return ErrorUnexpected;
3601 case Stmt::OMPTargetParallelForDirectiveClass:3631 case clang::Stmt::OMPTargetParallelForDirectiveClass:
3602 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelForDirectiveClass");3632 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelForDirectiveClass");
3603 return ErrorUnexpected;3633 return ErrorUnexpected;
3604 case Stmt::OMPTargetTeamsDirectiveClass:3634 case clang::Stmt::OMPTargetTeamsDirectiveClass:
3605 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDirectiveClass");3635 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDirectiveClass");
3606 return ErrorUnexpected;3636 return ErrorUnexpected;
3607 case Stmt::OMPTargetUpdateDirectiveClass:3637 case clang::Stmt::OMPTargetUpdateDirectiveClass:
3608 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetUpdateDirectiveClass");3638 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetUpdateDirectiveClass");
3609 return ErrorUnexpected;3639 return ErrorUnexpected;
3610 case Stmt::OMPTaskDirectiveClass:3640 case clang::Stmt::OMPTaskDirectiveClass:
3611 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskDirectiveClass");3641 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskDirectiveClass");
3612 return ErrorUnexpected;3642 return ErrorUnexpected;
3613 case Stmt::OMPTaskgroupDirectiveClass:3643 case clang::Stmt::OMPTaskgroupDirectiveClass:
3614 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskgroupDirectiveClass");3644 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskgroupDirectiveClass");
3615 return ErrorUnexpected;3645 return ErrorUnexpected;
3616 case Stmt::OMPTaskwaitDirectiveClass:3646 case clang::Stmt::OMPTaskwaitDirectiveClass:
3617 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskwaitDirectiveClass");3647 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskwaitDirectiveClass");
3618 return ErrorUnexpected;3648 return ErrorUnexpected;
3619 case Stmt::OMPTaskyieldDirectiveClass:3649 case clang::Stmt::OMPTaskyieldDirectiveClass:
3620 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskyieldDirectiveClass");3650 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskyieldDirectiveClass");
3621 return ErrorUnexpected;3651 return ErrorUnexpected;
3622 case Stmt::OMPTeamsDirectiveClass:3652 case clang::Stmt::OMPTeamsDirectiveClass:
3623 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDirectiveClass");3653 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDirectiveClass");
3624 return ErrorUnexpected;3654 return ErrorUnexpected;
3625 case Stmt::ObjCAtCatchStmtClass:3655 case clang::Stmt::ObjCAtCatchStmtClass:
3626 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtCatchStmtClass");3656 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtCatchStmtClass");
3627 return ErrorUnexpected;3657 return ErrorUnexpected;
3628 case Stmt::ObjCAtFinallyStmtClass:3658 case clang::Stmt::ObjCAtFinallyStmtClass:
3629 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtFinallyStmtClass");3659 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtFinallyStmtClass");
3630 return ErrorUnexpected;3660 return ErrorUnexpected;
3631 case Stmt::ObjCAtSynchronizedStmtClass:3661 case clang::Stmt::ObjCAtSynchronizedStmtClass:
3632 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtSynchronizedStmtClass");3662 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtSynchronizedStmtClass");
3633 return ErrorUnexpected;3663 return ErrorUnexpected;
3634 case Stmt::ObjCAtThrowStmtClass:3664 case clang::Stmt::ObjCAtThrowStmtClass:
3635 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtThrowStmtClass");3665 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtThrowStmtClass");
3636 return ErrorUnexpected;3666 return ErrorUnexpected;
3637 case Stmt::ObjCAtTryStmtClass:3667 case clang::Stmt::ObjCAtTryStmtClass:
3638 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtTryStmtClass");3668 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtTryStmtClass");
3639 return ErrorUnexpected;3669 return ErrorUnexpected;
3640 case Stmt::ObjCAutoreleasePoolStmtClass:3670 case clang::Stmt::ObjCAutoreleasePoolStmtClass:
3641 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAutoreleasePoolStmtClass");3671 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAutoreleasePoolStmtClass");
3642 return ErrorUnexpected;3672 return ErrorUnexpected;
3643 case Stmt::ObjCForCollectionStmtClass:3673 case clang::Stmt::ObjCForCollectionStmtClass:
3644 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCForCollectionStmtClass");3674 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCForCollectionStmtClass");
3645 return ErrorUnexpected;3675 return ErrorUnexpected;
3646 case Stmt::SEHExceptStmtClass:3676 case clang::Stmt::SEHExceptStmtClass:
3647 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHExceptStmtClass");3677 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHExceptStmtClass");
3648 return ErrorUnexpected;3678 return ErrorUnexpected;
3649 case Stmt::SEHFinallyStmtClass:3679 case clang::Stmt::SEHFinallyStmtClass:
3650 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHFinallyStmtClass");3680 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHFinallyStmtClass");
3651 return ErrorUnexpected;3681 return ErrorUnexpected;
3652 case Stmt::SEHLeaveStmtClass:3682 case clang::Stmt::SEHLeaveStmtClass:
3653 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHLeaveStmtClass");3683 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHLeaveStmtClass");
3654 return ErrorUnexpected;3684 return ErrorUnexpected;
3655 case Stmt::SEHTryStmtClass:3685 case clang::Stmt::SEHTryStmtClass:
3656 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHTryStmtClass");3686 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHTryStmtClass");
3657 return ErrorUnexpected;3687 return ErrorUnexpected;
3658 case Stmt::FixedPointLiteralClass:3688 case clang::Stmt::FixedPointLiteralClass:
3659 emit_warning(c, stmt->getLocStart(), "TODO handle C FixedPointLiteralClass");3689 emit_warning(c, stmt->getLocStart(), "TODO handle C FixedPointLiteralClass");
3660 return ErrorUnexpected;3690 return ErrorUnexpected;
3661 }3691 }
...@@ -3663,7 +3693,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,...@@ -3663,7 +3693,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,
3663}3693}
36643694
3665// Returns null if there was an error3695// Returns null if there was an error
3666static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr,3696static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr,
3667 TransLRValue lrval)3697 TransLRValue lrval)
3668{3698{
3669 AstNode *result_node;3699 AstNode *result_node;
...@@ -3676,7 +3706,7 @@ static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope...@@ -3676,7 +3706,7 @@ static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope
36763706
3677// Statements have no result and no concept of L or R value.3707// Statements have no result and no concept of L or R value.
3678// Returns child scope, or null if there was an error3708// Returns child scope, or null if there was an error
3679static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node) {3709static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node) {
3680 TransScope *child_scope;3710 TransScope *child_scope;
3681 if (trans_stmt_extra(c, scope, stmt, ResultUsedNo, TransRValue, out_node, &child_scope, nullptr)) {3711 if (trans_stmt_extra(c, scope, stmt, ResultUsedNo, TransRValue, out_node, &child_scope, nullptr)) {
3682 return nullptr;3712 return nullptr;
...@@ -3684,7 +3714,7 @@ static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, A...@@ -3684,7 +3714,7 @@ static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, A
3684 return child_scope;3714 return child_scope;
3685}3715}
36863716
3687static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {3717static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {
3688 Buf *fn_name = buf_create_from_str(decl_name(fn_decl));3718 Buf *fn_name = buf_create_from_str(decl_name(fn_decl));
36893719
3690 if (get_global(c, fn_name)) {3720 if (get_global(c, fn_name)) {
...@@ -3701,13 +3731,13 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {...@@ -3701,13 +3731,13 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
3701 proto_node->data.fn_proto.name = fn_name;3731 proto_node->data.fn_proto.name = fn_name;
3702 proto_node->data.fn_proto.is_extern = !fn_decl->hasBody();3732 proto_node->data.fn_proto.is_extern = !fn_decl->hasBody();
37033733
3704 StorageClass sc = fn_decl->getStorageClass();3734 clang::StorageClass sc = fn_decl->getStorageClass();
3705 if (sc == SC_None) {3735 if (sc == clang::SC_None) {
3706 proto_node->data.fn_proto.visib_mod = c->visib_mod;3736 proto_node->data.fn_proto.visib_mod = c->visib_mod;
3707 proto_node->data.fn_proto.is_export = fn_decl->hasBody() ? c->want_export : false;3737 proto_node->data.fn_proto.is_export = fn_decl->hasBody() ? c->want_export : false;
3708 } else if (sc == SC_Extern || sc == SC_Static) {3738 } else if (sc == clang::SC_Extern || sc == clang::SC_Static) {
3709 proto_node->data.fn_proto.visib_mod = c->visib_mod;3739 proto_node->data.fn_proto.visib_mod = c->visib_mod;
3710 } else if (sc == SC_PrivateExtern) {3740 } else if (sc == clang::SC_PrivateExtern) {
3711 emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern");3741 emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern");
3712 return;3742 return;
3713 } else {3743 } else {
...@@ -3719,7 +3749,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {...@@ -3719,7 +3749,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
37193749
3720 for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {3750 for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
3721 AstNode *param_node = proto_node->data.fn_proto.params.at(i);3751 AstNode *param_node = proto_node->data.fn_proto.params.at(i);
3722 const ParmVarDecl *param = fn_decl->getParamDecl(i);3752 const clang::ParmVarDecl *param = fn_decl->getParamDecl(i);
3723 const char *name = decl_name(param);3753 const char *name = decl_name(param);
37243754
3725 Buf *proto_param_name;3755 Buf *proto_param_name;
...@@ -3746,7 +3776,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {...@@ -3746,7 +3776,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
37463776
3747 // actual function definition with body3777 // actual function definition with body
3748 c->ptr_params.clear();3778 c->ptr_params.clear();
3749 Stmt *body = fn_decl->getBody();3779 clang::Stmt *body = fn_decl->getBody();
3750 AstNode *actual_body_node;3780 AstNode *actual_body_node;
3751 TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node);3781 TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node);
3752 if (result_scope == nullptr) {3782 if (result_scope == nullptr) {
...@@ -3788,19 +3818,19 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {...@@ -3788,19 +3818,19 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
3788 add_top_level_decl(c, fn_def_node->data.fn_def.fn_proto->data.fn_proto.name, fn_def_node);3818 add_top_level_decl(c, fn_def_node->data.fn_def.fn_proto->data.fn_proto.name, fn_def_node);
3789}3819}
37903820
3791static AstNode *resolve_typdef_as_builtin(Context *c, const TypedefNameDecl *typedef_decl, const char *primitive_name) {3821static AstNode *resolve_typdef_as_builtin(Context *c, const clang::TypedefNameDecl *typedef_decl, const char *primitive_name) {
3792 AstNode *node = trans_create_node_symbol_str(c, primitive_name);3822 AstNode *node = trans_create_node_symbol_str(c, primitive_name);
3793 c->decl_table.put(typedef_decl, node);3823 c->decl_table.put(typedef_decl, node);
3794 return node;3824 return node;
3795}3825}
37963826
3797static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) {3827static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl) {
3798 auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());3828 auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());
3799 if (existing_entry) {3829 if (existing_entry) {
3800 return existing_entry->value;3830 return existing_entry->value;
3801 }3831 }
38023832
3803 QualType child_qt = typedef_decl->getUnderlyingType();3833 clang::QualType child_qt = typedef_decl->getUnderlyingType();
3804 Buf *type_name = buf_create_from_str(decl_name(typedef_decl));3834 Buf *type_name = buf_create_from_str(decl_name(typedef_decl));
38053835
3806 if (buf_eql_str(type_name, "uint8_t")) {3836 if (buf_eql_str(type_name, "uint8_t")) {
...@@ -3849,7 +3879,7 @@ static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_...@@ -3849,7 +3879,7 @@ static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_
3849 return symbol_node;3879 return symbol_node;
3850}3880}
38513881
3852struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl,3882struct AstNode *demote_enum_to_opaque(Context *c, const clang::EnumDecl *enum_decl,
3853 Buf *full_type_name, Buf *bare_name)3883 Buf *full_type_name, Buf *bare_name)
3854{3884{
3855 AstNode *opaque_node = trans_create_node_opaque(c);3885 AstNode *opaque_node = trans_create_node_opaque(c);
...@@ -3864,7 +3894,7 @@ struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl,...@@ -3864,7 +3894,7 @@ struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl,
3864 return symbol_node;3894 return symbol_node;
3865}3895}
38663896
3867static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {3897static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl) {
3868 auto existing_entry = c->decl_table.maybe_get((void*)enum_decl->getCanonicalDecl());3898 auto existing_entry = c->decl_table.maybe_get((void*)enum_decl->getCanonicalDecl());
3869 if (existing_entry) {3899 if (existing_entry) {
3870 return existing_entry->value;3900 return existing_entry->value;
...@@ -3875,7 +3905,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -3875,7 +3905,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
3875 Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);3905 Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
3876 Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name));3906 Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name));
38773907
3878 const EnumDecl *enum_def = enum_decl->getDefinition();3908 const clang::EnumDecl *enum_def = enum_decl->getDefinition();
3879 if (!enum_def) {3909 if (!enum_def) {
3880 return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name);3910 return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name);
3881 }3911 }
...@@ -3887,7 +3917,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -3887,7 +3917,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
3887 it_end = enum_def->enumerator_end();3917 it_end = enum_def->enumerator_end();
3888 it != it_end; ++it, field_count += 1)3918 it != it_end; ++it, field_count += 1)
3889 {3919 {
3890 const EnumConstantDecl *enum_const = *it;3920 const clang::EnumConstantDecl *enum_const = *it;
3891 if (enum_const->getInitExpr()) {3921 if (enum_const->getInitExpr()) {
3892 pure_enum = false;3922 pure_enum = false;
3893 }3923 }
...@@ -3901,8 +3931,8 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -3901,8 +3931,8 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
3901 // TODO only emit this tag type if the enum tag type is not the default.3931 // TODO only emit this tag type if the enum tag type is not the default.
3902 // I don't know what the default is, need to figure out how clang is deciding.3932 // I don't know what the default is, need to figure out how clang is deciding.
3903 // it appears to at least be different across gcc/msvc3933 // it appears to at least be different across gcc/msvc
3904 if (!c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::UInt) &&3934 if (!c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::UInt) &&
3905 !c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::Int))3935 !c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::Int))
3906 {3936 {
3907 enum_node->data.container_decl.init_arg_expr = tag_int_type;3937 enum_node->data.container_decl.init_arg_expr = tag_int_type;
3908 }3938 }
...@@ -3912,7 +3942,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -3912,7 +3942,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
3912 it_end = enum_def->enumerator_end();3942 it_end = enum_def->enumerator_end();
3913 it != it_end; ++it, i += 1)3943 it != it_end; ++it, i += 1)
3914 {3944 {
3915 const EnumConstantDecl *enum_const = *it;3945 const clang::EnumConstantDecl *enum_const = *it;
39163946
3917 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));3947 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
3918 Buf *field_name;3948 Buf *field_name;
...@@ -3953,7 +3983,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -3953,7 +3983,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
3953 }3983 }
3954}3984}
39553985
3956static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_decl,3986static AstNode *demote_struct_to_opaque(Context *c, const clang::RecordDecl *record_decl,
3957 Buf *full_type_name, Buf *bare_name)3987 Buf *full_type_name, Buf *bare_name)
3958{3988{
3959 AstNode *opaque_node = trans_create_node_opaque(c);3989 AstNode *opaque_node = trans_create_node_opaque(c);
...@@ -3968,7 +3998,7 @@ static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_dec...@@ -3968,7 +3998,7 @@ static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_dec
3968 return symbol_node;3998 return symbol_node;
3969}3999}
39704000
3971static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {4001static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl) {
3972 auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl());4002 auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl());
3973 if (existing_entry) {4003 if (existing_entry) {
3974 return existing_entry->value;4004 return existing_entry->value;
...@@ -3994,7 +4024,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {...@@ -3994,7 +4024,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
3994 Buf *full_type_name = (bare_name == nullptr) ?4024 Buf *full_type_name = (bare_name == nullptr) ?
3995 nullptr : buf_sprintf("%s_%s", container_kind_name, buf_ptr(bare_name));4025 nullptr : buf_sprintf("%s_%s", container_kind_name, buf_ptr(bare_name));
39964026
3997 RecordDecl *record_def = record_decl->getDefinition();4027 clang::RecordDecl *record_def = record_decl->getDefinition();
3998 if (record_def == nullptr) {4028 if (record_def == nullptr) {
3999 return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);4029 return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
4000 }4030 }
...@@ -4005,7 +4035,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {...@@ -4005,7 +4035,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
4005 it_end = record_def->field_end();4035 it_end = record_def->field_end();
4006 it != it_end; ++it, field_count += 1)4036 it != it_end; ++it, field_count += 1)
4007 {4037 {
4008 const FieldDecl *field_decl = *it;4038 const clang::FieldDecl *field_decl = *it;
40094039
4010 if (field_decl->isBitField()) {4040 if (field_decl->isBitField()) {
4011 emit_warning(c, field_decl->getLocation(), "%s %s demoted to opaque type - has bitfield",4041 emit_warning(c, field_decl->getLocation(), "%s %s demoted to opaque type - has bitfield",
...@@ -4035,7 +4065,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {...@@ -4035,7 +4065,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
4035 it_end = record_def->field_end();4065 it_end = record_def->field_end();
4036 it != it_end; ++it, i += 1)4066 it != it_end; ++it, i += 1)
4037 {4067 {
4038 const FieldDecl *field_decl = *it;4068 const clang::FieldDecl *field_decl = *it;
40394069
4040 AstNode *field_node = trans_create_node(c, NodeTypeStructField);4070 AstNode *field_node = trans_create_node(c, NodeTypeStructField);
4041 field_node->data.struct_field.name = buf_create_from_str(decl_name(field_decl));4071 field_node->data.struct_field.name = buf_create_from_str(decl_name(field_decl));
...@@ -4062,13 +4092,13 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {...@@ -4062,13 +4092,13 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
4062 }4092 }
4063}4093}
40644094
4065static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const SourceLocation &source_loc) {4095static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, const clang::SourceLocation &source_loc) {
4066 switch (ap_value->getKind()) {4096 switch (ap_value->getKind()) {
4067 case APValue::Int:4097 case clang::APValue::Int:
4068 return trans_create_node_apint(c, ap_value->getInt());4098 return trans_create_node_apint(c, ap_value->getInt());
4069 case APValue::Uninitialized:4099 case clang::APValue::Uninitialized:
4070 return trans_create_node(c, NodeTypeUndefinedLiteral);4100 return trans_create_node(c, NodeTypeUndefinedLiteral);
4071 case APValue::Array: {4101 case clang::APValue::Array: {
4072 emit_warning(c, source_loc, "TODO add a test case for this code");4102 emit_warning(c, source_loc, "TODO add a test case for this code");
40734103
4074 unsigned init_count = ap_value->getArrayInitializedElts();4104 unsigned init_count = ap_value->getArrayInitializedElts();
...@@ -4076,13 +4106,16 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const...@@ -4076,13 +4106,16 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const
4076 unsigned leftover_count = all_count - init_count;4106 unsigned leftover_count = all_count - init_count;
4077 AstNode *init_node = trans_create_node(c, NodeTypeContainerInitExpr);4107 AstNode *init_node = trans_create_node(c, NodeTypeContainerInitExpr);
4078 AstNode *arr_type_node = trans_qual_type(c, qt, source_loc);4108 AstNode *arr_type_node = trans_qual_type(c, qt, source_loc);
4109 if (leftover_count != 0) { // We can't use the size of the final array for a partial initializer.
4110 bigint_init_unsigned(arr_type_node->data.array_type.size->data.int_literal.bigint, init_count);
4111 }
4079 init_node->data.container_init_expr.type = arr_type_node;4112 init_node->data.container_init_expr.type = arr_type_node;
4080 init_node->data.container_init_expr.kind = ContainerInitKindArray;4113 init_node->data.container_init_expr.kind = ContainerInitKindArray;
40814114
4082 QualType child_qt = qt.getTypePtr()->getLocallyUnqualifiedSingleStepDesugaredType();4115 clang::QualType child_qt = qt.getTypePtr()->getAsArrayTypeUnsafe()->getElementType();
40834116
4084 for (size_t i = 0; i < init_count; i += 1) {4117 for (size_t i = 0; i < init_count; i += 1) {
4085 APValue &elem_ap_val = ap_value->getArrayInitializedElt(i);4118 clang::APValue &elem_ap_val = ap_value->getArrayInitializedElt(i);
4086 AstNode *elem_node = trans_ap_value(c, &elem_ap_val, child_qt, source_loc);4119 AstNode *elem_node = trans_ap_value(c, &elem_ap_val, child_qt, source_loc);
4087 if (elem_node == nullptr)4120 if (elem_node == nullptr)
4088 return nullptr;4121 return nullptr;
...@@ -4092,15 +4125,19 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const...@@ -4092,15 +4125,19 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const
4092 return init_node;4125 return init_node;
4093 }4126 }
40944127
4095 APValue &filler_ap_val = ap_value->getArrayFiller();4128 clang::APValue &filler_ap_val = ap_value->getArrayFiller();
4096 AstNode *filler_node = trans_ap_value(c, &filler_ap_val, child_qt, source_loc);4129 AstNode *filler_node = trans_ap_value(c, &filler_ap_val, child_qt, source_loc);
4097 if (filler_node == nullptr)4130 if (filler_node == nullptr)
4098 return nullptr;4131 return nullptr;
40994132
4133 AstNode* filler_arr_type = trans_create_node(c, NodeTypeArrayType);
4134 *filler_arr_type = *arr_type_node;
4135 filler_arr_type->data.array_type.size = trans_create_node_unsigned(c, 1);
4136
4100 AstNode *filler_arr_1 = trans_create_node(c, NodeTypeContainerInitExpr);4137 AstNode *filler_arr_1 = trans_create_node(c, NodeTypeContainerInitExpr);
4101 init_node->data.container_init_expr.type = arr_type_node;4138 filler_arr_1->data.container_init_expr.type = filler_arr_type;
4102 init_node->data.container_init_expr.kind = ContainerInitKindArray;4139 filler_arr_1->data.container_init_expr.kind = ContainerInitKindArray;
4103 init_node->data.container_init_expr.entries.append(filler_node);4140 filler_arr_1->data.container_init_expr.entries.append(filler_node);
41044141
4105 AstNode *rhs_node;4142 AstNode *rhs_node;
4106 if (leftover_count == 1) {4143 if (leftover_count == 1) {
...@@ -4110,62 +4147,66 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const...@@ -4110,62 +4147,66 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const
4110 rhs_node = trans_create_node_bin_op(c, filler_arr_1, BinOpTypeArrayMult, amt_node);4147 rhs_node = trans_create_node_bin_op(c, filler_arr_1, BinOpTypeArrayMult, amt_node);
4111 }4148 }
41124149
4150 if (init_count == 0) {
4151 return rhs_node;
4152 }
4153
4113 return trans_create_node_bin_op(c, init_node, BinOpTypeArrayCat, rhs_node);4154 return trans_create_node_bin_op(c, init_node, BinOpTypeArrayCat, rhs_node);
4114 }4155 }
4115 case APValue::LValue: {4156 case clang::APValue::LValue: {
4116 const APValue::LValueBase lval_base = ap_value->getLValueBase();4157 const clang::APValue::LValueBase lval_base = ap_value->getLValueBase();
4117 if (const Expr *expr = lval_base.dyn_cast<const Expr *>()) {4158 if (const clang::Expr *expr = lval_base.dyn_cast<const clang::Expr *>()) {
4118 return trans_expr(c, ResultUsedYes, &c->global_scope->base, expr, TransRValue);4159 return trans_expr(c, ResultUsedYes, &c->global_scope->base, expr, TransRValue);
4119 }4160 }
4120 //const ValueDecl *value_decl = lval_base.get<const ValueDecl *>();4161 //const clang::ValueDecl *value_decl = lval_base.get<const clang::ValueDecl *>();
4121 emit_warning(c, source_loc, "TODO handle initializer LValue ValueDecl");4162 emit_warning(c, source_loc, "TODO handle initializer LValue clang::ValueDecl");
4122 return nullptr;4163 return nullptr;
4123 }4164 }
4124 case APValue::Float:4165 case clang::APValue::Float:
4125 emit_warning(c, source_loc, "unsupported initializer value kind: Float");4166 emit_warning(c, source_loc, "unsupported initializer value kind: Float");
4126 return nullptr;4167 return nullptr;
4127 case APValue::ComplexInt:4168 case clang::APValue::ComplexInt:
4128 emit_warning(c, source_loc, "unsupported initializer value kind: ComplexInt");4169 emit_warning(c, source_loc, "unsupported initializer value kind: ComplexInt");
4129 return nullptr;4170 return nullptr;
4130 case APValue::ComplexFloat:4171 case clang::APValue::ComplexFloat:
4131 emit_warning(c, source_loc, "unsupported initializer value kind: ComplexFloat");4172 emit_warning(c, source_loc, "unsupported initializer value kind: ComplexFloat");
4132 return nullptr;4173 return nullptr;
4133 case APValue::Vector:4174 case clang::APValue::Vector:
4134 emit_warning(c, source_loc, "unsupported initializer value kind: Vector");4175 emit_warning(c, source_loc, "unsupported initializer value kind: Vector");
4135 return nullptr;4176 return nullptr;
4136 case APValue::Struct:4177 case clang::APValue::Struct:
4137 emit_warning(c, source_loc, "unsupported initializer value kind: Struct");4178 emit_warning(c, source_loc, "unsupported initializer value kind: Struct");
4138 return nullptr;4179 return nullptr;
4139 case APValue::Union:4180 case clang::APValue::Union:
4140 emit_warning(c, source_loc, "unsupported initializer value kind: Union");4181 emit_warning(c, source_loc, "unsupported initializer value kind: Union");
4141 return nullptr;4182 return nullptr;
4142 case APValue::MemberPointer:4183 case clang::APValue::MemberPointer:
4143 emit_warning(c, source_loc, "unsupported initializer value kind: MemberPointer");4184 emit_warning(c, source_loc, "unsupported initializer value kind: MemberPointer");
4144 return nullptr;4185 return nullptr;
4145 case APValue::AddrLabelDiff:4186 case clang::APValue::AddrLabelDiff:
4146 emit_warning(c, source_loc, "unsupported initializer value kind: AddrLabelDiff");4187 emit_warning(c, source_loc, "unsupported initializer value kind: AddrLabelDiff");
4147 return nullptr;4188 return nullptr;
4148 }4189 }
4149 zig_unreachable();4190 zig_unreachable();
4150}4191}
41514192
4152static void visit_var_decl(Context *c, const VarDecl *var_decl) {4193static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) {
4153 Buf *name = buf_create_from_str(decl_name(var_decl));4194 Buf *name = buf_create_from_str(decl_name(var_decl));
41544195
4155 switch (var_decl->getTLSKind()) {4196 switch (var_decl->getTLSKind()) {
4156 case VarDecl::TLS_None:4197 case clang::VarDecl::TLS_None:
4157 break;4198 break;
4158 case VarDecl::TLS_Static:4199 case clang::VarDecl::TLS_Static:
4159 emit_warning(c, var_decl->getLocation(),4200 emit_warning(c, var_decl->getLocation(),
4160 "ignoring variable '%s' - static thread local storage", buf_ptr(name));4201 "ignoring variable '%s' - static thread local storage", buf_ptr(name));
4161 return;4202 return;
4162 case VarDecl::TLS_Dynamic:4203 case clang::VarDecl::TLS_Dynamic:
4163 emit_warning(c, var_decl->getLocation(),4204 emit_warning(c, var_decl->getLocation(),
4164 "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name));4205 "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name));
4165 return;4206 return;
4166 }4207 }
41674208
4168 QualType qt = var_decl->getType();4209 clang::QualType qt = var_decl->getType();
4169 AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation());4210 AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation());
4170 if (var_type == nullptr) {4211 if (var_type == nullptr) {
4171 emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type", buf_ptr(name));4212 emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type", buf_ptr(name));
...@@ -4179,7 +4220,7 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {...@@ -4179,7 +4220,7 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
4179 if (is_static && !is_extern) {4220 if (is_static && !is_extern) {
4180 AstNode *init_node;4221 AstNode *init_node;
4181 if (var_decl->hasInit()) {4222 if (var_decl->hasInit()) {
4182 APValue *ap_value = var_decl->evaluateValue();4223 clang::APValue *ap_value = var_decl->evaluateValue();
4183 if (ap_value == nullptr) {4224 if (ap_value == nullptr) {
4184 emit_warning(c, var_decl->getLocation(),4225 emit_warning(c, var_decl->getLocation(),
4185 "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name));4226 "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name));
...@@ -4209,24 +4250,25 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {...@@ -4209,24 +4250,25 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
4209 return;4250 return;
4210}4251}
42114252
4212static bool decl_visitor(void *context, const Decl *decl) {4253static bool decl_visitor(void *context, const ZigClangDecl *zdecl) {
4254 const clang::Decl *decl = reinterpret_cast<const clang::Decl *>(zdecl);
4213 Context *c = (Context*)context;4255 Context *c = (Context*)context;
42144256
4215 switch (decl->getKind()) {4257 switch (decl->getKind()) {
4216 case Decl::Function:4258 case clang::Decl::Function:
4217 visit_fn_decl(c, static_cast<const FunctionDecl*>(decl));4259 visit_fn_decl(c, static_cast<const clang::FunctionDecl*>(decl));
4218 break;4260 break;
4219 case Decl::Typedef:4261 case clang::Decl::Typedef:
4220 resolve_typedef_decl(c, static_cast<const TypedefNameDecl *>(decl));4262 resolve_typedef_decl(c, static_cast<const clang::TypedefNameDecl *>(decl));
4221 break;4263 break;
4222 case Decl::Enum:4264 case clang::Decl::Enum:
4223 resolve_enum_decl(c, static_cast<const EnumDecl *>(decl));4265 resolve_enum_decl(c, static_cast<const clang::EnumDecl *>(decl));
4224 break;4266 break;
4225 case Decl::Record:4267 case clang::Decl::Record:
4226 resolve_record_decl(c, static_cast<const RecordDecl *>(decl));4268 resolve_record_decl(c, static_cast<const clang::RecordDecl *>(decl));
4227 break;4269 break;
4228 case Decl::Var:4270 case clang::Decl::Var:
4229 visit_var_decl(c, static_cast<const VarDecl *>(decl));4271 visit_var_decl(c, static_cast<const clang::VarDecl *>(decl));
4230 break;4272 break;
4231 default:4273 default:
4232 emit_warning(c, decl->getLocation(), "ignoring %s decl", decl->getDeclKindName());4274 emit_warning(c, decl->getLocation(), "ignoring %s decl", decl->getDeclKindName());
...@@ -4568,7 +4610,7 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t...@@ -4568,7 +4610,7 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t
4568 } else if (first_tok->id == CTokIdAsterisk) {4610 } else if (first_tok->id == CTokIdAsterisk) {
4569 *tok_i += 1;4611 *tok_i += 1;
45704612
4571 node = trans_create_node_ptr_type(c, false, false, node, PtrLenUnknown);4613 node = trans_create_node_ptr_type(c, false, false, node, PtrLenC);
4572 } else {4614 } else {
4573 return node;4615 return node;
4574 }4616 }
...@@ -4647,24 +4689,25 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch...@@ -4647,24 +4689,25 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch
4647 c->macro_table.put(name, result_node);4689 c->macro_table.put(name, result_node);
4648}4690}
46494691
4650static void process_preprocessor_entities(Context *c, ASTUnit &unit) {4692static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) {
4693 clang::ASTUnit *unit = reinterpret_cast<clang::ASTUnit *>(zunit);
4651 CTokenize ctok = {{0}};4694 CTokenize ctok = {{0}};
46524695
4653 // TODO if we see #undef, delete it from the table4696 // TODO if we see #undef, delete it from the table
46544697
4655 for (PreprocessedEntity *entity : unit.getLocalPreprocessingEntities()) {4698 for (clang::PreprocessedEntity *entity : unit->getLocalPreprocessingEntities()) {
4656 switch (entity->getKind()) {4699 switch (entity->getKind()) {
4657 case PreprocessedEntity::InvalidKind:4700 case clang::PreprocessedEntity::InvalidKind:
4658 case PreprocessedEntity::InclusionDirectiveKind:4701 case clang::PreprocessedEntity::InclusionDirectiveKind:
4659 case PreprocessedEntity::MacroExpansionKind:4702 case clang::PreprocessedEntity::MacroExpansionKind:
4660 continue;4703 continue;
4661 case PreprocessedEntity::MacroDefinitionKind:4704 case clang::PreprocessedEntity::MacroDefinitionKind:
4662 {4705 {
4663 MacroDefinitionRecord *macro = static_cast<MacroDefinitionRecord *>(entity);4706 clang::MacroDefinitionRecord *macro = static_cast<clang::MacroDefinitionRecord *>(entity);
4664 const char *raw_name = macro->getName()->getNameStart();4707 const char *raw_name = macro->getName()->getNameStart();
4665 SourceRange range = macro->getSourceRange();4708 clang::SourceRange range = macro->getSourceRange();
4666 SourceLocation begin_loc = range.getBegin();4709 clang::SourceLocation begin_loc = range.getBegin();
4667 SourceLocation end_loc = range.getEnd();4710 clang::SourceLocation end_loc = range.getEnd();
46684711
4669 if (begin_loc == end_loc) {4712 if (begin_loc == end_loc) {
4670 // this means it is a macro without a value4713 // this means it is a macro without a value
...@@ -4676,7 +4719,7 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) {...@@ -4676,7 +4719,7 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) {
4676 continue;4719 continue;
4677 }4720 }
46784721
4679 const char *begin_c = c->source_manager->getCharacterData(begin_loc);4722 const char *begin_c = ZigClangSourceManager_getCharacterData(c->source_manager, bitcast(begin_loc));
4680 process_macro(c, &ctok, name, begin_c);4723 process_macro(c, &ctok, name, begin_c);
4681 }4724 }
4682 }4725 }
...@@ -4749,8 +4792,10 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const...@@ -4749,8 +4792,10 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
4749 clang_argv.append("-isystem");4792 clang_argv.append("-isystem");
4750 clang_argv.append(buf_ptr(codegen->zig_c_headers_dir));4793 clang_argv.append(buf_ptr(codegen->zig_c_headers_dir));
47514794
4752 clang_argv.append("-isystem");4795 if (codegen->libc_include_dir != nullptr) {
4753 clang_argv.append(buf_ptr(codegen->libc_include_dir));4796 clang_argv.append("-isystem");
4797 clang_argv.append(buf_ptr(codegen->libc_include_dir));
4798 }
47544799
4755 // windows c runtime requires -D_DEBUG if using debug libraries4800 // windows c runtime requires -D_DEBUG if using debug libraries
4756 if (codegen->build_mode == BuildModeDebug) {4801 if (codegen->build_mode == BuildModeDebug) {
...@@ -4776,12 +4821,20 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const...@@ -4776,12 +4821,20 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
47764821
4777 clang_argv.append(target_file);4822 clang_argv.append(target_file);
47784823
4824 if (codegen->verbose_cimport) {
4825 fprintf(stderr, "clang");
4826 for (size_t i = 0; i < clang_argv.length; i += 1) {
4827 fprintf(stderr, " %s", clang_argv.at(i));
4828 }
4829 fprintf(stderr, "\n");
4830 }
4831
4779 // to make the [start...end] argument work4832 // to make the [start...end] argument work
4780 clang_argv.append(nullptr);4833 clang_argv.append(nullptr);
47814834
4782 IntrusiveRefCntPtr<DiagnosticsEngine> diags(CompilerInstance::createDiagnostics(new DiagnosticOptions));4835 clang::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions));
47834836
4784 std::shared_ptr<PCHContainerOperations> pch_container_ops = std::make_shared<PCHContainerOperations>();4837 std::shared_ptr<clang::PCHContainerOperations> pch_container_ops = std::make_shared<clang::PCHContainerOperations>();
47854838
4786 bool only_local_decls = true;4839 bool only_local_decls = true;
4787 bool capture_diagnostics = true;4840 bool capture_diagnostics = true;
...@@ -4790,13 +4843,13 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const...@@ -4790,13 +4843,13 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
4790 bool single_file_parse = false;4843 bool single_file_parse = false;
4791 bool for_serialization = false;4844 bool for_serialization = false;
4792 const char *resources_path = buf_ptr(codegen->zig_c_headers_dir);4845 const char *resources_path = buf_ptr(codegen->zig_c_headers_dir);
4793 std::unique_ptr<ASTUnit> err_unit;4846 std::unique_ptr<clang::ASTUnit> err_unit;
4794 std::unique_ptr<ASTUnit> ast_unit(ASTUnit::LoadFromCommandLine(4847 ZigClangASTUnit *ast_unit = reinterpret_cast<ZigClangASTUnit *>(clang::ASTUnit::LoadFromCommandLine(
4795 &clang_argv.at(0), &clang_argv.last(),4848 &clang_argv.at(0), &clang_argv.last(),
4796 pch_container_ops, diags, resources_path,4849 pch_container_ops, diags, resources_path,
4797 only_local_decls, capture_diagnostics, None, true, 0, TU_Complete,4850 only_local_decls, capture_diagnostics, clang::None, true, 0, clang::TU_Complete,
4798 false, false, allow_pch_with_compiler_errors, SkipFunctionBodiesScope::None,4851 false, false, allow_pch_with_compiler_errors, clang::SkipFunctionBodiesScope::None,
4799 single_file_parse, user_files_are_volatile, for_serialization, None, &err_unit,4852 single_file_parse, user_files_are_volatile, for_serialization, clang::None, &err_unit,
4800 nullptr));4853 nullptr));
48014854
4802 // Early failures in LoadFromCommandLine may return with ErrUnit unset.4855 // Early failures in LoadFromCommandLine may return with ErrUnit unset.
...@@ -4806,29 +4859,29 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const...@@ -4806,29 +4859,29 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
48064859
4807 if (diags->getClient()->getNumErrors() > 0) {4860 if (diags->getClient()->getNumErrors() > 0) {
4808 if (ast_unit) {4861 if (ast_unit) {
4809 err_unit = std::move(ast_unit);4862 err_unit = std::unique_ptr<clang::ASTUnit>(reinterpret_cast<clang::ASTUnit *>(ast_unit));
4810 }4863 }
48114864
4812 for (ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(),4865 for (clang::ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(),
4813 it_end = err_unit->stored_diag_end();4866 it_end = err_unit->stored_diag_end();
4814 it != it_end; ++it)4867 it != it_end; ++it)
4815 {4868 {
4816 switch (it->getLevel()) {4869 switch (it->getLevel()) {
4817 case DiagnosticsEngine::Ignored:4870 case clang::DiagnosticsEngine::Ignored:
4818 case DiagnosticsEngine::Note:4871 case clang::DiagnosticsEngine::Note:
4819 case DiagnosticsEngine::Remark:4872 case clang::DiagnosticsEngine::Remark:
4820 case DiagnosticsEngine::Warning:4873 case clang::DiagnosticsEngine::Warning:
4821 continue;4874 continue;
4822 case DiagnosticsEngine::Error:4875 case clang::DiagnosticsEngine::Error:
4823 case DiagnosticsEngine::Fatal:4876 case clang::DiagnosticsEngine::Fatal:
4824 break;4877 break;
4825 }4878 }
4826 StringRef msg_str_ref = it->getMessage();4879 StringRef msg_str_ref = it->getMessage();
4827 Buf *msg = string_ref_to_buf(msg_str_ref);4880 Buf *msg = string_ref_to_buf(msg_str_ref);
4828 FullSourceLoc fsl = it->getLocation();4881 clang::FullSourceLoc fsl = it->getLocation();
4829 if (fsl.hasManager()) {4882 if (fsl.hasManager()) {
4830 FileID file_id = fsl.getFileID();4883 clang::FileID file_id = fsl.getFileID();
4831 StringRef filename = fsl.getManager().getFilename(fsl);4884 clang::StringRef filename = fsl.getManager().getFilename(fsl);
4832 unsigned line = fsl.getSpellingLineNumber() - 1;4885 unsigned line = fsl.getSpellingLineNumber() - 1;
4833 unsigned column = fsl.getSpellingColumnNumber() - 1;4886 unsigned column = fsl.getSpellingColumnNumber() - 1;
4834 unsigned offset = fsl.getManager().getFileOffset(fsl);4887 unsigned offset = fsl.getManager().getFileOffset(fsl);
...@@ -4853,14 +4906,14 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const...@@ -4853,14 +4906,14 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
4853 return ErrorCCompileErrors;4906 return ErrorCCompileErrors;
4854 }4907 }
48554908
4856 c->ctx = &ast_unit->getASTContext();4909 c->ctx = ZigClangASTUnit_getASTContext(ast_unit);
4857 c->source_manager = &ast_unit->getSourceManager();4910 c->source_manager = ZigClangASTUnit_getSourceManager(ast_unit);
4858 c->root = trans_create_node(c, NodeTypeContainerDecl);4911 c->root = trans_create_node(c, NodeTypeContainerDecl);
4859 c->root->data.container_decl.is_root = true;4912 c->root->data.container_decl.is_root = true;
48604913
4861 ast_unit->visitLocalTopLevelDecls(c, decl_visitor);4914 ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, c, decl_visitor);
48624915
4863 process_preprocessor_entities(c, *ast_unit);4916 process_preprocessor_entities(c, ast_unit);
48644917
4865 render_macros(c);4918 render_macros(c);
4866 render_aliases(c);4919 render_aliases(c);
src/zig_clang.cpp created+214
...@@ -0,0 +1,214 @@
1/*
2 * Copyright (c) 2019 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8
9/*
10 * The point of this file is to contain all the Clang C++ API interaction so that:
11 * 1. The compile time of other files is kept under control.
12 * 2. Provide a C interface to the Clang functions we need for self-hosting purposes.
13 * 3. Prevent C++ from infecting the rest of the project.
14 */
15#include "zig_clang.h"
16
17#if __GNUC__ >= 8
18#pragma GCC diagnostic push
19#pragma GCC diagnostic ignored "-Wclass-memaccess"
20#endif
21
22#include <clang/Frontend/ASTUnit.h>
23#include <clang/Frontend/CompilerInstance.h>
24#include <clang/AST/Expr.h>
25
26#if __GNUC__ >= 8
27#pragma GCC diagnostic pop
28#endif
29
30// Detect additions to the enum
31void zig2clang_BO(ZigClangBO op) {
32 switch (op) {
33 case ZigClangBO_PtrMemD:
34 case ZigClangBO_PtrMemI:
35 case ZigClangBO_Cmp:
36 case ZigClangBO_Mul:
37 case ZigClangBO_Div:
38 case ZigClangBO_Rem:
39 case ZigClangBO_Add:
40 case ZigClangBO_Sub:
41 case ZigClangBO_Shl:
42 case ZigClangBO_Shr:
43 case ZigClangBO_LT:
44 case ZigClangBO_GT:
45 case ZigClangBO_LE:
46 case ZigClangBO_GE:
47 case ZigClangBO_EQ:
48 case ZigClangBO_NE:
49 case ZigClangBO_And:
50 case ZigClangBO_Xor:
51 case ZigClangBO_Or:
52 case ZigClangBO_LAnd:
53 case ZigClangBO_LOr:
54 case ZigClangBO_Assign:
55 case ZigClangBO_Comma:
56 case ZigClangBO_MulAssign:
57 case ZigClangBO_DivAssign:
58 case ZigClangBO_RemAssign:
59 case ZigClangBO_AddAssign:
60 case ZigClangBO_SubAssign:
61 case ZigClangBO_ShlAssign:
62 case ZigClangBO_ShrAssign:
63 case ZigClangBO_AndAssign:
64 case ZigClangBO_XorAssign:
65 case ZigClangBO_OrAssign:
66 break;
67 }
68}
69
70static_assert((clang::BinaryOperatorKind)ZigClangBO_Add == clang::BO_Add, "");
71static_assert((clang::BinaryOperatorKind)ZigClangBO_AddAssign == clang::BO_AddAssign, "");
72static_assert((clang::BinaryOperatorKind)ZigClangBO_And == clang::BO_And, "");
73static_assert((clang::BinaryOperatorKind)ZigClangBO_AndAssign == clang::BO_AndAssign, "");
74static_assert((clang::BinaryOperatorKind)ZigClangBO_Assign == clang::BO_Assign, "");
75static_assert((clang::BinaryOperatorKind)ZigClangBO_Cmp == clang::BO_Cmp, "");
76static_assert((clang::BinaryOperatorKind)ZigClangBO_Comma == clang::BO_Comma, "");
77static_assert((clang::BinaryOperatorKind)ZigClangBO_Div == clang::BO_Div, "");
78static_assert((clang::BinaryOperatorKind)ZigClangBO_DivAssign == clang::BO_DivAssign, "");
79static_assert((clang::BinaryOperatorKind)ZigClangBO_EQ == clang::BO_EQ, "");
80static_assert((clang::BinaryOperatorKind)ZigClangBO_GE == clang::BO_GE, "");
81static_assert((clang::BinaryOperatorKind)ZigClangBO_GT == clang::BO_GT, "");
82static_assert((clang::BinaryOperatorKind)ZigClangBO_LAnd == clang::BO_LAnd, "");
83static_assert((clang::BinaryOperatorKind)ZigClangBO_LE == clang::BO_LE, "");
84static_assert((clang::BinaryOperatorKind)ZigClangBO_LOr == clang::BO_LOr, "");
85static_assert((clang::BinaryOperatorKind)ZigClangBO_LT == clang::BO_LT, "");
86static_assert((clang::BinaryOperatorKind)ZigClangBO_Mul == clang::BO_Mul, "");
87static_assert((clang::BinaryOperatorKind)ZigClangBO_MulAssign == clang::BO_MulAssign, "");
88static_assert((clang::BinaryOperatorKind)ZigClangBO_NE == clang::BO_NE, "");
89static_assert((clang::BinaryOperatorKind)ZigClangBO_Or == clang::BO_Or, "");
90static_assert((clang::BinaryOperatorKind)ZigClangBO_OrAssign == clang::BO_OrAssign, "");
91static_assert((clang::BinaryOperatorKind)ZigClangBO_PtrMemD == clang::BO_PtrMemD, "");
92static_assert((clang::BinaryOperatorKind)ZigClangBO_PtrMemI == clang::BO_PtrMemI, "");
93static_assert((clang::BinaryOperatorKind)ZigClangBO_Rem == clang::BO_Rem, "");
94static_assert((clang::BinaryOperatorKind)ZigClangBO_RemAssign == clang::BO_RemAssign, "");
95static_assert((clang::BinaryOperatorKind)ZigClangBO_Shl == clang::BO_Shl, "");
96static_assert((clang::BinaryOperatorKind)ZigClangBO_ShlAssign == clang::BO_ShlAssign, "");
97static_assert((clang::BinaryOperatorKind)ZigClangBO_Shr == clang::BO_Shr, "");
98static_assert((clang::BinaryOperatorKind)ZigClangBO_ShrAssign == clang::BO_ShrAssign, "");
99static_assert((clang::BinaryOperatorKind)ZigClangBO_Sub == clang::BO_Sub, "");
100static_assert((clang::BinaryOperatorKind)ZigClangBO_SubAssign == clang::BO_SubAssign, "");
101static_assert((clang::BinaryOperatorKind)ZigClangBO_Xor == clang::BO_Xor, "");
102static_assert((clang::BinaryOperatorKind)ZigClangBO_XorAssign == clang::BO_XorAssign, "");
103
104// This function detects additions to the enum
105void zig2clang_UO(ZigClangUO op) {
106 switch (op) {
107 case ZigClangUO_AddrOf:
108 case ZigClangUO_Coawait:
109 case ZigClangUO_Deref:
110 case ZigClangUO_Extension:
111 case ZigClangUO_Imag:
112 case ZigClangUO_LNot:
113 case ZigClangUO_Minus:
114 case ZigClangUO_Not:
115 case ZigClangUO_Plus:
116 case ZigClangUO_PostDec:
117 case ZigClangUO_PostInc:
118 case ZigClangUO_PreDec:
119 case ZigClangUO_PreInc:
120 case ZigClangUO_Real:
121 break;
122 }
123}
124
125static_assert((clang::UnaryOperatorKind)ZigClangUO_AddrOf == clang::UO_AddrOf, "");
126static_assert((clang::UnaryOperatorKind)ZigClangUO_Coawait == clang::UO_Coawait, "");
127static_assert((clang::UnaryOperatorKind)ZigClangUO_Deref == clang::UO_Deref, "");
128static_assert((clang::UnaryOperatorKind)ZigClangUO_Extension == clang::UO_Extension, "");
129static_assert((clang::UnaryOperatorKind)ZigClangUO_Imag == clang::UO_Imag, "");
130static_assert((clang::UnaryOperatorKind)ZigClangUO_LNot == clang::UO_LNot, "");
131static_assert((clang::UnaryOperatorKind)ZigClangUO_Minus == clang::UO_Minus, "");
132static_assert((clang::UnaryOperatorKind)ZigClangUO_Not == clang::UO_Not, "");
133static_assert((clang::UnaryOperatorKind)ZigClangUO_Plus == clang::UO_Plus, "");
134static_assert((clang::UnaryOperatorKind)ZigClangUO_PostDec == clang::UO_PostDec, "");
135static_assert((clang::UnaryOperatorKind)ZigClangUO_PostInc == clang::UO_PostInc, "");
136static_assert((clang::UnaryOperatorKind)ZigClangUO_PreDec == clang::UO_PreDec, "");
137static_assert((clang::UnaryOperatorKind)ZigClangUO_PreInc == clang::UO_PreInc, "");
138static_assert((clang::UnaryOperatorKind)ZigClangUO_Real == clang::UO_Real, "");
139
140static_assert(sizeof(ZigClangSourceLocation) == sizeof(clang::SourceLocation), "");
141static ZigClangSourceLocation bitcast(clang::SourceLocation src) {
142 ZigClangSourceLocation dest;
143 memcpy(&dest, &src, sizeof(ZigClangSourceLocation));
144 return dest;
145}
146static clang::SourceLocation bitcast(ZigClangSourceLocation src) {
147 clang::SourceLocation dest;
148 memcpy(&dest, &src, sizeof(ZigClangSourceLocation));
149 return dest;
150}
151
152static_assert(sizeof(ZigClangQualType) == sizeof(clang::QualType), "");
153static ZigClangQualType bitcast(clang::QualType src) {
154 ZigClangQualType dest;
155 memcpy(&dest, &src, sizeof(ZigClangQualType));
156 return dest;
157}
158static clang::QualType bitcast(ZigClangQualType src) {
159 clang::QualType dest;
160 memcpy(&dest, &src, sizeof(ZigClangQualType));
161 return dest;
162}
163
164ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *self,
165 ZigClangSourceLocation Loc)
166{
167 return bitcast(reinterpret_cast<const clang::SourceManager *>(self)->getSpellingLoc(bitcast(Loc)));
168}
169
170const char *ZigClangSourceManager_getFilename(const ZigClangSourceManager *self,
171 ZigClangSourceLocation SpellingLoc)
172{
173 StringRef s = reinterpret_cast<const clang::SourceManager *>(self)->getFilename(bitcast(SpellingLoc));
174 return (const char *)s.bytes_begin();
175}
176
177unsigned ZigClangSourceManager_getSpellingLineNumber(const ZigClangSourceManager *self,
178 ZigClangSourceLocation Loc)
179{
180 return reinterpret_cast<const clang::SourceManager *>(self)->getSpellingLineNumber(bitcast(Loc));
181}
182
183unsigned ZigClangSourceManager_getSpellingColumnNumber(const ZigClangSourceManager *self,
184 ZigClangSourceLocation Loc)
185{
186 return reinterpret_cast<const clang::SourceManager *>(self)->getSpellingColumnNumber(bitcast(Loc));
187}
188
189const char* ZigClangSourceManager_getCharacterData(const ZigClangSourceManager *self,
190 ZigClangSourceLocation SL)
191{
192 return reinterpret_cast<const clang::SourceManager *>(self)->getCharacterData(bitcast(SL));
193}
194
195ZigClangQualType ZigClangASTContext_getPointerType(const ZigClangASTContext* self, ZigClangQualType T) {
196 return bitcast(reinterpret_cast<const clang::ASTContext *>(self)->getPointerType(bitcast(T)));
197}
198
199ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit *self) {
200 clang::ASTContext *result = &reinterpret_cast<clang::ASTUnit *>(self)->getASTContext();
201 return reinterpret_cast<ZigClangASTContext *>(result);
202}
203
204ZigClangSourceManager *ZigClangASTUnit_getSourceManager(ZigClangASTUnit *self) {
205 clang::SourceManager *result = &reinterpret_cast<clang::ASTUnit *>(self)->getSourceManager();
206 return reinterpret_cast<ZigClangSourceManager *>(result);
207}
208
209bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *self, void *context,
210 bool (*Fn)(void *context, const ZigClangDecl *decl))
211{
212 return reinterpret_cast<clang::ASTUnit *>(self)->visitLocalTopLevelDecls(context,
213 reinterpret_cast<bool (*)(void *, const clang::Decl *)>(Fn));
214}
src/zig_clang.h created+259
...@@ -0,0 +1,259 @@
1/*
2 * Copyright (c) 2019 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_ZIG_CLANG_H
9#define ZIG_ZIG_CLANG_H
10
11#ifdef __cplusplus
12#define ZIG_EXTERN_C extern "C"
13#else
14#define ZIG_EXTERN_C
15#endif
16
17// ATTENTION: If you modify this file, be sure to update the corresponding
18// extern function declarations in the self-hosted compiler.
19
20struct ZigClangSourceLocation {
21 unsigned ID;
22};
23
24struct ZigClangQualType {
25 void *ptr;
26};
27
28struct ZigClangAPValue;
29struct ZigClangASTContext;
30struct ZigClangASTUnit;
31struct ZigClangArraySubscriptExpr;
32struct ZigClangArrayType;
33struct ZigClangAttributedType;
34struct ZigClangBinaryOperator;
35struct ZigClangBreakStmt;
36struct ZigClangBuiltinType;
37struct ZigClangCStyleCastExpr;
38struct ZigClangCallExpr;
39struct ZigClangCaseStmt;
40struct ZigClangCompoundAssignOperator;
41struct ZigClangCompoundStmt;
42struct ZigClangConditionalOperator;
43struct ZigClangConstantArrayType;
44struct ZigClangContinueStmt;
45struct ZigClangDecayedType;
46struct ZigClangDecl;
47struct ZigClangDeclRefExpr;
48struct ZigClangDeclStmt;
49struct ZigClangDefaultStmt;
50struct ZigClangDiagnosticOptions;
51struct ZigClangDiagnosticsEngine;
52struct ZigClangDoStmt;
53struct ZigClangElaboratedType;
54struct ZigClangEnumConstantDecl;
55struct ZigClangEnumDecl;
56struct ZigClangEnumType;
57struct ZigClangExpr;
58struct ZigClangFieldDecl;
59struct ZigClangFileID;
60struct ZigClangForStmt;
61struct ZigClangFullSourceLoc;
62struct ZigClangFunctionDecl;
63struct ZigClangFunctionProtoType;
64struct ZigClangIfStmt;
65struct ZigClangImplicitCastExpr;
66struct ZigClangIncompleteArrayType;
67struct ZigClangIntegerLiteral;
68struct ZigClangMacroDefinitionRecord;
69struct ZigClangMemberExpr;
70struct ZigClangNamedDecl;
71struct ZigClangNone;
72struct ZigClangPCHContainerOperations;
73struct ZigClangParenExpr;
74struct ZigClangParenType;
75struct ZigClangParmVarDecl;
76struct ZigClangPointerType;
77struct ZigClangPreprocessedEntity;
78struct ZigClangRecordDecl;
79struct ZigClangRecordType;
80struct ZigClangReturnStmt;
81struct ZigClangSkipFunctionBodiesScope;
82struct ZigClangSourceManager;
83struct ZigClangSourceRange;
84struct ZigClangStmt;
85struct ZigClangStorageClass;
86struct ZigClangStringLiteral;
87struct ZigClangStringRef;
88struct ZigClangSwitchStmt;
89struct ZigClangType;
90struct ZigClangTypedefNameDecl;
91struct ZigClangTypedefType;
92struct ZigClangUnaryExprOrTypeTraitExpr;
93struct ZigClangUnaryOperator;
94struct ZigClangValueDecl;
95struct ZigClangVarDecl;
96struct ZigClangWhileStmt;
97
98enum ZigClangBO {
99 ZigClangBO_PtrMemD,
100 ZigClangBO_PtrMemI,
101 ZigClangBO_Mul,
102 ZigClangBO_Div,
103 ZigClangBO_Rem,
104 ZigClangBO_Add,
105 ZigClangBO_Sub,
106 ZigClangBO_Shl,
107 ZigClangBO_Shr,
108 ZigClangBO_Cmp,
109 ZigClangBO_LT,
110 ZigClangBO_GT,
111 ZigClangBO_LE,
112 ZigClangBO_GE,
113 ZigClangBO_EQ,
114 ZigClangBO_NE,
115 ZigClangBO_And,
116 ZigClangBO_Xor,
117 ZigClangBO_Or,
118 ZigClangBO_LAnd,
119 ZigClangBO_LOr,
120 ZigClangBO_Assign,
121 ZigClangBO_MulAssign,
122 ZigClangBO_DivAssign,
123 ZigClangBO_RemAssign,
124 ZigClangBO_AddAssign,
125 ZigClangBO_SubAssign,
126 ZigClangBO_ShlAssign,
127 ZigClangBO_ShrAssign,
128 ZigClangBO_AndAssign,
129 ZigClangBO_XorAssign,
130 ZigClangBO_OrAssign,
131 ZigClangBO_Comma,
132};
133
134enum ZigClangUO {
135 ZigClangUO_PostInc,
136 ZigClangUO_PostDec,
137 ZigClangUO_PreInc,
138 ZigClangUO_PreDec,
139 ZigClangUO_AddrOf,
140 ZigClangUO_Deref,
141 ZigClangUO_Plus,
142 ZigClangUO_Minus,
143 ZigClangUO_Not,
144 ZigClangUO_LNot,
145 ZigClangUO_Real,
146 ZigClangUO_Imag,
147 ZigClangUO_Extension,
148 ZigClangUO_Coawait,
149};
150
151//struct ZigClangCC_AAPCS;
152//struct ZigClangCC_AAPCS_VFP;
153//struct ZigClangCC_C;
154//struct ZigClangCC_IntelOclBicc;
155//struct ZigClangCC_OpenCLKernel;
156//struct ZigClangCC_PreserveAll;
157//struct ZigClangCC_PreserveMost;
158//struct ZigClangCC_SpirFunction;
159//struct ZigClangCC_Swift;
160//struct ZigClangCC_Win64;
161//struct ZigClangCC_X86FastCall;
162//struct ZigClangCC_X86Pascal;
163//struct ZigClangCC_X86RegCall;
164//struct ZigClangCC_X86StdCall;
165//struct ZigClangCC_X86ThisCall;
166//struct ZigClangCC_X86VectorCall;
167//struct ZigClangCC_X86_64SysV;
168
169//struct ZigClangCK_ARCConsumeObject;
170//struct ZigClangCK_ARCExtendBlockObject;
171//struct ZigClangCK_ARCProduceObject;
172//struct ZigClangCK_ARCReclaimReturnedObject;
173//struct ZigClangCK_AddressSpaceConversion;
174//struct ZigClangCK_AnyPointerToBlockPointerCast;
175//struct ZigClangCK_ArrayToPointerDecay;
176//struct ZigClangCK_AtomicToNonAtomic;
177//struct ZigClangCK_BaseToDerived;
178//struct ZigClangCK_BaseToDerivedMemberPointer;
179//struct ZigClangCK_BitCast;
180//struct ZigClangCK_BlockPointerToObjCPointerCast;
181//struct ZigClangCK_BooleanToSignedIntegral;
182//struct ZigClangCK_BuiltinFnToFnPtr;
183//struct ZigClangCK_CPointerToObjCPointerCast;
184//struct ZigClangCK_ConstructorConversion;
185//struct ZigClangCK_CopyAndAutoreleaseBlockObject;
186//struct ZigClangCK_Dependent;
187//struct ZigClangCK_DerivedToBase;
188//struct ZigClangCK_DerivedToBaseMemberPointer;
189//struct ZigClangCK_Dynamic;
190//struct ZigClangCK_FloatingCast;
191//struct ZigClangCK_FloatingComplexCast;
192//struct ZigClangCK_FloatingComplexToBoolean;
193//struct ZigClangCK_FloatingComplexToIntegralComplex;
194//struct ZigClangCK_FloatingComplexToReal;
195//struct ZigClangCK_FloatingRealToComplex;
196//struct ZigClangCK_FloatingToBoolean;
197//struct ZigClangCK_FloatingToIntegral;
198//struct ZigClangCK_FunctionToPointerDecay;
199//struct ZigClangCK_IntToOCLSampler;
200//struct ZigClangCK_IntegralCast;
201//struct ZigClangCK_IntegralComplexCast;
202//struct ZigClangCK_IntegralComplexToBoolean;
203//struct ZigClangCK_IntegralComplexToFloatingComplex;
204//struct ZigClangCK_IntegralComplexToReal;
205//struct ZigClangCK_IntegralRealToComplex;
206//struct ZigClangCK_IntegralToBoolean;
207//struct ZigClangCK_IntegralToFloating;
208//struct ZigClangCK_IntegralToPointer;
209//struct ZigClangCK_LValueBitCast;
210//struct ZigClangCK_LValueToRValue;
211//struct ZigClangCK_MemberPointerToBoolean;
212//struct ZigClangCK_NoOp;
213//struct ZigClangCK_NonAtomicToAtomic;
214//struct ZigClangCK_NullToMemberPointer;
215//struct ZigClangCK_NullToPointer;
216//struct ZigClangCK_ObjCObjectLValueCast;
217//struct ZigClangCK_PointerToBoolean;
218//struct ZigClangCK_PointerToIntegral;
219//struct ZigClangCK_ReinterpretMemberPointer;
220//struct ZigClangCK_ToUnion;
221//struct ZigClangCK_ToVoid;
222//struct ZigClangCK_UncheckedDerivedToBase;
223//struct ZigClangCK_UserDefinedConversion;
224//struct ZigClangCK_VectorSplat;
225//struct ZigClangCK_ZeroToOCLEvent;
226//struct ZigClangCK_ZeroToOCLQueue;
227
228//struct ZigClangETK_Class;
229//struct ZigClangETK_Enum;
230//struct ZigClangETK_Interface;
231//struct ZigClangETK_None;
232//struct ZigClangETK_Struct;
233//struct ZigClangETK_Typename;
234//struct ZigClangETK_Union;
235
236//struct ZigClangSC_None;
237//struct ZigClangSC_PrivateExtern;
238//struct ZigClangSC_Static;
239
240//struct ZigClangTU_Complete;
241
242ZIG_EXTERN_C ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *,
243 ZigClangSourceLocation Loc);
244ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const ZigClangSourceManager *,
245 ZigClangSourceLocation SpellingLoc);
246ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingLineNumber(const ZigClangSourceManager *,
247 ZigClangSourceLocation Loc);
248ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingColumnNumber(const ZigClangSourceManager *,
249 ZigClangSourceLocation Loc);
250ZIG_EXTERN_C const char* ZigClangSourceManager_getCharacterData(const ZigClangSourceManager *,
251 ZigClangSourceLocation SL);
252
253ZIG_EXTERN_C ZigClangQualType ZigClangASTContext_getPointerType(const ZigClangASTContext*, ZigClangQualType T);
254
255ZIG_EXTERN_C ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit *);
256ZIG_EXTERN_C ZigClangSourceManager *ZigClangASTUnit_getSourceManager(ZigClangASTUnit *);
257ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *, void *context,
258 bool (*Fn)(void *context, const ZigClangDecl *decl));
259#endif
src/zig_llvm.cpp+14-1
...@@ -263,6 +263,19 @@ ZigLLVMDIType *ZigLLVMCreateDebugBasicType(ZigLLVMDIBuilder *dibuilder, const ch...@@ -263,6 +263,19 @@ ZigLLVMDIType *ZigLLVMCreateDebugBasicType(ZigLLVMDIBuilder *dibuilder, const ch
263 return reinterpret_cast<ZigLLVMDIType*>(di_type);263 return reinterpret_cast<ZigLLVMDIType*>(di_type);
264}264}
265265
266struct ZigLLVMDIType *ZigLLVMDIBuilderCreateVectorType(struct ZigLLVMDIBuilder *dibuilder,
267 uint64_t SizeInBits, uint32_t AlignInBits, struct ZigLLVMDIType *Ty, uint32_t elem_count)
268{
269 SmallVector<Metadata *, 1> subrange;
270 subrange.push_back(reinterpret_cast<DIBuilder*>(dibuilder)->getOrCreateSubrange(0, elem_count));
271 DIType *di_type = reinterpret_cast<DIBuilder*>(dibuilder)->createVectorType(
272 SizeInBits,
273 AlignInBits,
274 reinterpret_cast<DIType*>(Ty),
275 reinterpret_cast<DIBuilder*>(dibuilder)->getOrCreateArray(subrange));
276 return reinterpret_cast<ZigLLVMDIType*>(di_type);
277}
278
266ZigLLVMDIType *ZigLLVMCreateDebugArrayType(ZigLLVMDIBuilder *dibuilder, uint64_t size_in_bits,279ZigLLVMDIType *ZigLLVMCreateDebugArrayType(ZigLLVMDIBuilder *dibuilder, uint64_t size_in_bits,
267 uint64_t align_in_bits, ZigLLVMDIType *elem_type, int elem_count)280 uint64_t align_in_bits, ZigLLVMDIType *elem_type, int elem_count)
268{281{
...@@ -605,7 +618,7 @@ ZigLLVMDISubprogram *ZigLLVMCreateFunction(ZigLLVMDIBuilder *dibuilder, ZigLLVMD...@@ -605,7 +618,7 @@ ZigLLVMDISubprogram *ZigLLVMCreateFunction(ZigLLVMDIBuilder *dibuilder, ZigLLVMD
605 reinterpret_cast<DIFile*>(file),618 reinterpret_cast<DIFile*>(file),
606 lineno,619 lineno,
607 di_sub_type,620 di_sub_type,
608 is_local_to_unit, is_definition, scope_line, DINode::FlagZero, is_optimized,621 is_local_to_unit, is_definition, scope_line, DINode::FlagStaticMember, is_optimized,
609 nullptr,622 nullptr,
610 reinterpret_cast<DISubprogram *>(decl_subprogram));623 reinterpret_cast<DISubprogram *>(decl_subprogram));
611 return reinterpret_cast<ZigLLVMDISubprogram*>(result);624 return reinterpret_cast<ZigLLVMDISubprogram*>(result);
src/zig_llvm.h+3
...@@ -191,6 +191,9 @@ ZIG_EXTERN_C struct ZigLLVMDISubprogram *ZigLLVMCreateFunction(struct ZigLLVMDIB...@@ -191,6 +191,9 @@ ZIG_EXTERN_C struct ZigLLVMDISubprogram *ZigLLVMCreateFunction(struct ZigLLVMDIB
191 unsigned lineno, struct ZigLLVMDIType *fn_di_type, bool is_local_to_unit, bool is_definition,191 unsigned lineno, struct ZigLLVMDIType *fn_di_type, bool is_local_to_unit, bool is_definition,
192 unsigned scope_line, unsigned flags, bool is_optimized, struct ZigLLVMDISubprogram *decl_subprogram);192 unsigned scope_line, unsigned flags, bool is_optimized, struct ZigLLVMDISubprogram *decl_subprogram);
193193
194ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMDIBuilderCreateVectorType(struct ZigLLVMDIBuilder *dibuilder,
195 uint64_t SizeInBits, uint32_t AlignInBits, struct ZigLLVMDIType *Ty, uint32_t elem_count);
196
194ZIG_EXTERN_C void ZigLLVMFnSetSubprogram(LLVMValueRef fn, struct ZigLLVMDISubprogram *subprogram);197ZIG_EXTERN_C void ZigLLVMFnSetSubprogram(LLVMValueRef fn, struct ZigLLVMDISubprogram *subprogram);
195198
196ZIG_EXTERN_C void ZigLLVMDIBuilderFinalize(struct ZigLLVMDIBuilder *dibuilder);199ZIG_EXTERN_C void ZigLLVMDIBuilderFinalize(struct ZigLLVMDIBuilder *dibuilder);
std/array_list.zig+63-52
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1const std = @import("index.zig");1const std = @import("index.zig");
2const debug = std.debug;2const debug = std.debug;
3const assert = debug.assert;3const assert = debug.assert;
4const assertError = debug.assertError;4const testing = std.testing;
5const mem = std.mem;5const mem = std.mem;
6const Allocator = mem.Allocator;6const Allocator = mem.Allocator;
77
...@@ -212,8 +212,8 @@ test "std.ArrayList.init" {...@@ -212,8 +212,8 @@ test "std.ArrayList.init" {
212 var list = ArrayList(i32).init(allocator);212 var list = ArrayList(i32).init(allocator);
213 defer list.deinit();213 defer list.deinit();
214214
215 assert(list.count() == 0);215 testing.expect(list.count() == 0);
216 assert(list.capacity() == 0);216 testing.expect(list.capacity() == 0);
217}217}
218218
219test "std.ArrayList.basic" {219test "std.ArrayList.basic" {
...@@ -224,7 +224,7 @@ test "std.ArrayList.basic" {...@@ -224,7 +224,7 @@ test "std.ArrayList.basic" {
224 defer list.deinit();224 defer list.deinit();
225225
226 // setting on empty list is out of bounds226 // setting on empty list is out of bounds
227 assertError(list.setOrError(0, 1), error.OutOfBounds);227 testing.expectError(error.OutOfBounds, list.setOrError(0, 1));
228228
229 {229 {
230 var i: usize = 0;230 var i: usize = 0;
...@@ -236,44 +236,44 @@ test "std.ArrayList.basic" {...@@ -236,44 +236,44 @@ test "std.ArrayList.basic" {
236 {236 {
237 var i: usize = 0;237 var i: usize = 0;
238 while (i < 10) : (i += 1) {238 while (i < 10) : (i += 1) {
239 assert(list.items[i] == @intCast(i32, i + 1));239 testing.expect(list.items[i] == @intCast(i32, i + 1));
240 }240 }
241 }241 }
242242
243 for (list.toSlice()) |v, i| {243 for (list.toSlice()) |v, i| {
244 assert(v == @intCast(i32, i + 1));244 testing.expect(v == @intCast(i32, i + 1));
245 }245 }
246246
247 for (list.toSliceConst()) |v, i| {247 for (list.toSliceConst()) |v, i| {
248 assert(v == @intCast(i32, i + 1));248 testing.expect(v == @intCast(i32, i + 1));
249 }249 }
250250
251 assert(list.pop() == 10);251 testing.expect(list.pop() == 10);
252 assert(list.len == 9);252 testing.expect(list.len == 9);
253253
254 list.appendSlice([]const i32{254 list.appendSlice([]const i32{
255 1,255 1,
256 2,256 2,
257 3,257 3,
258 }) catch unreachable;258 }) catch unreachable;
259 assert(list.len == 12);259 testing.expect(list.len == 12);
260 assert(list.pop() == 3);260 testing.expect(list.pop() == 3);
261 assert(list.pop() == 2);261 testing.expect(list.pop() == 2);
262 assert(list.pop() == 1);262 testing.expect(list.pop() == 1);
263 assert(list.len == 9);263 testing.expect(list.len == 9);
264264
265 list.appendSlice([]const i32{}) catch unreachable;265 list.appendSlice([]const i32{}) catch unreachable;
266 assert(list.len == 9);266 testing.expect(list.len == 9);
267267
268 // can only set on indices < self.len268 // can only set on indices < self.len
269 list.set(7, 33);269 list.set(7, 33);
270 list.set(8, 42);270 list.set(8, 42);
271271
272 assertError(list.setOrError(9, 99), error.OutOfBounds);272 testing.expectError(error.OutOfBounds, list.setOrError(9, 99));
273 assertError(list.setOrError(10, 123), error.OutOfBounds);273 testing.expectError(error.OutOfBounds, list.setOrError(10, 123));
274274
275 assert(list.pop() == 42);275 testing.expect(list.pop() == 42);
276 assert(list.pop() == 33);276 testing.expect(list.pop() == 33);
277}277}
278278
279test "std.ArrayList.swapRemove" {279test "std.ArrayList.swapRemove" {
...@@ -289,18 +289,18 @@ test "std.ArrayList.swapRemove" {...@@ -289,18 +289,18 @@ test "std.ArrayList.swapRemove" {
289 try list.append(7);289 try list.append(7);
290290
291 //remove from middle291 //remove from middle
292 assert(list.swapRemove(3) == 4);292 testing.expect(list.swapRemove(3) == 4);
293 assert(list.at(3) == 7);293 testing.expect(list.at(3) == 7);
294 assert(list.len == 6);294 testing.expect(list.len == 6);
295295
296 //remove from end296 //remove from end
297 assert(list.swapRemove(5) == 6);297 testing.expect(list.swapRemove(5) == 6);
298 assert(list.len == 5);298 testing.expect(list.len == 5);
299299
300 //remove from front300 //remove from front
301 assert(list.swapRemove(0) == 1);301 testing.expect(list.swapRemove(0) == 1);
302 assert(list.at(0) == 5);302 testing.expect(list.at(0) == 5);
303 assert(list.len == 4);303 testing.expect(list.len == 4);
304}304}
305305
306test "std.ArrayList.swapRemoveOrError" {306test "std.ArrayList.swapRemoveOrError" {
...@@ -308,27 +308,27 @@ test "std.ArrayList.swapRemoveOrError" {...@@ -308,27 +308,27 @@ test "std.ArrayList.swapRemoveOrError" {
308 defer list.deinit();308 defer list.deinit();
309309
310 // Test just after initialization310 // Test just after initialization
311 assertError(list.swapRemoveOrError(0), error.OutOfBounds);311 testing.expectError(error.OutOfBounds, list.swapRemoveOrError(0));
312312
313 // Test after adding one item and remote it313 // Test after adding one item and remote it
314 try list.append(1);314 try list.append(1);
315 assert((try list.swapRemoveOrError(0)) == 1);315 testing.expect((try list.swapRemoveOrError(0)) == 1);
316 assertError(list.swapRemoveOrError(0), error.OutOfBounds);316 testing.expectError(error.OutOfBounds, list.swapRemoveOrError(0));
317317
318 // Test after adding two items and remote both318 // Test after adding two items and remote both
319 try list.append(1);319 try list.append(1);
320 try list.append(2);320 try list.append(2);
321 assert((try list.swapRemoveOrError(1)) == 2);321 testing.expect((try list.swapRemoveOrError(1)) == 2);
322 assert((try list.swapRemoveOrError(0)) == 1);322 testing.expect((try list.swapRemoveOrError(0)) == 1);
323 assertError(list.swapRemoveOrError(0), error.OutOfBounds);323 testing.expectError(error.OutOfBounds, list.swapRemoveOrError(0));
324324
325 // Test out of bounds with one item325 // Test out of bounds with one item
326 try list.append(1);326 try list.append(1);
327 assertError(list.swapRemoveOrError(1), error.OutOfBounds);327 testing.expectError(error.OutOfBounds, list.swapRemoveOrError(1));
328328
329 // Test out of bounds with two items329 // Test out of bounds with two items
330 try list.append(2);330 try list.append(2);
331 assertError(list.swapRemoveOrError(2), error.OutOfBounds);331 testing.expectError(error.OutOfBounds, list.swapRemoveOrError(2));
332}332}
333333
334test "std.ArrayList.iterator" {334test "std.ArrayList.iterator" {
...@@ -342,22 +342,22 @@ test "std.ArrayList.iterator" {...@@ -342,22 +342,22 @@ test "std.ArrayList.iterator" {
342 var count: i32 = 0;342 var count: i32 = 0;
343 var it = list.iterator();343 var it = list.iterator();
344 while (it.next()) |next| {344 while (it.next()) |next| {
345 assert(next == count + 1);345 testing.expect(next == count + 1);
346 count += 1;346 count += 1;
347 }347 }
348348
349 assert(count == 3);349 testing.expect(count == 3);
350 assert(it.next() == null);350 testing.expect(it.next() == null);
351 it.reset();351 it.reset();
352 count = 0;352 count = 0;
353 while (it.next()) |next| {353 while (it.next()) |next| {
354 assert(next == count + 1);354 testing.expect(next == count + 1);
355 count += 1;355 count += 1;
356 if (count == 2) break;356 if (count == 2) break;
357 }357 }
358358
359 it.reset();359 it.reset();
360 assert(it.next().? == 1);360 testing.expect(it.next().? == 1);
361}361}
362362
363test "std.ArrayList.insert" {363test "std.ArrayList.insert" {
...@@ -368,10 +368,10 @@ test "std.ArrayList.insert" {...@@ -368,10 +368,10 @@ test "std.ArrayList.insert" {
368 try list.append(2);368 try list.append(2);
369 try list.append(3);369 try list.append(3);
370 try list.insert(0, 5);370 try list.insert(0, 5);
371 assert(list.items[0] == 5);371 testing.expect(list.items[0] == 5);
372 assert(list.items[1] == 1);372 testing.expect(list.items[1] == 1);
373 assert(list.items[2] == 2);373 testing.expect(list.items[2] == 2);
374 assert(list.items[3] == 3);374 testing.expect(list.items[3] == 3);
375}375}
376376
377test "std.ArrayList.insertSlice" {377test "std.ArrayList.insertSlice" {
...@@ -386,15 +386,26 @@ test "std.ArrayList.insertSlice" {...@@ -386,15 +386,26 @@ test "std.ArrayList.insertSlice" {
386 9,386 9,
387 8,387 8,
388 });388 });
389 assert(list.items[0] == 1);389 testing.expect(list.items[0] == 1);
390 assert(list.items[1] == 9);390 testing.expect(list.items[1] == 9);
391 assert(list.items[2] == 8);391 testing.expect(list.items[2] == 8);
392 assert(list.items[3] == 2);392 testing.expect(list.items[3] == 2);
393 assert(list.items[4] == 3);393 testing.expect(list.items[4] == 3);
394 assert(list.items[5] == 4);394 testing.expect(list.items[5] == 4);
395395
396 const items = []const i32{1};396 const items = []const i32{1};
397 try list.insertSlice(0, items[0..0]);397 try list.insertSlice(0, items[0..0]);
398 assert(list.len == 6);398 testing.expect(list.len == 6);
399 assert(list.items[0] == 1);399 testing.expect(list.items[0] == 1);
400}
401
402const Item = struct {
403 integer: i32,
404 sub_items: ArrayList(Item),
405};
406
407test "std.ArrayList: ArrayList(T) of struct T" {
408 var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(debug.global_allocator) };
409 try root.sub_items.append( Item{ .integer = 42, .sub_items = ArrayList(Item).init(debug.global_allocator) } );
410 testing.expect(root.sub_items.items[0].integer == 42);
400}411}
std/atomic/queue.zig+42-24
...@@ -3,6 +3,7 @@ const builtin = @import("builtin");...@@ -3,6 +3,7 @@ const builtin = @import("builtin");
3const AtomicOrder = builtin.AtomicOrder;3const AtomicOrder = builtin.AtomicOrder;
4const AtomicRmwOp = builtin.AtomicRmwOp;4const AtomicRmwOp = builtin.AtomicRmwOp;
5const assert = std.debug.assert;5const assert = std.debug.assert;
6const expect = std.testing.expect;
67
7/// Many producer, many consumer, non-allocating, thread-safe.8/// Many producer, many consumer, non-allocating, thread-safe.
8/// Uses a mutex to protect access.9/// Uses a mutex to protect access.
...@@ -170,20 +171,36 @@ test "std.atomic.Queue" {...@@ -170,20 +171,36 @@ test "std.atomic.Queue" {
170 .get_count = 0,171 .get_count = 0,
171 };172 };
172173
173 var putters: [put_thread_count]*std.os.Thread = undefined;174 if (builtin.single_threaded) {
174 for (putters) |*t| {175 {
175 t.* = try std.os.spawnThread(&context, startPuts);176 var i: usize = 0;
176 }177 while (i < put_thread_count) : (i += 1) {
177 var getters: [put_thread_count]*std.os.Thread = undefined;178 expect(startPuts(&context) == 0);
178 for (getters) |*t| {179 }
179 t.* = try std.os.spawnThread(&context, startGets);180 }
180 }181 context.puts_done = 1;
182 {
183 var i: usize = 0;
184 while (i < put_thread_count) : (i += 1) {
185 expect(startGets(&context) == 0);
186 }
187 }
188 } else {
189 var putters: [put_thread_count]*std.os.Thread = undefined;
190 for (putters) |*t| {
191 t.* = try std.os.spawnThread(&context, startPuts);
192 }
193 var getters: [put_thread_count]*std.os.Thread = undefined;
194 for (getters) |*t| {
195 t.* = try std.os.spawnThread(&context, startGets);
196 }
181197
182 for (putters) |t|198 for (putters) |t|
183 t.wait();199 t.wait();
184 _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);200 _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
185 for (getters) |t|201 for (getters) |t|
186 t.wait();202 t.wait();
203 }
187204
188 if (context.put_sum != context.get_sum) {205 if (context.put_sum != context.get_sum) {
189 std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum);206 std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum);
...@@ -205,11 +222,12 @@ fn startPuts(ctx: *Context) u8 {...@@ -205,11 +222,12 @@ fn startPuts(ctx: *Context) u8 {
205 while (put_count != 0) : (put_count -= 1) {222 while (put_count != 0) : (put_count -= 1) {
206 std.os.time.sleep(1); // let the os scheduler be our fuzz223 std.os.time.sleep(1); // let the os scheduler be our fuzz
207 const x = @bitCast(i32, r.random.scalar(u32));224 const x = @bitCast(i32, r.random.scalar(u32));
208 const node = ctx.allocator.create(Queue(i32).Node{225 const node = ctx.allocator.create(Queue(i32).Node) catch unreachable;
226 node.* = Queue(i32).Node{
209 .prev = undefined,227 .prev = undefined,
210 .next = undefined,228 .next = undefined,
211 .data = x,229 .data = x,
212 }) catch unreachable;230 };
213 ctx.queue.put(node);231 ctx.queue.put(node);
214 _ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst);232 _ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst);
215 }233 }
...@@ -247,7 +265,7 @@ test "std.atomic.Queue single-threaded" {...@@ -247,7 +265,7 @@ test "std.atomic.Queue single-threaded" {
247 };265 };
248 queue.put(&node_1);266 queue.put(&node_1);
249267
250 assert(queue.get().?.data == 0);268 expect(queue.get().?.data == 0);
251269
252 var node_2 = Queue(i32).Node{270 var node_2 = Queue(i32).Node{
253 .data = 2,271 .data = 2,
...@@ -263,9 +281,9 @@ test "std.atomic.Queue single-threaded" {...@@ -263,9 +281,9 @@ test "std.atomic.Queue single-threaded" {
263 };281 };
264 queue.put(&node_3);282 queue.put(&node_3);
265283
266 assert(queue.get().?.data == 1);284 expect(queue.get().?.data == 1);
267285
268 assert(queue.get().?.data == 2);286 expect(queue.get().?.data == 2);
269287
270 var node_4 = Queue(i32).Node{288 var node_4 = Queue(i32).Node{
271 .data = 4,289 .data = 4,
...@@ -274,12 +292,12 @@ test "std.atomic.Queue single-threaded" {...@@ -274,12 +292,12 @@ test "std.atomic.Queue single-threaded" {
274 };292 };
275 queue.put(&node_4);293 queue.put(&node_4);
276294
277 assert(queue.get().?.data == 3);295 expect(queue.get().?.data == 3);
278 node_3.next = null;296 node_3.next = null;
279297
280 assert(queue.get().?.data == 4);298 expect(queue.get().?.data == 4);
281299
282 assert(queue.get() == null);300 expect(queue.get() == null);
283}301}
284302
285test "std.atomic.Queue dump" {303test "std.atomic.Queue dump" {
...@@ -294,7 +312,7 @@ test "std.atomic.Queue dump" {...@@ -294,7 +312,7 @@ test "std.atomic.Queue dump" {
294 // Test empty stream312 // Test empty stream
295 sos.reset();313 sos.reset();
296 try queue.dumpToStream(SliceOutStream.Error, &sos.stream);314 try queue.dumpToStream(SliceOutStream.Error, &sos.stream);
297 assert(mem.eql(u8, buffer[0..sos.pos],315 expect(mem.eql(u8, buffer[0..sos.pos],
298 \\head: (null)316 \\head: (null)
299 \\tail: (null)317 \\tail: (null)
300 \\318 \\
...@@ -318,7 +336,7 @@ test "std.atomic.Queue dump" {...@@ -318,7 +336,7 @@ test "std.atomic.Queue dump" {
318 \\ (null)336 \\ (null)
319 \\337 \\
320 , @ptrToInt(queue.head), @ptrToInt(queue.tail));338 , @ptrToInt(queue.head), @ptrToInt(queue.tail));
321 assert(mem.eql(u8, buffer[0..sos.pos], expected));339 expect(mem.eql(u8, buffer[0..sos.pos], expected));
322340
323 // Test a stream with two elements341 // Test a stream with two elements
324 var node_1 = Queue(i32).Node{342 var node_1 = Queue(i32).Node{
...@@ -339,5 +357,5 @@ test "std.atomic.Queue dump" {...@@ -339,5 +357,5 @@ test "std.atomic.Queue dump" {
339 \\ (null)357 \\ (null)
340 \\358 \\
341 , @ptrToInt(queue.head), @ptrToInt(queue.head.?.next), @ptrToInt(queue.tail));359 , @ptrToInt(queue.head), @ptrToInt(queue.head.?.next), @ptrToInt(queue.tail));
342 assert(mem.eql(u8, buffer[0..sos.pos], expected));360 expect(mem.eql(u8, buffer[0..sos.pos], expected));
343}361}
std/atomic/stack.zig+60-28
...@@ -1,13 +1,17 @@...@@ -1,13 +1,17 @@
1const assert = std.debug.assert;1const assert = std.debug.assert;
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const AtomicOrder = builtin.AtomicOrder;3const AtomicOrder = builtin.AtomicOrder;
4const expect = std.testing.expect;
45
5/// Many reader, many writer, non-allocating, thread-safe6/// Many reader, many writer, non-allocating, thread-safe
6/// Uses a spinlock to protect push() and pop()7/// Uses a spinlock to protect push() and pop()
8/// When building in single threaded mode, this is a simple linked list.
7pub fn Stack(comptime T: type) type {9pub fn Stack(comptime T: type) type {
8 return struct {10 return struct {
9 root: ?*Node,11 root: ?*Node,
10 lock: u8,12 lock: @typeOf(lock_init),
13
14 const lock_init = if (builtin.single_threaded) {} else u8(0);
1115
12 pub const Self = @This();16 pub const Self = @This();
1317
...@@ -19,7 +23,7 @@ pub fn Stack(comptime T: type) type {...@@ -19,7 +23,7 @@ pub fn Stack(comptime T: type) type {
19 pub fn init() Self {23 pub fn init() Self {
20 return Self{24 return Self{
21 .root = null,25 .root = null,
22 .lock = 0,26 .lock = lock_init,
23 };27 };
24 }28 }
2529
...@@ -31,20 +35,31 @@ pub fn Stack(comptime T: type) type {...@@ -31,20 +35,31 @@ pub fn Stack(comptime T: type) type {
31 }35 }
3236
33 pub fn push(self: *Self, node: *Node) void {37 pub fn push(self: *Self, node: *Node) void {
34 while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}38 if (builtin.single_threaded) {
35 defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);39 node.next = self.root;
3640 self.root = node;
37 node.next = self.root;41 } else {
38 self.root = node;42 while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
43 defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
44
45 node.next = self.root;
46 self.root = node;
47 }
39 }48 }
4049
41 pub fn pop(self: *Self) ?*Node {50 pub fn pop(self: *Self) ?*Node {
42 while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}51 if (builtin.single_threaded) {
43 defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);52 const root = self.root orelse return null;
4453 self.root = root.next;
45 const root = self.root orelse return null;54 return root;
46 self.root = root.next;55 } else {
47 return root;56 while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
57 defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
58
59 const root = self.root orelse return null;
60 self.root = root.next;
61 return root;
62 }
48 }63 }
4964
50 pub fn isEmpty(self: *Self) bool {65 pub fn isEmpty(self: *Self) bool {
...@@ -90,20 +105,36 @@ test "std.atomic.stack" {...@@ -90,20 +105,36 @@ test "std.atomic.stack" {
90 .get_count = 0,105 .get_count = 0,
91 };106 };
92107
93 var putters: [put_thread_count]*std.os.Thread = undefined;108 if (builtin.single_threaded) {
94 for (putters) |*t| {109 {
95 t.* = try std.os.spawnThread(&context, startPuts);110 var i: usize = 0;
96 }111 while (i < put_thread_count) : (i += 1) {
97 var getters: [put_thread_count]*std.os.Thread = undefined;112 expect(startPuts(&context) == 0);
98 for (getters) |*t| {113 }
99 t.* = try std.os.spawnThread(&context, startGets);114 }
100 }115 context.puts_done = 1;
116 {
117 var i: usize = 0;
118 while (i < put_thread_count) : (i += 1) {
119 expect(startGets(&context) == 0);
120 }
121 }
122 } else {
123 var putters: [put_thread_count]*std.os.Thread = undefined;
124 for (putters) |*t| {
125 t.* = try std.os.spawnThread(&context, startPuts);
126 }
127 var getters: [put_thread_count]*std.os.Thread = undefined;
128 for (getters) |*t| {
129 t.* = try std.os.spawnThread(&context, startGets);
130 }
101131
102 for (putters) |t|132 for (putters) |t|
103 t.wait();133 t.wait();
104 _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);134 _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
105 for (getters) |t|135 for (getters) |t|
106 t.wait();136 t.wait();
137 }
107138
108 if (context.put_sum != context.get_sum) {139 if (context.put_sum != context.get_sum) {
109 std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum);140 std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum);
...@@ -125,10 +156,11 @@ fn startPuts(ctx: *Context) u8 {...@@ -125,10 +156,11 @@ fn startPuts(ctx: *Context) u8 {
125 while (put_count != 0) : (put_count -= 1) {156 while (put_count != 0) : (put_count -= 1) {
126 std.os.time.sleep(1); // let the os scheduler be our fuzz157 std.os.time.sleep(1); // let the os scheduler be our fuzz
127 const x = @bitCast(i32, r.random.scalar(u32));158 const x = @bitCast(i32, r.random.scalar(u32));
128 const node = ctx.allocator.create(Stack(i32).Node{159 const node = ctx.allocator.create(Stack(i32).Node) catch unreachable;
160 node.* = Stack(i32).Node{
129 .next = undefined,161 .next = undefined,
130 .data = x,162 .data = x,
131 }) catch unreachable;163 };
132 ctx.stack.push(node);164 ctx.stack.push(node);
133 _ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst);165 _ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst);
134 }166 }
std/base64.zig+7-6
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const std = @import("index.zig");1const std = @import("index.zig");
2const assert = std.debug.assert;2const assert = std.debug.assert;
3const testing = std.testing;
3const mem = std.mem;4const mem = std.mem;
45
5pub const standard_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";6pub const standard_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
...@@ -394,7 +395,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void...@@ -394,7 +395,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void
394 var buffer: [0x100]u8 = undefined;395 var buffer: [0x100]u8 = undefined;
395 var encoded = buffer[0..Base64Encoder.calcSize(expected_decoded.len)];396 var encoded = buffer[0..Base64Encoder.calcSize(expected_decoded.len)];
396 standard_encoder.encode(encoded, expected_decoded);397 standard_encoder.encode(encoded, expected_decoded);
397 assert(mem.eql(u8, encoded, expected_encoded));398 testing.expectEqualSlices(u8, expected_encoded, encoded);
398 }399 }
399400
400 // Base64Decoder401 // Base64Decoder
...@@ -402,7 +403,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void...@@ -402,7 +403,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void
402 var buffer: [0x100]u8 = undefined;403 var buffer: [0x100]u8 = undefined;
403 var decoded = buffer[0..try standard_decoder.calcSize(expected_encoded)];404 var decoded = buffer[0..try standard_decoder.calcSize(expected_encoded)];
404 try standard_decoder.decode(decoded, expected_encoded);405 try standard_decoder.decode(decoded, expected_encoded);
405 assert(mem.eql(u8, decoded, expected_decoded));406 testing.expectEqualSlices(u8, expected_decoded, decoded);
406 }407 }
407408
408 // Base64DecoderWithIgnore409 // Base64DecoderWithIgnore
...@@ -411,8 +412,8 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void...@@ -411,8 +412,8 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void
411 var buffer: [0x100]u8 = undefined;412 var buffer: [0x100]u8 = undefined;
412 var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(expected_encoded.len)];413 var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(expected_encoded.len)];
413 var written = try standard_decoder_ignore_nothing.decode(decoded, expected_encoded);414 var written = try standard_decoder_ignore_nothing.decode(decoded, expected_encoded);
414 assert(written <= decoded.len);415 testing.expect(written <= decoded.len);
415 assert(mem.eql(u8, decoded[0..written], expected_decoded));416 testing.expectEqualSlices(u8, expected_decoded, decoded[0..written]);
416 }417 }
417418
418 // Base64DecoderUnsafe419 // Base64DecoderUnsafe
...@@ -420,7 +421,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void...@@ -420,7 +421,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void
420 var buffer: [0x100]u8 = undefined;421 var buffer: [0x100]u8 = undefined;
421 var decoded = buffer[0..standard_decoder_unsafe.calcSize(expected_encoded)];422 var decoded = buffer[0..standard_decoder_unsafe.calcSize(expected_encoded)];
422 standard_decoder_unsafe.decode(decoded, expected_encoded);423 standard_decoder_unsafe.decode(decoded, expected_encoded);
423 assert(mem.eql(u8, decoded, expected_decoded));424 testing.expectEqualSlices(u8, expected_decoded, decoded);
424 }425 }
425}426}
426427
...@@ -429,7 +430,7 @@ fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !voi...@@ -429,7 +430,7 @@ fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !voi
429 var buffer: [0x100]u8 = undefined;430 var buffer: [0x100]u8 = undefined;
430 var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(encoded.len)];431 var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(encoded.len)];
431 var written = try standard_decoder_ignore_space.decode(decoded, encoded);432 var written = try standard_decoder_ignore_space.decode(decoded, encoded);
432 assert(mem.eql(u8, decoded[0..written], expected_decoded));433 testing.expectEqualSlices(u8, expected_decoded, decoded[0..written]);
433}434}
434435
435fn testError(encoded: []const u8, expected_err: anyerror) !void {436fn testError(encoded: []const u8, expected_err: anyerror) !void {
std/buf_map.zig+35-17
...@@ -2,7 +2,7 @@ const std = @import("index.zig");...@@ -2,7 +2,7 @@ const std = @import("index.zig");
2const HashMap = std.HashMap;2const HashMap = std.HashMap;
3const mem = std.mem;3const mem = std.mem;
4const Allocator = mem.Allocator;4const Allocator = mem.Allocator;
5const assert = std.debug.assert;5const testing = std.testing;
66
7/// BufMap copies keys and values before they go into the map, and7/// BufMap copies keys and values before they go into the map, and
8/// frees them when they get removed.8/// frees them when they get removed.
...@@ -16,7 +16,7 @@ pub const BufMap = struct {...@@ -16,7 +16,7 @@ pub const BufMap = struct {
16 return self;16 return self;
17 }17 }
1818
19 pub fn deinit(self: *const BufMap) void {19 pub fn deinit(self: *BufMap) void {
20 var it = self.hash_map.iterator();20 var it = self.hash_map.iterator();
21 while (true) {21 while (true) {
22 const entry = it.next() orelse break;22 const entry = it.next() orelse break;
...@@ -27,16 +27,34 @@ pub const BufMap = struct {...@@ -27,16 +27,34 @@ pub const BufMap = struct {
27 self.hash_map.deinit();27 self.hash_map.deinit();
28 }28 }
2929
30 /// Same as `set` but the key and value become owned by the BufMap rather
31 /// than being copied.
32 /// If `setMove` fails, the ownership of key and value does not transfer.
33 pub fn setMove(self: *BufMap, key: []u8, value: []u8) !void {
34 const get_or_put = try self.hash_map.getOrPut(key);
35 if (get_or_put.found_existing) {
36 self.free(get_or_put.kv.key);
37 get_or_put.kv.key = key;
38 }
39 get_or_put.kv.value = value;
40 }
41
42 /// `key` and `value` are copied into the BufMap.
30 pub fn set(self: *BufMap, key: []const u8, value: []const u8) !void {43 pub fn set(self: *BufMap, key: []const u8, value: []const u8) !void {
31 self.delete(key);
32 const key_copy = try self.copy(key);
33 errdefer self.free(key_copy);
34 const value_copy = try self.copy(value);44 const value_copy = try self.copy(value);
35 errdefer self.free(value_copy);45 errdefer self.free(value_copy);
36 _ = try self.hash_map.put(key_copy, value_copy);46 // Avoid copying key if it already exists
47 const get_or_put = try self.hash_map.getOrPut(key);
48 if (!get_or_put.found_existing) {
49 get_or_put.kv.key = self.copy(key) catch |err| {
50 _ = self.hash_map.remove(key);
51 return err;
52 };
53 }
54 get_or_put.kv.value = value_copy;
37 }55 }
3856
39 pub fn get(self: *const BufMap, key: []const u8) ?[]const u8 {57 pub fn get(self: BufMap, key: []const u8) ?[]const u8 {
40 const entry = self.hash_map.get(key) orelse return null;58 const entry = self.hash_map.get(key) orelse return null;
41 return entry.value;59 return entry.value;
42 }60 }
...@@ -47,7 +65,7 @@ pub const BufMap = struct {...@@ -47,7 +65,7 @@ pub const BufMap = struct {
47 self.free(entry.value);65 self.free(entry.value);
48 }66 }
4967
50 pub fn count(self: *const BufMap) usize {68 pub fn count(self: BufMap) usize {
51 return self.hash_map.count();69 return self.hash_map.count();
52 }70 }
5371
...@@ -55,11 +73,11 @@ pub const BufMap = struct {...@@ -55,11 +73,11 @@ pub const BufMap = struct {
55 return self.hash_map.iterator();73 return self.hash_map.iterator();
56 }74 }
5775
58 fn free(self: *const BufMap, value: []const u8) void {76 fn free(self: BufMap, value: []const u8) void {
59 self.hash_map.allocator.free(value);77 self.hash_map.allocator.free(value);
60 }78 }
6179
62 fn copy(self: *const BufMap, value: []const u8) ![]const u8 {80 fn copy(self: BufMap, value: []const u8) ![]u8 {
63 return mem.dupe(self.hash_map.allocator, u8, value);81 return mem.dupe(self.hash_map.allocator, u8, value);
64 }82 }
65};83};
...@@ -72,17 +90,17 @@ test "BufMap" {...@@ -72,17 +90,17 @@ test "BufMap" {
72 defer bufmap.deinit();90 defer bufmap.deinit();
7391
74 try bufmap.set("x", "1");92 try bufmap.set("x", "1");
75 assert(mem.eql(u8, bufmap.get("x").?, "1"));93 testing.expect(mem.eql(u8, bufmap.get("x").?, "1"));
76 assert(1 == bufmap.count());94 testing.expect(1 == bufmap.count());
7795
78 try bufmap.set("x", "2");96 try bufmap.set("x", "2");
79 assert(mem.eql(u8, bufmap.get("x").?, "2"));97 testing.expect(mem.eql(u8, bufmap.get("x").?, "2"));
80 assert(1 == bufmap.count());98 testing.expect(1 == bufmap.count());
8199
82 try bufmap.set("x", "3");100 try bufmap.set("x", "3");
83 assert(mem.eql(u8, bufmap.get("x").?, "3"));101 testing.expect(mem.eql(u8, bufmap.get("x").?, "3"));
84 assert(1 == bufmap.count());102 testing.expect(1 == bufmap.count());
85103
86 bufmap.delete("x");104 bufmap.delete("x");
87 assert(0 == bufmap.count());105 testing.expect(0 == bufmap.count());
88}106}
std/buf_set.zig+3-3
...@@ -2,7 +2,7 @@ const std = @import("index.zig");...@@ -2,7 +2,7 @@ const std = @import("index.zig");
2const HashMap = @import("hash_map.zig").HashMap;2const HashMap = @import("hash_map.zig").HashMap;
3const mem = @import("mem.zig");3const mem = @import("mem.zig");
4const Allocator = mem.Allocator;4const Allocator = mem.Allocator;
5const assert = std.debug.assert;5const testing = std.testing;
66
7pub const BufSet = struct {7pub const BufSet = struct {
8 hash_map: BufSetHashMap,8 hash_map: BufSetHashMap,
...@@ -68,9 +68,9 @@ test "BufSet" {...@@ -68,9 +68,9 @@ test "BufSet" {
68 defer bufset.deinit();68 defer bufset.deinit();
6969
70 try bufset.put("x");70 try bufset.put("x");
71 assert(bufset.count() == 1);71 testing.expect(bufset.count() == 1);
72 bufset.delete("x");72 bufset.delete("x");
73 assert(bufset.count() == 0);73 testing.expect(bufset.count() == 0);
7474
75 try bufset.put("x");75 try bufset.put("x");
76 try bufset.put("y");76 try bufset.put("y");
std/buffer.zig+8-7
...@@ -3,6 +3,7 @@ const debug = std.debug;...@@ -3,6 +3,7 @@ const debug = std.debug;
3const mem = std.mem;3const mem = std.mem;
4const Allocator = mem.Allocator;4const Allocator = mem.Allocator;
5const assert = debug.assert;5const assert = debug.assert;
6const testing = std.testing;
6const ArrayList = std.ArrayList;7const ArrayList = std.ArrayList;
78
8/// A buffer that allocates memory and maintains a null byte at the end.9/// A buffer that allocates memory and maintains a null byte at the end.
...@@ -141,19 +142,19 @@ test "simple Buffer" {...@@ -141,19 +142,19 @@ test "simple Buffer" {
141 const cstr = @import("cstr.zig");142 const cstr = @import("cstr.zig");
142143
143 var buf = try Buffer.init(debug.global_allocator, "");144 var buf = try Buffer.init(debug.global_allocator, "");
144 assert(buf.len() == 0);145 testing.expect(buf.len() == 0);
145 try buf.append("hello");146 try buf.append("hello");
146 try buf.append(" ");147 try buf.append(" ");
147 try buf.append("world");148 try buf.append("world");
148 assert(buf.eql("hello world"));149 testing.expect(buf.eql("hello world"));
149 assert(mem.eql(u8, cstr.toSliceConst(buf.toSliceConst().ptr), buf.toSliceConst()));150 testing.expect(mem.eql(u8, cstr.toSliceConst(buf.toSliceConst().ptr), buf.toSliceConst()));
150151
151 var buf2 = try Buffer.initFromBuffer(buf);152 var buf2 = try Buffer.initFromBuffer(buf);
152 assert(buf.eql(buf2.toSliceConst()));153 testing.expect(buf.eql(buf2.toSliceConst()));
153154
154 assert(buf.startsWith("hell"));155 testing.expect(buf.startsWith("hell"));
155 assert(buf.endsWith("orld"));156 testing.expect(buf.endsWith("orld"));
156157
157 try buf2.resize(4);158 try buf2.resize(4);
158 assert(buf.startsWith(buf2.toSlice()));159 testing.expect(buf.startsWith(buf2.toSlice()));
159}160}
std/build.zig+107-42
...@@ -89,7 +89,7 @@ pub const Builder = struct {...@@ -89,7 +89,7 @@ pub const Builder = struct {
89 };89 };
9090
91 pub fn init(allocator: *Allocator, zig_exe: []const u8, build_root: []const u8, cache_root: []const u8) Builder {91 pub fn init(allocator: *Allocator, zig_exe: []const u8, build_root: []const u8, cache_root: []const u8) Builder {
92 const env_map = allocator.createOne(BufMap) catch unreachable;92 const env_map = allocator.create(BufMap) catch unreachable;
93 env_map.* = os.getEnvMap(allocator) catch unreachable;93 env_map.* = os.getEnvMap(allocator) catch unreachable;
94 var self = Builder{94 var self = Builder{
95 .zig_exe = zig_exe,95 .zig_exe = zig_exe,
...@@ -145,8 +145,8 @@ pub const Builder = struct {...@@ -145,8 +145,8 @@ pub const Builder = struct {
145145
146 pub fn setInstallPrefix(self: *Builder, maybe_prefix: ?[]const u8) void {146 pub fn setInstallPrefix(self: *Builder, maybe_prefix: ?[]const u8) void {
147 self.prefix = maybe_prefix orelse "/usr/local"; // TODO better default147 self.prefix = maybe_prefix orelse "/usr/local"; // TODO better default
148 self.lib_dir = os.path.join(self.allocator, self.prefix, "lib") catch unreachable;148 self.lib_dir = os.path.join(self.allocator, [][]const u8{ self.prefix, "lib" }) catch unreachable;
149 self.exe_dir = os.path.join(self.allocator, self.prefix, "bin") catch unreachable;149 self.exe_dir = os.path.join(self.allocator, [][]const u8{ self.prefix, "bin" }) catch unreachable;
150 }150 }
151151
152 pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {152 pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
...@@ -170,7 +170,8 @@ pub const Builder = struct {...@@ -170,7 +170,8 @@ pub const Builder = struct {
170 }170 }
171171
172 pub fn addTest(self: *Builder, root_src: []const u8) *TestStep {172 pub fn addTest(self: *Builder, root_src: []const u8) *TestStep {
173 const test_step = self.allocator.create(TestStep.init(self, root_src)) catch unreachable;173 const test_step = self.allocator.create(TestStep) catch unreachable;
174 test_step.* = TestStep.init(self, root_src);
174 return test_step;175 return test_step;
175 }176 }
176177
...@@ -202,18 +203,21 @@ pub const Builder = struct {...@@ -202,18 +203,21 @@ pub const Builder = struct {
202 }203 }
203204
204 pub fn addWriteFile(self: *Builder, file_path: []const u8, data: []const u8) *WriteFileStep {205 pub fn addWriteFile(self: *Builder, file_path: []const u8, data: []const u8) *WriteFileStep {
205 const write_file_step = self.allocator.create(WriteFileStep.init(self, file_path, data)) catch unreachable;206 const write_file_step = self.allocator.create(WriteFileStep) catch unreachable;
207 write_file_step.* = WriteFileStep.init(self, file_path, data);
206 return write_file_step;208 return write_file_step;
207 }209 }
208210
209 pub fn addLog(self: *Builder, comptime format: []const u8, args: ...) *LogStep {211 pub fn addLog(self: *Builder, comptime format: []const u8, args: ...) *LogStep {
210 const data = self.fmt(format, args);212 const data = self.fmt(format, args);
211 const log_step = self.allocator.create(LogStep.init(self, data)) catch unreachable;213 const log_step = self.allocator.create(LogStep) catch unreachable;
214 log_step.* = LogStep.init(self, data);
212 return log_step;215 return log_step;
213 }216 }
214217
215 pub fn addRemoveDirTree(self: *Builder, dir_path: []const u8) *RemoveDirStep {218 pub fn addRemoveDirTree(self: *Builder, dir_path: []const u8) *RemoveDirStep {
216 const remove_dir_step = self.allocator.create(RemoveDirStep.init(self, dir_path)) catch unreachable;219 const remove_dir_step = self.allocator.create(RemoveDirStep) catch unreachable;
220 remove_dir_step.* = RemoveDirStep.init(self, dir_path);
217 return remove_dir_step;221 return remove_dir_step;
218 }222 }
219223
...@@ -320,7 +324,7 @@ pub const Builder = struct {...@@ -320,7 +324,7 @@ pub const Builder = struct {
320324
321 fn processNixOSEnvVars(self: *Builder) void {325 fn processNixOSEnvVars(self: *Builder) void {
322 if (os.getEnvVarOwned(self.allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {326 if (os.getEnvVarOwned(self.allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {
323 var it = mem.split(nix_cflags_compile, " ");327 var it = mem.tokenize(nix_cflags_compile, " ");
324 while (true) {328 while (true) {
325 const word = it.next() orelse break;329 const word = it.next() orelse break;
326 if (mem.eql(u8, word, "-isystem")) {330 if (mem.eql(u8, word, "-isystem")) {
...@@ -338,7 +342,7 @@ pub const Builder = struct {...@@ -338,7 +342,7 @@ pub const Builder = struct {
338 assert(err == error.EnvironmentVariableNotFound);342 assert(err == error.EnvironmentVariableNotFound);
339 }343 }
340 if (os.getEnvVarOwned(self.allocator, "NIX_LDFLAGS")) |nix_ldflags| {344 if (os.getEnvVarOwned(self.allocator, "NIX_LDFLAGS")) |nix_ldflags| {
341 var it = mem.split(nix_ldflags, " ");345 var it = mem.tokenize(nix_ldflags, " ");
342 while (true) {346 while (true) {
343 const word = it.next() orelse break;347 const word = it.next() orelse break;
344 if (mem.eql(u8, word, "-rpath")) {348 if (mem.eql(u8, word, "-rpath")) {
...@@ -414,10 +418,11 @@ pub const Builder = struct {...@@ -414,10 +418,11 @@ pub const Builder = struct {
414 }418 }
415419
416 pub fn step(self: *Builder, name: []const u8, description: []const u8) *Step {420 pub fn step(self: *Builder, name: []const u8, description: []const u8) *Step {
417 const step_info = self.allocator.create(TopLevelStep{421 const step_info = self.allocator.create(TopLevelStep) catch unreachable;
422 step_info.* = TopLevelStep{
418 .step = Step.initNoOp(name, self.allocator),423 .step = Step.initNoOp(name, self.allocator),
419 .description = description,424 .description = description,
420 }) catch unreachable;425 };
421 self.top_level_steps.append(step_info) catch unreachable;426 self.top_level_steps.append(step_info) catch unreachable;
422 return &step_info.step;427 return &step_info.step;
423 }428 }
...@@ -613,10 +618,14 @@ pub const Builder = struct {...@@ -613,10 +618,14 @@ pub const Builder = struct {
613618
614 ///::dest_rel_path is relative to prefix path or it can be an absolute path619 ///::dest_rel_path is relative to prefix path or it can be an absolute path
615 pub fn addInstallFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep {620 pub fn addInstallFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep {
616 const full_dest_path = os.path.resolve(self.allocator, self.prefix, dest_rel_path) catch unreachable;621 const full_dest_path = os.path.resolve(
622 self.allocator,
623 [][]const u8{ self.prefix, dest_rel_path },
624 ) catch unreachable;
617 self.pushInstalledFile(full_dest_path);625 self.pushInstalledFile(full_dest_path);
618626
619 const install_step = self.allocator.create(InstallFileStep.init(self, src_path, full_dest_path)) catch unreachable;627 const install_step = self.allocator.create(InstallFileStep) catch unreachable;
628 install_step.* = InstallFileStep.init(self, src_path, full_dest_path);
620 return install_step;629 return install_step;
621 }630 }
622631
...@@ -647,7 +656,7 @@ pub const Builder = struct {...@@ -647,7 +656,7 @@ pub const Builder = struct {
647 }656 }
648657
649 fn pathFromRoot(self: *Builder, rel_path: []const u8) []u8 {658 fn pathFromRoot(self: *Builder, rel_path: []const u8) []u8 {
650 return os.path.resolve(self.allocator, self.build_root, rel_path) catch unreachable;659 return os.path.resolve(self.allocator, [][]const u8{ self.build_root, rel_path }) catch unreachable;
651 }660 }
652661
653 pub fn fmt(self: *Builder, comptime format: []const u8, args: ...) []u8 {662 pub fn fmt(self: *Builder, comptime format: []const u8, args: ...) []u8 {
...@@ -670,7 +679,7 @@ pub const Builder = struct {...@@ -670,7 +679,7 @@ pub const Builder = struct {
670 if (os.path.isAbsolute(name)) {679 if (os.path.isAbsolute(name)) {
671 return name;680 return name;
672 }681 }
673 const full_path = try os.path.join(self.allocator, search_prefix, "bin", self.fmt("{}{}", name, exe_extension));682 const full_path = try os.path.join(self.allocator, [][]const u8{ search_prefix, "bin", self.fmt("{}{}", name, exe_extension) });
674 if (os.path.real(self.allocator, full_path)) |real_path| {683 if (os.path.real(self.allocator, full_path)) |real_path| {
675 return real_path;684 return real_path;
676 } else |_| {685 } else |_| {
...@@ -683,9 +692,9 @@ pub const Builder = struct {...@@ -683,9 +692,9 @@ pub const Builder = struct {
683 if (os.path.isAbsolute(name)) {692 if (os.path.isAbsolute(name)) {
684 return name;693 return name;
685 }694 }
686 var it = mem.split(PATH, []u8{os.path.delimiter});695 var it = mem.tokenize(PATH, []u8{os.path.delimiter});
687 while (it.next()) |path| {696 while (it.next()) |path| {
688 const full_path = try os.path.join(self.allocator, path, self.fmt("{}{}", name, exe_extension));697 const full_path = try os.path.join(self.allocator, [][]const u8{ path, self.fmt("{}{}", name, exe_extension) });
689 if (os.path.real(self.allocator, full_path)) |real_path| {698 if (os.path.real(self.allocator, full_path)) |real_path| {
690 return real_path;699 return real_path;
691 } else |_| {700 } else |_| {
...@@ -699,7 +708,7 @@ pub const Builder = struct {...@@ -699,7 +708,7 @@ pub const Builder = struct {
699 return name;708 return name;
700 }709 }
701 for (paths) |path| {710 for (paths) |path| {
702 const full_path = try os.path.join(self.allocator, path, self.fmt("{}{}", name, exe_extension));711 const full_path = try os.path.join(self.allocator, [][]const u8{ path, self.fmt("{}{}", name, exe_extension) });
703 if (os.path.real(self.allocator, full_path)) |real_path| {712 if (os.path.real(self.allocator, full_path)) |real_path| {
704 return real_path;713 return real_path;
705 } else |_| {714 } else |_| {
...@@ -865,43 +874,51 @@ pub const LibExeObjStep = struct {...@@ -865,43 +874,51 @@ pub const LibExeObjStep = struct {
865 };874 };
866875
867 pub fn createSharedLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8, ver: Version) *LibExeObjStep {876 pub fn createSharedLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8, ver: Version) *LibExeObjStep {
868 const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Lib, false, ver)) catch unreachable;877 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
878 self.* = initExtraArgs(builder, name, root_src, Kind.Lib, false, ver);
869 return self;879 return self;
870 }880 }
871881
872 pub fn createCSharedLibrary(builder: *Builder, name: []const u8, version: Version) *LibExeObjStep {882 pub fn createCSharedLibrary(builder: *Builder, name: []const u8, version: Version) *LibExeObjStep {
873 const self = builder.allocator.create(initC(builder, name, Kind.Lib, version, false)) catch unreachable;883 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
884 self.* = initC(builder, name, Kind.Lib, version, false);
874 return self;885 return self;
875 }886 }
876887
877 pub fn createStaticLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {888 pub fn createStaticLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
878 const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0))) catch unreachable;889 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
890 self.* = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0));
879 return self;891 return self;
880 }892 }
881893
882 pub fn createCStaticLibrary(builder: *Builder, name: []const u8) *LibExeObjStep {894 pub fn createCStaticLibrary(builder: *Builder, name: []const u8) *LibExeObjStep {
883 const self = builder.allocator.create(initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true)) catch unreachable;895 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
896 self.* = initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true);
884 return self;897 return self;
885 }898 }
886899
887 pub fn createObject(builder: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep {900 pub fn createObject(builder: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep {
888 const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0))) catch unreachable;901 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
902 self.* = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0));
889 return self;903 return self;
890 }904 }
891905
892 pub fn createCObject(builder: *Builder, name: []const u8, src: []const u8) *LibExeObjStep {906 pub fn createCObject(builder: *Builder, name: []const u8, src: []const u8) *LibExeObjStep {
893 const self = builder.allocator.create(initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false)) catch unreachable;907 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
908 self.* = initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false);
894 self.object_src = src;909 self.object_src = src;
895 return self;910 return self;
896 }911 }
897912
898 pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8, static: bool) *LibExeObjStep {913 pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8, static: bool) *LibExeObjStep {
899 const self = builder.allocator.create(initExtraArgs(builder, name, root_src, Kind.Exe, static, builder.version(0, 0, 0))) catch unreachable;914 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
915 self.* = initExtraArgs(builder, name, root_src, Kind.Exe, static, builder.version(0, 0, 0));
900 return self;916 return self;
901 }917 }
902918
903 pub fn createCExecutable(builder: *Builder, name: []const u8) *LibExeObjStep {919 pub fn createCExecutable(builder: *Builder, name: []const u8) *LibExeObjStep {
904 const self = builder.allocator.create(initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false)) catch unreachable;920 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
921 self.* = initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false);
905 return self;922 return self;
906 }923 }
907924
...@@ -1099,7 +1116,10 @@ pub const LibExeObjStep = struct {...@@ -1099,7 +1116,10 @@ pub const LibExeObjStep = struct {
1099 }1116 }
11001117
1101 pub fn getOutputPath(self: *LibExeObjStep) []const u8 {1118 pub fn getOutputPath(self: *LibExeObjStep) []const u8 {
1102 return if (self.output_path) |output_path| output_path else os.path.join(self.builder.allocator, self.builder.cache_root, self.out_filename) catch unreachable;1119 return if (self.output_path) |output_path| output_path else os.path.join(
1120 self.builder.allocator,
1121 [][]const u8{ self.builder.cache_root, self.out_filename },
1122 ) catch unreachable;
1103 }1123 }
11041124
1105 pub fn setOutputHPath(self: *LibExeObjStep, file_path: []const u8) void {1125 pub fn setOutputHPath(self: *LibExeObjStep, file_path: []const u8) void {
...@@ -1112,7 +1132,10 @@ pub const LibExeObjStep = struct {...@@ -1112,7 +1132,10 @@ pub const LibExeObjStep = struct {
1112 }1132 }
11131133
1114 pub fn getOutputHPath(self: *LibExeObjStep) []const u8 {1134 pub fn getOutputHPath(self: *LibExeObjStep) []const u8 {
1115 return if (self.output_h_path) |output_h_path| output_h_path else os.path.join(self.builder.allocator, self.builder.cache_root, self.out_h_filename) catch unreachable;1135 return if (self.output_h_path) |output_h_path| output_h_path else os.path.join(
1136 self.builder.allocator,
1137 [][]const u8{ self.builder.cache_root, self.out_h_filename },
1138 ) catch unreachable;
1116 }1139 }
11171140
1118 pub fn addAssemblyFile(self: *LibExeObjStep, path: []const u8) void {1141 pub fn addAssemblyFile(self: *LibExeObjStep, path: []const u8) void {
...@@ -1212,7 +1235,10 @@ pub const LibExeObjStep = struct {...@@ -1212,7 +1235,10 @@ pub const LibExeObjStep = struct {
1212 }1235 }
12131236
1214 if (self.build_options_contents.len() > 0) {1237 if (self.build_options_contents.len() > 0) {
1215 const build_options_file = try os.path.join(builder.allocator, builder.cache_root, builder.fmt("{}_build_options.zig", self.name));1238 const build_options_file = try os.path.join(
1239 builder.allocator,
1240 [][]const u8{ builder.cache_root, builder.fmt("{}_build_options.zig", self.name) },
1241 );
1216 try std.io.writeFile(build_options_file, self.build_options_contents.toSliceConst());1242 try std.io.writeFile(build_options_file, self.build_options_contents.toSliceConst());
1217 try zig_args.append("--pkg-begin");1243 try zig_args.append("--pkg-begin");
1218 try zig_args.append("build_options");1244 try zig_args.append("build_options");
...@@ -1462,7 +1488,10 @@ pub const LibExeObjStep = struct {...@@ -1462,7 +1488,10 @@ pub const LibExeObjStep = struct {
1462 cc_args.append("-c") catch unreachable;1488 cc_args.append("-c") catch unreachable;
1463 cc_args.append(abs_source_file) catch unreachable;1489 cc_args.append(abs_source_file) catch unreachable;
14641490
1465 const cache_o_src = os.path.join(builder.allocator, builder.cache_root, source_file) catch unreachable;1491 const cache_o_src = os.path.join(
1492 builder.allocator,
1493 [][]const u8{ builder.cache_root, source_file },
1494 ) catch unreachable;
1466 if (os.path.dirname(cache_o_src)) |cache_o_dir| {1495 if (os.path.dirname(cache_o_src)) |cache_o_dir| {
1467 try builder.makePath(cache_o_dir);1496 try builder.makePath(cache_o_dir);
1468 }1497 }
...@@ -1514,7 +1543,10 @@ pub const LibExeObjStep = struct {...@@ -1514,7 +1543,10 @@ pub const LibExeObjStep = struct {
1514 cc_args.append("-current_version") catch unreachable;1543 cc_args.append("-current_version") catch unreachable;
1515 cc_args.append(builder.fmt("{}.{}.{}", self.version.major, self.version.minor, self.version.patch)) catch unreachable;1544 cc_args.append(builder.fmt("{}.{}.{}", self.version.major, self.version.minor, self.version.patch)) catch unreachable;
15161545
1517 const install_name = builder.pathFromRoot(os.path.join(builder.allocator, builder.cache_root, self.major_only_filename) catch unreachable);1546 const install_name = builder.pathFromRoot(os.path.join(
1547 builder.allocator,
1548 [][]const u8{ builder.cache_root, self.major_only_filename },
1549 ) catch unreachable);
1518 cc_args.append("-install_name") catch unreachable;1550 cc_args.append("-install_name") catch unreachable;
1519 cc_args.append(install_name) catch unreachable;1551 cc_args.append(install_name) catch unreachable;
1520 } else {1552 } else {
...@@ -1580,7 +1612,10 @@ pub const LibExeObjStep = struct {...@@ -1580,7 +1612,10 @@ pub const LibExeObjStep = struct {
1580 cc_args.append("-c") catch unreachable;1612 cc_args.append("-c") catch unreachable;
1581 cc_args.append(abs_source_file) catch unreachable;1613 cc_args.append(abs_source_file) catch unreachable;
15821614
1583 const cache_o_src = os.path.join(builder.allocator, builder.cache_root, source_file) catch unreachable;1615 const cache_o_src = os.path.join(
1616 builder.allocator,
1617 [][]const u8{ builder.cache_root, source_file },
1618 ) catch unreachable;
1584 if (os.path.dirname(cache_o_src)) |cache_o_dir| {1619 if (os.path.dirname(cache_o_src)) |cache_o_dir| {
1585 try builder.makePath(cache_o_dir);1620 try builder.makePath(cache_o_dir);
1586 }1621 }
...@@ -1672,6 +1707,7 @@ pub const TestStep = struct {...@@ -1672,6 +1707,7 @@ pub const TestStep = struct {
1672 no_rosegment: bool,1707 no_rosegment: bool,
1673 output_path: ?[]const u8,1708 output_path: ?[]const u8,
1674 system_linker_hack: bool,1709 system_linker_hack: bool,
1710 override_std_dir: ?[]const u8,
16751711
1676 pub fn init(builder: *Builder, root_src: []const u8) TestStep {1712 pub fn init(builder: *Builder, root_src: []const u8) TestStep {
1677 const step_name = builder.fmt("test {}", root_src);1713 const step_name = builder.fmt("test {}", root_src);
...@@ -1693,6 +1729,7 @@ pub const TestStep = struct {...@@ -1693,6 +1729,7 @@ pub const TestStep = struct {
1693 .no_rosegment = false,1729 .no_rosegment = false,
1694 .output_path = null,1730 .output_path = null,
1695 .system_linker_hack = false,1731 .system_linker_hack = false,
1732 .override_std_dir = null,
1696 };1733 };
1697 }1734 }
16981735
...@@ -1723,6 +1760,10 @@ pub const TestStep = struct {...@@ -1723,6 +1760,10 @@ pub const TestStep = struct {
1723 self.build_mode = mode;1760 self.build_mode = mode;
1724 }1761 }
17251762
1763 pub fn overrideStdDir(self: *TestStep, dir_path: []const u8) void {
1764 self.override_std_dir = dir_path;
1765 }
1766
1726 pub fn setOutputPath(self: *TestStep, file_path: []const u8) void {1767 pub fn setOutputPath(self: *TestStep, file_path: []const u8) void {
1727 self.output_path = file_path;1768 self.output_path = file_path;
17281769
...@@ -1737,7 +1778,10 @@ pub const TestStep = struct {...@@ -1737,7 +1778,10 @@ pub const TestStep = struct {
1737 return output_path;1778 return output_path;
1738 } else {1779 } else {
1739 const basename = self.builder.fmt("test{}", self.target.exeFileExt());1780 const basename = self.builder.fmt("test{}", self.target.exeFileExt());
1740 return os.path.join(self.builder.allocator, self.builder.cache_root, basename) catch unreachable;1781 return os.path.join(
1782 self.builder.allocator,
1783 [][]const u8{ self.builder.cache_root, basename },
1784 ) catch unreachable;
1741 }1785 }
1742 }1786 }
17431787
...@@ -1900,6 +1944,10 @@ pub const TestStep = struct {...@@ -1900,6 +1944,10 @@ pub const TestStep = struct {
1900 if (self.system_linker_hack) {1944 if (self.system_linker_hack) {
1901 try zig_args.append("--system-linker-hack");1945 try zig_args.append("--system-linker-hack");
1902 }1946 }
1947 if (self.override_std_dir) |dir| {
1948 try zig_args.append("--override-std-dir");
1949 try zig_args.append(builder.pathFromRoot(dir));
1950 }
19031951
1904 try builder.spawnChild(zig_args.toSliceConst());1952 try builder.spawnChild(zig_args.toSliceConst());
1905 }1953 }
...@@ -1914,13 +1962,14 @@ pub const CommandStep = struct {...@@ -1914,13 +1962,14 @@ pub const CommandStep = struct {
19141962
1915 /// ::argv is copied.1963 /// ::argv is copied.
1916 pub fn create(builder: *Builder, cwd: ?[]const u8, env_map: *const BufMap, argv: []const []const u8) *CommandStep {1964 pub fn create(builder: *Builder, cwd: ?[]const u8, env_map: *const BufMap, argv: []const []const u8) *CommandStep {
1917 const self = builder.allocator.create(CommandStep{1965 const self = builder.allocator.create(CommandStep) catch unreachable;
1966 self.* = CommandStep{
1918 .builder = builder,1967 .builder = builder,
1919 .step = Step.init(argv[0], builder.allocator, make),1968 .step = Step.init(argv[0], builder.allocator, make),
1920 .argv = builder.allocator.alloc([]u8, argv.len) catch unreachable,1969 .argv = builder.allocator.alloc([]u8, argv.len) catch unreachable,
1921 .cwd = cwd,1970 .cwd = cwd,
1922 .env_map = env_map,1971 .env_map = env_map,
1923 }) catch unreachable;1972 };
19241973
1925 mem.copy([]const u8, self.argv, argv);1974 mem.copy([]const u8, self.argv, argv);
1926 self.step.name = self.argv[0];1975 self.step.name = self.argv[0];
...@@ -1949,17 +1998,27 @@ const InstallArtifactStep = struct {...@@ -1949,17 +1998,27 @@ const InstallArtifactStep = struct {
1949 LibExeObjStep.Kind.Exe => builder.exe_dir,1998 LibExeObjStep.Kind.Exe => builder.exe_dir,
1950 LibExeObjStep.Kind.Lib => builder.lib_dir,1999 LibExeObjStep.Kind.Lib => builder.lib_dir,
1951 };2000 };
1952 const self = builder.allocator.create(Self{2001 const self = builder.allocator.create(Self) catch unreachable;
2002 self.* = Self{
1953 .builder = builder,2003 .builder = builder,
1954 .step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make),2004 .step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make),
1955 .artifact = artifact,2005 .artifact = artifact,
1956 .dest_file = os.path.join(builder.allocator, dest_dir, artifact.out_filename) catch unreachable,2006 .dest_file = os.path.join(
1957 }) catch unreachable;2007 builder.allocator,
2008 [][]const u8{ dest_dir, artifact.out_filename },
2009 ) catch unreachable,
2010 };
1958 self.step.dependOn(&artifact.step);2011 self.step.dependOn(&artifact.step);
1959 builder.pushInstalledFile(self.dest_file);2012 builder.pushInstalledFile(self.dest_file);
1960 if (self.artifact.kind == LibExeObjStep.Kind.Lib and !self.artifact.static) {2013 if (self.artifact.kind == LibExeObjStep.Kind.Lib and !self.artifact.static) {
1961 builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, artifact.major_only_filename) catch unreachable);2014 builder.pushInstalledFile(os.path.join(
1962 builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, artifact.name_only_filename) catch unreachable);2015 builder.allocator,
2016 [][]const u8{ builder.lib_dir, artifact.major_only_filename },
2017 ) catch unreachable);
2018 builder.pushInstalledFile(os.path.join(
2019 builder.allocator,
2020 [][]const u8{ builder.lib_dir, artifact.name_only_filename },
2021 ) catch unreachable);
1963 }2022 }
1964 return self;2023 return self;
1965 }2024 }
...@@ -2115,13 +2174,19 @@ fn doAtomicSymLinks(allocator: *Allocator, output_path: []const u8, filename_maj...@@ -2115,13 +2174,19 @@ fn doAtomicSymLinks(allocator: *Allocator, output_path: []const u8, filename_maj
2115 const out_dir = os.path.dirname(output_path) orelse ".";2174 const out_dir = os.path.dirname(output_path) orelse ".";
2116 const out_basename = os.path.basename(output_path);2175 const out_basename = os.path.basename(output_path);
2117 // sym link for libfoo.so.1 to libfoo.so.1.2.32176 // sym link for libfoo.so.1 to libfoo.so.1.2.3
2118 const major_only_path = os.path.join(allocator, out_dir, filename_major_only) catch unreachable;2177 const major_only_path = os.path.join(
2178 allocator,
2179 [][]const u8{ out_dir, filename_major_only },
2180 ) catch unreachable;
2119 os.atomicSymLink(allocator, out_basename, major_only_path) catch |err| {2181 os.atomicSymLink(allocator, out_basename, major_only_path) catch |err| {
2120 warn("Unable to symlink {} -> {}\n", major_only_path, out_basename);2182 warn("Unable to symlink {} -> {}\n", major_only_path, out_basename);
2121 return err;2183 return err;
2122 };2184 };
2123 // sym link for libfoo.so to libfoo.so.12185 // sym link for libfoo.so to libfoo.so.1
2124 const name_only_path = os.path.join(allocator, out_dir, filename_name_only) catch unreachable;2186 const name_only_path = os.path.join(
2187 allocator,
2188 [][]const u8{ out_dir, filename_name_only },
2189 ) catch unreachable;
2125 os.atomicSymLink(allocator, filename_major_only, name_only_path) catch |err| {2190 os.atomicSymLink(allocator, filename_major_only, name_only_path) catch |err| {
2126 warn("Unable to symlink {} -> {}\n", name_only_path, filename_major_only);2191 warn("Unable to symlink {} -> {}\n", name_only_path, filename_major_only);
2127 return err;2192 return err;
std/c/darwin.zig+20-2
...@@ -73,8 +73,8 @@ pub const sockaddr_in6 = extern struct {...@@ -73,8 +73,8 @@ pub const sockaddr_in6 = extern struct {
73};73};
7474
75pub const timeval = extern struct {75pub const timeval = extern struct {
76 tv_sec: isize,76 tv_sec: c_long,
77 tv_usec: isize,77 tv_usec: i32,
78};78};
7979
80pub const timezone = extern struct {80pub const timezone = extern struct {
...@@ -176,6 +176,24 @@ pub const kevent64_s = extern struct {...@@ -176,6 +176,24 @@ pub const kevent64_s = extern struct {
176 ext: [2]u64,176 ext: [2]u64,
177};177};
178178
179pub const mach_port_t = c_uint;
180pub const clock_serv_t = mach_port_t;
181pub const clock_res_t = c_int;
182pub const mach_port_name_t = natural_t;
183pub const natural_t = c_uint;
184pub const mach_timespec_t = extern struct {
185 tv_sec: c_uint,
186 tv_nsec: clock_res_t,
187};
188pub const kern_return_t = c_int;
189pub const host_t = mach_port_t;
190pub const CALENDAR_CLOCK = 1;
191
192pub extern fn mach_host_self() mach_port_t;
193pub extern fn clock_get_time(clock_serv: clock_serv_t, cur_time: *mach_timespec_t) kern_return_t;
194pub extern fn host_get_clock_service(host: host_t, clock_id: clock_id_t, clock_serv: ?[*]clock_serv_t) kern_return_t;
195pub extern fn mach_port_deallocate(task: ipc_space_t, name: mach_port_name_t) kern_return_t;
196
179// sys/types.h on macos uses #pragma pack() so these checks are197// sys/types.h on macos uses #pragma pack() so these checks are
180// to make sure the struct is laid out the same. These values were198// to make sure the struct is laid out the same. These values were
181// produced from C code using the offsetof macro.199// produced from C code using the offsetof macro.
std/c/freebsd.zig+89-2
...@@ -1,5 +1,3 @@...@@ -1,5 +1,3 @@
1const timespec = @import("../os/freebsd/index.zig").timespec;
2
3extern "c" fn __error() *c_int;1extern "c" fn __error() *c_int;
4pub const _errno = __error;2pub const _errno = __error;
53
...@@ -15,6 +13,17 @@ pub extern "c" fn kevent(...@@ -15,6 +13,17 @@ pub extern "c" fn kevent(
15pub extern "c" fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;13pub extern "c" fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
16pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;14pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
17pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) c_int;15pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) c_int;
16pub extern "c" fn getdirentries(fd: c_int, buf_ptr: [*]u8, nbytes: usize, basep: *i64) usize;
17pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) usize;
18pub extern "c" fn pipe2(arg0: *[2]c_int, arg1: u32) c_int;
19pub extern "c" fn preadv(fd: c_int, iov: *const c_void, iovcnt: c_int, offset: usize) isize;
20pub extern "c" fn pwritev(fd: c_int, iov: *const c_void, iovcnt: c_int, offset: usize) isize;
21pub extern "c" fn openat(fd: c_int, path: ?[*]const u8, flags: c_int) c_int;
22pub extern "c" fn setgid(ruid: c_uint, euid: c_uint) c_int;
23pub extern "c" fn setuid(uid: c_uint) c_int;
24pub extern "c" fn kill(pid: c_int, sig: c_int) c_int;
25pub extern "c" fn clock_gettime(clk_id: c_int, tp: *timespec) c_int;
26pub extern "c" fn clock_getres(clk_id: c_int, tp: *timespec) c_int;
1827
19/// Renamed from `kevent` to `Kevent` to avoid conflict with function name.28/// Renamed from `kevent` to `Kevent` to avoid conflict with function name.
20pub const Kevent = extern struct {29pub const Kevent = extern struct {
...@@ -31,3 +40,81 @@ pub const pthread_attr_t = extern struct {...@@ -31,3 +40,81 @@ pub const pthread_attr_t = extern struct {
31 __size: [56]u8,40 __size: [56]u8,
32 __align: c_long,41 __align: c_long,
33};42};
43
44pub const msghdr = extern struct {
45 msg_name: *u8,
46 msg_namelen: socklen_t,
47 msg_iov: *iovec,
48 msg_iovlen: i32,
49 __pad1: i32,
50 msg_control: *u8,
51 msg_controllen: socklen_t,
52 __pad2: socklen_t,
53 msg_flags: i32,
54};
55
56pub const Stat = extern struct {
57 dev: u64,
58 ino: u64,
59 nlink: usize,
60
61 mode: u16,
62 __pad0: u16,
63 uid: u32,
64 gid: u32,
65 __pad1: u32,
66 rdev: u64,
67
68 atim: timespec,
69 mtim: timespec,
70 ctim: timespec,
71 birthtim: timespec,
72
73 size: i64,
74 blocks: i64,
75 blksize: isize,
76 flags: u32,
77 gen: u64,
78 __spare: [10]u64,
79};
80
81pub const timespec = extern struct {
82 tv_sec: isize,
83 tv_nsec: isize,
84};
85
86pub const dirent = extern struct {
87 d_fileno: usize,
88 d_off: i64,
89 d_reclen: u16,
90 d_type: u8,
91 d_pad0: u8,
92 d_namlen: u16,
93 d_pad1: u16,
94 d_name: [256]u8,
95};
96
97pub const in_port_t = u16;
98pub const sa_family_t = u16;
99
100pub const sockaddr = extern union {
101 in: sockaddr_in,
102 in6: sockaddr_in6,
103};
104
105pub const sockaddr_in = extern struct {
106 len: u8,
107 family: sa_family_t,
108 port: in_port_t,
109 addr: [16]u8,
110 zero: [8]u8,
111};
112
113pub const sockaddr_in6 = extern struct {
114 len: u8,
115 family: sa_family_t,
116 port: in_port_t,
117 flowinfo: u32,
118 addr: [16]u8,
119 scope_id: u32,
120};
std/c/index.zig+1-1
...@@ -44,7 +44,7 @@ pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) c_int;...@@ -44,7 +44,7 @@ pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) c_int;
44pub extern "c" fn readlink(noalias path: [*]const u8, noalias buf: [*]u8, bufsize: usize) isize;44pub extern "c" fn readlink(noalias path: [*]const u8, noalias buf: [*]u8, bufsize: usize) isize;
45pub extern "c" fn realpath(noalias file_name: [*]const u8, noalias resolved_name: [*]u8) ?[*]u8;45pub extern "c" fn realpath(noalias file_name: [*]const u8, noalias resolved_name: [*]u8) ?[*]u8;
46pub extern "c" fn sigprocmask(how: c_int, noalias set: *const sigset_t, noalias oset: ?*sigset_t) c_int;46pub extern "c" fn sigprocmask(how: c_int, noalias set: *const sigset_t, noalias oset: ?*sigset_t) c_int;
47pub extern "c" fn gettimeofday(tv: ?*timeval, tz: ?*timezone) c_int;47pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int;
48pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int;48pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int;
49pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int;49pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int;
50pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int;50pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int;
std/coff.zig+22-22
...@@ -51,7 +51,7 @@ pub const Coff = struct {...@@ -51,7 +51,7 @@ pub const Coff = struct {
5151
52 // Seek to PE File Header (coff header)52 // Seek to PE File Header (coff header)
53 try self.in_file.seekTo(pe_pointer_offset);53 try self.in_file.seekTo(pe_pointer_offset);
54 const pe_magic_offset = try in.readIntLe(u32);54 const pe_magic_offset = try in.readIntLittle(u32);
55 try self.in_file.seekTo(pe_magic_offset);55 try self.in_file.seekTo(pe_magic_offset);
5656
57 var pe_header_magic: [4]u8 = undefined;57 var pe_header_magic: [4]u8 = undefined;
...@@ -60,13 +60,13 @@ pub const Coff = struct {...@@ -60,13 +60,13 @@ pub const Coff = struct {
60 return error.InvalidPEHeader;60 return error.InvalidPEHeader;
6161
62 self.coff_header = CoffHeader{62 self.coff_header = CoffHeader{
63 .machine = try in.readIntLe(u16),63 .machine = try in.readIntLittle(u16),
64 .number_of_sections = try in.readIntLe(u16),64 .number_of_sections = try in.readIntLittle(u16),
65 .timedate_stamp = try in.readIntLe(u32),65 .timedate_stamp = try in.readIntLittle(u32),
66 .pointer_to_symbol_table = try in.readIntLe(u32),66 .pointer_to_symbol_table = try in.readIntLittle(u32),
67 .number_of_symbols = try in.readIntLe(u32),67 .number_of_symbols = try in.readIntLittle(u32),
68 .size_of_optional_header = try in.readIntLe(u16),68 .size_of_optional_header = try in.readIntLittle(u16),
69 .characteristics = try in.readIntLe(u16),69 .characteristics = try in.readIntLittle(u16),
70 };70 };
7171
72 switch (self.coff_header.machine) {72 switch (self.coff_header.machine) {
...@@ -79,7 +79,7 @@ pub const Coff = struct {...@@ -79,7 +79,7 @@ pub const Coff = struct {
7979
80 fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void {80 fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void {
81 const in = &file_stream.stream;81 const in = &file_stream.stream;
82 self.pe_header.magic = try in.readIntLe(u16);82 self.pe_header.magic = try in.readIntLittle(u16);
83 // For now we're only interested in finding the reference to the .pdb,83 // For now we're only interested in finding the reference to the .pdb,
84 // so we'll skip most of this header, which size is different in 3284 // so we'll skip most of this header, which size is different in 32
85 // 64 bits by the way.85 // 64 bits by the way.
...@@ -93,14 +93,14 @@ pub const Coff = struct {...@@ -93,14 +93,14 @@ pub const Coff = struct {
9393
94 try self.in_file.seekForward(skip_size);94 try self.in_file.seekForward(skip_size);
9595
96 const number_of_rva_and_sizes = try in.readIntLe(u32);96 const number_of_rva_and_sizes = try in.readIntLittle(u32);
97 if (number_of_rva_and_sizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES)97 if (number_of_rva_and_sizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
98 return error.InvalidPEHeader;98 return error.InvalidPEHeader;
9999
100 for (self.pe_header.data_directory) |*data_dir| {100 for (self.pe_header.data_directory) |*data_dir| {
101 data_dir.* = OptionalHeader.DataDirectory{101 data_dir.* = OptionalHeader.DataDirectory{
102 .virtual_address = try in.readIntLe(u32),102 .virtual_address = try in.readIntLittle(u32),
103 .size = try in.readIntLe(u32),103 .size = try in.readIntLittle(u32),
104 };104 };
105 }105 }
106 }106 }
...@@ -124,7 +124,7 @@ pub const Coff = struct {...@@ -124,7 +124,7 @@ pub const Coff = struct {
124 if (!mem.eql(u8, cv_signature, "RSDS"))124 if (!mem.eql(u8, cv_signature, "RSDS"))
125 return error.InvalidPEMagic;125 return error.InvalidPEMagic;
126 try in.readNoEof(self.guid[0..]);126 try in.readNoEof(self.guid[0..]);
127 self.age = try in.readIntLe(u32);127 self.age = try in.readIntLittle(u32);
128128
129 // Finally read the null-terminated string.129 // Finally read the null-terminated string.
130 var byte = try in.readByte();130 var byte = try in.readByte();
...@@ -157,15 +157,15 @@ pub const Coff = struct {...@@ -157,15 +157,15 @@ pub const Coff = struct {
157 try self.sections.append(Section{157 try self.sections.append(Section{
158 .header = SectionHeader{158 .header = SectionHeader{
159 .name = name,159 .name = name,
160 .misc = SectionHeader.Misc{ .physical_address = try in.readIntLe(u32) },160 .misc = SectionHeader.Misc{ .physical_address = try in.readIntLittle(u32) },
161 .virtual_address = try in.readIntLe(u32),161 .virtual_address = try in.readIntLittle(u32),
162 .size_of_raw_data = try in.readIntLe(u32),162 .size_of_raw_data = try in.readIntLittle(u32),
163 .pointer_to_raw_data = try in.readIntLe(u32),163 .pointer_to_raw_data = try in.readIntLittle(u32),
164 .pointer_to_relocations = try in.readIntLe(u32),164 .pointer_to_relocations = try in.readIntLittle(u32),
165 .pointer_to_line_numbers = try in.readIntLe(u32),165 .pointer_to_line_numbers = try in.readIntLittle(u32),
166 .number_of_relocations = try in.readIntLe(u16),166 .number_of_relocations = try in.readIntLittle(u16),
167 .number_of_line_numbers = try in.readIntLe(u16),167 .number_of_line_numbers = try in.readIntLittle(u16),
168 .characteristics = try in.readIntLe(u32),168 .characteristics = try in.readIntLittle(u32),
169 },169 },
170 });170 });
171 }171 }
std/crypto/blake2.zig+7-4
...@@ -123,7 +123,8 @@ fn Blake2s(comptime out_len: usize) type {...@@ -123,7 +123,8 @@ fn Blake2s(comptime out_len: usize) type {
123 const rr = d.h[0 .. out_len / 32];123 const rr = d.h[0 .. out_len / 32];
124124
125 for (rr) |s, j| {125 for (rr) |s, j| {
126 mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Little);126 // TODO https://github.com/ziglang/zig/issues/863
127 mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s);
127 }128 }
128 }129 }
129130
...@@ -134,7 +135,8 @@ fn Blake2s(comptime out_len: usize) type {...@@ -134,7 +135,8 @@ fn Blake2s(comptime out_len: usize) type {
134 var v: [16]u32 = undefined;135 var v: [16]u32 = undefined;
135136
136 for (m) |*r, i| {137 for (m) |*r, i| {
137 r.* = mem.readIntLE(u32, b[4 * i .. 4 * i + 4]);138 // TODO https://github.com/ziglang/zig/issues/863
139 r.* = mem.readIntSliceLittle(u32, b[4 * i .. 4 * i + 4]);
138 }140 }
139141
140 var k: usize = 0;142 var k: usize = 0;
...@@ -356,7 +358,8 @@ fn Blake2b(comptime out_len: usize) type {...@@ -356,7 +358,8 @@ fn Blake2b(comptime out_len: usize) type {
356 const rr = d.h[0 .. out_len / 64];358 const rr = d.h[0 .. out_len / 64];
357359
358 for (rr) |s, j| {360 for (rr) |s, j| {
359 mem.writeInt(out[8 * j .. 8 * j + 8], s, builtin.Endian.Little);361 // TODO https://github.com/ziglang/zig/issues/863
362 mem.writeIntSliceLittle(u64, out[8 * j .. 8 * j + 8], s);
360 }363 }
361 }364 }
362365
...@@ -367,7 +370,7 @@ fn Blake2b(comptime out_len: usize) type {...@@ -367,7 +370,7 @@ fn Blake2b(comptime out_len: usize) type {
367 var v: [16]u64 = undefined;370 var v: [16]u64 = undefined;
368371
369 for (m) |*r, i| {372 for (m) |*r, i| {
370 r.* = mem.readIntLE(u64, b[8 * i .. 8 * i + 8]);373 r.* = mem.readIntSliceLittle(u64, b[8 * i .. 8 * i + 8]);
371 }374 }
372375
373 var k: usize = 0;376 var k: usize = 0;
std/crypto/chacha20.zig+35-33
...@@ -4,6 +4,7 @@ const std = @import("../index.zig");...@@ -4,6 +4,7 @@ const std = @import("../index.zig");
4const mem = std.mem;4const mem = std.mem;
5const endian = std.endian;5const endian = std.endian;
6const assert = std.debug.assert;6const assert = std.debug.assert;
7const testing = std.testing;
7const builtin = @import("builtin");8const builtin = @import("builtin");
8const maxInt = std.math.maxInt;9const maxInt = std.math.maxInt;
910
...@@ -59,7 +60,8 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void {...@@ -59,7 +60,8 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void {
59 }60 }
6061
61 for (x) |_, i| {62 for (x) |_, i| {
62 mem.writeInt(out[4 * i .. 4 * i + 4], x[i] +% input[i], builtin.Endian.Little);63 // TODO https://github.com/ziglang/zig/issues/863
64 mem.writeIntSliceLittle(u32, out[4 * i .. 4 * i + 4], x[i] +% input[i]);
63 }65 }
64}66}
6567
...@@ -70,10 +72,10 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo...@@ -70,10 +72,10 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo
7072
71 const c = "expand 32-byte k";73 const c = "expand 32-byte k";
72 const constant_le = []u32{74 const constant_le = []u32{
73 mem.readIntLE(u32, c[0..4]),75 mem.readIntSliceLittle(u32, c[0..4]),
74 mem.readIntLE(u32, c[4..8]),76 mem.readIntSliceLittle(u32, c[4..8]),
75 mem.readIntLE(u32, c[8..12]),77 mem.readIntSliceLittle(u32, c[8..12]),
76 mem.readIntLE(u32, c[12..16]),78 mem.readIntSliceLittle(u32, c[12..16]),
77 };79 };
7880
79 mem.copy(u32, ctx[0..], constant_le[0..4]);81 mem.copy(u32, ctx[0..], constant_le[0..4]);
...@@ -117,19 +119,19 @@ pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce:...@@ -117,19 +119,19 @@ pub fn chaCha20IETF(out: []u8, in: []const u8, counter: u32, key: [32]u8, nonce:
117 var k: [8]u32 = undefined;119 var k: [8]u32 = undefined;
118 var c: [4]u32 = undefined;120 var c: [4]u32 = undefined;
119121
120 k[0] = mem.readIntLE(u32, key[0..4]);122 k[0] = mem.readIntSliceLittle(u32, key[0..4]);
121 k[1] = mem.readIntLE(u32, key[4..8]);123 k[1] = mem.readIntSliceLittle(u32, key[4..8]);
122 k[2] = mem.readIntLE(u32, key[8..12]);124 k[2] = mem.readIntSliceLittle(u32, key[8..12]);
123 k[3] = mem.readIntLE(u32, key[12..16]);125 k[3] = mem.readIntSliceLittle(u32, key[12..16]);
124 k[4] = mem.readIntLE(u32, key[16..20]);126 k[4] = mem.readIntSliceLittle(u32, key[16..20]);
125 k[5] = mem.readIntLE(u32, key[20..24]);127 k[5] = mem.readIntSliceLittle(u32, key[20..24]);
126 k[6] = mem.readIntLE(u32, key[24..28]);128 k[6] = mem.readIntSliceLittle(u32, key[24..28]);
127 k[7] = mem.readIntLE(u32, key[28..32]);129 k[7] = mem.readIntSliceLittle(u32, key[28..32]);
128130
129 c[0] = counter;131 c[0] = counter;
130 c[1] = mem.readIntLE(u32, nonce[0..4]);132 c[1] = mem.readIntSliceLittle(u32, nonce[0..4]);
131 c[2] = mem.readIntLE(u32, nonce[4..8]);133 c[2] = mem.readIntSliceLittle(u32, nonce[4..8]);
132 c[3] = mem.readIntLE(u32, nonce[8..12]);134 c[3] = mem.readIntSliceLittle(u32, nonce[8..12]);
133 chaCha20_internal(out, in, k, c);135 chaCha20_internal(out, in, k, c);
134}136}
135137
...@@ -144,19 +146,19 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]...@@ -144,19 +146,19 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]
144 var k: [8]u32 = undefined;146 var k: [8]u32 = undefined;
145 var c: [4]u32 = undefined;147 var c: [4]u32 = undefined;
146148
147 k[0] = mem.readIntLE(u32, key[0..4]);149 k[0] = mem.readIntSliceLittle(u32, key[0..4]);
148 k[1] = mem.readIntLE(u32, key[4..8]);150 k[1] = mem.readIntSliceLittle(u32, key[4..8]);
149 k[2] = mem.readIntLE(u32, key[8..12]);151 k[2] = mem.readIntSliceLittle(u32, key[8..12]);
150 k[3] = mem.readIntLE(u32, key[12..16]);152 k[3] = mem.readIntSliceLittle(u32, key[12..16]);
151 k[4] = mem.readIntLE(u32, key[16..20]);153 k[4] = mem.readIntSliceLittle(u32, key[16..20]);
152 k[5] = mem.readIntLE(u32, key[20..24]);154 k[5] = mem.readIntSliceLittle(u32, key[20..24]);
153 k[6] = mem.readIntLE(u32, key[24..28]);155 k[6] = mem.readIntSliceLittle(u32, key[24..28]);
154 k[7] = mem.readIntLE(u32, key[28..32]);156 k[7] = mem.readIntSliceLittle(u32, key[28..32]);
155157
156 c[0] = @truncate(u32, counter);158 c[0] = @truncate(u32, counter);
157 c[1] = @truncate(u32, counter >> 32);159 c[1] = @truncate(u32, counter >> 32);
158 c[2] = mem.readIntLE(u32, nonce[0..4]);160 c[2] = mem.readIntSliceLittle(u32, nonce[0..4]);
159 c[3] = mem.readIntLE(u32, nonce[4..8]);161 c[3] = mem.readIntSliceLittle(u32, nonce[4..8]);
160162
161 const block_size = (1 << 6);163 const block_size = (1 << 6);
162 const big_block = (block_size << 32);164 const big_block = (block_size << 32);
...@@ -215,12 +217,12 @@ test "crypto.chacha20 test vector sunscreen" {...@@ -215,12 +217,12 @@ test "crypto.chacha20 test vector sunscreen" {
215 };217 };
216218
217 chaCha20IETF(result[0..], input[0..], 1, key, nonce);219 chaCha20IETF(result[0..], input[0..], 1, key, nonce);
218 assert(mem.eql(u8, expected_result, result));220 testing.expectEqualSlices(u8, expected_result, result);
219221
220 // Chacha20 is self-reversing.222 // Chacha20 is self-reversing.
221 var plaintext: [114]u8 = undefined;223 var plaintext: [114]u8 = undefined;
222 chaCha20IETF(plaintext[0..], result[0..], 1, key, nonce);224 chaCha20IETF(plaintext[0..], result[0..], 1, key, nonce);
223 assert(mem.compare(u8, input, plaintext) == mem.Compare.Equal);225 testing.expect(mem.compare(u8, input, plaintext) == mem.Compare.Equal);
224}226}
225227
226// https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7228// https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7
...@@ -255,7 +257,7 @@ test "crypto.chacha20 test vector 1" {...@@ -255,7 +257,7 @@ test "crypto.chacha20 test vector 1" {
255 const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 0 };257 const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 0 };
256258
257 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);259 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
258 assert(mem.eql(u8, expected_result, result));260 testing.expectEqualSlices(u8, expected_result, result);
259}261}
260262
261test "crypto.chacha20 test vector 2" {263test "crypto.chacha20 test vector 2" {
...@@ -289,7 +291,7 @@ test "crypto.chacha20 test vector 2" {...@@ -289,7 +291,7 @@ test "crypto.chacha20 test vector 2" {
289 const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 0 };291 const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 0 };
290292
291 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);293 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
292 assert(mem.eql(u8, expected_result, result));294 testing.expectEqualSlices(u8, expected_result, result);
293}295}
294296
295test "crypto.chacha20 test vector 3" {297test "crypto.chacha20 test vector 3" {
...@@ -323,7 +325,7 @@ test "crypto.chacha20 test vector 3" {...@@ -323,7 +325,7 @@ test "crypto.chacha20 test vector 3" {
323 const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 1 };325 const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 1 };
324326
325 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);327 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
326 assert(mem.eql(u8, expected_result, result));328 testing.expectEqualSlices(u8, expected_result, result);
327}329}
328330
329test "crypto.chacha20 test vector 4" {331test "crypto.chacha20 test vector 4" {
...@@ -357,7 +359,7 @@ test "crypto.chacha20 test vector 4" {...@@ -357,7 +359,7 @@ test "crypto.chacha20 test vector 4" {
357 const nonce = []u8{ 1, 0, 0, 0, 0, 0, 0, 0 };359 const nonce = []u8{ 1, 0, 0, 0, 0, 0, 0, 0 };
358360
359 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);361 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
360 assert(mem.eql(u8, expected_result, result));362 testing.expectEqualSlices(u8, expected_result, result);
361}363}
362364
363test "crypto.chacha20 test vector 5" {365test "crypto.chacha20 test vector 5" {
...@@ -429,5 +431,5 @@ test "crypto.chacha20 test vector 5" {...@@ -429,5 +431,5 @@ test "crypto.chacha20 test vector 5" {
429 };431 };
430432
431 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);433 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
432 assert(mem.eql(u8, expected_result, result));434 testing.expectEqualSlices(u8, expected_result, result);
433}435}
std/crypto/md5.zig+2-1
...@@ -112,7 +112,8 @@ pub const Md5 = struct {...@@ -112,7 +112,8 @@ pub const Md5 = struct {
112 d.round(d.buf[0..]);112 d.round(d.buf[0..]);
113113
114 for (d.s) |s, j| {114 for (d.s) |s, j| {
115 mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Little);115 // TODO https://github.com/ziglang/zig/issues/863
116 mem.writeIntSliceLittle(u32, out[4 * j .. 4 * j + 4], s);
116 }117 }
117 }118 }
118119
std/crypto/poly1305.zig+15-14
...@@ -6,8 +6,8 @@ const std = @import("../index.zig");...@@ -6,8 +6,8 @@ const std = @import("../index.zig");
6const builtin = @import("builtin");6const builtin = @import("builtin");
77
8const Endian = builtin.Endian;8const Endian = builtin.Endian;
9const readInt = std.mem.readInt;9const readIntSliceLittle = std.mem.readIntSliceLittle;
10const writeInt = std.mem.writeInt;10const writeIntSliceLittle = std.mem.writeIntSliceLittle;
1111
12pub const Poly1305 = struct {12pub const Poly1305 = struct {
13 const Self = @This();13 const Self = @This();
...@@ -59,19 +59,19 @@ pub const Poly1305 = struct {...@@ -59,19 +59,19 @@ pub const Poly1305 = struct {
59 {59 {
60 var i: usize = 0;60 var i: usize = 0;
61 while (i < 1) : (i += 1) {61 while (i < 1) : (i += 1) {
62 ctx.r[0] = readInt(key[0..4], u32, Endian.Little) & 0x0fffffff;62 ctx.r[0] = readIntSliceLittle(u32, key[0..4]) & 0x0fffffff;
63 }63 }
64 }64 }
65 {65 {
66 var i: usize = 1;66 var i: usize = 1;
67 while (i < 4) : (i += 1) {67 while (i < 4) : (i += 1) {
68 ctx.r[i] = readInt(key[i * 4 .. i * 4 + 4], u32, Endian.Little) & 0x0ffffffc;68 ctx.r[i] = readIntSliceLittle(u32, key[i * 4 .. i * 4 + 4]) & 0x0ffffffc;
69 }69 }
70 }70 }
71 {71 {
72 var i: usize = 0;72 var i: usize = 0;
73 while (i < 4) : (i += 1) {73 while (i < 4) : (i += 1) {
74 ctx.pad[i] = readInt(key[i * 4 + 16 .. i * 4 + 16 + 4], u32, Endian.Little);74 ctx.pad[i] = readIntSliceLittle(u32, key[i * 4 + 16 .. i * 4 + 16 + 4]);
75 }75 }
76 }76 }
7777
...@@ -168,10 +168,10 @@ pub const Poly1305 = struct {...@@ -168,10 +168,10 @@ pub const Poly1305 = struct {
168 const nb_blocks = nmsg.len >> 4;168 const nb_blocks = nmsg.len >> 4;
169 var i: usize = 0;169 var i: usize = 0;
170 while (i < nb_blocks) : (i += 1) {170 while (i < nb_blocks) : (i += 1) {
171 ctx.c[0] = readInt(nmsg[0..4], u32, Endian.Little);171 ctx.c[0] = readIntSliceLittle(u32, nmsg[0..4]);
172 ctx.c[1] = readInt(nmsg[4..8], u32, Endian.Little);172 ctx.c[1] = readIntSliceLittle(u32, nmsg[4..8]);
173 ctx.c[2] = readInt(nmsg[8..12], u32, Endian.Little);173 ctx.c[2] = readIntSliceLittle(u32, nmsg[8..12]);
174 ctx.c[3] = readInt(nmsg[12..16], u32, Endian.Little);174 ctx.c[3] = readIntSliceLittle(u32, nmsg[12..16]);
175 polyBlock(ctx);175 polyBlock(ctx);
176 nmsg = nmsg[16..];176 nmsg = nmsg[16..];
177 }177 }
...@@ -210,10 +210,11 @@ pub const Poly1305 = struct {...@@ -210,10 +210,11 @@ pub const Poly1305 = struct {
210 const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000210 const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000
211 const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000211 const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000
212212
213 writeInt(out[0..], @truncate(u32, uu0), Endian.Little);213 // TODO https://github.com/ziglang/zig/issues/863
214 writeInt(out[4..], @truncate(u32, uu1), Endian.Little);214 writeIntSliceLittle(u32, out[0..], @truncate(u32, uu0));
215 writeInt(out[8..], @truncate(u32, uu2), Endian.Little);215 writeIntSliceLittle(u32, out[4..], @truncate(u32, uu1));
216 writeInt(out[12..], @truncate(u32, uu3), Endian.Little);216 writeIntSliceLittle(u32, out[8..], @truncate(u32, uu2));
217 writeIntSliceLittle(u32, out[12..], @truncate(u32, uu3));
217218
218 ctx.secureZero();219 ctx.secureZero();
219 }220 }
...@@ -229,5 +230,5 @@ test "poly1305 rfc7439 vector1" {...@@ -229,5 +230,5 @@ test "poly1305 rfc7439 vector1" {
229 var mac: [16]u8 = undefined;230 var mac: [16]u8 = undefined;
230 Poly1305.create(mac[0..], msg, key);231 Poly1305.create(mac[0..], msg, key);
231232
232 std.debug.assert(std.mem.eql(u8, mac, expected_mac));233 std.testing.expectEqualSlices(u8, expected_mac, mac);
233}234}
std/crypto/sha1.zig+2-1
...@@ -109,7 +109,8 @@ pub const Sha1 = struct {...@@ -109,7 +109,8 @@ pub const Sha1 = struct {
109 d.round(d.buf[0..]);109 d.round(d.buf[0..]);
110110
111 for (d.s) |s, j| {111 for (d.s) |s, j| {
112 mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Big);112 // TODO https://github.com/ziglang/zig/issues/863
113 mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s);
113 }114 }
114 }115 }
115116
std/crypto/sha2.zig+4-2
...@@ -167,7 +167,8 @@ fn Sha2_32(comptime params: Sha2Params32) type {...@@ -167,7 +167,8 @@ fn Sha2_32(comptime params: Sha2Params32) type {
167 const rr = d.s[0 .. params.out_len / 32];167 const rr = d.s[0 .. params.out_len / 32];
168168
169 for (rr) |s, j| {169 for (rr) |s, j| {
170 mem.writeInt(out[4 * j .. 4 * j + 4], s, builtin.Endian.Big);170 // TODO https://github.com/ziglang/zig/issues/863
171 mem.writeIntSliceBig(u32, out[4 * j .. 4 * j + 4], s);
171 }172 }
172 }173 }
173174
...@@ -508,7 +509,8 @@ fn Sha2_64(comptime params: Sha2Params64) type {...@@ -508,7 +509,8 @@ fn Sha2_64(comptime params: Sha2Params64) type {
508 const rr = d.s[0 .. params.out_len / 64];509 const rr = d.s[0 .. params.out_len / 64];
509510
510 for (rr) |s, j| {511 for (rr) |s, j| {
511 mem.writeInt(out[8 * j .. 8 * j + 8], s, builtin.Endian.Big);512 // TODO https://github.com/ziglang/zig/issues/863
513 mem.writeIntSliceBig(u64, out[8 * j .. 8 * j + 8], s);
512 }514 }
513 }515 }
514516
std/crypto/sha3.zig+3-2
...@@ -120,7 +120,7 @@ fn keccak_f(comptime F: usize, d: []u8) void {...@@ -120,7 +120,7 @@ fn keccak_f(comptime F: usize, d: []u8) void {
120 var c = []const u64{0} ** 5;120 var c = []const u64{0} ** 5;
121121
122 for (s) |*r, i| {122 for (s) |*r, i| {
123 r.* = mem.readIntLE(u64, d[8 * i .. 8 * i + 8]);123 r.* = mem.readIntSliceLittle(u64, d[8 * i .. 8 * i + 8]);
124 }124 }
125125
126 comptime var x: usize = 0;126 comptime var x: usize = 0;
...@@ -167,7 +167,8 @@ fn keccak_f(comptime F: usize, d: []u8) void {...@@ -167,7 +167,8 @@ fn keccak_f(comptime F: usize, d: []u8) void {
167 }167 }
168168
169 for (s) |r, i| {169 for (s) |r, i| {
170 mem.writeInt(d[8 * i .. 8 * i + 8], r, builtin.Endian.Little);170 // TODO https://github.com/ziglang/zig/issues/863
171 mem.writeIntSliceLittle(u64, d[8 * i .. 8 * i + 8], r);
171 }172 }
172}173}
173174
std/crypto/test.zig+5-4
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const debug = @import("../debug/index.zig");1const std = @import("../index.zig");
2const mem = @import("../mem.zig");2const testing = std.testing;
3const fmt = @import("../fmt/index.zig");3const mem = std.mem;
4const fmt = std.fmt;
45
5// Hash using the specified hasher `H` asserting `expected == H(input)`.6// Hash using the specified hasher `H` asserting `expected == H(input)`.
6pub fn assertEqualHash(comptime Hasher: var, comptime expected: []const u8, input: []const u8) void {7pub fn assertEqualHash(comptime Hasher: var, comptime expected: []const u8, input: []const u8) void {
...@@ -17,5 +18,5 @@ pub fn assertEqual(comptime expected: []const u8, input: []const u8) void {...@@ -17,5 +18,5 @@ pub fn assertEqual(comptime expected: []const u8, input: []const u8) void {
17 r.* = fmt.parseInt(u8, expected[2 * i .. 2 * i + 2], 16) catch unreachable;18 r.* = fmt.parseInt(u8, expected[2 * i .. 2 * i + 2], 16) catch unreachable;
18 }19 }
1920
20 debug.assert(mem.eql(u8, expected_bytes, input));21 testing.expectEqualSlices(u8, expected_bytes, input);
21}22}
std/crypto/x25519.zig+33-32
...@@ -7,8 +7,8 @@ const builtin = @import("builtin");...@@ -7,8 +7,8 @@ const builtin = @import("builtin");
7const fmt = std.fmt;7const fmt = std.fmt;
88
9const Endian = builtin.Endian;9const Endian = builtin.Endian;
10const readInt = std.mem.readInt;10const readIntSliceLittle = std.mem.readIntSliceLittle;
11const writeInt = std.mem.writeInt;11const writeIntSliceLittle = std.mem.writeIntSliceLittle;
1212
13// Based on Supercop's ref10 implementation.13// Based on Supercop's ref10 implementation.
14pub const X25519 = struct {14pub const X25519 = struct {
...@@ -255,16 +255,16 @@ const Fe = struct {...@@ -255,16 +255,16 @@ const Fe = struct {
255255
256 var t: [10]i64 = undefined;256 var t: [10]i64 = undefined;
257257
258 t[0] = readInt(s[0..4], u32, Endian.Little);258 t[0] = readIntSliceLittle(u32, s[0..4]);
259 t[1] = readInt(s[4..7], u32, Endian.Little) << 6;259 t[1] = u32(readIntSliceLittle(u24, s[4..7])) << 6;
260 t[2] = readInt(s[7..10], u32, Endian.Little) << 5;260 t[2] = u32(readIntSliceLittle(u24, s[7..10])) << 5;
261 t[3] = readInt(s[10..13], u32, Endian.Little) << 3;261 t[3] = u32(readIntSliceLittle(u24, s[10..13])) << 3;
262 t[4] = readInt(s[13..16], u32, Endian.Little) << 2;262 t[4] = u32(readIntSliceLittle(u24, s[13..16])) << 2;
263 t[5] = readInt(s[16..20], u32, Endian.Little);263 t[5] = readIntSliceLittle(u32, s[16..20]);
264 t[6] = readInt(s[20..23], u32, Endian.Little) << 7;264 t[6] = u32(readIntSliceLittle(u24, s[20..23])) << 7;
265 t[7] = readInt(s[23..26], u32, Endian.Little) << 5;265 t[7] = u32(readIntSliceLittle(u24, s[23..26])) << 5;
266 t[8] = readInt(s[26..29], u32, Endian.Little) << 4;266 t[8] = u32(readIntSliceLittle(u24, s[26..29])) << 4;
267 t[9] = (readInt(s[29..32], u32, Endian.Little) & 0x7fffff) << 2;267 t[9] = (u32(readIntSliceLittle(u24, s[29..32])) & 0x7fffff) << 2;
268268
269 carry1(h, t[0..]);269 carry1(h, t[0..]);
270 }270 }
...@@ -544,14 +544,15 @@ const Fe = struct {...@@ -544,14 +544,15 @@ const Fe = struct {
544 ut[i] = @bitCast(u32, @intCast(i32, t[i]));544 ut[i] = @bitCast(u32, @intCast(i32, t[i]));
545 }545 }
546546
547 writeInt(s[0..], (ut[0] >> 0) | (ut[1] << 26), Endian.Little);547 // TODO https://github.com/ziglang/zig/issues/863
548 writeInt(s[4..], (ut[1] >> 6) | (ut[2] << 19), Endian.Little);548 writeIntSliceLittle(u32, s[0..4], (ut[0] >> 0) | (ut[1] << 26));
549 writeInt(s[8..], (ut[2] >> 13) | (ut[3] << 13), Endian.Little);549 writeIntSliceLittle(u32, s[4..8], (ut[1] >> 6) | (ut[2] << 19));
550 writeInt(s[12..], (ut[3] >> 19) | (ut[4] << 6), Endian.Little);550 writeIntSliceLittle(u32, s[8..12], (ut[2] >> 13) | (ut[3] << 13));
551 writeInt(s[16..], (ut[5] >> 0) | (ut[6] << 25), Endian.Little);551 writeIntSliceLittle(u32, s[12..16], (ut[3] >> 19) | (ut[4] << 6));
552 writeInt(s[20..], (ut[6] >> 7) | (ut[7] << 19), Endian.Little);552 writeIntSliceLittle(u32, s[16..20], (ut[5] >> 0) | (ut[6] << 25));
553 writeInt(s[24..], (ut[7] >> 13) | (ut[8] << 12), Endian.Little);553 writeIntSliceLittle(u32, s[20..24], (ut[6] >> 7) | (ut[7] << 19));
554 writeInt(s[28..], (ut[8] >> 20) | (ut[9] << 6), Endian.Little);554 writeIntSliceLittle(u32, s[24..28], (ut[7] >> 13) | (ut[8] << 12));
555 writeIntSliceLittle(u32, s[28..], (ut[8] >> 20) | (ut[9] << 6));
555556
556 std.mem.secureZero(i64, t[0..]);557 std.mem.secureZero(i64, t[0..]);
557 }558 }
...@@ -580,8 +581,8 @@ test "x25519 public key calculation from secret key" {...@@ -580,8 +581,8 @@ test "x25519 public key calculation from secret key" {
580 var pk_calculated: [32]u8 = undefined;581 var pk_calculated: [32]u8 = undefined;
581 try fmt.hexToBytes(sk[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");582 try fmt.hexToBytes(sk[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");
582 try fmt.hexToBytes(pk_expected[0..], "f1814f0e8ff1043d8a44d25babff3cedcae6c22c3edaa48f857ae70de2baae50");583 try fmt.hexToBytes(pk_expected[0..], "f1814f0e8ff1043d8a44d25babff3cedcae6c22c3edaa48f857ae70de2baae50");
583 std.debug.assert(X25519.createPublicKey(pk_calculated[0..], sk));584 std.testing.expect(X25519.createPublicKey(pk_calculated[0..], sk));
584 std.debug.assert(std.mem.eql(u8, pk_calculated, pk_expected));585 std.testing.expect(std.mem.eql(u8, pk_calculated, pk_expected));
585}586}
586587
587test "x25519 rfc7748 vector1" {588test "x25519 rfc7748 vector1" {
...@@ -592,8 +593,8 @@ test "x25519 rfc7748 vector1" {...@@ -592,8 +593,8 @@ test "x25519 rfc7748 vector1" {
592593
593 var output: [32]u8 = undefined;594 var output: [32]u8 = undefined;
594595
595 std.debug.assert(X25519.create(output[0..], secret_key, public_key));596 std.testing.expect(X25519.create(output[0..], secret_key, public_key));
596 std.debug.assert(std.mem.eql(u8, output, expected_output));597 std.testing.expect(std.mem.eql(u8, output, expected_output));
597}598}
598599
599test "x25519 rfc7748 vector2" {600test "x25519 rfc7748 vector2" {
...@@ -604,8 +605,8 @@ test "x25519 rfc7748 vector2" {...@@ -604,8 +605,8 @@ test "x25519 rfc7748 vector2" {
604605
605 var output: [32]u8 = undefined;606 var output: [32]u8 = undefined;
606607
607 std.debug.assert(X25519.create(output[0..], secret_key, public_key));608 std.testing.expect(X25519.create(output[0..], secret_key, public_key));
608 std.debug.assert(std.mem.eql(u8, output, expected_output));609 std.testing.expect(std.mem.eql(u8, output, expected_output));
609}610}
610611
611test "x25519 rfc7748 one iteration" {612test "x25519 rfc7748 one iteration" {
...@@ -618,13 +619,13 @@ test "x25519 rfc7748 one iteration" {...@@ -618,13 +619,13 @@ test "x25519 rfc7748 one iteration" {
618 var i: usize = 0;619 var i: usize = 0;
619 while (i < 1) : (i += 1) {620 while (i < 1) : (i += 1) {
620 var output: [32]u8 = undefined;621 var output: [32]u8 = undefined;
621 std.debug.assert(X25519.create(output[0..], k, u));622 std.testing.expect(X25519.create(output[0..], k, u));
622623
623 std.mem.copy(u8, u[0..], k[0..]);624 std.mem.copy(u8, u[0..], k[0..]);
624 std.mem.copy(u8, k[0..], output[0..]);625 std.mem.copy(u8, k[0..], output[0..]);
625 }626 }
626627
627 std.debug.assert(std.mem.eql(u8, k[0..], expected_output));628 std.testing.expect(std.mem.eql(u8, k[0..], expected_output));
628}629}
629630
630test "x25519 rfc7748 1,000 iterations" {631test "x25519 rfc7748 1,000 iterations" {
...@@ -642,13 +643,13 @@ test "x25519 rfc7748 1,000 iterations" {...@@ -642,13 +643,13 @@ test "x25519 rfc7748 1,000 iterations" {
642 var i: usize = 0;643 var i: usize = 0;
643 while (i < 1000) : (i += 1) {644 while (i < 1000) : (i += 1) {
644 var output: [32]u8 = undefined;645 var output: [32]u8 = undefined;
645 std.debug.assert(X25519.create(output[0..], k, u));646 std.testing.expect(X25519.create(output[0..], k, u));
646647
647 std.mem.copy(u8, u[0..], k[0..]);648 std.mem.copy(u8, u[0..], k[0..]);
648 std.mem.copy(u8, k[0..], output[0..]);649 std.mem.copy(u8, k[0..], output[0..]);
649 }650 }
650651
651 std.debug.assert(std.mem.eql(u8, k[0..], expected_output));652 std.testing.expect(std.mem.eql(u8, k[0..], expected_output));
652}653}
653654
654test "x25519 rfc7748 1,000,000 iterations" {655test "x25519 rfc7748 1,000,000 iterations" {
...@@ -665,11 +666,11 @@ test "x25519 rfc7748 1,000,000 iterations" {...@@ -665,11 +666,11 @@ test "x25519 rfc7748 1,000,000 iterations" {
665 var i: usize = 0;666 var i: usize = 0;
666 while (i < 1000000) : (i += 1) {667 while (i < 1000000) : (i += 1) {
667 var output: [32]u8 = undefined;668 var output: [32]u8 = undefined;
668 std.debug.assert(X25519.create(output[0..], k, u));669 std.testing.expect(X25519.create(output[0..], k, u));
669670
670 std.mem.copy(u8, u[0..], k[0..]);671 std.mem.copy(u8, u[0..], k[0..]);
671 std.mem.copy(u8, k[0..], output[0..]);672 std.mem.copy(u8, k[0..], output[0..]);
672 }673 }
673674
674 std.debug.assert(std.mem.eql(u8, k[0..], expected_output));675 std.testing.expect(std.mem.eql(u8, k[0..], expected_output));
675}676}
std/cstr.zig+3-3
...@@ -2,7 +2,7 @@ const std = @import("index.zig");...@@ -2,7 +2,7 @@ const std = @import("index.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const debug = std.debug;3const debug = std.debug;
4const mem = std.mem;4const mem = std.mem;
5const assert = debug.assert;5const testing = std.testing;
66
7pub const line_sep = switch (builtin.os) {7pub const line_sep = switch (builtin.os) {
8 builtin.Os.windows => "\r\n",8 builtin.Os.windows => "\r\n",
...@@ -42,8 +42,8 @@ test "cstr fns" {...@@ -42,8 +42,8 @@ test "cstr fns" {
42}42}
4343
44fn testCStrFnsImpl() void {44fn testCStrFnsImpl() void {
45 assert(cmp(c"aoeu", c"aoez") == -1);45 testing.expect(cmp(c"aoeu", c"aoez") == -1);
46 assert(len(c"123456789") == 9);46 testing.expect(len(c"123456789") == 9);
47}47}
4848
49/// Returns a mutable slice with 1 more byte of length which is a null byte.49/// Returns a mutable slice with 1 more byte of length which is a null byte.
std/debug/index.zig+96-94
...@@ -37,7 +37,6 @@ const Module = struct {...@@ -37,7 +37,6 @@ const Module = struct {
37var stderr_file: os.File = undefined;37var stderr_file: os.File = undefined;
38var stderr_file_out_stream: os.File.OutStream = undefined;38var stderr_file_out_stream: os.File.OutStream = undefined;
3939
40/// TODO multithreaded awareness
41var stderr_stream: ?*io.OutStream(os.File.WriteError) = null;40var stderr_stream: ?*io.OutStream(os.File.WriteError) = null;
42var stderr_mutex = std.Mutex.init();41var stderr_mutex = std.Mutex.init();
43pub fn warn(comptime fmt: []const u8, args: ...) void {42pub fn warn(comptime fmt: []const u8, args: ...) void {
...@@ -108,37 +107,15 @@ pub fn dumpStackTrace(stack_trace: *const builtin.StackTrace) void {...@@ -108,37 +107,15 @@ pub fn dumpStackTrace(stack_trace: *const builtin.StackTrace) void {
108/// This function invokes undefined behavior when `ok` is `false`.107/// This function invokes undefined behavior when `ok` is `false`.
109/// In Debug and ReleaseSafe modes, calls to this function are always108/// In Debug and ReleaseSafe modes, calls to this function are always
110/// generated, and the `unreachable` statement triggers a panic.109/// generated, and the `unreachable` statement triggers a panic.
111/// In ReleaseFast and ReleaseSmall modes, calls to this function can be110/// In ReleaseFast and ReleaseSmall modes, calls to this function are
112/// optimized away.111/// optimized away, and in fact the optimizer is able to use the assertion
112/// in its heuristics.
113/// Inside a test block, it is best to use the `std.testing` module rather
114/// than this function, because this function may not detect a test failure
115/// in ReleaseFast and ReleaseSafe mode. Outside of a test block, this assert
116/// function is the correct function to use.
113pub fn assert(ok: bool) void {117pub fn assert(ok: bool) void {
114 if (!ok) {118 if (!ok) unreachable; // assertion failure
115 // In ReleaseFast test mode, we still want assert(false) to crash, so
116 // we insert an explicit call to @panic instead of unreachable.
117 // TODO we should use `assertOrPanic` in tests and remove this logic.
118 if (builtin.is_test) {
119 @panic("assertion failure");
120 } else {
121 unreachable; // assertion failure
122 }
123 }
124}
125
126/// TODO: add `==` operator for `error_union == error_set`, and then
127/// remove this function
128pub fn assertError(value: var, expected_error: anyerror) void {
129 if (value) {
130 @panic("expected error");
131 } else |actual_error| {
132 assert(actual_error == expected_error);
133 }
134}
135
136/// Call this function when you want to panic if the condition is not true.
137/// If `ok` is `false`, this function will panic in every release mode.
138pub fn assertOrPanic(ok: bool) void {
139 if (!ok) {
140 @panic("assertion failure");
141 }
142}119}
143120
144pub fn panic(comptime format: []const u8, args: ...) noreturn {121pub fn panic(comptime format: []const u8, args: ...) noreturn {
...@@ -247,8 +224,7 @@ pub fn writeCurrentStackTraceWindows(...@@ -247,8 +224,7 @@ pub fn writeCurrentStackTraceWindows(
247 start_addr: ?usize,224 start_addr: ?usize,
248) !void {225) !void {
249 var addr_buf: [1024]usize = undefined;226 var addr_buf: [1024]usize = undefined;
250 const casted_len = @intCast(u32, addr_buf.len); // TODO shouldn't need this cast227 const n = windows.RtlCaptureStackBackTrace(0, addr_buf.len, @ptrCast(**c_void, &addr_buf), null);
251 const n = windows.RtlCaptureStackBackTrace(0, casted_len, @ptrCast(**c_void, &addr_buf), null);
252 const addrs = addr_buf[0..n];228 const addrs = addr_buf[0..n];
253 var start_i: usize = if (start_addr) |saddr| blk: {229 var start_i: usize = if (start_addr) |saddr| blk: {
254 for (addrs) |addr, i| {230 for (addrs) |addr, i| {
...@@ -264,7 +240,7 @@ pub fn writeCurrentStackTraceWindows(...@@ -264,7 +240,7 @@ pub fn writeCurrentStackTraceWindows(
264pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {240pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {
265 switch (builtin.os) {241 switch (builtin.os) {
266 builtin.Os.macosx => return printSourceAtAddressMacOs(debug_info, out_stream, address, tty_color),242 builtin.Os.macosx => return printSourceAtAddressMacOs(debug_info, out_stream, address, tty_color),
267 builtin.Os.linux => return printSourceAtAddressLinux(debug_info, out_stream, address, tty_color),243 builtin.Os.linux, builtin.Os.freebsd => return printSourceAtAddressLinux(debug_info, out_stream, address, tty_color),
268 builtin.Os.windows => return printSourceAtAddressWindows(debug_info, out_stream, address, tty_color),244 builtin.Os.windows => return printSourceAtAddressWindows(debug_info, out_stream, address, tty_color),
269 else => return error.UnsupportedOperatingSystem,245 else => return error.UnsupportedOperatingSystem,
270 }246 }
...@@ -338,50 +314,74 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres...@@ -338,50 +314,74 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
338314
339 switch (subsect_hdr.Kind) {315 switch (subsect_hdr.Kind) {
340 pdb.DebugSubsectionKind.Lines => {316 pdb.DebugSubsectionKind.Lines => {
341 var line_index: usize = sect_offset;317 var line_index = sect_offset;
342318
343 const line_hdr = @ptrCast(*pdb.LineFragmentHeader, &subsect_info[line_index]);319 const line_hdr = @ptrCast(*pdb.LineFragmentHeader, &subsect_info[line_index]);
344 if (line_hdr.RelocSegment == 0) return error.MissingDebugInfo;320 if (line_hdr.RelocSegment == 0) return error.MissingDebugInfo;
345 line_index += @sizeOf(pdb.LineFragmentHeader);321 line_index += @sizeOf(pdb.LineFragmentHeader);
346
347 const block_hdr = @ptrCast(*pdb.LineBlockFragmentHeader, &subsect_info[line_index]);
348 line_index += @sizeOf(pdb.LineBlockFragmentHeader);
349
350 const has_column = line_hdr.Flags.LF_HaveColumns;
351
352 const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset;322 const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset;
353 const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize;323 const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize;
354 if (relative_address >= frag_vaddr_start and relative_address < frag_vaddr_end) {324
355 var line_i: usize = 0;325 // There is an unknown number of LineBlockFragmentHeaders (and their accompanying line and column records)
326 // from now on. We will iterate through them, and eventually find a LineInfo that we're interested in,
327 // breaking out to :subsections. If not, we will make sure to not read anything outside of this subsection.
328 const subsection_end_index = sect_offset + subsect_hdr.Length;
329 while (line_index < subsection_end_index) {
330 const block_hdr = @ptrCast(*pdb.LineBlockFragmentHeader, &subsect_info[line_index]);
331 line_index += @sizeOf(pdb.LineBlockFragmentHeader);
356 const start_line_index = line_index;332 const start_line_index = line_index;
357 while (line_i < block_hdr.NumLines) : (line_i += 1) {333
358 const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[line_index]);334 const has_column = line_hdr.Flags.LF_HaveColumns;
359 line_index += @sizeOf(pdb.LineNumberEntry);335
360 const flags = @ptrCast(*pdb.LineNumberEntry.Flags, &line_num_entry.Flags);336 if (relative_address >= frag_vaddr_start and relative_address < frag_vaddr_end) {
361 const vaddr_start = frag_vaddr_start + line_num_entry.Offset;337 // All line entries are stored inside their line block by ascending start address.
362 const vaddr_end = if (flags.End == 0) frag_vaddr_end else vaddr_start + flags.End;338 // Heuristic: we want to find the last line entry that has a vaddr_start <= relative_address.
363 if (relative_address >= vaddr_start and relative_address < vaddr_end) {339 // This is done with a simple linear search.
340 var line_i: u32 = 0;
341 while (line_i < block_hdr.NumLines) : (line_i += 1) {
342 const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[line_index]);
343 line_index += @sizeOf(pdb.LineNumberEntry);
344
345 const vaddr_start = frag_vaddr_start + line_num_entry.Offset;
346 if (relative_address <= vaddr_start) {
347 break;
348 }
349 }
350
351 // line_i == 0 would mean that no matching LineNumberEntry was found.
352 if (line_i > 0) {
364 const subsect_index = checksum_offset + block_hdr.NameIndex;353 const subsect_index = checksum_offset + block_hdr.NameIndex;
365 const chksum_hdr = @ptrCast(*pdb.FileChecksumEntryHeader, &mod.subsect_info[subsect_index]);354 const chksum_hdr = @ptrCast(*pdb.FileChecksumEntryHeader, &mod.subsect_info[subsect_index]);
366 const strtab_offset = @sizeOf(pdb.PDBStringTableHeader) + chksum_hdr.FileNameOffset;355 const strtab_offset = @sizeOf(pdb.PDBStringTableHeader) + chksum_hdr.FileNameOffset;
367 try di.pdb.string_table.seekTo(strtab_offset);356 try di.pdb.string_table.seekTo(strtab_offset);
368 const source_file_name = try di.pdb.string_table.readNullTermString(allocator);357 const source_file_name = try di.pdb.string_table.readNullTermString(allocator);
369 const line = flags.Start;358
359 const line_entry_idx = line_i - 1;
360
370 const column = if (has_column) blk: {361 const column = if (has_column) blk: {
371 line_index = start_line_index + @sizeOf(pdb.LineNumberEntry) * block_hdr.NumLines;362 const start_col_index = start_line_index + @sizeOf(pdb.LineNumberEntry) * block_hdr.NumLines;
372 line_index += @sizeOf(pdb.ColumnNumberEntry) * line_i;363 const col_index = start_col_index + @sizeOf(pdb.ColumnNumberEntry) * line_entry_idx;
373 const col_num_entry = @ptrCast(*pdb.ColumnNumberEntry, &subsect_info[line_index]);364 const col_num_entry = @ptrCast(*pdb.ColumnNumberEntry, &subsect_info[col_index]);
374 break :blk col_num_entry.StartColumn;365 break :blk col_num_entry.StartColumn;
375 } else 0;366 } else 0;
367
368 const found_line_index = start_line_index + line_entry_idx * @sizeOf(pdb.LineNumberEntry);
369 const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[found_line_index]);
370 const flags = @ptrCast(*pdb.LineNumberEntry.Flags, &line_num_entry.Flags);
371
376 break :subsections LineInfo{372 break :subsections LineInfo{
377 .allocator = allocator,373 .allocator = allocator,
378 .file_name = source_file_name,374 .file_name = source_file_name,
379 .line = line,375 .line = flags.Start,
380 .column = column,376 .column = column,
381 };377 };
382 }378 }
383 }379 }
384 break :subsections null;380 }
381
382 // Checking that we are not reading garbage after the (possibly) multiple block fragments.
383 if (line_index != subsection_end_index) {
384 return error.InvalidDebugInfo;
385 }385 }
386 },386 },
387 else => {},387 else => {},
...@@ -523,7 +523,7 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void {...@@ -523,7 +523,7 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void {
523523
524 const modi = di.pdb.getStreamById(mod.mod_info.ModuleSymStream) orelse return error.MissingDebugInfo;524 const modi = di.pdb.getStreamById(mod.mod_info.ModuleSymStream) orelse return error.MissingDebugInfo;
525525
526 const signature = try modi.stream.readIntLe(u32);526 const signature = try modi.stream.readIntLittle(u32);
527 if (signature != 4)527 if (signature != 4)
528 return error.InvalidDebugInfo;528 return error.InvalidDebugInfo;
529529
...@@ -717,7 +717,7 @@ pub const OpenSelfDebugInfoError = error{...@@ -717,7 +717,7 @@ pub const OpenSelfDebugInfoError = error{
717717
718pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo {718pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo {
719 switch (builtin.os) {719 switch (builtin.os) {
720 builtin.Os.linux => return openSelfDebugInfoLinux(allocator),720 builtin.Os.linux, builtin.Os.freebsd => return openSelfDebugInfoLinux(allocator),
721 builtin.Os.macosx, builtin.Os.ios => return openSelfDebugInfoMacOs(allocator),721 builtin.Os.macosx, builtin.Os.ios => return openSelfDebugInfoMacOs(allocator),
722 builtin.Os.windows => return openSelfDebugInfoWindows(allocator),722 builtin.Os.windows => return openSelfDebugInfoWindows(allocator),
723 else => return error.UnsupportedOperatingSystem,723 else => return error.UnsupportedOperatingSystem,
...@@ -728,7 +728,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {...@@ -728,7 +728,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
728 const self_file = try os.openSelfExe();728 const self_file = try os.openSelfExe();
729 defer self_file.close();729 defer self_file.close();
730730
731 const coff_obj = try allocator.createOne(coff.Coff);731 const coff_obj = try allocator.create(coff.Coff);
732 coff_obj.* = coff.Coff{732 coff_obj.* = coff.Coff{
733 .in_file = self_file,733 .in_file = self_file,
734 .allocator = allocator,734 .allocator = allocator,
...@@ -752,14 +752,14 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {...@@ -752,14 +752,14 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
752 const len = try di.coff.getPdbPath(path_buf[0..]);752 const len = try di.coff.getPdbPath(path_buf[0..]);
753 const raw_path = path_buf[0..len];753 const raw_path = path_buf[0..len];
754754
755 const path = try os.path.resolve(allocator, raw_path);755 const path = try os.path.resolve(allocator, [][]const u8{raw_path});
756756
757 try di.pdb.openFile(di.coff, path);757 try di.pdb.openFile(di.coff, path);
758758
759 var pdb_stream = di.pdb.getStream(pdb.StreamType.Pdb) orelse return error.InvalidDebugInfo;759 var pdb_stream = di.pdb.getStream(pdb.StreamType.Pdb) orelse return error.InvalidDebugInfo;
760 const version = try pdb_stream.stream.readIntLe(u32);760 const version = try pdb_stream.stream.readIntLittle(u32);
761 const signature = try pdb_stream.stream.readIntLe(u32);761 const signature = try pdb_stream.stream.readIntLittle(u32);
762 const age = try pdb_stream.stream.readIntLe(u32);762 const age = try pdb_stream.stream.readIntLittle(u32);
763 var guid: [16]u8 = undefined;763 var guid: [16]u8 = undefined;
764 try pdb_stream.stream.readNoEof(guid[0..]);764 try pdb_stream.stream.readNoEof(guid[0..]);
765 if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age)765 if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age)
...@@ -767,7 +767,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {...@@ -767,7 +767,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
767 // We validated the executable and pdb match.767 // We validated the executable and pdb match.
768768
769 const string_table_index = str_tab_index: {769 const string_table_index = str_tab_index: {
770 const name_bytes_len = try pdb_stream.stream.readIntLe(u32);770 const name_bytes_len = try pdb_stream.stream.readIntLittle(u32);
771 const name_bytes = try allocator.alloc(u8, name_bytes_len);771 const name_bytes = try allocator.alloc(u8, name_bytes_len);
772 try pdb_stream.stream.readNoEof(name_bytes);772 try pdb_stream.stream.readNoEof(name_bytes);
773773
...@@ -797,8 +797,8 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {...@@ -797,8 +797,8 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
797 };797 };
798 const bucket_list = try allocator.alloc(Bucket, present.len);798 const bucket_list = try allocator.alloc(Bucket, present.len);
799 for (present) |_| {799 for (present) |_| {
800 const name_offset = try pdb_stream.stream.readIntLe(u32);800 const name_offset = try pdb_stream.stream.readIntLittle(u32);
801 const name_index = try pdb_stream.stream.readIntLe(u32);801 const name_index = try pdb_stream.stream.readIntLittle(u32);
802 const name = mem.toSlice(u8, name_bytes.ptr + name_offset);802 const name = mem.toSlice(u8, name_bytes.ptr + name_offset);
803 if (mem.eql(u8, name, "/names")) {803 if (mem.eql(u8, name, "/names")) {
804 break :str_tab_index name_index;804 break :str_tab_index name_index;
...@@ -859,7 +859,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {...@@ -859,7 +859,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
859 var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator);859 var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator);
860 var sect_cont_offset: usize = 0;860 var sect_cont_offset: usize = 0;
861 if (section_contrib_size != 0) {861 if (section_contrib_size != 0) {
862 const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLe(u32));862 const ver = @intToEnum(pdb.SectionContrSubstreamVersion, try dbi.stream.readIntLittle(u32));
863 if (ver != pdb.SectionContrSubstreamVersion.Ver60)863 if (ver != pdb.SectionContrSubstreamVersion.Ver60)
864 return error.InvalidDebugInfo;864 return error.InvalidDebugInfo;
865 sect_cont_offset += @sizeOf(u32);865 sect_cont_offset += @sizeOf(u32);
...@@ -879,11 +879,11 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {...@@ -879,11 +879,11 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
879}879}
880880
881fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {881fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {
882 const num_words = try stream.readIntLe(u32);882 const num_words = try stream.readIntLittle(u32);
883 var word_i: usize = 0;883 var word_i: usize = 0;
884 var list = ArrayList(usize).init(allocator);884 var list = ArrayList(usize).init(allocator);
885 while (word_i != num_words) : (word_i += 1) {885 while (word_i != num_words) : (word_i += 1) {
886 const word = try stream.readIntLe(u32);886 const word = try stream.readIntLittle(u32);
887 var bit_i: u5 = 0;887 var bit_i: u5 = 0;
888 while (true) : (bit_i += 1) {888 while (true) : (bit_i += 1) {
889 if (word & (u32(1) << bit_i) != 0) {889 if (word & (u32(1) << bit_i) != 0) {
...@@ -1013,7 +1013,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {...@@ -1013,7 +1013,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
1013 }1013 }
1014 }1014 }
1015 }1015 }
1016 const sentinel = try allocator.createOne(macho.nlist_64);1016 const sentinel = try allocator.create(macho.nlist_64);
1017 sentinel.* = macho.nlist_64{1017 sentinel.* = macho.nlist_64{
1018 .n_strx = 0,1018 .n_strx = 0,
1019 .n_type = 36,1019 .n_type = 36,
...@@ -1135,14 +1135,13 @@ pub const DebugInfo = switch (builtin.os) {...@@ -1135,14 +1135,13 @@ pub const DebugInfo = switch (builtin.os) {
1135 return self.ofiles.allocator;1135 return self.ofiles.allocator;
1136 }1136 }
1137 },1137 },
1138 builtin.Os.windows => struct {1138 builtin.Os.uefi, builtin.Os.windows => struct {
1139 pdb: pdb.Pdb,1139 pdb: pdb.Pdb,
1140 coff: *coff.Coff,1140 coff: *coff.Coff,
1141 sect_contribs: []pdb.SectionContribEntry,1141 sect_contribs: []pdb.SectionContribEntry,
1142 modules: []Module,1142 modules: []Module,
1143 },1143 },
1144 builtin.Os.linux => DwarfInfo,1144 builtin.Os.linux, builtin.Os.freebsd => DwarfInfo,
1145 builtin.Os.freebsd => struct {},
1146 else => @compileError("Unsupported OS"),1145 else => @compileError("Unsupported OS"),
1147};1146};
11481147
...@@ -1200,7 +1199,7 @@ const Constant = struct {...@@ -1200,7 +1199,7 @@ const Constant = struct {
1200 fn asUnsignedLe(self: *const Constant) !u64 {1199 fn asUnsignedLe(self: *const Constant) !u64 {
1201 if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo;1200 if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo;
1202 if (self.signed) return error.InvalidDebugInfo;1201 if (self.signed) return error.InvalidDebugInfo;
1203 return mem.readInt(self.payload, u64, builtin.Endian.Little);1202 return mem.readVarInt(u64, self.payload, builtin.Endian.Little);
1204 }1203 }
1205};1204};
12061205
...@@ -1331,7 +1330,7 @@ const LineNumberProgram = struct {...@@ -1331,7 +1330,7 @@ const LineNumberProgram = struct {
1331 return error.InvalidDebugInfo;1330 return error.InvalidDebugInfo;
1332 } else1331 } else
1333 self.include_dirs[file_entry.dir_index];1332 self.include_dirs[file_entry.dir_index];
1334 const file_name = try os.path.join(self.file_entries.allocator, dir_name, file_entry.file_name);1333 const file_name = try os.path.join(self.file_entries.allocator, [][]const u8{ dir_name, file_entry.file_name });
1335 errdefer self.file_entries.allocator.free(file_name);1334 errdefer self.file_entries.allocator.free(file_name);
1336 return LineInfo{1335 return LineInfo{
1337 .line = if (self.prev_line >= 0) @intCast(usize, self.prev_line) else 0,1336 .line = if (self.prev_line >= 0) @intCast(usize, self.prev_line) else 0,
...@@ -1381,7 +1380,7 @@ fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize...@@ -1381,7 +1380,7 @@ fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize
1381}1380}
13821381
1383fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {1382fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
1384 const block_len = try in_stream.readVarInt(builtin.Endian.Little, usize, size);1383 const block_len = try in_stream.readVarInt(usize, builtin.Endian.Little, size);
1385 return parseFormValueBlockLen(allocator, in_stream, block_len);1384 return parseFormValueBlockLen(allocator, in_stream, block_len);
1386}1385}
13871386
...@@ -1395,11 +1394,11 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo...@@ -1395,11 +1394,11 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo
1395}1394}
13961395
1397fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {1396fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {
1398 return if (is_64) try in_stream.readIntLe(u64) else u64(try in_stream.readIntLe(u32));1397 return if (is_64) try in_stream.readIntLittle(u64) else u64(try in_stream.readIntLittle(u32));
1399}1398}
14001399
1401fn parseFormValueTargetAddrSize(in_stream: var) !u64 {1400fn parseFormValueTargetAddrSize(in_stream: var) !u64 {
1402 return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLe(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLe(u64) else unreachable;1401 return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLittle(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLittle(u64) else unreachable;
1403}1402}
14041403
1405fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {1404fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
...@@ -1408,7 +1407,7 @@ fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize)...@@ -1408,7 +1407,7 @@ fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize)
1408}1407}
14091408
1410fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue {1409fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue {
1411 const block_len = try in_stream.readIntLe(T);1410 const block_len = try in_stream.readIntLittle(T);
1412 return parseFormValueRefLen(allocator, in_stream, block_len);1411 return parseFormValueRefLen(allocator, in_stream, block_len);
1413}1412}
14141413
...@@ -1450,7 +1449,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64...@@ -1450,7 +1449,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
1450 },1449 },
14511450
1452 DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },1451 DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
1453 DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLe(u64) },1452 DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLittle(u64) },
14541453
1455 DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },1454 DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },
1456 DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },1455 DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
...@@ -1747,11 +1746,11 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr...@@ -1747,11 +1746,11 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr
1747 continue;1746 continue;
1748 }1747 }
17491748
1750 const version = try di.dwarf_in_stream.readInt(di.endian, u16);1749 const version = try di.dwarf_in_stream.readInt(u16, di.endian);
1751 // TODO support 3 and 51750 // TODO support 3 and 5
1752 if (version != 2 and version != 4) return error.InvalidDebugInfo;1751 if (version != 2 and version != 4) return error.InvalidDebugInfo;
17531752
1754 const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(di.endian, u64) else try di.dwarf_in_stream.readInt(di.endian, u32);1753 const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian);
1755 const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length;1754 const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length;
17561755
1757 const minimum_instruction_length = try di.dwarf_in_stream.readByte();1756 const minimum_instruction_length = try di.dwarf_in_stream.readByte();
...@@ -1820,7 +1819,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr...@@ -1820,7 +1819,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr
1820 return error.MissingDebugInfo;1819 return error.MissingDebugInfo;
1821 },1820 },
1822 DW.LNE_set_address => {1821 DW.LNE_set_address => {
1823 const addr = try di.dwarf_in_stream.readInt(di.endian, usize);1822 const addr = try di.dwarf_in_stream.readInt(usize, di.endian);
1824 prog.address = addr;1823 prog.address = addr;
1825 },1824 },
1826 DW.LNE_define_file => {1825 DW.LNE_define_file => {
...@@ -1882,7 +1881,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr...@@ -1882,7 +1881,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr
1882 prog.address += inc_addr;1881 prog.address += inc_addr;
1883 },1882 },
1884 DW.LNS_fixed_advance_pc => {1883 DW.LNS_fixed_advance_pc => {
1885 const arg = try di.dwarf_in_stream.readInt(di.endian, u16);1884 const arg = try di.dwarf_in_stream.readInt(u16, di.endian);
1886 prog.address += arg;1885 prog.address += arg;
1887 },1886 },
1888 DW.LNS_set_prologue_end => {},1887 DW.LNS_set_prologue_end => {},
...@@ -1914,10 +1913,10 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void {...@@ -1914,10 +1913,10 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void {
1914 if (unit_length == 0) return;1913 if (unit_length == 0) return;
1915 const next_offset = unit_length + (if (is_64) usize(12) else usize(4));1914 const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
19161915
1917 const version = try di.dwarf_in_stream.readInt(di.endian, u16);1916 const version = try di.dwarf_in_stream.readInt(u16, di.endian);
1918 if (version < 2 or version > 5) return error.InvalidDebugInfo;1917 if (version < 2 or version > 5) return error.InvalidDebugInfo;
19191918
1920 const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(di.endian, u64) else try di.dwarf_in_stream.readInt(di.endian, u32);1919 const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian);
19211920
1922 const address_size = try di.dwarf_in_stream.readByte();1921 const address_size = try di.dwarf_in_stream.readByte();
1923 if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;1922 if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
...@@ -1927,7 +1926,8 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void {...@@ -1927,7 +1926,8 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void {
19271926
1928 try di.dwarf_seekable_stream.seekTo(compile_unit_pos);1927 try di.dwarf_seekable_stream.seekTo(compile_unit_pos);
19291928
1930 const compile_unit_die = try di.allocator().create(try parseDie(di, abbrev_table, is_64));1929 const compile_unit_die = try di.allocator().create(Die);
1930 compile_unit_die.* = try parseDie(di, abbrev_table, is_64);
19311931
1932 if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo;1932 if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo;
19331933
...@@ -1978,8 +1978,8 @@ fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit {...@@ -1978,8 +1978,8 @@ fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit {
1978 if (di.debug_ranges) |debug_ranges| {1978 if (di.debug_ranges) |debug_ranges| {
1979 try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset);1979 try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset);
1980 while (true) {1980 while (true) {
1981 const begin_addr = try di.dwarf_in_stream.readIntLe(usize);1981 const begin_addr = try di.dwarf_in_stream.readIntLittle(usize);
1982 const end_addr = try di.dwarf_in_stream.readIntLe(usize);1982 const end_addr = try di.dwarf_in_stream.readIntLittle(usize);
1983 if (begin_addr == 0 and end_addr == 0) {1983 if (begin_addr == 0 and end_addr == 0) {
1984 break;1984 break;
1985 }1985 }
...@@ -2001,7 +2001,8 @@ fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit {...@@ -2001,7 +2001,8 @@ fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit {
2001}2001}
20022002
2003fn readIntMem(ptr: *[*]const u8, comptime T: type, endian: builtin.Endian) T {2003fn readIntMem(ptr: *[*]const u8, comptime T: type, endian: builtin.Endian) T {
2004 const result = mem.readInt(ptr.*[0..@sizeOf(T)], T, endian);2004 // TODO https://github.com/ziglang/zig/issues/863
2005 const result = mem.readIntSlice(T, ptr.*[0..@sizeOf(T)], endian);
2005 ptr.* += @sizeOf(T);2006 ptr.* += @sizeOf(T);
2006 return result;2007 return result;
2007}2008}
...@@ -2017,11 +2018,12 @@ fn readByteSignedMem(ptr: *[*]const u8) i8 {...@@ -2017,11 +2018,12 @@ fn readByteSignedMem(ptr: *[*]const u8) i8 {
2017}2018}
20182019
2019fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 {2020fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 {
2020 const first_32_bits = mem.readIntLE(u32, ptr.*[0..4]);2021 // TODO this code can be improved with https://github.com/ziglang/zig/issues/863
2022 const first_32_bits = mem.readIntSliceLittle(u32, ptr.*[0..4]);
2021 is_64.* = (first_32_bits == 0xffffffff);2023 is_64.* = (first_32_bits == 0xffffffff);
2022 if (is_64.*) {2024 if (is_64.*) {
2023 ptr.* += 4;2025 ptr.* += 4;
2024 const result = mem.readIntLE(u64, ptr.*[0..8]);2026 const result = mem.readIntSliceLittle(u64, ptr.*[0..8]);
2025 ptr.* += 8;2027 ptr.* += 8;
2026 return result;2028 return result;
2027 } else {2029 } else {
...@@ -2084,10 +2086,10 @@ fn readILeb128Mem(ptr: *[*]const u8) !i64 {...@@ -2084,10 +2086,10 @@ fn readILeb128Mem(ptr: *[*]const u8) !i64 {
2084}2086}
20852087
2086fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 {2088fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 {
2087 const first_32_bits = try in_stream.readIntLe(u32);2089 const first_32_bits = try in_stream.readIntLittle(u32);
2088 is_64.* = (first_32_bits == 0xffffffff);2090 is_64.* = (first_32_bits == 0xffffffff);
2089 if (is_64.*) {2091 if (is_64.*) {
2090 return in_stream.readIntLe(u64);2092 return in_stream.readIntLittle(u64);
2091 } else {2093 } else {
2092 if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo;2094 if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo;
2093 return u64(first_32_bits);2095 return u64(first_32_bits);
std/dynamic_library.zig+3-4
...@@ -6,6 +6,7 @@ const mem = std.mem;...@@ -6,6 +6,7 @@ const mem = std.mem;
6const cstr = std.cstr;6const cstr = std.cstr;
7const os = std.os;7const os = std.os;
8const assert = std.debug.assert;8const assert = std.debug.assert;
9const testing = std.testing;
9const elf = std.elf;10const elf = std.elf;
10const linux = os.linux;11const linux = os.linux;
11const windows = os.windows;12const windows = os.windows;
...@@ -19,7 +20,6 @@ pub const DynLib = switch (builtin.os) {...@@ -19,7 +20,6 @@ pub const DynLib = switch (builtin.os) {
19};20};
2021
21pub const LinuxDynLib = struct {22pub const LinuxDynLib = struct {
22 allocator: *mem.Allocator,
23 elf_lib: ElfLib,23 elf_lib: ElfLib,
24 fd: i32,24 fd: i32,
25 map_addr: usize,25 map_addr: usize,
...@@ -27,7 +27,7 @@ pub const LinuxDynLib = struct {...@@ -27,7 +27,7 @@ pub const LinuxDynLib = struct {
2727
28 /// Trusts the file28 /// Trusts the file
29 pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib {29 pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib {
30 const fd = try std.os.posixOpen(allocator, path, 0, linux.O_RDONLY | linux.O_CLOEXEC);30 const fd = try std.os.posixOpen(path, 0, linux.O_RDONLY | linux.O_CLOEXEC);
31 errdefer std.os.close(fd);31 errdefer std.os.close(fd);
3232
33 const size = @intCast(usize, (try std.os.posixFStat(fd)).size);33 const size = @intCast(usize, (try std.os.posixFStat(fd)).size);
...@@ -45,7 +45,6 @@ pub const LinuxDynLib = struct {...@@ -45,7 +45,6 @@ pub const LinuxDynLib = struct {
45 const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size];45 const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size];
4646
47 return DynLib{47 return DynLib{
48 .allocator = allocator,
49 .elf_lib = try ElfLib.init(bytes),48 .elf_lib = try ElfLib.init(bytes),
50 .fd = fd,49 .fd = fd,
51 .map_addr = addr,50 .map_addr = addr,
...@@ -208,7 +207,7 @@ test "dynamic_library" {...@@ -208,7 +207,7 @@ test "dynamic_library" {
208 };207 };
209208
210 const dynlib = DynLib.open(std.debug.global_allocator, libname) catch |err| {209 const dynlib = DynLib.open(std.debug.global_allocator, libname) catch |err| {
211 assert(err == error.FileNotFound);210 testing.expect(err == error.FileNotFound);
212 return;211 return;
213 };212 };
214 @panic("Expected error from function");213 @panic("Expected error from function");
std/elf.zig+35-35
...@@ -412,7 +412,7 @@ pub const Elf = struct {...@@ -412,7 +412,7 @@ pub const Elf = struct {
412 // skip over padding412 // skip over padding
413 try seekable_stream.seekForward(9);413 try seekable_stream.seekForward(9);
414414
415 elf.file_type = switch (try in.readInt(elf.endian, u16)) {415 elf.file_type = switch (try in.readInt(u16, elf.endian)) {
416 1 => FileType.Relocatable,416 1 => FileType.Relocatable,
417 2 => FileType.Executable,417 2 => FileType.Executable,
418 3 => FileType.Shared,418 3 => FileType.Shared,
...@@ -420,7 +420,7 @@ pub const Elf = struct {...@@ -420,7 +420,7 @@ pub const Elf = struct {
420 else => return error.InvalidFormat,420 else => return error.InvalidFormat,
421 };421 };
422422
423 elf.arch = switch (try in.readInt(elf.endian, u16)) {423 elf.arch = switch (try in.readInt(u16, elf.endian)) {
424 0x02 => Arch.Sparc,424 0x02 => Arch.Sparc,
425 0x03 => Arch.x86,425 0x03 => Arch.x86,
426 0x08 => Arch.Mips,426 0x08 => Arch.Mips,
...@@ -433,32 +433,32 @@ pub const Elf = struct {...@@ -433,32 +433,32 @@ pub const Elf = struct {
433 else => return error.InvalidFormat,433 else => return error.InvalidFormat,
434 };434 };
435435
436 const elf_version = try in.readInt(elf.endian, u32);436 const elf_version = try in.readInt(u32, elf.endian);
437 if (elf_version != 1) return error.InvalidFormat;437 if (elf_version != 1) return error.InvalidFormat;
438438
439 if (elf.is_64) {439 if (elf.is_64) {
440 elf.entry_addr = try in.readInt(elf.endian, u64);440 elf.entry_addr = try in.readInt(u64, elf.endian);
441 elf.program_header_offset = try in.readInt(elf.endian, u64);441 elf.program_header_offset = try in.readInt(u64, elf.endian);
442 elf.section_header_offset = try in.readInt(elf.endian, u64);442 elf.section_header_offset = try in.readInt(u64, elf.endian);
443 } else {443 } else {
444 elf.entry_addr = u64(try in.readInt(elf.endian, u32));444 elf.entry_addr = u64(try in.readInt(u32, elf.endian));
445 elf.program_header_offset = u64(try in.readInt(elf.endian, u32));445 elf.program_header_offset = u64(try in.readInt(u32, elf.endian));
446 elf.section_header_offset = u64(try in.readInt(elf.endian, u32));446 elf.section_header_offset = u64(try in.readInt(u32, elf.endian));
447 }447 }
448448
449 // skip over flags449 // skip over flags
450 try seekable_stream.seekForward(4);450 try seekable_stream.seekForward(4);
451451
452 const header_size = try in.readInt(elf.endian, u16);452 const header_size = try in.readInt(u16, elf.endian);
453 if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) {453 if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) {
454 return error.InvalidFormat;454 return error.InvalidFormat;
455 }455 }
456456
457 const ph_entry_size = try in.readInt(elf.endian, u16);457 const ph_entry_size = try in.readInt(u16, elf.endian);
458 const ph_entry_count = try in.readInt(elf.endian, u16);458 const ph_entry_count = try in.readInt(u16, elf.endian);
459 const sh_entry_size = try in.readInt(elf.endian, u16);459 const sh_entry_size = try in.readInt(u16, elf.endian);
460 const sh_entry_count = try in.readInt(elf.endian, u16);460 const sh_entry_count = try in.readInt(u16, elf.endian);
461 elf.string_section_index = u64(try in.readInt(elf.endian, u16));461 elf.string_section_index = u64(try in.readInt(u16, elf.endian));
462462
463 if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat;463 if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat;
464464
...@@ -481,32 +481,32 @@ pub const Elf = struct {...@@ -481,32 +481,32 @@ pub const Elf = struct {
481 if (sh_entry_size != 64) return error.InvalidFormat;481 if (sh_entry_size != 64) return error.InvalidFormat;
482482
483 for (elf.section_headers) |*elf_section| {483 for (elf.section_headers) |*elf_section| {
484 elf_section.name = try in.readInt(elf.endian, u32);484 elf_section.name = try in.readInt(u32, elf.endian);
485 elf_section.sh_type = try in.readInt(elf.endian, u32);485 elf_section.sh_type = try in.readInt(u32, elf.endian);
486 elf_section.flags = try in.readInt(elf.endian, u64);486 elf_section.flags = try in.readInt(u64, elf.endian);
487 elf_section.addr = try in.readInt(elf.endian, u64);487 elf_section.addr = try in.readInt(u64, elf.endian);
488 elf_section.offset = try in.readInt(elf.endian, u64);488 elf_section.offset = try in.readInt(u64, elf.endian);
489 elf_section.size = try in.readInt(elf.endian, u64);489 elf_section.size = try in.readInt(u64, elf.endian);
490 elf_section.link = try in.readInt(elf.endian, u32);490 elf_section.link = try in.readInt(u32, elf.endian);
491 elf_section.info = try in.readInt(elf.endian, u32);491 elf_section.info = try in.readInt(u32, elf.endian);
492 elf_section.addr_align = try in.readInt(elf.endian, u64);492 elf_section.addr_align = try in.readInt(u64, elf.endian);
493 elf_section.ent_size = try in.readInt(elf.endian, u64);493 elf_section.ent_size = try in.readInt(u64, elf.endian);
494 }494 }
495 } else {495 } else {
496 if (sh_entry_size != 40) return error.InvalidFormat;496 if (sh_entry_size != 40) return error.InvalidFormat;
497497
498 for (elf.section_headers) |*elf_section| {498 for (elf.section_headers) |*elf_section| {
499 // TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ?499 // TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ?
500 elf_section.name = try in.readInt(elf.endian, u32);500 elf_section.name = try in.readInt(u32, elf.endian);
501 elf_section.sh_type = try in.readInt(elf.endian, u32);501 elf_section.sh_type = try in.readInt(u32, elf.endian);
502 elf_section.flags = u64(try in.readInt(elf.endian, u32));502 elf_section.flags = u64(try in.readInt(u32, elf.endian));
503 elf_section.addr = u64(try in.readInt(elf.endian, u32));503 elf_section.addr = u64(try in.readInt(u32, elf.endian));
504 elf_section.offset = u64(try in.readInt(elf.endian, u32));504 elf_section.offset = u64(try in.readInt(u32, elf.endian));
505 elf_section.size = u64(try in.readInt(elf.endian, u32));505 elf_section.size = u64(try in.readInt(u32, elf.endian));
506 elf_section.link = try in.readInt(elf.endian, u32);506 elf_section.link = try in.readInt(u32, elf.endian);
507 elf_section.info = try in.readInt(elf.endian, u32);507 elf_section.info = try in.readInt(u32, elf.endian);
508 elf_section.addr_align = u64(try in.readInt(elf.endian, u32));508 elf_section.addr_align = u64(try in.readInt(u32, elf.endian));
509 elf_section.ent_size = u64(try in.readInt(elf.endian, u32));509 elf_section.ent_size = u64(try in.readInt(u32, elf.endian));
510 }510 }
511 }511 }
512512
std/event/channel.zig+11-6
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const std = @import("../index.zig");1const std = @import("../index.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const assert = std.debug.assert;3const assert = std.debug.assert;
4const testing = std.testing;
4const AtomicRmwOp = builtin.AtomicRmwOp;5const AtomicRmwOp = builtin.AtomicRmwOp;
5const AtomicOrder = builtin.AtomicOrder;6const AtomicOrder = builtin.AtomicOrder;
6const Loop = std.event.Loop;7const Loop = std.event.Loop;
...@@ -54,7 +55,8 @@ pub fn Channel(comptime T: type) type {...@@ -54,7 +55,8 @@ pub fn Channel(comptime T: type) type {
54 const buffer_nodes = try loop.allocator.alloc(T, capacity);55 const buffer_nodes = try loop.allocator.alloc(T, capacity);
55 errdefer loop.allocator.free(buffer_nodes);56 errdefer loop.allocator.free(buffer_nodes);
5657
57 const self = try loop.allocator.create(SelfChannel{58 const self = try loop.allocator.create(SelfChannel);
59 self.* = SelfChannel{
58 .loop = loop,60 .loop = loop,
59 .buffer_len = 0,61 .buffer_len = 0,
60 .buffer_nodes = buffer_nodes,62 .buffer_nodes = buffer_nodes,
...@@ -66,7 +68,7 @@ pub fn Channel(comptime T: type) type {...@@ -66,7 +68,7 @@ pub fn Channel(comptime T: type) type {
66 .or_null_queue = std.atomic.Queue(*std.atomic.Queue(GetNode).Node).init(),68 .or_null_queue = std.atomic.Queue(*std.atomic.Queue(GetNode).Node).init(),
67 .get_count = 0,69 .get_count = 0,
68 .put_count = 0,70 .put_count = 0,
69 });71 };
70 errdefer loop.allocator.destroy(self);72 errdefer loop.allocator.destroy(self);
7173
72 return self;74 return self;
...@@ -319,6 +321,9 @@ pub fn Channel(comptime T: type) type {...@@ -319,6 +321,9 @@ pub fn Channel(comptime T: type) type {
319}321}
320322
321test "std.event.Channel" {323test "std.event.Channel" {
324 // https://github.com/ziglang/zig/issues/1908
325 if (builtin.single_threaded) return error.SkipZigTest;
326
322 var da = std.heap.DirectAllocator.init();327 var da = std.heap.DirectAllocator.init();
323 defer da.deinit();328 defer da.deinit();
324329
...@@ -346,19 +351,19 @@ async fn testChannelGetter(loop: *Loop, channel: *Channel(i32)) void {...@@ -346,19 +351,19 @@ async fn testChannelGetter(loop: *Loop, channel: *Channel(i32)) void {
346351
347 const value1_promise = try async channel.get();352 const value1_promise = try async channel.get();
348 const value1 = await value1_promise;353 const value1 = await value1_promise;
349 assert(value1 == 1234);354 testing.expect(value1 == 1234);
350355
351 const value2_promise = try async channel.get();356 const value2_promise = try async channel.get();
352 const value2 = await value2_promise;357 const value2 = await value2_promise;
353 assert(value2 == 4567);358 testing.expect(value2 == 4567);
354359
355 const value3_promise = try async channel.getOrNull();360 const value3_promise = try async channel.getOrNull();
356 const value3 = await value3_promise;361 const value3 = await value3_promise;
357 assert(value3 == null);362 testing.expect(value3 == null);
358363
359 const last_put = try async testPut(channel, 4444);364 const last_put = try async testPut(channel, 4444);
360 const value4 = await try async channel.getOrNull();365 const value4 = await try async channel.getOrNull();
361 assert(value4.? == 4444);366 testing.expect(value4.? == 4444);
362 await last_put;367 await last_put;
363}368}
364369
std/event/fs.zig+34-36
...@@ -2,6 +2,7 @@ const builtin = @import("builtin");...@@ -2,6 +2,7 @@ const builtin = @import("builtin");
2const std = @import("../index.zig");2const std = @import("../index.zig");
3const event = std.event;3const event = std.event;
4const assert = std.debug.assert;4const assert = std.debug.assert;
5const testing = std.testing;
5const os = std.os;6const os = std.os;
6const mem = std.mem;7const mem = std.mem;
7const posix = os.posix;8const posix = os.posix;
...@@ -495,7 +496,7 @@ pub const CloseOperation = struct {...@@ -495,7 +496,7 @@ pub const CloseOperation = struct {
495 };496 };
496497
497 pub fn start(loop: *Loop) (error{OutOfMemory}!*CloseOperation) {498 pub fn start(loop: *Loop) (error{OutOfMemory}!*CloseOperation) {
498 const self = try loop.allocator.createOne(CloseOperation);499 const self = try loop.allocator.create(CloseOperation);
499 self.* = CloseOperation{500 self.* = CloseOperation{
500 .loop = loop,501 .loop = loop,
501 .os_data = switch (builtin.os) {502 .os_data = switch (builtin.os) {
...@@ -787,7 +788,7 @@ pub fn Watch(comptime V: type) type {...@@ -787,7 +788,7 @@ pub fn Watch(comptime V: type) type {
787 },788 },
788789
789 builtin.Os.windows => {790 builtin.Os.windows => {
790 const self = try loop.allocator.createOne(Self);791 const self = try loop.allocator.create(Self);
791 errdefer loop.allocator.destroy(self);792 errdefer loop.allocator.destroy(self);
792 self.* = Self{793 self.* = Self{
793 .channel = channel,794 .channel = channel,
...@@ -802,7 +803,7 @@ pub fn Watch(comptime V: type) type {...@@ -802,7 +803,7 @@ pub fn Watch(comptime V: type) type {
802 },803 },
803804
804 builtin.Os.macosx, builtin.Os.freebsd => {805 builtin.Os.macosx, builtin.Os.freebsd => {
805 const self = try loop.allocator.createOne(Self);806 const self = try loop.allocator.create(Self);
806 errdefer loop.allocator.destroy(self);807 errdefer loop.allocator.destroy(self);
807808
808 self.* = Self{809 self.* = Self{
...@@ -871,7 +872,7 @@ pub fn Watch(comptime V: type) type {...@@ -871,7 +872,7 @@ pub fn Watch(comptime V: type) type {
871 }872 }
872873
873 async fn addFileKEvent(self: *Self, file_path: []const u8, value: V) !?V {874 async fn addFileKEvent(self: *Self, file_path: []const u8, value: V) !?V {
874 const resolved_path = try os.path.resolve(self.channel.loop.allocator, file_path);875 const resolved_path = try os.path.resolve(self.channel.loop.allocator, [][]const u8{file_path});
875 var resolved_path_consumed = false;876 var resolved_path_consumed = false;
876 defer if (!resolved_path_consumed) self.channel.loop.allocator.free(resolved_path);877 defer if (!resolved_path_consumed) self.channel.loop.allocator.free(resolved_path);
877878
...@@ -1068,7 +1069,7 @@ pub fn Watch(comptime V: type) type {...@@ -1068,7 +1069,7 @@ pub fn Watch(comptime V: type) type {
1068 }1069 }
1069 } else {1070 } else {
1070 errdefer _ = self.os_data.dir_table.remove(dirname);1071 errdefer _ = self.os_data.dir_table.remove(dirname);
1071 const dir = try self.channel.loop.allocator.createOne(OsData.Dir);1072 const dir = try self.channel.loop.allocator.create(OsData.Dir);
1072 errdefer self.channel.loop.allocator.destroy(dir);1073 errdefer self.channel.loop.allocator.destroy(dir);
10731074
1074 dir.* = OsData.Dir{1075 dir.* = OsData.Dir{
...@@ -1307,39 +1308,36 @@ pub fn Watch(comptime V: type) type {...@@ -1307,39 +1308,36 @@ pub fn Watch(comptime V: type) type {
13071308
1308const test_tmp_dir = "std_event_fs_test";1309const test_tmp_dir = "std_event_fs_test";
13091310
1310test "write a file, watch it, write it again" {1311// TODO this test is disabled until the coroutine rewrite is finished.
1311 if (builtin.os == builtin.Os.windows) {1312//test "write a file, watch it, write it again" {
1312 // TODO this test is disabled on windows until the coroutine rewrite is finished.1313// return error.SkipZigTest;
1313 // https://github.com/ziglang/zig/issues/13631314// var da = std.heap.DirectAllocator.init();
1314 return error.SkipZigTest;1315// defer da.deinit();
1315 }1316//
1316 var da = std.heap.DirectAllocator.init();1317// const allocator = &da.allocator;
1317 defer da.deinit();1318//
13181319// // TODO move this into event loop too
1319 const allocator = &da.allocator;1320// try os.makePath(allocator, test_tmp_dir);
13201321// defer os.deleteTree(allocator, test_tmp_dir) catch {};
1321 // TODO move this into event loop too1322//
1322 try os.makePath(allocator, test_tmp_dir);1323// var loop: Loop = undefined;
1323 defer os.deleteTree(allocator, test_tmp_dir) catch {};1324// try loop.initMultiThreaded(allocator);
13241325// defer loop.deinit();
1325 var loop: Loop = undefined;1326//
1326 try loop.initMultiThreaded(allocator);1327// var result: anyerror!void = error.ResultNeverWritten;
1327 defer loop.deinit();1328// const handle = try async<allocator> testFsWatchCantFail(&loop, &result);
13281329// defer cancel handle;
1329 var result: anyerror!void = error.ResultNeverWritten;1330//
1330 const handle = try async<allocator> testFsWatchCantFail(&loop, &result);1331// loop.run();
1331 defer cancel handle;1332// return result;
13321333//}
1333 loop.run();
1334 return result;
1335}
13361334
1337async fn testFsWatchCantFail(loop: *Loop, result: *(anyerror!void)) void {1335async fn testFsWatchCantFail(loop: *Loop, result: *(anyerror!void)) void {
1338 result.* = await (async testFsWatch(loop) catch unreachable);1336 result.* = await (async testFsWatch(loop) catch unreachable);
1339}1337}
13401338
1341async fn testFsWatch(loop: *Loop) !void {1339async fn testFsWatch(loop: *Loop) !void {
1342 const file_path = try os.path.join(loop.allocator, test_tmp_dir, "file.txt");1340 const file_path = try os.path.join(loop.allocator, [][]const u8{ test_tmp_dir, "file.txt" });
1343 defer loop.allocator.free(file_path);1341 defer loop.allocator.free(file_path);
13441342
1345 const contents =1343 const contents =
...@@ -1352,13 +1350,13 @@ async fn testFsWatch(loop: *Loop) !void {...@@ -1352,13 +1350,13 @@ async fn testFsWatch(loop: *Loop) !void {
1352 try await try async writeFile(loop, file_path, contents);1350 try await try async writeFile(loop, file_path, contents);
13531351
1354 const read_contents = try await try async readFile(loop, file_path, 1024 * 1024);1352 const read_contents = try await try async readFile(loop, file_path, 1024 * 1024);
1355 assert(mem.eql(u8, read_contents, contents));1353 testing.expectEqualSlices(u8, contents, read_contents);
13561354
1357 // now watch the file1355 // now watch the file
1358 var watch = try Watch(void).create(loop, 0);1356 var watch = try Watch(void).create(loop, 0);
1359 defer watch.destroy();1357 defer watch.destroy();
13601358
1361 assert((try await try async watch.addFile(file_path, {})) == null);1359 testing.expect((try await try async watch.addFile(file_path, {})) == null);
13621360
1363 const ev = try async watch.channel.get();1361 const ev = try async watch.channel.get();
1364 var ev_consumed = false;1362 var ev_consumed = false;
...@@ -1378,10 +1376,10 @@ async fn testFsWatch(loop: *Loop) !void {...@@ -1378,10 +1376,10 @@ async fn testFsWatch(loop: *Loop) !void {
1378 WatchEventId.Delete => @panic("wrong event"),1376 WatchEventId.Delete => @panic("wrong event"),
1379 }1377 }
1380 const contents_updated = try await try async readFile(loop, file_path, 1024 * 1024);1378 const contents_updated = try await try async readFile(loop, file_path, 1024 * 1024);
1381 assert(mem.eql(u8, contents_updated,1379 testing.expectEqualSlices(u8,
1382 \\line 11380 \\line 1
1383 \\lorem ipsum1381 \\lorem ipsum
1384 ));1382 , contents_updated);
13851383
1386 // TODO test deleting the file and then re-adding it. we should get events for both1384 // TODO test deleting the file and then re-adding it. we should get events for both
1387}1385}
std/event/future.zig+5-1
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const std = @import("../index.zig");1const std = @import("../index.zig");
2const assert = std.debug.assert;2const assert = std.debug.assert;
3const testing = std.testing;
3const builtin = @import("builtin");4const builtin = @import("builtin");
4const AtomicRmwOp = builtin.AtomicRmwOp;5const AtomicRmwOp = builtin.AtomicRmwOp;
5const AtomicOrder = builtin.AtomicOrder;6const AtomicOrder = builtin.AtomicOrder;
...@@ -84,6 +85,9 @@ pub fn Future(comptime T: type) type {...@@ -84,6 +85,9 @@ pub fn Future(comptime T: type) type {
84}85}
8586
86test "std.event.Future" {87test "std.event.Future" {
88 // https://github.com/ziglang/zig/issues/1908
89 if (builtin.single_threaded) return error.SkipZigTest;
90
87 var da = std.heap.DirectAllocator.init();91 var da = std.heap.DirectAllocator.init();
88 defer da.deinit();92 defer da.deinit();
8993
...@@ -111,7 +115,7 @@ async fn testFuture(loop: *Loop) void {...@@ -111,7 +115,7 @@ async fn testFuture(loop: *Loop) void {
111115
112 const result = (await a) + (await b);116 const result = (await a) + (await b);
113 cancel c;117 cancel c;
114 assert(result == 12);118 testing.expect(result == 12);
115}119}
116120
117async fn waitOnFuture(future: *Future(i32)) i32 {121async fn waitOnFuture(future: *Future(i32)) i32 {
std/event/group.zig+9-5
...@@ -4,7 +4,7 @@ const Lock = std.event.Lock;...@@ -4,7 +4,7 @@ const Lock = std.event.Lock;
4const Loop = std.event.Loop;4const Loop = std.event.Loop;
5const AtomicRmwOp = builtin.AtomicRmwOp;5const AtomicRmwOp = builtin.AtomicRmwOp;
6const AtomicOrder = builtin.AtomicOrder;6const AtomicOrder = builtin.AtomicOrder;
7const assert = std.debug.assert;7const testing = std.testing;
88
9/// ReturnType must be `void` or `E!void`9/// ReturnType must be `void` or `E!void`
10pub fn Group(comptime ReturnType: type) type {10pub fn Group(comptime ReturnType: type) type {
...@@ -42,10 +42,11 @@ pub fn Group(comptime ReturnType: type) type {...@@ -42,10 +42,11 @@ pub fn Group(comptime ReturnType: type) type {
4242
43 /// Add a promise to the group. Thread-safe.43 /// Add a promise to the group. Thread-safe.
44 pub fn add(self: *Self, handle: promise->ReturnType) (error{OutOfMemory}!void) {44 pub fn add(self: *Self, handle: promise->ReturnType) (error{OutOfMemory}!void) {
45 const node = try self.lock.loop.allocator.create(Stack.Node{45 const node = try self.lock.loop.allocator.create(Stack.Node);
46 node.* = Stack.Node{
46 .next = undefined,47 .next = undefined,
47 .data = handle,48 .data = handle,
48 });49 };
49 self.alloc_stack.push(node);50 self.alloc_stack.push(node);
50 }51 }
5152
...@@ -121,6 +122,9 @@ pub fn Group(comptime ReturnType: type) type {...@@ -121,6 +122,9 @@ pub fn Group(comptime ReturnType: type) type {
121}122}
122123
123test "std.event.Group" {124test "std.event.Group" {
125 // https://github.com/ziglang/zig/issues/1908
126 if (builtin.single_threaded) return error.SkipZigTest;
127
124 var da = std.heap.DirectAllocator.init();128 var da = std.heap.DirectAllocator.init();
125 defer da.deinit();129 defer da.deinit();
126130
...@@ -142,12 +146,12 @@ async fn testGroup(loop: *Loop) void {...@@ -142,12 +146,12 @@ async fn testGroup(loop: *Loop) void {
142 group.add(async sleepALittle(&count) catch @panic("memory")) catch @panic("memory");146 group.add(async sleepALittle(&count) catch @panic("memory")) catch @panic("memory");
143 group.call(increaseByTen, &count) catch @panic("memory");147 group.call(increaseByTen, &count) catch @panic("memory");
144 await (async group.wait() catch @panic("memory"));148 await (async group.wait() catch @panic("memory"));
145 assert(count == 11);149 testing.expect(count == 11);
146150
147 var another = Group(anyerror!void).init(loop);151 var another = Group(anyerror!void).init(loop);
148 another.add(async somethingElse() catch @panic("memory")) catch @panic("memory");152 another.add(async somethingElse() catch @panic("memory")) catch @panic("memory");
149 another.call(doSomethingThatFails) catch @panic("memory");153 another.call(doSomethingThatFails) catch @panic("memory");
150 std.debug.assertError(await (async another.wait() catch @panic("memory")), error.ItBroke);154 testing.expectError(error.ItBroke, await (async another.wait() catch @panic("memory")));
151}155}
152156
153async fn sleepALittle(count: *usize) void {157async fn sleepALittle(count: *usize) void {
std/event/io.zig+9-5
...@@ -39,18 +39,22 @@ pub fn InStream(comptime ReadError: type) type {...@@ -39,18 +39,22 @@ pub fn InStream(comptime ReadError: type) type {
39 if (amt_read < buf.len) return error.EndOfStream;39 if (amt_read < buf.len) return error.EndOfStream;
40 }40 }
4141
42 pub async fn readIntLe(self: *Self, comptime T: type) !T {42 pub async fn readIntLittle(self: *Self, comptime T: type) !T {
43 return await (async self.readInt(builtin.Endian.Little, T) catch unreachable);43 var bytes: [@sizeOf(T)]u8 = undefined;
44 try await (async self.readNoEof(bytes[0..]) catch unreachable);
45 return mem.readIntLittle(T, &bytes);
44 }46 }
4547
46 pub async fn readIntBe(self: *Self, comptime T: type) !T {48 pub async fn readIntBe(self: *Self, comptime T: type) !T {
47 return await (async self.readInt(builtin.Endian.Big, T) catch unreachable);49 var bytes: [@sizeOf(T)]u8 = undefined;
50 try await (async self.readNoEof(bytes[0..]) catch unreachable);
51 return mem.readIntBig(T, &bytes);
48 }52 }
4953
50 pub async fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T {54 pub async fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
51 var bytes: [@sizeOf(T)]u8 = undefined;55 var bytes: [@sizeOf(T)]u8 = undefined;
52 try await (async self.readNoEof(bytes[0..]) catch unreachable);56 try await (async self.readNoEof(bytes[0..]) catch unreachable);
53 return mem.readInt(bytes, T, endian);57 return mem.readInt(T, &bytes, endian);
54 }58 }
5559
56 pub async fn readStruct(self: *Self, comptime T: type) !T {60 pub async fn readStruct(self: *Self, comptime T: type) !T {
std/event/lock.zig+5-1
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const std = @import("../index.zig");1const std = @import("../index.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const assert = std.debug.assert;3const assert = std.debug.assert;
4const testing = std.testing;
4const mem = std.mem;5const mem = std.mem;
5const AtomicRmwOp = builtin.AtomicRmwOp;6const AtomicRmwOp = builtin.AtomicRmwOp;
6const AtomicOrder = builtin.AtomicOrder;7const AtomicOrder = builtin.AtomicOrder;
...@@ -122,6 +123,9 @@ pub const Lock = struct {...@@ -122,6 +123,9 @@ pub const Lock = struct {
122};123};
123124
124test "std.event.Lock" {125test "std.event.Lock" {
126 // https://github.com/ziglang/zig/issues/1908
127 if (builtin.single_threaded) return error.SkipZigTest;
128
125 var da = std.heap.DirectAllocator.init();129 var da = std.heap.DirectAllocator.init();
126 defer da.deinit();130 defer da.deinit();
127131
...@@ -138,7 +142,7 @@ test "std.event.Lock" {...@@ -138,7 +142,7 @@ test "std.event.Lock" {
138 defer cancel handle;142 defer cancel handle;
139 loop.run();143 loop.run();
140144
141 assert(mem.eql(i32, shared_test_data, [1]i32{3 * @intCast(i32, shared_test_data.len)} ** shared_test_data.len));145 testing.expectEqualSlices(i32, [1]i32{3 * @intCast(i32, shared_test_data.len)} ** shared_test_data.len, shared_test_data);
142}146}
143147
144async fn testLock(loop: *Loop, lock: *Lock) void {148async fn testLock(loop: *Loop, lock: *Lock) void {
std/event/loop.zig+25-2
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const std = @import("../index.zig");1const std = @import("../index.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const assert = std.debug.assert;3const assert = std.debug.assert;
4const testing = std.testing;
4const mem = std.mem;5const mem = std.mem;
5const AtomicRmwOp = builtin.AtomicRmwOp;6const AtomicRmwOp = builtin.AtomicRmwOp;
6const AtomicOrder = builtin.AtomicOrder;7const AtomicOrder = builtin.AtomicOrder;
...@@ -97,6 +98,7 @@ pub const Loop = struct {...@@ -97,6 +98,7 @@ pub const Loop = struct {
97 /// TODO copy elision / named return values so that the threads referencing *Loop98 /// TODO copy elision / named return values so that the threads referencing *Loop
98 /// have the correct pointer value.99 /// have the correct pointer value.
99 pub fn initMultiThreaded(self: *Loop, allocator: *mem.Allocator) !void {100 pub fn initMultiThreaded(self: *Loop, allocator: *mem.Allocator) !void {
101 if (builtin.single_threaded) @compileError("initMultiThreaded unavailable when building in single-threaded mode");
100 const core_count = try os.cpuCount(allocator);102 const core_count = try os.cpuCount(allocator);
101 return self.initInternal(allocator, core_count);103 return self.initInternal(allocator, core_count);
102 }104 }
...@@ -201,6 +203,11 @@ pub const Loop = struct {...@@ -201,6 +203,11 @@ pub const Loop = struct {
201 self.os_data.fs_thread.wait();203 self.os_data.fs_thread.wait();
202 }204 }
203205
206 if (builtin.single_threaded) {
207 assert(extra_thread_count == 0);
208 return;
209 }
210
204 var extra_thread_index: usize = 0;211 var extra_thread_index: usize = 0;
205 errdefer {212 errdefer {
206 // writing 8 bytes to an eventfd cannot fail213 // writing 8 bytes to an eventfd cannot fail
...@@ -301,6 +308,11 @@ pub const Loop = struct {...@@ -301,6 +308,11 @@ pub const Loop = struct {
301 self.os_data.fs_thread.wait();308 self.os_data.fs_thread.wait();
302 }309 }
303310
311 if (builtin.single_threaded) {
312 assert(extra_thread_count == 0);
313 return;
314 }
315
304 var extra_thread_index: usize = 0;316 var extra_thread_index: usize = 0;
305 errdefer {317 errdefer {
306 _ = os.bsdKEvent(self.os_data.kqfd, final_kev_arr, empty_kevs, null) catch unreachable;318 _ = os.bsdKEvent(self.os_data.kqfd, final_kev_arr, empty_kevs, null) catch unreachable;
...@@ -338,6 +350,11 @@ pub const Loop = struct {...@@ -338,6 +350,11 @@ pub const Loop = struct {
338 self.available_eventfd_resume_nodes.push(eventfd_node);350 self.available_eventfd_resume_nodes.push(eventfd_node);
339 }351 }
340352
353 if (builtin.single_threaded) {
354 assert(extra_thread_count == 0);
355 return;
356 }
357
341 var extra_thread_index: usize = 0;358 var extra_thread_index: usize = 0;
342 errdefer {359 errdefer {
343 var i: usize = 0;360 var i: usize = 0;
...@@ -845,6 +862,9 @@ pub const Loop = struct {...@@ -845,6 +862,9 @@ pub const Loop = struct {
845};862};
846863
847test "std.event.Loop - basic" {864test "std.event.Loop - basic" {
865 // https://github.com/ziglang/zig/issues/1908
866 if (builtin.single_threaded) return error.SkipZigTest;
867
848 var da = std.heap.DirectAllocator.init();868 var da = std.heap.DirectAllocator.init();
849 defer da.deinit();869 defer da.deinit();
850870
...@@ -858,6 +878,9 @@ test "std.event.Loop - basic" {...@@ -858,6 +878,9 @@ test "std.event.Loop - basic" {
858}878}
859879
860test "std.event.Loop - call" {880test "std.event.Loop - call" {
881 // https://github.com/ziglang/zig/issues/1908
882 if (builtin.single_threaded) return error.SkipZigTest;
883
861 var da = std.heap.DirectAllocator.init();884 var da = std.heap.DirectAllocator.init();
862 defer da.deinit();885 defer da.deinit();
863886
...@@ -874,7 +897,7 @@ test "std.event.Loop - call" {...@@ -874,7 +897,7 @@ test "std.event.Loop - call" {
874897
875 loop.run();898 loop.run();
876899
877 assert(did_it);900 testing.expect(did_it);
878}901}
879902
880async fn testEventLoop() i32 {903async fn testEventLoop() i32 {
...@@ -883,6 +906,6 @@ async fn testEventLoop() i32 {...@@ -883,6 +906,6 @@ async fn testEventLoop() i32 {
883906
884async fn testEventLoop2(h: promise->i32, did_it: *bool) void {907async fn testEventLoop2(h: promise->i32, did_it: *bool) void {
885 const value = await h;908 const value = await h;
886 assert(value == 1234);909 testing.expect(value == 1234);
887 did_it.* = true;910 did_it.* = true;
888}911}
std/event/net.zig+5-2
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const std = @import("../index.zig");1const std = @import("../index.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const assert = std.debug.assert;3const testing = std.testing;
4const event = std.event;4const event = std.event;
5const mem = std.mem;5const mem = std.mem;
6const os = std.os;6const os = std.os;
...@@ -269,6 +269,9 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !os.File {...@@ -269,6 +269,9 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !os.File {
269}269}
270270
271test "listen on a port, send bytes, receive bytes" {271test "listen on a port, send bytes, receive bytes" {
272 // https://github.com/ziglang/zig/issues/1908
273 if (builtin.single_threaded) return error.SkipZigTest;
274
272 if (builtin.os != builtin.Os.linux) {275 if (builtin.os != builtin.Os.linux) {
273 // TODO build abstractions for other operating systems276 // TODO build abstractions for other operating systems
274 return error.SkipZigTest;277 return error.SkipZigTest;
...@@ -323,7 +326,7 @@ async fn doAsyncTest(loop: *Loop, address: *const std.net.Address, server: *Serv...@@ -323,7 +326,7 @@ async fn doAsyncTest(loop: *Loop, address: *const std.net.Address, server: *Serv
323 var buf: [512]u8 = undefined;326 var buf: [512]u8 = undefined;
324 const amt_read = try socket_file.read(buf[0..]);327 const amt_read = try socket_file.read(buf[0..]);
325 const msg = buf[0..amt_read];328 const msg = buf[0..amt_read];
326 assert(mem.eql(u8, msg, "hello from server\n"));329 testing.expect(mem.eql(u8, msg, "hello from server\n"));
327 server.close();330 server.close();
328}331}
329332
std/event/rwlock.zig+7-3
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const std = @import("../index.zig");1const std = @import("../index.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const assert = std.debug.assert;3const assert = std.debug.assert;
4const testing = std.testing;
4const mem = std.mem;5const mem = std.mem;
5const AtomicRmwOp = builtin.AtomicRmwOp;6const AtomicRmwOp = builtin.AtomicRmwOp;
6const AtomicOrder = builtin.AtomicOrder;7const AtomicOrder = builtin.AtomicOrder;
...@@ -211,6 +212,9 @@ pub const RwLock = struct {...@@ -211,6 +212,9 @@ pub const RwLock = struct {
211};212};
212213
213test "std.event.RwLock" {214test "std.event.RwLock" {
215 // https://github.com/ziglang/zig/issues/1908
216 if (builtin.single_threaded) return error.SkipZigTest;
217
214 var da = std.heap.DirectAllocator.init();218 var da = std.heap.DirectAllocator.init();
215 defer da.deinit();219 defer da.deinit();
216220
...@@ -228,7 +232,7 @@ test "std.event.RwLock" {...@@ -228,7 +232,7 @@ test "std.event.RwLock" {
228 loop.run();232 loop.run();
229233
230 const expected_result = [1]i32{shared_it_count * @intCast(i32, shared_test_data.len)} ** shared_test_data.len;234 const expected_result = [1]i32{shared_it_count * @intCast(i32, shared_test_data.len)} ** shared_test_data.len;
231 assert(mem.eql(i32, shared_test_data, expected_result));235 testing.expectEqualSlices(i32, expected_result, shared_test_data);
232}236}
233237
234async fn testLock(loop: *Loop, lock: *RwLock) void {238async fn testLock(loop: *Loop, lock: *RwLock) void {
...@@ -290,7 +294,7 @@ async fn readRunner(lock: *RwLock) void {...@@ -290,7 +294,7 @@ async fn readRunner(lock: *RwLock) void {
290 const handle = await lock_promise;294 const handle = await lock_promise;
291 defer handle.release();295 defer handle.release();
292296
293 assert(shared_test_index == 0);297 testing.expect(shared_test_index == 0);
294 assert(shared_test_data[i] == @intCast(i32, shared_count));298 testing.expect(shared_test_data[i] == @intCast(i32, shared_count));
295 }299 }
296}300}
std/fmt/index.zig+125-83
...@@ -2,7 +2,7 @@ const std = @import("../index.zig");...@@ -2,7 +2,7 @@ const std = @import("../index.zig");
2const math = std.math;2const math = std.math;
3const debug = std.debug;3const debug = std.debug;
4const assert = debug.assert;4const assert = debug.assert;
5const assertError = debug.assertError;5const testing = std.testing;
6const mem = std.mem;6const mem = std.mem;
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const errol = @import("errol/index.zig");8const errol = @import("errol/index.zig");
...@@ -117,7 +117,7 @@ pub fn formatType(...@@ -117,7 +117,7 @@ pub fn formatType(
117 return output(context, @errorName(value));117 return output(context, @errorName(value));
118 }118 }
119 switch (@typeInfo(T)) {119 switch (@typeInfo(T)) {
120 builtin.TypeId.Int, builtin.TypeId.Float => {120 builtin.TypeId.ComptimeInt, builtin.TypeId.Int, builtin.TypeId.Float => {
121 return formatValue(value, fmt, context, Errors, output);121 return formatValue(value, fmt, context, Errors, output);
122 },122 },
123 builtin.TypeId.Void => {123 builtin.TypeId.Void => {
...@@ -236,6 +236,9 @@ pub fn formatType(...@@ -236,6 +236,9 @@ pub fn formatType(
236 const casted_value = ([]const u8)(value);236 const casted_value = ([]const u8)(value);
237 return output(context, casted_value);237 return output(context, casted_value);
238 },238 },
239 builtin.TypeInfo.Pointer.Size.C => {
240 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
241 },
239 },242 },
240 builtin.TypeId.Array => |info| {243 builtin.TypeId.Array => |info| {
241 if (info.child == u8) {244 if (info.child == u8) {
...@@ -243,6 +246,9 @@ pub fn formatType(...@@ -243,6 +246,9 @@ pub fn formatType(
243 }246 }
244 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));247 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));
245 },248 },
249 builtin.TypeId.Fn => {
250 return format(context, Errors, output, "{}@{x}", @typeName(T), @ptrToInt(value));
251 },
246 else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),252 else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
247 }253 }
248}254}
...@@ -268,11 +274,15 @@ fn formatValue(...@@ -268,11 +274,15 @@ fn formatValue(
268 }274 }
269 }275 }
270276
271 comptime var T = @typeOf(value);277 const T = @typeOf(value);
272 switch (@typeId(T)) {278 switch (@typeId(T)) {
273 builtin.TypeId.Float => return formatFloatValue(value, fmt, context, Errors, output),279 builtin.TypeId.Float => return formatFloatValue(value, fmt, context, Errors, output),
274 builtin.TypeId.Int => return formatIntValue(value, fmt, context, Errors, output),280 builtin.TypeId.Int => return formatIntValue(value, fmt, context, Errors, output),
275 else => unreachable,281 builtin.TypeId.ComptimeInt => {
282 const Int = math.IntFittingRange(value, value);
283 return formatIntValue(Int(value), fmt, context, Errors, output);
284 },
285 else => comptime unreachable,
276 }286 }
277}287}
278288
...@@ -289,9 +299,10 @@ pub fn formatIntValue(...@@ -289,9 +299,10 @@ pub fn formatIntValue(
289 if (fmt.len > 0) {299 if (fmt.len > 0) {
290 switch (fmt[0]) {300 switch (fmt[0]) {
291 'c' => {301 'c' => {
292 if (@typeOf(value) == u8) {302 if (@typeOf(value).bit_count <= 8) {
293 if (fmt.len > 1) @compileError("Unknown format character: " ++ []u8{fmt[1]});303 if (fmt.len > 1)
294 return formatAsciiChar(value, context, Errors, output);304 @compileError("Unknown format character: " ++ []u8{fmt[1]});
305 return formatAsciiChar(u8(value), context, Errors, output);
295 }306 }
296 },307 },
297 'b' => {308 'b' => {
...@@ -580,7 +591,7 @@ pub fn formatFloatDecimal(...@@ -580,7 +591,7 @@ pub fn formatFloatDecimal(
580 }591 }
581592
582 // Remaining fractional portion, zero-padding if insufficient.593 // Remaining fractional portion, zero-padding if insufficient.
583 debug.assert(precision >= printed);594 assert(precision >= printed);
584 if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) {595 if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) {
585 try output(context, float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]);596 try output(context, float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]);
586 return;597 return;
...@@ -790,13 +801,13 @@ pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {...@@ -790,13 +801,13 @@ pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {
790}801}
791802
792test "fmt.parseInt" {803test "fmt.parseInt" {
793 assert((parseInt(i32, "-10", 10) catch unreachable) == -10);804 testing.expect((parseInt(i32, "-10", 10) catch unreachable) == -10);
794 assert((parseInt(i32, "+10", 10) catch unreachable) == 10);805 testing.expect((parseInt(i32, "+10", 10) catch unreachable) == 10);
795 assert(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidCharacter);806 testing.expect(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidCharacter);
796 assert(if (parseInt(i32, "10 ", 10)) |_| false else |err| err == error.InvalidCharacter);807 testing.expect(if (parseInt(i32, "10 ", 10)) |_| false else |err| err == error.InvalidCharacter);
797 assert(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter);808 testing.expect(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter);
798 assert((parseInt(u8, "255", 10) catch unreachable) == 255);809 testing.expect((parseInt(u8, "255", 10) catch unreachable) == 255);
799 assert(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);810 testing.expect(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
800}811}
801812
802const ParseUnsignedError = error{813const ParseUnsignedError = error{
...@@ -820,31 +831,37 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned...@@ -820,31 +831,37 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned
820 return x;831 return x;
821}832}
822833
823test "parseUnsigned" {834test "fmt.parseUnsigned" {
824 assert((try parseUnsigned(u16, "050124", 10)) == 50124);835 testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);
825 assert((try parseUnsigned(u16, "65535", 10)) == 65535);836 testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);
826 assertError(parseUnsigned(u16, "65536", 10), error.Overflow);837 testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
827838
828 assert((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);839 testing.expect((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);
829 assertError(parseUnsigned(u64, "10000000000000000", 16), error.Overflow);840 testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16));
830841
831 assert((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF);842 testing.expect((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF);
832843
833 assert((try parseUnsigned(u7, "1", 10)) == 1);844 testing.expect((try parseUnsigned(u7, "1", 10)) == 1);
834 assert((try parseUnsigned(u7, "1000", 2)) == 8);845 testing.expect((try parseUnsigned(u7, "1000", 2)) == 8);
835846
836 assertError(parseUnsigned(u32, "f", 10), error.InvalidCharacter);847 testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10));
837 assertError(parseUnsigned(u8, "109", 8), error.InvalidCharacter);848 testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "109", 8));
838849
839 assert((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747);850 testing.expect((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747);
840851
841 // these numbers should fit even though the radix itself doesn't fit in the destination type852 // these numbers should fit even though the radix itself doesn't fit in the destination type
842 assert((try parseUnsigned(u1, "0", 10)) == 0);853 testing.expect((try parseUnsigned(u1, "0", 10)) == 0);
843 assert((try parseUnsigned(u1, "1", 10)) == 1);854 testing.expect((try parseUnsigned(u1, "1", 10)) == 1);
844 assertError(parseUnsigned(u1, "2", 10), error.Overflow);855 testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10));
845 assert((try parseUnsigned(u1, "001", 16)) == 1);856 testing.expect((try parseUnsigned(u1, "001", 16)) == 1);
846 assert((try parseUnsigned(u2, "3", 16)) == 3);857 testing.expect((try parseUnsigned(u2, "3", 16)) == 3);
847 assertError(parseUnsigned(u2, "4", 16), error.Overflow);858 testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));
859}
860
861pub const parseFloat = @import("parse_float.zig").parseFloat;
862
863test "fmt.parseFloat" {
864 _ = @import("parse_float.zig");
848}865}
849866
850pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {867pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
...@@ -902,19 +919,19 @@ fn countSize(size: *usize, bytes: []const u8) (error{}!void) {...@@ -902,19 +919,19 @@ fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
902test "buf print int" {919test "buf print int" {
903 var buffer: [max_int_digits]u8 = undefined;920 var buffer: [max_int_digits]u8 = undefined;
904 const buf = buffer[0..];921 const buf = buffer[0..];
905 assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 2, false, 0), "-101111000110000101001110"));922 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 2, false, 0), "-101111000110000101001110"));
906 assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 10, false, 0), "-12345678"));923 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 10, false, 0), "-12345678"));
907 assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, false, 0), "-bc614e"));924 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, false, 0), "-bc614e"));
908 assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, true, 0), "-BC614E"));925 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, true, 0), "-BC614E"));
909926
910 assert(mem.eql(u8, bufPrintIntToSlice(buf, u32(12345678), 10, true, 0), "12345678"));927 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(12345678), 10, true, 0), "12345678"));
911928
912 assert(mem.eql(u8, bufPrintIntToSlice(buf, u32(666), 10, false, 6), "000666"));929 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(666), 10, false, 6), "000666"));
913 assert(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 6), "001234"));930 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 6), "001234"));
914 assert(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 1), "1234"));931 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 1), "1234"));
915932
916 assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(42), 10, false, 3), "+42"));933 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(42), 10, false, 3), "+42"));
917 assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-42), 10, false, 3), "-42"));934 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-42), 10, false, 3), "-42"));
918}935}
919936
920fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, width: usize) []u8 {937fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, width: usize) []u8 {
...@@ -931,7 +948,7 @@ test "parse u64 digit too big" {...@@ -931,7 +948,7 @@ test "parse u64 digit too big" {
931948
932test "parse unsigned comptime" {949test "parse unsigned comptime" {
933 comptime {950 comptime {
934 assert((try parseUnsigned(usize, "2", 10)) == 2);951 testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
935 }952 }
936}953}
937954
...@@ -964,6 +981,23 @@ test "fmt.format" {...@@ -964,6 +981,23 @@ test "fmt.format" {
964 const value: u8 = 0b1100;981 const value: u8 = 0b1100;
965 try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", value);982 try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", value);
966 }983 }
984 {
985 var buf1: [32]u8 = undefined;
986 var context = BufPrintContext{ .remaining = buf1[0..] };
987 try formatType(1234, "", &context, error{BufferTooSmall}, bufPrintWrite);
988 var res = buf1[0 .. buf1.len - context.remaining.len];
989 testing.expect(mem.eql(u8, res, "1234"));
990
991 context = BufPrintContext{ .remaining = buf1[0..] };
992 try formatType('a', "c", &context, error{BufferTooSmall}, bufPrintWrite);
993 res = buf1[0 .. buf1.len - context.remaining.len];
994 testing.expect(mem.eql(u8, res, "a"));
995
996 context = BufPrintContext{ .remaining = buf1[0..] };
997 try formatType(0b1100, "b", &context, error{BufferTooSmall}, bufPrintWrite);
998 res = buf1[0 .. buf1.len - context.remaining.len];
999 testing.expect(mem.eql(u8, res, "1100"));
1000 }
967 {1001 {
968 const value: [3]u8 = "abc";1002 const value: [3]u8 = "abc";
969 try testFmt("array: abc\n", "array: {}\n", value);1003 try testFmt("array: abc\n", "array: {}\n", value);
...@@ -985,6 +1019,14 @@ test "fmt.format" {...@@ -985,6 +1019,14 @@ test "fmt.format" {
985 try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", value);1019 try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", value);
986 try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", value);1020 try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", value);
987 }1021 }
1022 {
1023 const value = @intToPtr(fn () void, 0xdeadbeef);
1024 try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value);
1025 }
1026 {
1027 const value = @intToPtr(fn () void, 0xdeadbeef);
1028 try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value);
1029 }
988 try testFmt("buf: Test \n", "buf: {s5}\n", "Test");1030 try testFmt("buf: Test \n", "buf: {s5}\n", "Test");
989 try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test");1031 try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test");
990 try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C");1032 try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C");
...@@ -1020,19 +1062,19 @@ test "fmt.format" {...@@ -1020,19 +1062,19 @@ test "fmt.format" {
1020 var buf1: [32]u8 = undefined;1062 var buf1: [32]u8 = undefined;
1021 const value: f32 = 1.34;1063 const value: f32 = 1.34;
1022 const result = try bufPrint(buf1[0..], "f32: {e}\n", value);1064 const result = try bufPrint(buf1[0..], "f32: {e}\n", value);
1023 assert(mem.eql(u8, result, "f32: 1.34000003e+00\n"));1065 testing.expect(mem.eql(u8, result, "f32: 1.34000003e+00\n"));
1024 }1066 }
1025 {1067 {
1026 var buf1: [32]u8 = undefined;1068 var buf1: [32]u8 = undefined;
1027 const value: f32 = 12.34;1069 const value: f32 = 12.34;
1028 const result = try bufPrint(buf1[0..], "f32: {e}\n", value);1070 const result = try bufPrint(buf1[0..], "f32: {e}\n", value);
1029 assert(mem.eql(u8, result, "f32: 1.23400001e+01\n"));1071 testing.expect(mem.eql(u8, result, "f32: 1.23400001e+01\n"));
1030 }1072 }
1031 {1073 {
1032 var buf1: [32]u8 = undefined;1074 var buf1: [32]u8 = undefined;
1033 const value: f64 = -12.34e10;1075 const value: f64 = -12.34e10;
1034 const result = try bufPrint(buf1[0..], "f64: {e}\n", value);1076 const result = try bufPrint(buf1[0..], "f64: {e}\n", value);
1035 assert(mem.eql(u8, result, "f64: -1.234e+11\n"));1077 testing.expect(mem.eql(u8, result, "f64: -1.234e+11\n"));
1036 }1078 }
1037 {1079 {
1038 // This fails on release due to a minor rounding difference.1080 // This fails on release due to a minor rounding difference.
...@@ -1042,26 +1084,26 @@ test "fmt.format" {...@@ -1042,26 +1084,26 @@ test "fmt.format" {
1042 var buf1: [32]u8 = undefined;1084 var buf1: [32]u8 = undefined;
1043 const value: f64 = 9.999960e-40;1085 const value: f64 = 9.999960e-40;
1044 const result = try bufPrint(buf1[0..], "f64: {e}\n", value);1086 const result = try bufPrint(buf1[0..], "f64: {e}\n", value);
1045 assert(mem.eql(u8, result, "f64: 9.99996e-40\n"));1087 testing.expect(mem.eql(u8, result, "f64: 9.99996e-40\n"));
1046 }1088 }
1047 }1089 }
1048 {1090 {
1049 var buf1: [32]u8 = undefined;1091 var buf1: [32]u8 = undefined;
1050 const value: f64 = 1.409706e-42;1092 const value: f64 = 1.409706e-42;
1051 const result = try bufPrint(buf1[0..], "f64: {e5}\n", value);1093 const result = try bufPrint(buf1[0..], "f64: {e5}\n", value);
1052 assert(mem.eql(u8, result, "f64: 1.40971e-42\n"));1094 testing.expect(mem.eql(u8, result, "f64: 1.40971e-42\n"));
1053 }1095 }
1054 {1096 {
1055 var buf1: [32]u8 = undefined;1097 var buf1: [32]u8 = undefined;
1056 const value: f64 = @bitCast(f32, u32(814313563));1098 const value: f64 = @bitCast(f32, u32(814313563));
1057 const result = try bufPrint(buf1[0..], "f64: {e5}\n", value);1099 const result = try bufPrint(buf1[0..], "f64: {e5}\n", value);
1058 assert(mem.eql(u8, result, "f64: 1.00000e-09\n"));1100 testing.expect(mem.eql(u8, result, "f64: 1.00000e-09\n"));
1059 }1101 }
1060 {1102 {
1061 var buf1: [32]u8 = undefined;1103 var buf1: [32]u8 = undefined;
1062 const value: f64 = @bitCast(f32, u32(1006632960));1104 const value: f64 = @bitCast(f32, u32(1006632960));
1063 const result = try bufPrint(buf1[0..], "f64: {e5}\n", value);1105 const result = try bufPrint(buf1[0..], "f64: {e5}\n", value);
1064 assert(mem.eql(u8, result, "f64: 7.81250e-03\n"));1106 testing.expect(mem.eql(u8, result, "f64: 7.81250e-03\n"));
1065 }1107 }
1066 {1108 {
1067 // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.1109 // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.
...@@ -1069,47 +1111,47 @@ test "fmt.format" {...@@ -1069,47 +1111,47 @@ test "fmt.format" {
1069 var buf1: [32]u8 = undefined;1111 var buf1: [32]u8 = undefined;
1070 const value: f64 = @bitCast(f32, u32(1203982400));1112 const value: f64 = @bitCast(f32, u32(1203982400));
1071 const result = try bufPrint(buf1[0..], "f64: {e5}\n", value);1113 const result = try bufPrint(buf1[0..], "f64: {e5}\n", value);
1072 assert(mem.eql(u8, result, "f64: 1.00001e+05\n"));1114 testing.expect(mem.eql(u8, result, "f64: 1.00001e+05\n"));
1073 }1115 }
1074 {1116 {
1075 var buf1: [32]u8 = undefined;1117 var buf1: [32]u8 = undefined;
1076 const result = try bufPrint(buf1[0..], "f64: {}\n", math.nan_f64);1118 const result = try bufPrint(buf1[0..], "f64: {}\n", math.nan_f64);
1077 assert(mem.eql(u8, result, "f64: nan\n"));1119 testing.expect(mem.eql(u8, result, "f64: nan\n"));
1078 }1120 }
1079 if (builtin.arch != builtin.Arch.armv8) {1121 if (builtin.arch != builtin.Arch.armv8) {
1080 // negative nan is not defined by IEE 754,1122 // negative nan is not defined by IEE 754,
1081 // and ARM thus normalizes it to positive nan1123 // and ARM thus normalizes it to positive nan
1082 var buf1: [32]u8 = undefined;1124 var buf1: [32]u8 = undefined;
1083 const result = try bufPrint(buf1[0..], "f64: {}\n", -math.nan_f64);1125 const result = try bufPrint(buf1[0..], "f64: {}\n", -math.nan_f64);
1084 assert(mem.eql(u8, result, "f64: -nan\n"));1126 testing.expect(mem.eql(u8, result, "f64: -nan\n"));
1085 }1127 }
1086 {1128 {
1087 var buf1: [32]u8 = undefined;1129 var buf1: [32]u8 = undefined;
1088 const result = try bufPrint(buf1[0..], "f64: {}\n", math.inf_f64);1130 const result = try bufPrint(buf1[0..], "f64: {}\n", math.inf_f64);
1089 assert(mem.eql(u8, result, "f64: inf\n"));1131 testing.expect(mem.eql(u8, result, "f64: inf\n"));
1090 }1132 }
1091 {1133 {
1092 var buf1: [32]u8 = undefined;1134 var buf1: [32]u8 = undefined;
1093 const result = try bufPrint(buf1[0..], "f64: {}\n", -math.inf_f64);1135 const result = try bufPrint(buf1[0..], "f64: {}\n", -math.inf_f64);
1094 assert(mem.eql(u8, result, "f64: -inf\n"));1136 testing.expect(mem.eql(u8, result, "f64: -inf\n"));
1095 }1137 }
1096 {1138 {
1097 var buf1: [64]u8 = undefined;1139 var buf1: [64]u8 = undefined;
1098 const value: f64 = 1.52314e+29;1140 const value: f64 = 1.52314e+29;
1099 const result = try bufPrint(buf1[0..], "f64: {.}\n", value);1141 const result = try bufPrint(buf1[0..], "f64: {.}\n", value);
1100 assert(mem.eql(u8, result, "f64: 152314000000000000000000000000\n"));1142 testing.expect(mem.eql(u8, result, "f64: 152314000000000000000000000000\n"));
1101 }1143 }
1102 {1144 {
1103 var buf1: [32]u8 = undefined;1145 var buf1: [32]u8 = undefined;
1104 const value: f32 = 1.1234;1146 const value: f32 = 1.1234;
1105 const result = try bufPrint(buf1[0..], "f32: {.1}\n", value);1147 const result = try bufPrint(buf1[0..], "f32: {.1}\n", value);
1106 assert(mem.eql(u8, result, "f32: 1.1\n"));1148 testing.expect(mem.eql(u8, result, "f32: 1.1\n"));
1107 }1149 }
1108 {1150 {
1109 var buf1: [32]u8 = undefined;1151 var buf1: [32]u8 = undefined;
1110 const value: f32 = 1234.567;1152 const value: f32 = 1234.567;
1111 const result = try bufPrint(buf1[0..], "f32: {.2}\n", value);1153 const result = try bufPrint(buf1[0..], "f32: {.2}\n", value);
1112 assert(mem.eql(u8, result, "f32: 1234.57\n"));1154 testing.expect(mem.eql(u8, result, "f32: 1234.57\n"));
1113 }1155 }
1114 {1156 {
1115 var buf1: [32]u8 = undefined;1157 var buf1: [32]u8 = undefined;
...@@ -1117,92 +1159,92 @@ test "fmt.format" {...@@ -1117,92 +1159,92 @@ test "fmt.format" {
1117 const result = try bufPrint(buf1[0..], "f32: {.4}\n", value);1159 const result = try bufPrint(buf1[0..], "f32: {.4}\n", value);
1118 // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).1160 // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
1119 // -11.12339... is rounded back up to -11.12341161 // -11.12339... is rounded back up to -11.1234
1120 assert(mem.eql(u8, result, "f32: -11.1234\n"));1162 testing.expect(mem.eql(u8, result, "f32: -11.1234\n"));
1121 }1163 }
1122 {1164 {
1123 var buf1: [32]u8 = undefined;1165 var buf1: [32]u8 = undefined;
1124 const value: f32 = 91.12345;1166 const value: f32 = 91.12345;
1125 const result = try bufPrint(buf1[0..], "f32: {.5}\n", value);1167 const result = try bufPrint(buf1[0..], "f32: {.5}\n", value);
1126 assert(mem.eql(u8, result, "f32: 91.12345\n"));1168 testing.expect(mem.eql(u8, result, "f32: 91.12345\n"));
1127 }1169 }
1128 {1170 {
1129 var buf1: [32]u8 = undefined;1171 var buf1: [32]u8 = undefined;
1130 const value: f64 = 91.12345678901235;1172 const value: f64 = 91.12345678901235;
1131 const result = try bufPrint(buf1[0..], "f64: {.10}\n", value);1173 const result = try bufPrint(buf1[0..], "f64: {.10}\n", value);
1132 assert(mem.eql(u8, result, "f64: 91.1234567890\n"));1174 testing.expect(mem.eql(u8, result, "f64: 91.1234567890\n"));
1133 }1175 }
1134 {1176 {
1135 var buf1: [32]u8 = undefined;1177 var buf1: [32]u8 = undefined;
1136 const value: f64 = 0.0;1178 const value: f64 = 0.0;
1137 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);1179 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1138 assert(mem.eql(u8, result, "f64: 0.00000\n"));1180 testing.expect(mem.eql(u8, result, "f64: 0.00000\n"));
1139 }1181 }
1140 {1182 {
1141 var buf1: [32]u8 = undefined;1183 var buf1: [32]u8 = undefined;
1142 const value: f64 = 5.700;1184 const value: f64 = 5.700;
1143 const result = try bufPrint(buf1[0..], "f64: {.0}\n", value);1185 const result = try bufPrint(buf1[0..], "f64: {.0}\n", value);
1144 assert(mem.eql(u8, result, "f64: 6\n"));1186 testing.expect(mem.eql(u8, result, "f64: 6\n"));
1145 }1187 }
1146 {1188 {
1147 var buf1: [32]u8 = undefined;1189 var buf1: [32]u8 = undefined;
1148 const value: f64 = 9.999;1190 const value: f64 = 9.999;
1149 const result = try bufPrint(buf1[0..], "f64: {.1}\n", value);1191 const result = try bufPrint(buf1[0..], "f64: {.1}\n", value);
1150 assert(mem.eql(u8, result, "f64: 10.0\n"));1192 testing.expect(mem.eql(u8, result, "f64: 10.0\n"));
1151 }1193 }
1152 {1194 {
1153 var buf1: [32]u8 = undefined;1195 var buf1: [32]u8 = undefined;
1154 const value: f64 = 1.0;1196 const value: f64 = 1.0;
1155 const result = try bufPrint(buf1[0..], "f64: {.3}\n", value);1197 const result = try bufPrint(buf1[0..], "f64: {.3}\n", value);
1156 assert(mem.eql(u8, result, "f64: 1.000\n"));1198 testing.expect(mem.eql(u8, result, "f64: 1.000\n"));
1157 }1199 }
1158 {1200 {
1159 var buf1: [32]u8 = undefined;1201 var buf1: [32]u8 = undefined;
1160 const value: f64 = 0.0003;1202 const value: f64 = 0.0003;
1161 const result = try bufPrint(buf1[0..], "f64: {.8}\n", value);1203 const result = try bufPrint(buf1[0..], "f64: {.8}\n", value);
1162 assert(mem.eql(u8, result, "f64: 0.00030000\n"));1204 testing.expect(mem.eql(u8, result, "f64: 0.00030000\n"));
1163 }1205 }
1164 {1206 {
1165 var buf1: [32]u8 = undefined;1207 var buf1: [32]u8 = undefined;
1166 const value: f64 = 1.40130e-45;1208 const value: f64 = 1.40130e-45;
1167 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);1209 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1168 assert(mem.eql(u8, result, "f64: 0.00000\n"));1210 testing.expect(mem.eql(u8, result, "f64: 0.00000\n"));
1169 }1211 }
1170 {1212 {
1171 var buf1: [32]u8 = undefined;1213 var buf1: [32]u8 = undefined;
1172 const value: f64 = 9.999960e-40;1214 const value: f64 = 9.999960e-40;
1173 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);1215 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1174 assert(mem.eql(u8, result, "f64: 0.00000\n"));1216 testing.expect(mem.eql(u8, result, "f64: 0.00000\n"));
1175 }1217 }
1176 // libc checks1218 // libc checks
1177 {1219 {
1178 var buf1: [32]u8 = undefined;1220 var buf1: [32]u8 = undefined;
1179 const value: f64 = f64(@bitCast(f32, u32(916964781)));1221 const value: f64 = f64(@bitCast(f32, u32(916964781)));
1180 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);1222 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1181 assert(mem.eql(u8, result, "f64: 0.00001\n"));1223 testing.expect(mem.eql(u8, result, "f64: 0.00001\n"));
1182 }1224 }
1183 {1225 {
1184 var buf1: [32]u8 = undefined;1226 var buf1: [32]u8 = undefined;
1185 const value: f64 = f64(@bitCast(f32, u32(925353389)));1227 const value: f64 = f64(@bitCast(f32, u32(925353389)));
1186 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);1228 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1187 assert(mem.eql(u8, result, "f64: 0.00001\n"));1229 testing.expect(mem.eql(u8, result, "f64: 0.00001\n"));
1188 }1230 }
1189 {1231 {
1190 var buf1: [32]u8 = undefined;1232 var buf1: [32]u8 = undefined;
1191 const value: f64 = f64(@bitCast(f32, u32(1036831278)));1233 const value: f64 = f64(@bitCast(f32, u32(1036831278)));
1192 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);1234 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1193 assert(mem.eql(u8, result, "f64: 0.10000\n"));1235 testing.expect(mem.eql(u8, result, "f64: 0.10000\n"));
1194 }1236 }
1195 {1237 {
1196 var buf1: [32]u8 = undefined;1238 var buf1: [32]u8 = undefined;
1197 const value: f64 = f64(@bitCast(f32, u32(1065353133)));1239 const value: f64 = f64(@bitCast(f32, u32(1065353133)));
1198 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);1240 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1199 assert(mem.eql(u8, result, "f64: 1.00000\n"));1241 testing.expect(mem.eql(u8, result, "f64: 1.00000\n"));
1200 }1242 }
1201 {1243 {
1202 var buf1: [32]u8 = undefined;1244 var buf1: [32]u8 = undefined;
1203 const value: f64 = f64(@bitCast(f32, u32(1092616192)));1245 const value: f64 = f64(@bitCast(f32, u32(1092616192)));
1204 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);1246 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1205 assert(mem.eql(u8, result, "f64: 10.00000\n"));1247 testing.expect(mem.eql(u8, result, "f64: 10.00000\n"));
1206 }1248 }
1207 // libc differences1249 // libc differences
1208 {1250 {
...@@ -1212,7 +1254,7 @@ test "fmt.format" {...@@ -1212,7 +1254,7 @@ test "fmt.format" {
1212 // floats of the form x.yyyy25 on a precision point.1254 // floats of the form x.yyyy25 on a precision point.
1213 const value: f64 = f64(@bitCast(f32, u32(1015021568)));1255 const value: f64 = f64(@bitCast(f32, u32(1015021568)));
1214 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);1256 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1215 assert(mem.eql(u8, result, "f64: 0.01563\n"));1257 testing.expect(mem.eql(u8, result, "f64: 0.01563\n"));
1216 }1258 }
1217 // std-windows-x86_64-Debug-bare test case fails1259 // std-windows-x86_64-Debug-bare test case fails
1218 {1260 {
...@@ -1222,7 +1264,7 @@ test "fmt.format" {...@@ -1222,7 +1264,7 @@ test "fmt.format" {
1222 var buf1: [32]u8 = undefined;1264 var buf1: [32]u8 = undefined;
1223 const value: f64 = f64(@bitCast(f32, u32(1518338049)));1265 const value: f64 = f64(@bitCast(f32, u32(1518338049)));
1224 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);1266 const result = try bufPrint(buf1[0..], "f64: {.5}\n", value);
1225 assert(mem.eql(u8, result, "f64: 18014400656965630.00000\n"));1267 testing.expect(mem.eql(u8, result, "f64: 18014400656965630.00000\n"));
1226 }1268 }
1227 //custom type format1269 //custom type format
1228 {1270 {
...@@ -1303,10 +1345,10 @@ test "fmt.format" {...@@ -1303,10 +1345,10 @@ test "fmt.format" {
13031345
1304 var buf: [100]u8 = undefined;1346 var buf: [100]u8 = undefined;
1305 const uu_result = try bufPrint(buf[0..], "{}", uu_inst);1347 const uu_result = try bufPrint(buf[0..], "{}", uu_inst);
1306 debug.assert(mem.eql(u8, uu_result[0..3], "UU@"));1348 testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
13071349
1308 const eu_result = try bufPrint(buf[0..], "{}", eu_inst);1350 const eu_result = try bufPrint(buf[0..], "{}", eu_inst);
1309 debug.assert(mem.eql(u8, uu_result[0..3], "EU@"));1351 testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
1310 }1352 }
1311 //enum format1353 //enum format
1312 {1354 {
...@@ -1365,11 +1407,11 @@ pub fn trim(buf: []const u8) []const u8 {...@@ -1365,11 +1407,11 @@ pub fn trim(buf: []const u8) []const u8 {
1365}1407}
13661408
1367test "fmt.trim" {1409test "fmt.trim" {
1368 assert(mem.eql(u8, "abc", trim("\n abc \t")));1410 testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
1369 assert(mem.eql(u8, "", trim(" ")));1411 testing.expect(mem.eql(u8, "", trim(" ")));
1370 assert(mem.eql(u8, "", trim("")));1412 testing.expect(mem.eql(u8, "", trim("")));
1371 assert(mem.eql(u8, "abc", trim(" abc")));1413 testing.expect(mem.eql(u8, "abc", trim(" abc")));
1372 assert(mem.eql(u8, "abc", trim("abc ")));1414 testing.expect(mem.eql(u8, "abc", trim("abc ")));
1373}1415}
13741416
1375pub fn isWhiteSpace(byte: u8) bool {1417pub fn isWhiteSpace(byte: u8) bool {
std/fmt/parse_float.zig created+420
...@@ -0,0 +1,420 @@
1// Adapted from https://github.com/grzegorz-kraszewski/stringtofloat.
2
3// MIT License
4//
5// Copyright (c) 2016 Grzegorz Kraszewski
6//
7// Permission is hereby granted, free of charge, to any person obtaining a copy
8// of this software and associated documentation files (the "Software"), to deal
9// in the Software without restriction, including without limitation the rights
10// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11// copies of the Software, and to permit persons to whom the Software is
12// furnished to do so, subject to the following conditions:
13//
14// The above copyright notice and this permission notice shall be included in all
15// copies or substantial portions of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23// SOFTWARE.
24//
25
26// Be aware that this implementation has the following limitations:
27//
28// - Is not round-trip accurate for all values
29// - Only supports round-to-zero
30// - Does not handle denormals
31
32const std = @import("../index.zig");
33
34const max_digits = 25;
35
36const f64_plus_zero: u64 = 0x0000000000000000;
37const f64_minus_zero: u64 = 0x8000000000000000;
38const f64_plus_infinity: u64 = 0x7FF0000000000000;
39const f64_minus_infinity: u64 = 0xFFF0000000000000;
40
41const Z96 = struct {
42 d0: u32,
43 d1: u32,
44 d2: u32,
45
46 // d = s >> 1
47 inline fn shiftRight1(d: *Z96, s: Z96) void {
48 d.d0 = (s.d0 >> 1) | ((s.d1 & 1) << 31);
49 d.d1 = (s.d1 >> 1) | ((s.d2 & 1) << 31);
50 d.d2 = s.d2 >> 1;
51 }
52
53 // d = s << 1
54 inline fn shiftLeft1(d: *Z96, s: Z96) void {
55 d.d2 = (s.d2 << 1) | ((s.d1 & (1 << 31)) >> 31);
56 d.d1 = (s.d1 << 1) | ((s.d0 & (1 << 31)) >> 31);
57 d.d0 = s.d0 << 1;
58 }
59
60 // d += s
61 inline fn add(d: *Z96, s: Z96) void {
62 var w = u64(d.d0) + u64(s.d0);
63 d.d0 = @truncate(u32, w);
64
65 w >>= 32;
66 w += u64(d.d1) + u64(s.d1);
67 d.d1 = @truncate(u32, w);
68
69 w >>= 32;
70 w += u64(d.d2) + u64(s.d2);
71 d.d2 = @truncate(u32, w);
72 }
73
74 // d -= s
75 inline fn sub(d: *Z96, s: Z96) void {
76 var w = u64(d.d0) -% u64(s.d0);
77 d.d0 = @truncate(u32, w);
78
79 w >>= 32;
80 w += u64(d.d1) -% u64(s.d1);
81 d.d1 = @truncate(u32, w);
82
83 w >>= 32;
84 w += u64(d.d2) -% u64(s.d2);
85 d.d2 = @truncate(u32, w);
86 }
87};
88
89const FloatRepr = struct {
90 negative: bool,
91 exponent: i32,
92 mantissa: u64,
93};
94
95fn convertRepr(comptime T: type, n: FloatRepr) T {
96 const mask28: u32 = 0xf << 28;
97
98 var s: Z96 = undefined;
99 var q: Z96 = undefined;
100 var r: Z96 = undefined;
101
102 s.d0 = @truncate(u32, n.mantissa);
103 s.d1 = @truncate(u32, n.mantissa >> 32);
104 s.d2 = 0;
105
106 var binary_exponent: u64 = 92;
107 var exp = n.exponent;
108
109 while (exp > 0) : (exp -= 1) {
110 q.shiftLeft1(s); // q = p << 1
111 r.shiftLeft1(q); // r = p << 2
112 s.shiftLeft1(r); // p = p << 3
113 q.add(s); // p = (p << 3) + (p << 1)
114
115 exp -= 1;
116
117 while (s.d2 & mask28 != 0) {
118 q.shiftRight1(s);
119 binary_exponent += 1;
120 s = q;
121 }
122 }
123
124 while (exp < 0) {
125 while (s.d2 & (1 << 31) == 0) {
126 q.shiftLeft1(s);
127 binary_exponent -= 1;
128 s = q;
129 }
130
131 q.d2 = s.d2 / 10;
132 r.d1 = s.d2 % 10;
133 r.d2 = (s.d1 >> 8) | (r.d1 << 24);
134 q.d1 = r.d2 / 10;
135 r.d1 = r.d2 % 10;
136 r.d2 = ((s.d1 & 0xff) << 16) | (s.d0 >> 16) | (r.d1 << 24);
137 r.d0 = r.d2 / 10;
138 r.d1 = r.d2 % 10;
139 q.d1 = (q.d1 << 8) | ((r.d0 & 0x00ff0000) >> 16);
140 q.d0 = r.d0 << 16;
141 r.d2 = (s.d0 *% 0xffff) | (r.d1 << 16);
142 q.d0 |= r.d2 / 10;
143 s = q;
144
145 exp += 1;
146 }
147
148 if (s.d0 != 0 or s.d1 != 0 or s.d2 != 0) {
149 while (s.d2 & mask28 == 0) {
150 q.shiftLeft1(s);
151 binary_exponent -= 1;
152 s = q;
153 }
154 }
155
156 binary_exponent += 1023;
157
158 const repr: u64 = blk: {
159 if (binary_exponent > 2046) {
160 break :blk if (n.negative) f64_minus_infinity else f64_plus_infinity;
161 } else if (binary_exponent < 1) {
162 break :blk if (n.negative) f64_minus_zero else f64_plus_zero;
163 } else if (s.d2 != 0) {
164 const binexs2 = u64(binary_exponent) << 52;
165 const rr = (u64(s.d2 & ~mask28) << 24) | ((u64(s.d1) + 128) >> 8) | binexs2;
166 break :blk if (n.negative) rr | (1 << 63) else rr;
167 } else {
168 break :blk 0;
169 }
170 };
171
172 const f = @bitCast(f64, repr);
173 return @floatCast(T, f);
174}
175
176const State = enum {
177 MaybeSign,
178 LeadingMantissaZeros,
179 LeadingFractionalZeros,
180 MantissaIntegral,
181 MantissaFractional,
182 ExponentSign,
183 LeadingExponentZeros,
184 Exponent,
185};
186
187const ParseResult = enum {
188 Ok,
189 PlusZero,
190 MinusZero,
191 PlusInf,
192 MinusInf,
193};
194
195inline fn isDigit(c: u8) bool {
196 return c >= '0' and c <= '9';
197}
198
199inline fn isSpace(c: u8) bool {
200 return (c >= 0x09 and c <= 0x13) or c == 0x20;
201}
202
203fn parseRepr(s: []const u8, n: *FloatRepr) !ParseResult {
204 var digit_index: usize = 0;
205 var negative = false;
206 var negative_exp = false;
207 var exponent: i32 = 0;
208
209 var state = State.MaybeSign;
210
211 var i: usize = 0;
212 loop: while (i < s.len) {
213 const c = s[i];
214
215 switch (state) {
216 State.MaybeSign => {
217 state = State.LeadingMantissaZeros;
218
219 if (c == '+') {
220 i += 1;
221 } else if (c == '-') {
222 n.negative = true;
223 i += 1;
224 } else if (isDigit(c) or c == '.') {
225 // continue
226 } else {
227 return error.InvalidCharacter;
228 }
229 },
230
231 State.LeadingMantissaZeros => {
232 if (c == '0') {
233 i += 1;
234 } else if (c == '.') {
235 i += 1;
236 state = State.LeadingFractionalZeros;
237 } else {
238 state = State.MantissaIntegral;
239 }
240 },
241
242 State.LeadingFractionalZeros => {
243 if (c == '0') {
244 i += 1;
245 if (n.exponent > std.math.minInt(i32)) {
246 n.exponent -= 1;
247 }
248 } else {
249 state = State.MantissaFractional;
250 }
251 },
252
253 State.MantissaIntegral => {
254 if (isDigit(c)) {
255 if (digit_index < max_digits) {
256 n.mantissa *%= 10;
257 n.mantissa += s[i] - '0';
258 digit_index += 1;
259 } else if (n.exponent < std.math.maxInt(i32)) {
260 n.exponent += 1;
261 }
262
263 i += 1;
264 } else if (c == '.') {
265 i += 1;
266 state = State.MantissaFractional;
267 } else {
268 state = State.MantissaFractional;
269 }
270 },
271
272 State.MantissaFractional => {
273 if (isDigit(c)) {
274 if (digit_index < max_digits) {
275 n.mantissa *%= 10;
276 n.mantissa += c - '0';
277 n.exponent -%= 1;
278 digit_index += 1;
279 }
280
281 i += 1;
282 } else if (c == 'e' or c == 'E') {
283 i += 1;
284 state = State.ExponentSign;
285 } else {
286 state = State.ExponentSign;
287 }
288 },
289
290 State.ExponentSign => {
291 if (c == '+') {
292 i += 1;
293 } else if (c == '-') {
294 negative_exp = true;
295 i += 1;
296 }
297
298 state = State.LeadingExponentZeros;
299 },
300
301 State.LeadingExponentZeros => {
302 if (c == '0') {
303 i += 1;
304 } else {
305 state = State.Exponent;
306 }
307 },
308
309 State.Exponent => {
310 if (isDigit(c)) {
311 if (exponent < std.math.maxInt(i32)) {
312 exponent *= 10;
313 exponent += @intCast(i32, c - '0');
314 }
315
316 i += 1;
317 } else {
318 return error.InvalidCharacter;
319 }
320 },
321 }
322 }
323
324 if (negative_exp) exponent = -exponent;
325 n.exponent += exponent;
326
327 if (n.mantissa == 0) {
328 return if (n.negative) ParseResult.MinusZero else ParseResult.PlusZero;
329 } else if (n.exponent > 309) {
330 return if (n.negative) ParseResult.MinusInf else ParseResult.PlusInf;
331 } else if (n.exponent < -328) {
332 return if (n.negative) ParseResult.MinusZero else ParseResult.PlusZero;
333 }
334
335 return ParseResult.Ok;
336}
337
338inline fn isLower(c: u8) bool {
339 return c -% 'a' < 26;
340}
341
342inline fn toUpper(c: u8) u8 {
343 return if (isLower(c)) (c & 0x5f) else c;
344}
345
346fn caseInEql(a: []const u8, b: []const u8) bool {
347 if (a.len != b.len) return false;
348
349 for (a) |_, i| {
350 if (toUpper(a[i]) != toUpper(b[i])) {
351 return false;
352 }
353 }
354
355 return true;
356}
357
358pub fn parseFloat(comptime T: type, s: []const u8) !T {
359 if (s.len == 0) {
360 return error.InvalidCharacter;
361 }
362
363 if (caseInEql(s, "nan")) {
364 return std.math.nan(T);
365 } else if (caseInEql(s, "inf") or caseInEql(s, "+inf")) {
366 return std.math.inf(T);
367 } else if (caseInEql(s, "-inf")) {
368 return -std.math.inf(T);
369 }
370
371 var r = FloatRepr{
372 .negative = false,
373 .exponent = 0,
374 .mantissa = 0,
375 };
376
377 return switch (try parseRepr(s, &r)) {
378 ParseResult.Ok => convertRepr(T, r),
379 ParseResult.PlusZero => 0.0,
380 ParseResult.MinusZero => -T(0.0),
381 ParseResult.PlusInf => std.math.inf(T),
382 ParseResult.MinusInf => -std.math.inf(T),
383 };
384}
385
386test "fmt.parseFloat" {
387 const testing = std.testing;
388 const expect = testing.expect;
389 const expectEqual = testing.expectEqual;
390 const approxEq = std.math.approxEq;
391 const epsilon = 1e-7;
392
393 inline for ([]type{ f16, f32, f64, f128 }) |T| {
394 const Z = @IntType(false, T.bit_count);
395
396 testing.expectError(error.InvalidCharacter, parseFloat(T, ""));
397 testing.expectError(error.InvalidCharacter, parseFloat(T, " 1"));
398 testing.expectError(error.InvalidCharacter, parseFloat(T, "1abc"));
399
400 expectEqual(try parseFloat(T, "0"), 0.0);
401 expectEqual((try parseFloat(T, "0")), 0.0);
402 expectEqual((try parseFloat(T, "+0")), 0.0);
403 expectEqual((try parseFloat(T, "-0")), 0.0);
404
405 expect(approxEq(T, try parseFloat(T, "3.141"), 3.141, epsilon));
406 expect(approxEq(T, try parseFloat(T, "-3.141"), -3.141, epsilon));
407
408 expectEqual((try parseFloat(T, "1e-700")), 0);
409 expectEqual((try parseFloat(T, "1e+700")), std.math.inf(T));
410
411 expectEqual(@bitCast(Z, try parseFloat(T, "nAn")), @bitCast(Z, std.math.nan(T)));
412 expectEqual((try parseFloat(T, "inF")), std.math.inf(T));
413 expectEqual((try parseFloat(T, "-INF")), -std.math.inf(T));
414
415 if (T != f16) {
416 expect(approxEq(T, try parseFloat(T, "123142.1"), 123142.1, epsilon));
417 expect(approxEq(T, try parseFloat(T, "-123142.1124"), T(-123142.1124), epsilon));
418 }
419 }
420}
std/hash/adler.zig+6-6
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// https://github.com/madler/zlib/blob/master/adler32.c4// https://github.com/madler/zlib/blob/master/adler32.c
55
6const std = @import("../index.zig");6const std = @import("../index.zig");
7const debug = std.debug;7const testing = std.testing;
88
9pub const Adler32 = struct {9pub const Adler32 = struct {
10 const base = 65521;10 const base = 65521;
...@@ -89,19 +89,19 @@ pub const Adler32 = struct {...@@ -89,19 +89,19 @@ pub const Adler32 = struct {
89};89};
9090
91test "adler32 sanity" {91test "adler32 sanity" {
92 debug.assert(Adler32.hash("a") == 0x620062);92 testing.expect(Adler32.hash("a") == 0x620062);
93 debug.assert(Adler32.hash("example") == 0xbc002ed);93 testing.expect(Adler32.hash("example") == 0xbc002ed);
94}94}
9595
96test "adler32 long" {96test "adler32 long" {
97 const long1 = []u8{1} ** 1024;97 const long1 = []u8{1} ** 1024;
98 debug.assert(Adler32.hash(long1[0..]) == 0x06780401);98 testing.expect(Adler32.hash(long1[0..]) == 0x06780401);
9999
100 const long2 = []u8{1} ** 1025;100 const long2 = []u8{1} ** 1025;
101 debug.assert(Adler32.hash(long2[0..]) == 0x0a7a0402);101 testing.expect(Adler32.hash(long2[0..]) == 0x0a7a0402);
102}102}
103103
104test "adler32 very long" {104test "adler32 very long" {
105 const long = []u8{1} ** 5553;105 const long = []u8{1} ** 5553;
106 debug.assert(Adler32.hash(long[0..]) == 0x707f15b2);106 testing.expect(Adler32.hash(long[0..]) == 0x707f15b2);
107}107}
std/hash/crc.zig+13-12
...@@ -7,6 +7,7 @@...@@ -7,6 +7,7 @@
77
8const std = @import("../index.zig");8const std = @import("../index.zig");
9const debug = std.debug;9const debug = std.debug;
10const testing = std.testing;
1011
11pub const Polynomial = struct {12pub const Polynomial = struct {
12 const IEEE = 0xedb88320;13 const IEEE = 0xedb88320;
...@@ -101,17 +102,17 @@ pub fn Crc32WithPoly(comptime poly: u32) type {...@@ -101,17 +102,17 @@ pub fn Crc32WithPoly(comptime poly: u32) type {
101test "crc32 ieee" {102test "crc32 ieee" {
102 const Crc32Ieee = Crc32WithPoly(Polynomial.IEEE);103 const Crc32Ieee = Crc32WithPoly(Polynomial.IEEE);
103104
104 debug.assert(Crc32Ieee.hash("") == 0x00000000);105 testing.expect(Crc32Ieee.hash("") == 0x00000000);
105 debug.assert(Crc32Ieee.hash("a") == 0xe8b7be43);106 testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43);
106 debug.assert(Crc32Ieee.hash("abc") == 0x352441c2);107 testing.expect(Crc32Ieee.hash("abc") == 0x352441c2);
107}108}
108109
109test "crc32 castagnoli" {110test "crc32 castagnoli" {
110 const Crc32Castagnoli = Crc32WithPoly(Polynomial.Castagnoli);111 const Crc32Castagnoli = Crc32WithPoly(Polynomial.Castagnoli);
111112
112 debug.assert(Crc32Castagnoli.hash("") == 0x00000000);113 testing.expect(Crc32Castagnoli.hash("") == 0x00000000);
113 debug.assert(Crc32Castagnoli.hash("a") == 0xc1d04330);114 testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330);
114 debug.assert(Crc32Castagnoli.hash("abc") == 0x364b3fb7);115 testing.expect(Crc32Castagnoli.hash("abc") == 0x364b3fb7);
115}116}
116117
117// half-byte lookup table implementation.118// half-byte lookup table implementation.
...@@ -165,15 +166,15 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type {...@@ -165,15 +166,15 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type {
165test "small crc32 ieee" {166test "small crc32 ieee" {
166 const Crc32Ieee = Crc32SmallWithPoly(Polynomial.IEEE);167 const Crc32Ieee = Crc32SmallWithPoly(Polynomial.IEEE);
167168
168 debug.assert(Crc32Ieee.hash("") == 0x00000000);169 testing.expect(Crc32Ieee.hash("") == 0x00000000);
169 debug.assert(Crc32Ieee.hash("a") == 0xe8b7be43);170 testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43);
170 debug.assert(Crc32Ieee.hash("abc") == 0x352441c2);171 testing.expect(Crc32Ieee.hash("abc") == 0x352441c2);
171}172}
172173
173test "small crc32 castagnoli" {174test "small crc32 castagnoli" {
174 const Crc32Castagnoli = Crc32SmallWithPoly(Polynomial.Castagnoli);175 const Crc32Castagnoli = Crc32SmallWithPoly(Polynomial.Castagnoli);
175176
176 debug.assert(Crc32Castagnoli.hash("") == 0x00000000);177 testing.expect(Crc32Castagnoli.hash("") == 0x00000000);
177 debug.assert(Crc32Castagnoli.hash("a") == 0xc1d04330);178 testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330);
178 debug.assert(Crc32Castagnoli.hash("abc") == 0x364b3fb7);179 testing.expect(Crc32Castagnoli.hash("abc") == 0x364b3fb7);
179}180}
std/hash/fnv.zig+9-9
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5// https://tools.ietf.org/html/draft-eastlake-fnv-145// https://tools.ietf.org/html/draft-eastlake-fnv-14
66
7const std = @import("../index.zig");7const std = @import("../index.zig");
8const debug = std.debug;8const testing = std.testing;
99
10pub const Fnv1a_32 = Fnv1a(u32, 0x01000193, 0x811c9dc5);10pub const Fnv1a_32 = Fnv1a(u32, 0x01000193, 0x811c9dc5);
11pub const Fnv1a_64 = Fnv1a(u64, 0x100000001b3, 0xcbf29ce484222325);11pub const Fnv1a_64 = Fnv1a(u64, 0x100000001b3, 0xcbf29ce484222325);
...@@ -41,18 +41,18 @@ fn Fnv1a(comptime T: type, comptime prime: T, comptime offset: T) type {...@@ -41,18 +41,18 @@ fn Fnv1a(comptime T: type, comptime prime: T, comptime offset: T) type {
41}41}
4242
43test "fnv1a-32" {43test "fnv1a-32" {
44 debug.assert(Fnv1a_32.hash("") == 0x811c9dc5);44 testing.expect(Fnv1a_32.hash("") == 0x811c9dc5);
45 debug.assert(Fnv1a_32.hash("a") == 0xe40c292c);45 testing.expect(Fnv1a_32.hash("a") == 0xe40c292c);
46 debug.assert(Fnv1a_32.hash("foobar") == 0xbf9cf968);46 testing.expect(Fnv1a_32.hash("foobar") == 0xbf9cf968);
47}47}
4848
49test "fnv1a-64" {49test "fnv1a-64" {
50 debug.assert(Fnv1a_64.hash("") == 0xcbf29ce484222325);50 testing.expect(Fnv1a_64.hash("") == 0xcbf29ce484222325);
51 debug.assert(Fnv1a_64.hash("a") == 0xaf63dc4c8601ec8c);51 testing.expect(Fnv1a_64.hash("a") == 0xaf63dc4c8601ec8c);
52 debug.assert(Fnv1a_64.hash("foobar") == 0x85944171f73967e8);52 testing.expect(Fnv1a_64.hash("foobar") == 0x85944171f73967e8);
53}53}
5454
55test "fnv1a-128" {55test "fnv1a-128" {
56 debug.assert(Fnv1a_128.hash("") == 0x6c62272e07bb014262b821756295c58d);56 testing.expect(Fnv1a_128.hash("") == 0x6c62272e07bb014262b821756295c58d);
57 debug.assert(Fnv1a_128.hash("a") == 0xd228cb696f1a8caf78912b704e4a8964);57 testing.expect(Fnv1a_128.hash("a") == 0xd228cb696f1a8caf78912b704e4a8964);
58}58}
std/hash/siphash.zig+15-14
...@@ -6,7 +6,8 @@...@@ -6,7 +6,8 @@
6// https://131002.net/siphash/6// https://131002.net/siphash/
77
8const std = @import("../index.zig");8const std = @import("../index.zig");
9const debug = std.debug;9const assert = std.debug.assert;
10const testing = std.testing;
10const math = std.math;11const math = std.math;
11const mem = std.mem;12const mem = std.mem;
1213
...@@ -21,8 +22,8 @@ pub fn SipHash128(comptime c_rounds: usize, comptime d_rounds: usize) type {...@@ -21,8 +22,8 @@ pub fn SipHash128(comptime c_rounds: usize, comptime d_rounds: usize) type {
21}22}
2223
23fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) type {24fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) type {
24 debug.assert(T == u64 or T == u128);25 assert(T == u64 or T == u128);
25 debug.assert(c_rounds > 0 and d_rounds > 0);26 assert(c_rounds > 0 and d_rounds > 0);
2627
27 return struct {28 return struct {
28 const Self = @This();29 const Self = @This();
...@@ -40,10 +41,10 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)...@@ -40,10 +41,10 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
40 msg_len: u8,41 msg_len: u8,
4142
42 pub fn init(key: []const u8) Self {43 pub fn init(key: []const u8) Self {
43 debug.assert(key.len >= 16);44 assert(key.len >= 16);
4445
45 const k0 = mem.readInt(key[0..8], u64, Endian.Little);46 const k0 = mem.readIntSliceLittle(u64, key[0..8]);
46 const k1 = mem.readInt(key[8..16], u64, Endian.Little);47 const k1 = mem.readIntSliceLittle(u64, key[8..16]);
4748
48 var d = Self{49 var d = Self{
49 .v0 = k0 ^ 0x736f6d6570736575,50 .v0 = k0 ^ 0x736f6d6570736575,
...@@ -119,9 +120,9 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)...@@ -119,9 +120,9 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
119 }120 }
120121
121 fn round(d: *Self, b: []const u8) void {122 fn round(d: *Self, b: []const u8) void {
122 debug.assert(b.len == 8);123 assert(b.len == 8);
123124
124 const m = mem.readInt(b[0..], u64, Endian.Little);125 const m = mem.readIntSliceLittle(u64, b[0..]);
125 d.v3 ^= m;126 d.v3 ^= m;
126127
127 comptime var i: usize = 0;128 comptime var i: usize = 0;
...@@ -162,7 +163,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)...@@ -162,7 +163,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
162const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";163const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";
163164
164test "siphash64-2-4 sanity" {165test "siphash64-2-4 sanity" {
165 const vectors = [][]const u8{166 const vectors = [][8]u8{
166 "\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // ""167 "\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // ""
167 "\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00"168 "\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00"
168 "\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc169 "\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc
...@@ -235,13 +236,13 @@ test "siphash64-2-4 sanity" {...@@ -235,13 +236,13 @@ test "siphash64-2-4 sanity" {
235 for (vectors) |vector, i| {236 for (vectors) |vector, i| {
236 buffer[i] = @intCast(u8, i);237 buffer[i] = @intCast(u8, i);
237238
238 const expected = mem.readInt(vector, u64, Endian.Little);239 const expected = mem.readIntLittle(u64, &vector);
239 debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);240 testing.expect(siphash.hash(test_key, buffer[0..i]) == expected);
240 }241 }
241}242}
242243
243test "siphash128-2-4 sanity" {244test "siphash128-2-4 sanity" {
244 const vectors = [][]const u8{245 const vectors = [][16]u8{
245 "\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93",246 "\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93",
246 "\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45",247 "\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45",
247 "\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4",248 "\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4",
...@@ -314,7 +315,7 @@ test "siphash128-2-4 sanity" {...@@ -314,7 +315,7 @@ test "siphash128-2-4 sanity" {
314 for (vectors) |vector, i| {315 for (vectors) |vector, i| {
315 buffer[i] = @intCast(u8, i);316 buffer[i] = @intCast(u8, i);
316317
317 const expected = mem.readInt(vector, u128, Endian.Little);318 const expected = mem.readIntLittle(u128, &vector);
318 debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);319 testing.expect(siphash.hash(test_key, buffer[0..i]) == expected);
319 }320 }
320}321}
std/hash_map.zig+34-29
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const std = @import("index.zig");1const std = @import("index.zig");
2const debug = std.debug;2const debug = std.debug;
3const assert = debug.assert;3const assert = debug.assert;
4const testing = std.testing;
4const math = std.math;5const math = std.math;
5const mem = std.mem;6const mem = std.mem;
6const Allocator = mem.Allocator;7const Allocator = mem.Allocator;
...@@ -342,37 +343,37 @@ test "basic hash map usage" {...@@ -342,37 +343,37 @@ test "basic hash map usage" {
342 var map = AutoHashMap(i32, i32).init(&direct_allocator.allocator);343 var map = AutoHashMap(i32, i32).init(&direct_allocator.allocator);
343 defer map.deinit();344 defer map.deinit();
344345
345 assert((try map.put(1, 11)) == null);346 testing.expect((try map.put(1, 11)) == null);
346 assert((try map.put(2, 22)) == null);347 testing.expect((try map.put(2, 22)) == null);
347 assert((try map.put(3, 33)) == null);348 testing.expect((try map.put(3, 33)) == null);
348 assert((try map.put(4, 44)) == null);349 testing.expect((try map.put(4, 44)) == null);
349 assert((try map.put(5, 55)) == null);350 testing.expect((try map.put(5, 55)) == null);
350351
351 assert((try map.put(5, 66)).?.value == 55);352 testing.expect((try map.put(5, 66)).?.value == 55);
352 assert((try map.put(5, 55)).?.value == 66);353 testing.expect((try map.put(5, 55)).?.value == 66);
353354
354 const gop1 = try map.getOrPut(5);355 const gop1 = try map.getOrPut(5);
355 assert(gop1.found_existing == true);356 testing.expect(gop1.found_existing == true);
356 assert(gop1.kv.value == 55);357 testing.expect(gop1.kv.value == 55);
357 gop1.kv.value = 77;358 gop1.kv.value = 77;
358 assert(map.get(5).?.value == 77);359 testing.expect(map.get(5).?.value == 77);
359360
360 const gop2 = try map.getOrPut(99);361 const gop2 = try map.getOrPut(99);
361 assert(gop2.found_existing == false);362 testing.expect(gop2.found_existing == false);
362 gop2.kv.value = 42;363 gop2.kv.value = 42;
363 assert(map.get(99).?.value == 42);364 testing.expect(map.get(99).?.value == 42);
364365
365 const gop3 = try map.getOrPutValue(5, 5);366 const gop3 = try map.getOrPutValue(5, 5);
366 assert(gop3.value == 77);367 testing.expect(gop3.value == 77);
367368
368 const gop4 = try map.getOrPutValue(100, 41);369 const gop4 = try map.getOrPutValue(100, 41);
369 assert(gop4.value == 41);370 testing.expect(gop4.value == 41);
370371
371 assert(map.contains(2));372 testing.expect(map.contains(2));
372 assert(map.get(2).?.value == 22);373 testing.expect(map.get(2).?.value == 22);
373 _ = map.remove(2);374 _ = map.remove(2);
374 assert(map.remove(2) == null);375 testing.expect(map.remove(2) == null);
375 assert(map.get(2) == null);376 testing.expect(map.get(2) == null);
376}377}
377378
378test "iterator hash map" {379test "iterator hash map" {
...@@ -382,9 +383,9 @@ test "iterator hash map" {...@@ -382,9 +383,9 @@ test "iterator hash map" {
382 var reset_map = AutoHashMap(i32, i32).init(&direct_allocator.allocator);383 var reset_map = AutoHashMap(i32, i32).init(&direct_allocator.allocator);
383 defer reset_map.deinit();384 defer reset_map.deinit();
384385
385 assert((try reset_map.put(1, 11)) == null);386 testing.expect((try reset_map.put(1, 11)) == null);
386 assert((try reset_map.put(2, 22)) == null);387 testing.expect((try reset_map.put(2, 22)) == null);
387 assert((try reset_map.put(3, 33)) == null);388 testing.expect((try reset_map.put(3, 33)) == null);
388389
389 var keys = []i32{390 var keys = []i32{
390 3,391 3,
...@@ -400,26 +401,26 @@ test "iterator hash map" {...@@ -400,26 +401,26 @@ test "iterator hash map" {
400 var it = reset_map.iterator();401 var it = reset_map.iterator();
401 var count: usize = 0;402 var count: usize = 0;
402 while (it.next()) |next| {403 while (it.next()) |next| {
403 assert(next.key == keys[count]);404 testing.expect(next.key == keys[count]);
404 assert(next.value == values[count]);405 testing.expect(next.value == values[count]);
405 count += 1;406 count += 1;
406 }407 }
407408
408 assert(count == 3);409 testing.expect(count == 3);
409 assert(it.next() == null);410 testing.expect(it.next() == null);
410 it.reset();411 it.reset();
411 count = 0;412 count = 0;
412 while (it.next()) |next| {413 while (it.next()) |next| {
413 assert(next.key == keys[count]);414 testing.expect(next.key == keys[count]);
414 assert(next.value == values[count]);415 testing.expect(next.value == values[count]);
415 count += 1;416 count += 1;
416 if (count == 2) break;417 if (count == 2) break;
417 }418 }
418419
419 it.reset();420 it.reset();
420 var entry = it.next().?;421 var entry = it.next().?;
421 assert(entry.key == keys[0]);422 testing.expect(entry.key == keys[0]);
422 assert(entry.value == values[0]);423 testing.expect(entry.value == values[0]);
423}424}
424425
425pub fn getHashPtrAddrFn(comptime K: type) (fn (K) u32) {426pub fn getHashPtrAddrFn(comptime K: type) (fn (K) u32) {
...@@ -495,6 +496,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type...@@ -495,6 +496,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type
495 builtin.TypeId.Pointer => |info| switch (info.size) {496 builtin.TypeId.Pointer => |info| switch (info.size) {
496 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto hash for single item pointers"),497 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto hash for single item pointers"),
497 builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto hash for many item pointers"),498 builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto hash for many item pointers"),
499 builtin.TypeInfo.Pointer.Size.C => @compileError("TODO auto hash C pointers"),
498 builtin.TypeInfo.Pointer.Size.Slice => {500 builtin.TypeInfo.Pointer.Size.Slice => {
499 const interval = std.math.max(1, key.len / 256);501 const interval = std.math.max(1, key.len / 256);
500 var i: usize = 0;502 var i: usize = 0;
...@@ -508,6 +510,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type...@@ -508,6 +510,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type
508510
509 builtin.TypeId.Optional => @compileError("TODO auto hash for optionals"),511 builtin.TypeId.Optional => @compileError("TODO auto hash for optionals"),
510 builtin.TypeId.Array => @compileError("TODO auto hash for arrays"),512 builtin.TypeId.Array => @compileError("TODO auto hash for arrays"),
513 builtin.TypeId.Vector => @compileError("TODO auto hash for vectors"),
511 builtin.TypeId.Struct => @compileError("TODO auto hash for structs"),514 builtin.TypeId.Struct => @compileError("TODO auto hash for structs"),
512 builtin.TypeId.Union => @compileError("TODO auto hash for unions"),515 builtin.TypeId.Union => @compileError("TODO auto hash for unions"),
513 builtin.TypeId.ErrorUnion => @compileError("TODO auto hash for unions"),516 builtin.TypeId.ErrorUnion => @compileError("TODO auto hash for unions"),
...@@ -541,6 +544,7 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {...@@ -541,6 +544,7 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {
541 builtin.TypeId.Pointer => |info| switch (info.size) {544 builtin.TypeId.Pointer => |info| switch (info.size) {
542 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto eql for single item pointers"),545 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto eql for single item pointers"),
543 builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto eql for many item pointers"),546 builtin.TypeInfo.Pointer.Size.Many => @compileError("TODO auto eql for many item pointers"),
547 builtin.TypeInfo.Pointer.Size.C => @compileError("TODO auto eql for C pointers"),
544 builtin.TypeInfo.Pointer.Size.Slice => {548 builtin.TypeInfo.Pointer.Size.Slice => {
545 if (a.len != b.len) return false;549 if (a.len != b.len) return false;
546 for (a) |a_item, i| {550 for (a) |a_item, i| {
...@@ -555,5 +559,6 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {...@@ -555,5 +559,6 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {
555 builtin.TypeId.Struct => @compileError("TODO auto eql for structs"),559 builtin.TypeId.Struct => @compileError("TODO auto eql for structs"),
556 builtin.TypeId.Union => @compileError("TODO auto eql for unions"),560 builtin.TypeId.Union => @compileError("TODO auto eql for unions"),
557 builtin.TypeId.ErrorUnion => @compileError("TODO auto eql for unions"),561 builtin.TypeId.ErrorUnion => @compileError("TODO auto eql for unions"),
562 builtin.TypeId.Vector => @compileError("TODO auto eql for vectors"),
558 }563 }
559}564}
std/heap.zig+79-74
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const std = @import("index.zig");1const std = @import("index.zig");
2const debug = std.debug;2const debug = std.debug;
3const assert = debug.assert;3const assert = debug.assert;
4const testing = std.testing;
4const mem = std.mem;5const mem = std.mem;
5const os = std.os;6const os = std.os;
6const builtin = @import("builtin");7const builtin = @import("builtin");
...@@ -66,7 +67,7 @@ pub const DirectAllocator = struct {...@@ -66,7 +67,7 @@ pub const DirectAllocator = struct {
66 }67 }
67 }68 }
6869
69 fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 {70 fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 {
70 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);71 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
7172
72 switch (builtin.os) {73 switch (builtin.os) {
...@@ -106,9 +107,7 @@ pub const DirectAllocator = struct {...@@ -106,9 +107,7 @@ pub const DirectAllocator = struct {
106 };107 };
107 const ptr = os.windows.HeapAlloc(heap_handle, 0, amt) orelse return error.OutOfMemory;108 const ptr = os.windows.HeapAlloc(heap_handle, 0, amt) orelse return error.OutOfMemory;
108 const root_addr = @ptrToInt(ptr);109 const root_addr = @ptrToInt(ptr);
109 const rem = @rem(root_addr, alignment);110 const adjusted_addr = mem.alignForward(root_addr, alignment);
110 const march_forward_bytes = if (rem == 0) 0 else (alignment - rem);
111 const adjusted_addr = root_addr + march_forward_bytes;
112 const record_addr = adjusted_addr + n;111 const record_addr = adjusted_addr + n;
113 @intToPtr(*align(1) usize, record_addr).* = root_addr;112 @intToPtr(*align(1) usize, record_addr).* = root_addr;
114 return @intToPtr([*]u8, adjusted_addr)[0..n];113 return @intToPtr([*]u8, adjusted_addr)[0..n];
...@@ -126,8 +125,7 @@ pub const DirectAllocator = struct {...@@ -126,8 +125,7 @@ pub const DirectAllocator = struct {
126 const base_addr = @ptrToInt(old_mem.ptr);125 const base_addr = @ptrToInt(old_mem.ptr);
127 const old_addr_end = base_addr + old_mem.len;126 const old_addr_end = base_addr + old_mem.len;
128 const new_addr_end = base_addr + new_size;127 const new_addr_end = base_addr + new_size;
129 const rem = @rem(new_addr_end, os.page_size);128 const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size);
130 const new_addr_end_rounded = new_addr_end + if (rem == 0) 0 else (os.page_size - rem);
131 if (old_addr_end > new_addr_end_rounded) {129 if (old_addr_end > new_addr_end_rounded) {
132 _ = os.posix.munmap(new_addr_end_rounded, old_addr_end - new_addr_end_rounded);130 _ = os.posix.munmap(new_addr_end_rounded, old_addr_end - new_addr_end_rounded);
133 }131 }
...@@ -324,51 +322,57 @@ pub const FixedBufferAllocator = struct {...@@ -324,51 +322,57 @@ pub const FixedBufferAllocator = struct {
324 fn free(allocator: *Allocator, bytes: []u8) void {}322 fn free(allocator: *Allocator, bytes: []u8) void {}
325};323};
326324
327/// lock free325pub const ThreadSafeFixedBufferAllocator = blk: {
328pub const ThreadSafeFixedBufferAllocator = struct {326 if (builtin.single_threaded) {
329 allocator: Allocator,327 break :blk FixedBufferAllocator;
330 end_index: usize,328 } else {
331 buffer: []u8,329 /// lock free
330 break :blk struct {
331 allocator: Allocator,
332 end_index: usize,
333 buffer: []u8,
334
335 pub fn init(buffer: []u8) ThreadSafeFixedBufferAllocator {
336 return ThreadSafeFixedBufferAllocator{
337 .allocator = Allocator{
338 .allocFn = alloc,
339 .reallocFn = realloc,
340 .freeFn = free,
341 },
342 .buffer = buffer,
343 .end_index = 0,
344 };
345 }
332346
333 pub fn init(buffer: []u8) ThreadSafeFixedBufferAllocator {347 fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 {
334 return ThreadSafeFixedBufferAllocator{348 const self = @fieldParentPtr(ThreadSafeFixedBufferAllocator, "allocator", allocator);
335 .allocator = Allocator{349 var end_index = @atomicLoad(usize, &self.end_index, builtin.AtomicOrder.SeqCst);
336 .allocFn = alloc,350 while (true) {
337 .reallocFn = realloc,351 const addr = @ptrToInt(self.buffer.ptr) + end_index;
338 .freeFn = free,352 const rem = @rem(addr, alignment);
339 },353 const march_forward_bytes = if (rem == 0) 0 else (alignment - rem);
340 .buffer = buffer,354 const adjusted_index = end_index + march_forward_bytes;
341 .end_index = 0,355 const new_end_index = adjusted_index + n;
342 };356 if (new_end_index > self.buffer.len) {
343 }357 return error.OutOfMemory;
358 }
359 end_index = @cmpxchgWeak(usize, &self.end_index, end_index, new_end_index, builtin.AtomicOrder.SeqCst, builtin.AtomicOrder.SeqCst) orelse return self.buffer[adjusted_index..new_end_index];
360 }
361 }
344362
345 fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 {363 fn realloc(allocator: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {
346 const self = @fieldParentPtr(ThreadSafeFixedBufferAllocator, "allocator", allocator);364 if (new_size <= old_mem.len) {
347 var end_index = @atomicLoad(usize, &self.end_index, builtin.AtomicOrder.SeqCst);365 return old_mem[0..new_size];
348 while (true) {366 } else {
349 const addr = @ptrToInt(self.buffer.ptr) + end_index;367 const result = try alloc(allocator, new_size, alignment);
350 const rem = @rem(addr, alignment);368 mem.copy(u8, result, old_mem);
351 const march_forward_bytes = if (rem == 0) 0 else (alignment - rem);369 return result;
352 const adjusted_index = end_index + march_forward_bytes;370 }
353 const new_end_index = adjusted_index + n;
354 if (new_end_index > self.buffer.len) {
355 return error.OutOfMemory;
356 }371 }
357 end_index = @cmpxchgWeak(usize, &self.end_index, end_index, new_end_index, builtin.AtomicOrder.SeqCst, builtin.AtomicOrder.SeqCst) orelse return self.buffer[adjusted_index..new_end_index];
358 }
359 }
360372
361 fn realloc(allocator: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {373 fn free(allocator: *Allocator, bytes: []u8) void {}
362 if (new_size <= old_mem.len) {374 };
363 return old_mem[0..new_size];
364 } else {
365 const result = try alloc(allocator, new_size, alignment);
366 mem.copy(u8, result, old_mem);
367 return result;
368 }
369 }375 }
370
371 fn free(allocator: *Allocator, bytes: []u8) void {}
372};376};
373377
374pub fn stackFallback(comptime size: usize, fallback_allocator: *Allocator) StackFallbackAllocator(size) {378pub fn stackFallback(comptime size: usize, fallback_allocator: *Allocator) StackFallbackAllocator(size) {
...@@ -484,11 +488,11 @@ test "FixedBufferAllocator Reuse memory on realloc" {...@@ -484,11 +488,11 @@ test "FixedBufferAllocator Reuse memory on realloc" {
484 var fixed_buffer_allocator = FixedBufferAllocator.init(small_fixed_buffer[0..]);488 var fixed_buffer_allocator = FixedBufferAllocator.init(small_fixed_buffer[0..]);
485489
486 var slice0 = try fixed_buffer_allocator.allocator.alloc(u8, 5);490 var slice0 = try fixed_buffer_allocator.allocator.alloc(u8, 5);
487 assert(slice0.len == 5);491 testing.expect(slice0.len == 5);
488 var slice1 = try fixed_buffer_allocator.allocator.realloc(u8, slice0, 10);492 var slice1 = try fixed_buffer_allocator.allocator.realloc(u8, slice0, 10);
489 assert(slice1.ptr == slice0.ptr);493 testing.expect(slice1.ptr == slice0.ptr);
490 assert(slice1.len == 10);494 testing.expect(slice1.len == 10);
491 debug.assertError(fixed_buffer_allocator.allocator.realloc(u8, slice1, 11), error.OutOfMemory);495 testing.expectError(error.OutOfMemory, fixed_buffer_allocator.allocator.realloc(u8, slice1, 11));
492 }496 }
493 // check that we don't re-use the memory if it's not the most recent block497 // check that we don't re-use the memory if it's not the most recent block
494 {498 {
...@@ -499,10 +503,10 @@ test "FixedBufferAllocator Reuse memory on realloc" {...@@ -499,10 +503,10 @@ test "FixedBufferAllocator Reuse memory on realloc" {
499 slice0[1] = 2;503 slice0[1] = 2;
500 var slice1 = try fixed_buffer_allocator.allocator.alloc(u8, 2);504 var slice1 = try fixed_buffer_allocator.allocator.alloc(u8, 2);
501 var slice2 = try fixed_buffer_allocator.allocator.realloc(u8, slice0, 4);505 var slice2 = try fixed_buffer_allocator.allocator.realloc(u8, slice0, 4);
502 assert(slice0.ptr != slice2.ptr);506 testing.expect(slice0.ptr != slice2.ptr);
503 assert(slice1.ptr != slice2.ptr);507 testing.expect(slice1.ptr != slice2.ptr);
504 assert(slice2[0] == 1);508 testing.expect(slice2[0] == 1);
505 assert(slice2[1] == 2);509 testing.expect(slice2[1] == 2);
506 }510 }
507}511}
508512
...@@ -516,27 +520,28 @@ test "ThreadSafeFixedBufferAllocator" {...@@ -516,27 +520,28 @@ test "ThreadSafeFixedBufferAllocator" {
516520
517fn testAllocator(allocator: *mem.Allocator) !void {521fn testAllocator(allocator: *mem.Allocator) !void {
518 var slice = try allocator.alloc(*i32, 100);522 var slice = try allocator.alloc(*i32, 100);
519 assert(slice.len == 100);523 testing.expect(slice.len == 100);
520 for (slice) |*item, i| {524 for (slice) |*item, i| {
521 item.* = try allocator.create(@intCast(i32, i));525 item.* = try allocator.create(i32);
526 item.*.* = @intCast(i32, i);
522 }527 }
523528
524 slice = try allocator.realloc(*i32, slice, 20000);529 slice = try allocator.realloc(*i32, slice, 20000);
525 assert(slice.len == 20000);530 testing.expect(slice.len == 20000);
526531
527 for (slice[0..100]) |item, i| {532 for (slice[0..100]) |item, i| {
528 assert(item.* == @intCast(i32, i));533 testing.expect(item.* == @intCast(i32, i));
529 allocator.destroy(item);534 allocator.destroy(item);
530 }535 }
531536
532 slice = try allocator.realloc(*i32, slice, 50);537 slice = try allocator.realloc(*i32, slice, 50);
533 assert(slice.len == 50);538 testing.expect(slice.len == 50);
534 slice = try allocator.realloc(*i32, slice, 25);539 slice = try allocator.realloc(*i32, slice, 25);
535 assert(slice.len == 25);540 testing.expect(slice.len == 25);
536 slice = try allocator.realloc(*i32, slice, 0);541 slice = try allocator.realloc(*i32, slice, 0);
537 assert(slice.len == 0);542 testing.expect(slice.len == 0);
538 slice = try allocator.realloc(*i32, slice, 10);543 slice = try allocator.realloc(*i32, slice, 10);
539 assert(slice.len == 10);544 testing.expect(slice.len == 10);
540545
541 allocator.free(slice);546 allocator.free(slice);
542}547}
...@@ -544,25 +549,25 @@ fn testAllocator(allocator: *mem.Allocator) !void {...@@ -544,25 +549,25 @@ fn testAllocator(allocator: *mem.Allocator) !void {
544fn testAllocatorAligned(allocator: *mem.Allocator, comptime alignment: u29) !void {549fn testAllocatorAligned(allocator: *mem.Allocator, comptime alignment: u29) !void {
545 // initial550 // initial
546 var slice = try allocator.alignedAlloc(u8, alignment, 10);551 var slice = try allocator.alignedAlloc(u8, alignment, 10);
547 assert(slice.len == 10);552 testing.expect(slice.len == 10);
548 // grow553 // grow
549 slice = try allocator.alignedRealloc(u8, alignment, slice, 100);554 slice = try allocator.alignedRealloc(u8, alignment, slice, 100);
550 assert(slice.len == 100);555 testing.expect(slice.len == 100);
551 // shrink556 // shrink
552 slice = try allocator.alignedRealloc(u8, alignment, slice, 10);557 slice = try allocator.alignedRealloc(u8, alignment, slice, 10);
553 assert(slice.len == 10);558 testing.expect(slice.len == 10);
554 // go to zero559 // go to zero
555 slice = try allocator.alignedRealloc(u8, alignment, slice, 0);560 slice = try allocator.alignedRealloc(u8, alignment, slice, 0);
556 assert(slice.len == 0);561 testing.expect(slice.len == 0);
557 // realloc from zero562 // realloc from zero
558 slice = try allocator.alignedRealloc(u8, alignment, slice, 100);563 slice = try allocator.alignedRealloc(u8, alignment, slice, 100);
559 assert(slice.len == 100);564 testing.expect(slice.len == 100);
560 // shrink with shrink565 // shrink with shrink
561 slice = allocator.alignedShrink(u8, alignment, slice, 10);566 slice = allocator.alignedShrink(u8, alignment, slice, 10);
562 assert(slice.len == 10);567 testing.expect(slice.len == 10);
563 // shrink to zero568 // shrink to zero
564 slice = allocator.alignedShrink(u8, alignment, slice, 0);569 slice = allocator.alignedShrink(u8, alignment, slice, 0);
565 assert(slice.len == 0);570 testing.expect(slice.len == 0);
566}571}
567572
568fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!void {573fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!void {
...@@ -577,19 +582,19 @@ fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!vo...@@ -577,19 +582,19 @@ fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!vo
577 _ = @shlWithOverflow(usize, ~usize(0), USizeShift(@ctz(large_align)), &align_mask);582 _ = @shlWithOverflow(usize, ~usize(0), USizeShift(@ctz(large_align)), &align_mask);
578583
579 var slice = try allocator.allocFn(allocator, 500, large_align);584 var slice = try allocator.allocFn(allocator, 500, large_align);
580 debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));585 testing.expect(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
581586
582 slice = try allocator.reallocFn(allocator, slice, 100, large_align);587 slice = try allocator.reallocFn(allocator, slice, 100, large_align);
583 debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));588 testing.expect(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
584589
585 slice = try allocator.reallocFn(allocator, slice, 5000, large_align);590 slice = try allocator.reallocFn(allocator, slice, 5000, large_align);
586 debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));591 testing.expect(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
587592
588 slice = try allocator.reallocFn(allocator, slice, 10, large_align);593 slice = try allocator.reallocFn(allocator, slice, 10, large_align);
589 debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));594 testing.expect(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
590595
591 slice = try allocator.reallocFn(allocator, slice, 20000, large_align);596 slice = try allocator.reallocFn(allocator, slice, 20000, large_align);
592 debug.assert(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));597 testing.expect(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr));
593598
594 allocator.free(slice);599 allocator.free(slice);
595}600}
std/index.zig+12-8
...@@ -9,6 +9,7 @@ pub const DynLib = @import("dynamic_library.zig").DynLib;...@@ -9,6 +9,7 @@ pub const DynLib = @import("dynamic_library.zig").DynLib;
9pub const HashMap = @import("hash_map.zig").HashMap;9pub const HashMap = @import("hash_map.zig").HashMap;
10pub const LinkedList = @import("linked_list.zig").LinkedList;10pub const LinkedList = @import("linked_list.zig").LinkedList;
11pub const Mutex = @import("mutex.zig").Mutex;11pub const Mutex = @import("mutex.zig").Mutex;
12pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex;
12pub const SegmentedList = @import("segmented_list.zig").SegmentedList;13pub const SegmentedList = @import("segmented_list.zig").SegmentedList;
13pub const SpinLock = @import("spinlock.zig").SpinLock;14pub const SpinLock = @import("spinlock.zig").SpinLock;
1415
...@@ -30,21 +31,21 @@ pub const hash_map = @import("hash_map.zig");...@@ -30,21 +31,21 @@ pub const hash_map = @import("hash_map.zig");
30pub const heap = @import("heap.zig");31pub const heap = @import("heap.zig");
31pub const io = @import("io.zig");32pub const io = @import("io.zig");
32pub const json = @import("json.zig");33pub const json = @import("json.zig");
34pub const lazyInit = @import("lazy_init.zig").lazyInit;
33pub const macho = @import("macho.zig");35pub const macho = @import("macho.zig");
34pub const math = @import("math/index.zig");36pub const math = @import("math/index.zig");
35pub const meta = @import("meta/index.zig");
36pub const mem = @import("mem.zig");37pub const mem = @import("mem.zig");
38pub const meta = @import("meta/index.zig");
37pub const net = @import("net.zig");39pub const net = @import("net.zig");
38pub const os = @import("os/index.zig");40pub const os = @import("os/index.zig");
39pub const pdb = @import("pdb.zig");41pub const pdb = @import("pdb.zig");
40pub const rand = @import("rand/index.zig");42pub const rand = @import("rand/index.zig");
41pub const rb = @import("rb.zig");43pub const rb = @import("rb.zig");
42pub const sort = @import("sort.zig");44pub const sort = @import("sort.zig");
45pub const testing = @import("testing.zig");
43pub const unicode = @import("unicode.zig");46pub const unicode = @import("unicode.zig");
44pub const zig = @import("zig/index.zig");47pub const zig = @import("zig/index.zig");
4548
46pub const lazyInit = @import("lazy_init.zig").lazyInit;
47
48test "std" {49test "std" {
49 // run tests from these50 // run tests from these
50 _ = @import("array_list.zig");51 _ = @import("array_list.zig");
...@@ -55,9 +56,10 @@ test "std" {...@@ -55,9 +56,10 @@ test "std" {
55 _ = @import("hash_map.zig");56 _ = @import("hash_map.zig");
56 _ = @import("linked_list.zig");57 _ = @import("linked_list.zig");
57 _ = @import("mutex.zig");58 _ = @import("mutex.zig");
59 _ = @import("statically_initialized_mutex.zig");
58 _ = @import("segmented_list.zig");60 _ = @import("segmented_list.zig");
59 _ = @import("spinlock.zig");61 _ = @import("spinlock.zig");
6062
61 _ = @import("base64.zig");63 _ = @import("base64.zig");
62 _ = @import("build.zig");64 _ = @import("build.zig");
63 _ = @import("c/index.zig");65 _ = @import("c/index.zig");
...@@ -66,24 +68,26 @@ test "std" {...@@ -66,24 +68,26 @@ test "std" {
66 _ = @import("cstr.zig");68 _ = @import("cstr.zig");
67 _ = @import("debug/index.zig");69 _ = @import("debug/index.zig");
68 _ = @import("dwarf.zig");70 _ = @import("dwarf.zig");
71 _ = @import("dynamic_library.zig");
69 _ = @import("elf.zig");72 _ = @import("elf.zig");
70 _ = @import("empty.zig");73 _ = @import("empty.zig");
71 _ = @import("event.zig");74 _ = @import("event.zig");
72 _ = @import("fmt/index.zig");75 _ = @import("fmt/index.zig");
73 _ = @import("hash/index.zig");76 _ = @import("hash/index.zig");
77 _ = @import("heap.zig");
74 _ = @import("io.zig");78 _ = @import("io.zig");
75 _ = @import("json.zig");79 _ = @import("json.zig");
80 _ = @import("lazy_init.zig");
76 _ = @import("macho.zig");81 _ = @import("macho.zig");
77 _ = @import("math/index.zig");82 _ = @import("math/index.zig");
78 _ = @import("meta/index.zig");
79 _ = @import("mem.zig");83 _ = @import("mem.zig");
84 _ = @import("meta/index.zig");
80 _ = @import("net.zig");85 _ = @import("net.zig");
81 _ = @import("heap.zig");
82 _ = @import("os/index.zig");86 _ = @import("os/index.zig");
83 _ = @import("rand/index.zig");
84 _ = @import("pdb.zig");87 _ = @import("pdb.zig");
88 _ = @import("rand/index.zig");
85 _ = @import("sort.zig");89 _ = @import("sort.zig");
90 _ = @import("testing.zig");
86 _ = @import("unicode.zig");91 _ = @import("unicode.zig");
87 _ = @import("zig/index.zig");92 _ = @import("zig/index.zig");
88 _ = @import("lazy_init.zig");
89}93}
std/io.zig+751-53
...@@ -8,9 +8,12 @@ const debug = std.debug;...@@ -8,9 +8,12 @@ const debug = std.debug;
8const assert = debug.assert;8const assert = debug.assert;
9const os = std.os;9const os = std.os;
10const mem = std.mem;10const mem = std.mem;
11const meta = std.meta;
12const trait = meta.trait;
11const Buffer = std.Buffer;13const Buffer = std.Buffer;
12const fmt = std.fmt;14const fmt = std.fmt;
13const File = std.os.File;15const File = std.os.File;
16const testing = std.testing;
1417
15const is_posix = builtin.os != builtin.Os.windows;18const is_posix = builtin.os != builtin.Os.windows;
16const is_windows = builtin.os == builtin.Os.windows;19const is_windows = builtin.os == builtin.Os.windows;
...@@ -152,35 +155,43 @@ pub fn InStream(comptime ReadError: type) type {...@@ -152,35 +155,43 @@ pub fn InStream(comptime ReadError: type) type {
152 }155 }
153156
154 /// Reads a native-endian integer157 /// Reads a native-endian integer
155 pub fn readIntNe(self: *Self, comptime T: type) !T {158 pub fn readIntNative(self: *Self, comptime T: type) !T {
156 return self.readInt(builtin.endian, T);159 var bytes: [@sizeOf(T)]u8 = undefined;
160 try self.readNoEof(bytes[0..]);
161 return mem.readIntNative(T, &bytes);
157 }162 }
158163
159 pub fn readIntLe(self: *Self, comptime T: type) !T {164 /// Reads a foreign-endian integer
165 pub fn readIntForeign(self: *Self, comptime T: type) !T {
160 var bytes: [@sizeOf(T)]u8 = undefined;166 var bytes: [@sizeOf(T)]u8 = undefined;
161 try self.readNoEof(bytes[0..]);167 try self.readNoEof(bytes[0..]);
162 return mem.readIntLE(T, bytes);168 return mem.readIntForeign(T, &bytes);
163 }169 }
164170
165 pub fn readIntBe(self: *Self, comptime T: type) !T {171 pub fn readIntLittle(self: *Self, comptime T: type) !T {
166 var bytes: [@sizeOf(T)]u8 = undefined;172 var bytes: [@sizeOf(T)]u8 = undefined;
167 try self.readNoEof(bytes[0..]);173 try self.readNoEof(bytes[0..]);
168 return mem.readIntBE(T, bytes);174 return mem.readIntLittle(T, &bytes);
169 }175 }
170176
171 pub fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T {177 pub fn readIntBig(self: *Self, comptime T: type) !T {
172 var bytes: [@sizeOf(T)]u8 = undefined;178 var bytes: [@sizeOf(T)]u8 = undefined;
173 try self.readNoEof(bytes[0..]);179 try self.readNoEof(bytes[0..]);
174 return mem.readInt(bytes, T, endian);180 return mem.readIntBig(T, &bytes);
175 }181 }
176182
177 pub fn readVarInt(self: *Self, endian: builtin.Endian, comptime T: type, size: usize) !T {183 pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
178 assert(size <= @sizeOf(T));184 var bytes: [@sizeOf(T)]u8 = undefined;
179 assert(size <= 8);185 try self.readNoEof(bytes[0..]);
180 var input_buf: [8]u8 = undefined;186 return mem.readInt(T, &bytes, endian);
181 const input_slice = input_buf[0..size];187 }
182 try self.readNoEof(input_slice);188
183 return mem.readInt(input_slice, T, endian);189 pub fn readVarInt(self: *Self, comptime ReturnType: type, endian: builtin.Endian, size: usize) !ReturnType {
190 assert(size <= @sizeOf(ReturnType));
191 var bytes_buf: [@sizeOf(ReturnType)]u8 = undefined;
192 const bytes = bytes_buf[0..size];
193 try self.readNoEof(bytes);
194 return mem.readVarInt(ReturnType, bytes, endian);
184 }195 }
185196
186 pub fn skipBytes(self: *Self, num_bytes: usize) !void {197 pub fn skipBytes(self: *Self, num_bytes: usize) !void {
...@@ -229,25 +240,34 @@ pub fn OutStream(comptime WriteError: type) type {...@@ -229,25 +240,34 @@ pub fn OutStream(comptime WriteError: type) type {
229 }240 }
230241
231 /// Write a native-endian integer.242 /// Write a native-endian integer.
232 pub fn writeIntNe(self: *Self, comptime T: type, value: T) Error!void {243 pub fn writeIntNative(self: *Self, comptime T: type, value: T) Error!void {
233 return self.writeInt(builtin.endian, T, value);244 var bytes: [@sizeOf(T)]u8 = undefined;
245 mem.writeIntNative(T, &bytes, value);
246 return self.writeFn(self, bytes);
247 }
248
249 /// Write a foreign-endian integer.
250 pub fn writeIntForeign(self: *Self, comptime T: type, value: T) Error!void {
251 var bytes: [@sizeOf(T)]u8 = undefined;
252 mem.writeIntForeign(T, &bytes, value);
253 return self.writeFn(self, bytes);
234 }254 }
235255
236 pub fn writeIntLe(self: *Self, comptime T: type, value: T) Error!void {256 pub fn writeIntLittle(self: *Self, comptime T: type, value: T) Error!void {
237 var bytes: [@sizeOf(T)]u8 = undefined;257 var bytes: [@sizeOf(T)]u8 = undefined;
238 mem.writeIntLE(T, &bytes, value);258 mem.writeIntLittle(T, &bytes, value);
239 return self.writeFn(self, bytes);259 return self.writeFn(self, bytes);
240 }260 }
241261
242 pub fn writeIntBe(self: *Self, comptime T: type, value: T) Error!void {262 pub fn writeIntBig(self: *Self, comptime T: type, value: T) Error!void {
243 var bytes: [@sizeOf(T)]u8 = undefined;263 var bytes: [@sizeOf(T)]u8 = undefined;
244 mem.writeIntBE(T, &bytes, value);264 mem.writeIntBig(T, &bytes, value);
245 return self.writeFn(self, bytes);265 return self.writeFn(self, bytes);
246 }266 }
247267
248 pub fn writeInt(self: *Self, endian: builtin.Endian, comptime T: type, value: T) Error!void {268 pub fn writeInt(self: *Self, comptime T: type, value: T, endian: builtin.Endian) Error!void {
249 var bytes: [@sizeOf(T)]u8 = undefined;269 var bytes: [@sizeOf(T)]u8 = undefined;
250 mem.writeInt(bytes[0..], value, endian);270 mem.writeInt(T, &bytes, value, endian);
251 return self.writeFn(self, bytes);271 return self.writeFn(self, bytes);
252 }272 }
253 };273 };
...@@ -323,23 +343,24 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)...@@ -323,23 +343,24 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)
323 const amt_buffered = self.end_index - self.start_index;343 const amt_buffered = self.end_index - self.start_index;
324 if (amt_buffered == 0) {344 if (amt_buffered == 0) {
325 assert(self.end_index <= buffer_size);345 assert(self.end_index <= buffer_size);
326 if (self.end_index == buffer_size) {346 // Make sure the last read actually gave us some data
327 // we can read more data from the unbuffered stream347 if (self.end_index == 0) {
328 if (dest_space < buffer_size) {348 // reading from the unbuffered stream returned nothing
329 self.start_index = 0;349 // so we have nothing left to read.
330 self.end_index = try self.unbuffered_in_stream.read(self.buffer[0..]);
331 } else {
332 // asking for so much data that buffering is actually less efficient.
333 // forward the request directly to the unbuffered stream
334 const amt_read = try self.unbuffered_in_stream.read(dest[dest_index..]);
335 return dest_index + amt_read;
336 }
337 } else {
338 // reading from the unbuffered stream returned less than we asked for
339 // so we cannot read any more data.
340 return dest_index;350 return dest_index;
341 }351 }
352 // we can read more data from the unbuffered stream
353 if (dest_space < buffer_size) {
354 self.start_index = 0;
355 self.end_index = try self.unbuffered_in_stream.read(self.buffer[0..]);
356 } else {
357 // asking for so much data that buffering is actually less efficient.
358 // forward the request directly to the unbuffered stream
359 const amt_read = try self.unbuffered_in_stream.read(dest[dest_index..]);
360 return dest_index + amt_read;
361 }
342 }362 }
363
343 const copy_amount = math.min(dest_space, amt_buffered);364 const copy_amount = math.min(dest_space, amt_buffered);
344 const copy_end_index = self.start_index + copy_amount;365 const copy_end_index = self.start_index + copy_amount;
345 mem.copy(u8, dest[dest_index..], self.buffer[self.start_index..copy_end_index]);366 mem.copy(u8, dest[dest_index..], self.buffer[self.start_index..copy_end_index]);
...@@ -350,6 +371,46 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)...@@ -350,6 +371,46 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)
350 };371 };
351}372}
352373
374test "io.BufferedInStream" {
375 const OneByteReadInStream = struct {
376 const Error = error{NoError};
377 const Stream = InStream(Error);
378
379 stream: Stream,
380 str: []const u8,
381 curr: usize,
382
383 fn init(str: []const u8) @This() {
384 return @This(){
385 .stream = Stream{ .readFn = readFn },
386 .str = str,
387 .curr = 0,
388 };
389 }
390
391 fn readFn(in_stream: *Stream, dest: []u8) Error!usize {
392 const self = @fieldParentPtr(@This(), "stream", in_stream);
393 if (self.str.len <= self.curr or dest.len == 0)
394 return 0;
395
396 dest[0] = self.str[self.curr];
397 self.curr += 1;
398 return 1;
399 }
400 };
401
402 var buf: [100]u8 = undefined;
403 const allocator = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator;
404
405 const str = "This is a test";
406 var one_byte_stream = OneByteReadInStream.init(str);
407 var buf_in_stream = BufferedInStream(OneByteReadInStream.Error).init(&one_byte_stream.stream);
408 const stream = &buf_in_stream.stream;
409
410 const res = try stream.readAllAlloc(allocator, str.len + 1);
411 testing.expectEqualSlices(u8, str, res);
412}
413
353/// Creates a stream which supports 'un-reading' data, so that it can be read again.414/// Creates a stream which supports 'un-reading' data, so that it can be read again.
354/// This makes look-ahead style parsing much easier.415/// This makes look-ahead style parsing much easier.
355pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) type {416pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) type {
...@@ -446,6 +507,153 @@ pub const SliceInStream = struct {...@@ -446,6 +507,153 @@ pub const SliceInStream = struct {
446 }507 }
447};508};
448509
510/// Creates a stream which allows for reading bit fields from another stream
511pub fn BitInStream(endian: builtin.Endian, comptime Error: type) type {
512 return struct {
513 const Self = @This();
514
515 in_stream: *Stream,
516 bit_buffer: u7,
517 bit_count: u3,
518 stream: Stream,
519
520 pub const Stream = InStream(Error);
521 const u8_bit_count = comptime meta.bitCount(u8);
522 const u7_bit_count = comptime meta.bitCount(u7);
523 const u4_bit_count = comptime meta.bitCount(u4);
524
525 pub fn init(in_stream: *Stream) Self {
526 return Self{
527 .in_stream = in_stream,
528 .bit_buffer = 0,
529 .bit_count = 0,
530 .stream = Stream{ .readFn = read },
531 };
532 }
533
534 /// Reads `bits` bits from the stream and returns a specified unsigned int type
535 /// containing them in the least significant end, returning an error if the
536 /// specified number of bits could not be read.
537 pub fn readBitsNoEof(self: *Self, comptime U: type, bits: usize) !U {
538 var n: usize = undefined;
539 const result = try self.readBits(U, bits, &n);
540 if (n < bits) return error.EndOfStream;
541 return result;
542 }
543
544 /// Reads `bits` bits from the stream and returns a specified unsigned int type
545 /// containing them in the least significant end. The number of bits successfully
546 /// read is placed in `out_bits`, as reaching the end of the stream is not an error.
547 pub fn readBits(self: *Self, comptime U: type, bits: usize, out_bits: *usize) Error!U {
548 comptime assert(trait.isUnsignedInt(U));
549
550 //by extending the buffer to a minimum of u8 we can cover a number of edge cases
551 // related to shifting and casting.
552 const u_bit_count = comptime meta.bitCount(U);
553 const buf_bit_count = bc: {
554 assert(u_bit_count >= bits);
555 break :bc if (u_bit_count <= u8_bit_count) u8_bit_count else u_bit_count;
556 };
557 const Buf = @IntType(false, buf_bit_count);
558 const BufShift = math.Log2Int(Buf);
559
560 out_bits.* = usize(0);
561 if (U == u0 or bits == 0) return 0;
562 var out_buffer = Buf(0);
563
564 if (self.bit_count > 0) {
565 const n = if (self.bit_count >= bits) @intCast(u3, bits) else self.bit_count;
566 const shift = u7_bit_count - n;
567 switch (endian) {
568 builtin.Endian.Big => {
569 out_buffer = Buf(self.bit_buffer >> shift);
570 self.bit_buffer <<= n;
571 },
572 builtin.Endian.Little => {
573 const value = (self.bit_buffer << shift) >> shift;
574 out_buffer = Buf(value);
575 self.bit_buffer >>= n;
576 },
577 }
578 self.bit_count -= n;
579 out_bits.* = n;
580 }
581 //at this point we know bit_buffer is empty
582
583 //copy bytes until we have enough bits, then leave the rest in bit_buffer
584 while (out_bits.* < bits) {
585 const n = bits - out_bits.*;
586 const next_byte = self.in_stream.readByte() catch |err| {
587 if (err == error.EndOfStream) {
588 return @intCast(U, out_buffer);
589 }
590 //@BUG: See #1810. Not sure if the bug is that I have to do this for some
591 // streams, or that I don't for streams with emtpy errorsets.
592 return @errSetCast(Error, err);
593 };
594
595 switch (endian) {
596 builtin.Endian.Big => {
597 if (n >= u8_bit_count) {
598 out_buffer <<= @intCast(u3, u8_bit_count - 1);
599 out_buffer <<= 1;
600 out_buffer |= Buf(next_byte);
601 out_bits.* += u8_bit_count;
602 continue;
603 }
604
605 const shift = @intCast(u3, u8_bit_count - n);
606 out_buffer <<= @intCast(BufShift, n);
607 out_buffer |= Buf(next_byte >> shift);
608 out_bits.* += n;
609 self.bit_buffer = @truncate(u7, next_byte << @intCast(u3, n - 1));
610 self.bit_count = shift;
611 },
612 builtin.Endian.Little => {
613 if (n >= u8_bit_count) {
614 out_buffer |= Buf(next_byte) << @intCast(BufShift, out_bits.*);
615 out_bits.* += u8_bit_count;
616 continue;
617 }
618
619 const shift = @intCast(u3, u8_bit_count - n);
620 const value = (next_byte << shift) >> shift;
621 out_buffer |= Buf(value) << @intCast(BufShift, out_bits.*);
622 out_bits.* += n;
623 self.bit_buffer = @truncate(u7, next_byte >> @intCast(u3, n));
624 self.bit_count = shift;
625 },
626 }
627 }
628
629 return @intCast(U, out_buffer);
630 }
631
632 pub fn alignToByte(self: *Self) void {
633 self.bit_buffer = 0;
634 self.bit_count = 0;
635 }
636
637 pub fn read(self_stream: *Stream, buffer: []u8) Error!usize {
638 var self = @fieldParentPtr(Self, "stream", self_stream);
639
640 var out_bits: usize = undefined;
641 var out_bits_total = usize(0);
642 //@NOTE: I'm not sure this is a good idea, maybe alignToByte should be forced
643 if (self.bit_count > 0) {
644 for (buffer) |*b, i| {
645 b.* = try self.readBits(u8, u8_bit_count, &out_bits);
646 out_bits_total += out_bits;
647 }
648 const incomplete_byte = @boolToInt(out_bits_total % u8_bit_count > 0);
649 return (out_bits_total / u8_bit_count) + incomplete_byte;
650 }
651
652 return self.in_stream.read(buffer);
653 }
654 };
655}
656
449/// This is a simple OutStream that writes to a slice, and returns an error657/// This is a simple OutStream that writes to a slice, and returns an error
450/// when it runs out of space.658/// when it runs out of space.
451pub const SliceOutStream = struct {659pub const SliceOutStream = struct {
...@@ -498,7 +706,7 @@ test "io.SliceOutStream" {...@@ -498,7 +706,7 @@ test "io.SliceOutStream" {
498 const stream = &slice_stream.stream;706 const stream = &slice_stream.stream;
499707
500 try stream.print("{}{}!", "Hello", "World");708 try stream.print("{}{}!", "Hello", "World");
501 debug.assert(mem.eql(u8, "HelloWorld!", slice_stream.getWritten()));709 testing.expectEqualSlices(u8, "HelloWorld!", slice_stream.getWritten());
502}710}
503711
504var null_out_stream_state = NullOutStream.init();712var null_out_stream_state = NullOutStream.init();
...@@ -560,7 +768,7 @@ test "io.CountingOutStream" {...@@ -560,7 +768,7 @@ test "io.CountingOutStream" {
560768
561 const bytes = "yay" ** 10000;769 const bytes = "yay" ** 10000;
562 stream.write(bytes) catch unreachable;770 stream.write(bytes) catch unreachable;
563 debug.assert(counting_stream.bytes_written == bytes.len);771 testing.expect(counting_stream.bytes_written == bytes.len);
564}772}
565773
566pub fn BufferedOutStream(comptime Error: type) type {774pub fn BufferedOutStream(comptime Error: type) type {
...@@ -639,6 +847,135 @@ pub const BufferOutStream = struct {...@@ -639,6 +847,135 @@ pub const BufferOutStream = struct {
639 }847 }
640};848};
641849
850/// Creates a stream which allows for writing bit fields to another stream
851pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type {
852 return struct {
853 const Self = @This();
854
855 out_stream: *Stream,
856 bit_buffer: u8,
857 bit_count: u4,
858 stream: Stream,
859
860 pub const Stream = OutStream(Error);
861 const u8_bit_count = comptime meta.bitCount(u8);
862 const u4_bit_count = comptime meta.bitCount(u4);
863
864 pub fn init(out_stream: *Stream) Self {
865 return Self{
866 .out_stream = out_stream,
867 .bit_buffer = 0,
868 .bit_count = 0,
869 .stream = Stream{ .writeFn = write },
870 };
871 }
872
873 /// Write the specified number of bits to the stream from the least significant bits of
874 /// the specified unsigned int value. Bits will only be written to the stream when there
875 /// are enough to fill a byte.
876 pub fn writeBits(self: *Self, value: var, bits: usize) Error!void {
877 if (bits == 0) return;
878
879 const U = @typeOf(value);
880 comptime assert(trait.isUnsignedInt(U));
881
882 //by extending the buffer to a minimum of u8 we can cover a number of edge cases
883 // related to shifting and casting.
884 const u_bit_count = comptime meta.bitCount(U);
885 const buf_bit_count = bc: {
886 assert(u_bit_count >= bits);
887 break :bc if (u_bit_count <= u8_bit_count) u8_bit_count else u_bit_count;
888 };
889 const Buf = @IntType(false, buf_bit_count);
890 const BufShift = math.Log2Int(Buf);
891
892 const buf_value = @intCast(Buf, value);
893
894 const high_byte_shift = @intCast(BufShift, buf_bit_count - u8_bit_count);
895 var in_buffer = switch (endian) {
896 builtin.Endian.Big => buf_value << @intCast(BufShift, buf_bit_count - bits),
897 builtin.Endian.Little => buf_value,
898 };
899 var in_bits = bits;
900
901 if (self.bit_count > 0) {
902 const bits_remaining = u8_bit_count - self.bit_count;
903 const n = @intCast(u3, if (bits_remaining > bits) bits else bits_remaining);
904 switch (endian) {
905 builtin.Endian.Big => {
906 const shift = @intCast(BufShift, high_byte_shift + self.bit_count);
907 const v = @intCast(u8, in_buffer >> shift);
908 self.bit_buffer |= v;
909 in_buffer <<= n;
910 },
911 builtin.Endian.Little => {
912 const v = @truncate(u8, in_buffer) << @intCast(u3, self.bit_count);
913 self.bit_buffer |= v;
914 in_buffer >>= n;
915 },
916 }
917 self.bit_count += n;
918 in_bits -= n;
919
920 //if we didn't fill the buffer, it's because bits < bits_remaining;
921 if (self.bit_count != u8_bit_count) return;
922 try self.out_stream.writeByte(self.bit_buffer);
923 self.bit_buffer = 0;
924 self.bit_count = 0;
925 }
926 //at this point we know bit_buffer is empty
927
928 //copy bytes until we can't fill one anymore, then leave the rest in bit_buffer
929 while (in_bits >= u8_bit_count) {
930 switch (endian) {
931 builtin.Endian.Big => {
932 const v = @intCast(u8, in_buffer >> high_byte_shift);
933 try self.out_stream.writeByte(v);
934 in_buffer <<= @intCast(u3, u8_bit_count - 1);
935 in_buffer <<= 1;
936 },
937 builtin.Endian.Little => {
938 const v = @truncate(u8, in_buffer);
939 try self.out_stream.writeByte(v);
940 in_buffer >>= @intCast(u3, u8_bit_count - 1);
941 in_buffer >>= 1;
942 },
943 }
944 in_bits -= u8_bit_count;
945 }
946
947 if (in_bits > 0) {
948 self.bit_count = @intCast(u4, in_bits);
949 self.bit_buffer = switch (endian) {
950 builtin.Endian.Big => @truncate(u8, in_buffer >> high_byte_shift),
951 builtin.Endian.Little => @truncate(u8, in_buffer),
952 };
953 }
954 }
955
956 /// Flush any remaining bits to the stream.
957 pub fn flushBits(self: *Self) Error!void {
958 if (self.bit_count == 0) return;
959 try self.out_stream.writeByte(self.bit_buffer);
960 self.bit_buffer = 0;
961 self.bit_count = 0;
962 }
963
964 pub fn write(self_stream: *Stream, buffer: []const u8) Error!void {
965 var self = @fieldParentPtr(Self, "stream", self_stream);
966
967 //@NOTE: I'm not sure this is a good idea, maybe flushBits should be forced
968 if (self.bit_count > 0) {
969 for (buffer) |b, i|
970 try self.writeBits(b, u8_bit_count);
971 return;
972 }
973
974 return self.out_stream.write(buffer);
975 }
976 };
977}
978
642pub const BufferedAtomicFile = struct {979pub const BufferedAtomicFile = struct {
643 atomic_file: os.AtomicFile,980 atomic_file: os.AtomicFile,
644 file_stream: os.File.OutStream,981 file_stream: os.File.OutStream,
...@@ -647,12 +984,13 @@ pub const BufferedAtomicFile = struct {...@@ -647,12 +984,13 @@ pub const BufferedAtomicFile = struct {
647984
648 pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile {985 pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile {
649 // TODO with well defined copy elision we don't need this allocation986 // TODO with well defined copy elision we don't need this allocation
650 var self = try allocator.create(BufferedAtomicFile{987 var self = try allocator.create(BufferedAtomicFile);
988 self.* = BufferedAtomicFile{
651 .atomic_file = undefined,989 .atomic_file = undefined,
652 .file_stream = undefined,990 .file_stream = undefined,
653 .buffered_stream = undefined,991 .buffered_stream = undefined,
654 .allocator = allocator,992 .allocator = allocator,
655 });993 };
656 errdefer allocator.destroy(self);994 errdefer allocator.destroy(self);
657995
658 self.atomic_file = try os.AtomicFile.init(dest_path, os.File.default_mode);996 self.atomic_file = try os.AtomicFile.init(dest_path, os.File.default_mode);
...@@ -679,12 +1017,6 @@ pub const BufferedAtomicFile = struct {...@@ -679,12 +1017,6 @@ pub const BufferedAtomicFile = struct {
679 }1017 }
680};1018};
6811019
682test "import io tests" {
683 comptime {
684 _ = @import("io_test.zig");
685 }
686}
687
688pub fn readLine(buf: *std.Buffer) ![]u8 {1020pub fn readLine(buf: *std.Buffer) ![]u8 {
689 var stdin = try getStdIn();1021 var stdin = try getStdIn();
690 var stdin_stream = stdin.inStream();1022 var stdin_stream = stdin.inStream();
...@@ -721,10 +1053,10 @@ test "io.readLineFrom" {...@@ -721,10 +1053,10 @@ test "io.readLineFrom" {
721 );1053 );
722 const stream = &mem_stream.stream;1054 const stream = &mem_stream.stream;
7231055
724 debug.assert(mem.eql(u8, "Line 1", try readLineFrom(stream, &buf)));1056 testing.expectEqualSlices(u8, "Line 1", try readLineFrom(stream, &buf));
725 debug.assert(mem.eql(u8, "Line 22", try readLineFrom(stream, &buf)));1057 testing.expectEqualSlices(u8, "Line 22", try readLineFrom(stream, &buf));
726 debug.assertError(readLineFrom(stream, &buf), error.EndOfStream);1058 testing.expectError(error.EndOfStream, readLineFrom(stream, &buf));
727 debug.assert(mem.eql(u8, buf.toSlice(), "Line 1Line 22Line 333"));1059 testing.expectEqualSlices(u8, "Line 1Line 22Line 333", buf.toSlice());
728}1060}
7291061
730pub fn readLineSlice(slice: []u8) ![]u8 {1062pub fn readLineSlice(slice: []u8) ![]u8 {
...@@ -752,6 +1084,372 @@ test "io.readLineSliceFrom" {...@@ -752,6 +1084,372 @@ test "io.readLineSliceFrom" {
752 );1084 );
753 const stream = &mem_stream.stream;1085 const stream = &mem_stream.stream;
7541086
755 debug.assert(mem.eql(u8, "Line 1", try readLineSliceFrom(stream, buf[0..])));1087 testing.expectEqualSlices(u8, "Line 1", try readLineSliceFrom(stream, buf[0..]));
756 debug.assertError(readLineSliceFrom(stream, buf[0..]), error.OutOfMemory);1088 testing.expectError(error.OutOfMemory, readLineSliceFrom(stream, buf[0..]));
757}1089}
1090
1091/// Creates a deserializer that deserializes types from any stream.
1092/// If `is_packed` is true, the data stream is treated as bit-packed,
1093/// otherwise data is expected to be packed to the smallest byte.
1094/// Types may implement a custom deserialization routine with a
1095/// function named `deserialize` in the form of:
1096/// pub fn deserialize(self: *Self, deserializer: var) !void
1097/// which will be called when the deserializer is used to deserialize
1098/// that type. It will pass a pointer to the type instance to deserialize
1099/// into and a pointer to the deserializer struct.
1100pub fn Deserializer(comptime endian: builtin.Endian, is_packed: bool, comptime Error: type) type {
1101 return struct {
1102 const Self = @This();
1103
1104 in_stream: if (is_packed) BitInStream(endian, Stream.Error) else *Stream,
1105
1106 pub const Stream = InStream(Error);
1107
1108 pub fn init(in_stream: *Stream) Self {
1109 return Self{ .in_stream = switch (is_packed) {
1110 true => BitInStream(endian, Stream.Error).init(in_stream),
1111 else => in_stream,
1112 } };
1113 }
1114
1115 pub fn alignToByte(self: *Self) void {
1116 if (!is_packed) return;
1117 self.in_stream.alignToByte();
1118 }
1119
1120 //@BUG: inferred error issue. See: #1386
1121 fn deserializeInt(self: *Self, comptime T: type) (Error || error{EndOfStream})!T {
1122 comptime assert(trait.is(builtin.TypeId.Int)(T) or trait.is(builtin.TypeId.Float)(T));
1123
1124 const u8_bit_count = 8;
1125 const t_bit_count = comptime meta.bitCount(T);
1126
1127 const U = @IntType(false, t_bit_count);
1128 const Log2U = math.Log2Int(U);
1129 const int_size = (U.bit_count + 7) / 8;
1130
1131 if (is_packed) {
1132 const result = try self.in_stream.readBitsNoEof(U, t_bit_count);
1133 return @bitCast(T, result);
1134 }
1135
1136 var buffer: [int_size]u8 = undefined;
1137 const read_size = try self.in_stream.read(buffer[0..]);
1138 if (read_size < int_size) return error.EndOfStream;
1139
1140 if (int_size == 1) {
1141 if (t_bit_count == 8) return @bitCast(T, buffer[0]);
1142 const PossiblySignedByte = @IntType(T.is_signed, 8);
1143 return @truncate(T, @bitCast(PossiblySignedByte, buffer[0]));
1144 }
1145
1146 var result = U(0);
1147 for (buffer) |byte, i| {
1148 switch (endian) {
1149 builtin.Endian.Big => {
1150 result = (result << u8_bit_count) | byte;
1151 },
1152 builtin.Endian.Little => {
1153 result |= U(byte) << @intCast(Log2U, u8_bit_count * i);
1154 },
1155 }
1156 }
1157
1158 return @bitCast(T, result);
1159 }
1160
1161 //@TODO: Replace this with @unionInit or whatever when it is added
1162 // see: #1315
1163 fn setTag(ptr: var, tag: var) void {
1164 const T = @typeOf(ptr);
1165 comptime assert(trait.isPtrTo(builtin.TypeId.Union)(T));
1166 const U = meta.Child(T);
1167
1168 const info = @typeInfo(U).Union;
1169 if (info.tag_type) |TagType| {
1170 comptime assert(TagType == @typeOf(tag));
1171
1172 var ptr_tag = ptr: {
1173 if (@alignOf(TagType) >= @alignOf(U)) break :ptr @ptrCast(*TagType, ptr);
1174 const offset = comptime max: {
1175 var max_field_size: comptime_int = 0;
1176 for (info.fields) |field_info| {
1177 const field_size = @sizeOf(field_info.field_type);
1178 max_field_size = math.max(max_field_size, field_size);
1179 }
1180 break :max math.max(max_field_size, @alignOf(U));
1181 };
1182 break :ptr @intToPtr(*TagType, @ptrToInt(ptr) + offset);
1183 };
1184 ptr_tag.* = tag;
1185 }
1186 }
1187
1188 /// Deserializes and returns data of the specified type from the stream
1189 pub fn deserialize(self: *Self, comptime T: type) !T {
1190 var value: T = undefined;
1191 try self.deserializeInto(&value);
1192 return value;
1193 }
1194
1195 /// Deserializes data into the type pointed to by `ptr`
1196 pub fn deserializeInto(self: *Self, ptr: var) !void {
1197 const T = @typeOf(ptr);
1198 comptime assert(trait.is(builtin.TypeId.Pointer)(T));
1199
1200 if (comptime trait.isSlice(T) or comptime trait.isPtrTo(builtin.TypeId.Array)(T)) {
1201 for (ptr) |*v|
1202 try self.deserializeInto(v);
1203 return;
1204 }
1205
1206 comptime assert(trait.isSingleItemPtr(T));
1207
1208 const C = comptime meta.Child(T);
1209 const child_type_id = @typeId(C);
1210
1211 //custom deserializer: fn(self: *Self, deserializer: var) !void
1212 if (comptime trait.hasFn("deserialize")(C)) return C.deserialize(ptr, self);
1213
1214 if (comptime trait.isPacked(C) and !is_packed) {
1215 var packed_deserializer = Deserializer(endian, true, Error).init(self.in_stream);
1216 return packed_deserializer.deserializeInto(ptr);
1217 }
1218
1219 switch (child_type_id) {
1220 builtin.TypeId.Void => return,
1221 builtin.TypeId.Bool => ptr.* = (try self.deserializeInt(u1)) > 0,
1222 builtin.TypeId.Float, builtin.TypeId.Int => ptr.* = try self.deserializeInt(C),
1223 builtin.TypeId.Struct => {
1224 const info = @typeInfo(C).Struct;
1225
1226 inline for (info.fields) |*field_info| {
1227 const name = field_info.name;
1228 const FieldType = field_info.field_type;
1229
1230 if (FieldType == void or FieldType == u0) continue;
1231
1232 //it doesn't make any sense to read pointers
1233 if (comptime trait.is(builtin.TypeId.Pointer)(FieldType)) {
1234 @compileError("Will not " ++ "read field " ++ name ++ " of struct " ++
1235 @typeName(C) ++ " because it " ++ "is of pointer-type " ++
1236 @typeName(FieldType) ++ ".");
1237 }
1238
1239 try self.deserializeInto(&@field(ptr, name));
1240 }
1241 },
1242 builtin.TypeId.Union => {
1243 const info = @typeInfo(C).Union;
1244 if (info.tag_type) |TagType| {
1245 //we avoid duplicate iteration over the enum tags
1246 // by getting the int directly and casting it without
1247 // safety. If it is bad, it will be caught anyway.
1248 const TagInt = @TagType(TagType);
1249 const tag = try self.deserializeInt(TagInt);
1250
1251 {
1252 @setRuntimeSafety(false);
1253 //See: #1315
1254 setTag(ptr, @intToEnum(TagType, tag));
1255 }
1256
1257 inline for (info.fields) |field_info| {
1258 if (field_info.enum_field.?.value == tag) {
1259 const name = field_info.name;
1260 const FieldType = field_info.field_type;
1261 @field(ptr, name) = FieldType(undefined);
1262 try self.deserializeInto(&@field(ptr, name));
1263 return;
1264 }
1265 }
1266 //This is reachable if the enum data is bad
1267 return error.InvalidEnumTag;
1268 }
1269 @compileError("Cannot meaningfully deserialize " ++ @typeName(C) ++
1270 " because it is an untagged union Use a custom deserialize().");
1271 },
1272 builtin.TypeId.Optional => {
1273 const OC = comptime meta.Child(C);
1274 const exists = (try self.deserializeInt(u1)) > 0;
1275 if (!exists) {
1276 ptr.* = null;
1277 return;
1278 }
1279
1280 //The way non-pointer optionals are implemented ensures a pointer to them
1281 // will point to the value. The flag is stored at the end of that data.
1282 var val_ptr = @ptrCast(*OC, ptr);
1283 try self.deserializeInto(val_ptr);
1284 //This bit ensures the null flag isn't set. Any actual copying should be
1285 // optimized out... I hope.
1286 ptr.* = val_ptr.*;
1287 },
1288 builtin.TypeId.Enum => {
1289 var value = try self.deserializeInt(@TagType(C));
1290 ptr.* = try meta.intToEnum(C, value);
1291 },
1292 else => {
1293 @compileError("Cannot deserialize " ++ @tagName(child_type_id) ++ " types (unimplemented).");
1294 },
1295 }
1296 }
1297 };
1298}
1299
1300/// Creates a serializer that serializes types to any stream.
1301/// If `is_packed` is true, the data will be bit-packed into the stream.
1302/// Note that the you must call `serializer.flush()` when you are done
1303/// writing bit-packed data in order ensure any unwritten bits are committed.
1304/// If `is_packed` is false, data is packed to the smallest byte. In the case
1305/// of packed structs, the struct will written bit-packed and with the specified
1306/// endianess, after which data will resume being written at the next byte boundary.
1307/// Types may implement a custom serialization routine with a
1308/// function named `serialize` in the form of:
1309/// pub fn serialize(self: Self, serializer: var) !void
1310/// which will be called when the serializer is used to serialize that type. It will
1311/// pass a const pointer to the type instance to be serialized and a pointer
1312/// to the serializer struct.
1313pub fn Serializer(comptime endian: builtin.Endian, comptime is_packed: bool, comptime Error: type) type {
1314 return struct {
1315 const Self = @This();
1316
1317 out_stream: if (is_packed) BitOutStream(endian, Stream.Error) else *Stream,
1318
1319 pub const Stream = OutStream(Error);
1320
1321 pub fn init(out_stream: *Stream) Self {
1322 return Self{ .out_stream = switch (is_packed) {
1323 true => BitOutStream(endian, Stream.Error).init(out_stream),
1324 else => out_stream,
1325 } };
1326 }
1327
1328 /// Flushes any unwritten bits to the stream
1329 pub fn flush(self: *Self) Error!void {
1330 if (is_packed) return self.out_stream.flushBits();
1331 }
1332
1333 fn serializeInt(self: *Self, value: var) Error!void {
1334 const T = @typeOf(value);
1335 comptime assert(trait.is(builtin.TypeId.Int)(T) or trait.is(builtin.TypeId.Float)(T));
1336
1337 const t_bit_count = comptime meta.bitCount(T);
1338 const u8_bit_count = comptime meta.bitCount(u8);
1339
1340 const U = @IntType(false, t_bit_count);
1341 const Log2U = math.Log2Int(U);
1342 const int_size = (U.bit_count + 7) / 8;
1343
1344 const u_value = @bitCast(U, value);
1345
1346 if (is_packed) return self.out_stream.writeBits(u_value, t_bit_count);
1347
1348 var buffer: [int_size]u8 = undefined;
1349 if (int_size == 1) buffer[0] = u_value;
1350
1351 for (buffer) |*byte, i| {
1352 const idx = switch (endian) {
1353 builtin.Endian.Big => int_size - i - 1,
1354 builtin.Endian.Little => i,
1355 };
1356 const shift = @intCast(Log2U, idx * u8_bit_count);
1357 const v = u_value >> shift;
1358 byte.* = if (t_bit_count < u8_bit_count) v else @truncate(u8, v);
1359 }
1360
1361 try self.out_stream.write(buffer);
1362 }
1363
1364 /// Serializes the passed value into the stream
1365 pub fn serialize(self: *Self, value: var) Error!void {
1366 const T = comptime @typeOf(value);
1367
1368 if (comptime trait.isIndexable(T)) {
1369 for (value) |v|
1370 try self.serialize(v);
1371 return;
1372 }
1373
1374 //custom serializer: fn(self: Self, serializer: var) !void
1375 if (comptime trait.hasFn("serialize")(T)) return T.serialize(value, self);
1376
1377 if (comptime trait.isPacked(T) and !is_packed) {
1378 var packed_serializer = Serializer(endian, true, Error).init(self.out_stream);
1379 try packed_serializer.serialize(value);
1380 try packed_serializer.flush();
1381 return;
1382 }
1383
1384 switch (@typeId(T)) {
1385 builtin.TypeId.Void => return,
1386 builtin.TypeId.Bool => try self.serializeInt(u1(@boolToInt(value))),
1387 builtin.TypeId.Float, builtin.TypeId.Int => try self.serializeInt(value),
1388 builtin.TypeId.Struct => {
1389 const info = @typeInfo(T);
1390
1391 inline for (info.Struct.fields) |*field_info| {
1392 const name = field_info.name;
1393 const FieldType = field_info.field_type;
1394
1395 if (FieldType == void or FieldType == u0) continue;
1396
1397 //It doesn't make sense to write pointers
1398 if (comptime trait.is(builtin.TypeId.Pointer)(FieldType)) {
1399 @compileError("Will not " ++ "serialize field " ++ name ++
1400 " of struct " ++ @typeName(T) ++ " because it " ++
1401 "is of pointer-type " ++ @typeName(FieldType) ++ ".");
1402 }
1403 try self.serialize(@field(value, name));
1404 }
1405 },
1406 builtin.TypeId.Union => {
1407 const info = @typeInfo(T).Union;
1408 if (info.tag_type) |TagType| {
1409 const active_tag = meta.activeTag(value);
1410 try self.serialize(active_tag);
1411 //This inline loop is necessary because active_tag is a runtime
1412 // value, but @field requires a comptime value. Our alternative
1413 // is to check each field for a match
1414 inline for (info.fields) |field_info| {
1415 if (field_info.enum_field.?.value == @enumToInt(active_tag)) {
1416 const name = field_info.name;
1417 const FieldType = field_info.field_type;
1418 try self.serialize(@field(value, name));
1419 return;
1420 }
1421 }
1422 unreachable;
1423 }
1424 @compileError("Cannot meaningfully serialize " ++ @typeName(T) ++
1425 " because it is an untagged union Use a custom serialize().");
1426 },
1427 builtin.TypeId.Optional => {
1428 if (value == null) {
1429 try self.serializeInt(u1(@boolToInt(false)));
1430 return;
1431 }
1432 try self.serializeInt(u1(@boolToInt(true)));
1433
1434 const OC = comptime meta.Child(T);
1435
1436 //The way non-pointer optionals are implemented ensures a pointer to them
1437 // will point to the value. The flag is stored at the end of that data.
1438 var val_ptr = @ptrCast(*const OC, &value);
1439 try self.serialize(val_ptr.*);
1440 },
1441 builtin.TypeId.Enum => {
1442 try self.serializeInt(@enumToInt(value));
1443 },
1444 else => @compileError("Cannot serialize " ++ @tagName(@typeId(T)) ++ " types (unimplemented)."),
1445 }
1446 }
1447 };
1448}
1449
1450test "import io tests" {
1451 comptime {
1452 _ = @import("io_test.zig");
1453 }
1454}
1455
std/io_test.zig+476-30
...@@ -1,8 +1,10 @@...@@ -1,8 +1,10 @@
1const std = @import("index.zig");1const std = @import("index.zig");
2const io = std.io;2const io = std.io;
3const meta = std.meta;
4const trait = std.trait;
3const DefaultPrng = std.rand.DefaultPrng;5const DefaultPrng = std.rand.DefaultPrng;
4const assert = std.debug.assert;6const expect = std.testing.expect;
5const assertError = std.debug.assertError;7const expectError = std.testing.expectError;
6const mem = std.mem;8const mem = std.mem;
7const os = std.os;9const os = std.os;
8const builtin = @import("builtin");10const builtin = @import("builtin");
...@@ -33,7 +35,7 @@ test "write a file, read it, then delete it" {...@@ -33,7 +35,7 @@ test "write a file, read it, then delete it" {
3335
34 const file_size = try file.getEndPos();36 const file_size = try file.getEndPos();
35 const expected_file_size = "begin".len + data.len + "end".len;37 const expected_file_size = "begin".len + data.len + "end".len;
36 assert(file_size == expected_file_size);38 expect(file_size == expected_file_size);
3739
38 var file_in_stream = file.inStream();40 var file_in_stream = file.inStream();
39 var buf_stream = io.BufferedInStream(os.File.ReadError).init(&file_in_stream.stream);41 var buf_stream = io.BufferedInStream(os.File.ReadError).init(&file_in_stream.stream);
...@@ -41,9 +43,9 @@ test "write a file, read it, then delete it" {...@@ -41,9 +43,9 @@ test "write a file, read it, then delete it" {
41 const contents = try st.readAllAlloc(allocator, 2 * 1024);43 const contents = try st.readAllAlloc(allocator, 2 * 1024);
42 defer allocator.free(contents);44 defer allocator.free(contents);
4345
44 assert(mem.eql(u8, contents[0.."begin".len], "begin"));46 expect(mem.eql(u8, contents[0.."begin".len], "begin"));
45 assert(mem.eql(u8, contents["begin".len .. contents.len - "end".len], data));47 expect(mem.eql(u8, contents["begin".len .. contents.len - "end".len], data));
46 assert(mem.eql(u8, contents[contents.len - "end".len ..], "end"));48 expect(mem.eql(u8, contents[contents.len - "end".len ..], "end"));
47 }49 }
48 try os.deleteFile(tmp_file_name);50 try os.deleteFile(tmp_file_name);
49}51}
...@@ -59,7 +61,7 @@ test "BufferOutStream" {...@@ -59,7 +61,7 @@ test "BufferOutStream" {
59 const y: i32 = 1234;61 const y: i32 = 1234;
60 try buf_stream.print("x: {}\ny: {}\n", x, y);62 try buf_stream.print("x: {}\ny: {}\n", x, y);
6163
62 assert(mem.eql(u8, buffer.toSlice(), "x: 42\ny: 1234\n"));64 expect(mem.eql(u8, buffer.toSlice(), "x: 42\ny: 1234\n"));
63}65}
6466
65test "SliceInStream" {67test "SliceInStream" {
...@@ -69,15 +71,15 @@ test "SliceInStream" {...@@ -69,15 +71,15 @@ test "SliceInStream" {
69 var dest: [4]u8 = undefined;71 var dest: [4]u8 = undefined;
7072
71 var read = try ss.stream.read(dest[0..4]);73 var read = try ss.stream.read(dest[0..4]);
72 assert(read == 4);74 expect(read == 4);
73 assert(mem.eql(u8, dest[0..4], bytes[0..4]));75 expect(mem.eql(u8, dest[0..4], bytes[0..4]));
7476
75 read = try ss.stream.read(dest[0..4]);77 read = try ss.stream.read(dest[0..4]);
76 assert(read == 3);78 expect(read == 3);
77 assert(mem.eql(u8, dest[0..3], bytes[4..7]));79 expect(mem.eql(u8, dest[0..3], bytes[4..7]));
7880
79 read = try ss.stream.read(dest[0..4]);81 read = try ss.stream.read(dest[0..4]);
80 assert(read == 0);82 expect(read == 0);
81}83}
8284
83test "PeekStream" {85test "PeekStream" {
...@@ -91,26 +93,26 @@ test "PeekStream" {...@@ -91,26 +93,26 @@ test "PeekStream" {
91 ps.putBackByte(10);93 ps.putBackByte(10);
9294
93 var read = try ps.stream.read(dest[0..4]);95 var read = try ps.stream.read(dest[0..4]);
94 assert(read == 4);96 expect(read == 4);
95 assert(dest[0] == 10);97 expect(dest[0] == 10);
96 assert(dest[1] == 9);98 expect(dest[1] == 9);
97 assert(mem.eql(u8, dest[2..4], bytes[0..2]));99 expect(mem.eql(u8, dest[2..4], bytes[0..2]));
98100
99 read = try ps.stream.read(dest[0..4]);101 read = try ps.stream.read(dest[0..4]);
100 assert(read == 4);102 expect(read == 4);
101 assert(mem.eql(u8, dest[0..4], bytes[2..6]));103 expect(mem.eql(u8, dest[0..4], bytes[2..6]));
102104
103 read = try ps.stream.read(dest[0..4]);105 read = try ps.stream.read(dest[0..4]);
104 assert(read == 2);106 expect(read == 2);
105 assert(mem.eql(u8, dest[0..2], bytes[6..8]));107 expect(mem.eql(u8, dest[0..2], bytes[6..8]));
106108
107 ps.putBackByte(11);109 ps.putBackByte(11);
108 ps.putBackByte(12);110 ps.putBackByte(12);
109111
110 read = try ps.stream.read(dest[0..4]);112 read = try ps.stream.read(dest[0..4]);
111 assert(read == 2);113 expect(read == 2);
112 assert(dest[0] == 12);114 expect(dest[0] == 12);
113 assert(dest[1] == 11);115 expect(dest[1] == 11);
114}116}
115117
116test "SliceOutStream" {118test "SliceOutStream" {
...@@ -118,17 +120,461 @@ test "SliceOutStream" {...@@ -118,17 +120,461 @@ test "SliceOutStream" {
118 var ss = io.SliceOutStream.init(buffer[0..]);120 var ss = io.SliceOutStream.init(buffer[0..]);
119121
120 try ss.stream.write("Hello");122 try ss.stream.write("Hello");
121 assert(mem.eql(u8, ss.getWritten(), "Hello"));123 expect(mem.eql(u8, ss.getWritten(), "Hello"));
122124
123 try ss.stream.write("world");125 try ss.stream.write("world");
124 assert(mem.eql(u8, ss.getWritten(), "Helloworld"));126 expect(mem.eql(u8, ss.getWritten(), "Helloworld"));
125127
126 assertError(ss.stream.write("!"), error.OutOfSpace);128 expectError(error.OutOfSpace, ss.stream.write("!"));
127 assert(mem.eql(u8, ss.getWritten(), "Helloworld"));129 expect(mem.eql(u8, ss.getWritten(), "Helloworld"));
128130
129 ss.reset();131 ss.reset();
130 assert(ss.getWritten().len == 0);132 expect(ss.getWritten().len == 0);
131133
132 assertError(ss.stream.write("Hello world!"), error.OutOfSpace);134 expectError(error.OutOfSpace, ss.stream.write("Hello world!"));
133 assert(mem.eql(u8, ss.getWritten(), "Hello worl"));135 expect(mem.eql(u8, ss.getWritten(), "Hello worl"));
136}
137
138test "BitInStream" {
139 const mem_be = []u8{ 0b11001101, 0b00001011 };
140 const mem_le = []u8{ 0b00011101, 0b10010101 };
141
142 var mem_in_be = io.SliceInStream.init(mem_be[0..]);
143 const InError = io.SliceInStream.Error;
144 var bit_stream_be = io.BitInStream(builtin.Endian.Big, InError).init(&mem_in_be.stream);
145
146 var out_bits: usize = undefined;
147
148 expect(1 == try bit_stream_be.readBits(u2, 1, &out_bits));
149 expect(out_bits == 1);
150 expect(2 == try bit_stream_be.readBits(u5, 2, &out_bits));
151 expect(out_bits == 2);
152 expect(3 == try bit_stream_be.readBits(u128, 3, &out_bits));
153 expect(out_bits == 3);
154 expect(4 == try bit_stream_be.readBits(u8, 4, &out_bits));
155 expect(out_bits == 4);
156 expect(5 == try bit_stream_be.readBits(u9, 5, &out_bits));
157 expect(out_bits == 5);
158 expect(1 == try bit_stream_be.readBits(u1, 1, &out_bits));
159 expect(out_bits == 1);
160
161 mem_in_be.pos = 0;
162 bit_stream_be.bit_count = 0;
163 expect(0b110011010000101 == try bit_stream_be.readBits(u15, 15, &out_bits));
164 expect(out_bits == 15);
165
166 mem_in_be.pos = 0;
167 bit_stream_be.bit_count = 0;
168 expect(0b1100110100001011 == try bit_stream_be.readBits(u16, 16, &out_bits));
169 expect(out_bits == 16);
170
171 _ = try bit_stream_be.readBits(u0, 0, &out_bits);
172
173 expect(0 == try bit_stream_be.readBits(u1, 1, &out_bits));
174 expect(out_bits == 0);
175 expectError(error.EndOfStream, bit_stream_be.readBitsNoEof(u1, 1));
176
177 var mem_in_le = io.SliceInStream.init(mem_le[0..]);
178 var bit_stream_le = io.BitInStream(builtin.Endian.Little, InError).init(&mem_in_le.stream);
179
180 expect(1 == try bit_stream_le.readBits(u2, 1, &out_bits));
181 expect(out_bits == 1);
182 expect(2 == try bit_stream_le.readBits(u5, 2, &out_bits));
183 expect(out_bits == 2);
184 expect(3 == try bit_stream_le.readBits(u128, 3, &out_bits));
185 expect(out_bits == 3);
186 expect(4 == try bit_stream_le.readBits(u8, 4, &out_bits));
187 expect(out_bits == 4);
188 expect(5 == try bit_stream_le.readBits(u9, 5, &out_bits));
189 expect(out_bits == 5);
190 expect(1 == try bit_stream_le.readBits(u1, 1, &out_bits));
191 expect(out_bits == 1);
192
193 mem_in_le.pos = 0;
194 bit_stream_le.bit_count = 0;
195 expect(0b001010100011101 == try bit_stream_le.readBits(u15, 15, &out_bits));
196 expect(out_bits == 15);
197
198 mem_in_le.pos = 0;
199 bit_stream_le.bit_count = 0;
200 expect(0b1001010100011101 == try bit_stream_le.readBits(u16, 16, &out_bits));
201 expect(out_bits == 16);
202
203 _ = try bit_stream_le.readBits(u0, 0, &out_bits);
204
205 expect(0 == try bit_stream_le.readBits(u1, 1, &out_bits));
206 expect(out_bits == 0);
207 expectError(error.EndOfStream, bit_stream_le.readBitsNoEof(u1, 1));
208}
209
210test "BitOutStream" {
211 var mem_be = []u8{0} ** 2;
212 var mem_le = []u8{0} ** 2;
213
214 var mem_out_be = io.SliceOutStream.init(mem_be[0..]);
215 const OutError = io.SliceOutStream.Error;
216 var bit_stream_be = io.BitOutStream(builtin.Endian.Big, OutError).init(&mem_out_be.stream);
217
218 try bit_stream_be.writeBits(u2(1), 1);
219 try bit_stream_be.writeBits(u5(2), 2);
220 try bit_stream_be.writeBits(u128(3), 3);
221 try bit_stream_be.writeBits(u8(4), 4);
222 try bit_stream_be.writeBits(u9(5), 5);
223 try bit_stream_be.writeBits(u1(1), 1);
224
225 expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001011);
226
227 mem_out_be.pos = 0;
228
229 try bit_stream_be.writeBits(u15(0b110011010000101), 15);
230 try bit_stream_be.flushBits();
231 expect(mem_be[0] == 0b11001101 and mem_be[1] == 0b00001010);
232
233 mem_out_be.pos = 0;
234 try bit_stream_be.writeBits(u32(0b110011010000101), 16);
235 expect(mem_be[0] == 0b01100110 and mem_be[1] == 0b10000101);
236
237 try bit_stream_be.writeBits(u0(0), 0);
238
239 var mem_out_le = io.SliceOutStream.init(mem_le[0..]);
240 var bit_stream_le = io.BitOutStream(builtin.Endian.Little, OutError).init(&mem_out_le.stream);
241
242 try bit_stream_le.writeBits(u2(1), 1);
243 try bit_stream_le.writeBits(u5(2), 2);
244 try bit_stream_le.writeBits(u128(3), 3);
245 try bit_stream_le.writeBits(u8(4), 4);
246 try bit_stream_le.writeBits(u9(5), 5);
247 try bit_stream_le.writeBits(u1(1), 1);
248
249 expect(mem_le[0] == 0b00011101 and mem_le[1] == 0b10010101);
250
251 mem_out_le.pos = 0;
252 try bit_stream_le.writeBits(u15(0b110011010000101), 15);
253 try bit_stream_le.flushBits();
254 expect(mem_le[0] == 0b10000101 and mem_le[1] == 0b01100110);
255
256 mem_out_le.pos = 0;
257 try bit_stream_le.writeBits(u32(0b1100110100001011), 16);
258 expect(mem_le[0] == 0b00001011 and mem_le[1] == 0b11001101);
259
260 try bit_stream_le.writeBits(u0(0), 0);
261}
262
263test "BitStreams with File Stream" {
264 const tmp_file_name = "temp_test_file.txt";
265 {
266 var file = try os.File.openWrite(tmp_file_name);
267 defer file.close();
268
269 var file_out = file.outStream();
270 var file_out_stream = &file_out.stream;
271 const OutError = os.File.WriteError;
272 var bit_stream = io.BitOutStream(builtin.endian, OutError).init(file_out_stream);
273
274 try bit_stream.writeBits(u2(1), 1);
275 try bit_stream.writeBits(u5(2), 2);
276 try bit_stream.writeBits(u128(3), 3);
277 try bit_stream.writeBits(u8(4), 4);
278 try bit_stream.writeBits(u9(5), 5);
279 try bit_stream.writeBits(u1(1), 1);
280 try bit_stream.flushBits();
281 }
282 {
283 var file = try os.File.openRead(tmp_file_name);
284 defer file.close();
285
286 var file_in = file.inStream();
287 var file_in_stream = &file_in.stream;
288 const InError = os.File.ReadError;
289 var bit_stream = io.BitInStream(builtin.endian, InError).init(file_in_stream);
290
291 var out_bits: usize = undefined;
292
293 expect(1 == try bit_stream.readBits(u2, 1, &out_bits));
294 expect(out_bits == 1);
295 expect(2 == try bit_stream.readBits(u5, 2, &out_bits));
296 expect(out_bits == 2);
297 expect(3 == try bit_stream.readBits(u128, 3, &out_bits));
298 expect(out_bits == 3);
299 expect(4 == try bit_stream.readBits(u8, 4, &out_bits));
300 expect(out_bits == 4);
301 expect(5 == try bit_stream.readBits(u9, 5, &out_bits));
302 expect(out_bits == 5);
303 expect(1 == try bit_stream.readBits(u1, 1, &out_bits));
304 expect(out_bits == 1);
305
306 expectError(error.EndOfStream, bit_stream.readBitsNoEof(u1, 1));
307 }
308 try os.deleteFile(tmp_file_name);
309}
310
311fn testIntSerializerDeserializer(comptime endian: builtin.Endian, comptime is_packed: bool) !void {
312 //@NOTE: if this test is taking too long, reduce the maximum tested bitsize
313 const max_test_bitsize = 128;
314
315 const total_bytes = comptime blk: {
316 var bytes = 0;
317 comptime var i = 0;
318 while (i <= max_test_bitsize) : (i += 1) bytes += (i / 8) + @boolToInt(i % 8 > 0);
319 break :blk bytes * 2;
320 };
321
322 var data_mem: [total_bytes]u8 = undefined;
323 var out = io.SliceOutStream.init(data_mem[0..]);
324 const OutError = io.SliceOutStream.Error;
325 var out_stream = &out.stream;
326 var serializer = io.Serializer(endian, is_packed, OutError).init(out_stream);
327
328 var in = io.SliceInStream.init(data_mem[0..]);
329 const InError = io.SliceInStream.Error;
330 var in_stream = &in.stream;
331 var deserializer = io.Deserializer(endian, is_packed, InError).init(in_stream);
332
333 comptime var i = 0;
334 inline while (i <= max_test_bitsize) : (i += 1) {
335 const U = @IntType(false, i);
336 const S = @IntType(true, i);
337 try serializer.serializeInt(U(i));
338 if (i != 0) try serializer.serializeInt(S(-1)) else try serializer.serialize(S(0));
339 }
340 try serializer.flush();
341
342 i = 0;
343 inline while (i <= max_test_bitsize) : (i += 1) {
344 const U = @IntType(false, i);
345 const S = @IntType(true, i);
346 const x = try deserializer.deserializeInt(U);
347 const y = try deserializer.deserializeInt(S);
348 expect(x == U(i));
349 if (i != 0) expect(y == S(-1)) else expect(y == 0);
350 }
351
352 const u8_bit_count = comptime meta.bitCount(u8);
353 //0 + 1 + 2 + ... n = (n * (n + 1)) / 2
354 //and we have each for unsigned and signed, so * 2
355 const total_bits = (max_test_bitsize * (max_test_bitsize + 1));
356 const extra_packed_byte = @boolToInt(total_bits % u8_bit_count > 0);
357 const total_packed_bytes = (total_bits / u8_bit_count) + extra_packed_byte;
358
359 expect(in.pos == if (is_packed) total_packed_bytes else total_bytes);
360
361 //Verify that empty error set works with serializer.
362 //deserializer is covered by SliceInStream
363 const NullError = io.NullOutStream.Error;
364 var null_out = io.NullOutStream.init();
365 var null_out_stream = &null_out.stream;
366 var null_serializer = io.Serializer(endian, is_packed, NullError).init(null_out_stream);
367 try null_serializer.serialize(data_mem[0..]);
368 try null_serializer.flush();
369}
370
371test "Serializer/Deserializer Int" {
372 try testIntSerializerDeserializer(builtin.Endian.Big, false);
373 try testIntSerializerDeserializer(builtin.Endian.Little, false);
374 try testIntSerializerDeserializer(builtin.Endian.Big, true);
375 try testIntSerializerDeserializer(builtin.Endian.Little, true);
376}
377
378fn testIntSerializerDeserializerInfNaN(comptime endian: builtin.Endian,
379 comptime is_packed: bool) !void
380{
381 const mem_size = (16*2 + 32*2 + 64*2 + 128*2) / comptime meta.bitCount(u8);
382 var data_mem: [mem_size]u8 = undefined;
383
384 var out = io.SliceOutStream.init(data_mem[0..]);
385 const OutError = io.SliceOutStream.Error;
386 var out_stream = &out.stream;
387 var serializer = io.Serializer(endian, is_packed, OutError).init(out_stream);
388
389 var in = io.SliceInStream.init(data_mem[0..]);
390 const InError = io.SliceInStream.Error;
391 var in_stream = &in.stream;
392 var deserializer = io.Deserializer(endian, is_packed, InError).init(in_stream);
393
394 //@TODO: isInf/isNan not currently implemented for f128.
395 try serializer.serialize(std.math.nan(f16));
396 try serializer.serialize(std.math.inf(f16));
397 try serializer.serialize(std.math.nan(f32));
398 try serializer.serialize(std.math.inf(f32));
399 try serializer.serialize(std.math.nan(f64));
400 try serializer.serialize(std.math.inf(f64));
401 //try serializer.serialize(std.math.nan(f128));
402 //try serializer.serialize(std.math.inf(f128));
403 const nan_check_f16 = try deserializer.deserialize(f16);
404 const inf_check_f16 = try deserializer.deserialize(f16);
405 const nan_check_f32 = try deserializer.deserialize(f32);
406 const inf_check_f32 = try deserializer.deserialize(f32);
407 const nan_check_f64 = try deserializer.deserialize(f64);
408 const inf_check_f64 = try deserializer.deserialize(f64);
409 //const nan_check_f128 = try deserializer.deserialize(f128);
410 //const inf_check_f128 = try deserializer.deserialize(f128);
411 expect(std.math.isNan(nan_check_f16));
412 expect(std.math.isInf(inf_check_f16));
413 expect(std.math.isNan(nan_check_f32));
414 expect(std.math.isInf(inf_check_f32));
415 expect(std.math.isNan(nan_check_f64));
416 expect(std.math.isInf(inf_check_f64));
417 //expect(std.math.isNan(nan_check_f128));
418 //expect(std.math.isInf(inf_check_f128));
419}
420
421test "Serializer/Deserializer Int: Inf/NaN" {
422 try testIntSerializerDeserializerInfNaN(builtin.Endian.Big, false);
423 try testIntSerializerDeserializerInfNaN(builtin.Endian.Little, false);
424 try testIntSerializerDeserializerInfNaN(builtin.Endian.Big, true);
425 try testIntSerializerDeserializerInfNaN(builtin.Endian.Little, true);
426}
427
428fn testAlternateSerializer(self: var, serializer: var) !void {
429 try serializer.serialize(self.f_f16);
430}
431
432fn testSerializerDeserializer(comptime endian: builtin.Endian, comptime is_packed: bool) !void {
433 const ColorType = enum(u4) {
434 RGB8 = 1,
435 RA16 = 2,
436 R32 = 3,
437 };
438
439 const TagAlign = union(enum(u32)) {
440 A: u8,
441 B: u8,
442 C: u8,
443 };
444
445 const Color = union(ColorType) {
446 RGB8: struct {
447 r: u8,
448 g: u8,
449 b: u8,
450 a: u8,
451 },
452 RA16: struct {
453 r: u16,
454 a: u16,
455 },
456 R32: u32,
457 };
458
459 const PackedStruct = packed struct {
460 f_i3: i3,
461 f_u2: u2,
462 };
463
464
465
466 //to test custom serialization
467 const Custom = struct {
468 f_f16: f16,
469 f_unused_u32: u32,
470
471 pub fn deserialize(self: *@This(), deserializer: var) !void {
472 try deserializer.deserializeInto(&self.f_f16);
473 self.f_unused_u32 = 47;
474 }
475
476 pub const serialize = testAlternateSerializer;
477 };
478
479 const MyStruct = struct {
480 f_i3: i3,
481 f_u8: u8,
482 f_tag_align: TagAlign,
483 f_u24: u24,
484 f_i19: i19,
485 f_void: void,
486 f_f32: f32,
487 f_f128: f128,
488 f_packed_0: PackedStruct,
489 f_i7arr: [10]i7,
490 f_of64n: ?f64,
491 f_of64v: ?f64,
492 f_color_type: ColorType,
493 f_packed_1: PackedStruct,
494 f_custom: Custom,
495 f_color: Color,
496 };
497
498 const my_inst = MyStruct{
499 .f_i3 = -1,
500 .f_u8 = 8,
501 .f_tag_align = TagAlign{ .B = 148 },
502 .f_u24 = 24,
503 .f_i19 = 19,
504 .f_void = {},
505 .f_f32 = 32.32,
506 .f_f128 = 128.128,
507 .f_packed_0 = PackedStruct{ .f_i3 = -1, .f_u2 = 2 },
508 .f_i7arr = [10]i7{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
509 .f_of64n = null,
510 .f_of64v = 64.64,
511 .f_color_type = ColorType.R32,
512 .f_packed_1 = PackedStruct{ .f_i3 = 1, .f_u2 = 1 },
513 .f_custom = Custom{ .f_f16 = 38.63, .f_unused_u32 = 47 },
514 .f_color = Color{ .R32 = 123822 },
515 };
516
517 var data_mem: [@sizeOf(MyStruct)]u8 = undefined;
518 var out = io.SliceOutStream.init(data_mem[0..]);
519 const OutError = io.SliceOutStream.Error;
520 var out_stream = &out.stream;
521 var serializer = io.Serializer(endian, is_packed, OutError).init(out_stream);
522
523 var in = io.SliceInStream.init(data_mem[0..]);
524 const InError = io.SliceInStream.Error;
525 var in_stream = &in.stream;
526 var deserializer = io.Deserializer(endian, is_packed, InError).init(in_stream);
527
528 try serializer.serialize(my_inst);
529
530 const my_copy = try deserializer.deserialize(MyStruct);
531 expect(meta.eql(my_copy, my_inst));
532}
533
534test "Serializer/Deserializer generic" {
535 try testSerializerDeserializer(builtin.Endian.Big, false);
536 try testSerializerDeserializer(builtin.Endian.Little, false);
537 try testSerializerDeserializer(builtin.Endian.Big, true);
538 try testSerializerDeserializer(builtin.Endian.Little, true);
539}
540
541fn testBadData(comptime endian: builtin.Endian, comptime is_packed: bool) !void {
542 const E = enum(u14) {
543 One = 1,
544 Two = 2,
545 };
546
547 const A = struct {
548 e: E,
549 };
550
551 const C = union(E) {
552 One: u14,
553 Two: f16,
554 };
555
556 var data_mem: [4]u8 = undefined;
557 var out = io.SliceOutStream.init(data_mem[0..]);
558 const OutError = io.SliceOutStream.Error;
559 var out_stream = &out.stream;
560 var serializer = io.Serializer(endian, is_packed, OutError).init(out_stream);
561
562 var in = io.SliceInStream.init(data_mem[0..]);
563 const InError = io.SliceInStream.Error;
564 var in_stream = &in.stream;
565 var deserializer = io.Deserializer(endian, is_packed, InError).init(in_stream);
566
567 try serializer.serialize(u14(3));
568 expectError(error.InvalidEnumTag, deserializer.deserialize(A));
569 out.pos = 0;
570 try serializer.serialize(u14(3));
571 try serializer.serialize(u14(88));
572 expectError(error.InvalidEnumTag, deserializer.deserialize(C));
573}
574
575test "Deserializer bad data" {
576 try testBadData(builtin.Endian.Big, false);
577 try testBadData(builtin.Endian.Little, false);
578 try testBadData(builtin.Endian.Big, true);
579 try testBadData(builtin.Endian.Little, true);
134}580}
std/json.zig+15-10
...@@ -4,6 +4,7 @@...@@ -4,6 +4,7 @@
44
5const std = @import("index.zig");5const std = @import("index.zig");
6const debug = std.debug;6const debug = std.debug;
7const testing = std.testing;
7const mem = std.mem;8const mem = std.mem;
8const maxInt = std.math.maxInt;9const maxInt = std.math.maxInt;
910
...@@ -960,7 +961,7 @@ test "json.token" {...@@ -960,7 +961,7 @@ test "json.token" {
960 checkNext(&p, Token.Id.ObjectEnd);961 checkNext(&p, Token.Id.ObjectEnd);
961 checkNext(&p, Token.Id.ObjectEnd);962 checkNext(&p, Token.Id.ObjectEnd);
962963
963 debug.assert((try p.next()) == null);964 testing.expect((try p.next()) == null);
964}965}
965966
966// Validate a JSON string. This does not limit number precision so a decoder may not necessarily967// Validate a JSON string. This does not limit number precision so a decoder may not necessarily
...@@ -981,7 +982,7 @@ pub fn validate(s: []const u8) bool {...@@ -981,7 +982,7 @@ pub fn validate(s: []const u8) bool {
981}982}
982983
983test "json.validate" {984test "json.validate" {
984 debug.assert(validate("{}"));985 testing.expect(validate("{}"));
985}986}
986987
987const Allocator = std.mem.Allocator;988const Allocator = std.mem.Allocator;
...@@ -1344,7 +1345,7 @@ pub const Parser = struct {...@@ -1344,7 +1345,7 @@ pub const Parser = struct {
1344 return if (token.number_is_integer)1345 return if (token.number_is_integer)
1345 Value{ .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) }1346 Value{ .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) }
1346 else1347 else
1347 @panic("TODO: fmt.parseFloat not yet implemented");1348 Value{ .Float = try std.fmt.parseFloat(f64, token.slice(input, i)) };
1348 }1349 }
1349};1350};
13501351
...@@ -1365,7 +1366,8 @@ test "json.parser.dynamic" {...@@ -1365,7 +1366,8 @@ test "json.parser.dynamic" {
1365 \\ },1366 \\ },
1366 \\ "Animated" : false,1367 \\ "Animated" : false,
1367 \\ "IDs": [116, 943, 234, 38793],1368 \\ "IDs": [116, 943, 234, 38793],
1368 \\ "ArrayOfObject": [{"n": "m"}]1369 \\ "ArrayOfObject": [{"n": "m"}],
1370 \\ "double": 1.3412
1369 \\ }1371 \\ }
1370 \\}1372 \\}
1371 ;1373 ;
...@@ -1378,20 +1380,23 @@ test "json.parser.dynamic" {...@@ -1378,20 +1380,23 @@ test "json.parser.dynamic" {
1378 var image = root.Object.get("Image").?.value;1380 var image = root.Object.get("Image").?.value;
13791381
1380 const width = image.Object.get("Width").?.value;1382 const width = image.Object.get("Width").?.value;
1381 debug.assert(width.Integer == 800);1383 testing.expect(width.Integer == 800);
13821384
1383 const height = image.Object.get("Height").?.value;1385 const height = image.Object.get("Height").?.value;
1384 debug.assert(height.Integer == 600);1386 testing.expect(height.Integer == 600);
13851387
1386 const title = image.Object.get("Title").?.value;1388 const title = image.Object.get("Title").?.value;
1387 debug.assert(mem.eql(u8, title.String, "View from 15th Floor"));1389 testing.expect(mem.eql(u8, title.String, "View from 15th Floor"));
13881390
1389 const animated = image.Object.get("Animated").?.value;1391 const animated = image.Object.get("Animated").?.value;
1390 debug.assert(animated.Bool == false);1392 testing.expect(animated.Bool == false);
13911393
1392 const array_of_object = image.Object.get("ArrayOfObject").?.value;1394 const array_of_object = image.Object.get("ArrayOfObject").?.value;
1393 debug.assert(array_of_object.Array.len == 1);1395 testing.expect(array_of_object.Array.len == 1);
13941396
1395 const obj0 = array_of_object.Array.at(0).Object.get("n").?.value;1397 const obj0 = array_of_object.Array.at(0).Object.get("n").?.value;
1396 debug.assert(mem.eql(u8, obj0.String, "m"));1398 testing.expect(mem.eql(u8, obj0.String, "m"));
1399
1400 const double = image.Object.get("double").?.value;
1401 testing.expect(double.Float == 1.3412);
1397}1402}
std/json_test.zig+3-3
...@@ -6,15 +6,15 @@...@@ -6,15 +6,15 @@
6const std = @import("index.zig");6const std = @import("index.zig");
77
8fn ok(comptime s: []const u8) void {8fn ok(comptime s: []const u8) void {
9 std.debug.assert(std.json.validate(s));9 std.testing.expect(std.json.validate(s));
10}10}
1111
12fn err(comptime s: []const u8) void {12fn err(comptime s: []const u8) void {
13 std.debug.assert(!std.json.validate(s));13 std.testing.expect(!std.json.validate(s));
14}14}
1515
16fn any(comptime s: []const u8) void {16fn any(comptime s: []const u8) void {
17 std.debug.assert(true);17 std.testing.expect(true);
18}18}
1919
20////////////////////////////////////////////////////////////////////////////////////////////////////20////////////////////////////////////////////////////////////////////////////////////////////////////
std/lazy_init.zig+5-4
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const std = @import("index.zig");1const std = @import("index.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const assert = std.debug.assert;3const assert = std.debug.assert;
4const testing = std.testing;
4const AtomicRmwOp = builtin.AtomicRmwOp;5const AtomicRmwOp = builtin.AtomicRmwOp;
5const AtomicOrder = builtin.AtomicOrder;6const AtomicOrder = builtin.AtomicOrder;
67
...@@ -63,12 +64,12 @@ test "std.lazyInit" {...@@ -63,12 +64,12 @@ test "std.lazyInit" {
63 global_number.resolve();64 global_number.resolve();
64 }65 }
65 if (global_number.get()) |x| {66 if (global_number.get()) |x| {
66 assert(x.* == 1234);67 testing.expect(x.* == 1234);
67 } else {68 } else {
68 @panic("bad");69 @panic("bad");
69 }70 }
70 if (global_number.get()) |x| {71 if (global_number.get()) |x| {
71 assert(x.* == 1234);72 testing.expect(x.* == 1234);
72 } else {73 } else {
73 @panic("bad");74 @panic("bad");
74 }75 }
...@@ -80,6 +81,6 @@ test "std.lazyInit(void)" {...@@ -80,6 +81,6 @@ test "std.lazyInit(void)" {
80 if (global_void.get()) |_| @panic("bad") else {81 if (global_void.get()) |_| @panic("bad") else {
81 global_void.resolve();82 global_void.resolve();
82 }83 }
83 assert(global_void.get() != null);84 testing.expect(global_void.get() != null);
84 assert(global_void.get() != null);85 testing.expect(global_void.get() != null);
85}86}
std/linked_list.zig+16-15
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const std = @import("index.zig");1const std = @import("index.zig");
2const debug = std.debug;2const debug = std.debug;
3const assert = debug.assert;3const assert = debug.assert;
4const testing = std.testing;
4const mem = std.mem;5const mem = std.mem;
5const Allocator = mem.Allocator;6const Allocator = mem.Allocator;
67
...@@ -190,7 +191,7 @@ pub fn LinkedList(comptime T: type) type {...@@ -190,7 +191,7 @@ pub fn LinkedList(comptime T: type) type {
190 /// Returns:191 /// Returns:
191 /// A pointer to the new node.192 /// A pointer to the new node.
192 pub fn allocateNode(list: *Self, allocator: *Allocator) !*Node {193 pub fn allocateNode(list: *Self, allocator: *Allocator) !*Node {
193 return allocator.create(Node(undefined));194 return allocator.create(Node);
194 }195 }
195196
196 /// Deallocate a node.197 /// Deallocate a node.
...@@ -246,7 +247,7 @@ test "basic linked list test" {...@@ -246,7 +247,7 @@ test "basic linked list test" {
246 var it = list.first;247 var it = list.first;
247 var index: u32 = 1;248 var index: u32 = 1;
248 while (it) |node| : (it = node.next) {249 while (it) |node| : (it = node.next) {
249 assert(node.data == index);250 testing.expect(node.data == index);
250 index += 1;251 index += 1;
251 }252 }
252 }253 }
...@@ -256,7 +257,7 @@ test "basic linked list test" {...@@ -256,7 +257,7 @@ test "basic linked list test" {
256 var it = list.last;257 var it = list.last;
257 var index: u32 = 1;258 var index: u32 = 1;
258 while (it) |node| : (it = node.prev) {259 while (it) |node| : (it = node.prev) {
259 assert(node.data == (6 - index));260 testing.expect(node.data == (6 - index));
260 index += 1;261 index += 1;
261 }262 }
262 }263 }
...@@ -265,9 +266,9 @@ test "basic linked list test" {...@@ -265,9 +266,9 @@ test "basic linked list test" {
265 var last = list.pop(); // {2, 3, 4}266 var last = list.pop(); // {2, 3, 4}
266 list.remove(three); // {2, 4}267 list.remove(three); // {2, 4}
267268
268 assert(list.first.?.data == 2);269 testing.expect(list.first.?.data == 2);
269 assert(list.last.?.data == 4);270 testing.expect(list.last.?.data == 4);
270 assert(list.len == 2);271 testing.expect(list.len == 2);
271}272}
272273
273test "linked list concatenation" {274test "linked list concatenation" {
...@@ -294,18 +295,18 @@ test "linked list concatenation" {...@@ -294,18 +295,18 @@ test "linked list concatenation" {
294295
295 list1.concatByMoving(&list2);296 list1.concatByMoving(&list2);
296297
297 assert(list1.last == five);298 testing.expect(list1.last == five);
298 assert(list1.len == 5);299 testing.expect(list1.len == 5);
299 assert(list2.first == null);300 testing.expect(list2.first == null);
300 assert(list2.last == null);301 testing.expect(list2.last == null);
301 assert(list2.len == 0);302 testing.expect(list2.len == 0);
302303
303 // Traverse forwards.304 // Traverse forwards.
304 {305 {
305 var it = list1.first;306 var it = list1.first;
306 var index: u32 = 1;307 var index: u32 = 1;
307 while (it) |node| : (it = node.next) {308 while (it) |node| : (it = node.next) {
308 assert(node.data == index);309 testing.expect(node.data == index);
309 index += 1;310 index += 1;
310 }311 }
311 }312 }
...@@ -315,7 +316,7 @@ test "linked list concatenation" {...@@ -315,7 +316,7 @@ test "linked list concatenation" {
315 var it = list1.last;316 var it = list1.last;
316 var index: u32 = 1;317 var index: u32 = 1;
317 while (it) |node| : (it = node.prev) {318 while (it) |node| : (it = node.prev) {
318 assert(node.data == (6 - index));319 testing.expect(node.data == (6 - index));
319 index += 1;320 index += 1;
320 }321 }
321 }322 }
...@@ -328,7 +329,7 @@ test "linked list concatenation" {...@@ -328,7 +329,7 @@ test "linked list concatenation" {
328 var it = list2.first;329 var it = list2.first;
329 var index: u32 = 1;330 var index: u32 = 1;
330 while (it) |node| : (it = node.next) {331 while (it) |node| : (it = node.next) {
331 assert(node.data == index);332 testing.expect(node.data == index);
332 index += 1;333 index += 1;
333 }334 }
334 }335 }
...@@ -338,7 +339,7 @@ test "linked list concatenation" {...@@ -338,7 +339,7 @@ test "linked list concatenation" {
338 var it = list2.last;339 var it = list2.last;
339 var index: u32 = 1;340 var index: u32 = 1;
340 while (it) |node| : (it = node.prev) {341 while (it) |node| : (it = node.prev) {
341 assert(node.data == (6 - index));342 testing.expect(node.data == (6 - index));
342 index += 1;343 index += 1;
343 }344 }
344 }345 }
std/math/acos.zig+19-19
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
44
5const std = @import("../index.zig");5const std = @import("../index.zig");
6const math = std.math;6const math = std.math;
7const assert = std.debug.assert;7const expect = std.testing.expect;
88
9pub fn acos(x: var) @typeOf(x) {9pub fn acos(x: var) @typeOf(x) {
10 const T = @typeOf(x);10 const T = @typeOf(x);
...@@ -143,38 +143,38 @@ fn acos64(x: f64) f64 {...@@ -143,38 +143,38 @@ fn acos64(x: f64) f64 {
143}143}
144144
145test "math.acos" {145test "math.acos" {
146 assert(acos(f32(0.0)) == acos32(0.0));146 expect(acos(f32(0.0)) == acos32(0.0));
147 assert(acos(f64(0.0)) == acos64(0.0));147 expect(acos(f64(0.0)) == acos64(0.0));
148}148}
149149
150test "math.acos32" {150test "math.acos32" {
151 const epsilon = 0.000001;151 const epsilon = 0.000001;
152152
153 assert(math.approxEq(f32, acos32(0.0), 1.570796, epsilon));153 expect(math.approxEq(f32, acos32(0.0), 1.570796, epsilon));
154 assert(math.approxEq(f32, acos32(0.2), 1.369438, epsilon));154 expect(math.approxEq(f32, acos32(0.2), 1.369438, epsilon));
155 assert(math.approxEq(f32, acos32(0.3434), 1.220262, epsilon));155 expect(math.approxEq(f32, acos32(0.3434), 1.220262, epsilon));
156 assert(math.approxEq(f32, acos32(0.5), 1.047198, epsilon));156 expect(math.approxEq(f32, acos32(0.5), 1.047198, epsilon));
157 assert(math.approxEq(f32, acos32(0.8923), 0.468382, epsilon));157 expect(math.approxEq(f32, acos32(0.8923), 0.468382, epsilon));
158 assert(math.approxEq(f32, acos32(-0.2), 1.772154, epsilon));158 expect(math.approxEq(f32, acos32(-0.2), 1.772154, epsilon));
159}159}
160160
161test "math.acos64" {161test "math.acos64" {
162 const epsilon = 0.000001;162 const epsilon = 0.000001;
163163
164 assert(math.approxEq(f64, acos64(0.0), 1.570796, epsilon));164 expect(math.approxEq(f64, acos64(0.0), 1.570796, epsilon));
165 assert(math.approxEq(f64, acos64(0.2), 1.369438, epsilon));165 expect(math.approxEq(f64, acos64(0.2), 1.369438, epsilon));
166 assert(math.approxEq(f64, acos64(0.3434), 1.220262, epsilon));166 expect(math.approxEq(f64, acos64(0.3434), 1.220262, epsilon));
167 assert(math.approxEq(f64, acos64(0.5), 1.047198, epsilon));167 expect(math.approxEq(f64, acos64(0.5), 1.047198, epsilon));
168 assert(math.approxEq(f64, acos64(0.8923), 0.468382, epsilon));168 expect(math.approxEq(f64, acos64(0.8923), 0.468382, epsilon));
169 assert(math.approxEq(f64, acos64(-0.2), 1.772154, epsilon));169 expect(math.approxEq(f64, acos64(-0.2), 1.772154, epsilon));
170}170}
171171
172test "math.acos32.special" {172test "math.acos32.special" {
173 assert(math.isNan(acos32(-2)));173 expect(math.isNan(acos32(-2)));
174 assert(math.isNan(acos32(1.5)));174 expect(math.isNan(acos32(1.5)));
175}175}
176176
177test "math.acos64.special" {177test "math.acos64.special" {
178 assert(math.isNan(acos64(-2)));178 expect(math.isNan(acos64(-2)));
179 assert(math.isNan(acos64(1.5)));179 expect(math.isNan(acos64(1.5)));
180}180}
std/math/acosh.zig+15-15
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6const builtin = @import("builtin");6const builtin = @import("builtin");
7const std = @import("../index.zig");7const std = @import("../index.zig");
8const math = std.math;8const math = std.math;
9const assert = std.debug.assert;9const expect = std.testing.expect;
1010
11pub fn acosh(x: var) @typeOf(x) {11pub fn acosh(x: var) @typeOf(x) {
12 const T = @typeOf(x);12 const T = @typeOf(x);
...@@ -55,34 +55,34 @@ fn acosh64(x: f64) f64 {...@@ -55,34 +55,34 @@ fn acosh64(x: f64) f64 {
55}55}
5656
57test "math.acosh" {57test "math.acosh" {
58 assert(acosh(f32(1.5)) == acosh32(1.5));58 expect(acosh(f32(1.5)) == acosh32(1.5));
59 assert(acosh(f64(1.5)) == acosh64(1.5));59 expect(acosh(f64(1.5)) == acosh64(1.5));
60}60}
6161
62test "math.acosh32" {62test "math.acosh32" {
63 const epsilon = 0.000001;63 const epsilon = 0.000001;
6464
65 assert(math.approxEq(f32, acosh32(1.5), 0.962424, epsilon));65 expect(math.approxEq(f32, acosh32(1.5), 0.962424, epsilon));
66 assert(math.approxEq(f32, acosh32(37.45), 4.315976, epsilon));66 expect(math.approxEq(f32, acosh32(37.45), 4.315976, epsilon));
67 assert(math.approxEq(f32, acosh32(89.123), 5.183133, epsilon));67 expect(math.approxEq(f32, acosh32(89.123), 5.183133, epsilon));
68 assert(math.approxEq(f32, acosh32(123123.234375), 12.414088, epsilon));68 expect(math.approxEq(f32, acosh32(123123.234375), 12.414088, epsilon));
69}69}
7070
71test "math.acosh64" {71test "math.acosh64" {
72 const epsilon = 0.000001;72 const epsilon = 0.000001;
7373
74 assert(math.approxEq(f64, acosh64(1.5), 0.962424, epsilon));74 expect(math.approxEq(f64, acosh64(1.5), 0.962424, epsilon));
75 assert(math.approxEq(f64, acosh64(37.45), 4.315976, epsilon));75 expect(math.approxEq(f64, acosh64(37.45), 4.315976, epsilon));
76 assert(math.approxEq(f64, acosh64(89.123), 5.183133, epsilon));76 expect(math.approxEq(f64, acosh64(89.123), 5.183133, epsilon));
77 assert(math.approxEq(f64, acosh64(123123.234375), 12.414088, epsilon));77 expect(math.approxEq(f64, acosh64(123123.234375), 12.414088, epsilon));
78}78}
7979
80test "math.acosh32.special" {80test "math.acosh32.special" {
81 assert(math.isNan(acosh32(math.nan(f32))));81 expect(math.isNan(acosh32(math.nan(f32))));
82 assert(math.isSignalNan(acosh32(0.5)));82 expect(math.isSignalNan(acosh32(0.5)));
83}83}
8484
85test "math.acosh64.special" {85test "math.acosh64.special" {
86 assert(math.isNan(acosh64(math.nan(f64))));86 expect(math.isNan(acosh64(math.nan(f64))));
87 assert(math.isSignalNan(acosh64(0.5)));87 expect(math.isSignalNan(acosh64(0.5)));
88}88}
std/math/asin.zig+23-23
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
55
6const std = @import("../index.zig");6const std = @import("../index.zig");
7const math = std.math;7const math = std.math;
8const assert = std.debug.assert;8const expect = std.testing.expect;
99
10pub fn asin(x: var) @typeOf(x) {10pub fn asin(x: var) @typeOf(x) {
11 const T = @typeOf(x);11 const T = @typeOf(x);
...@@ -136,42 +136,42 @@ fn asin64(x: f64) f64 {...@@ -136,42 +136,42 @@ fn asin64(x: f64) f64 {
136}136}
137137
138test "math.asin" {138test "math.asin" {
139 assert(asin(f32(0.0)) == asin32(0.0));139 expect(asin(f32(0.0)) == asin32(0.0));
140 assert(asin(f64(0.0)) == asin64(0.0));140 expect(asin(f64(0.0)) == asin64(0.0));
141}141}
142142
143test "math.asin32" {143test "math.asin32" {
144 const epsilon = 0.000001;144 const epsilon = 0.000001;
145145
146 assert(math.approxEq(f32, asin32(0.0), 0.0, epsilon));146 expect(math.approxEq(f32, asin32(0.0), 0.0, epsilon));
147 assert(math.approxEq(f32, asin32(0.2), 0.201358, epsilon));147 expect(math.approxEq(f32, asin32(0.2), 0.201358, epsilon));
148 assert(math.approxEq(f32, asin32(-0.2), -0.201358, epsilon));148 expect(math.approxEq(f32, asin32(-0.2), -0.201358, epsilon));
149 assert(math.approxEq(f32, asin32(0.3434), 0.350535, epsilon));149 expect(math.approxEq(f32, asin32(0.3434), 0.350535, epsilon));
150 assert(math.approxEq(f32, asin32(0.5), 0.523599, epsilon));150 expect(math.approxEq(f32, asin32(0.5), 0.523599, epsilon));
151 assert(math.approxEq(f32, asin32(0.8923), 1.102415, epsilon));151 expect(math.approxEq(f32, asin32(0.8923), 1.102415, epsilon));
152}152}
153153
154test "math.asin64" {154test "math.asin64" {
155 const epsilon = 0.000001;155 const epsilon = 0.000001;
156156
157 assert(math.approxEq(f64, asin64(0.0), 0.0, epsilon));157 expect(math.approxEq(f64, asin64(0.0), 0.0, epsilon));
158 assert(math.approxEq(f64, asin64(0.2), 0.201358, epsilon));158 expect(math.approxEq(f64, asin64(0.2), 0.201358, epsilon));
159 assert(math.approxEq(f64, asin64(-0.2), -0.201358, epsilon));159 expect(math.approxEq(f64, asin64(-0.2), -0.201358, epsilon));
160 assert(math.approxEq(f64, asin64(0.3434), 0.350535, epsilon));160 expect(math.approxEq(f64, asin64(0.3434), 0.350535, epsilon));
161 assert(math.approxEq(f64, asin64(0.5), 0.523599, epsilon));161 expect(math.approxEq(f64, asin64(0.5), 0.523599, epsilon));
162 assert(math.approxEq(f64, asin64(0.8923), 1.102415, epsilon));162 expect(math.approxEq(f64, asin64(0.8923), 1.102415, epsilon));
163}163}
164164
165test "math.asin32.special" {165test "math.asin32.special" {
166 assert(asin32(0.0) == 0.0);166 expect(asin32(0.0) == 0.0);
167 assert(asin32(-0.0) == -0.0);167 expect(asin32(-0.0) == -0.0);
168 assert(math.isNan(asin32(-2)));168 expect(math.isNan(asin32(-2)));
169 assert(math.isNan(asin32(1.5)));169 expect(math.isNan(asin32(1.5)));
170}170}
171171
172test "math.asin64.special" {172test "math.asin64.special" {
173 assert(asin64(0.0) == 0.0);173 expect(asin64(0.0) == 0.0);
174 assert(asin64(-0.0) == -0.0);174 expect(asin64(-0.0) == -0.0);
175 assert(math.isNan(asin64(-2)));175 expect(math.isNan(asin64(-2)));
176 assert(math.isNan(asin64(1.5)));176 expect(math.isNan(asin64(1.5)));
177}177}
std/math/asinh.zig+27-27
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
66
7const std = @import("../index.zig");7const std = @import("../index.zig");
8const math = std.math;8const math = std.math;
9const assert = std.debug.assert;9const expect = std.testing.expect;
10const maxInt = std.math.maxInt;10const maxInt = std.math.maxInt;
1111
12pub fn asinh(x: var) @typeOf(x) {12pub fn asinh(x: var) @typeOf(x) {
...@@ -83,46 +83,46 @@ fn asinh64(x: f64) f64 {...@@ -83,46 +83,46 @@ fn asinh64(x: f64) f64 {
83}83}
8484
85test "math.asinh" {85test "math.asinh" {
86 assert(asinh(f32(0.0)) == asinh32(0.0));86 expect(asinh(f32(0.0)) == asinh32(0.0));
87 assert(asinh(f64(0.0)) == asinh64(0.0));87 expect(asinh(f64(0.0)) == asinh64(0.0));
88}88}
8989
90test "math.asinh32" {90test "math.asinh32" {
91 const epsilon = 0.000001;91 const epsilon = 0.000001;
9292
93 assert(math.approxEq(f32, asinh32(0.0), 0.0, epsilon));93 expect(math.approxEq(f32, asinh32(0.0), 0.0, epsilon));
94 assert(math.approxEq(f32, asinh32(0.2), 0.198690, epsilon));94 expect(math.approxEq(f32, asinh32(0.2), 0.198690, epsilon));
95 assert(math.approxEq(f32, asinh32(0.8923), 0.803133, epsilon));95 expect(math.approxEq(f32, asinh32(0.8923), 0.803133, epsilon));
96 assert(math.approxEq(f32, asinh32(1.5), 1.194763, epsilon));96 expect(math.approxEq(f32, asinh32(1.5), 1.194763, epsilon));
97 assert(math.approxEq(f32, asinh32(37.45), 4.316332, epsilon));97 expect(math.approxEq(f32, asinh32(37.45), 4.316332, epsilon));
98 assert(math.approxEq(f32, asinh32(89.123), 5.183196, epsilon));98 expect(math.approxEq(f32, asinh32(89.123), 5.183196, epsilon));
99 assert(math.approxEq(f32, asinh32(123123.234375), 12.414088, epsilon));99 expect(math.approxEq(f32, asinh32(123123.234375), 12.414088, epsilon));
100}100}
101101
102test "math.asinh64" {102test "math.asinh64" {
103 const epsilon = 0.000001;103 const epsilon = 0.000001;
104104
105 assert(math.approxEq(f64, asinh64(0.0), 0.0, epsilon));105 expect(math.approxEq(f64, asinh64(0.0), 0.0, epsilon));
106 assert(math.approxEq(f64, asinh64(0.2), 0.198690, epsilon));106 expect(math.approxEq(f64, asinh64(0.2), 0.198690, epsilon));
107 assert(math.approxEq(f64, asinh64(0.8923), 0.803133, epsilon));107 expect(math.approxEq(f64, asinh64(0.8923), 0.803133, epsilon));
108 assert(math.approxEq(f64, asinh64(1.5), 1.194763, epsilon));108 expect(math.approxEq(f64, asinh64(1.5), 1.194763, epsilon));
109 assert(math.approxEq(f64, asinh64(37.45), 4.316332, epsilon));109 expect(math.approxEq(f64, asinh64(37.45), 4.316332, epsilon));
110 assert(math.approxEq(f64, asinh64(89.123), 5.183196, epsilon));110 expect(math.approxEq(f64, asinh64(89.123), 5.183196, epsilon));
111 assert(math.approxEq(f64, asinh64(123123.234375), 12.414088, epsilon));111 expect(math.approxEq(f64, asinh64(123123.234375), 12.414088, epsilon));
112}112}
113113
114test "math.asinh32.special" {114test "math.asinh32.special" {
115 assert(asinh32(0.0) == 0.0);115 expect(asinh32(0.0) == 0.0);
116 assert(asinh32(-0.0) == -0.0);116 expect(asinh32(-0.0) == -0.0);
117 assert(math.isPositiveInf(asinh32(math.inf(f32))));117 expect(math.isPositiveInf(asinh32(math.inf(f32))));
118 assert(math.isNegativeInf(asinh32(-math.inf(f32))));118 expect(math.isNegativeInf(asinh32(-math.inf(f32))));
119 assert(math.isNan(asinh32(math.nan(f32))));119 expect(math.isNan(asinh32(math.nan(f32))));
120}120}
121121
122test "math.asinh64.special" {122test "math.asinh64.special" {
123 assert(asinh64(0.0) == 0.0);123 expect(asinh64(0.0) == 0.0);
124 assert(asinh64(-0.0) == -0.0);124 expect(asinh64(-0.0) == -0.0);
125 assert(math.isPositiveInf(asinh64(math.inf(f64))));125 expect(math.isPositiveInf(asinh64(math.inf(f64))));
126 assert(math.isNegativeInf(asinh64(-math.inf(f64))));126 expect(math.isNegativeInf(asinh64(-math.inf(f64))));
127 assert(math.isNan(asinh64(math.nan(f64))));127 expect(math.isNan(asinh64(math.nan(f64))));
128}128}
std/math/atan.zig+21-21
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
55
6const std = @import("../index.zig");6const std = @import("../index.zig");
7const math = std.math;7const math = std.math;
8const assert = std.debug.assert;8const expect = std.testing.expect;
99
10pub fn atan(x: var) @typeOf(x) {10pub fn atan(x: var) @typeOf(x) {
11 const T = @typeOf(x);11 const T = @typeOf(x);
...@@ -206,44 +206,44 @@ fn atan64(x_: f64) f64 {...@@ -206,44 +206,44 @@ fn atan64(x_: f64) f64 {
206}206}
207207
208test "math.atan" {208test "math.atan" {
209 assert(@bitCast(u32, atan(f32(0.2))) == @bitCast(u32, atan32(0.2)));209 expect(@bitCast(u32, atan(f32(0.2))) == @bitCast(u32, atan32(0.2)));
210 assert(atan(f64(0.2)) == atan64(0.2));210 expect(atan(f64(0.2)) == atan64(0.2));
211}211}
212212
213test "math.atan32" {213test "math.atan32" {
214 const epsilon = 0.000001;214 const epsilon = 0.000001;
215215
216 assert(math.approxEq(f32, atan32(0.2), 0.197396, epsilon));216 expect(math.approxEq(f32, atan32(0.2), 0.197396, epsilon));
217 assert(math.approxEq(f32, atan32(-0.2), -0.197396, epsilon));217 expect(math.approxEq(f32, atan32(-0.2), -0.197396, epsilon));
218 assert(math.approxEq(f32, atan32(0.3434), 0.330783, epsilon));218 expect(math.approxEq(f32, atan32(0.3434), 0.330783, epsilon));
219 assert(math.approxEq(f32, atan32(0.8923), 0.728545, epsilon));219 expect(math.approxEq(f32, atan32(0.8923), 0.728545, epsilon));
220 assert(math.approxEq(f32, atan32(1.5), 0.982794, epsilon));220 expect(math.approxEq(f32, atan32(1.5), 0.982794, epsilon));
221}221}
222222
223test "math.atan64" {223test "math.atan64" {
224 const epsilon = 0.000001;224 const epsilon = 0.000001;
225225
226 assert(math.approxEq(f64, atan64(0.2), 0.197396, epsilon));226 expect(math.approxEq(f64, atan64(0.2), 0.197396, epsilon));
227 assert(math.approxEq(f64, atan64(-0.2), -0.197396, epsilon));227 expect(math.approxEq(f64, atan64(-0.2), -0.197396, epsilon));
228 assert(math.approxEq(f64, atan64(0.3434), 0.330783, epsilon));228 expect(math.approxEq(f64, atan64(0.3434), 0.330783, epsilon));
229 assert(math.approxEq(f64, atan64(0.8923), 0.728545, epsilon));229 expect(math.approxEq(f64, atan64(0.8923), 0.728545, epsilon));
230 assert(math.approxEq(f64, atan64(1.5), 0.982794, epsilon));230 expect(math.approxEq(f64, atan64(1.5), 0.982794, epsilon));
231}231}
232232
233test "math.atan32.special" {233test "math.atan32.special" {
234 const epsilon = 0.000001;234 const epsilon = 0.000001;
235235
236 assert(atan32(0.0) == 0.0);236 expect(atan32(0.0) == 0.0);
237 assert(atan32(-0.0) == -0.0);237 expect(atan32(-0.0) == -0.0);
238 assert(math.approxEq(f32, atan32(math.inf(f32)), math.pi / 2.0, epsilon));238 expect(math.approxEq(f32, atan32(math.inf(f32)), math.pi / 2.0, epsilon));
239 assert(math.approxEq(f32, atan32(-math.inf(f32)), -math.pi / 2.0, epsilon));239 expect(math.approxEq(f32, atan32(-math.inf(f32)), -math.pi / 2.0, epsilon));
240}240}
241241
242test "math.atan64.special" {242test "math.atan64.special" {
243 const epsilon = 0.000001;243 const epsilon = 0.000001;
244244
245 assert(atan64(0.0) == 0.0);245 expect(atan64(0.0) == 0.0);
246 assert(atan64(-0.0) == -0.0);246 expect(atan64(-0.0) == -0.0);
247 assert(math.approxEq(f64, atan64(math.inf(f64)), math.pi / 2.0, epsilon));247 expect(math.approxEq(f64, atan64(math.inf(f64)), math.pi / 2.0, epsilon));
248 assert(math.approxEq(f64, atan64(-math.inf(f64)), -math.pi / 2.0, epsilon));248 expect(math.approxEq(f64, atan64(-math.inf(f64)), -math.pi / 2.0, epsilon));
249}249}
std/math/atan2.zig+58-58
...@@ -20,12 +20,12 @@...@@ -20,12 +20,12 @@
2020
21const std = @import("../index.zig");21const std = @import("../index.zig");
22const math = std.math;22const math = std.math;
23const assert = std.debug.assert;23const expect = std.testing.expect;
2424
25pub fn atan2(comptime T: type, x: T, y: T) T {25pub fn atan2(comptime T: type, y: T, x: T) T {
26 return switch (T) {26 return switch (T) {
27 f32 => atan2_32(x, y),27 f32 => atan2_32(y, x),
28 f64 => atan2_64(x, y),28 f64 => atan2_64(y, x),
29 else => @compileError("atan2 not implemented for " ++ @typeName(T)),29 else => @compileError("atan2 not implemented for " ++ @typeName(T)),
30 };30 };
31}31}
...@@ -206,78 +206,78 @@ fn atan2_64(y: f64, x: f64) f64 {...@@ -206,78 +206,78 @@ fn atan2_64(y: f64, x: f64) f64 {
206}206}
207207
208test "math.atan2" {208test "math.atan2" {
209 assert(atan2(f32, 0.2, 0.21) == atan2_32(0.2, 0.21));209 expect(atan2(f32, 0.2, 0.21) == atan2_32(0.2, 0.21));
210 assert(atan2(f64, 0.2, 0.21) == atan2_64(0.2, 0.21));210 expect(atan2(f64, 0.2, 0.21) == atan2_64(0.2, 0.21));
211}211}
212212
213test "math.atan2_32" {213test "math.atan2_32" {
214 const epsilon = 0.000001;214 const epsilon = 0.000001;
215215
216 assert(math.approxEq(f32, atan2_32(0.0, 0.0), 0.0, epsilon));216 expect(math.approxEq(f32, atan2_32(0.0, 0.0), 0.0, epsilon));
217 assert(math.approxEq(f32, atan2_32(0.2, 0.2), 0.785398, epsilon));217 expect(math.approxEq(f32, atan2_32(0.2, 0.2), 0.785398, epsilon));
218 assert(math.approxEq(f32, atan2_32(-0.2, 0.2), -0.785398, epsilon));218 expect(math.approxEq(f32, atan2_32(-0.2, 0.2), -0.785398, epsilon));
219 assert(math.approxEq(f32, atan2_32(0.2, -0.2), 2.356194, epsilon));219 expect(math.approxEq(f32, atan2_32(0.2, -0.2), 2.356194, epsilon));
220 assert(math.approxEq(f32, atan2_32(-0.2, -0.2), -2.356194, epsilon));220 expect(math.approxEq(f32, atan2_32(-0.2, -0.2), -2.356194, epsilon));
221 assert(math.approxEq(f32, atan2_32(0.34, -0.4), 2.437099, epsilon));221 expect(math.approxEq(f32, atan2_32(0.34, -0.4), 2.437099, epsilon));
222 assert(math.approxEq(f32, atan2_32(0.34, 1.243), 0.267001, epsilon));222 expect(math.approxEq(f32, atan2_32(0.34, 1.243), 0.267001, epsilon));
223}223}
224224
225test "math.atan2_64" {225test "math.atan2_64" {
226 const epsilon = 0.000001;226 const epsilon = 0.000001;
227227
228 assert(math.approxEq(f64, atan2_64(0.0, 0.0), 0.0, epsilon));228 expect(math.approxEq(f64, atan2_64(0.0, 0.0), 0.0, epsilon));
229 assert(math.approxEq(f64, atan2_64(0.2, 0.2), 0.785398, epsilon));229 expect(math.approxEq(f64, atan2_64(0.2, 0.2), 0.785398, epsilon));
230 assert(math.approxEq(f64, atan2_64(-0.2, 0.2), -0.785398, epsilon));230 expect(math.approxEq(f64, atan2_64(-0.2, 0.2), -0.785398, epsilon));
231 assert(math.approxEq(f64, atan2_64(0.2, -0.2), 2.356194, epsilon));231 expect(math.approxEq(f64, atan2_64(0.2, -0.2), 2.356194, epsilon));
232 assert(math.approxEq(f64, atan2_64(-0.2, -0.2), -2.356194, epsilon));232 expect(math.approxEq(f64, atan2_64(-0.2, -0.2), -2.356194, epsilon));
233 assert(math.approxEq(f64, atan2_64(0.34, -0.4), 2.437099, epsilon));233 expect(math.approxEq(f64, atan2_64(0.34, -0.4), 2.437099, epsilon));
234 assert(math.approxEq(f64, atan2_64(0.34, 1.243), 0.267001, epsilon));234 expect(math.approxEq(f64, atan2_64(0.34, 1.243), 0.267001, epsilon));
235}235}
236236
237test "math.atan2_32.special" {237test "math.atan2_32.special" {
238 const epsilon = 0.000001;238 const epsilon = 0.000001;
239239
240 assert(math.isNan(atan2_32(1.0, math.nan(f32))));240 expect(math.isNan(atan2_32(1.0, math.nan(f32))));
241 assert(math.isNan(atan2_32(math.nan(f32), 1.0)));241 expect(math.isNan(atan2_32(math.nan(f32), 1.0)));
242 assert(atan2_32(0.0, 5.0) == 0.0);242 expect(atan2_32(0.0, 5.0) == 0.0);
243 assert(atan2_32(-0.0, 5.0) == -0.0);243 expect(atan2_32(-0.0, 5.0) == -0.0);
244 assert(math.approxEq(f32, atan2_32(0.0, -5.0), math.pi, epsilon));244 expect(math.approxEq(f32, atan2_32(0.0, -5.0), math.pi, epsilon));
245 //assert(math.approxEq(f32, atan2_32(-0.0, -5.0), -math.pi, epsilon)); TODO support negative zero?245 //expect(math.approxEq(f32, atan2_32(-0.0, -5.0), -math.pi, epsilon)); TODO support negative zero?
246 assert(math.approxEq(f32, atan2_32(1.0, 0.0), math.pi / 2.0, epsilon));246 expect(math.approxEq(f32, atan2_32(1.0, 0.0), math.pi / 2.0, epsilon));
247 assert(math.approxEq(f32, atan2_32(1.0, -0.0), math.pi / 2.0, epsilon));247 expect(math.approxEq(f32, atan2_32(1.0, -0.0), math.pi / 2.0, epsilon));
248 assert(math.approxEq(f32, atan2_32(-1.0, 0.0), -math.pi / 2.0, epsilon));248 expect(math.approxEq(f32, atan2_32(-1.0, 0.0), -math.pi / 2.0, epsilon));
249 assert(math.approxEq(f32, atan2_32(-1.0, -0.0), -math.pi / 2.0, epsilon));249 expect(math.approxEq(f32, atan2_32(-1.0, -0.0), -math.pi / 2.0, epsilon));
250 assert(math.approxEq(f32, atan2_32(math.inf(f32), math.inf(f32)), math.pi / 4.0, epsilon));250 expect(math.approxEq(f32, atan2_32(math.inf(f32), math.inf(f32)), math.pi / 4.0, epsilon));
251 assert(math.approxEq(f32, atan2_32(-math.inf(f32), math.inf(f32)), -math.pi / 4.0, epsilon));251 expect(math.approxEq(f32, atan2_32(-math.inf(f32), math.inf(f32)), -math.pi / 4.0, epsilon));
252 assert(math.approxEq(f32, atan2_32(math.inf(f32), -math.inf(f32)), 3.0 * math.pi / 4.0, epsilon));252 expect(math.approxEq(f32, atan2_32(math.inf(f32), -math.inf(f32)), 3.0 * math.pi / 4.0, epsilon));
253 assert(math.approxEq(f32, atan2_32(-math.inf(f32), -math.inf(f32)), -3.0 * math.pi / 4.0, epsilon));253 expect(math.approxEq(f32, atan2_32(-math.inf(f32), -math.inf(f32)), -3.0 * math.pi / 4.0, epsilon));
254 assert(atan2_32(1.0, math.inf(f32)) == 0.0);254 expect(atan2_32(1.0, math.inf(f32)) == 0.0);
255 assert(math.approxEq(f32, atan2_32(1.0, -math.inf(f32)), math.pi, epsilon));255 expect(math.approxEq(f32, atan2_32(1.0, -math.inf(f32)), math.pi, epsilon));
256 assert(math.approxEq(f32, atan2_32(-1.0, -math.inf(f32)), -math.pi, epsilon));256 expect(math.approxEq(f32, atan2_32(-1.0, -math.inf(f32)), -math.pi, epsilon));
257 assert(math.approxEq(f32, atan2_32(math.inf(f32), 1.0), math.pi / 2.0, epsilon));257 expect(math.approxEq(f32, atan2_32(math.inf(f32), 1.0), math.pi / 2.0, epsilon));
258 assert(math.approxEq(f32, atan2_32(-math.inf(f32), 1.0), -math.pi / 2.0, epsilon));258 expect(math.approxEq(f32, atan2_32(-math.inf(f32), 1.0), -math.pi / 2.0, epsilon));
259}259}
260260
261test "math.atan2_64.special" {261test "math.atan2_64.special" {
262 const epsilon = 0.000001;262 const epsilon = 0.000001;
263263
264 assert(math.isNan(atan2_64(1.0, math.nan(f64))));264 expect(math.isNan(atan2_64(1.0, math.nan(f64))));
265 assert(math.isNan(atan2_64(math.nan(f64), 1.0)));265 expect(math.isNan(atan2_64(math.nan(f64), 1.0)));
266 assert(atan2_64(0.0, 5.0) == 0.0);266 expect(atan2_64(0.0, 5.0) == 0.0);
267 assert(atan2_64(-0.0, 5.0) == -0.0);267 expect(atan2_64(-0.0, 5.0) == -0.0);
268 assert(math.approxEq(f64, atan2_64(0.0, -5.0), math.pi, epsilon));268 expect(math.approxEq(f64, atan2_64(0.0, -5.0), math.pi, epsilon));
269 //assert(math.approxEq(f64, atan2_64(-0.0, -5.0), -math.pi, epsilon)); TODO support negative zero?269 //expect(math.approxEq(f64, atan2_64(-0.0, -5.0), -math.pi, epsilon)); TODO support negative zero?
270 assert(math.approxEq(f64, atan2_64(1.0, 0.0), math.pi / 2.0, epsilon));270 expect(math.approxEq(f64, atan2_64(1.0, 0.0), math.pi / 2.0, epsilon));
271 assert(math.approxEq(f64, atan2_64(1.0, -0.0), math.pi / 2.0, epsilon));271 expect(math.approxEq(f64, atan2_64(1.0, -0.0), math.pi / 2.0, epsilon));
272 assert(math.approxEq(f64, atan2_64(-1.0, 0.0), -math.pi / 2.0, epsilon));272 expect(math.approxEq(f64, atan2_64(-1.0, 0.0), -math.pi / 2.0, epsilon));
273 assert(math.approxEq(f64, atan2_64(-1.0, -0.0), -math.pi / 2.0, epsilon));273 expect(math.approxEq(f64, atan2_64(-1.0, -0.0), -math.pi / 2.0, epsilon));
274 assert(math.approxEq(f64, atan2_64(math.inf(f64), math.inf(f64)), math.pi / 4.0, epsilon));274 expect(math.approxEq(f64, atan2_64(math.inf(f64), math.inf(f64)), math.pi / 4.0, epsilon));
275 assert(math.approxEq(f64, atan2_64(-math.inf(f64), math.inf(f64)), -math.pi / 4.0, epsilon));275 expect(math.approxEq(f64, atan2_64(-math.inf(f64), math.inf(f64)), -math.pi / 4.0, epsilon));
276 assert(math.approxEq(f64, atan2_64(math.inf(f64), -math.inf(f64)), 3.0 * math.pi / 4.0, epsilon));276 expect(math.approxEq(f64, atan2_64(math.inf(f64), -math.inf(f64)), 3.0 * math.pi / 4.0, epsilon));
277 assert(math.approxEq(f64, atan2_64(-math.inf(f64), -math.inf(f64)), -3.0 * math.pi / 4.0, epsilon));277 expect(math.approxEq(f64, atan2_64(-math.inf(f64), -math.inf(f64)), -3.0 * math.pi / 4.0, epsilon));
278 assert(atan2_64(1.0, math.inf(f64)) == 0.0);278 expect(atan2_64(1.0, math.inf(f64)) == 0.0);
279 assert(math.approxEq(f64, atan2_64(1.0, -math.inf(f64)), math.pi, epsilon));279 expect(math.approxEq(f64, atan2_64(1.0, -math.inf(f64)), math.pi, epsilon));
280 assert(math.approxEq(f64, atan2_64(-1.0, -math.inf(f64)), -math.pi, epsilon));280 expect(math.approxEq(f64, atan2_64(-1.0, -math.inf(f64)), -math.pi, epsilon));
281 assert(math.approxEq(f64, atan2_64(math.inf(f64), 1.0), math.pi / 2.0, epsilon));281 expect(math.approxEq(f64, atan2_64(math.inf(f64), 1.0), math.pi / 2.0, epsilon));
282 assert(math.approxEq(f64, atan2_64(-math.inf(f64), 1.0), -math.pi / 2.0, epsilon));282 expect(math.approxEq(f64, atan2_64(-math.inf(f64), 1.0), -math.pi / 2.0, epsilon));
283}283}
std/math/atanh.zig+19-19
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
66
7const std = @import("../index.zig");7const std = @import("../index.zig");
8const math = std.math;8const math = std.math;
9const assert = std.debug.assert;9const expect = std.testing.expect;
10const maxInt = std.math.maxInt;10const maxInt = std.math.maxInt;
1111
12pub fn atanh(x: var) @typeOf(x) {12pub fn atanh(x: var) @typeOf(x) {
...@@ -78,38 +78,38 @@ fn atanh_64(x: f64) f64 {...@@ -78,38 +78,38 @@ fn atanh_64(x: f64) f64 {
78}78}
7979
80test "math.atanh" {80test "math.atanh" {
81 assert(atanh(f32(0.0)) == atanh_32(0.0));81 expect(atanh(f32(0.0)) == atanh_32(0.0));
82 assert(atanh(f64(0.0)) == atanh_64(0.0));82 expect(atanh(f64(0.0)) == atanh_64(0.0));
83}83}
8484
85test "math.atanh_32" {85test "math.atanh_32" {
86 const epsilon = 0.000001;86 const epsilon = 0.000001;
8787
88 assert(math.approxEq(f32, atanh_32(0.0), 0.0, epsilon));88 expect(math.approxEq(f32, atanh_32(0.0), 0.0, epsilon));
89 assert(math.approxEq(f32, atanh_32(0.2), 0.202733, epsilon));89 expect(math.approxEq(f32, atanh_32(0.2), 0.202733, epsilon));
90 assert(math.approxEq(f32, atanh_32(0.8923), 1.433099, epsilon));90 expect(math.approxEq(f32, atanh_32(0.8923), 1.433099, epsilon));
91}91}
9292
93test "math.atanh_64" {93test "math.atanh_64" {
94 const epsilon = 0.000001;94 const epsilon = 0.000001;
9595
96 assert(math.approxEq(f64, atanh_64(0.0), 0.0, epsilon));96 expect(math.approxEq(f64, atanh_64(0.0), 0.0, epsilon));
97 assert(math.approxEq(f64, atanh_64(0.2), 0.202733, epsilon));97 expect(math.approxEq(f64, atanh_64(0.2), 0.202733, epsilon));
98 assert(math.approxEq(f64, atanh_64(0.8923), 1.433099, epsilon));98 expect(math.approxEq(f64, atanh_64(0.8923), 1.433099, epsilon));
99}99}
100100
101test "math.atanh32.special" {101test "math.atanh32.special" {
102 assert(math.isPositiveInf(atanh_32(1)));102 expect(math.isPositiveInf(atanh_32(1)));
103 assert(math.isNegativeInf(atanh_32(-1)));103 expect(math.isNegativeInf(atanh_32(-1)));
104 assert(math.isSignalNan(atanh_32(1.5)));104 expect(math.isSignalNan(atanh_32(1.5)));
105 assert(math.isSignalNan(atanh_32(-1.5)));105 expect(math.isSignalNan(atanh_32(-1.5)));
106 assert(math.isNan(atanh_32(math.nan(f32))));106 expect(math.isNan(atanh_32(math.nan(f32))));
107}107}
108108
109test "math.atanh64.special" {109test "math.atanh64.special" {
110 assert(math.isPositiveInf(atanh_64(1)));110 expect(math.isPositiveInf(atanh_64(1)));
111 assert(math.isNegativeInf(atanh_64(-1)));111 expect(math.isNegativeInf(atanh_64(-1)));
112 assert(math.isSignalNan(atanh_64(1.5)));112 expect(math.isSignalNan(atanh_64(1.5)));
113 assert(math.isSignalNan(atanh_64(-1.5)));113 expect(math.isSignalNan(atanh_64(-1.5)));
114 assert(math.isNan(atanh_64(math.nan(f64))));114 expect(math.isNan(atanh_64(math.nan(f64))));
115}115}
std/math/big/int.zig+180-187
...@@ -1,6 +1,7 @@...@@ -1,6 +1,7 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const debug = std.debug;3const debug = std.debug;
4const testing = std.testing;
4const math = std.math;5const math = std.math;
5const mem = std.mem;6const mem = std.mem;
6const Allocator = mem.Allocator;7const Allocator = mem.Allocator;
...@@ -1086,44 +1087,40 @@ test "big.int comptime_int set" {...@@ -1086,44 +1087,40 @@ test "big.int comptime_int set" {
1086 const result = Limb(s & maxInt(Limb));1087 const result = Limb(s & maxInt(Limb));
1087 s >>= Limb.bit_count / 2;1088 s >>= Limb.bit_count / 2;
1088 s >>= Limb.bit_count / 2;1089 s >>= Limb.bit_count / 2;
1089 debug.assert(a.limbs[i] == result);1090 testing.expect(a.limbs[i] == result);
1090 }1091 }
1091}1092}
10921093
1093test "big.int comptime_int set negative" {1094test "big.int comptime_int set negative" {
1094 var a = try Int.initSet(al, -10);1095 var a = try Int.initSet(al, -10);
10951096
1096 debug.assert(a.limbs[0] == 10);1097 testing.expect(a.limbs[0] == 10);
1097 debug.assert(a.positive == false);1098 testing.expect(a.positive == false);
1098}1099}
10991100
1100test "big.int int set unaligned small" {1101test "big.int int set unaligned small" {
1101 var a = try Int.initSet(al, u7(45));1102 var a = try Int.initSet(al, u7(45));
11021103
1103 debug.assert(a.limbs[0] == 45);1104 testing.expect(a.limbs[0] == 45);
1104 debug.assert(a.positive == true);1105 testing.expect(a.positive == true);
1105}1106}
11061107
1107test "big.int comptime_int to" {1108test "big.int comptime_int to" {
1108 const a = try Int.initSet(al, 0xefffffff00000001eeeeeeefaaaaaaab);1109 const a = try Int.initSet(al, 0xefffffff00000001eeeeeeefaaaaaaab);
11091110
1110 debug.assert((try a.to(u128)) == 0xefffffff00000001eeeeeeefaaaaaaab);1111 testing.expect((try a.to(u128)) == 0xefffffff00000001eeeeeeefaaaaaaab);
1111}1112}
11121113
1113test "big.int sub-limb to" {1114test "big.int sub-limb to" {
1114 const a = try Int.initSet(al, 10);1115 const a = try Int.initSet(al, 10);
11151116
1116 debug.assert((try a.to(u8)) == 10);1117 testing.expect((try a.to(u8)) == 10);
1117}1118}
11181119
1119test "big.int to target too small error" {1120test "big.int to target too small error" {
1120 const a = try Int.initSet(al, 0xffffffff);1121 const a = try Int.initSet(al, 0xffffffff);
11211122
1122 if (a.to(u8)) |_| {1123 testing.expectError(error.TargetTooSmall, a.to(u8));
1123 unreachable;
1124 } else |err| {
1125 debug.assert(err == error.TargetTooSmall);
1126 }
1127}1124}
11281125
1129test "big.int norm1" {1126test "big.int norm1" {
...@@ -1135,22 +1132,22 @@ test "big.int norm1" {...@@ -1135,22 +1132,22 @@ test "big.int norm1" {
1135 a.limbs[2] = 3;1132 a.limbs[2] = 3;
1136 a.limbs[3] = 0;1133 a.limbs[3] = 0;
1137 a.norm1(4);1134 a.norm1(4);
1138 debug.assert(a.len == 3);1135 testing.expect(a.len == 3);
11391136
1140 a.limbs[0] = 1;1137 a.limbs[0] = 1;
1141 a.limbs[1] = 2;1138 a.limbs[1] = 2;
1142 a.limbs[2] = 3;1139 a.limbs[2] = 3;
1143 a.norm1(3);1140 a.norm1(3);
1144 debug.assert(a.len == 3);1141 testing.expect(a.len == 3);
11451142
1146 a.limbs[0] = 0;1143 a.limbs[0] = 0;
1147 a.limbs[1] = 0;1144 a.limbs[1] = 0;
1148 a.norm1(2);1145 a.norm1(2);
1149 debug.assert(a.len == 1);1146 testing.expect(a.len == 1);
11501147
1151 a.limbs[0] = 0;1148 a.limbs[0] = 0;
1152 a.norm1(1);1149 a.norm1(1);
1153 debug.assert(a.len == 1);1150 testing.expect(a.len == 1);
1154}1151}
11551152
1156test "big.int normN" {1153test "big.int normN" {
...@@ -1162,144 +1159,144 @@ test "big.int normN" {...@@ -1162,144 +1159,144 @@ test "big.int normN" {
1162 a.limbs[2] = 0;1159 a.limbs[2] = 0;
1163 a.limbs[3] = 0;1160 a.limbs[3] = 0;
1164 a.normN(4);1161 a.normN(4);
1165 debug.assert(a.len == 2);1162 testing.expect(a.len == 2);
11661163
1167 a.limbs[0] = 1;1164 a.limbs[0] = 1;
1168 a.limbs[1] = 2;1165 a.limbs[1] = 2;
1169 a.limbs[2] = 3;1166 a.limbs[2] = 3;
1170 a.normN(3);1167 a.normN(3);
1171 debug.assert(a.len == 3);1168 testing.expect(a.len == 3);
11721169
1173 a.limbs[0] = 0;1170 a.limbs[0] = 0;
1174 a.limbs[1] = 0;1171 a.limbs[1] = 0;
1175 a.limbs[2] = 0;1172 a.limbs[2] = 0;
1176 a.limbs[3] = 0;1173 a.limbs[3] = 0;
1177 a.normN(4);1174 a.normN(4);
1178 debug.assert(a.len == 1);1175 testing.expect(a.len == 1);
11791176
1180 a.limbs[0] = 0;1177 a.limbs[0] = 0;
1181 a.normN(1);1178 a.normN(1);
1182 debug.assert(a.len == 1);1179 testing.expect(a.len == 1);
1183}1180}
11841181
1185test "big.int parity" {1182test "big.int parity" {
1186 var a = try Int.init(al);1183 var a = try Int.init(al);
1187 try a.set(0);1184 try a.set(0);
1188 debug.assert(a.isEven());1185 testing.expect(a.isEven());
1189 debug.assert(!a.isOdd());1186 testing.expect(!a.isOdd());
11901187
1191 try a.set(7);1188 try a.set(7);
1192 debug.assert(!a.isEven());1189 testing.expect(!a.isEven());
1193 debug.assert(a.isOdd());1190 testing.expect(a.isOdd());
1194}1191}
11951192
1196test "big.int bitcount + sizeInBase" {1193test "big.int bitcount + sizeInBase" {
1197 var a = try Int.init(al);1194 var a = try Int.init(al);
11981195
1199 try a.set(0b100);1196 try a.set(0b100);
1200 debug.assert(a.bitCountAbs() == 3);1197 testing.expect(a.bitCountAbs() == 3);
1201 debug.assert(a.sizeInBase(2) >= 3);1198 testing.expect(a.sizeInBase(2) >= 3);
1202 debug.assert(a.sizeInBase(10) >= 1);1199 testing.expect(a.sizeInBase(10) >= 1);
12031200
1204 a.negate();1201 a.negate();
1205 debug.assert(a.bitCountAbs() == 3);1202 testing.expect(a.bitCountAbs() == 3);
1206 debug.assert(a.sizeInBase(2) >= 4);1203 testing.expect(a.sizeInBase(2) >= 4);
1207 debug.assert(a.sizeInBase(10) >= 2);1204 testing.expect(a.sizeInBase(10) >= 2);
12081205
1209 try a.set(0xffffffff);1206 try a.set(0xffffffff);
1210 debug.assert(a.bitCountAbs() == 32);1207 testing.expect(a.bitCountAbs() == 32);
1211 debug.assert(a.sizeInBase(2) >= 32);1208 testing.expect(a.sizeInBase(2) >= 32);
1212 debug.assert(a.sizeInBase(10) >= 10);1209 testing.expect(a.sizeInBase(10) >= 10);
12131210
1214 try a.shiftLeft(a, 5000);1211 try a.shiftLeft(a, 5000);
1215 debug.assert(a.bitCountAbs() == 5032);1212 testing.expect(a.bitCountAbs() == 5032);
1216 debug.assert(a.sizeInBase(2) >= 5032);1213 testing.expect(a.sizeInBase(2) >= 5032);
1217 a.positive = false;1214 a.positive = false;
12181215
1219 debug.assert(a.bitCountAbs() == 5032);1216 testing.expect(a.bitCountAbs() == 5032);
1220 debug.assert(a.sizeInBase(2) >= 5033);1217 testing.expect(a.sizeInBase(2) >= 5033);
1221}1218}
12221219
1223test "big.int bitcount/to" {1220test "big.int bitcount/to" {
1224 var a = try Int.init(al);1221 var a = try Int.init(al);
12251222
1226 try a.set(0);1223 try a.set(0);
1227 debug.assert(a.bitCountTwosComp() == 0);1224 testing.expect(a.bitCountTwosComp() == 0);
12281225
1229 // TODO: stack smashing1226 // TODO: stack smashing
1230 // debug.assert((try a.to(u0)) == 0);1227 // testing.expect((try a.to(u0)) == 0);
1231 // TODO: sigsegv1228 // TODO: sigsegv
1232 // debug.assert((try a.to(i0)) == 0);1229 // testing.expect((try a.to(i0)) == 0);
12331230
1234 try a.set(-1);1231 try a.set(-1);
1235 debug.assert(a.bitCountTwosComp() == 1);1232 testing.expect(a.bitCountTwosComp() == 1);
1236 debug.assert((try a.to(i1)) == -1);1233 testing.expect((try a.to(i1)) == -1);
12371234
1238 try a.set(-8);1235 try a.set(-8);
1239 debug.assert(a.bitCountTwosComp() == 4);1236 testing.expect(a.bitCountTwosComp() == 4);
1240 debug.assert((try a.to(i4)) == -8);1237 testing.expect((try a.to(i4)) == -8);
12411238
1242 try a.set(127);1239 try a.set(127);
1243 debug.assert(a.bitCountTwosComp() == 7);1240 testing.expect(a.bitCountTwosComp() == 7);
1244 debug.assert((try a.to(u7)) == 127);1241 testing.expect((try a.to(u7)) == 127);
12451242
1246 try a.set(-128);1243 try a.set(-128);
1247 debug.assert(a.bitCountTwosComp() == 8);1244 testing.expect(a.bitCountTwosComp() == 8);
1248 debug.assert((try a.to(i8)) == -128);1245 testing.expect((try a.to(i8)) == -128);
12491246
1250 try a.set(-129);1247 try a.set(-129);
1251 debug.assert(a.bitCountTwosComp() == 9);1248 testing.expect(a.bitCountTwosComp() == 9);
1252 debug.assert((try a.to(i9)) == -129);1249 testing.expect((try a.to(i9)) == -129);
1253}1250}
12541251
1255test "big.int fits" {1252test "big.int fits" {
1256 var a = try Int.init(al);1253 var a = try Int.init(al);
12571254
1258 try a.set(0);1255 try a.set(0);
1259 debug.assert(a.fits(u0));1256 testing.expect(a.fits(u0));
1260 debug.assert(a.fits(i0));1257 testing.expect(a.fits(i0));
12611258
1262 try a.set(255);1259 try a.set(255);
1263 debug.assert(!a.fits(u0));1260 testing.expect(!a.fits(u0));
1264 debug.assert(!a.fits(u1));1261 testing.expect(!a.fits(u1));
1265 debug.assert(!a.fits(i8));1262 testing.expect(!a.fits(i8));
1266 debug.assert(a.fits(u8));1263 testing.expect(a.fits(u8));
1267 debug.assert(a.fits(u9));1264 testing.expect(a.fits(u9));
1268 debug.assert(a.fits(i9));1265 testing.expect(a.fits(i9));
12691266
1270 try a.set(-128);1267 try a.set(-128);
1271 debug.assert(!a.fits(i7));1268 testing.expect(!a.fits(i7));
1272 debug.assert(a.fits(i8));1269 testing.expect(a.fits(i8));
1273 debug.assert(a.fits(i9));1270 testing.expect(a.fits(i9));
1274 debug.assert(!a.fits(u9));1271 testing.expect(!a.fits(u9));
12751272
1276 try a.set(0x1ffffffffeeeeeeee);1273 try a.set(0x1ffffffffeeeeeeee);
1277 debug.assert(!a.fits(u32));1274 testing.expect(!a.fits(u32));
1278 debug.assert(!a.fits(u64));1275 testing.expect(!a.fits(u64));
1279 debug.assert(a.fits(u65));1276 testing.expect(a.fits(u65));
1280}1277}
12811278
1282test "big.int string set" {1279test "big.int string set" {
1283 var a = try Int.init(al);1280 var a = try Int.init(al);
1284 try a.setString(10, "120317241209124781241290847124");1281 try a.setString(10, "120317241209124781241290847124");
12851282
1286 debug.assert((try a.to(u128)) == 120317241209124781241290847124);1283 testing.expect((try a.to(u128)) == 120317241209124781241290847124);
1287}1284}
12881285
1289test "big.int string negative" {1286test "big.int string negative" {
1290 var a = try Int.init(al);1287 var a = try Int.init(al);
1291 try a.setString(10, "-1023");1288 try a.setString(10, "-1023");
1292 debug.assert((try a.to(i32)) == -1023);1289 testing.expect((try a.to(i32)) == -1023);
1293}1290}
12941291
1295test "big.int string set bad char error" {1292test "big.int string set bad char error" {
1296 var a = try Int.init(al);1293 var a = try Int.init(al);
1297 a.setString(10, "x") catch |err| debug.assert(err == error.InvalidCharForDigit);1294 testing.expectError(error.InvalidCharForDigit, a.setString(10, "x"));
1298}1295}
12991296
1300test "big.int string set bad base error" {1297test "big.int string set bad base error" {
1301 var a = try Int.init(al);1298 var a = try Int.init(al);
1302 a.setString(45, "10") catch |err| debug.assert(err == error.InvalidBase);1299 testing.expectError(error.InvalidBase, a.setString(45, "10"));
1303}1300}
13041301
1305test "big.int string to" {1302test "big.int string to" {
...@@ -1308,17 +1305,13 @@ test "big.int string to" {...@@ -1308,17 +1305,13 @@ test "big.int string to" {
1308 const as = try a.toString(al, 10);1305 const as = try a.toString(al, 10);
1309 const es = "120317241209124781241290847124";1306 const es = "120317241209124781241290847124";
13101307
1311 debug.assert(mem.eql(u8, as, es));1308 testing.expect(mem.eql(u8, as, es));
1312}1309}
13131310
1314test "big.int string to base base error" {1311test "big.int string to base base error" {
1315 const a = try Int.initSet(al, 0xffffffff);1312 const a = try Int.initSet(al, 0xffffffff);
13161313
1317 if (a.toString(al, 45)) |_| {1314 testing.expectError(error.InvalidBase, a.toString(al, 45));
1318 unreachable;
1319 } else |err| {
1320 debug.assert(err == error.InvalidBase);
1321 }
1322}1315}
13231316
1324test "big.int string to base 2" {1317test "big.int string to base 2" {
...@@ -1327,7 +1320,7 @@ test "big.int string to base 2" {...@@ -1327,7 +1320,7 @@ test "big.int string to base 2" {
1327 const as = try a.toString(al, 2);1320 const as = try a.toString(al, 2);
1328 const es = "-1011";1321 const es = "-1011";
13291322
1330 debug.assert(mem.eql(u8, as, es));1323 testing.expect(mem.eql(u8, as, es));
1331}1324}
13321325
1333test "big.int string to base 16" {1326test "big.int string to base 16" {
...@@ -1336,7 +1329,7 @@ test "big.int string to base 16" {...@@ -1336,7 +1329,7 @@ test "big.int string to base 16" {
1336 const as = try a.toString(al, 16);1329 const as = try a.toString(al, 16);
1337 const es = "efffffff00000001eeeeeeefaaaaaaab";1330 const es = "efffffff00000001eeeeeeefaaaaaaab";
13381331
1339 debug.assert(mem.eql(u8, as, es));1332 testing.expect(mem.eql(u8, as, es));
1340}1333}
13411334
1342test "big.int neg string to" {1335test "big.int neg string to" {
...@@ -1345,7 +1338,7 @@ test "big.int neg string to" {...@@ -1345,7 +1338,7 @@ test "big.int neg string to" {
1345 const as = try a.toString(al, 10);1338 const as = try a.toString(al, 10);
1346 const es = "-123907434";1339 const es = "-123907434";
13471340
1348 debug.assert(mem.eql(u8, as, es));1341 testing.expect(mem.eql(u8, as, es));
1349}1342}
13501343
1351test "big.int zero string to" {1344test "big.int zero string to" {
...@@ -1354,98 +1347,98 @@ test "big.int zero string to" {...@@ -1354,98 +1347,98 @@ test "big.int zero string to" {
1354 const as = try a.toString(al, 10);1347 const as = try a.toString(al, 10);
1355 const es = "0";1348 const es = "0";
13561349
1357 debug.assert(mem.eql(u8, as, es));1350 testing.expect(mem.eql(u8, as, es));
1358}1351}
13591352
1360test "big.int clone" {1353test "big.int clone" {
1361 var a = try Int.initSet(al, 1234);1354 var a = try Int.initSet(al, 1234);
1362 const b = try a.clone();1355 const b = try a.clone();
13631356
1364 debug.assert((try a.to(u32)) == 1234);1357 testing.expect((try a.to(u32)) == 1234);
1365 debug.assert((try b.to(u32)) == 1234);1358 testing.expect((try b.to(u32)) == 1234);
13661359
1367 try a.set(77);1360 try a.set(77);
1368 debug.assert((try a.to(u32)) == 77);1361 testing.expect((try a.to(u32)) == 77);
1369 debug.assert((try b.to(u32)) == 1234);1362 testing.expect((try b.to(u32)) == 1234);
1370}1363}
13711364
1372test "big.int swap" {1365test "big.int swap" {
1373 var a = try Int.initSet(al, 1234);1366 var a = try Int.initSet(al, 1234);
1374 var b = try Int.initSet(al, 5678);1367 var b = try Int.initSet(al, 5678);
13751368
1376 debug.assert((try a.to(u32)) == 1234);1369 testing.expect((try a.to(u32)) == 1234);
1377 debug.assert((try b.to(u32)) == 5678);1370 testing.expect((try b.to(u32)) == 5678);
13781371
1379 a.swap(&b);1372 a.swap(&b);
13801373
1381 debug.assert((try a.to(u32)) == 5678);1374 testing.expect((try a.to(u32)) == 5678);
1382 debug.assert((try b.to(u32)) == 1234);1375 testing.expect((try b.to(u32)) == 1234);
1383}1376}
13841377
1385test "big.int to negative" {1378test "big.int to negative" {
1386 var a = try Int.initSet(al, -10);1379 var a = try Int.initSet(al, -10);
13871380
1388 debug.assert((try a.to(i32)) == -10);1381 testing.expect((try a.to(i32)) == -10);
1389}1382}
13901383
1391test "big.int compare" {1384test "big.int compare" {
1392 var a = try Int.initSet(al, -11);1385 var a = try Int.initSet(al, -11);
1393 var b = try Int.initSet(al, 10);1386 var b = try Int.initSet(al, 10);
13941387
1395 debug.assert(a.cmpAbs(b) == 1);1388 testing.expect(a.cmpAbs(b) == 1);
1396 debug.assert(a.cmp(b) == -1);1389 testing.expect(a.cmp(b) == -1);
1397}1390}
13981391
1399test "big.int compare similar" {1392test "big.int compare similar" {
1400 var a = try Int.initSet(al, 0xffffffffeeeeeeeeffffffffeeeeeeee);1393 var a = try Int.initSet(al, 0xffffffffeeeeeeeeffffffffeeeeeeee);
1401 var b = try Int.initSet(al, 0xffffffffeeeeeeeeffffffffeeeeeeef);1394 var b = try Int.initSet(al, 0xffffffffeeeeeeeeffffffffeeeeeeef);
14021395
1403 debug.assert(a.cmpAbs(b) == -1);1396 testing.expect(a.cmpAbs(b) == -1);
1404 debug.assert(b.cmpAbs(a) == 1);1397 testing.expect(b.cmpAbs(a) == 1);
1405}1398}
14061399
1407test "big.int compare different limb size" {1400test "big.int compare different limb size" {
1408 var a = try Int.initSet(al, maxInt(Limb) + 1);1401 var a = try Int.initSet(al, maxInt(Limb) + 1);
1409 var b = try Int.initSet(al, 1);1402 var b = try Int.initSet(al, 1);
14101403
1411 debug.assert(a.cmpAbs(b) == 1);1404 testing.expect(a.cmpAbs(b) == 1);
1412 debug.assert(b.cmpAbs(a) == -1);1405 testing.expect(b.cmpAbs(a) == -1);
1413}1406}
14141407
1415test "big.int compare multi-limb" {1408test "big.int compare multi-limb" {
1416 var a = try Int.initSet(al, -0x7777777799999999ffffeeeeffffeeeeffffeeeef);1409 var a = try Int.initSet(al, -0x7777777799999999ffffeeeeffffeeeeffffeeeef);
1417 var b = try Int.initSet(al, 0x7777777799999999ffffeeeeffffeeeeffffeeeee);1410 var b = try Int.initSet(al, 0x7777777799999999ffffeeeeffffeeeeffffeeeee);
14181411
1419 debug.assert(a.cmpAbs(b) == 1);1412 testing.expect(a.cmpAbs(b) == 1);
1420 debug.assert(a.cmp(b) == -1);1413 testing.expect(a.cmp(b) == -1);
1421}1414}
14221415
1423test "big.int equality" {1416test "big.int equality" {
1424 var a = try Int.initSet(al, 0xffffffff1);1417 var a = try Int.initSet(al, 0xffffffff1);
1425 var b = try Int.initSet(al, -0xffffffff1);1418 var b = try Int.initSet(al, -0xffffffff1);
14261419
1427 debug.assert(a.eqAbs(b));1420 testing.expect(a.eqAbs(b));
1428 debug.assert(!a.eq(b));1421 testing.expect(!a.eq(b));
1429}1422}
14301423
1431test "big.int abs" {1424test "big.int abs" {
1432 var a = try Int.initSet(al, -5);1425 var a = try Int.initSet(al, -5);
14331426
1434 a.abs();1427 a.abs();
1435 debug.assert((try a.to(u32)) == 5);1428 testing.expect((try a.to(u32)) == 5);
14361429
1437 a.abs();1430 a.abs();
1438 debug.assert((try a.to(u32)) == 5);1431 testing.expect((try a.to(u32)) == 5);
1439}1432}
14401433
1441test "big.int negate" {1434test "big.int negate" {
1442 var a = try Int.initSet(al, 5);1435 var a = try Int.initSet(al, 5);
14431436
1444 a.negate();1437 a.negate();
1445 debug.assert((try a.to(i32)) == -5);1438 testing.expect((try a.to(i32)) == -5);
14461439
1447 a.negate();1440 a.negate();
1448 debug.assert((try a.to(i32)) == 5);1441 testing.expect((try a.to(i32)) == 5);
1449}1442}
14501443
1451test "big.int add single-single" {1444test "big.int add single-single" {
...@@ -1455,7 +1448,7 @@ test "big.int add single-single" {...@@ -1455,7 +1448,7 @@ test "big.int add single-single" {
1455 var c = try Int.init(al);1448 var c = try Int.init(al);
1456 try c.add(a, b);1449 try c.add(a, b);
14571450
1458 debug.assert((try c.to(u32)) == 55);1451 testing.expect((try c.to(u32)) == 55);
1459}1452}
14601453
1461test "big.int add multi-single" {1454test "big.int add multi-single" {
...@@ -1465,10 +1458,10 @@ test "big.int add multi-single" {...@@ -1465,10 +1458,10 @@ test "big.int add multi-single" {
1465 var c = try Int.init(al);1458 var c = try Int.init(al);
14661459
1467 try c.add(a, b);1460 try c.add(a, b);
1468 debug.assert((try c.to(DoubleLimb)) == maxInt(Limb) + 2);1461 testing.expect((try c.to(DoubleLimb)) == maxInt(Limb) + 2);
14691462
1470 try c.add(b, a);1463 try c.add(b, a);
1471 debug.assert((try c.to(DoubleLimb)) == maxInt(Limb) + 2);1464 testing.expect((try c.to(DoubleLimb)) == maxInt(Limb) + 2);
1472}1465}
14731466
1474test "big.int add multi-multi" {1467test "big.int add multi-multi" {
...@@ -1480,7 +1473,7 @@ test "big.int add multi-multi" {...@@ -1480,7 +1473,7 @@ test "big.int add multi-multi" {
1480 var c = try Int.init(al);1473 var c = try Int.init(al);
1481 try c.add(a, b);1474 try c.add(a, b);
14821475
1483 debug.assert((try c.to(u128)) == op1 + op2);1476 testing.expect((try c.to(u128)) == op1 + op2);
1484}1477}
14851478
1486test "big.int add zero-zero" {1479test "big.int add zero-zero" {
...@@ -1490,7 +1483,7 @@ test "big.int add zero-zero" {...@@ -1490,7 +1483,7 @@ test "big.int add zero-zero" {
1490 var c = try Int.init(al);1483 var c = try Int.init(al);
1491 try c.add(a, b);1484 try c.add(a, b);
14921485
1493 debug.assert((try c.to(u32)) == 0);1486 testing.expect((try c.to(u32)) == 0);
1494}1487}
14951488
1496test "big.int add alias multi-limb nonzero-zero" {1489test "big.int add alias multi-limb nonzero-zero" {
...@@ -1500,7 +1493,7 @@ test "big.int add alias multi-limb nonzero-zero" {...@@ -1500,7 +1493,7 @@ test "big.int add alias multi-limb nonzero-zero" {
15001493
1501 try a.add(a, b);1494 try a.add(a, b);
15021495
1503 debug.assert((try a.to(u128)) == op1);1496 testing.expect((try a.to(u128)) == op1);
1504}1497}
15051498
1506test "big.int add sign" {1499test "big.int add sign" {
...@@ -1512,16 +1505,16 @@ test "big.int add sign" {...@@ -1512,16 +1505,16 @@ test "big.int add sign" {
1512 const neg_two = try Int.initSet(al, -2);1505 const neg_two = try Int.initSet(al, -2);
15131506
1514 try a.add(one, two);1507 try a.add(one, two);
1515 debug.assert((try a.to(i32)) == 3);1508 testing.expect((try a.to(i32)) == 3);
15161509
1517 try a.add(neg_one, two);1510 try a.add(neg_one, two);
1518 debug.assert((try a.to(i32)) == 1);1511 testing.expect((try a.to(i32)) == 1);
15191512
1520 try a.add(one, neg_two);1513 try a.add(one, neg_two);
1521 debug.assert((try a.to(i32)) == -1);1514 testing.expect((try a.to(i32)) == -1);
15221515
1523 try a.add(neg_one, neg_two);1516 try a.add(neg_one, neg_two);
1524 debug.assert((try a.to(i32)) == -3);1517 testing.expect((try a.to(i32)) == -3);
1525}1518}
15261519
1527test "big.int sub single-single" {1520test "big.int sub single-single" {
...@@ -1531,7 +1524,7 @@ test "big.int sub single-single" {...@@ -1531,7 +1524,7 @@ test "big.int sub single-single" {
1531 var c = try Int.init(al);1524 var c = try Int.init(al);
1532 try c.sub(a, b);1525 try c.sub(a, b);
15331526
1534 debug.assert((try c.to(u32)) == 45);1527 testing.expect((try c.to(u32)) == 45);
1535}1528}
15361529
1537test "big.int sub multi-single" {1530test "big.int sub multi-single" {
...@@ -1541,7 +1534,7 @@ test "big.int sub multi-single" {...@@ -1541,7 +1534,7 @@ test "big.int sub multi-single" {
1541 var c = try Int.init(al);1534 var c = try Int.init(al);
1542 try c.sub(a, b);1535 try c.sub(a, b);
15431536
1544 debug.assert((try c.to(Limb)) == maxInt(Limb));1537 testing.expect((try c.to(Limb)) == maxInt(Limb));
1545}1538}
15461539
1547test "big.int sub multi-multi" {1540test "big.int sub multi-multi" {
...@@ -1554,7 +1547,7 @@ test "big.int sub multi-multi" {...@@ -1554,7 +1547,7 @@ test "big.int sub multi-multi" {
1554 var c = try Int.init(al);1547 var c = try Int.init(al);
1555 try c.sub(a, b);1548 try c.sub(a, b);
15561549
1557 debug.assert((try c.to(u128)) == op1 - op2);1550 testing.expect((try c.to(u128)) == op1 - op2);
1558}1551}
15591552
1560test "big.int sub equal" {1553test "big.int sub equal" {
...@@ -1564,7 +1557,7 @@ test "big.int sub equal" {...@@ -1564,7 +1557,7 @@ test "big.int sub equal" {
1564 var c = try Int.init(al);1557 var c = try Int.init(al);
1565 try c.sub(a, b);1558 try c.sub(a, b);
15661559
1567 debug.assert((try c.to(u32)) == 0);1560 testing.expect((try c.to(u32)) == 0);
1568}1561}
15691562
1570test "big.int sub sign" {1563test "big.int sub sign" {
...@@ -1576,19 +1569,19 @@ test "big.int sub sign" {...@@ -1576,19 +1569,19 @@ test "big.int sub sign" {
1576 const neg_two = try Int.initSet(al, -2);1569 const neg_two = try Int.initSet(al, -2);
15771570
1578 try a.sub(one, two);1571 try a.sub(one, two);
1579 debug.assert((try a.to(i32)) == -1);1572 testing.expect((try a.to(i32)) == -1);
15801573
1581 try a.sub(neg_one, two);1574 try a.sub(neg_one, two);
1582 debug.assert((try a.to(i32)) == -3);1575 testing.expect((try a.to(i32)) == -3);
15831576
1584 try a.sub(one, neg_two);1577 try a.sub(one, neg_two);
1585 debug.assert((try a.to(i32)) == 3);1578 testing.expect((try a.to(i32)) == 3);
15861579
1587 try a.sub(neg_one, neg_two);1580 try a.sub(neg_one, neg_two);
1588 debug.assert((try a.to(i32)) == 1);1581 testing.expect((try a.to(i32)) == 1);
15891582
1590 try a.sub(neg_two, neg_one);1583 try a.sub(neg_two, neg_one);
1591 debug.assert((try a.to(i32)) == -1);1584 testing.expect((try a.to(i32)) == -1);
1592}1585}
15931586
1594test "big.int mul single-single" {1587test "big.int mul single-single" {
...@@ -1598,7 +1591,7 @@ test "big.int mul single-single" {...@@ -1598,7 +1591,7 @@ test "big.int mul single-single" {
1598 var c = try Int.init(al);1591 var c = try Int.init(al);
1599 try c.mul(a, b);1592 try c.mul(a, b);
16001593
1601 debug.assert((try c.to(u64)) == 250);1594 testing.expect((try c.to(u64)) == 250);
1602}1595}
16031596
1604test "big.int mul multi-single" {1597test "big.int mul multi-single" {
...@@ -1608,7 +1601,7 @@ test "big.int mul multi-single" {...@@ -1608,7 +1601,7 @@ test "big.int mul multi-single" {
1608 var c = try Int.init(al);1601 var c = try Int.init(al);
1609 try c.mul(a, b);1602 try c.mul(a, b);
16101603
1611 debug.assert((try c.to(DoubleLimb)) == 2 * maxInt(Limb));1604 testing.expect((try c.to(DoubleLimb)) == 2 * maxInt(Limb));
1612}1605}
16131606
1614test "big.int mul multi-multi" {1607test "big.int mul multi-multi" {
...@@ -1620,7 +1613,7 @@ test "big.int mul multi-multi" {...@@ -1620,7 +1613,7 @@ test "big.int mul multi-multi" {
1620 var c = try Int.init(al);1613 var c = try Int.init(al);
1621 try c.mul(a, b);1614 try c.mul(a, b);
16221615
1623 debug.assert((try c.to(u256)) == op1 * op2);1616 testing.expect((try c.to(u256)) == op1 * op2);
1624}1617}
16251618
1626test "big.int mul alias r with a" {1619test "big.int mul alias r with a" {
...@@ -1629,7 +1622,7 @@ test "big.int mul alias r with a" {...@@ -1629,7 +1622,7 @@ test "big.int mul alias r with a" {
16291622
1630 try a.mul(a, b);1623 try a.mul(a, b);
16311624
1632 debug.assert((try a.to(DoubleLimb)) == 2 * maxInt(Limb));1625 testing.expect((try a.to(DoubleLimb)) == 2 * maxInt(Limb));
1633}1626}
16341627
1635test "big.int mul alias r with b" {1628test "big.int mul alias r with b" {
...@@ -1638,7 +1631,7 @@ test "big.int mul alias r with b" {...@@ -1638,7 +1631,7 @@ test "big.int mul alias r with b" {
16381631
1639 try a.mul(b, a);1632 try a.mul(b, a);
16401633
1641 debug.assert((try a.to(DoubleLimb)) == 2 * maxInt(Limb));1634 testing.expect((try a.to(DoubleLimb)) == 2 * maxInt(Limb));
1642}1635}
16431636
1644test "big.int mul alias r with a and b" {1637test "big.int mul alias r with a and b" {
...@@ -1646,7 +1639,7 @@ test "big.int mul alias r with a and b" {...@@ -1646,7 +1639,7 @@ test "big.int mul alias r with a and b" {
16461639
1647 try a.mul(a, a);1640 try a.mul(a, a);
16481641
1649 debug.assert((try a.to(DoubleLimb)) == maxInt(Limb) * maxInt(Limb));1642 testing.expect((try a.to(DoubleLimb)) == maxInt(Limb) * maxInt(Limb));
1650}1643}
16511644
1652test "big.int mul a*0" {1645test "big.int mul a*0" {
...@@ -1656,7 +1649,7 @@ test "big.int mul a*0" {...@@ -1656,7 +1649,7 @@ test "big.int mul a*0" {
1656 var c = try Int.init(al);1649 var c = try Int.init(al);
1657 try c.mul(a, b);1650 try c.mul(a, b);
16581651
1659 debug.assert((try c.to(u32)) == 0);1652 testing.expect((try c.to(u32)) == 0);
1660}1653}
16611654
1662test "big.int mul 0*0" {1655test "big.int mul 0*0" {
...@@ -1666,7 +1659,7 @@ test "big.int mul 0*0" {...@@ -1666,7 +1659,7 @@ test "big.int mul 0*0" {
1666 var c = try Int.init(al);1659 var c = try Int.init(al);
1667 try c.mul(a, b);1660 try c.mul(a, b);
16681661
1669 debug.assert((try c.to(u32)) == 0);1662 testing.expect((try c.to(u32)) == 0);
1670}1663}
16711664
1672test "big.int div single-single no rem" {1665test "big.int div single-single no rem" {
...@@ -1677,8 +1670,8 @@ test "big.int div single-single no rem" {...@@ -1677,8 +1670,8 @@ test "big.int div single-single no rem" {
1677 var r = try Int.init(al);1670 var r = try Int.init(al);
1678 try Int.divTrunc(&q, &r, a, b);1671 try Int.divTrunc(&q, &r, a, b);
16791672
1680 debug.assert((try q.to(u32)) == 10);1673 testing.expect((try q.to(u32)) == 10);
1681 debug.assert((try r.to(u32)) == 0);1674 testing.expect((try r.to(u32)) == 0);
1682}1675}
16831676
1684test "big.int div single-single with rem" {1677test "big.int div single-single with rem" {
...@@ -1689,8 +1682,8 @@ test "big.int div single-single with rem" {...@@ -1689,8 +1682,8 @@ test "big.int div single-single with rem" {
1689 var r = try Int.init(al);1682 var r = try Int.init(al);
1690 try Int.divTrunc(&q, &r, a, b);1683 try Int.divTrunc(&q, &r, a, b);
16911684
1692 debug.assert((try q.to(u32)) == 9);1685 testing.expect((try q.to(u32)) == 9);
1693 debug.assert((try r.to(u32)) == 4);1686 testing.expect((try r.to(u32)) == 4);
1694}1687}
16951688
1696test "big.int div multi-single no rem" {1689test "big.int div multi-single no rem" {
...@@ -1704,8 +1697,8 @@ test "big.int div multi-single no rem" {...@@ -1704,8 +1697,8 @@ test "big.int div multi-single no rem" {
1704 var r = try Int.init(al);1697 var r = try Int.init(al);
1705 try Int.divTrunc(&q, &r, a, b);1698 try Int.divTrunc(&q, &r, a, b);
17061699
1707 debug.assert((try q.to(u64)) == op1 / op2);1700 testing.expect((try q.to(u64)) == op1 / op2);
1708 debug.assert((try r.to(u64)) == 0);1701 testing.expect((try r.to(u64)) == 0);
1709}1702}
17101703
1711test "big.int div multi-single with rem" {1704test "big.int div multi-single with rem" {
...@@ -1719,8 +1712,8 @@ test "big.int div multi-single with rem" {...@@ -1719,8 +1712,8 @@ test "big.int div multi-single with rem" {
1719 var r = try Int.init(al);1712 var r = try Int.init(al);
1720 try Int.divTrunc(&q, &r, a, b);1713 try Int.divTrunc(&q, &r, a, b);
17211714
1722 debug.assert((try q.to(u64)) == op1 / op2);1715 testing.expect((try q.to(u64)) == op1 / op2);
1723 debug.assert((try r.to(u64)) == 3);1716 testing.expect((try r.to(u64)) == 3);
1724}1717}
17251718
1726test "big.int div multi>2-single" {1719test "big.int div multi>2-single" {
...@@ -1734,8 +1727,8 @@ test "big.int div multi>2-single" {...@@ -1734,8 +1727,8 @@ test "big.int div multi>2-single" {
1734 var r = try Int.init(al);1727 var r = try Int.init(al);
1735 try Int.divTrunc(&q, &r, a, b);1728 try Int.divTrunc(&q, &r, a, b);
17361729
1737 debug.assert((try q.to(u128)) == op1 / op2);1730 testing.expect((try q.to(u128)) == op1 / op2);
1738 debug.assert((try r.to(u32)) == 0x3e4e);1731 testing.expect((try r.to(u32)) == 0x3e4e);
1739}1732}
17401733
1741test "big.int div single-single q < r" {1734test "big.int div single-single q < r" {
...@@ -1746,8 +1739,8 @@ test "big.int div single-single q < r" {...@@ -1746,8 +1739,8 @@ test "big.int div single-single q < r" {
1746 var r = try Int.init(al);1739 var r = try Int.init(al);
1747 try Int.divTrunc(&q, &r, a, b);1740 try Int.divTrunc(&q, &r, a, b);
17481741
1749 debug.assert((try q.to(u64)) == 0);1742 testing.expect((try q.to(u64)) == 0);
1750 debug.assert((try r.to(u64)) == 0x0078f432);1743 testing.expect((try r.to(u64)) == 0x0078f432);
1751}1744}
17521745
1753test "big.int div single-single q == r" {1746test "big.int div single-single q == r" {
...@@ -1758,8 +1751,8 @@ test "big.int div single-single q == r" {...@@ -1758,8 +1751,8 @@ test "big.int div single-single q == r" {
1758 var r = try Int.init(al);1751 var r = try Int.init(al);
1759 try Int.divTrunc(&q, &r, a, b);1752 try Int.divTrunc(&q, &r, a, b);
17601753
1761 debug.assert((try q.to(u64)) == 1);1754 testing.expect((try q.to(u64)) == 1);
1762 debug.assert((try r.to(u64)) == 0);1755 testing.expect((try r.to(u64)) == 0);
1763}1756}
17641757
1765test "big.int div q=0 alias" {1758test "big.int div q=0 alias" {
...@@ -1768,8 +1761,8 @@ test "big.int div q=0 alias" {...@@ -1768,8 +1761,8 @@ test "big.int div q=0 alias" {
17681761
1769 try Int.divTrunc(&a, &b, a, b);1762 try Int.divTrunc(&a, &b, a, b);
17701763
1771 debug.assert((try a.to(u64)) == 0);1764 testing.expect((try a.to(u64)) == 0);
1772 debug.assert((try b.to(u64)) == 3);1765 testing.expect((try b.to(u64)) == 3);
1773}1766}
17741767
1775test "big.int div multi-multi q < r" {1768test "big.int div multi-multi q < r" {
...@@ -1782,8 +1775,8 @@ test "big.int div multi-multi q < r" {...@@ -1782,8 +1775,8 @@ test "big.int div multi-multi q < r" {
1782 var r = try Int.init(al);1775 var r = try Int.init(al);
1783 try Int.divTrunc(&q, &r, a, b);1776 try Int.divTrunc(&q, &r, a, b);
17841777
1785 debug.assert((try q.to(u128)) == 0);1778 testing.expect((try q.to(u128)) == 0);
1786 debug.assert((try r.to(u128)) == op1);1779 testing.expect((try r.to(u128)) == op1);
1787}1780}
17881781
1789test "big.int div trunc single-single +/+" {1782test "big.int div trunc single-single +/+" {
...@@ -1802,8 +1795,8 @@ test "big.int div trunc single-single +/+" {...@@ -1802,8 +1795,8 @@ test "big.int div trunc single-single +/+" {
1802 const eq = @divTrunc(u, v);1795 const eq = @divTrunc(u, v);
1803 const er = @mod(u, v);1796 const er = @mod(u, v);
18041797
1805 debug.assert((try q.to(i32)) == eq);1798 testing.expect((try q.to(i32)) == eq);
1806 debug.assert((try r.to(i32)) == er);1799 testing.expect((try r.to(i32)) == er);
1807}1800}
18081801
1809test "big.int div trunc single-single -/+" {1802test "big.int div trunc single-single -/+" {
...@@ -1822,8 +1815,8 @@ test "big.int div trunc single-single -/+" {...@@ -1822,8 +1815,8 @@ test "big.int div trunc single-single -/+" {
1822 const eq = -1;1815 const eq = -1;
1823 const er = -2;1816 const er = -2;
18241817
1825 debug.assert((try q.to(i32)) == eq);1818 testing.expect((try q.to(i32)) == eq);
1826 debug.assert((try r.to(i32)) == er);1819 testing.expect((try r.to(i32)) == er);
1827}1820}
18281821
1829test "big.int div trunc single-single +/-" {1822test "big.int div trunc single-single +/-" {
...@@ -1842,8 +1835,8 @@ test "big.int div trunc single-single +/-" {...@@ -1842,8 +1835,8 @@ test "big.int div trunc single-single +/-" {
1842 const eq = -1;1835 const eq = -1;
1843 const er = 2;1836 const er = 2;
18441837
1845 debug.assert((try q.to(i32)) == eq);1838 testing.expect((try q.to(i32)) == eq);
1846 debug.assert((try r.to(i32)) == er);1839 testing.expect((try r.to(i32)) == er);
1847}1840}
18481841
1849test "big.int div trunc single-single -/-" {1842test "big.int div trunc single-single -/-" {
...@@ -1862,8 +1855,8 @@ test "big.int div trunc single-single -/-" {...@@ -1862,8 +1855,8 @@ test "big.int div trunc single-single -/-" {
1862 const eq = 1;1855 const eq = 1;
1863 const er = -2;1856 const er = -2;
18641857
1865 debug.assert((try q.to(i32)) == eq);1858 testing.expect((try q.to(i32)) == eq);
1866 debug.assert((try r.to(i32)) == er);1859 testing.expect((try r.to(i32)) == er);
1867}1860}
18681861
1869test "big.int div floor single-single +/+" {1862test "big.int div floor single-single +/+" {
...@@ -1882,8 +1875,8 @@ test "big.int div floor single-single +/+" {...@@ -1882,8 +1875,8 @@ test "big.int div floor single-single +/+" {
1882 const eq = 1;1875 const eq = 1;
1883 const er = 2;1876 const er = 2;
18841877
1885 debug.assert((try q.to(i32)) == eq);1878 testing.expect((try q.to(i32)) == eq);
1886 debug.assert((try r.to(i32)) == er);1879 testing.expect((try r.to(i32)) == er);
1887}1880}
18881881
1889test "big.int div floor single-single -/+" {1882test "big.int div floor single-single -/+" {
...@@ -1902,8 +1895,8 @@ test "big.int div floor single-single -/+" {...@@ -1902,8 +1895,8 @@ test "big.int div floor single-single -/+" {
1902 const eq = -2;1895 const eq = -2;
1903 const er = 1;1896 const er = 1;
19041897
1905 debug.assert((try q.to(i32)) == eq);1898 testing.expect((try q.to(i32)) == eq);
1906 debug.assert((try r.to(i32)) == er);1899 testing.expect((try r.to(i32)) == er);
1907}1900}
19081901
1909test "big.int div floor single-single +/-" {1902test "big.int div floor single-single +/-" {
...@@ -1922,8 +1915,8 @@ test "big.int div floor single-single +/-" {...@@ -1922,8 +1915,8 @@ test "big.int div floor single-single +/-" {
1922 const eq = -2;1915 const eq = -2;
1923 const er = -1;1916 const er = -1;
19241917
1925 debug.assert((try q.to(i32)) == eq);1918 testing.expect((try q.to(i32)) == eq);
1926 debug.assert((try r.to(i32)) == er);1919 testing.expect((try r.to(i32)) == er);
1927}1920}
19281921
1929test "big.int div floor single-single -/-" {1922test "big.int div floor single-single -/-" {
...@@ -1942,8 +1935,8 @@ test "big.int div floor single-single -/-" {...@@ -1942,8 +1935,8 @@ test "big.int div floor single-single -/-" {
1942 const eq = 1;1935 const eq = 1;
1943 const er = -2;1936 const er = -2;
19441937
1945 debug.assert((try q.to(i32)) == eq);1938 testing.expect((try q.to(i32)) == eq);
1946 debug.assert((try r.to(i32)) == er);1939 testing.expect((try r.to(i32)) == er);
1947}1940}
19481941
1949test "big.int div multi-multi with rem" {1942test "big.int div multi-multi with rem" {
...@@ -1954,8 +1947,8 @@ test "big.int div multi-multi with rem" {...@@ -1954,8 +1947,8 @@ test "big.int div multi-multi with rem" {
1954 var r = try Int.init(al);1947 var r = try Int.init(al);
1955 try Int.divTrunc(&q, &r, a, b);1948 try Int.divTrunc(&q, &r, a, b);
19561949
1957 debug.assert((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b);1950 testing.expect((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b);
1958 debug.assert((try r.to(u128)) == 0x28de0acacd806823638);1951 testing.expect((try r.to(u128)) == 0x28de0acacd806823638);
1959}1952}
19601953
1961test "big.int div multi-multi no rem" {1954test "big.int div multi-multi no rem" {
...@@ -1966,8 +1959,8 @@ test "big.int div multi-multi no rem" {...@@ -1966,8 +1959,8 @@ test "big.int div multi-multi no rem" {
1966 var r = try Int.init(al);1959 var r = try Int.init(al);
1967 try Int.divTrunc(&q, &r, a, b);1960 try Int.divTrunc(&q, &r, a, b);
19681961
1969 debug.assert((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b);1962 testing.expect((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b);
1970 debug.assert((try r.to(u128)) == 0);1963 testing.expect((try r.to(u128)) == 0);
1971}1964}
19721965
1973test "big.int div multi-multi (2 branch)" {1966test "big.int div multi-multi (2 branch)" {
...@@ -1978,8 +1971,8 @@ test "big.int div multi-multi (2 branch)" {...@@ -1978,8 +1971,8 @@ test "big.int div multi-multi (2 branch)" {
1978 var r = try Int.init(al);1971 var r = try Int.init(al);
1979 try Int.divTrunc(&q, &r, a, b);1972 try Int.divTrunc(&q, &r, a, b);
19801973
1981 debug.assert((try q.to(u128)) == 0x10000000000000000);1974 testing.expect((try q.to(u128)) == 0x10000000000000000);
1982 debug.assert((try r.to(u128)) == 0x44444443444444431111111111111111);1975 testing.expect((try r.to(u128)) == 0x44444443444444431111111111111111);
1983}1976}
19841977
1985test "big.int div multi-multi (3.1/3.3 branch)" {1978test "big.int div multi-multi (3.1/3.3 branch)" {
...@@ -1990,53 +1983,53 @@ test "big.int div multi-multi (3.1/3.3 branch)" {...@@ -1990,53 +1983,53 @@ test "big.int div multi-multi (3.1/3.3 branch)" {
1990 var r = try Int.init(al);1983 var r = try Int.init(al);
1991 try Int.divTrunc(&q, &r, a, b);1984 try Int.divTrunc(&q, &r, a, b);
19921985
1993 debug.assert((try q.to(u128)) == 0xfffffffffffffffffff);1986 testing.expect((try q.to(u128)) == 0xfffffffffffffffffff);
1994 debug.assert((try r.to(u256)) == 0x1111111111111111111110b12222222222222222282);1987 testing.expect((try r.to(u256)) == 0x1111111111111111111110b12222222222222222282);
1995}1988}
19961989
1997test "big.int shift-right single" {1990test "big.int shift-right single" {
1998 var a = try Int.initSet(al, 0xffff0000);1991 var a = try Int.initSet(al, 0xffff0000);
1999 try a.shiftRight(a, 16);1992 try a.shiftRight(a, 16);
20001993
2001 debug.assert((try a.to(u32)) == 0xffff);1994 testing.expect((try a.to(u32)) == 0xffff);
2002}1995}
20031996
2004test "big.int shift-right multi" {1997test "big.int shift-right multi" {
2005 var a = try Int.initSet(al, 0xffff0000eeee1111dddd2222cccc3333);1998 var a = try Int.initSet(al, 0xffff0000eeee1111dddd2222cccc3333);
2006 try a.shiftRight(a, 67);1999 try a.shiftRight(a, 67);
20072000
2008 debug.assert((try a.to(u64)) == 0x1fffe0001dddc222);2001 testing.expect((try a.to(u64)) == 0x1fffe0001dddc222);
2009}2002}
20102003
2011test "big.int shift-left single" {2004test "big.int shift-left single" {
2012 var a = try Int.initSet(al, 0xffff);2005 var a = try Int.initSet(al, 0xffff);
2013 try a.shiftLeft(a, 16);2006 try a.shiftLeft(a, 16);
20142007
2015 debug.assert((try a.to(u64)) == 0xffff0000);2008 testing.expect((try a.to(u64)) == 0xffff0000);
2016}2009}
20172010
2018test "big.int shift-left multi" {2011test "big.int shift-left multi" {
2019 var a = try Int.initSet(al, 0x1fffe0001dddc222);2012 var a = try Int.initSet(al, 0x1fffe0001dddc222);
2020 try a.shiftLeft(a, 67);2013 try a.shiftLeft(a, 67);
20212014
2022 debug.assert((try a.to(u128)) == 0xffff0000eeee11100000000000000000);2015 testing.expect((try a.to(u128)) == 0xffff0000eeee11100000000000000000);
2023}2016}
20242017
2025test "big.int shift-right negative" {2018test "big.int shift-right negative" {
2026 var a = try Int.init(al);2019 var a = try Int.init(al);
20272020
2028 try a.shiftRight(try Int.initSet(al, -20), 2);2021 try a.shiftRight(try Int.initSet(al, -20), 2);
2029 debug.assert((try a.to(i32)) == -20 >> 2);2022 testing.expect((try a.to(i32)) == -20 >> 2);
20302023
2031 try a.shiftRight(try Int.initSet(al, -5), 10);2024 try a.shiftRight(try Int.initSet(al, -5), 10);
2032 debug.assert((try a.to(i32)) == -5 >> 10);2025 testing.expect((try a.to(i32)) == -5 >> 10);
2033}2026}
20342027
2035test "big.int shift-left negative" {2028test "big.int shift-left negative" {
2036 var a = try Int.init(al);2029 var a = try Int.init(al);
20372030
2038 try a.shiftRight(try Int.initSet(al, -10), 1232);2031 try a.shiftRight(try Int.initSet(al, -10), 1232);
2039 debug.assert((try a.to(i32)) == -10 >> 1232);2032 testing.expect((try a.to(i32)) == -10 >> 1232);
2040}2033}
20412034
2042test "big.int bitwise and simple" {2035test "big.int bitwise and simple" {
...@@ -2045,7 +2038,7 @@ test "big.int bitwise and simple" {...@@ -2045,7 +2038,7 @@ test "big.int bitwise and simple" {
20452038
2046 try a.bitAnd(a, b);2039 try a.bitAnd(a, b);
20472040
2048 debug.assert((try a.to(u64)) == 0xeeeeeeee00000000);2041 testing.expect((try a.to(u64)) == 0xeeeeeeee00000000);
2049}2042}
20502043
2051test "big.int bitwise and multi-limb" {2044test "big.int bitwise and multi-limb" {
...@@ -2054,7 +2047,7 @@ test "big.int bitwise and multi-limb" {...@@ -2054,7 +2047,7 @@ test "big.int bitwise and multi-limb" {
20542047
2055 try a.bitAnd(a, b);2048 try a.bitAnd(a, b);
20562049
2057 debug.assert((try a.to(u128)) == 0);2050 testing.expect((try a.to(u128)) == 0);
2058}2051}
20592052
2060test "big.int bitwise xor simple" {2053test "big.int bitwise xor simple" {
...@@ -2063,7 +2056,7 @@ test "big.int bitwise xor simple" {...@@ -2063,7 +2056,7 @@ test "big.int bitwise xor simple" {
20632056
2064 try a.bitXor(a, b);2057 try a.bitXor(a, b);
20652058
2066 debug.assert((try a.to(u64)) == 0x1111111133333333);2059 testing.expect((try a.to(u64)) == 0x1111111133333333);
2067}2060}
20682061
2069test "big.int bitwise xor multi-limb" {2062test "big.int bitwise xor multi-limb" {
...@@ -2072,7 +2065,7 @@ test "big.int bitwise xor multi-limb" {...@@ -2072,7 +2065,7 @@ test "big.int bitwise xor multi-limb" {
20722065
2073 try a.bitXor(a, b);2066 try a.bitXor(a, b);
20742067
2075 debug.assert((try a.to(DoubleLimb)) == (maxInt(Limb) + 1) ^ maxInt(Limb));2068 testing.expect((try a.to(DoubleLimb)) == (maxInt(Limb) + 1) ^ maxInt(Limb));
2076}2069}
20772070
2078test "big.int bitwise or simple" {2071test "big.int bitwise or simple" {
...@@ -2081,7 +2074,7 @@ test "big.int bitwise or simple" {...@@ -2081,7 +2074,7 @@ test "big.int bitwise or simple" {
20812074
2082 try a.bitOr(a, b);2075 try a.bitOr(a, b);
20832076
2084 debug.assert((try a.to(u64)) == 0xffffffff33333333);2077 testing.expect((try a.to(u64)) == 0xffffffff33333333);
2085}2078}
20862079
2087test "big.int bitwise or multi-limb" {2080test "big.int bitwise or multi-limb" {
...@@ -2091,15 +2084,15 @@ test "big.int bitwise or multi-limb" {...@@ -2091,15 +2084,15 @@ test "big.int bitwise or multi-limb" {
2091 try a.bitOr(a, b);2084 try a.bitOr(a, b);
20922085
2093 // TODO: big.int.cpp or is wrong on multi-limb.2086 // TODO: big.int.cpp or is wrong on multi-limb.
2094 debug.assert((try a.to(DoubleLimb)) == (maxInt(Limb) + 1) + maxInt(Limb));2087 testing.expect((try a.to(DoubleLimb)) == (maxInt(Limb) + 1) + maxInt(Limb));
2095}2088}
20962089
2097test "big.int var args" {2090test "big.int var args" {
2098 var a = try Int.initSet(al, 5);2091 var a = try Int.initSet(al, 5);
20992092
2100 try a.add(a, try Int.initSet(al, 6));2093 try a.add(a, try Int.initSet(al, 6));
2101 debug.assert((try a.to(u64)) == 11);2094 testing.expect((try a.to(u64)) == 11);
21022095
2103 debug.assert(a.cmp(try Int.initSet(al, 11)) == 0);2096 testing.expect(a.cmp(try Int.initSet(al, 11)) == 0);
2104 debug.assert(a.cmp(try Int.initSet(al, 14)) <= 0);2097 testing.expect(a.cmp(try Int.initSet(al, 14)) <= 0);
2105}2098}
std/math/cbrt.zig+25-25
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
66
7const std = @import("../index.zig");7const std = @import("../index.zig");
8const math = std.math;8const math = std.math;
9const assert = std.debug.assert;9const expect = std.testing.expect;
1010
11pub fn cbrt(x: var) @typeOf(x) {11pub fn cbrt(x: var) @typeOf(x) {
12 const T = @typeOf(x);12 const T = @typeOf(x);
...@@ -114,44 +114,44 @@ fn cbrt64(x: f64) f64 {...@@ -114,44 +114,44 @@ fn cbrt64(x: f64) f64 {
114}114}
115115
116test "math.cbrt" {116test "math.cbrt" {
117 assert(cbrt(f32(0.0)) == cbrt32(0.0));117 expect(cbrt(f32(0.0)) == cbrt32(0.0));
118 assert(cbrt(f64(0.0)) == cbrt64(0.0));118 expect(cbrt(f64(0.0)) == cbrt64(0.0));
119}119}
120120
121test "math.cbrt32" {121test "math.cbrt32" {
122 const epsilon = 0.000001;122 const epsilon = 0.000001;
123123
124 assert(cbrt32(0.0) == 0.0);124 expect(cbrt32(0.0) == 0.0);
125 assert(math.approxEq(f32, cbrt32(0.2), 0.584804, epsilon));125 expect(math.approxEq(f32, cbrt32(0.2), 0.584804, epsilon));
126 assert(math.approxEq(f32, cbrt32(0.8923), 0.962728, epsilon));126 expect(math.approxEq(f32, cbrt32(0.8923), 0.962728, epsilon));
127 assert(math.approxEq(f32, cbrt32(1.5), 1.144714, epsilon));127 expect(math.approxEq(f32, cbrt32(1.5), 1.144714, epsilon));
128 assert(math.approxEq(f32, cbrt32(37.45), 3.345676, epsilon));128 expect(math.approxEq(f32, cbrt32(37.45), 3.345676, epsilon));
129 assert(math.approxEq(f32, cbrt32(123123.234375), 49.748501, epsilon));129 expect(math.approxEq(f32, cbrt32(123123.234375), 49.748501, epsilon));
130}130}
131131
132test "math.cbrt64" {132test "math.cbrt64" {
133 const epsilon = 0.000001;133 const epsilon = 0.000001;
134134
135 assert(cbrt64(0.0) == 0.0);135 expect(cbrt64(0.0) == 0.0);
136 assert(math.approxEq(f64, cbrt64(0.2), 0.584804, epsilon));136 expect(math.approxEq(f64, cbrt64(0.2), 0.584804, epsilon));
137 assert(math.approxEq(f64, cbrt64(0.8923), 0.962728, epsilon));137 expect(math.approxEq(f64, cbrt64(0.8923), 0.962728, epsilon));
138 assert(math.approxEq(f64, cbrt64(1.5), 1.144714, epsilon));138 expect(math.approxEq(f64, cbrt64(1.5), 1.144714, epsilon));
139 assert(math.approxEq(f64, cbrt64(37.45), 3.345676, epsilon));139 expect(math.approxEq(f64, cbrt64(37.45), 3.345676, epsilon));
140 assert(math.approxEq(f64, cbrt64(123123.234375), 49.748501, epsilon));140 expect(math.approxEq(f64, cbrt64(123123.234375), 49.748501, epsilon));
141}141}
142142
143test "math.cbrt.special" {143test "math.cbrt.special" {
144 assert(cbrt32(0.0) == 0.0);144 expect(cbrt32(0.0) == 0.0);
145 assert(cbrt32(-0.0) == -0.0);145 expect(cbrt32(-0.0) == -0.0);
146 assert(math.isPositiveInf(cbrt32(math.inf(f32))));146 expect(math.isPositiveInf(cbrt32(math.inf(f32))));
147 assert(math.isNegativeInf(cbrt32(-math.inf(f32))));147 expect(math.isNegativeInf(cbrt32(-math.inf(f32))));
148 assert(math.isNan(cbrt32(math.nan(f32))));148 expect(math.isNan(cbrt32(math.nan(f32))));
149}149}
150150
151test "math.cbrt64.special" {151test "math.cbrt64.special" {
152 assert(cbrt64(0.0) == 0.0);152 expect(cbrt64(0.0) == 0.0);
153 assert(cbrt64(-0.0) == -0.0);153 expect(cbrt64(-0.0) == -0.0);
154 assert(math.isPositiveInf(cbrt64(math.inf(f64))));154 expect(math.isPositiveInf(cbrt64(math.inf(f64))));
155 assert(math.isNegativeInf(cbrt64(-math.inf(f64))));155 expect(math.isNegativeInf(cbrt64(-math.inf(f64))));
156 assert(math.isNan(cbrt64(math.nan(f64))));156 expect(math.isNan(cbrt64(math.nan(f64))));
157}157}
std/math/ceil.zig+19-19
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const std = @import("../index.zig");8const std = @import("../index.zig");
9const math = std.math;9const math = std.math;
10const assert = std.debug.assert;10const expect = std.testing.expect;
1111
12pub fn ceil(x: var) @typeOf(x) {12pub fn ceil(x: var) @typeOf(x) {
13 const T = @typeOf(x);13 const T = @typeOf(x);
...@@ -81,34 +81,34 @@ fn ceil64(x: f64) f64 {...@@ -81,34 +81,34 @@ fn ceil64(x: f64) f64 {
81}81}
8282
83test "math.ceil" {83test "math.ceil" {
84 assert(ceil(f32(0.0)) == ceil32(0.0));84 expect(ceil(f32(0.0)) == ceil32(0.0));
85 assert(ceil(f64(0.0)) == ceil64(0.0));85 expect(ceil(f64(0.0)) == ceil64(0.0));
86}86}
8787
88test "math.ceil32" {88test "math.ceil32" {
89 assert(ceil32(1.3) == 2.0);89 expect(ceil32(1.3) == 2.0);
90 assert(ceil32(-1.3) == -1.0);90 expect(ceil32(-1.3) == -1.0);
91 assert(ceil32(0.2) == 1.0);91 expect(ceil32(0.2) == 1.0);
92}92}
9393
94test "math.ceil64" {94test "math.ceil64" {
95 assert(ceil64(1.3) == 2.0);95 expect(ceil64(1.3) == 2.0);
96 assert(ceil64(-1.3) == -1.0);96 expect(ceil64(-1.3) == -1.0);
97 assert(ceil64(0.2) == 1.0);97 expect(ceil64(0.2) == 1.0);
98}98}
9999
100test "math.ceil32.special" {100test "math.ceil32.special" {
101 assert(ceil32(0.0) == 0.0);101 expect(ceil32(0.0) == 0.0);
102 assert(ceil32(-0.0) == -0.0);102 expect(ceil32(-0.0) == -0.0);
103 assert(math.isPositiveInf(ceil32(math.inf(f32))));103 expect(math.isPositiveInf(ceil32(math.inf(f32))));
104 assert(math.isNegativeInf(ceil32(-math.inf(f32))));104 expect(math.isNegativeInf(ceil32(-math.inf(f32))));
105 assert(math.isNan(ceil32(math.nan(f32))));105 expect(math.isNan(ceil32(math.nan(f32))));
106}106}
107107
108test "math.ceil64.special" {108test "math.ceil64.special" {
109 assert(ceil64(0.0) == 0.0);109 expect(ceil64(0.0) == 0.0);
110 assert(ceil64(-0.0) == -0.0);110 expect(ceil64(-0.0) == -0.0);
111 assert(math.isPositiveInf(ceil64(math.inf(f64))));111 expect(math.isPositiveInf(ceil64(math.inf(f64))));
112 assert(math.isNegativeInf(ceil64(-math.inf(f64))));112 expect(math.isNegativeInf(ceil64(-math.inf(f64))));
113 assert(math.isNan(ceil64(math.nan(f64))));113 expect(math.isNan(ceil64(math.nan(f64))));
114}114}
std/math/complex/abs.zig+2-2
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -14,5 +14,5 @@ const epsilon = 0.0001;...@@ -14,5 +14,5 @@ const epsilon = 0.0001;
14test "complex.cabs" {14test "complex.cabs" {
15 const a = Complex(f32).new(5, 3);15 const a = Complex(f32).new(5, 3);
16 const c = abs(a);16 const c = abs(a);
17 debug.assert(math.approxEq(f32, c, 5.83095, epsilon));17 testing.expect(math.approxEq(f32, c, 5.83095, epsilon));
18}18}
std/math/complex/acos.zig+3-3
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -16,6 +16,6 @@ test "complex.cacos" {...@@ -16,6 +16,6 @@ test "complex.cacos" {
16 const a = Complex(f32).new(5, 3);16 const a = Complex(f32).new(5, 3);
17 const c = acos(a);17 const c = acos(a);
1818
19 debug.assert(math.approxEq(f32, c.re, 0.546975, epsilon));19 testing.expect(math.approxEq(f32, c.re, 0.546975, epsilon));
20 debug.assert(math.approxEq(f32, c.im, -2.452914, epsilon));20 testing.expect(math.approxEq(f32, c.im, -2.452914, epsilon));
21}21}
std/math/complex/acosh.zig+3-3
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -16,6 +16,6 @@ test "complex.cacosh" {...@@ -16,6 +16,6 @@ test "complex.cacosh" {
16 const a = Complex(f32).new(5, 3);16 const a = Complex(f32).new(5, 3);
17 const c = acosh(a);17 const c = acosh(a);
1818
19 debug.assert(math.approxEq(f32, c.re, 2.452914, epsilon));19 testing.expect(math.approxEq(f32, c.re, 2.452914, epsilon));
20 debug.assert(math.approxEq(f32, c.im, 0.546975, epsilon));20 testing.expect(math.approxEq(f32, c.im, 0.546975, epsilon));
21}21}
std/math/complex/arg.zig+2-2
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -14,5 +14,5 @@ const epsilon = 0.0001;...@@ -14,5 +14,5 @@ const epsilon = 0.0001;
14test "complex.carg" {14test "complex.carg" {
15 const a = Complex(f32).new(5, 3);15 const a = Complex(f32).new(5, 3);
16 const c = arg(a);16 const c = arg(a);
17 debug.assert(math.approxEq(f32, c, 0.540420, epsilon));17 testing.expect(math.approxEq(f32, c, 0.540420, epsilon));
18}18}
std/math/complex/asin.zig+3-3
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -22,6 +22,6 @@ test "complex.casin" {...@@ -22,6 +22,6 @@ test "complex.casin" {
22 const a = Complex(f32).new(5, 3);22 const a = Complex(f32).new(5, 3);
23 const c = asin(a);23 const c = asin(a);
2424
25 debug.assert(math.approxEq(f32, c.re, 1.023822, epsilon));25 testing.expect(math.approxEq(f32, c.re, 1.023822, epsilon));
26 debug.assert(math.approxEq(f32, c.im, 2.452914, epsilon));26 testing.expect(math.approxEq(f32, c.im, 2.452914, epsilon));
27}27}
std/math/complex/asinh.zig+3-3
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -17,6 +17,6 @@ test "complex.casinh" {...@@ -17,6 +17,6 @@ test "complex.casinh" {
17 const a = Complex(f32).new(5, 3);17 const a = Complex(f32).new(5, 3);
18 const c = asinh(a);18 const c = asinh(a);
1919
20 debug.assert(math.approxEq(f32, c.re, 2.459831, epsilon));20 testing.expect(math.approxEq(f32, c.re, 2.459831, epsilon));
21 debug.assert(math.approxEq(f32, c.im, 0.533999, epsilon));21 testing.expect(math.approxEq(f32, c.im, 0.533999, epsilon));
22}22}
std/math/complex/atan.zig+5-5
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -117,14 +117,14 @@ test "complex.catan32" {...@@ -117,14 +117,14 @@ test "complex.catan32" {
117 const a = Complex(f32).new(5, 3);117 const a = Complex(f32).new(5, 3);
118 const c = atan(a);118 const c = atan(a);
119119
120 debug.assert(math.approxEq(f32, c.re, 1.423679, epsilon));120 testing.expect(math.approxEq(f32, c.re, 1.423679, epsilon));
121 debug.assert(math.approxEq(f32, c.im, 0.086569, epsilon));121 testing.expect(math.approxEq(f32, c.im, 0.086569, epsilon));
122}122}
123123
124test "complex.catan64" {124test "complex.catan64" {
125 const a = Complex(f64).new(5, 3);125 const a = Complex(f64).new(5, 3);
126 const c = atan(a);126 const c = atan(a);
127127
128 debug.assert(math.approxEq(f64, c.re, 1.423679, epsilon));128 testing.expect(math.approxEq(f64, c.re, 1.423679, epsilon));
129 debug.assert(math.approxEq(f64, c.im, 0.086569, epsilon));129 testing.expect(math.approxEq(f64, c.im, 0.086569, epsilon));
130}130}
std/math/complex/atanh.zig+3-3
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -17,6 +17,6 @@ test "complex.catanh" {...@@ -17,6 +17,6 @@ test "complex.catanh" {
17 const a = Complex(f32).new(5, 3);17 const a = Complex(f32).new(5, 3);
18 const c = atanh(a);18 const c = atanh(a);
1919
20 debug.assert(math.approxEq(f32, c.re, 0.146947, epsilon));20 testing.expect(math.approxEq(f32, c.re, 0.146947, epsilon));
21 debug.assert(math.approxEq(f32, c.im, 1.480870, epsilon));21 testing.expect(math.approxEq(f32, c.im, 1.480870, epsilon));
22}22}
std/math/complex/conj.zig+2-2
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -13,5 +13,5 @@ test "complex.conj" {...@@ -13,5 +13,5 @@ test "complex.conj" {
13 const a = Complex(f32).new(5, 3);13 const a = Complex(f32).new(5, 3);
14 const c = a.conjugate();14 const c = a.conjugate();
1515
16 debug.assert(c.re == 5 and c.im == -3);16 testing.expect(c.re == 5 and c.im == -3);
17}17}
std/math/complex/cos.zig+3-3
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -16,6 +16,6 @@ test "complex.ccos" {...@@ -16,6 +16,6 @@ test "complex.ccos" {
16 const a = Complex(f32).new(5, 3);16 const a = Complex(f32).new(5, 3);
17 const c = cos(a);17 const c = cos(a);
1818
19 debug.assert(math.approxEq(f32, c.re, 2.855815, epsilon));19 testing.expect(math.approxEq(f32, c.re, 2.855815, epsilon));
20 debug.assert(math.approxEq(f32, c.im, 9.606383, epsilon));20 testing.expect(math.approxEq(f32, c.im, 9.606383, epsilon));
21}21}
std/math/complex/cosh.zig+5-5
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -152,14 +152,14 @@ test "complex.ccosh32" {...@@ -152,14 +152,14 @@ test "complex.ccosh32" {
152 const a = Complex(f32).new(5, 3);152 const a = Complex(f32).new(5, 3);
153 const c = cosh(a);153 const c = cosh(a);
154154
155 debug.assert(math.approxEq(f32, c.re, -73.467300, epsilon));155 testing.expect(math.approxEq(f32, c.re, -73.467300, epsilon));
156 debug.assert(math.approxEq(f32, c.im, 10.471557, epsilon));156 testing.expect(math.approxEq(f32, c.im, 10.471557, epsilon));
157}157}
158158
159test "complex.ccosh64" {159test "complex.ccosh64" {
160 const a = Complex(f64).new(5, 3);160 const a = Complex(f64).new(5, 3);
161 const c = cosh(a);161 const c = cosh(a);
162162
163 debug.assert(math.approxEq(f64, c.re, -73.467300, epsilon));163 testing.expect(math.approxEq(f64, c.re, -73.467300, epsilon));
164 debug.assert(math.approxEq(f64, c.im, 10.471557, epsilon));164 testing.expect(math.approxEq(f64, c.im, 10.471557, epsilon));
165}165}
std/math/complex/exp.zig+5-5
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -118,14 +118,14 @@ test "complex.cexp32" {...@@ -118,14 +118,14 @@ test "complex.cexp32" {
118 const a = Complex(f32).new(5, 3);118 const a = Complex(f32).new(5, 3);
119 const c = exp(a);119 const c = exp(a);
120120
121 debug.assert(math.approxEq(f32, c.re, -146.927917, epsilon));121 testing.expect(math.approxEq(f32, c.re, -146.927917, epsilon));
122 debug.assert(math.approxEq(f32, c.im, 20.944065, epsilon));122 testing.expect(math.approxEq(f32, c.im, 20.944065, epsilon));
123}123}
124124
125test "complex.cexp64" {125test "complex.cexp64" {
126 const a = Complex(f64).new(5, 3);126 const a = Complex(f64).new(5, 3);
127 const c = exp(a);127 const c = exp(a);
128128
129 debug.assert(math.approxEq(f64, c.re, -146.927917, epsilon));129 testing.expect(math.approxEq(f64, c.re, -146.927917, epsilon));
130 debug.assert(math.approxEq(f64, c.im, 20.944065, epsilon));130 testing.expect(math.approxEq(f64, c.im, 20.944065, epsilon));
131}131}
std/math/complex/index.zig+8-8
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
44
5pub const abs = @import("abs.zig").abs;5pub const abs = @import("abs.zig").abs;
...@@ -97,7 +97,7 @@ test "complex.add" {...@@ -97,7 +97,7 @@ test "complex.add" {
97 const b = Complex(f32).new(2, 7);97 const b = Complex(f32).new(2, 7);
98 const c = a.add(b);98 const c = a.add(b);
9999
100 debug.assert(c.re == 7 and c.im == 10);100 testing.expect(c.re == 7 and c.im == 10);
101}101}
102102
103test "complex.sub" {103test "complex.sub" {
...@@ -105,7 +105,7 @@ test "complex.sub" {...@@ -105,7 +105,7 @@ test "complex.sub" {
105 const b = Complex(f32).new(2, 7);105 const b = Complex(f32).new(2, 7);
106 const c = a.sub(b);106 const c = a.sub(b);
107107
108 debug.assert(c.re == 3 and c.im == -4);108 testing.expect(c.re == 3 and c.im == -4);
109}109}
110110
111test "complex.mul" {111test "complex.mul" {
...@@ -113,7 +113,7 @@ test "complex.mul" {...@@ -113,7 +113,7 @@ test "complex.mul" {
113 const b = Complex(f32).new(2, 7);113 const b = Complex(f32).new(2, 7);
114 const c = a.mul(b);114 const c = a.mul(b);
115115
116 debug.assert(c.re == -11 and c.im == 41);116 testing.expect(c.re == -11 and c.im == 41);
117}117}
118118
119test "complex.div" {119test "complex.div" {
...@@ -121,7 +121,7 @@ test "complex.div" {...@@ -121,7 +121,7 @@ test "complex.div" {
121 const b = Complex(f32).new(2, 7);121 const b = Complex(f32).new(2, 7);
122 const c = a.div(b);122 const c = a.div(b);
123123
124 debug.assert(math.approxEq(f32, c.re, f32(31) / 53, epsilon) and124 testing.expect(math.approxEq(f32, c.re, f32(31) / 53, epsilon) and
125 math.approxEq(f32, c.im, f32(-29) / 53, epsilon));125 math.approxEq(f32, c.im, f32(-29) / 53, epsilon));
126}126}
127127
...@@ -129,14 +129,14 @@ test "complex.conjugate" {...@@ -129,14 +129,14 @@ test "complex.conjugate" {
129 const a = Complex(f32).new(5, 3);129 const a = Complex(f32).new(5, 3);
130 const c = a.conjugate();130 const c = a.conjugate();
131131
132 debug.assert(c.re == 5 and c.im == -3);132 testing.expect(c.re == 5 and c.im == -3);
133}133}
134134
135test "complex.reciprocal" {135test "complex.reciprocal" {
136 const a = Complex(f32).new(5, 3);136 const a = Complex(f32).new(5, 3);
137 const c = a.reciprocal();137 const c = a.reciprocal();
138138
139 debug.assert(math.approxEq(f32, c.re, f32(5) / 34, epsilon) and139 testing.expect(math.approxEq(f32, c.re, f32(5) / 34, epsilon) and
140 math.approxEq(f32, c.im, f32(-3) / 34, epsilon));140 math.approxEq(f32, c.im, f32(-3) / 34, epsilon));
141}141}
142142
...@@ -144,7 +144,7 @@ test "complex.magnitude" {...@@ -144,7 +144,7 @@ test "complex.magnitude" {
144 const a = Complex(f32).new(5, 3);144 const a = Complex(f32).new(5, 3);
145 const c = a.magnitude();145 const c = a.magnitude();
146146
147 debug.assert(math.approxEq(f32, c, 5.83095, epsilon));147 testing.expect(math.approxEq(f32, c, 5.83095, epsilon));
148}148}
149149
150test "complex.cmath" {150test "complex.cmath" {
std/math/complex/log.zig+3-3
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -18,6 +18,6 @@ test "complex.clog" {...@@ -18,6 +18,6 @@ test "complex.clog" {
18 const a = Complex(f32).new(5, 3);18 const a = Complex(f32).new(5, 3);
19 const c = log(a);19 const c = log(a);
2020
21 debug.assert(math.approxEq(f32, c.re, 1.763180, epsilon));21 testing.expect(math.approxEq(f32, c.re, 1.763180, epsilon));
22 debug.assert(math.approxEq(f32, c.im, 0.540419, epsilon));22 testing.expect(math.approxEq(f32, c.im, 0.540419, epsilon));
23}23}
std/math/complex/pow.zig+3-3
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -17,6 +17,6 @@ test "complex.cpow" {...@@ -17,6 +17,6 @@ test "complex.cpow" {
17 const b = Complex(f32).new(2.3, -1.3);17 const b = Complex(f32).new(2.3, -1.3);
18 const c = pow(Complex(f32), a, b);18 const c = pow(Complex(f32), a, b);
1919
20 debug.assert(math.approxEq(f32, c.re, 58.049110, epsilon));20 testing.expect(math.approxEq(f32, c.re, 58.049110, epsilon));
21 debug.assert(math.approxEq(f32, c.im, -101.003433, epsilon));21 testing.expect(math.approxEq(f32, c.im, -101.003433, epsilon));
22}22}
std/math/complex/proj.zig+2-2
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -20,5 +20,5 @@ test "complex.cproj" {...@@ -20,5 +20,5 @@ test "complex.cproj" {
20 const a = Complex(f32).new(5, 3);20 const a = Complex(f32).new(5, 3);
21 const c = proj(a);21 const c = proj(a);
2222
23 debug.assert(c.re == 5 and c.im == 3);23 testing.expect(c.re == 5 and c.im == 3);
24}24}
std/math/complex/sin.zig+3-3
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -17,6 +17,6 @@ test "complex.csin" {...@@ -17,6 +17,6 @@ test "complex.csin" {
17 const a = Complex(f32).new(5, 3);17 const a = Complex(f32).new(5, 3);
18 const c = sin(a);18 const c = sin(a);
1919
20 debug.assert(math.approxEq(f32, c.re, -9.654126, epsilon));20 testing.expect(math.approxEq(f32, c.re, -9.654126, epsilon));
21 debug.assert(math.approxEq(f32, c.im, 2.841692, epsilon));21 testing.expect(math.approxEq(f32, c.im, 2.841692, epsilon));
22}22}
std/math/complex/sinh.zig+5-5
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -151,14 +151,14 @@ test "complex.csinh32" {...@@ -151,14 +151,14 @@ test "complex.csinh32" {
151 const a = Complex(f32).new(5, 3);151 const a = Complex(f32).new(5, 3);
152 const c = sinh(a);152 const c = sinh(a);
153153
154 debug.assert(math.approxEq(f32, c.re, -73.460617, epsilon));154 testing.expect(math.approxEq(f32, c.re, -73.460617, epsilon));
155 debug.assert(math.approxEq(f32, c.im, 10.472508, epsilon));155 testing.expect(math.approxEq(f32, c.im, 10.472508, epsilon));
156}156}
157157
158test "complex.csinh64" {158test "complex.csinh64" {
159 const a = Complex(f64).new(5, 3);159 const a = Complex(f64).new(5, 3);
160 const c = sinh(a);160 const c = sinh(a);
161161
162 debug.assert(math.approxEq(f64, c.re, -73.460617, epsilon));162 testing.expect(math.approxEq(f64, c.re, -73.460617, epsilon));
163 debug.assert(math.approxEq(f64, c.im, 10.472508, epsilon));163 testing.expect(math.approxEq(f64, c.im, 10.472508, epsilon));
164}164}
std/math/complex/sqrt.zig+5-5
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -125,14 +125,14 @@ test "complex.csqrt32" {...@@ -125,14 +125,14 @@ test "complex.csqrt32" {
125 const a = Complex(f32).new(5, 3);125 const a = Complex(f32).new(5, 3);
126 const c = sqrt(a);126 const c = sqrt(a);
127127
128 debug.assert(math.approxEq(f32, c.re, 2.327117, epsilon));128 testing.expect(math.approxEq(f32, c.re, 2.327117, epsilon));
129 debug.assert(math.approxEq(f32, c.im, 0.644574, epsilon));129 testing.expect(math.approxEq(f32, c.im, 0.644574, epsilon));
130}130}
131131
132test "complex.csqrt64" {132test "complex.csqrt64" {
133 const a = Complex(f64).new(5, 3);133 const a = Complex(f64).new(5, 3);
134 const c = sqrt(a);134 const c = sqrt(a);
135135
136 debug.assert(math.approxEq(f64, c.re, 2.3271175190399496, epsilon));136 testing.expect(math.approxEq(f64, c.re, 2.3271175190399496, epsilon));
137 debug.assert(math.approxEq(f64, c.im, 0.6445742373246469, epsilon));137 testing.expect(math.approxEq(f64, c.im, 0.6445742373246469, epsilon));
138}138}
std/math/complex/tan.zig+3-3
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -17,6 +17,6 @@ test "complex.ctan" {...@@ -17,6 +17,6 @@ test "complex.ctan" {
17 const a = Complex(f32).new(5, 3);17 const a = Complex(f32).new(5, 3);
18 const c = tan(a);18 const c = tan(a);
1919
20 debug.assert(math.approxEq(f32, c.re, -0.002708233, epsilon));20 testing.expect(math.approxEq(f32, c.re, -0.002708233, epsilon));
21 debug.assert(math.approxEq(f32, c.im, 1.004165, epsilon));21 testing.expect(math.approxEq(f32, c.im, 1.004165, epsilon));
22}22}
std/math/complex/tanh.zig+5-5
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const debug = std.debug;2const testing = std.testing;
3const math = std.math;3const math = std.math;
4const cmath = math.complex;4const cmath = math.complex;
5const Complex = cmath.Complex;5const Complex = cmath.Complex;
...@@ -100,14 +100,14 @@ test "complex.ctanh32" {...@@ -100,14 +100,14 @@ test "complex.ctanh32" {
100 const a = Complex(f32).new(5, 3);100 const a = Complex(f32).new(5, 3);
101 const c = tanh(a);101 const c = tanh(a);
102102
103 debug.assert(math.approxEq(f32, c.re, 0.999913, epsilon));103 testing.expect(math.approxEq(f32, c.re, 0.999913, epsilon));
104 debug.assert(math.approxEq(f32, c.im, -0.000025, epsilon));104 testing.expect(math.approxEq(f32, c.im, -0.000025, epsilon));
105}105}
106106
107test "complex.ctanh64" {107test "complex.ctanh64" {
108 const a = Complex(f64).new(5, 3);108 const a = Complex(f64).new(5, 3);
109 const c = tanh(a);109 const c = tanh(a);
110110
111 debug.assert(math.approxEq(f64, c.re, 0.999913, epsilon));111 testing.expect(math.approxEq(f64, c.re, 0.999913, epsilon));
112 debug.assert(math.approxEq(f64, c.im, -0.000025, epsilon));112 testing.expect(math.approxEq(f64, c.im, -0.000025, epsilon));
113}113}
std/math/copysign.zig+16-16
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const std = @import("../index.zig");1const std = @import("../index.zig");
2const math = std.math;2const math = std.math;
3const assert = std.debug.assert;3const expect = std.testing.expect;
4const maxInt = std.math.maxInt;4const maxInt = std.math.maxInt;
55
6pub fn copysign(comptime T: type, x: T, y: T) T {6pub fn copysign(comptime T: type, x: T, y: T) T {
...@@ -40,28 +40,28 @@ fn copysign64(x: f64, y: f64) f64 {...@@ -40,28 +40,28 @@ fn copysign64(x: f64, y: f64) f64 {
40}40}
4141
42test "math.copysign" {42test "math.copysign" {
43 assert(copysign(f16, 1.0, 1.0) == copysign16(1.0, 1.0));43 expect(copysign(f16, 1.0, 1.0) == copysign16(1.0, 1.0));
44 assert(copysign(f32, 1.0, 1.0) == copysign32(1.0, 1.0));44 expect(copysign(f32, 1.0, 1.0) == copysign32(1.0, 1.0));
45 assert(copysign(f64, 1.0, 1.0) == copysign64(1.0, 1.0));45 expect(copysign(f64, 1.0, 1.0) == copysign64(1.0, 1.0));
46}46}
4747
48test "math.copysign16" {48test "math.copysign16" {
49 assert(copysign16(5.0, 1.0) == 5.0);49 expect(copysign16(5.0, 1.0) == 5.0);
50 assert(copysign16(5.0, -1.0) == -5.0);50 expect(copysign16(5.0, -1.0) == -5.0);
51 assert(copysign16(-5.0, -1.0) == -5.0);51 expect(copysign16(-5.0, -1.0) == -5.0);
52 assert(copysign16(-5.0, 1.0) == 5.0);52 expect(copysign16(-5.0, 1.0) == 5.0);
53}53}
5454
55test "math.copysign32" {55test "math.copysign32" {
56 assert(copysign32(5.0, 1.0) == 5.0);56 expect(copysign32(5.0, 1.0) == 5.0);
57 assert(copysign32(5.0, -1.0) == -5.0);57 expect(copysign32(5.0, -1.0) == -5.0);
58 assert(copysign32(-5.0, -1.0) == -5.0);58 expect(copysign32(-5.0, -1.0) == -5.0);
59 assert(copysign32(-5.0, 1.0) == 5.0);59 expect(copysign32(-5.0, 1.0) == 5.0);
60}60}
6161
62test "math.copysign64" {62test "math.copysign64" {
63 assert(copysign64(5.0, 1.0) == 5.0);63 expect(copysign64(5.0, 1.0) == 5.0);
64 assert(copysign64(5.0, -1.0) == -5.0);64 expect(copysign64(5.0, -1.0) == -5.0);
65 assert(copysign64(-5.0, -1.0) == -5.0);65 expect(copysign64(-5.0, -1.0) == -5.0);
66 assert(copysign64(-5.0, 1.0) == 5.0);66 expect(copysign64(-5.0, 1.0) == 5.0);
67}67}
std/math/cos.zig+21-21
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6const builtin = @import("builtin");6const builtin = @import("builtin");
7const std = @import("../index.zig");7const std = @import("../index.zig");
8const math = std.math;8const math = std.math;
9const assert = std.debug.assert;9const expect = std.testing.expect;
1010
11pub fn cos(x: var) @typeOf(x) {11pub fn cos(x: var) @typeOf(x) {
12 const T = @typeOf(x);12 const T = @typeOf(x);
...@@ -139,40 +139,40 @@ fn cos64(x_: f64) f64 {...@@ -139,40 +139,40 @@ fn cos64(x_: f64) f64 {
139}139}
140140
141test "math.cos" {141test "math.cos" {
142 assert(cos(f32(0.0)) == cos32(0.0));142 expect(cos(f32(0.0)) == cos32(0.0));
143 assert(cos(f64(0.0)) == cos64(0.0));143 expect(cos(f64(0.0)) == cos64(0.0));
144}144}
145145
146test "math.cos32" {146test "math.cos32" {
147 const epsilon = 0.000001;147 const epsilon = 0.000001;
148148
149 assert(math.approxEq(f32, cos32(0.0), 1.0, epsilon));149 expect(math.approxEq(f32, cos32(0.0), 1.0, epsilon));
150 assert(math.approxEq(f32, cos32(0.2), 0.980067, epsilon));150 expect(math.approxEq(f32, cos32(0.2), 0.980067, epsilon));
151 assert(math.approxEq(f32, cos32(0.8923), 0.627623, epsilon));151 expect(math.approxEq(f32, cos32(0.8923), 0.627623, epsilon));
152 assert(math.approxEq(f32, cos32(1.5), 0.070737, epsilon));152 expect(math.approxEq(f32, cos32(1.5), 0.070737, epsilon));
153 assert(math.approxEq(f32, cos32(37.45), 0.969132, epsilon));153 expect(math.approxEq(f32, cos32(37.45), 0.969132, epsilon));
154 assert(math.approxEq(f32, cos32(89.123), 0.400798, epsilon));154 expect(math.approxEq(f32, cos32(89.123), 0.400798, epsilon));
155}155}
156156
157test "math.cos64" {157test "math.cos64" {
158 const epsilon = 0.000001;158 const epsilon = 0.000001;
159159
160 assert(math.approxEq(f64, cos64(0.0), 1.0, epsilon));160 expect(math.approxEq(f64, cos64(0.0), 1.0, epsilon));
161 assert(math.approxEq(f64, cos64(0.2), 0.980067, epsilon));161 expect(math.approxEq(f64, cos64(0.2), 0.980067, epsilon));
162 assert(math.approxEq(f64, cos64(0.8923), 0.627623, epsilon));162 expect(math.approxEq(f64, cos64(0.8923), 0.627623, epsilon));
163 assert(math.approxEq(f64, cos64(1.5), 0.070737, epsilon));163 expect(math.approxEq(f64, cos64(1.5), 0.070737, epsilon));
164 assert(math.approxEq(f64, cos64(37.45), 0.969132, epsilon));164 expect(math.approxEq(f64, cos64(37.45), 0.969132, epsilon));
165 assert(math.approxEq(f64, cos64(89.123), 0.40080, epsilon));165 expect(math.approxEq(f64, cos64(89.123), 0.40080, epsilon));
166}166}
167167
168test "math.cos32.special" {168test "math.cos32.special" {
169 assert(math.isNan(cos32(math.inf(f32))));169 expect(math.isNan(cos32(math.inf(f32))));
170 assert(math.isNan(cos32(-math.inf(f32))));170 expect(math.isNan(cos32(-math.inf(f32))));
171 assert(math.isNan(cos32(math.nan(f32))));171 expect(math.isNan(cos32(math.nan(f32))));
172}172}
173173
174test "math.cos64.special" {174test "math.cos64.special" {
175 assert(math.isNan(cos64(math.inf(f64))));175 expect(math.isNan(cos64(math.inf(f64))));
176 assert(math.isNan(cos64(-math.inf(f64))));176 expect(math.isNan(cos64(-math.inf(f64))));
177 assert(math.isNan(cos64(math.nan(f64))));177 expect(math.isNan(cos64(math.nan(f64))));
178}178}
std/math/cosh.zig+21-21
...@@ -8,7 +8,7 @@ const builtin = @import("builtin");...@@ -8,7 +8,7 @@ const builtin = @import("builtin");
8const std = @import("../index.zig");8const std = @import("../index.zig");
9const math = std.math;9const math = std.math;
10const expo2 = @import("expo2.zig").expo2;10const expo2 = @import("expo2.zig").expo2;
11const assert = std.debug.assert;11const expect = std.testing.expect;
12const maxInt = std.math.maxInt;12const maxInt = std.math.maxInt;
1313
14pub fn cosh(x: var) @typeOf(x) {14pub fn cosh(x: var) @typeOf(x) {
...@@ -82,40 +82,40 @@ fn cosh64(x: f64) f64 {...@@ -82,40 +82,40 @@ fn cosh64(x: f64) f64 {
82}82}
8383
84test "math.cosh" {84test "math.cosh" {
85 assert(cosh(f32(1.5)) == cosh32(1.5));85 expect(cosh(f32(1.5)) == cosh32(1.5));
86 assert(cosh(f64(1.5)) == cosh64(1.5));86 expect(cosh(f64(1.5)) == cosh64(1.5));
87}87}
8888
89test "math.cosh32" {89test "math.cosh32" {
90 const epsilon = 0.000001;90 const epsilon = 0.000001;
9191
92 assert(math.approxEq(f32, cosh32(0.0), 1.0, epsilon));92 expect(math.approxEq(f32, cosh32(0.0), 1.0, epsilon));
93 assert(math.approxEq(f32, cosh32(0.2), 1.020067, epsilon));93 expect(math.approxEq(f32, cosh32(0.2), 1.020067, epsilon));
94 assert(math.approxEq(f32, cosh32(0.8923), 1.425225, epsilon));94 expect(math.approxEq(f32, cosh32(0.8923), 1.425225, epsilon));
95 assert(math.approxEq(f32, cosh32(1.5), 2.352410, epsilon));95 expect(math.approxEq(f32, cosh32(1.5), 2.352410, epsilon));
96}96}
9797
98test "math.cosh64" {98test "math.cosh64" {
99 const epsilon = 0.000001;99 const epsilon = 0.000001;
100100
101 assert(math.approxEq(f64, cosh64(0.0), 1.0, epsilon));101 expect(math.approxEq(f64, cosh64(0.0), 1.0, epsilon));
102 assert(math.approxEq(f64, cosh64(0.2), 1.020067, epsilon));102 expect(math.approxEq(f64, cosh64(0.2), 1.020067, epsilon));
103 assert(math.approxEq(f64, cosh64(0.8923), 1.425225, epsilon));103 expect(math.approxEq(f64, cosh64(0.8923), 1.425225, epsilon));
104 assert(math.approxEq(f64, cosh64(1.5), 2.352410, epsilon));104 expect(math.approxEq(f64, cosh64(1.5), 2.352410, epsilon));
105}105}
106106
107test "math.cosh32.special" {107test "math.cosh32.special" {
108 assert(cosh32(0.0) == 1.0);108 expect(cosh32(0.0) == 1.0);
109 assert(cosh32(-0.0) == 1.0);109 expect(cosh32(-0.0) == 1.0);
110 assert(math.isPositiveInf(cosh32(math.inf(f32))));110 expect(math.isPositiveInf(cosh32(math.inf(f32))));
111 assert(math.isPositiveInf(cosh32(-math.inf(f32))));111 expect(math.isPositiveInf(cosh32(-math.inf(f32))));
112 assert(math.isNan(cosh32(math.nan(f32))));112 expect(math.isNan(cosh32(math.nan(f32))));
113}113}
114114
115test "math.cosh64.special" {115test "math.cosh64.special" {
116 assert(cosh64(0.0) == 1.0);116 expect(cosh64(0.0) == 1.0);
117 assert(cosh64(-0.0) == 1.0);117 expect(cosh64(-0.0) == 1.0);
118 assert(math.isPositiveInf(cosh64(math.inf(f64))));118 expect(math.isPositiveInf(cosh64(math.inf(f64))));
119 assert(math.isPositiveInf(cosh64(-math.inf(f64))));119 expect(math.isPositiveInf(cosh64(-math.inf(f64))));
120 assert(math.isNan(cosh64(math.nan(f64))));120 expect(math.isNan(cosh64(math.nan(f64))));
121}121}
std/math/exp2.zig+16-16
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
55
6const std = @import("../index.zig");6const std = @import("../index.zig");
7const math = std.math;7const math = std.math;
8const assert = std.debug.assert;8const expect = std.testing.expect;
99
10pub fn exp2(x: var) @typeOf(x) {10pub fn exp2(x: var) @typeOf(x) {
11 const T = @typeOf(x);11 const T = @typeOf(x);
...@@ -415,35 +415,35 @@ fn exp2_64(x: f64) f64 {...@@ -415,35 +415,35 @@ fn exp2_64(x: f64) f64 {
415}415}
416416
417test "math.exp2" {417test "math.exp2" {
418 assert(exp2(f32(0.8923)) == exp2_32(0.8923));418 expect(exp2(f32(0.8923)) == exp2_32(0.8923));
419 assert(exp2(f64(0.8923)) == exp2_64(0.8923));419 expect(exp2(f64(0.8923)) == exp2_64(0.8923));
420}420}
421421
422test "math.exp2_32" {422test "math.exp2_32" {
423 const epsilon = 0.000001;423 const epsilon = 0.000001;
424424
425 assert(exp2_32(0.0) == 1.0);425 expect(exp2_32(0.0) == 1.0);
426 assert(math.approxEq(f32, exp2_32(0.2), 1.148698, epsilon));426 expect(math.approxEq(f32, exp2_32(0.2), 1.148698, epsilon));
427 assert(math.approxEq(f32, exp2_32(0.8923), 1.856133, epsilon));427 expect(math.approxEq(f32, exp2_32(0.8923), 1.856133, epsilon));
428 assert(math.approxEq(f32, exp2_32(1.5), 2.828427, epsilon));428 expect(math.approxEq(f32, exp2_32(1.5), 2.828427, epsilon));
429 assert(math.approxEq(f32, exp2_32(37.45), 187747237888, epsilon));429 expect(math.approxEq(f32, exp2_32(37.45), 187747237888, epsilon));
430}430}
431431
432test "math.exp2_64" {432test "math.exp2_64" {
433 const epsilon = 0.000001;433 const epsilon = 0.000001;
434434
435 assert(exp2_64(0.0) == 1.0);435 expect(exp2_64(0.0) == 1.0);
436 assert(math.approxEq(f64, exp2_64(0.2), 1.148698, epsilon));436 expect(math.approxEq(f64, exp2_64(0.2), 1.148698, epsilon));
437 assert(math.approxEq(f64, exp2_64(0.8923), 1.856133, epsilon));437 expect(math.approxEq(f64, exp2_64(0.8923), 1.856133, epsilon));
438 assert(math.approxEq(f64, exp2_64(1.5), 2.828427, epsilon));438 expect(math.approxEq(f64, exp2_64(1.5), 2.828427, epsilon));
439}439}
440440
441test "math.exp2_32.special" {441test "math.exp2_32.special" {
442 assert(math.isPositiveInf(exp2_32(math.inf(f32))));442 expect(math.isPositiveInf(exp2_32(math.inf(f32))));
443 assert(math.isNan(exp2_32(math.nan(f32))));443 expect(math.isNan(exp2_32(math.nan(f32))));
444}444}
445445
446test "math.exp2_64.special" {446test "math.exp2_64.special" {
447 assert(math.isPositiveInf(exp2_64(math.inf(f64))));447 expect(math.isPositiveInf(exp2_64(math.inf(f64))));
448 assert(math.isNan(exp2_64(math.nan(f64))));448 expect(math.isNan(exp2_64(math.nan(f64))));
449}449}
std/math/expm1.zig+19-19
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const std = @import("../index.zig");8const std = @import("../index.zig");
9const math = std.math;9const math = std.math;
10const assert = std.debug.assert;10const expect = std.testing.expect;
1111
12pub fn expm1(x: var) @typeOf(x) {12pub fn expm1(x: var) @typeOf(x) {
13 const T = @typeOf(x);13 const T = @typeOf(x);
...@@ -278,42 +278,42 @@ fn expm1_64(x_: f64) f64 {...@@ -278,42 +278,42 @@ fn expm1_64(x_: f64) f64 {
278}278}
279279
280test "math.exp1m" {280test "math.exp1m" {
281 assert(expm1(f32(0.0)) == expm1_32(0.0));281 expect(expm1(f32(0.0)) == expm1_32(0.0));
282 assert(expm1(f64(0.0)) == expm1_64(0.0));282 expect(expm1(f64(0.0)) == expm1_64(0.0));
283}283}
284284
285test "math.expm1_32" {285test "math.expm1_32" {
286 const epsilon = 0.000001;286 const epsilon = 0.000001;
287287
288 assert(expm1_32(0.0) == 0.0);288 expect(expm1_32(0.0) == 0.0);
289 assert(math.approxEq(f32, expm1_32(0.0), 0.0, epsilon));289 expect(math.approxEq(f32, expm1_32(0.0), 0.0, epsilon));
290 assert(math.approxEq(f32, expm1_32(0.2), 0.221403, epsilon));290 expect(math.approxEq(f32, expm1_32(0.2), 0.221403, epsilon));
291 assert(math.approxEq(f32, expm1_32(0.8923), 1.440737, epsilon));291 expect(math.approxEq(f32, expm1_32(0.8923), 1.440737, epsilon));
292 assert(math.approxEq(f32, expm1_32(1.5), 3.481689, epsilon));292 expect(math.approxEq(f32, expm1_32(1.5), 3.481689, epsilon));
293}293}
294294
295test "math.expm1_64" {295test "math.expm1_64" {
296 const epsilon = 0.000001;296 const epsilon = 0.000001;
297297
298 assert(expm1_64(0.0) == 0.0);298 expect(expm1_64(0.0) == 0.0);
299 assert(math.approxEq(f64, expm1_64(0.0), 0.0, epsilon));299 expect(math.approxEq(f64, expm1_64(0.0), 0.0, epsilon));
300 assert(math.approxEq(f64, expm1_64(0.2), 0.221403, epsilon));300 expect(math.approxEq(f64, expm1_64(0.2), 0.221403, epsilon));
301 assert(math.approxEq(f64, expm1_64(0.8923), 1.440737, epsilon));301 expect(math.approxEq(f64, expm1_64(0.8923), 1.440737, epsilon));
302 assert(math.approxEq(f64, expm1_64(1.5), 3.481689, epsilon));302 expect(math.approxEq(f64, expm1_64(1.5), 3.481689, epsilon));
303}303}
304304
305test "math.expm1_32.special" {305test "math.expm1_32.special" {
306 const epsilon = 0.000001;306 const epsilon = 0.000001;
307307
308 assert(math.isPositiveInf(expm1_32(math.inf(f32))));308 expect(math.isPositiveInf(expm1_32(math.inf(f32))));
309 assert(expm1_32(-math.inf(f32)) == -1.0);309 expect(expm1_32(-math.inf(f32)) == -1.0);
310 assert(math.isNan(expm1_32(math.nan(f32))));310 expect(math.isNan(expm1_32(math.nan(f32))));
311}311}
312312
313test "math.expm1_64.special" {313test "math.expm1_64.special" {
314 const epsilon = 0.000001;314 const epsilon = 0.000001;
315315
316 assert(math.isPositiveInf(expm1_64(math.inf(f64))));316 expect(math.isPositiveInf(expm1_64(math.inf(f64))));
317 assert(expm1_64(-math.inf(f64)) == -1.0);317 expect(expm1_64(-math.inf(f64)) == -1.0);
318 assert(math.isNan(expm1_64(math.nan(f64))));318 expect(math.isNan(expm1_64(math.nan(f64))));
319}319}
std/math/fabs.zig+38-19
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
55
6const std = @import("../index.zig");6const std = @import("../index.zig");
7const math = std.math;7const math = std.math;
8const assert = std.debug.assert;8const expect = std.testing.expect;
9const maxInt = std.math.maxInt;9const maxInt = std.math.maxInt;
1010
11pub fn fabs(x: var) @typeOf(x) {11pub fn fabs(x: var) @typeOf(x) {
...@@ -14,6 +14,7 @@ pub fn fabs(x: var) @typeOf(x) {...@@ -14,6 +14,7 @@ pub fn fabs(x: var) @typeOf(x) {
14 f16 => fabs16(x),14 f16 => fabs16(x),
15 f32 => fabs32(x),15 f32 => fabs32(x),
16 f64 => fabs64(x),16 f64 => fabs64(x),
17 f128 => fabs128(x),
17 else => @compileError("fabs not implemented for " ++ @typeName(T)),18 else => @compileError("fabs not implemented for " ++ @typeName(T)),
18 };19 };
19}20}
...@@ -36,41 +37,59 @@ fn fabs64(x: f64) f64 {...@@ -36,41 +37,59 @@ fn fabs64(x: f64) f64 {
36 return @bitCast(f64, u);37 return @bitCast(f64, u);
37}38}
3839
40fn fabs128(x: f128) f128 {
41 var u = @bitCast(u128, x);
42 u &= maxInt(u128) >> 1;
43 return @bitCast(f128, u);
44}
45
39test "math.fabs" {46test "math.fabs" {
40 assert(fabs(f16(1.0)) == fabs16(1.0));47 expect(fabs(f16(1.0)) == fabs16(1.0));
41 assert(fabs(f32(1.0)) == fabs32(1.0));48 expect(fabs(f32(1.0)) == fabs32(1.0));
42 assert(fabs(f64(1.0)) == fabs64(1.0));49 expect(fabs(f64(1.0)) == fabs64(1.0));
50 expect(fabs(f128(1.0)) == fabs128(1.0));
43}51}
4452
45test "math.fabs16" {53test "math.fabs16" {
46 assert(fabs16(1.0) == 1.0);54 expect(fabs16(1.0) == 1.0);
47 assert(fabs16(-1.0) == 1.0);55 expect(fabs16(-1.0) == 1.0);
48}56}
4957
50test "math.fabs32" {58test "math.fabs32" {
51 assert(fabs32(1.0) == 1.0);59 expect(fabs32(1.0) == 1.0);
52 assert(fabs32(-1.0) == 1.0);60 expect(fabs32(-1.0) == 1.0);
53}61}
5462
55test "math.fabs64" {63test "math.fabs64" {
56 assert(fabs64(1.0) == 1.0);64 expect(fabs64(1.0) == 1.0);
57 assert(fabs64(-1.0) == 1.0);65 expect(fabs64(-1.0) == 1.0);
66}
67
68test "math.fabs128" {
69 expect(fabs128(1.0) == 1.0);
70 expect(fabs128(-1.0) == 1.0);
58}71}
5972
60test "math.fabs16.special" {73test "math.fabs16.special" {
61 assert(math.isPositiveInf(fabs(math.inf(f16))));74 expect(math.isPositiveInf(fabs(math.inf(f16))));
62 assert(math.isPositiveInf(fabs(-math.inf(f16))));75 expect(math.isPositiveInf(fabs(-math.inf(f16))));
63 assert(math.isNan(fabs(math.nan(f16))));76 expect(math.isNan(fabs(math.nan(f16))));
64}77}
6578
66test "math.fabs32.special" {79test "math.fabs32.special" {
67 assert(math.isPositiveInf(fabs(math.inf(f32))));80 expect(math.isPositiveInf(fabs(math.inf(f32))));
68 assert(math.isPositiveInf(fabs(-math.inf(f32))));81 expect(math.isPositiveInf(fabs(-math.inf(f32))));
69 assert(math.isNan(fabs(math.nan(f32))));82 expect(math.isNan(fabs(math.nan(f32))));
70}83}
7184
72test "math.fabs64.special" {85test "math.fabs64.special" {
73 assert(math.isPositiveInf(fabs(math.inf(f64))));86 expect(math.isPositiveInf(fabs(math.inf(f64))));
74 assert(math.isPositiveInf(fabs(-math.inf(f64))));87 expect(math.isPositiveInf(fabs(-math.inf(f64))));
75 assert(math.isNan(fabs(math.nan(f64))));88 expect(math.isNan(fabs(math.nan(f64))));
89}
90
91test "math.fabs128.special" {
92 expect(math.isPositiveInf(fabs(math.inf(f128))));
93 expect(math.isPositiveInf(fabs(-math.inf(f128))));
94 expect(math.isNan(fabs(math.nan(f128))));
76}95}
std/math/floor.zig+28-28
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5// - floor(nan) = nan5// - floor(nan) = nan
66
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const assert = std.debug.assert;8const expect = std.testing.expect;
9const std = @import("../index.zig");9const std = @import("../index.zig");
10const math = std.math;10const math = std.math;
1111
...@@ -117,49 +117,49 @@ fn floor64(x: f64) f64 {...@@ -117,49 +117,49 @@ fn floor64(x: f64) f64 {
117}117}
118118
119test "math.floor" {119test "math.floor" {
120 assert(floor(f16(1.3)) == floor16(1.3));120 expect(floor(f16(1.3)) == floor16(1.3));
121 assert(floor(f32(1.3)) == floor32(1.3));121 expect(floor(f32(1.3)) == floor32(1.3));
122 assert(floor(f64(1.3)) == floor64(1.3));122 expect(floor(f64(1.3)) == floor64(1.3));
123}123}
124124
125test "math.floor16" {125test "math.floor16" {
126 assert(floor16(1.3) == 1.0);126 expect(floor16(1.3) == 1.0);
127 assert(floor16(-1.3) == -2.0);127 expect(floor16(-1.3) == -2.0);
128 assert(floor16(0.2) == 0.0);128 expect(floor16(0.2) == 0.0);
129}129}
130130
131test "math.floor32" {131test "math.floor32" {
132 assert(floor32(1.3) == 1.0);132 expect(floor32(1.3) == 1.0);
133 assert(floor32(-1.3) == -2.0);133 expect(floor32(-1.3) == -2.0);
134 assert(floor32(0.2) == 0.0);134 expect(floor32(0.2) == 0.0);
135}135}
136136
137test "math.floor64" {137test "math.floor64" {
138 assert(floor64(1.3) == 1.0);138 expect(floor64(1.3) == 1.0);
139 assert(floor64(-1.3) == -2.0);139 expect(floor64(-1.3) == -2.0);
140 assert(floor64(0.2) == 0.0);140 expect(floor64(0.2) == 0.0);
141}141}
142142
143test "math.floor16.special" {143test "math.floor16.special" {
144 assert(floor16(0.0) == 0.0);144 expect(floor16(0.0) == 0.0);
145 assert(floor16(-0.0) == -0.0);145 expect(floor16(-0.0) == -0.0);
146 assert(math.isPositiveInf(floor16(math.inf(f16))));146 expect(math.isPositiveInf(floor16(math.inf(f16))));
147 assert(math.isNegativeInf(floor16(-math.inf(f16))));147 expect(math.isNegativeInf(floor16(-math.inf(f16))));
148 assert(math.isNan(floor16(math.nan(f16))));148 expect(math.isNan(floor16(math.nan(f16))));
149}149}
150150
151test "math.floor32.special" {151test "math.floor32.special" {
152 assert(floor32(0.0) == 0.0);152 expect(floor32(0.0) == 0.0);
153 assert(floor32(-0.0) == -0.0);153 expect(floor32(-0.0) == -0.0);
154 assert(math.isPositiveInf(floor32(math.inf(f32))));154 expect(math.isPositiveInf(floor32(math.inf(f32))));
155 assert(math.isNegativeInf(floor32(-math.inf(f32))));155 expect(math.isNegativeInf(floor32(-math.inf(f32))));
156 assert(math.isNan(floor32(math.nan(f32))));156 expect(math.isNan(floor32(math.nan(f32))));
157}157}
158158
159test "math.floor64.special" {159test "math.floor64.special" {
160 assert(floor64(0.0) == 0.0);160 expect(floor64(0.0) == 0.0);
161 assert(floor64(-0.0) == -0.0);161 expect(floor64(-0.0) == -0.0);
162 assert(math.isPositiveInf(floor64(math.inf(f64))));162 expect(math.isPositiveInf(floor64(math.inf(f64))));
163 assert(math.isNegativeInf(floor64(-math.inf(f64))));163 expect(math.isNegativeInf(floor64(-math.inf(f64))));
164 assert(math.isNan(floor64(math.nan(f64))));164 expect(math.isNan(floor64(math.nan(f64))));
165}165}
std/math/fma.zig+17-17
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const std = @import("../index.zig");1const std = @import("../index.zig");
2const math = std.math;2const math = std.math;
3const assert = std.debug.assert;3const expect = std.testing.expect;
44
5pub fn fma(comptime T: type, x: T, y: T, z: T) T {5pub fn fma(comptime T: type, x: T, y: T, z: T) T {
6 return switch (T) {6 return switch (T) {
...@@ -135,30 +135,30 @@ fn add_and_denorm(a: f64, b: f64, scale: i32) f64 {...@@ -135,30 +135,30 @@ fn add_and_denorm(a: f64, b: f64, scale: i32) f64 {
135}135}
136136
137test "math.fma" {137test "math.fma" {
138 assert(fma(f32, 0.0, 1.0, 1.0) == fma32(0.0, 1.0, 1.0));138 expect(fma(f32, 0.0, 1.0, 1.0) == fma32(0.0, 1.0, 1.0));
139 assert(fma(f64, 0.0, 1.0, 1.0) == fma64(0.0, 1.0, 1.0));139 expect(fma(f64, 0.0, 1.0, 1.0) == fma64(0.0, 1.0, 1.0));
140}140}
141141
142test "math.fma32" {142test "math.fma32" {
143 const epsilon = 0.000001;143 const epsilon = 0.000001;
144144
145 assert(math.approxEq(f32, fma32(0.0, 5.0, 9.124), 9.124, epsilon));145 expect(math.approxEq(f32, fma32(0.0, 5.0, 9.124), 9.124, epsilon));
146 assert(math.approxEq(f32, fma32(0.2, 5.0, 9.124), 10.124, epsilon));146 expect(math.approxEq(f32, fma32(0.2, 5.0, 9.124), 10.124, epsilon));
147 assert(math.approxEq(f32, fma32(0.8923, 5.0, 9.124), 13.5855, epsilon));147 expect(math.approxEq(f32, fma32(0.8923, 5.0, 9.124), 13.5855, epsilon));
148 assert(math.approxEq(f32, fma32(1.5, 5.0, 9.124), 16.624, epsilon));148 expect(math.approxEq(f32, fma32(1.5, 5.0, 9.124), 16.624, epsilon));
149 assert(math.approxEq(f32, fma32(37.45, 5.0, 9.124), 196.374004, epsilon));149 expect(math.approxEq(f32, fma32(37.45, 5.0, 9.124), 196.374004, epsilon));
150 assert(math.approxEq(f32, fma32(89.123, 5.0, 9.124), 454.739005, epsilon));150 expect(math.approxEq(f32, fma32(89.123, 5.0, 9.124), 454.739005, epsilon));
151 assert(math.approxEq(f32, fma32(123123.234375, 5.0, 9.124), 615625.295875, epsilon));151 expect(math.approxEq(f32, fma32(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
152}152}
153153
154test "math.fma64" {154test "math.fma64" {
155 const epsilon = 0.000001;155 const epsilon = 0.000001;
156156
157 assert(math.approxEq(f64, fma64(0.0, 5.0, 9.124), 9.124, epsilon));157 expect(math.approxEq(f64, fma64(0.0, 5.0, 9.124), 9.124, epsilon));
158 assert(math.approxEq(f64, fma64(0.2, 5.0, 9.124), 10.124, epsilon));158 expect(math.approxEq(f64, fma64(0.2, 5.0, 9.124), 10.124, epsilon));
159 assert(math.approxEq(f64, fma64(0.8923, 5.0, 9.124), 13.5855, epsilon));159 expect(math.approxEq(f64, fma64(0.8923, 5.0, 9.124), 13.5855, epsilon));
160 assert(math.approxEq(f64, fma64(1.5, 5.0, 9.124), 16.624, epsilon));160 expect(math.approxEq(f64, fma64(1.5, 5.0, 9.124), 16.624, epsilon));
161 assert(math.approxEq(f64, fma64(37.45, 5.0, 9.124), 196.374, epsilon));161 expect(math.approxEq(f64, fma64(37.45, 5.0, 9.124), 196.374, epsilon));
162 assert(math.approxEq(f64, fma64(89.123, 5.0, 9.124), 454.739, epsilon));162 expect(math.approxEq(f64, fma64(89.123, 5.0, 9.124), 454.739, epsilon));
163 assert(math.approxEq(f64, fma64(123123.234375, 5.0, 9.124), 615625.295875, epsilon));163 expect(math.approxEq(f64, fma64(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
164}164}
std/math/frexp.zig+17-17
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
66
7const std = @import("../index.zig");7const std = @import("../index.zig");
8const math = std.math;8const math = std.math;
9const assert = std.debug.assert;9const expect = std.testing.expect;
1010
11fn frexp_result(comptime T: type) type {11fn frexp_result(comptime T: type) type {
12 return struct {12 return struct {
...@@ -103,11 +103,11 @@ fn frexp64(x: f64) frexp64_result {...@@ -103,11 +103,11 @@ fn frexp64(x: f64) frexp64_result {
103test "math.frexp" {103test "math.frexp" {
104 const a = frexp(f32(1.3));104 const a = frexp(f32(1.3));
105 const b = frexp32(1.3);105 const b = frexp32(1.3);
106 assert(a.significand == b.significand and a.exponent == b.exponent);106 expect(a.significand == b.significand and a.exponent == b.exponent);
107107
108 const c = frexp(f64(1.3));108 const c = frexp(f64(1.3));
109 const d = frexp64(1.3);109 const d = frexp64(1.3);
110 assert(c.significand == d.significand and c.exponent == d.exponent);110 expect(c.significand == d.significand and c.exponent == d.exponent);
111}111}
112112
113test "math.frexp32" {113test "math.frexp32" {
...@@ -115,10 +115,10 @@ test "math.frexp32" {...@@ -115,10 +115,10 @@ test "math.frexp32" {
115 var r: frexp32_result = undefined;115 var r: frexp32_result = undefined;
116116
117 r = frexp32(1.3);117 r = frexp32(1.3);
118 assert(math.approxEq(f32, r.significand, 0.65, epsilon) and r.exponent == 1);118 expect(math.approxEq(f32, r.significand, 0.65, epsilon) and r.exponent == 1);
119119
120 r = frexp32(78.0234);120 r = frexp32(78.0234);
121 assert(math.approxEq(f32, r.significand, 0.609558, epsilon) and r.exponent == 7);121 expect(math.approxEq(f32, r.significand, 0.609558, epsilon) and r.exponent == 7);
122}122}
123123
124test "math.frexp64" {124test "math.frexp64" {
...@@ -126,46 +126,46 @@ test "math.frexp64" {...@@ -126,46 +126,46 @@ test "math.frexp64" {
126 var r: frexp64_result = undefined;126 var r: frexp64_result = undefined;
127127
128 r = frexp64(1.3);128 r = frexp64(1.3);
129 assert(math.approxEq(f64, r.significand, 0.65, epsilon) and r.exponent == 1);129 expect(math.approxEq(f64, r.significand, 0.65, epsilon) and r.exponent == 1);
130130
131 r = frexp64(78.0234);131 r = frexp64(78.0234);
132 assert(math.approxEq(f64, r.significand, 0.609558, epsilon) and r.exponent == 7);132 expect(math.approxEq(f64, r.significand, 0.609558, epsilon) and r.exponent == 7);
133}133}
134134
135test "math.frexp32.special" {135test "math.frexp32.special" {
136 var r: frexp32_result = undefined;136 var r: frexp32_result = undefined;
137137
138 r = frexp32(0.0);138 r = frexp32(0.0);
139 assert(r.significand == 0.0 and r.exponent == 0);139 expect(r.significand == 0.0 and r.exponent == 0);
140140
141 r = frexp32(-0.0);141 r = frexp32(-0.0);
142 assert(r.significand == -0.0 and r.exponent == 0);142 expect(r.significand == -0.0 and r.exponent == 0);
143143
144 r = frexp32(math.inf(f32));144 r = frexp32(math.inf(f32));
145 assert(math.isPositiveInf(r.significand) and r.exponent == 0);145 expect(math.isPositiveInf(r.significand) and r.exponent == 0);
146146
147 r = frexp32(-math.inf(f32));147 r = frexp32(-math.inf(f32));
148 assert(math.isNegativeInf(r.significand) and r.exponent == 0);148 expect(math.isNegativeInf(r.significand) and r.exponent == 0);
149149
150 r = frexp32(math.nan(f32));150 r = frexp32(math.nan(f32));
151 assert(math.isNan(r.significand));151 expect(math.isNan(r.significand));
152}152}
153153
154test "math.frexp64.special" {154test "math.frexp64.special" {
155 var r: frexp64_result = undefined;155 var r: frexp64_result = undefined;
156156
157 r = frexp64(0.0);157 r = frexp64(0.0);
158 assert(r.significand == 0.0 and r.exponent == 0);158 expect(r.significand == 0.0 and r.exponent == 0);
159159
160 r = frexp64(-0.0);160 r = frexp64(-0.0);
161 assert(r.significand == -0.0 and r.exponent == 0);161 expect(r.significand == -0.0 and r.exponent == 0);
162162
163 r = frexp64(math.inf(f64));163 r = frexp64(math.inf(f64));
164 assert(math.isPositiveInf(r.significand) and r.exponent == 0);164 expect(math.isPositiveInf(r.significand) and r.exponent == 0);
165165
166 r = frexp64(-math.inf(f64));166 r = frexp64(-math.inf(f64));
167 assert(math.isNegativeInf(r.significand) and r.exponent == 0);167 expect(math.isNegativeInf(r.significand) and r.exponent == 0);
168168
169 r = frexp64(math.nan(f64));169 r = frexp64(math.nan(f64));
170 assert(math.isNan(r.significand));170 expect(math.isNan(r.significand));
171}171}
std/math/hypot.zig+29-29
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
77
8const std = @import("../index.zig");8const std = @import("../index.zig");
9const math = std.math;9const math = std.math;
10const assert = std.debug.assert;10const expect = std.testing.expect;
11const maxInt = std.math.maxInt;11const maxInt = std.math.maxInt;
1212
13pub fn hypot(comptime T: type, x: T, y: T) T {13pub fn hypot(comptime T: type, x: T, y: T) T {
...@@ -115,48 +115,48 @@ fn hypot64(x: f64, y: f64) f64 {...@@ -115,48 +115,48 @@ fn hypot64(x: f64, y: f64) f64 {
115}115}
116116
117test "math.hypot" {117test "math.hypot" {
118 assert(hypot(f32, 0.0, -1.2) == hypot32(0.0, -1.2));118 expect(hypot(f32, 0.0, -1.2) == hypot32(0.0, -1.2));
119 assert(hypot(f64, 0.0, -1.2) == hypot64(0.0, -1.2));119 expect(hypot(f64, 0.0, -1.2) == hypot64(0.0, -1.2));
120}120}
121121
122test "math.hypot32" {122test "math.hypot32" {
123 const epsilon = 0.000001;123 const epsilon = 0.000001;
124124
125 assert(math.approxEq(f32, hypot32(0.0, -1.2), 1.2, epsilon));125 expect(math.approxEq(f32, hypot32(0.0, -1.2), 1.2, epsilon));
126 assert(math.approxEq(f32, hypot32(0.2, -0.34), 0.394462, epsilon));126 expect(math.approxEq(f32, hypot32(0.2, -0.34), 0.394462, epsilon));
127 assert(math.approxEq(f32, hypot32(0.8923, 2.636890), 2.783772, epsilon));127 expect(math.approxEq(f32, hypot32(0.8923, 2.636890), 2.783772, epsilon));
128 assert(math.approxEq(f32, hypot32(1.5, 5.25), 5.460083, epsilon));128 expect(math.approxEq(f32, hypot32(1.5, 5.25), 5.460083, epsilon));
129 assert(math.approxEq(f32, hypot32(37.45, 159.835), 164.163742, epsilon));129 expect(math.approxEq(f32, hypot32(37.45, 159.835), 164.163742, epsilon));
130 assert(math.approxEq(f32, hypot32(89.123, 382.028905), 392.286865, epsilon));130 expect(math.approxEq(f32, hypot32(89.123, 382.028905), 392.286865, epsilon));
131 assert(math.approxEq(f32, hypot32(123123.234375, 529428.707813), 543556.875, epsilon));131 expect(math.approxEq(f32, hypot32(123123.234375, 529428.707813), 543556.875, epsilon));
132}132}
133133
134test "math.hypot64" {134test "math.hypot64" {
135 const epsilon = 0.000001;135 const epsilon = 0.000001;
136136
137 assert(math.approxEq(f64, hypot64(0.0, -1.2), 1.2, epsilon));137 expect(math.approxEq(f64, hypot64(0.0, -1.2), 1.2, epsilon));
138 assert(math.approxEq(f64, hypot64(0.2, -0.34), 0.394462, epsilon));138 expect(math.approxEq(f64, hypot64(0.2, -0.34), 0.394462, epsilon));
139 assert(math.approxEq(f64, hypot64(0.8923, 2.636890), 2.783772, epsilon));139 expect(math.approxEq(f64, hypot64(0.8923, 2.636890), 2.783772, epsilon));
140 assert(math.approxEq(f64, hypot64(1.5, 5.25), 5.460082, epsilon));140 expect(math.approxEq(f64, hypot64(1.5, 5.25), 5.460082, epsilon));
141 assert(math.approxEq(f64, hypot64(37.45, 159.835), 164.163728, epsilon));141 expect(math.approxEq(f64, hypot64(37.45, 159.835), 164.163728, epsilon));
142 assert(math.approxEq(f64, hypot64(89.123, 382.028905), 392.286876, epsilon));142 expect(math.approxEq(f64, hypot64(89.123, 382.028905), 392.286876, epsilon));
143 assert(math.approxEq(f64, hypot64(123123.234375, 529428.707813), 543556.885247, epsilon));143 expect(math.approxEq(f64, hypot64(123123.234375, 529428.707813), 543556.885247, epsilon));
144}144}
145145
146test "math.hypot32.special" {146test "math.hypot32.special" {
147 assert(math.isPositiveInf(hypot32(math.inf(f32), 0.0)));147 expect(math.isPositiveInf(hypot32(math.inf(f32), 0.0)));
148 assert(math.isPositiveInf(hypot32(-math.inf(f32), 0.0)));148 expect(math.isPositiveInf(hypot32(-math.inf(f32), 0.0)));
149 assert(math.isPositiveInf(hypot32(0.0, math.inf(f32))));149 expect(math.isPositiveInf(hypot32(0.0, math.inf(f32))));
150 assert(math.isPositiveInf(hypot32(0.0, -math.inf(f32))));150 expect(math.isPositiveInf(hypot32(0.0, -math.inf(f32))));
151 assert(math.isNan(hypot32(math.nan(f32), 0.0)));151 expect(math.isNan(hypot32(math.nan(f32), 0.0)));
152 assert(math.isNan(hypot32(0.0, math.nan(f32))));152 expect(math.isNan(hypot32(0.0, math.nan(f32))));
153}153}
154154
155test "math.hypot64.special" {155test "math.hypot64.special" {
156 assert(math.isPositiveInf(hypot64(math.inf(f64), 0.0)));156 expect(math.isPositiveInf(hypot64(math.inf(f64), 0.0)));
157 assert(math.isPositiveInf(hypot64(-math.inf(f64), 0.0)));157 expect(math.isPositiveInf(hypot64(-math.inf(f64), 0.0)));
158 assert(math.isPositiveInf(hypot64(0.0, math.inf(f64))));158 expect(math.isPositiveInf(hypot64(0.0, math.inf(f64))));
159 assert(math.isPositiveInf(hypot64(0.0, -math.inf(f64))));159 expect(math.isPositiveInf(hypot64(0.0, -math.inf(f64))));
160 assert(math.isNan(hypot64(math.nan(f64), 0.0)));160 expect(math.isNan(hypot64(math.nan(f64), 0.0)));
161 assert(math.isNan(hypot64(0.0, math.nan(f64))));161 expect(math.isNan(hypot64(0.0, math.nan(f64))));
162}162}
std/math/ilogb.zig+23-23
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
66
7const std = @import("../index.zig");7const std = @import("../index.zig");
8const math = std.math;8const math = std.math;
9const assert = std.debug.assert;9const expect = std.testing.expect;
10const maxInt = std.math.maxInt;10const maxInt = std.math.maxInt;
11const minInt = std.math.minInt;11const minInt = std.math.minInt;
1212
...@@ -95,38 +95,38 @@ fn ilogb64(x: f64) i32 {...@@ -95,38 +95,38 @@ fn ilogb64(x: f64) i32 {
95}95}
9696
97test "math.ilogb" {97test "math.ilogb" {
98 assert(ilogb(f32(0.2)) == ilogb32(0.2));98 expect(ilogb(f32(0.2)) == ilogb32(0.2));
99 assert(ilogb(f64(0.2)) == ilogb64(0.2));99 expect(ilogb(f64(0.2)) == ilogb64(0.2));
100}100}
101101
102test "math.ilogb32" {102test "math.ilogb32" {
103 assert(ilogb32(0.0) == fp_ilogb0);103 expect(ilogb32(0.0) == fp_ilogb0);
104 assert(ilogb32(0.5) == -1);104 expect(ilogb32(0.5) == -1);
105 assert(ilogb32(0.8923) == -1);105 expect(ilogb32(0.8923) == -1);
106 assert(ilogb32(10.0) == 3);106 expect(ilogb32(10.0) == 3);
107 assert(ilogb32(-123984) == 16);107 expect(ilogb32(-123984) == 16);
108 assert(ilogb32(2398.23) == 11);108 expect(ilogb32(2398.23) == 11);
109}109}
110110
111test "math.ilogb64" {111test "math.ilogb64" {
112 assert(ilogb64(0.0) == fp_ilogb0);112 expect(ilogb64(0.0) == fp_ilogb0);
113 assert(ilogb64(0.5) == -1);113 expect(ilogb64(0.5) == -1);
114 assert(ilogb64(0.8923) == -1);114 expect(ilogb64(0.8923) == -1);
115 assert(ilogb64(10.0) == 3);115 expect(ilogb64(10.0) == 3);
116 assert(ilogb64(-123984) == 16);116 expect(ilogb64(-123984) == 16);
117 assert(ilogb64(2398.23) == 11);117 expect(ilogb64(2398.23) == 11);
118}118}
119119
120test "math.ilogb32.special" {120test "math.ilogb32.special" {
121 assert(ilogb32(math.inf(f32)) == maxInt(i32));121 expect(ilogb32(math.inf(f32)) == maxInt(i32));
122 assert(ilogb32(-math.inf(f32)) == maxInt(i32));122 expect(ilogb32(-math.inf(f32)) == maxInt(i32));
123 assert(ilogb32(0.0) == minInt(i32));123 expect(ilogb32(0.0) == minInt(i32));
124 assert(ilogb32(math.nan(f32)) == maxInt(i32));124 expect(ilogb32(math.nan(f32)) == maxInt(i32));
125}125}
126126
127test "math.ilogb64.special" {127test "math.ilogb64.special" {
128 assert(ilogb64(math.inf(f64)) == maxInt(i32));128 expect(ilogb64(math.inf(f64)) == maxInt(i32));
129 assert(ilogb64(-math.inf(f64)) == maxInt(i32));129 expect(ilogb64(-math.inf(f64)) == maxInt(i32));
130 assert(ilogb64(0.0) == minInt(i32));130 expect(ilogb64(0.0) == minInt(i32));
131 assert(ilogb64(math.nan(f64)) == maxInt(i32));131 expect(ilogb64(math.nan(f64)) == maxInt(i32));
132}132}
std/math/index.zig+190-172
...@@ -2,10 +2,18 @@ const builtin = @import("builtin");...@@ -2,10 +2,18 @@ const builtin = @import("builtin");
2const std = @import("../index.zig");2const std = @import("../index.zig");
3const TypeId = builtin.TypeId;3const TypeId = builtin.TypeId;
4const assert = std.debug.assert;4const assert = std.debug.assert;
5const testing = std.testing;
56
6pub const e = 2.71828182845904523536028747135266249775724709369995;7pub const e = 2.71828182845904523536028747135266249775724709369995;
7pub const pi = 3.14159265358979323846264338327950288419716939937510;8pub const pi = 3.14159265358979323846264338327950288419716939937510;
89
10// From a small c++ [program using boost float128](https://github.com/winksaville/cpp_boost_float128)
11pub const f128_true_min = @bitCast(f128, u128(0x00000000000000000000000000000001));
12pub const f128_min = @bitCast(f128, u128(0x00010000000000000000000000000000));
13pub const f128_max = @bitCast(f128, u128(0x7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFF));
14pub const f128_epsilon = @bitCast(f128, u128(0x3F8F0000000000000000000000000000));
15pub const f128_toint = 1.0 / f128_epsilon;
16
9// float.h details17// float.h details
10pub const f64_true_min = 4.94065645841246544177e-324;18pub const f64_true_min = 4.94065645841246544177e-324;
11pub const f64_min = 2.2250738585072014e-308;19pub const f64_min = 2.2250738585072014e-308;
...@@ -43,6 +51,12 @@ pub const nan_f64 = @bitCast(f64, nan_u64);...@@ -43,6 +51,12 @@ pub const nan_f64 = @bitCast(f64, nan_u64);
43pub const inf_u64 = u64(0x7FF << 52);51pub const inf_u64 = u64(0x7FF << 52);
44pub const inf_f64 = @bitCast(f64, inf_u64);52pub const inf_f64 = @bitCast(f64, inf_u64);
4553
54pub const nan_u128 = u128(0x7fff0000000000000000000000000001);
55pub const nan_f128 = @bitCast(f128, nan_u128);
56
57pub const inf_u128 = u128(0x7fff0000000000000000000000000000);
58pub const inf_f128 = @bitCast(f128, inf_u128);
59
46pub const nan = @import("nan.zig").nan;60pub const nan = @import("nan.zig").nan;
47pub const snan = @import("nan.zig").snan;61pub const snan = @import("nan.zig").snan;
48pub const inf = @import("inf.zig").inf;62pub const inf = @import("inf.zig").inf;
...@@ -233,7 +247,7 @@ pub fn min(x: var, y: var) @typeOf(x + y) {...@@ -233,7 +247,7 @@ pub fn min(x: var, y: var) @typeOf(x + y) {
233}247}
234248
235test "math.min" {249test "math.min" {
236 assert(min(i32(-1), i32(2)) == -1);250 testing.expect(min(i32(-1), i32(2)) == -1);
237}251}
238252
239pub fn max(x: var, y: var) @typeOf(x + y) {253pub fn max(x: var, y: var) @typeOf(x + y) {
...@@ -241,7 +255,7 @@ pub fn max(x: var, y: var) @typeOf(x + y) {...@@ -241,7 +255,7 @@ pub fn max(x: var, y: var) @typeOf(x + y) {
241}255}
242256
243test "math.max" {257test "math.max" {
244 assert(max(i32(-1), i32(2)) == 2);258 testing.expect(max(i32(-1), i32(2)) == 2);
245}259}
246260
247pub fn mul(comptime T: type, a: T, b: T) (error{Overflow}!T) {261pub fn mul(comptime T: type, a: T, b: T) (error{Overflow}!T) {
...@@ -286,10 +300,10 @@ pub fn shl(comptime T: type, a: T, shift_amt: var) T {...@@ -286,10 +300,10 @@ pub fn shl(comptime T: type, a: T, shift_amt: var) T {
286}300}
287301
288test "math.shl" {302test "math.shl" {
289 assert(shl(u8, 0b11111111, usize(3)) == 0b11111000);303 testing.expect(shl(u8, 0b11111111, usize(3)) == 0b11111000);
290 assert(shl(u8, 0b11111111, usize(8)) == 0);304 testing.expect(shl(u8, 0b11111111, usize(8)) == 0);
291 assert(shl(u8, 0b11111111, usize(9)) == 0);305 testing.expect(shl(u8, 0b11111111, usize(9)) == 0);
292 assert(shl(u8, 0b11111111, isize(-2)) == 0b00111111);306 testing.expect(shl(u8, 0b11111111, isize(-2)) == 0b00111111);
293}307}
294308
295/// Shifts right. Overflowed bits are truncated.309/// Shifts right. Overflowed bits are truncated.
...@@ -310,10 +324,10 @@ pub fn shr(comptime T: type, a: T, shift_amt: var) T {...@@ -310,10 +324,10 @@ pub fn shr(comptime T: type, a: T, shift_amt: var) T {
310}324}
311325
312test "math.shr" {326test "math.shr" {
313 assert(shr(u8, 0b11111111, usize(3)) == 0b00011111);327 testing.expect(shr(u8, 0b11111111, usize(3)) == 0b00011111);
314 assert(shr(u8, 0b11111111, usize(8)) == 0);328 testing.expect(shr(u8, 0b11111111, usize(8)) == 0);
315 assert(shr(u8, 0b11111111, usize(9)) == 0);329 testing.expect(shr(u8, 0b11111111, usize(9)) == 0);
316 assert(shr(u8, 0b11111111, isize(-2)) == 0b11111100);330 testing.expect(shr(u8, 0b11111111, isize(-2)) == 0b11111100);
317}331}
318332
319/// Rotates right. Only unsigned values can be rotated.333/// Rotates right. Only unsigned values can be rotated.
...@@ -328,11 +342,11 @@ pub fn rotr(comptime T: type, x: T, r: var) T {...@@ -328,11 +342,11 @@ pub fn rotr(comptime T: type, x: T, r: var) T {
328}342}
329343
330test "math.rotr" {344test "math.rotr" {
331 assert(rotr(u8, 0b00000001, usize(0)) == 0b00000001);345 testing.expect(rotr(u8, 0b00000001, usize(0)) == 0b00000001);
332 assert(rotr(u8, 0b00000001, usize(9)) == 0b10000000);346 testing.expect(rotr(u8, 0b00000001, usize(9)) == 0b10000000);
333 assert(rotr(u8, 0b00000001, usize(8)) == 0b00000001);347 testing.expect(rotr(u8, 0b00000001, usize(8)) == 0b00000001);
334 assert(rotr(u8, 0b00000001, usize(4)) == 0b00010000);348 testing.expect(rotr(u8, 0b00000001, usize(4)) == 0b00010000);
335 assert(rotr(u8, 0b00000001, isize(-1)) == 0b00000010);349 testing.expect(rotr(u8, 0b00000001, isize(-1)) == 0b00000010);
336}350}
337351
338/// Rotates left. Only unsigned values can be rotated.352/// Rotates left. Only unsigned values can be rotated.
...@@ -347,11 +361,11 @@ pub fn rotl(comptime T: type, x: T, r: var) T {...@@ -347,11 +361,11 @@ pub fn rotl(comptime T: type, x: T, r: var) T {
347}361}
348362
349test "math.rotl" {363test "math.rotl" {
350 assert(rotl(u8, 0b00000001, usize(0)) == 0b00000001);364 testing.expect(rotl(u8, 0b00000001, usize(0)) == 0b00000001);
351 assert(rotl(u8, 0b00000001, usize(9)) == 0b00000010);365 testing.expect(rotl(u8, 0b00000001, usize(9)) == 0b00000010);
352 assert(rotl(u8, 0b00000001, usize(8)) == 0b00000001);366 testing.expect(rotl(u8, 0b00000001, usize(8)) == 0b00000001);
353 assert(rotl(u8, 0b00000001, usize(4)) == 0b00010000);367 testing.expect(rotl(u8, 0b00000001, usize(4)) == 0b00010000);
354 assert(rotl(u8, 0b00000001, isize(-1)) == 0b10000000);368 testing.expect(rotl(u8, 0b00000001, isize(-1)) == 0b10000000);
355}369}
356370
357pub fn Log2Int(comptime T: type) type {371pub fn Log2Int(comptime T: type) type {
...@@ -371,7 +385,7 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t...@@ -371,7 +385,7 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t
371 return u0;385 return u0;
372 }386 }
373 const is_signed = from < 0;387 const is_signed = from < 0;
374 const largest_positive_integer = max(if (from<0) (-from)-1 else from, to); // two's complement388 const largest_positive_integer = max(if (from < 0) (-from) - 1 else from, to); // two's complement
375 const base = log2(largest_positive_integer);389 const base = log2(largest_positive_integer);
376 const upper = (1 << base) - 1;390 const upper = (1 << base) - 1;
377 var magnitude_bits = if (upper >= largest_positive_integer) base else base + 1;391 var magnitude_bits = if (upper >= largest_positive_integer) base else base + 1;
...@@ -382,50 +396,50 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t...@@ -382,50 +396,50 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t
382}396}
383397
384test "math.IntFittingRange" {398test "math.IntFittingRange" {
385 assert(IntFittingRange(0, 0) == u0);399 testing.expect(IntFittingRange(0, 0) == u0);
386 assert(IntFittingRange(0, 1) == u1);400 testing.expect(IntFittingRange(0, 1) == u1);
387 assert(IntFittingRange(0, 2) == u2);401 testing.expect(IntFittingRange(0, 2) == u2);
388 assert(IntFittingRange(0, 3) == u2);402 testing.expect(IntFittingRange(0, 3) == u2);
389 assert(IntFittingRange(0, 4) == u3);403 testing.expect(IntFittingRange(0, 4) == u3);
390 assert(IntFittingRange(0, 7) == u3);404 testing.expect(IntFittingRange(0, 7) == u3);
391 assert(IntFittingRange(0, 8) == u4);405 testing.expect(IntFittingRange(0, 8) == u4);
392 assert(IntFittingRange(0, 9) == u4);406 testing.expect(IntFittingRange(0, 9) == u4);
393 assert(IntFittingRange(0, 15) == u4);407 testing.expect(IntFittingRange(0, 15) == u4);
394 assert(IntFittingRange(0, 16) == u5);408 testing.expect(IntFittingRange(0, 16) == u5);
395 assert(IntFittingRange(0, 17) == u5);409 testing.expect(IntFittingRange(0, 17) == u5);
396 assert(IntFittingRange(0, 4095) == u12);410 testing.expect(IntFittingRange(0, 4095) == u12);
397 assert(IntFittingRange(2000, 4095) == u12);411 testing.expect(IntFittingRange(2000, 4095) == u12);
398 assert(IntFittingRange(0, 4096) == u13);412 testing.expect(IntFittingRange(0, 4096) == u13);
399 assert(IntFittingRange(2000, 4096) == u13);413 testing.expect(IntFittingRange(2000, 4096) == u13);
400 assert(IntFittingRange(0, 4097) == u13);414 testing.expect(IntFittingRange(0, 4097) == u13);
401 assert(IntFittingRange(2000, 4097) == u13);415 testing.expect(IntFittingRange(2000, 4097) == u13);
402 assert(IntFittingRange(0, 123456789123456798123456789) == u87);416 testing.expect(IntFittingRange(0, 123456789123456798123456789) == u87);
403 assert(IntFittingRange(0, 123456789123456798123456789123456789123456798123456789) == u177);417 testing.expect(IntFittingRange(0, 123456789123456798123456789123456789123456798123456789) == u177);
404418
405 assert(IntFittingRange(-1, -1) == i1);419 testing.expect(IntFittingRange(-1, -1) == i1);
406 assert(IntFittingRange(-1, 0) == i1);420 testing.expect(IntFittingRange(-1, 0) == i1);
407 assert(IntFittingRange(-1, 1) == i2);421 testing.expect(IntFittingRange(-1, 1) == i2);
408 assert(IntFittingRange(-2, -2) == i2);422 testing.expect(IntFittingRange(-2, -2) == i2);
409 assert(IntFittingRange(-2, -1) == i2);423 testing.expect(IntFittingRange(-2, -1) == i2);
410 assert(IntFittingRange(-2, 0) == i2);424 testing.expect(IntFittingRange(-2, 0) == i2);
411 assert(IntFittingRange(-2, 1) == i2);425 testing.expect(IntFittingRange(-2, 1) == i2);
412 assert(IntFittingRange(-2, 2) == i3);426 testing.expect(IntFittingRange(-2, 2) == i3);
413 assert(IntFittingRange(-1, 2) == i3);427 testing.expect(IntFittingRange(-1, 2) == i3);
414 assert(IntFittingRange(-1, 3) == i3);428 testing.expect(IntFittingRange(-1, 3) == i3);
415 assert(IntFittingRange(-1, 4) == i4);429 testing.expect(IntFittingRange(-1, 4) == i4);
416 assert(IntFittingRange(-1, 7) == i4);430 testing.expect(IntFittingRange(-1, 7) == i4);
417 assert(IntFittingRange(-1, 8) == i5);431 testing.expect(IntFittingRange(-1, 8) == i5);
418 assert(IntFittingRange(-1, 9) == i5);432 testing.expect(IntFittingRange(-1, 9) == i5);
419 assert(IntFittingRange(-1, 15) == i5);433 testing.expect(IntFittingRange(-1, 15) == i5);
420 assert(IntFittingRange(-1, 16) == i6);434 testing.expect(IntFittingRange(-1, 16) == i6);
421 assert(IntFittingRange(-1, 17) == i6);435 testing.expect(IntFittingRange(-1, 17) == i6);
422 assert(IntFittingRange(-1, 4095) == i13);436 testing.expect(IntFittingRange(-1, 4095) == i13);
423 assert(IntFittingRange(-4096, 4095) == i13);437 testing.expect(IntFittingRange(-4096, 4095) == i13);
424 assert(IntFittingRange(-1, 4096) == i14);438 testing.expect(IntFittingRange(-1, 4096) == i14);
425 assert(IntFittingRange(-4097, 4095) == i14);439 testing.expect(IntFittingRange(-4097, 4095) == i14);
426 assert(IntFittingRange(-1, 4097) == i14);440 testing.expect(IntFittingRange(-1, 4097) == i14);
427 assert(IntFittingRange(-1, 123456789123456798123456789) == i88);441 testing.expect(IntFittingRange(-1, 123456789123456798123456789) == i88);
428 assert(IntFittingRange(-1, 123456789123456798123456789123456789123456798123456789) == i178);442 testing.expect(IntFittingRange(-1, 123456789123456798123456789123456789123456798123456789) == i178);
429}443}
430444
431test "math overflow functions" {445test "math overflow functions" {
...@@ -434,10 +448,10 @@ test "math overflow functions" {...@@ -434,10 +448,10 @@ test "math overflow functions" {
434}448}
435449
436fn testOverflow() void {450fn testOverflow() void {
437 assert((mul(i32, 3, 4) catch unreachable) == 12);451 testing.expect((mul(i32, 3, 4) catch unreachable) == 12);
438 assert((add(i32, 3, 4) catch unreachable) == 7);452 testing.expect((add(i32, 3, 4) catch unreachable) == 7);
439 assert((sub(i32, 3, 4) catch unreachable) == -1);453 testing.expect((sub(i32, 3, 4) catch unreachable) == -1);
440 assert((shlExact(i32, 0b11, 4) catch unreachable) == 0b110000);454 testing.expect((shlExact(i32, 0b11, 4) catch unreachable) == 0b110000);
441}455}
442456
443pub fn absInt(x: var) !@typeOf(x) {457pub fn absInt(x: var) !@typeOf(x) {
...@@ -458,8 +472,8 @@ test "math.absInt" {...@@ -458,8 +472,8 @@ test "math.absInt" {
458 comptime testAbsInt();472 comptime testAbsInt();
459}473}
460fn testAbsInt() void {474fn testAbsInt() void {
461 assert((absInt(i32(-10)) catch unreachable) == 10);475 testing.expect((absInt(i32(-10)) catch unreachable) == 10);
462 assert((absInt(i32(10)) catch unreachable) == 10);476 testing.expect((absInt(i32(10)) catch unreachable) == 10);
463}477}
464478
465pub const absFloat = @import("fabs.zig").fabs;479pub const absFloat = @import("fabs.zig").fabs;
...@@ -476,13 +490,13 @@ test "math.divTrunc" {...@@ -476,13 +490,13 @@ test "math.divTrunc" {
476 comptime testDivTrunc();490 comptime testDivTrunc();
477}491}
478fn testDivTrunc() void {492fn testDivTrunc() void {
479 assert((divTrunc(i32, 5, 3) catch unreachable) == 1);493 testing.expect((divTrunc(i32, 5, 3) catch unreachable) == 1);
480 assert((divTrunc(i32, -5, 3) catch unreachable) == -1);494 testing.expect((divTrunc(i32, -5, 3) catch unreachable) == -1);
481 if (divTrunc(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);495 testing.expectError(error.DivisionByZero, divTrunc(i8, -5, 0));
482 if (divTrunc(i8, -128, -1)) |_| unreachable else |err| assert(err == error.Overflow);496 testing.expectError(error.Overflow, divTrunc(i8, -128, -1));
483497
484 assert((divTrunc(f32, 5.0, 3.0) catch unreachable) == 1.0);498 testing.expect((divTrunc(f32, 5.0, 3.0) catch unreachable) == 1.0);
485 assert((divTrunc(f32, -5.0, 3.0) catch unreachable) == -1.0);499 testing.expect((divTrunc(f32, -5.0, 3.0) catch unreachable) == -1.0);
486}500}
487501
488pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T {502pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T {
...@@ -497,13 +511,13 @@ test "math.divFloor" {...@@ -497,13 +511,13 @@ test "math.divFloor" {
497 comptime testDivFloor();511 comptime testDivFloor();
498}512}
499fn testDivFloor() void {513fn testDivFloor() void {
500 assert((divFloor(i32, 5, 3) catch unreachable) == 1);514 testing.expect((divFloor(i32, 5, 3) catch unreachable) == 1);
501 assert((divFloor(i32, -5, 3) catch unreachable) == -2);515 testing.expect((divFloor(i32, -5, 3) catch unreachable) == -2);
502 if (divFloor(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);516 testing.expectError(error.DivisionByZero, divFloor(i8, -5, 0));
503 if (divFloor(i8, -128, -1)) |_| unreachable else |err| assert(err == error.Overflow);517 testing.expectError(error.Overflow, divFloor(i8, -128, -1));
504518
505 assert((divFloor(f32, 5.0, 3.0) catch unreachable) == 1.0);519 testing.expect((divFloor(f32, 5.0, 3.0) catch unreachable) == 1.0);
506 assert((divFloor(f32, -5.0, 3.0) catch unreachable) == -2.0);520 testing.expect((divFloor(f32, -5.0, 3.0) catch unreachable) == -2.0);
507}521}
508522
509pub fn divExact(comptime T: type, numerator: T, denominator: T) !T {523pub fn divExact(comptime T: type, numerator: T, denominator: T) !T {
...@@ -520,15 +534,15 @@ test "math.divExact" {...@@ -520,15 +534,15 @@ test "math.divExact" {
520 comptime testDivExact();534 comptime testDivExact();
521}535}
522fn testDivExact() void {536fn testDivExact() void {
523 assert((divExact(i32, 10, 5) catch unreachable) == 2);537 testing.expect((divExact(i32, 10, 5) catch unreachable) == 2);
524 assert((divExact(i32, -10, 5) catch unreachable) == -2);538 testing.expect((divExact(i32, -10, 5) catch unreachable) == -2);
525 if (divExact(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);539 testing.expectError(error.DivisionByZero, divExact(i8, -5, 0));
526 if (divExact(i8, -128, -1)) |_| unreachable else |err| assert(err == error.Overflow);540 testing.expectError(error.Overflow, divExact(i8, -128, -1));
527 if (divExact(i32, 5, 2)) |_| unreachable else |err| assert(err == error.UnexpectedRemainder);541 testing.expectError(error.UnexpectedRemainder, divExact(i32, 5, 2));
528542
529 assert((divExact(f32, 10.0, 5.0) catch unreachable) == 2.0);543 testing.expect((divExact(f32, 10.0, 5.0) catch unreachable) == 2.0);
530 assert((divExact(f32, -10.0, 5.0) catch unreachable) == -2.0);544 testing.expect((divExact(f32, -10.0, 5.0) catch unreachable) == -2.0);
531 if (divExact(f32, 5.0, 2.0)) |_| unreachable else |err| assert(err == error.UnexpectedRemainder);545 testing.expectError(error.UnexpectedRemainder, divExact(f32, 5.0, 2.0));
532}546}
533547
534pub fn mod(comptime T: type, numerator: T, denominator: T) !T {548pub fn mod(comptime T: type, numerator: T, denominator: T) !T {
...@@ -543,15 +557,15 @@ test "math.mod" {...@@ -543,15 +557,15 @@ test "math.mod" {
543 comptime testMod();557 comptime testMod();
544}558}
545fn testMod() void {559fn testMod() void {
546 assert((mod(i32, -5, 3) catch unreachable) == 1);560 testing.expect((mod(i32, -5, 3) catch unreachable) == 1);
547 assert((mod(i32, 5, 3) catch unreachable) == 2);561 testing.expect((mod(i32, 5, 3) catch unreachable) == 2);
548 if (mod(i32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator);562 testing.expectError(error.NegativeDenominator, mod(i32, 10, -1));
549 if (mod(i32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);563 testing.expectError(error.DivisionByZero, mod(i32, 10, 0));
550564
551 assert((mod(f32, -5, 3) catch unreachable) == 1);565 testing.expect((mod(f32, -5, 3) catch unreachable) == 1);
552 assert((mod(f32, 5, 3) catch unreachable) == 2);566 testing.expect((mod(f32, 5, 3) catch unreachable) == 2);
553 if (mod(f32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator);567 testing.expectError(error.NegativeDenominator, mod(f32, 10, -1));
554 if (mod(f32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);568 testing.expectError(error.DivisionByZero, mod(f32, 10, 0));
555}569}
556570
557pub fn rem(comptime T: type, numerator: T, denominator: T) !T {571pub fn rem(comptime T: type, numerator: T, denominator: T) !T {
...@@ -566,15 +580,15 @@ test "math.rem" {...@@ -566,15 +580,15 @@ test "math.rem" {
566 comptime testRem();580 comptime testRem();
567}581}
568fn testRem() void {582fn testRem() void {
569 assert((rem(i32, -5, 3) catch unreachable) == -2);583 testing.expect((rem(i32, -5, 3) catch unreachable) == -2);
570 assert((rem(i32, 5, 3) catch unreachable) == 2);584 testing.expect((rem(i32, 5, 3) catch unreachable) == 2);
571 if (rem(i32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator);585 testing.expectError(error.NegativeDenominator, rem(i32, 10, -1));
572 if (rem(i32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);586 testing.expectError(error.DivisionByZero, rem(i32, 10, 0));
573587
574 assert((rem(f32, -5, 3) catch unreachable) == -2);588 testing.expect((rem(f32, -5, 3) catch unreachable) == -2);
575 assert((rem(f32, 5, 3) catch unreachable) == 2);589 testing.expect((rem(f32, 5, 3) catch unreachable) == 2);
576 if (rem(f32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator);590 testing.expectError(error.NegativeDenominator, rem(f32, 10, -1));
577 if (rem(f32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);591 testing.expectError(error.DivisionByZero, rem(f32, 10, 0));
578}592}
579593
580/// Returns the absolute value of the integer parameter.594/// Returns the absolute value of the integer parameter.
...@@ -587,14 +601,14 @@ pub fn absCast(x: var) @IntType(false, @typeOf(x).bit_count) {...@@ -587,14 +601,14 @@ pub fn absCast(x: var) @IntType(false, @typeOf(x).bit_count) {
587}601}
588602
589test "math.absCast" {603test "math.absCast" {
590 assert(absCast(i32(-999)) == 999);604 testing.expect(absCast(i32(-999)) == 999);
591 assert(@typeOf(absCast(i32(-999))) == u32);605 testing.expect(@typeOf(absCast(i32(-999))) == u32);
592606
593 assert(absCast(i32(999)) == 999);607 testing.expect(absCast(i32(999)) == 999);
594 assert(@typeOf(absCast(i32(999))) == u32);608 testing.expect(@typeOf(absCast(i32(999))) == u32);
595609
596 assert(absCast(i32(minInt(i32))) == -minInt(i32));610 testing.expect(absCast(i32(minInt(i32))) == -minInt(i32));
597 assert(@typeOf(absCast(i32(minInt(i32)))) == u32);611 testing.expect(@typeOf(absCast(i32(minInt(i32)))) == u32);
598}612}
599613
600/// Returns the negation of the integer parameter.614/// Returns the negation of the integer parameter.
...@@ -611,13 +625,13 @@ pub fn negateCast(x: var) !@IntType(true, @typeOf(x).bit_count) {...@@ -611,13 +625,13 @@ pub fn negateCast(x: var) !@IntType(true, @typeOf(x).bit_count) {
611}625}
612626
613test "math.negateCast" {627test "math.negateCast" {
614 assert((negateCast(u32(999)) catch unreachable) == -999);628 testing.expect((negateCast(u32(999)) catch unreachable) == -999);
615 assert(@typeOf(negateCast(u32(999)) catch unreachable) == i32);629 testing.expect(@typeOf(negateCast(u32(999)) catch unreachable) == i32);
616630
617 assert((negateCast(u32(-minInt(i32))) catch unreachable) == minInt(i32));631 testing.expect((negateCast(u32(-minInt(i32))) catch unreachable) == minInt(i32));
618 assert(@typeOf(negateCast(u32(-minInt(i32))) catch unreachable) == i32);632 testing.expect(@typeOf(negateCast(u32(-minInt(i32))) catch unreachable) == i32);
619633
620 if (negateCast(u32(maxInt(i32) + 10))) |_| unreachable else |err| assert(err == error.Overflow);634 testing.expectError(error.Overflow, negateCast(u32(maxInt(i32) + 10)));
621}635}
622636
623/// Cast an integer to a different integer type. If the value doesn't fit,637/// Cast an integer to a different integer type. If the value doesn't fit,
...@@ -635,13 +649,13 @@ pub fn cast(comptime T: type, x: var) (error{Overflow}!T) {...@@ -635,13 +649,13 @@ pub fn cast(comptime T: type, x: var) (error{Overflow}!T) {
635}649}
636650
637test "math.cast" {651test "math.cast" {
638 if (cast(u8, u32(300))) |_| @panic("fail") else |err| assert(err == error.Overflow);652 testing.expectError(error.Overflow, cast(u8, u32(300)));
639 if (cast(i8, i32(-200))) |_| @panic("fail") else |err| assert(err == error.Overflow);653 testing.expectError(error.Overflow, cast(i8, i32(-200)));
640 if (cast(u8, i8(-1))) |_| @panic("fail") else |err| assert(err == error.Overflow);654 testing.expectError(error.Overflow, cast(u8, i8(-1)));
641 if (cast(u64, i8(-1))) |_| @panic("fail") else |err| assert(err == error.Overflow);655 testing.expectError(error.Overflow, cast(u64, i8(-1)));
642656
643 assert((try cast(u8, u32(255))) == u8(255));657 testing.expect((try cast(u8, u32(255))) == u8(255));
644 assert(@typeOf(try cast(u8, u32(255))) == u8);658 testing.expect(@typeOf(try cast(u8, u32(255))) == u8);
645}659}
646660
647pub const AlignCastError = error{UnalignedMemory};661pub const AlignCastError = error{UnalignedMemory};
...@@ -685,25 +699,25 @@ pub fn log2_int_ceil(comptime T: type, x: T) Log2Int(T) {...@@ -685,25 +699,25 @@ pub fn log2_int_ceil(comptime T: type, x: T) Log2Int(T) {
685}699}
686700
687test "std.math.log2_int_ceil" {701test "std.math.log2_int_ceil" {
688 assert(log2_int_ceil(u32, 1) == 0);702 testing.expect(log2_int_ceil(u32, 1) == 0);
689 assert(log2_int_ceil(u32, 2) == 1);703 testing.expect(log2_int_ceil(u32, 2) == 1);
690 assert(log2_int_ceil(u32, 3) == 2);704 testing.expect(log2_int_ceil(u32, 3) == 2);
691 assert(log2_int_ceil(u32, 4) == 2);705 testing.expect(log2_int_ceil(u32, 4) == 2);
692 assert(log2_int_ceil(u32, 5) == 3);706 testing.expect(log2_int_ceil(u32, 5) == 3);
693 assert(log2_int_ceil(u32, 6) == 3);707 testing.expect(log2_int_ceil(u32, 6) == 3);
694 assert(log2_int_ceil(u32, 7) == 3);708 testing.expect(log2_int_ceil(u32, 7) == 3);
695 assert(log2_int_ceil(u32, 8) == 3);709 testing.expect(log2_int_ceil(u32, 8) == 3);
696 assert(log2_int_ceil(u32, 9) == 4);710 testing.expect(log2_int_ceil(u32, 9) == 4);
697 assert(log2_int_ceil(u32, 10) == 4);711 testing.expect(log2_int_ceil(u32, 10) == 4);
698}712}
699713
700fn testFloorPowerOfTwo() void {714fn testFloorPowerOfTwo() void {
701 assert(floorPowerOfTwo(u32, 63) == 32);715 testing.expect(floorPowerOfTwo(u32, 63) == 32);
702 assert(floorPowerOfTwo(u32, 64) == 64);716 testing.expect(floorPowerOfTwo(u32, 64) == 64);
703 assert(floorPowerOfTwo(u32, 65) == 64);717 testing.expect(floorPowerOfTwo(u32, 65) == 64);
704 assert(floorPowerOfTwo(u4, 7) == 4);718 testing.expect(floorPowerOfTwo(u4, 7) == 4);
705 assert(floorPowerOfTwo(u4, 8) == 8);719 testing.expect(floorPowerOfTwo(u4, 8) == 8);
706 assert(floorPowerOfTwo(u4, 9) == 8);720 testing.expect(floorPowerOfTwo(u4, 9) == 8);
707}721}
708722
709pub fn lossyCast(comptime T: type, value: var) T {723pub fn lossyCast(comptime T: type, value: var) T {
...@@ -719,7 +733,7 @@ pub fn lossyCast(comptime T: type, value: var) T {...@@ -719,7 +733,7 @@ pub fn lossyCast(comptime T: type, value: var) T {
719test "math.f64_min" {733test "math.f64_min" {
720 const f64_min_u64 = 0x0010000000000000;734 const f64_min_u64 = 0x0010000000000000;
721 const fmin: f64 = f64_min;735 const fmin: f64 = f64_min;
722 assert(@bitCast(u64, fmin) == f64_min_u64);736 testing.expect(@bitCast(u64, fmin) == f64_min_u64);
723}737}
724738
725pub fn maxInt(comptime T: type) comptime_int {739pub fn maxInt(comptime T: type) comptime_int {
...@@ -738,36 +752,40 @@ pub fn minInt(comptime T: type) comptime_int {...@@ -738,36 +752,40 @@ pub fn minInt(comptime T: type) comptime_int {
738}752}
739753
740test "minInt and maxInt" {754test "minInt and maxInt" {
741 assert(maxInt(u0) == 0);755 testing.expect(maxInt(u0) == 0);
742 assert(maxInt(u1) == 1);756 testing.expect(maxInt(u1) == 1);
743 assert(maxInt(u8) == 255);757 testing.expect(maxInt(u8) == 255);
744 assert(maxInt(u16) == 65535);758 testing.expect(maxInt(u16) == 65535);
745 assert(maxInt(u32) == 4294967295);759 testing.expect(maxInt(u32) == 4294967295);
746 assert(maxInt(u64) == 18446744073709551615);760 testing.expect(maxInt(u64) == 18446744073709551615);
747761 testing.expect(maxInt(u128) == 340282366920938463463374607431768211455);
748 assert(maxInt(i0) == 0);762
749 assert(maxInt(i1) == 0);763 testing.expect(maxInt(i0) == 0);
750 assert(maxInt(i8) == 127);764 testing.expect(maxInt(i1) == 0);
751 assert(maxInt(i16) == 32767);765 testing.expect(maxInt(i8) == 127);
752 assert(maxInt(i32) == 2147483647);766 testing.expect(maxInt(i16) == 32767);
753 assert(maxInt(i63) == 4611686018427387903);767 testing.expect(maxInt(i32) == 2147483647);
754 assert(maxInt(i64) == 9223372036854775807);768 testing.expect(maxInt(i63) == 4611686018427387903);
755769 testing.expect(maxInt(i64) == 9223372036854775807);
756 assert(minInt(u0) == 0);770 testing.expect(maxInt(i128) == 170141183460469231731687303715884105727);
757 assert(minInt(u1) == 0);771
758 assert(minInt(u8) == 0);772 testing.expect(minInt(u0) == 0);
759 assert(minInt(u16) == 0);773 testing.expect(minInt(u1) == 0);
760 assert(minInt(u32) == 0);774 testing.expect(minInt(u8) == 0);
761 assert(minInt(u63) == 0);775 testing.expect(minInt(u16) == 0);
762 assert(minInt(u64) == 0);776 testing.expect(minInt(u32) == 0);
763777 testing.expect(minInt(u63) == 0);
764 assert(minInt(i0) == 0);778 testing.expect(minInt(u64) == 0);
765 assert(minInt(i1) == -1);779 testing.expect(minInt(u128) == 0);
766 assert(minInt(i8) == -128);780
767 assert(minInt(i16) == -32768);781 testing.expect(minInt(i0) == 0);
768 assert(minInt(i32) == -2147483648);782 testing.expect(minInt(i1) == -1);
769 assert(minInt(i63) == -4611686018427387904);783 testing.expect(minInt(i8) == -128);
770 assert(minInt(i64) == -9223372036854775808);784 testing.expect(minInt(i16) == -32768);
785 testing.expect(minInt(i32) == -2147483648);
786 testing.expect(minInt(i63) == -4611686018427387904);
787 testing.expect(minInt(i64) == -9223372036854775808);
788 testing.expect(minInt(i128) == -170141183460469231731687303715884105728);
771}789}
772790
773test "max value type" {791test "max value type" {
...@@ -775,5 +793,5 @@ test "max value type" {...@@ -775,5 +793,5 @@ test "max value type" {
775 // u32 would not work. But since the value is a number literal,793 // u32 would not work. But since the value is a number literal,
776 // it works fine.794 // it works fine.
777 const x: u32 = maxInt(i32);795 const x: u32 = maxInt(i32);
778 assert(x == 2147483647);796 testing.expect(x == 2147483647);
779}797}
std/math/inf.zig+4-3
...@@ -3,9 +3,10 @@ const math = std.math;...@@ -3,9 +3,10 @@ const math = std.math;
33
4pub fn inf(comptime T: type) T {4pub fn inf(comptime T: type) T {
5 return switch (T) {5 return switch (T) {
6 f16 => @bitCast(f16, math.inf_u16),6 f16 => math.inf_f16,
7 f32 => @bitCast(f32, math.inf_u32),7 f32 => math.inf_f32,
8 f64 => @bitCast(f64, math.inf_u64),8 f64 => math.inf_f64,
9 f128 => math.inf_f128,
9 else => @compileError("inf not implemented for " ++ @typeName(T)),10 else => @compileError("inf not implemented for " ++ @typeName(T)),
10 };11 };
11}12}
std/math/isfinite.zig+13-13
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const std = @import("../index.zig");1const std = @import("../index.zig");
2const math = std.math;2const math = std.math;
3const assert = std.debug.assert;3const expect = std.testing.expect;
4const maxInt = std.math.maxInt;4const maxInt = std.math.maxInt;
55
6pub fn isFinite(x: var) bool {6pub fn isFinite(x: var) bool {
...@@ -25,16 +25,16 @@ pub fn isFinite(x: var) bool {...@@ -25,16 +25,16 @@ pub fn isFinite(x: var) bool {
25}25}
2626
27test "math.isFinite" {27test "math.isFinite" {
28 assert(isFinite(f16(0.0)));28 expect(isFinite(f16(0.0)));
29 assert(isFinite(f16(-0.0)));29 expect(isFinite(f16(-0.0)));
30 assert(isFinite(f32(0.0)));30 expect(isFinite(f32(0.0)));
31 assert(isFinite(f32(-0.0)));31 expect(isFinite(f32(-0.0)));
32 assert(isFinite(f64(0.0)));32 expect(isFinite(f64(0.0)));
33 assert(isFinite(f64(-0.0)));33 expect(isFinite(f64(-0.0)));
34 assert(!isFinite(math.inf(f16)));34 expect(!isFinite(math.inf(f16)));
35 assert(!isFinite(-math.inf(f16)));35 expect(!isFinite(-math.inf(f16)));
36 assert(!isFinite(math.inf(f32)));36 expect(!isFinite(math.inf(f32)));
37 assert(!isFinite(-math.inf(f32)));37 expect(!isFinite(-math.inf(f32)));
38 assert(!isFinite(math.inf(f64)));38 expect(!isFinite(math.inf(f64)));
39 assert(!isFinite(-math.inf(f64)));39 expect(!isFinite(-math.inf(f64)));
40}40}
std/math/isinf.zig+59-37
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const std = @import("../index.zig");1const std = @import("../index.zig");
2const math = std.math;2const math = std.math;
3const assert = std.debug.assert;3const expect = std.testing.expect;
4const maxInt = std.math.maxInt;4const maxInt = std.math.maxInt;
55
6pub fn isInf(x: var) bool {6pub fn isInf(x: var) bool {
...@@ -18,6 +18,10 @@ pub fn isInf(x: var) bool {...@@ -18,6 +18,10 @@ pub fn isInf(x: var) bool {
18 const bits = @bitCast(u64, x);18 const bits = @bitCast(u64, x);
19 return bits & (maxInt(u64) >> 1) == (0x7FF << 52);19 return bits & (maxInt(u64) >> 1) == (0x7FF << 52);
20 },20 },
21 f128 => {
22 const bits = @bitCast(u128, x);
23 return bits & (maxInt(u128) >> 1) == (0x7FFF << 112);
24 },
21 else => {25 else => {
22 @compileError("isInf not implemented for " ++ @typeName(T));26 @compileError("isInf not implemented for " ++ @typeName(T));
23 },27 },
...@@ -36,6 +40,9 @@ pub fn isPositiveInf(x: var) bool {...@@ -36,6 +40,9 @@ pub fn isPositiveInf(x: var) bool {
36 f64 => {40 f64 => {
37 return @bitCast(u64, x) == 0x7FF << 52;41 return @bitCast(u64, x) == 0x7FF << 52;
38 },42 },
43 f128 => {
44 return @bitCast(u128, x) == 0x7FFF << 112;
45 },
39 else => {46 else => {
40 @compileError("isPositiveInf not implemented for " ++ @typeName(T));47 @compileError("isPositiveInf not implemented for " ++ @typeName(T));
41 },48 },
...@@ -54,6 +61,9 @@ pub fn isNegativeInf(x: var) bool {...@@ -54,6 +61,9 @@ pub fn isNegativeInf(x: var) bool {
54 f64 => {61 f64 => {
55 return @bitCast(u64, x) == 0xFFF << 52;62 return @bitCast(u64, x) == 0xFFF << 52;
56 },63 },
64 f128 => {
65 return @bitCast(u128, x) == 0xFFFF << 112;
66 },
57 else => {67 else => {
58 @compileError("isNegativeInf not implemented for " ++ @typeName(T));68 @compileError("isNegativeInf not implemented for " ++ @typeName(T));
59 },69 },
...@@ -61,46 +71,58 @@ pub fn isNegativeInf(x: var) bool {...@@ -61,46 +71,58 @@ pub fn isNegativeInf(x: var) bool {
61}71}
6272
63test "math.isInf" {73test "math.isInf" {
64 assert(!isInf(f16(0.0)));74 expect(!isInf(f16(0.0)));
65 assert(!isInf(f16(-0.0)));75 expect(!isInf(f16(-0.0)));
66 assert(!isInf(f32(0.0)));76 expect(!isInf(f32(0.0)));
67 assert(!isInf(f32(-0.0)));77 expect(!isInf(f32(-0.0)));
68 assert(!isInf(f64(0.0)));78 expect(!isInf(f64(0.0)));
69 assert(!isInf(f64(-0.0)));79 expect(!isInf(f64(-0.0)));
70 assert(isInf(math.inf(f16)));80 expect(!isInf(f128(0.0)));
71 assert(isInf(-math.inf(f16)));81 expect(!isInf(f128(-0.0)));
72 assert(isInf(math.inf(f32)));82 expect(isInf(math.inf(f16)));
73 assert(isInf(-math.inf(f32)));83 expect(isInf(-math.inf(f16)));
74 assert(isInf(math.inf(f64)));84 expect(isInf(math.inf(f32)));
75 assert(isInf(-math.inf(f64)));85 expect(isInf(-math.inf(f32)));
86 expect(isInf(math.inf(f64)));
87 expect(isInf(-math.inf(f64)));
88 expect(isInf(math.inf(f128)));
89 expect(isInf(-math.inf(f128)));
76}90}
7791
78test "math.isPositiveInf" {92test "math.isPositiveInf" {
79 assert(!isPositiveInf(f16(0.0)));93 expect(!isPositiveInf(f16(0.0)));
80 assert(!isPositiveInf(f16(-0.0)));94 expect(!isPositiveInf(f16(-0.0)));
81 assert(!isPositiveInf(f32(0.0)));95 expect(!isPositiveInf(f32(0.0)));
82 assert(!isPositiveInf(f32(-0.0)));96 expect(!isPositiveInf(f32(-0.0)));
83 assert(!isPositiveInf(f64(0.0)));97 expect(!isPositiveInf(f64(0.0)));
84 assert(!isPositiveInf(f64(-0.0)));98 expect(!isPositiveInf(f64(-0.0)));
85 assert(isPositiveInf(math.inf(f16)));99 expect(!isPositiveInf(f128(0.0)));
86 assert(!isPositiveInf(-math.inf(f16)));100 expect(!isPositiveInf(f128(-0.0)));
87 assert(isPositiveInf(math.inf(f32)));101 expect(isPositiveInf(math.inf(f16)));
88 assert(!isPositiveInf(-math.inf(f32)));102 expect(!isPositiveInf(-math.inf(f16)));
89 assert(isPositiveInf(math.inf(f64)));103 expect(isPositiveInf(math.inf(f32)));
90 assert(!isPositiveInf(-math.inf(f64)));104 expect(!isPositiveInf(-math.inf(f32)));
105 expect(isPositiveInf(math.inf(f64)));
106 expect(!isPositiveInf(-math.inf(f64)));
107 expect(isPositiveInf(math.inf(f128)));
108 expect(!isPositiveInf(-math.inf(f128)));
91}109}
92110
93test "math.isNegativeInf" {111test "math.isNegativeInf" {
94 assert(!isNegativeInf(f16(0.0)));112 expect(!isNegativeInf(f16(0.0)));
95 assert(!isNegativeInf(f16(-0.0)));113 expect(!isNegativeInf(f16(-0.0)));
96 assert(!isNegativeInf(f32(0.0)));114 expect(!isNegativeInf(f32(0.0)));
97 assert(!isNegativeInf(f32(-0.0)));115 expect(!isNegativeInf(f32(-0.0)));
98 assert(!isNegativeInf(f64(0.0)));116 expect(!isNegativeInf(f64(0.0)));
99 assert(!isNegativeInf(f64(-0.0)));117 expect(!isNegativeInf(f64(-0.0)));
100 assert(!isNegativeInf(math.inf(f16)));118 expect(!isNegativeInf(f128(0.0)));
101 assert(isNegativeInf(-math.inf(f16)));119 expect(!isNegativeInf(f128(-0.0)));
102 assert(!isNegativeInf(math.inf(f32)));120 expect(!isNegativeInf(math.inf(f16)));
103 assert(isNegativeInf(-math.inf(f32)));121 expect(isNegativeInf(-math.inf(f16)));
104 assert(!isNegativeInf(math.inf(f64)));122 expect(!isNegativeInf(math.inf(f32)));
105 assert(isNegativeInf(-math.inf(f64)));123 expect(isNegativeInf(-math.inf(f32)));
124 expect(!isNegativeInf(math.inf(f64)));
125 expect(isNegativeInf(-math.inf(f64)));
126 expect(!isNegativeInf(math.inf(f128)));
127 expect(isNegativeInf(-math.inf(f128)));
106}128}
std/math/isnan.zig+13-7
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const std = @import("../index.zig");1const std = @import("../index.zig");
2const math = std.math;2const math = std.math;
3const assert = std.debug.assert;3const expect = std.testing.expect;
4const maxInt = std.math.maxInt;4const maxInt = std.math.maxInt;
55
6pub fn isNan(x: var) bool {6pub fn isNan(x: var) bool {
...@@ -18,6 +18,10 @@ pub fn isNan(x: var) bool {...@@ -18,6 +18,10 @@ pub fn isNan(x: var) bool {
18 const bits = @bitCast(u64, x);18 const bits = @bitCast(u64, x);
19 return (bits & (maxInt(u64) >> 1)) > (u64(0x7FF) << 52);19 return (bits & (maxInt(u64) >> 1)) > (u64(0x7FF) << 52);
20 },20 },
21 f128 => {
22 const bits = @bitCast(u128, x);
23 return (bits & (maxInt(u128) >> 1)) > (u128(0x7FFF) << 112);
24 },
21 else => {25 else => {
22 @compileError("isNan not implemented for " ++ @typeName(T));26 @compileError("isNan not implemented for " ++ @typeName(T));
23 },27 },
...@@ -31,10 +35,12 @@ pub fn isSignalNan(x: var) bool {...@@ -31,10 +35,12 @@ pub fn isSignalNan(x: var) bool {
31}35}
3236
33test "math.isNan" {37test "math.isNan" {
34 assert(isNan(math.nan(f16)));38 expect(isNan(math.nan(f16)));
35 assert(isNan(math.nan(f32)));39 expect(isNan(math.nan(f32)));
36 assert(isNan(math.nan(f64)));40 expect(isNan(math.nan(f64)));
37 assert(!isNan(f16(1.0)));41 expect(isNan(math.nan(f128)));
38 assert(!isNan(f32(1.0)));42 expect(!isNan(f16(1.0)));
39 assert(!isNan(f64(1.0)));43 expect(!isNan(f32(1.0)));
44 expect(!isNan(f64(1.0)));
45 expect(!isNan(f128(1.0)));
40}46}
std/math/isnormal.zig+10-10
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const std = @import("../index.zig");1const std = @import("../index.zig");
2const math = std.math;2const math = std.math;
3const assert = std.debug.assert;3const expect = std.testing.expect;
4const maxInt = std.math.maxInt;4const maxInt = std.math.maxInt;
55
6pub fn isNormal(x: var) bool {6pub fn isNormal(x: var) bool {
...@@ -25,13 +25,13 @@ pub fn isNormal(x: var) bool {...@@ -25,13 +25,13 @@ pub fn isNormal(x: var) bool {
25}25}
2626
27test "math.isNormal" {27test "math.isNormal" {
28 assert(!isNormal(math.nan(f16)));28 expect(!isNormal(math.nan(f16)));
29 assert(!isNormal(math.nan(f32)));29 expect(!isNormal(math.nan(f32)));
30 assert(!isNormal(math.nan(f64)));30 expect(!isNormal(math.nan(f64)));
31 assert(!isNormal(f16(0)));31 expect(!isNormal(f16(0)));
32 assert(!isNormal(f32(0)));32 expect(!isNormal(f32(0)));
33 assert(!isNormal(f64(0)));33 expect(!isNormal(f64(0)));
34 assert(isNormal(f16(1.0)));34 expect(isNormal(f16(1.0)));
35 assert(isNormal(f32(1.0)));35 expect(isNormal(f32(1.0)));
36 assert(isNormal(f64(1.0)));36 expect(isNormal(f64(1.0)));
37}37}
std/math/ln.zig+23-23
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
77
8const std = @import("../index.zig");8const std = @import("../index.zig");
9const math = std.math;9const math = std.math;
10const assert = std.debug.assert;10const expect = std.testing.expect;
11const builtin = @import("builtin");11const builtin = @import("builtin");
12const TypeId = builtin.TypeId;12const TypeId = builtin.TypeId;
1313
...@@ -143,42 +143,42 @@ pub fn ln_64(x_: f64) f64 {...@@ -143,42 +143,42 @@ pub fn ln_64(x_: f64) f64 {
143}143}
144144
145test "math.ln" {145test "math.ln" {
146 assert(ln(f32(0.2)) == ln_32(0.2));146 expect(ln(f32(0.2)) == ln_32(0.2));
147 assert(ln(f64(0.2)) == ln_64(0.2));147 expect(ln(f64(0.2)) == ln_64(0.2));
148}148}
149149
150test "math.ln32" {150test "math.ln32" {
151 const epsilon = 0.000001;151 const epsilon = 0.000001;
152152
153 assert(math.approxEq(f32, ln_32(0.2), -1.609438, epsilon));153 expect(math.approxEq(f32, ln_32(0.2), -1.609438, epsilon));
154 assert(math.approxEq(f32, ln_32(0.8923), -0.113953, epsilon));154 expect(math.approxEq(f32, ln_32(0.8923), -0.113953, epsilon));
155 assert(math.approxEq(f32, ln_32(1.5), 0.405465, epsilon));155 expect(math.approxEq(f32, ln_32(1.5), 0.405465, epsilon));
156 assert(math.approxEq(f32, ln_32(37.45), 3.623007, epsilon));156 expect(math.approxEq(f32, ln_32(37.45), 3.623007, epsilon));
157 assert(math.approxEq(f32, ln_32(89.123), 4.490017, epsilon));157 expect(math.approxEq(f32, ln_32(89.123), 4.490017, epsilon));
158 assert(math.approxEq(f32, ln_32(123123.234375), 11.720941, epsilon));158 expect(math.approxEq(f32, ln_32(123123.234375), 11.720941, epsilon));
159}159}
160160
161test "math.ln64" {161test "math.ln64" {
162 const epsilon = 0.000001;162 const epsilon = 0.000001;
163163
164 assert(math.approxEq(f64, ln_64(0.2), -1.609438, epsilon));164 expect(math.approxEq(f64, ln_64(0.2), -1.609438, epsilon));
165 assert(math.approxEq(f64, ln_64(0.8923), -0.113953, epsilon));165 expect(math.approxEq(f64, ln_64(0.8923), -0.113953, epsilon));
166 assert(math.approxEq(f64, ln_64(1.5), 0.405465, epsilon));166 expect(math.approxEq(f64, ln_64(1.5), 0.405465, epsilon));
167 assert(math.approxEq(f64, ln_64(37.45), 3.623007, epsilon));167 expect(math.approxEq(f64, ln_64(37.45), 3.623007, epsilon));
168 assert(math.approxEq(f64, ln_64(89.123), 4.490017, epsilon));168 expect(math.approxEq(f64, ln_64(89.123), 4.490017, epsilon));
169 assert(math.approxEq(f64, ln_64(123123.234375), 11.720941, epsilon));169 expect(math.approxEq(f64, ln_64(123123.234375), 11.720941, epsilon));
170}170}
171171
172test "math.ln32.special" {172test "math.ln32.special" {
173 assert(math.isPositiveInf(ln_32(math.inf(f32))));173 expect(math.isPositiveInf(ln_32(math.inf(f32))));
174 assert(math.isNegativeInf(ln_32(0.0)));174 expect(math.isNegativeInf(ln_32(0.0)));
175 assert(math.isNan(ln_32(-1.0)));175 expect(math.isNan(ln_32(-1.0)));
176 assert(math.isNan(ln_32(math.nan(f32))));176 expect(math.isNan(ln_32(math.nan(f32))));
177}177}
178178
179test "math.ln64.special" {179test "math.ln64.special" {
180 assert(math.isPositiveInf(ln_64(math.inf(f64))));180 expect(math.isPositiveInf(ln_64(math.inf(f64))));
181 assert(math.isNegativeInf(ln_64(0.0)));181 expect(math.isNegativeInf(ln_64(0.0)));
182 assert(math.isNan(ln_64(-1.0)));182 expect(math.isNan(ln_64(-1.0)));
183 assert(math.isNan(ln_64(math.nan(f64))));183 expect(math.isNan(ln_64(math.nan(f64))));
184}184}
std/math/log.zig+13-13
...@@ -2,7 +2,7 @@ const std = @import("../index.zig");...@@ -2,7 +2,7 @@ const std = @import("../index.zig");
2const math = std.math;2const math = std.math;
3const builtin = @import("builtin");3const builtin = @import("builtin");
4const TypeId = builtin.TypeId;4const TypeId = builtin.TypeId;
5const assert = std.debug.assert;5const expect = std.testing.expect;
66
7pub fn log(comptime T: type, base: T, x: T) T {7pub fn log(comptime T: type, base: T, x: T) T {
8 if (base == 2) {8 if (base == 2) {
...@@ -41,25 +41,25 @@ pub fn log(comptime T: type, base: T, x: T) T {...@@ -41,25 +41,25 @@ pub fn log(comptime T: type, base: T, x: T) T {
41}41}
4242
43test "math.log integer" {43test "math.log integer" {
44 assert(log(u8, 2, 0x1) == 0);44 expect(log(u8, 2, 0x1) == 0);
45 assert(log(u8, 2, 0x2) == 1);45 expect(log(u8, 2, 0x2) == 1);
46 assert(log(i16, 2, 0x72) == 6);46 expect(log(i16, 2, 0x72) == 6);
47 assert(log(u32, 2, 0xFFFFFF) == 23);47 expect(log(u32, 2, 0xFFFFFF) == 23);
48 assert(log(u64, 2, 0x7FF0123456789ABC) == 62);48 expect(log(u64, 2, 0x7FF0123456789ABC) == 62);
49}49}
5050
51test "math.log float" {51test "math.log float" {
52 const epsilon = 0.000001;52 const epsilon = 0.000001;
5353
54 assert(math.approxEq(f32, log(f32, 6, 0.23947), -0.797723, epsilon));54 expect(math.approxEq(f32, log(f32, 6, 0.23947), -0.797723, epsilon));
55 assert(math.approxEq(f32, log(f32, 89, 0.23947), -0.318432, epsilon));55 expect(math.approxEq(f32, log(f32, 89, 0.23947), -0.318432, epsilon));
56 assert(math.approxEq(f64, log(f64, 123897, 12389216414), 1.981724596, epsilon));56 expect(math.approxEq(f64, log(f64, 123897, 12389216414), 1.981724596, epsilon));
57}57}
5858
59test "math.log float_special" {59test "math.log float_special" {
60 assert(log(f32, 2, 0.2301974) == math.log2(f32(0.2301974)));60 expect(log(f32, 2, 0.2301974) == math.log2(f32(0.2301974)));
61 assert(log(f32, 10, 0.2301974) == math.log10(f32(0.2301974)));61 expect(log(f32, 10, 0.2301974) == math.log10(f32(0.2301974)));
6262
63 assert(log(f64, 2, 213.23019799993) == math.log2(f64(213.23019799993)));63 expect(log(f64, 2, 213.23019799993) == math.log2(f64(213.23019799993)));
64 assert(log(f64, 10, 213.23019799993) == math.log10(f64(213.23019799993)));64 expect(log(f64, 10, 213.23019799993) == math.log10(f64(213.23019799993)));
65}65}
std/math/log10.zig+23-23
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
77
8const std = @import("../index.zig");8const std = @import("../index.zig");
9const math = std.math;9const math = std.math;
10const assert = std.debug.assert;10const testing = std.testing;
11const builtin = @import("builtin");11const builtin = @import("builtin");
12const TypeId = builtin.TypeId;12const TypeId = builtin.TypeId;
13const maxInt = std.math.maxInt;13const maxInt = std.math.maxInt;
...@@ -171,42 +171,42 @@ pub fn log10_64(x_: f64) f64 {...@@ -171,42 +171,42 @@ pub fn log10_64(x_: f64) f64 {
171}171}
172172
173test "math.log10" {173test "math.log10" {
174 assert(log10(f32(0.2)) == log10_32(0.2));174 testing.expect(log10(f32(0.2)) == log10_32(0.2));
175 assert(log10(f64(0.2)) == log10_64(0.2));175 testing.expect(log10(f64(0.2)) == log10_64(0.2));
176}176}
177177
178test "math.log10_32" {178test "math.log10_32" {
179 const epsilon = 0.000001;179 const epsilon = 0.000001;
180180
181 assert(math.approxEq(f32, log10_32(0.2), -0.698970, epsilon));181 testing.expect(math.approxEq(f32, log10_32(0.2), -0.698970, epsilon));
182 assert(math.approxEq(f32, log10_32(0.8923), -0.049489, epsilon));182 testing.expect(math.approxEq(f32, log10_32(0.8923), -0.049489, epsilon));
183 assert(math.approxEq(f32, log10_32(1.5), 0.176091, epsilon));183 testing.expect(math.approxEq(f32, log10_32(1.5), 0.176091, epsilon));
184 assert(math.approxEq(f32, log10_32(37.45), 1.573452, epsilon));184 testing.expect(math.approxEq(f32, log10_32(37.45), 1.573452, epsilon));
185 assert(math.approxEq(f32, log10_32(89.123), 1.94999, epsilon));185 testing.expect(math.approxEq(f32, log10_32(89.123), 1.94999, epsilon));
186 assert(math.approxEq(f32, log10_32(123123.234375), 5.09034, epsilon));186 testing.expect(math.approxEq(f32, log10_32(123123.234375), 5.09034, epsilon));
187}187}
188188
189test "math.log10_64" {189test "math.log10_64" {
190 const epsilon = 0.000001;190 const epsilon = 0.000001;
191191
192 assert(math.approxEq(f64, log10_64(0.2), -0.698970, epsilon));192 testing.expect(math.approxEq(f64, log10_64(0.2), -0.698970, epsilon));
193 assert(math.approxEq(f64, log10_64(0.8923), -0.049489, epsilon));193 testing.expect(math.approxEq(f64, log10_64(0.8923), -0.049489, epsilon));
194 assert(math.approxEq(f64, log10_64(1.5), 0.176091, epsilon));194 testing.expect(math.approxEq(f64, log10_64(1.5), 0.176091, epsilon));
195 assert(math.approxEq(f64, log10_64(37.45), 1.573452, epsilon));195 testing.expect(math.approxEq(f64, log10_64(37.45), 1.573452, epsilon));
196 assert(math.approxEq(f64, log10_64(89.123), 1.94999, epsilon));196 testing.expect(math.approxEq(f64, log10_64(89.123), 1.94999, epsilon));
197 assert(math.approxEq(f64, log10_64(123123.234375), 5.09034, epsilon));197 testing.expect(math.approxEq(f64, log10_64(123123.234375), 5.09034, epsilon));
198}198}
199199
200test "math.log10_32.special" {200test "math.log10_32.special" {
201 assert(math.isPositiveInf(log10_32(math.inf(f32))));201 testing.expect(math.isPositiveInf(log10_32(math.inf(f32))));
202 assert(math.isNegativeInf(log10_32(0.0)));202 testing.expect(math.isNegativeInf(log10_32(0.0)));
203 assert(math.isNan(log10_32(-1.0)));203 testing.expect(math.isNan(log10_32(-1.0)));
204 assert(math.isNan(log10_32(math.nan(f32))));204 testing.expect(math.isNan(log10_32(math.nan(f32))));
205}205}
206206
207test "math.log10_64.special" {207test "math.log10_64.special" {
208 assert(math.isPositiveInf(log10_64(math.inf(f64))));208 testing.expect(math.isPositiveInf(log10_64(math.inf(f64))));
209 assert(math.isNegativeInf(log10_64(0.0)));209 testing.expect(math.isNegativeInf(log10_64(0.0)));
210 assert(math.isNan(log10_64(-1.0)));210 testing.expect(math.isNan(log10_64(-1.0)));
211 assert(math.isNan(log10_64(math.nan(f64))));211 testing.expect(math.isNan(log10_64(math.nan(f64))));
212}212}
std/math/log1p.zig+29-29
...@@ -9,7 +9,7 @@...@@ -9,7 +9,7 @@
9const builtin = @import("builtin");9const builtin = @import("builtin");
10const std = @import("../index.zig");10const std = @import("../index.zig");
11const math = std.math;11const math = std.math;
12const assert = std.debug.assert;12const expect = std.testing.expect;
1313
14pub fn log1p(x: var) @typeOf(x) {14pub fn log1p(x: var) @typeOf(x) {
15 const T = @typeOf(x);15 const T = @typeOf(x);
...@@ -177,48 +177,48 @@ fn log1p_64(x: f64) f64 {...@@ -177,48 +177,48 @@ fn log1p_64(x: f64) f64 {
177}177}
178178
179test "math.log1p" {179test "math.log1p" {
180 assert(log1p(f32(0.0)) == log1p_32(0.0));180 expect(log1p(f32(0.0)) == log1p_32(0.0));
181 assert(log1p(f64(0.0)) == log1p_64(0.0));181 expect(log1p(f64(0.0)) == log1p_64(0.0));
182}182}
183183
184test "math.log1p_32" {184test "math.log1p_32" {
185 const epsilon = 0.000001;185 const epsilon = 0.000001;
186186
187 assert(math.approxEq(f32, log1p_32(0.0), 0.0, epsilon));187 expect(math.approxEq(f32, log1p_32(0.0), 0.0, epsilon));
188 assert(math.approxEq(f32, log1p_32(0.2), 0.182322, epsilon));188 expect(math.approxEq(f32, log1p_32(0.2), 0.182322, epsilon));
189 assert(math.approxEq(f32, log1p_32(0.8923), 0.637793, epsilon));189 expect(math.approxEq(f32, log1p_32(0.8923), 0.637793, epsilon));
190 assert(math.approxEq(f32, log1p_32(1.5), 0.916291, epsilon));190 expect(math.approxEq(f32, log1p_32(1.5), 0.916291, epsilon));
191 assert(math.approxEq(f32, log1p_32(37.45), 3.649359, epsilon));191 expect(math.approxEq(f32, log1p_32(37.45), 3.649359, epsilon));
192 assert(math.approxEq(f32, log1p_32(89.123), 4.501175, epsilon));192 expect(math.approxEq(f32, log1p_32(89.123), 4.501175, epsilon));
193 assert(math.approxEq(f32, log1p_32(123123.234375), 11.720949, epsilon));193 expect(math.approxEq(f32, log1p_32(123123.234375), 11.720949, epsilon));
194}194}
195195
196test "math.log1p_64" {196test "math.log1p_64" {
197 const epsilon = 0.000001;197 const epsilon = 0.000001;
198198
199 assert(math.approxEq(f64, log1p_64(0.0), 0.0, epsilon));199 expect(math.approxEq(f64, log1p_64(0.0), 0.0, epsilon));
200 assert(math.approxEq(f64, log1p_64(0.2), 0.182322, epsilon));200 expect(math.approxEq(f64, log1p_64(0.2), 0.182322, epsilon));
201 assert(math.approxEq(f64, log1p_64(0.8923), 0.637793, epsilon));201 expect(math.approxEq(f64, log1p_64(0.8923), 0.637793, epsilon));
202 assert(math.approxEq(f64, log1p_64(1.5), 0.916291, epsilon));202 expect(math.approxEq(f64, log1p_64(1.5), 0.916291, epsilon));
203 assert(math.approxEq(f64, log1p_64(37.45), 3.649359, epsilon));203 expect(math.approxEq(f64, log1p_64(37.45), 3.649359, epsilon));
204 assert(math.approxEq(f64, log1p_64(89.123), 4.501175, epsilon));204 expect(math.approxEq(f64, log1p_64(89.123), 4.501175, epsilon));
205 assert(math.approxEq(f64, log1p_64(123123.234375), 11.720949, epsilon));205 expect(math.approxEq(f64, log1p_64(123123.234375), 11.720949, epsilon));
206}206}
207207
208test "math.log1p_32.special" {208test "math.log1p_32.special" {
209 assert(math.isPositiveInf(log1p_32(math.inf(f32))));209 expect(math.isPositiveInf(log1p_32(math.inf(f32))));
210 assert(log1p_32(0.0) == 0.0);210 expect(log1p_32(0.0) == 0.0);
211 assert(log1p_32(-0.0) == -0.0);211 expect(log1p_32(-0.0) == -0.0);
212 assert(math.isNegativeInf(log1p_32(-1.0)));212 expect(math.isNegativeInf(log1p_32(-1.0)));
213 assert(math.isNan(log1p_32(-2.0)));213 expect(math.isNan(log1p_32(-2.0)));
214 assert(math.isNan(log1p_32(math.nan(f32))));214 expect(math.isNan(log1p_32(math.nan(f32))));
215}215}
216216
217test "math.log1p_64.special" {217test "math.log1p_64.special" {
218 assert(math.isPositiveInf(log1p_64(math.inf(f64))));218 expect(math.isPositiveInf(log1p_64(math.inf(f64))));
219 assert(log1p_64(0.0) == 0.0);219 expect(log1p_64(0.0) == 0.0);
220 assert(log1p_64(-0.0) == -0.0);220 expect(log1p_64(-0.0) == -0.0);
221 assert(math.isNegativeInf(log1p_64(-1.0)));221 expect(math.isNegativeInf(log1p_64(-1.0)));
222 assert(math.isNan(log1p_64(-2.0)));222 expect(math.isNan(log1p_64(-2.0)));
223 assert(math.isNan(log1p_64(math.nan(f64))));223 expect(math.isNan(log1p_64(math.nan(f64))));
224}224}
std/math/log2.zig+21-21
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
77
8const std = @import("../index.zig");8const std = @import("../index.zig");
9const math = std.math;9const math = std.math;
10const assert = std.debug.assert;10const expect = std.testing.expect;
11const builtin = @import("builtin");11const builtin = @import("builtin");
12const TypeId = builtin.TypeId;12const TypeId = builtin.TypeId;
13const maxInt = std.math.maxInt;13const maxInt = std.math.maxInt;
...@@ -169,40 +169,40 @@ pub fn log2_64(x_: f64) f64 {...@@ -169,40 +169,40 @@ pub fn log2_64(x_: f64) f64 {
169}169}
170170
171test "math.log2" {171test "math.log2" {
172 assert(log2(f32(0.2)) == log2_32(0.2));172 expect(log2(f32(0.2)) == log2_32(0.2));
173 assert(log2(f64(0.2)) == log2_64(0.2));173 expect(log2(f64(0.2)) == log2_64(0.2));
174}174}
175175
176test "math.log2_32" {176test "math.log2_32" {
177 const epsilon = 0.000001;177 const epsilon = 0.000001;
178178
179 assert(math.approxEq(f32, log2_32(0.2), -2.321928, epsilon));179 expect(math.approxEq(f32, log2_32(0.2), -2.321928, epsilon));
180 assert(math.approxEq(f32, log2_32(0.8923), -0.164399, epsilon));180 expect(math.approxEq(f32, log2_32(0.8923), -0.164399, epsilon));
181 assert(math.approxEq(f32, log2_32(1.5), 0.584962, epsilon));181 expect(math.approxEq(f32, log2_32(1.5), 0.584962, epsilon));
182 assert(math.approxEq(f32, log2_32(37.45), 5.226894, epsilon));182 expect(math.approxEq(f32, log2_32(37.45), 5.226894, epsilon));
183 assert(math.approxEq(f32, log2_32(123123.234375), 16.909744, epsilon));183 expect(math.approxEq(f32, log2_32(123123.234375), 16.909744, epsilon));
184}184}
185185
186test "math.log2_64" {186test "math.log2_64" {
187 const epsilon = 0.000001;187 const epsilon = 0.000001;
188188
189 assert(math.approxEq(f64, log2_64(0.2), -2.321928, epsilon));189 expect(math.approxEq(f64, log2_64(0.2), -2.321928, epsilon));
190 assert(math.approxEq(f64, log2_64(0.8923), -0.164399, epsilon));190 expect(math.approxEq(f64, log2_64(0.8923), -0.164399, epsilon));
191 assert(math.approxEq(f64, log2_64(1.5), 0.584962, epsilon));191 expect(math.approxEq(f64, log2_64(1.5), 0.584962, epsilon));
192 assert(math.approxEq(f64, log2_64(37.45), 5.226894, epsilon));192 expect(math.approxEq(f64, log2_64(37.45), 5.226894, epsilon));
193 assert(math.approxEq(f64, log2_64(123123.234375), 16.909744, epsilon));193 expect(math.approxEq(f64, log2_64(123123.234375), 16.909744, epsilon));
194}194}
195195
196test "math.log2_32.special" {196test "math.log2_32.special" {
197 assert(math.isPositiveInf(log2_32(math.inf(f32))));197 expect(math.isPositiveInf(log2_32(math.inf(f32))));
198 assert(math.isNegativeInf(log2_32(0.0)));198 expect(math.isNegativeInf(log2_32(0.0)));
199 assert(math.isNan(log2_32(-1.0)));199 expect(math.isNan(log2_32(-1.0)));
200 assert(math.isNan(log2_32(math.nan(f32))));200 expect(math.isNan(log2_32(math.nan(f32))));
201}201}
202202
203test "math.log2_64.special" {203test "math.log2_64.special" {
204 assert(math.isPositiveInf(log2_64(math.inf(f64))));204 expect(math.isPositiveInf(log2_64(math.inf(f64))));
205 assert(math.isNegativeInf(log2_64(0.0)));205 expect(math.isNegativeInf(log2_64(0.0)));
206 assert(math.isNan(log2_64(-1.0)));206 expect(math.isNan(log2_64(-1.0)));
207 assert(math.isNan(log2_64(math.nan(f64))));207 expect(math.isNan(log2_64(math.nan(f64))));
208}208}
std/math/modf.zig+29-29
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
55
6const std = @import("../index.zig");6const std = @import("../index.zig");
7const math = std.math;7const math = std.math;
8const assert = std.debug.assert;8const expect = std.testing.expect;
9const maxInt = std.math.maxInt;9const maxInt = std.math.maxInt;
1010
11fn modf_result(comptime T: type) type {11fn modf_result(comptime T: type) type {
...@@ -119,11 +119,11 @@ test "math.modf" {...@@ -119,11 +119,11 @@ test "math.modf" {
119 const a = modf(f32(1.0));119 const a = modf(f32(1.0));
120 const b = modf32(1.0);120 const b = modf32(1.0);
121 // NOTE: No struct comparison on generic return type function? non-named, makes sense, but still.121 // NOTE: No struct comparison on generic return type function? non-named, makes sense, but still.
122 assert(a.ipart == b.ipart and a.fpart == b.fpart);122 expect(a.ipart == b.ipart and a.fpart == b.fpart);
123123
124 const c = modf(f64(1.0));124 const c = modf(f64(1.0));
125 const d = modf64(1.0);125 const d = modf64(1.0);
126 assert(a.ipart == b.ipart and a.fpart == b.fpart);126 expect(a.ipart == b.ipart and a.fpart == b.fpart);
127}127}
128128
129test "math.modf32" {129test "math.modf32" {
...@@ -131,24 +131,24 @@ test "math.modf32" {...@@ -131,24 +131,24 @@ test "math.modf32" {
131 var r: modf32_result = undefined;131 var r: modf32_result = undefined;
132132
133 r = modf32(1.0);133 r = modf32(1.0);
134 assert(math.approxEq(f32, r.ipart, 1.0, epsilon));134 expect(math.approxEq(f32, r.ipart, 1.0, epsilon));
135 assert(math.approxEq(f32, r.fpart, 0.0, epsilon));135 expect(math.approxEq(f32, r.fpart, 0.0, epsilon));
136136
137 r = modf32(2.545);137 r = modf32(2.545);
138 assert(math.approxEq(f32, r.ipart, 2.0, epsilon));138 expect(math.approxEq(f32, r.ipart, 2.0, epsilon));
139 assert(math.approxEq(f32, r.fpart, 0.545, epsilon));139 expect(math.approxEq(f32, r.fpart, 0.545, epsilon));
140140
141 r = modf32(3.978123);141 r = modf32(3.978123);
142 assert(math.approxEq(f32, r.ipart, 3.0, epsilon));142 expect(math.approxEq(f32, r.ipart, 3.0, epsilon));
143 assert(math.approxEq(f32, r.fpart, 0.978123, epsilon));143 expect(math.approxEq(f32, r.fpart, 0.978123, epsilon));
144144
145 r = modf32(43874.3);145 r = modf32(43874.3);
146 assert(math.approxEq(f32, r.ipart, 43874, epsilon));146 expect(math.approxEq(f32, r.ipart, 43874, epsilon));
147 assert(math.approxEq(f32, r.fpart, 0.300781, epsilon));147 expect(math.approxEq(f32, r.fpart, 0.300781, epsilon));
148148
149 r = modf32(1234.340780);149 r = modf32(1234.340780);
150 assert(math.approxEq(f32, r.ipart, 1234, epsilon));150 expect(math.approxEq(f32, r.ipart, 1234, epsilon));
151 assert(math.approxEq(f32, r.fpart, 0.340820, epsilon));151 expect(math.approxEq(f32, r.fpart, 0.340820, epsilon));
152}152}
153153
154test "math.modf64" {154test "math.modf64" {
...@@ -156,48 +156,48 @@ test "math.modf64" {...@@ -156,48 +156,48 @@ test "math.modf64" {
156 var r: modf64_result = undefined;156 var r: modf64_result = undefined;
157157
158 r = modf64(1.0);158 r = modf64(1.0);
159 assert(math.approxEq(f64, r.ipart, 1.0, epsilon));159 expect(math.approxEq(f64, r.ipart, 1.0, epsilon));
160 assert(math.approxEq(f64, r.fpart, 0.0, epsilon));160 expect(math.approxEq(f64, r.fpart, 0.0, epsilon));
161161
162 r = modf64(2.545);162 r = modf64(2.545);
163 assert(math.approxEq(f64, r.ipart, 2.0, epsilon));163 expect(math.approxEq(f64, r.ipart, 2.0, epsilon));
164 assert(math.approxEq(f64, r.fpart, 0.545, epsilon));164 expect(math.approxEq(f64, r.fpart, 0.545, epsilon));
165165
166 r = modf64(3.978123);166 r = modf64(3.978123);
167 assert(math.approxEq(f64, r.ipart, 3.0, epsilon));167 expect(math.approxEq(f64, r.ipart, 3.0, epsilon));
168 assert(math.approxEq(f64, r.fpart, 0.978123, epsilon));168 expect(math.approxEq(f64, r.fpart, 0.978123, epsilon));
169169
170 r = modf64(43874.3);170 r = modf64(43874.3);
171 assert(math.approxEq(f64, r.ipart, 43874, epsilon));171 expect(math.approxEq(f64, r.ipart, 43874, epsilon));
172 assert(math.approxEq(f64, r.fpart, 0.3, epsilon));172 expect(math.approxEq(f64, r.fpart, 0.3, epsilon));
173173
174 r = modf64(1234.340780);174 r = modf64(1234.340780);
175 assert(math.approxEq(f64, r.ipart, 1234, epsilon));175 expect(math.approxEq(f64, r.ipart, 1234, epsilon));
176 assert(math.approxEq(f64, r.fpart, 0.340780, epsilon));176 expect(math.approxEq(f64, r.fpart, 0.340780, epsilon));
177}177}
178178
179test "math.modf32.special" {179test "math.modf32.special" {
180 var r: modf32_result = undefined;180 var r: modf32_result = undefined;
181181
182 r = modf32(math.inf(f32));182 r = modf32(math.inf(f32));
183 assert(math.isPositiveInf(r.ipart) and math.isNan(r.fpart));183 expect(math.isPositiveInf(r.ipart) and math.isNan(r.fpart));
184184
185 r = modf32(-math.inf(f32));185 r = modf32(-math.inf(f32));
186 assert(math.isNegativeInf(r.ipart) and math.isNan(r.fpart));186 expect(math.isNegativeInf(r.ipart) and math.isNan(r.fpart));
187187
188 r = modf32(math.nan(f32));188 r = modf32(math.nan(f32));
189 assert(math.isNan(r.ipart) and math.isNan(r.fpart));189 expect(math.isNan(r.ipart) and math.isNan(r.fpart));
190}190}
191191
192test "math.modf64.special" {192test "math.modf64.special" {
193 var r: modf64_result = undefined;193 var r: modf64_result = undefined;
194194
195 r = modf64(math.inf(f64));195 r = modf64(math.inf(f64));
196 assert(math.isPositiveInf(r.ipart) and math.isNan(r.fpart));196 expect(math.isPositiveInf(r.ipart) and math.isNan(r.fpart));
197197
198 r = modf64(-math.inf(f64));198 r = modf64(-math.inf(f64));
199 assert(math.isNegativeInf(r.ipart) and math.isNan(r.fpart));199 expect(math.isNegativeInf(r.ipart) and math.isNan(r.fpart));
200200
201 r = modf64(math.nan(f64));201 r = modf64(math.nan(f64));
202 assert(math.isNan(r.ipart) and math.isNan(r.fpart));202 expect(math.isNan(r.ipart) and math.isNan(r.fpart));
203}203}
std/math/nan.zig+4-3
...@@ -2,9 +2,10 @@ const math = @import("index.zig");...@@ -2,9 +2,10 @@ const math = @import("index.zig");
22
3pub fn nan(comptime T: type) T {3pub fn nan(comptime T: type) T {
4 return switch (T) {4 return switch (T) {
5 f16 => @bitCast(f16, math.nan_u16),5 f16 => math.nan_f16,
6 f32 => @bitCast(f32, math.nan_u32),6 f32 => math.nan_f32,
7 f64 => @bitCast(f64, math.nan_u64),7 f64 => math.nan_f64,
8 f128 => math.nan_f128,
8 else => @compileError("nan not implemented for " ++ @typeName(T)),9 else => @compileError("nan not implemented for " ++ @typeName(T)),
9 };10 };
10}11}
std/math/pow.zig+48-48
...@@ -24,7 +24,7 @@...@@ -24,7 +24,7 @@
24const builtin = @import("builtin");24const builtin = @import("builtin");
25const std = @import("../index.zig");25const std = @import("../index.zig");
26const math = std.math;26const math = std.math;
27const assert = std.debug.assert;27const expect = std.testing.expect;
2828
29// This implementation is taken from the go stlib, musl is a bit more complex.29// This implementation is taken from the go stlib, musl is a bit more complex.
30pub fn pow(comptime T: type, x: T, y: T) T {30pub fn pow(comptime T: type, x: T, y: T) T {
...@@ -179,56 +179,56 @@ fn isOddInteger(x: f64) bool {...@@ -179,56 +179,56 @@ fn isOddInteger(x: f64) bool {
179test "math.pow" {179test "math.pow" {
180 const epsilon = 0.000001;180 const epsilon = 0.000001;
181181
182 assert(math.approxEq(f32, pow(f32, 0.0, 3.3), 0.0, epsilon));182 expect(math.approxEq(f32, pow(f32, 0.0, 3.3), 0.0, epsilon));
183 assert(math.approxEq(f32, pow(f32, 0.8923, 3.3), 0.686572, epsilon));183 expect(math.approxEq(f32, pow(f32, 0.8923, 3.3), 0.686572, epsilon));
184 assert(math.approxEq(f32, pow(f32, 0.2, 3.3), 0.004936, epsilon));184 expect(math.approxEq(f32, pow(f32, 0.2, 3.3), 0.004936, epsilon));
185 assert(math.approxEq(f32, pow(f32, 1.5, 3.3), 3.811546, epsilon));185 expect(math.approxEq(f32, pow(f32, 1.5, 3.3), 3.811546, epsilon));
186 assert(math.approxEq(f32, pow(f32, 37.45, 3.3), 155736.703125, epsilon));186 expect(math.approxEq(f32, pow(f32, 37.45, 3.3), 155736.703125, epsilon));
187 assert(math.approxEq(f32, pow(f32, 89.123, 3.3), 2722489.5, epsilon));187 expect(math.approxEq(f32, pow(f32, 89.123, 3.3), 2722489.5, epsilon));
188188
189 assert(math.approxEq(f64, pow(f64, 0.0, 3.3), 0.0, epsilon));189 expect(math.approxEq(f64, pow(f64, 0.0, 3.3), 0.0, epsilon));
190 assert(math.approxEq(f64, pow(f64, 0.8923, 3.3), 0.686572, epsilon));190 expect(math.approxEq(f64, pow(f64, 0.8923, 3.3), 0.686572, epsilon));
191 assert(math.approxEq(f64, pow(f64, 0.2, 3.3), 0.004936, epsilon));191 expect(math.approxEq(f64, pow(f64, 0.2, 3.3), 0.004936, epsilon));
192 assert(math.approxEq(f64, pow(f64, 1.5, 3.3), 3.811546, epsilon));192 expect(math.approxEq(f64, pow(f64, 1.5, 3.3), 3.811546, epsilon));
193 assert(math.approxEq(f64, pow(f64, 37.45, 3.3), 155736.7160616, epsilon));193 expect(math.approxEq(f64, pow(f64, 37.45, 3.3), 155736.7160616, epsilon));
194 assert(math.approxEq(f64, pow(f64, 89.123, 3.3), 2722490.231436, epsilon));194 expect(math.approxEq(f64, pow(f64, 89.123, 3.3), 2722490.231436, epsilon));
195}195}
196196
197test "math.pow.special" {197test "math.pow.special" {
198 const epsilon = 0.000001;198 const epsilon = 0.000001;
199199
200 assert(pow(f32, 4, 0.0) == 1.0);200 expect(pow(f32, 4, 0.0) == 1.0);
201 assert(pow(f32, 7, -0.0) == 1.0);201 expect(pow(f32, 7, -0.0) == 1.0);
202 assert(pow(f32, 45, 1.0) == 45);202 expect(pow(f32, 45, 1.0) == 45);
203 assert(pow(f32, -45, 1.0) == -45);203 expect(pow(f32, -45, 1.0) == -45);
204 assert(math.isNan(pow(f32, math.nan(f32), 5.0)));204 expect(math.isNan(pow(f32, math.nan(f32), 5.0)));
205 assert(math.isNan(pow(f32, 5.0, math.nan(f32))));205 expect(math.isNan(pow(f32, 5.0, math.nan(f32))));
206 assert(math.isPositiveInf(pow(f32, 0.0, -1.0)));206 expect(math.isPositiveInf(pow(f32, 0.0, -1.0)));
207 //assert(math.isNegativeInf(pow(f32, -0.0, -3.0))); TODO is this required?207 //expect(math.isNegativeInf(pow(f32, -0.0, -3.0))); TODO is this required?
208 assert(math.isPositiveInf(pow(f32, 0.0, -math.inf(f32))));208 expect(math.isPositiveInf(pow(f32, 0.0, -math.inf(f32))));
209 assert(math.isPositiveInf(pow(f32, -0.0, -math.inf(f32))));209 expect(math.isPositiveInf(pow(f32, -0.0, -math.inf(f32))));
210 assert(pow(f32, 0.0, math.inf(f32)) == 0.0);210 expect(pow(f32, 0.0, math.inf(f32)) == 0.0);
211 assert(pow(f32, -0.0, math.inf(f32)) == 0.0);211 expect(pow(f32, -0.0, math.inf(f32)) == 0.0);
212 assert(math.isPositiveInf(pow(f32, 0.0, -2.0)));212 expect(math.isPositiveInf(pow(f32, 0.0, -2.0)));
213 assert(math.isPositiveInf(pow(f32, -0.0, -2.0)));213 expect(math.isPositiveInf(pow(f32, -0.0, -2.0)));
214 assert(pow(f32, 0.0, 1.0) == 0.0);214 expect(pow(f32, 0.0, 1.0) == 0.0);
215 assert(pow(f32, -0.0, 1.0) == -0.0);215 expect(pow(f32, -0.0, 1.0) == -0.0);
216 assert(pow(f32, 0.0, 2.0) == 0.0);216 expect(pow(f32, 0.0, 2.0) == 0.0);
217 assert(pow(f32, -0.0, 2.0) == 0.0);217 expect(pow(f32, -0.0, 2.0) == 0.0);
218 assert(math.approxEq(f32, pow(f32, -1.0, math.inf(f32)), 1.0, epsilon));218 expect(math.approxEq(f32, pow(f32, -1.0, math.inf(f32)), 1.0, epsilon));
219 assert(math.approxEq(f32, pow(f32, -1.0, -math.inf(f32)), 1.0, epsilon));219 expect(math.approxEq(f32, pow(f32, -1.0, -math.inf(f32)), 1.0, epsilon));
220 assert(math.isPositiveInf(pow(f32, 1.2, math.inf(f32))));220 expect(math.isPositiveInf(pow(f32, 1.2, math.inf(f32))));
221 assert(math.isPositiveInf(pow(f32, -1.2, math.inf(f32))));221 expect(math.isPositiveInf(pow(f32, -1.2, math.inf(f32))));
222 assert(pow(f32, 1.2, -math.inf(f32)) == 0.0);222 expect(pow(f32, 1.2, -math.inf(f32)) == 0.0);
223 assert(pow(f32, -1.2, -math.inf(f32)) == 0.0);223 expect(pow(f32, -1.2, -math.inf(f32)) == 0.0);
224 assert(pow(f32, 0.2, math.inf(f32)) == 0.0);224 expect(pow(f32, 0.2, math.inf(f32)) == 0.0);
225 assert(pow(f32, -0.2, math.inf(f32)) == 0.0);225 expect(pow(f32, -0.2, math.inf(f32)) == 0.0);
226 assert(math.isPositiveInf(pow(f32, 0.2, -math.inf(f32))));226 expect(math.isPositiveInf(pow(f32, 0.2, -math.inf(f32))));
227 assert(math.isPositiveInf(pow(f32, -0.2, -math.inf(f32))));227 expect(math.isPositiveInf(pow(f32, -0.2, -math.inf(f32))));
228 assert(math.isPositiveInf(pow(f32, math.inf(f32), 1.0)));228 expect(math.isPositiveInf(pow(f32, math.inf(f32), 1.0)));
229 assert(pow(f32, math.inf(f32), -1.0) == 0.0);229 expect(pow(f32, math.inf(f32), -1.0) == 0.0);
230 //assert(pow(f32, -math.inf(f32), 5.0) == pow(f32, -0.0, -5.0)); TODO support negative 0?230 //expect(pow(f32, -math.inf(f32), 5.0) == pow(f32, -0.0, -5.0)); TODO support negative 0?
231 assert(pow(f32, -math.inf(f32), -5.2) == pow(f32, -0.0, 5.2));231 expect(pow(f32, -math.inf(f32), -5.2) == pow(f32, -0.0, 5.2));
232 assert(math.isNan(pow(f32, -1.0, 1.2)));232 expect(math.isNan(pow(f32, -1.0, 1.2)));
233 assert(math.isNan(pow(f32, -12.4, 78.5)));233 expect(math.isNan(pow(f32, -12.4, 78.5)));
234}234}
std/math/powi.zig+69-69
...@@ -12,7 +12,7 @@ const builtin = @import("builtin");...@@ -12,7 +12,7 @@ const builtin = @import("builtin");
12const std = @import("../index.zig");12const std = @import("../index.zig");
13const math = std.math;13const math = std.math;
14const assert = std.debug.assert;14const assert = std.debug.assert;
15const assertError = std.debug.assertError;15const testing = std.testing;
1616
17// This implementation is based on that from the rust stlib17// This implementation is based on that from the rust stlib
18pub fn powi(comptime T: type, x: T, y: T) (error{18pub fn powi(comptime T: type, x: T, y: T) (error{
...@@ -103,75 +103,75 @@ pub fn powi(comptime T: type, x: T, y: T) (error{...@@ -103,75 +103,75 @@ pub fn powi(comptime T: type, x: T, y: T) (error{
103}103}
104104
105test "math.powi" {105test "math.powi" {
106 assertError(powi(i8, -66, 6), error.Underflow);106 testing.expectError(error.Underflow, powi(i8, -66, 6));
107 assertError(powi(i16, -13, 13), error.Underflow);107 testing.expectError(error.Underflow, powi(i16, -13, 13));
108 assertError(powi(i32, -32, 21), error.Underflow);108 testing.expectError(error.Underflow, powi(i32, -32, 21));
109 assertError(powi(i64, -24, 61), error.Underflow);109 testing.expectError(error.Underflow, powi(i64, -24, 61));
110 assertError(powi(i17, -15, 15), error.Underflow);110 testing.expectError(error.Underflow, powi(i17, -15, 15));
111 assertError(powi(i42, -6, 40), error.Underflow);111 testing.expectError(error.Underflow, powi(i42, -6, 40));
112112
113 assert((try powi(i8, -5, 3)) == -125);113 testing.expect((try powi(i8, -5, 3)) == -125);
114 assert((try powi(i16, -16, 3)) == -4096);114 testing.expect((try powi(i16, -16, 3)) == -4096);
115 assert((try powi(i32, -91, 3)) == -753571);115 testing.expect((try powi(i32, -91, 3)) == -753571);
116 assert((try powi(i64, -36, 6)) == 2176782336);116 testing.expect((try powi(i64, -36, 6)) == 2176782336);
117 assert((try powi(i17, -2, 15)) == -32768);117 testing.expect((try powi(i17, -2, 15)) == -32768);
118 assert((try powi(i42, -5, 7)) == -78125);118 testing.expect((try powi(i42, -5, 7)) == -78125);
119119
120 assert((try powi(u8, 6, 2)) == 36);120 testing.expect((try powi(u8, 6, 2)) == 36);
121 assert((try powi(u16, 5, 4)) == 625);121 testing.expect((try powi(u16, 5, 4)) == 625);
122 assert((try powi(u32, 12, 6)) == 2985984);122 testing.expect((try powi(u32, 12, 6)) == 2985984);
123 assert((try powi(u64, 34, 2)) == 1156);123 testing.expect((try powi(u64, 34, 2)) == 1156);
124 assert((try powi(u17, 16, 3)) == 4096);124 testing.expect((try powi(u17, 16, 3)) == 4096);
125 assert((try powi(u42, 34, 6)) == 1544804416);125 testing.expect((try powi(u42, 34, 6)) == 1544804416);
126126
127 assertError(powi(i8, 120, 7), error.Overflow);127 testing.expectError(error.Overflow, powi(i8, 120, 7));
128 assertError(powi(i16, 73, 15), error.Overflow);128 testing.expectError(error.Overflow, powi(i16, 73, 15));
129 assertError(powi(i32, 23, 31), error.Overflow);129 testing.expectError(error.Overflow, powi(i32, 23, 31));
130 assertError(powi(i64, 68, 61), error.Overflow);130 testing.expectError(error.Overflow, powi(i64, 68, 61));
131 assertError(powi(i17, 15, 15), error.Overflow);131 testing.expectError(error.Overflow, powi(i17, 15, 15));
132 assertError(powi(i42, 121312, 41), error.Overflow);132 testing.expectError(error.Overflow, powi(i42, 121312, 41));
133133
134 assertError(powi(u8, 123, 7), error.Overflow);134 testing.expectError(error.Overflow, powi(u8, 123, 7));
135 assertError(powi(u16, 2313, 15), error.Overflow);135 testing.expectError(error.Overflow, powi(u16, 2313, 15));
136 assertError(powi(u32, 8968, 31), error.Overflow);136 testing.expectError(error.Overflow, powi(u32, 8968, 31));
137 assertError(powi(u64, 2342, 63), error.Overflow);137 testing.expectError(error.Overflow, powi(u64, 2342, 63));
138 assertError(powi(u17, 2723, 16), error.Overflow);138 testing.expectError(error.Overflow, powi(u17, 2723, 16));
139 assertError(powi(u42, 8234, 41), error.Overflow);139 testing.expectError(error.Overflow, powi(u42, 8234, 41));
140}140}
141141
142test "math.powi.special" {142test "math.powi.special" {
143 assertError(powi(i8, -2, 8), error.Underflow);143 testing.expectError(error.Underflow, powi(i8, -2, 8));
144 assertError(powi(i16, -2, 16), error.Underflow);144 testing.expectError(error.Underflow, powi(i16, -2, 16));
145 assertError(powi(i32, -2, 32), error.Underflow);145 testing.expectError(error.Underflow, powi(i32, -2, 32));
146 assertError(powi(i64, -2, 64), error.Underflow);146 testing.expectError(error.Underflow, powi(i64, -2, 64));
147 assertError(powi(i17, -2, 17), error.Underflow);147 testing.expectError(error.Underflow, powi(i17, -2, 17));
148 assertError(powi(i42, -2, 42), error.Underflow);148 testing.expectError(error.Underflow, powi(i42, -2, 42));
149149
150 assert((try powi(i8, -1, 3)) == -1);150 testing.expect((try powi(i8, -1, 3)) == -1);
151 assert((try powi(i16, -1, 2)) == 1);151 testing.expect((try powi(i16, -1, 2)) == 1);
152 assert((try powi(i32, -1, 16)) == 1);152 testing.expect((try powi(i32, -1, 16)) == 1);
153 assert((try powi(i64, -1, 6)) == 1);153 testing.expect((try powi(i64, -1, 6)) == 1);
154 assert((try powi(i17, -1, 15)) == -1);154 testing.expect((try powi(i17, -1, 15)) == -1);
155 assert((try powi(i42, -1, 7)) == -1);155 testing.expect((try powi(i42, -1, 7)) == -1);
156156
157 assert((try powi(u8, 1, 2)) == 1);157 testing.expect((try powi(u8, 1, 2)) == 1);
158 assert((try powi(u16, 1, 4)) == 1);158 testing.expect((try powi(u16, 1, 4)) == 1);
159 assert((try powi(u32, 1, 6)) == 1);159 testing.expect((try powi(u32, 1, 6)) == 1);
160 assert((try powi(u64, 1, 2)) == 1);160 testing.expect((try powi(u64, 1, 2)) == 1);
161 assert((try powi(u17, 1, 3)) == 1);161 testing.expect((try powi(u17, 1, 3)) == 1);
162 assert((try powi(u42, 1, 6)) == 1);162 testing.expect((try powi(u42, 1, 6)) == 1);
163163
164 assertError(powi(i8, 2, 7), error.Overflow);164 testing.expectError(error.Overflow, powi(i8, 2, 7));
165 assertError(powi(i16, 2, 15), error.Overflow);165 testing.expectError(error.Overflow, powi(i16, 2, 15));
166 assertError(powi(i32, 2, 31), error.Overflow);166 testing.expectError(error.Overflow, powi(i32, 2, 31));
167 assertError(powi(i64, 2, 63), error.Overflow);167 testing.expectError(error.Overflow, powi(i64, 2, 63));
168 assertError(powi(i17, 2, 16), error.Overflow);168 testing.expectError(error.Overflow, powi(i17, 2, 16));
169 assertError(powi(i42, 2, 41), error.Overflow);169 testing.expectError(error.Overflow, powi(i42, 2, 41));
170170
171 assertError(powi(u8, 2, 8), error.Overflow);171 testing.expectError(error.Overflow, powi(u8, 2, 8));
172 assertError(powi(u16, 2, 16), error.Overflow);172 testing.expectError(error.Overflow, powi(u16, 2, 16));
173 assertError(powi(u32, 2, 32), error.Overflow);173 testing.expectError(error.Overflow, powi(u32, 2, 32));
174 assertError(powi(u64, 2, 64), error.Overflow);174 testing.expectError(error.Overflow, powi(u64, 2, 64));
175 assertError(powi(u17, 2, 17), error.Overflow);175 testing.expectError(error.Overflow, powi(u17, 2, 17));
176 assertError(powi(u42, 2, 42), error.Overflow);176 testing.expectError(error.Overflow, powi(u42, 2, 42));
177}177}
std/math/round.zig+21-21
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5// - round(nan) = nan5// - round(nan) = nan
66
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const assert = std.debug.assert;8const expect = std.testing.expect;
9const std = @import("../index.zig");9const std = @import("../index.zig");
10const math = std.math;10const math = std.math;
1111
...@@ -85,36 +85,36 @@ fn round64(x_: f64) f64 {...@@ -85,36 +85,36 @@ fn round64(x_: f64) f64 {
85}85}
8686
87test "math.round" {87test "math.round" {
88 assert(round(f32(1.3)) == round32(1.3));88 expect(round(f32(1.3)) == round32(1.3));
89 assert(round(f64(1.3)) == round64(1.3));89 expect(round(f64(1.3)) == round64(1.3));
90}90}
9191
92test "math.round32" {92test "math.round32" {
93 assert(round32(1.3) == 1.0);93 expect(round32(1.3) == 1.0);
94 assert(round32(-1.3) == -1.0);94 expect(round32(-1.3) == -1.0);
95 assert(round32(0.2) == 0.0);95 expect(round32(0.2) == 0.0);
96 assert(round32(1.8) == 2.0);96 expect(round32(1.8) == 2.0);
97}97}
9898
99test "math.round64" {99test "math.round64" {
100 assert(round64(1.3) == 1.0);100 expect(round64(1.3) == 1.0);
101 assert(round64(-1.3) == -1.0);101 expect(round64(-1.3) == -1.0);
102 assert(round64(0.2) == 0.0);102 expect(round64(0.2) == 0.0);
103 assert(round64(1.8) == 2.0);103 expect(round64(1.8) == 2.0);
104}104}
105105
106test "math.round32.special" {106test "math.round32.special" {
107 assert(round32(0.0) == 0.0);107 expect(round32(0.0) == 0.0);
108 assert(round32(-0.0) == -0.0);108 expect(round32(-0.0) == -0.0);
109 assert(math.isPositiveInf(round32(math.inf(f32))));109 expect(math.isPositiveInf(round32(math.inf(f32))));
110 assert(math.isNegativeInf(round32(-math.inf(f32))));110 expect(math.isNegativeInf(round32(-math.inf(f32))));
111 assert(math.isNan(round32(math.nan(f32))));111 expect(math.isNan(round32(math.nan(f32))));
112}112}
113113
114test "math.round64.special" {114test "math.round64.special" {
115 assert(round64(0.0) == 0.0);115 expect(round64(0.0) == 0.0);
116 assert(round64(-0.0) == -0.0);116 expect(round64(-0.0) == -0.0);
117 assert(math.isPositiveInf(round64(math.inf(f64))));117 expect(math.isPositiveInf(round64(math.inf(f64))));
118 assert(math.isNegativeInf(round64(-math.inf(f64))));118 expect(math.isNegativeInf(round64(-math.inf(f64))));
119 assert(math.isNan(round64(math.nan(f64))));119 expect(math.isNan(round64(math.nan(f64))));
120}120}
std/math/scalbn.zig+5-5
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const std = @import("../index.zig");1const std = @import("../index.zig");
2const math = std.math;2const math = std.math;
3const assert = std.debug.assert;3const expect = std.testing.expect;
44
5pub fn scalbn(x: var, n: i32) @typeOf(x) {5pub fn scalbn(x: var, n: i32) @typeOf(x) {
6 const T = @typeOf(x);6 const T = @typeOf(x);
...@@ -72,14 +72,14 @@ fn scalbn64(x: f64, n_: i32) f64 {...@@ -72,14 +72,14 @@ fn scalbn64(x: f64, n_: i32) f64 {
72}72}
7373
74test "math.scalbn" {74test "math.scalbn" {
75 assert(scalbn(f32(1.5), 4) == scalbn32(1.5, 4));75 expect(scalbn(f32(1.5), 4) == scalbn32(1.5, 4));
76 assert(scalbn(f64(1.5), 4) == scalbn64(1.5, 4));76 expect(scalbn(f64(1.5), 4) == scalbn64(1.5, 4));
77}77}
7878
79test "math.scalbn32" {79test "math.scalbn32" {
80 assert(scalbn32(1.5, 4) == 24.0);80 expect(scalbn32(1.5, 4) == 24.0);
81}81}
8282
83test "math.scalbn64" {83test "math.scalbn64" {
84 assert(scalbn64(1.5, 4) == 24.0);84 expect(scalbn64(1.5, 4) == 24.0);
85}85}
std/math/signbit.zig+10-10
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const std = @import("../index.zig");1const std = @import("../index.zig");
2const math = std.math;2const math = std.math;
3const assert = std.debug.assert;3const expect = std.testing.expect;
44
5pub fn signbit(x: var) bool {5pub fn signbit(x: var) bool {
6 const T = @typeOf(x);6 const T = @typeOf(x);
...@@ -28,22 +28,22 @@ fn signbit64(x: f64) bool {...@@ -28,22 +28,22 @@ fn signbit64(x: f64) bool {
28}28}
2929
30test "math.signbit" {30test "math.signbit" {
31 assert(signbit(f16(4.0)) == signbit16(4.0));31 expect(signbit(f16(4.0)) == signbit16(4.0));
32 assert(signbit(f32(4.0)) == signbit32(4.0));32 expect(signbit(f32(4.0)) == signbit32(4.0));
33 assert(signbit(f64(4.0)) == signbit64(4.0));33 expect(signbit(f64(4.0)) == signbit64(4.0));
34}34}
3535
36test "math.signbit16" {36test "math.signbit16" {
37 assert(!signbit16(4.0));37 expect(!signbit16(4.0));
38 assert(signbit16(-3.0));38 expect(signbit16(-3.0));
39}39}
4040
41test "math.signbit32" {41test "math.signbit32" {
42 assert(!signbit32(4.0));42 expect(!signbit32(4.0));
43 assert(signbit32(-3.0));43 expect(signbit32(-3.0));
44}44}
4545
46test "math.signbit64" {46test "math.signbit64" {
47 assert(!signbit64(4.0));47 expect(!signbit64(4.0));
48 assert(signbit64(-3.0));48 expect(signbit64(-3.0));
49}49}
std/math/sin.zig+26-26
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const std = @import("../index.zig");8const std = @import("../index.zig");
9const math = std.math;9const math = std.math;
10const assert = std.debug.assert;10const expect = std.testing.expect;
1111
12pub fn sin(x: var) @typeOf(x) {12pub fn sin(x: var) @typeOf(x) {
13 const T = @typeOf(x);13 const T = @typeOf(x);
...@@ -142,45 +142,45 @@ fn sin64(x_: f64) f64 {...@@ -142,45 +142,45 @@ fn sin64(x_: f64) f64 {
142}142}
143143
144test "math.sin" {144test "math.sin" {
145 assert(sin(f32(0.0)) == sin32(0.0));145 expect(sin(f32(0.0)) == sin32(0.0));
146 assert(sin(f64(0.0)) == sin64(0.0));146 expect(sin(f64(0.0)) == sin64(0.0));
147 assert(comptime (math.sin(f64(2))) == math.sin(f64(2)));147 expect(comptime (math.sin(f64(2))) == math.sin(f64(2)));
148}148}
149149
150test "math.sin32" {150test "math.sin32" {
151 const epsilon = 0.000001;151 const epsilon = 0.000001;
152152
153 assert(math.approxEq(f32, sin32(0.0), 0.0, epsilon));153 expect(math.approxEq(f32, sin32(0.0), 0.0, epsilon));
154 assert(math.approxEq(f32, sin32(0.2), 0.198669, epsilon));154 expect(math.approxEq(f32, sin32(0.2), 0.198669, epsilon));
155 assert(math.approxEq(f32, sin32(0.8923), 0.778517, epsilon));155 expect(math.approxEq(f32, sin32(0.8923), 0.778517, epsilon));
156 assert(math.approxEq(f32, sin32(1.5), 0.997495, epsilon));156 expect(math.approxEq(f32, sin32(1.5), 0.997495, epsilon));
157 assert(math.approxEq(f32, sin32(37.45), -0.246544, epsilon));157 expect(math.approxEq(f32, sin32(37.45), -0.246544, epsilon));
158 assert(math.approxEq(f32, sin32(89.123), 0.916166, epsilon));158 expect(math.approxEq(f32, sin32(89.123), 0.916166, epsilon));
159}159}
160160
161test "math.sin64" {161test "math.sin64" {
162 const epsilon = 0.000001;162 const epsilon = 0.000001;
163163
164 assert(math.approxEq(f64, sin64(0.0), 0.0, epsilon));164 expect(math.approxEq(f64, sin64(0.0), 0.0, epsilon));
165 assert(math.approxEq(f64, sin64(0.2), 0.198669, epsilon));165 expect(math.approxEq(f64, sin64(0.2), 0.198669, epsilon));
166 assert(math.approxEq(f64, sin64(0.8923), 0.778517, epsilon));166 expect(math.approxEq(f64, sin64(0.8923), 0.778517, epsilon));
167 assert(math.approxEq(f64, sin64(1.5), 0.997495, epsilon));167 expect(math.approxEq(f64, sin64(1.5), 0.997495, epsilon));
168 assert(math.approxEq(f64, sin64(37.45), -0.246543, epsilon));168 expect(math.approxEq(f64, sin64(37.45), -0.246543, epsilon));
169 assert(math.approxEq(f64, sin64(89.123), 0.916166, epsilon));169 expect(math.approxEq(f64, sin64(89.123), 0.916166, epsilon));
170}170}
171171
172test "math.sin32.special" {172test "math.sin32.special" {
173 assert(sin32(0.0) == 0.0);173 expect(sin32(0.0) == 0.0);
174 assert(sin32(-0.0) == -0.0);174 expect(sin32(-0.0) == -0.0);
175 assert(math.isNan(sin32(math.inf(f32))));175 expect(math.isNan(sin32(math.inf(f32))));
176 assert(math.isNan(sin32(-math.inf(f32))));176 expect(math.isNan(sin32(-math.inf(f32))));
177 assert(math.isNan(sin32(math.nan(f32))));177 expect(math.isNan(sin32(math.nan(f32))));
178}178}
179179
180test "math.sin64.special" {180test "math.sin64.special" {
181 assert(sin64(0.0) == 0.0);181 expect(sin64(0.0) == 0.0);
182 assert(sin64(-0.0) == -0.0);182 expect(sin64(-0.0) == -0.0);
183 assert(math.isNan(sin64(math.inf(f64))));183 expect(math.isNan(sin64(math.inf(f64))));
184 assert(math.isNan(sin64(-math.inf(f64))));184 expect(math.isNan(sin64(-math.inf(f64))));
185 assert(math.isNan(sin64(math.nan(f64))));185 expect(math.isNan(sin64(math.nan(f64))));
186}186}
std/math/sinh.zig+21-21
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const std = @import("../index.zig");8const std = @import("../index.zig");
9const math = std.math;9const math = std.math;
10const assert = std.debug.assert;10const expect = std.testing.expect;
11const expo2 = @import("expo2.zig").expo2;11const expo2 = @import("expo2.zig").expo2;
12const maxInt = std.math.maxInt;12const maxInt = std.math.maxInt;
1313
...@@ -87,40 +87,40 @@ fn sinh64(x: f64) f64 {...@@ -87,40 +87,40 @@ fn sinh64(x: f64) f64 {
87}87}
8888
89test "math.sinh" {89test "math.sinh" {
90 assert(sinh(f32(1.5)) == sinh32(1.5));90 expect(sinh(f32(1.5)) == sinh32(1.5));
91 assert(sinh(f64(1.5)) == sinh64(1.5));91 expect(sinh(f64(1.5)) == sinh64(1.5));
92}92}
9393
94test "math.sinh32" {94test "math.sinh32" {
95 const epsilon = 0.000001;95 const epsilon = 0.000001;
9696
97 assert(math.approxEq(f32, sinh32(0.0), 0.0, epsilon));97 expect(math.approxEq(f32, sinh32(0.0), 0.0, epsilon));
98 assert(math.approxEq(f32, sinh32(0.2), 0.201336, epsilon));98 expect(math.approxEq(f32, sinh32(0.2), 0.201336, epsilon));
99 assert(math.approxEq(f32, sinh32(0.8923), 1.015512, epsilon));99 expect(math.approxEq(f32, sinh32(0.8923), 1.015512, epsilon));
100 assert(math.approxEq(f32, sinh32(1.5), 2.129279, epsilon));100 expect(math.approxEq(f32, sinh32(1.5), 2.129279, epsilon));
101}101}
102102
103test "math.sinh64" {103test "math.sinh64" {
104 const epsilon = 0.000001;104 const epsilon = 0.000001;
105105
106 assert(math.approxEq(f64, sinh64(0.0), 0.0, epsilon));106 expect(math.approxEq(f64, sinh64(0.0), 0.0, epsilon));
107 assert(math.approxEq(f64, sinh64(0.2), 0.201336, epsilon));107 expect(math.approxEq(f64, sinh64(0.2), 0.201336, epsilon));
108 assert(math.approxEq(f64, sinh64(0.8923), 1.015512, epsilon));108 expect(math.approxEq(f64, sinh64(0.8923), 1.015512, epsilon));
109 assert(math.approxEq(f64, sinh64(1.5), 2.129279, epsilon));109 expect(math.approxEq(f64, sinh64(1.5), 2.129279, epsilon));
110}110}
111111
112test "math.sinh32.special" {112test "math.sinh32.special" {
113 assert(sinh32(0.0) == 0.0);113 expect(sinh32(0.0) == 0.0);
114 assert(sinh32(-0.0) == -0.0);114 expect(sinh32(-0.0) == -0.0);
115 assert(math.isPositiveInf(sinh32(math.inf(f32))));115 expect(math.isPositiveInf(sinh32(math.inf(f32))));
116 assert(math.isNegativeInf(sinh32(-math.inf(f32))));116 expect(math.isNegativeInf(sinh32(-math.inf(f32))));
117 assert(math.isNan(sinh32(math.nan(f32))));117 expect(math.isNan(sinh32(math.nan(f32))));
118}118}
119119
120test "math.sinh64.special" {120test "math.sinh64.special" {
121 assert(sinh64(0.0) == 0.0);121 expect(sinh64(0.0) == 0.0);
122 assert(sinh64(-0.0) == -0.0);122 expect(sinh64(-0.0) == -0.0);
123 assert(math.isPositiveInf(sinh64(math.inf(f64))));123 expect(math.isPositiveInf(sinh64(math.inf(f64))));
124 assert(math.isNegativeInf(sinh64(-math.inf(f64))));124 expect(math.isNegativeInf(sinh64(-math.inf(f64))));
125 assert(math.isNan(sinh64(math.nan(f64))));125 expect(math.isNan(sinh64(math.nan(f64))));
126}126}
std/math/sqrt.zig+52-52
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
77
8const std = @import("../index.zig");8const std = @import("../index.zig");
9const math = std.math;9const math = std.math;
10const assert = std.debug.assert;10const expect = std.testing.expect;
11const builtin = @import("builtin");11const builtin = @import("builtin");
12const TypeId = builtin.TypeId;12const TypeId = builtin.TypeId;
13const maxInt = std.math.maxInt;13const maxInt = std.math.maxInt;
...@@ -32,75 +32,75 @@ pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typ...@@ -32,75 +32,75 @@ pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typ
32}32}
3333
34test "math.sqrt" {34test "math.sqrt" {
35 assert(sqrt(f16(0.0)) == @sqrt(f16, 0.0));35 expect(sqrt(f16(0.0)) == @sqrt(f16, 0.0));
36 assert(sqrt(f32(0.0)) == @sqrt(f32, 0.0));36 expect(sqrt(f32(0.0)) == @sqrt(f32, 0.0));
37 assert(sqrt(f64(0.0)) == @sqrt(f64, 0.0));37 expect(sqrt(f64(0.0)) == @sqrt(f64, 0.0));
38}38}
3939
40test "math.sqrt16" {40test "math.sqrt16" {
41 const epsilon = 0.000001;41 const epsilon = 0.000001;
4242
43 assert(@sqrt(f16, 0.0) == 0.0);43 expect(@sqrt(f16, 0.0) == 0.0);
44 assert(math.approxEq(f16, @sqrt(f16, 2.0), 1.414214, epsilon));44 expect(math.approxEq(f16, @sqrt(f16, 2.0), 1.414214, epsilon));
45 assert(math.approxEq(f16, @sqrt(f16, 3.6), 1.897367, epsilon));45 expect(math.approxEq(f16, @sqrt(f16, 3.6), 1.897367, epsilon));
46 assert(@sqrt(f16, 4.0) == 2.0);46 expect(@sqrt(f16, 4.0) == 2.0);
47 assert(math.approxEq(f16, @sqrt(f16, 7.539840), 2.745877, epsilon));47 expect(math.approxEq(f16, @sqrt(f16, 7.539840), 2.745877, epsilon));
48 assert(math.approxEq(f16, @sqrt(f16, 19.230934), 4.385309, epsilon));48 expect(math.approxEq(f16, @sqrt(f16, 19.230934), 4.385309, epsilon));
49 assert(@sqrt(f16, 64.0) == 8.0);49 expect(@sqrt(f16, 64.0) == 8.0);
50 assert(math.approxEq(f16, @sqrt(f16, 64.1), 8.006248, epsilon));50 expect(math.approxEq(f16, @sqrt(f16, 64.1), 8.006248, epsilon));
51 assert(math.approxEq(f16, @sqrt(f16, 8942.230469), 94.563370, epsilon));51 expect(math.approxEq(f16, @sqrt(f16, 8942.230469), 94.563370, epsilon));
52}52}
5353
54test "math.sqrt32" {54test "math.sqrt32" {
55 const epsilon = 0.000001;55 const epsilon = 0.000001;
5656
57 assert(@sqrt(f32, 0.0) == 0.0);57 expect(@sqrt(f32, 0.0) == 0.0);
58 assert(math.approxEq(f32, @sqrt(f32, 2.0), 1.414214, epsilon));58 expect(math.approxEq(f32, @sqrt(f32, 2.0), 1.414214, epsilon));
59 assert(math.approxEq(f32, @sqrt(f32, 3.6), 1.897367, epsilon));59 expect(math.approxEq(f32, @sqrt(f32, 3.6), 1.897367, epsilon));
60 assert(@sqrt(f32, 4.0) == 2.0);60 expect(@sqrt(f32, 4.0) == 2.0);
61 assert(math.approxEq(f32, @sqrt(f32, 7.539840), 2.745877, epsilon));61 expect(math.approxEq(f32, @sqrt(f32, 7.539840), 2.745877, epsilon));
62 assert(math.approxEq(f32, @sqrt(f32, 19.230934), 4.385309, epsilon));62 expect(math.approxEq(f32, @sqrt(f32, 19.230934), 4.385309, epsilon));
63 assert(@sqrt(f32, 64.0) == 8.0);63 expect(@sqrt(f32, 64.0) == 8.0);
64 assert(math.approxEq(f32, @sqrt(f32, 64.1), 8.006248, epsilon));64 expect(math.approxEq(f32, @sqrt(f32, 64.1), 8.006248, epsilon));
65 assert(math.approxEq(f32, @sqrt(f32, 8942.230469), 94.563370, epsilon));65 expect(math.approxEq(f32, @sqrt(f32, 8942.230469), 94.563370, epsilon));
66}66}
6767
68test "math.sqrt64" {68test "math.sqrt64" {
69 const epsilon = 0.000001;69 const epsilon = 0.000001;
7070
71 assert(@sqrt(f64, 0.0) == 0.0);71 expect(@sqrt(f64, 0.0) == 0.0);
72 assert(math.approxEq(f64, @sqrt(f64, 2.0), 1.414214, epsilon));72 expect(math.approxEq(f64, @sqrt(f64, 2.0), 1.414214, epsilon));
73 assert(math.approxEq(f64, @sqrt(f64, 3.6), 1.897367, epsilon));73 expect(math.approxEq(f64, @sqrt(f64, 3.6), 1.897367, epsilon));
74 assert(@sqrt(f64, 4.0) == 2.0);74 expect(@sqrt(f64, 4.0) == 2.0);
75 assert(math.approxEq(f64, @sqrt(f64, 7.539840), 2.745877, epsilon));75 expect(math.approxEq(f64, @sqrt(f64, 7.539840), 2.745877, epsilon));
76 assert(math.approxEq(f64, @sqrt(f64, 19.230934), 4.385309, epsilon));76 expect(math.approxEq(f64, @sqrt(f64, 19.230934), 4.385309, epsilon));
77 assert(@sqrt(f64, 64.0) == 8.0);77 expect(@sqrt(f64, 64.0) == 8.0);
78 assert(math.approxEq(f64, @sqrt(f64, 64.1), 8.006248, epsilon));78 expect(math.approxEq(f64, @sqrt(f64, 64.1), 8.006248, epsilon));
79 assert(math.approxEq(f64, @sqrt(f64, 8942.230469), 94.563367, epsilon));79 expect(math.approxEq(f64, @sqrt(f64, 8942.230469), 94.563367, epsilon));
80}80}
8181
82test "math.sqrt16.special" {82test "math.sqrt16.special" {
83 assert(math.isPositiveInf(@sqrt(f16, math.inf(f16))));83 expect(math.isPositiveInf(@sqrt(f16, math.inf(f16))));
84 assert(@sqrt(f16, 0.0) == 0.0);84 expect(@sqrt(f16, 0.0) == 0.0);
85 assert(@sqrt(f16, -0.0) == -0.0);85 expect(@sqrt(f16, -0.0) == -0.0);
86 assert(math.isNan(@sqrt(f16, -1.0)));86 expect(math.isNan(@sqrt(f16, -1.0)));
87 assert(math.isNan(@sqrt(f16, math.nan(f16))));87 expect(math.isNan(@sqrt(f16, math.nan(f16))));
88}88}
8989
90test "math.sqrt32.special" {90test "math.sqrt32.special" {
91 assert(math.isPositiveInf(@sqrt(f32, math.inf(f32))));91 expect(math.isPositiveInf(@sqrt(f32, math.inf(f32))));
92 assert(@sqrt(f32, 0.0) == 0.0);92 expect(@sqrt(f32, 0.0) == 0.0);
93 assert(@sqrt(f32, -0.0) == -0.0);93 expect(@sqrt(f32, -0.0) == -0.0);
94 assert(math.isNan(@sqrt(f32, -1.0)));94 expect(math.isNan(@sqrt(f32, -1.0)));
95 assert(math.isNan(@sqrt(f32, math.nan(f32))));95 expect(math.isNan(@sqrt(f32, math.nan(f32))));
96}96}
9797
98test "math.sqrt64.special" {98test "math.sqrt64.special" {
99 assert(math.isPositiveInf(@sqrt(f64, math.inf(f64))));99 expect(math.isPositiveInf(@sqrt(f64, math.inf(f64))));
100 assert(@sqrt(f64, 0.0) == 0.0);100 expect(@sqrt(f64, 0.0) == 0.0);
101 assert(@sqrt(f64, -0.0) == -0.0);101 expect(@sqrt(f64, -0.0) == -0.0);
102 assert(math.isNan(@sqrt(f64, -1.0)));102 expect(math.isNan(@sqrt(f64, -1.0)));
103 assert(math.isNan(@sqrt(f64, math.nan(f64))));103 expect(math.isNan(@sqrt(f64, math.nan(f64))));
104}104}
105105
106fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) {106fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) {
...@@ -127,10 +127,10 @@ fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) {...@@ -127,10 +127,10 @@ fn sqrt_int(comptime T: type, value: T) @IntType(false, T.bit_count / 2) {
127}127}
128128
129test "math.sqrt_int" {129test "math.sqrt_int" {
130 assert(sqrt_int(u32, 3) == 1);130 expect(sqrt_int(u32, 3) == 1);
131 assert(sqrt_int(u32, 4) == 2);131 expect(sqrt_int(u32, 4) == 2);
132 assert(sqrt_int(u32, 5) == 2);132 expect(sqrt_int(u32, 5) == 2);
133 assert(sqrt_int(u32, 8) == 2);133 expect(sqrt_int(u32, 8) == 2);
134 assert(sqrt_int(u32, 9) == 3);134 expect(sqrt_int(u32, 9) == 3);
135 assert(sqrt_int(u32, 10) == 3);135 expect(sqrt_int(u32, 10) == 3);
136}136}
std/math/tan.zig+25-25
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const std = @import("../index.zig");8const std = @import("../index.zig");
9const math = std.math;9const math = std.math;
10const assert = std.debug.assert;10const expect = std.testing.expect;
1111
12pub fn tan(x: var) @typeOf(x) {12pub fn tan(x: var) @typeOf(x) {
13 const T = @typeOf(x);13 const T = @typeOf(x);
...@@ -129,44 +129,44 @@ fn tan64(x_: f64) f64 {...@@ -129,44 +129,44 @@ fn tan64(x_: f64) f64 {
129}129}
130130
131test "math.tan" {131test "math.tan" {
132 assert(tan(f32(0.0)) == tan32(0.0));132 expect(tan(f32(0.0)) == tan32(0.0));
133 assert(tan(f64(0.0)) == tan64(0.0));133 expect(tan(f64(0.0)) == tan64(0.0));
134}134}
135135
136test "math.tan32" {136test "math.tan32" {
137 const epsilon = 0.000001;137 const epsilon = 0.000001;
138138
139 assert(math.approxEq(f32, tan32(0.0), 0.0, epsilon));139 expect(math.approxEq(f32, tan32(0.0), 0.0, epsilon));
140 assert(math.approxEq(f32, tan32(0.2), 0.202710, epsilon));140 expect(math.approxEq(f32, tan32(0.2), 0.202710, epsilon));
141 assert(math.approxEq(f32, tan32(0.8923), 1.240422, epsilon));141 expect(math.approxEq(f32, tan32(0.8923), 1.240422, epsilon));
142 assert(math.approxEq(f32, tan32(1.5), 14.101420, epsilon));142 expect(math.approxEq(f32, tan32(1.5), 14.101420, epsilon));
143 assert(math.approxEq(f32, tan32(37.45), -0.254397, epsilon));143 expect(math.approxEq(f32, tan32(37.45), -0.254397, epsilon));
144 assert(math.approxEq(f32, tan32(89.123), 2.285852, epsilon));144 expect(math.approxEq(f32, tan32(89.123), 2.285852, epsilon));
145}145}
146146
147test "math.tan64" {147test "math.tan64" {
148 const epsilon = 0.000001;148 const epsilon = 0.000001;
149149
150 assert(math.approxEq(f64, tan64(0.0), 0.0, epsilon));150 expect(math.approxEq(f64, tan64(0.0), 0.0, epsilon));
151 assert(math.approxEq(f64, tan64(0.2), 0.202710, epsilon));151 expect(math.approxEq(f64, tan64(0.2), 0.202710, epsilon));
152 assert(math.approxEq(f64, tan64(0.8923), 1.240422, epsilon));152 expect(math.approxEq(f64, tan64(0.8923), 1.240422, epsilon));
153 assert(math.approxEq(f64, tan64(1.5), 14.101420, epsilon));153 expect(math.approxEq(f64, tan64(1.5), 14.101420, epsilon));
154 assert(math.approxEq(f64, tan64(37.45), -0.254397, epsilon));154 expect(math.approxEq(f64, tan64(37.45), -0.254397, epsilon));
155 assert(math.approxEq(f64, tan64(89.123), 2.2858376, epsilon));155 expect(math.approxEq(f64, tan64(89.123), 2.2858376, epsilon));
156}156}
157157
158test "math.tan32.special" {158test "math.tan32.special" {
159 assert(tan32(0.0) == 0.0);159 expect(tan32(0.0) == 0.0);
160 assert(tan32(-0.0) == -0.0);160 expect(tan32(-0.0) == -0.0);
161 assert(math.isNan(tan32(math.inf(f32))));161 expect(math.isNan(tan32(math.inf(f32))));
162 assert(math.isNan(tan32(-math.inf(f32))));162 expect(math.isNan(tan32(-math.inf(f32))));
163 assert(math.isNan(tan32(math.nan(f32))));163 expect(math.isNan(tan32(math.nan(f32))));
164}164}
165165
166test "math.tan64.special" {166test "math.tan64.special" {
167 assert(tan64(0.0) == 0.0);167 expect(tan64(0.0) == 0.0);
168 assert(tan64(-0.0) == -0.0);168 expect(tan64(-0.0) == -0.0);
169 assert(math.isNan(tan64(math.inf(f64))));169 expect(math.isNan(tan64(math.inf(f64))));
170 assert(math.isNan(tan64(-math.inf(f64))));170 expect(math.isNan(tan64(-math.inf(f64))));
171 assert(math.isNan(tan64(math.nan(f64))));171 expect(math.isNan(tan64(math.nan(f64))));
172}172}
std/math/tanh.zig+23-23
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const std = @import("../index.zig");8const std = @import("../index.zig");
9const math = std.math;9const math = std.math;
10const assert = std.debug.assert;10const expect = std.testing.expect;
11const expo2 = @import("expo2.zig").expo2;11const expo2 = @import("expo2.zig").expo2;
12const maxInt = std.math.maxInt;12const maxInt = std.math.maxInt;
1313
...@@ -113,42 +113,42 @@ fn tanh64(x: f64) f64 {...@@ -113,42 +113,42 @@ fn tanh64(x: f64) f64 {
113}113}
114114
115test "math.tanh" {115test "math.tanh" {
116 assert(tanh(f32(1.5)) == tanh32(1.5));116 expect(tanh(f32(1.5)) == tanh32(1.5));
117 assert(tanh(f64(1.5)) == tanh64(1.5));117 expect(tanh(f64(1.5)) == tanh64(1.5));
118}118}
119119
120test "math.tanh32" {120test "math.tanh32" {
121 const epsilon = 0.000001;121 const epsilon = 0.000001;
122122
123 assert(math.approxEq(f32, tanh32(0.0), 0.0, epsilon));123 expect(math.approxEq(f32, tanh32(0.0), 0.0, epsilon));
124 assert(math.approxEq(f32, tanh32(0.2), 0.197375, epsilon));124 expect(math.approxEq(f32, tanh32(0.2), 0.197375, epsilon));
125 assert(math.approxEq(f32, tanh32(0.8923), 0.712528, epsilon));125 expect(math.approxEq(f32, tanh32(0.8923), 0.712528, epsilon));
126 assert(math.approxEq(f32, tanh32(1.5), 0.905148, epsilon));126 expect(math.approxEq(f32, tanh32(1.5), 0.905148, epsilon));
127 assert(math.approxEq(f32, tanh32(37.45), 1.0, epsilon));127 expect(math.approxEq(f32, tanh32(37.45), 1.0, epsilon));
128}128}
129129
130test "math.tanh64" {130test "math.tanh64" {
131 const epsilon = 0.000001;131 const epsilon = 0.000001;
132132
133 assert(math.approxEq(f64, tanh64(0.0), 0.0, epsilon));133 expect(math.approxEq(f64, tanh64(0.0), 0.0, epsilon));
134 assert(math.approxEq(f64, tanh64(0.2), 0.197375, epsilon));134 expect(math.approxEq(f64, tanh64(0.2), 0.197375, epsilon));
135 assert(math.approxEq(f64, tanh64(0.8923), 0.712528, epsilon));135 expect(math.approxEq(f64, tanh64(0.8923), 0.712528, epsilon));
136 assert(math.approxEq(f64, tanh64(1.5), 0.905148, epsilon));136 expect(math.approxEq(f64, tanh64(1.5), 0.905148, epsilon));
137 assert(math.approxEq(f64, tanh64(37.45), 1.0, epsilon));137 expect(math.approxEq(f64, tanh64(37.45), 1.0, epsilon));
138}138}
139139
140test "math.tanh32.special" {140test "math.tanh32.special" {
141 assert(tanh32(0.0) == 0.0);141 expect(tanh32(0.0) == 0.0);
142 assert(tanh32(-0.0) == -0.0);142 expect(tanh32(-0.0) == -0.0);
143 assert(tanh32(math.inf(f32)) == 1.0);143 expect(tanh32(math.inf(f32)) == 1.0);
144 assert(tanh32(-math.inf(f32)) == -1.0);144 expect(tanh32(-math.inf(f32)) == -1.0);
145 assert(math.isNan(tanh32(math.nan(f32))));145 expect(math.isNan(tanh32(math.nan(f32))));
146}146}
147147
148test "math.tanh64.special" {148test "math.tanh64.special" {
149 assert(tanh64(0.0) == 0.0);149 expect(tanh64(0.0) == 0.0);
150 assert(tanh64(-0.0) == -0.0);150 expect(tanh64(-0.0) == -0.0);
151 assert(tanh64(math.inf(f64)) == 1.0);151 expect(tanh64(math.inf(f64)) == 1.0);
152 assert(tanh64(-math.inf(f64)) == -1.0);152 expect(tanh64(-math.inf(f64)) == -1.0);
153 assert(math.isNan(tanh64(math.nan(f64))));153 expect(math.isNan(tanh64(math.nan(f64))));
154}154}
std/math/trunc.zig+19-19
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
66
7const std = @import("../index.zig");7const std = @import("../index.zig");
8const math = std.math;8const math = std.math;
9const assert = std.debug.assert;9const expect = std.testing.expect;
10const maxInt = std.math.maxInt;10const maxInt = std.math.maxInt;
1111
12pub fn trunc(x: var) @typeOf(x) {12pub fn trunc(x: var) @typeOf(x) {
...@@ -61,34 +61,34 @@ fn trunc64(x: f64) f64 {...@@ -61,34 +61,34 @@ fn trunc64(x: f64) f64 {
61}61}
6262
63test "math.trunc" {63test "math.trunc" {
64 assert(trunc(f32(1.3)) == trunc32(1.3));64 expect(trunc(f32(1.3)) == trunc32(1.3));
65 assert(trunc(f64(1.3)) == trunc64(1.3));65 expect(trunc(f64(1.3)) == trunc64(1.3));
66}66}
6767
68test "math.trunc32" {68test "math.trunc32" {
69 assert(trunc32(1.3) == 1.0);69 expect(trunc32(1.3) == 1.0);
70 assert(trunc32(-1.3) == -1.0);70 expect(trunc32(-1.3) == -1.0);
71 assert(trunc32(0.2) == 0.0);71 expect(trunc32(0.2) == 0.0);
72}72}
7373
74test "math.trunc64" {74test "math.trunc64" {
75 assert(trunc64(1.3) == 1.0);75 expect(trunc64(1.3) == 1.0);
76 assert(trunc64(-1.3) == -1.0);76 expect(trunc64(-1.3) == -1.0);
77 assert(trunc64(0.2) == 0.0);77 expect(trunc64(0.2) == 0.0);
78}78}
7979
80test "math.trunc32.special" {80test "math.trunc32.special" {
81 assert(trunc32(0.0) == 0.0); // 0x3F80000081 expect(trunc32(0.0) == 0.0); // 0x3F800000
82 assert(trunc32(-0.0) == -0.0);82 expect(trunc32(-0.0) == -0.0);
83 assert(math.isPositiveInf(trunc32(math.inf(f32))));83 expect(math.isPositiveInf(trunc32(math.inf(f32))));
84 assert(math.isNegativeInf(trunc32(-math.inf(f32))));84 expect(math.isNegativeInf(trunc32(-math.inf(f32))));
85 assert(math.isNan(trunc32(math.nan(f32))));85 expect(math.isNan(trunc32(math.nan(f32))));
86}86}
8787
88test "math.trunc64.special" {88test "math.trunc64.special" {
89 assert(trunc64(0.0) == 0.0);89 expect(trunc64(0.0) == 0.0);
90 assert(trunc64(-0.0) == -0.0);90 expect(trunc64(-0.0) == -0.0);
91 assert(math.isPositiveInf(trunc64(math.inf(f64))));91 expect(math.isPositiveInf(trunc64(math.inf(f64))));
92 assert(math.isNegativeInf(trunc64(-math.inf(f64))));92 expect(math.isNegativeInf(trunc64(-math.inf(f64))));
93 assert(math.isNan(trunc64(math.nan(f64))));93 expect(math.isNan(trunc64(math.nan(f64))));
94}94}
std/mem.zig+526-278
...@@ -6,6 +6,7 @@ const builtin = @import("builtin");...@@ -6,6 +6,7 @@ const builtin = @import("builtin");
6const mem = @This();6const mem = @This();
7const meta = std.meta;7const meta = std.meta;
8const trait = meta.trait;8const trait = meta.trait;
9const testing = std.testing;
910
10pub const Allocator = struct {11pub const Allocator = struct {
11 pub const Error = error{OutOfMemory};12 pub const Error = error{OutOfMemory};
...@@ -36,20 +37,9 @@ pub const Allocator = struct {...@@ -36,20 +37,9 @@ pub const Allocator = struct {
36 /// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn`37 /// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn`
37 freeFn: fn (self: *Allocator, old_mem: []u8) void,38 freeFn: fn (self: *Allocator, old_mem: []u8) void,
3839
39 /// Call `destroy` with the result
40 /// TODO this is deprecated. use createOne instead
41 pub fn create(self: *Allocator, init: var) Error!*@typeOf(init) {
42 const T = @typeOf(init);
43 if (@sizeOf(T) == 0) return &(T{});
44 const slice = try self.alloc(T, 1);
45 const ptr = &slice[0];
46 ptr.* = init;
47 return ptr;
48 }
49
50 /// Call `destroy` with the result.40 /// Call `destroy` with the result.
51 /// Returns undefined memory.41 /// Returns undefined memory.
52 pub fn createOne(self: *Allocator, comptime T: type) Error!*T {42 pub fn create(self: *Allocator, comptime T: type) Error!*T {
53 if (@sizeOf(T) == 0) return &(T{});43 if (@sizeOf(T) == 0) return &(T{});
54 const slice = try self.alloc(T, 1);44 const slice = try self.alloc(T, 1);
55 return &slice[0];45 return &slice[0];
...@@ -192,7 +182,7 @@ test "mem.secureZero" {...@@ -192,7 +182,7 @@ test "mem.secureZero" {
192 set(u8, a[0..], 0);182 set(u8, a[0..], 0);
193 secureZero(u8, b[0..]);183 secureZero(u8, b[0..]);
194184
195 assert(eql(u8, a[0..], b[0..]));185 testing.expectEqualSlices(u8, a[0..], b[0..]);
196}186}
197187
198pub fn compare(comptime T: type, lhs: []const T, rhs: []const T) Compare {188pub fn compare(comptime T: type, lhs: []const T, rhs: []const T) Compare {
...@@ -221,11 +211,11 @@ pub fn compare(comptime T: type, lhs: []const T, rhs: []const T) Compare {...@@ -221,11 +211,11 @@ pub fn compare(comptime T: type, lhs: []const T, rhs: []const T) Compare {
221}211}
222212
223test "mem.compare" {213test "mem.compare" {
224 assert(compare(u8, "abcd", "bee") == Compare.LessThan);214 testing.expect(compare(u8, "abcd", "bee") == Compare.LessThan);
225 assert(compare(u8, "abc", "abc") == Compare.Equal);215 testing.expect(compare(u8, "abc", "abc") == Compare.Equal);
226 assert(compare(u8, "abc", "abc0") == Compare.LessThan);216 testing.expect(compare(u8, "abc", "abc0") == Compare.LessThan);
227 assert(compare(u8, "", "") == Compare.Equal);217 testing.expect(compare(u8, "", "") == Compare.Equal);
228 assert(compare(u8, "", "a") == Compare.LessThan);218 testing.expect(compare(u8, "", "a") == Compare.LessThan);
229}219}
230220
231/// Returns true if lhs < rhs, false otherwise221/// Returns true if lhs < rhs, false otherwise
...@@ -238,11 +228,11 @@ pub fn lessThan(comptime T: type, lhs: []const T, rhs: []const T) bool {...@@ -238,11 +228,11 @@ pub fn lessThan(comptime T: type, lhs: []const T, rhs: []const T) bool {
238}228}
239229
240test "mem.lessThan" {230test "mem.lessThan" {
241 assert(lessThan(u8, "abcd", "bee"));231 testing.expect(lessThan(u8, "abcd", "bee"));
242 assert(!lessThan(u8, "abc", "abc"));232 testing.expect(!lessThan(u8, "abc", "abc"));
243 assert(lessThan(u8, "abc", "abc0"));233 testing.expect(lessThan(u8, "abc", "abc0"));
244 assert(!lessThan(u8, "", ""));234 testing.expect(!lessThan(u8, "", ""));
245 assert(lessThan(u8, "", "a"));235 testing.expect(lessThan(u8, "", "a"));
246}236}
247237
248/// Compares two slices and returns whether they are equal.238/// Compares two slices and returns whether they are equal.
...@@ -307,10 +297,10 @@ pub fn trim(comptime T: type, slice: []const T, values_to_strip: []const T) []co...@@ -307,10 +297,10 @@ pub fn trim(comptime T: type, slice: []const T, values_to_strip: []const T) []co
307}297}
308298
309test "mem.trim" {299test "mem.trim" {
310 assert(eql(u8, trimLeft(u8, " foo\n ", " \n"), "foo\n "));300 testing.expectEqualSlices(u8, "foo\n ", trimLeft(u8, " foo\n ", " \n"));
311 assert(eql(u8, trimRight(u8, " foo\n ", " \n"), " foo"));301 testing.expectEqualSlices(u8, " foo", trimRight(u8, " foo\n ", " \n"));
312 assert(eql(u8, trim(u8, " foo\n ", " \n"), "foo"));302 testing.expectEqualSlices(u8, "foo", trim(u8, " foo\n ", " \n"));
313 assert(eql(u8, trim(u8, "foo", " \n"), "foo"));303 testing.expectEqualSlices(u8, "foo", trim(u8, "foo", " \n"));
314}304}
315305
316/// Linear search for the index of a scalar value inside a slice.306/// Linear search for the index of a scalar value inside a slice.
...@@ -391,31 +381,27 @@ pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, nee...@@ -391,31 +381,27 @@ pub fn indexOfPos(comptime T: type, haystack: []const T, start_index: usize, nee
391}381}
392382
393test "mem.indexOf" {383test "mem.indexOf" {
394 assert(indexOf(u8, "one two three four", "four").? == 14);384 testing.expect(indexOf(u8, "one two three four", "four").? == 14);
395 assert(lastIndexOf(u8, "one two three two four", "two").? == 14);385 testing.expect(lastIndexOf(u8, "one two three two four", "two").? == 14);
396 assert(indexOf(u8, "one two three four", "gour") == null);386 testing.expect(indexOf(u8, "one two three four", "gour") == null);
397 assert(lastIndexOf(u8, "one two three four", "gour") == null);387 testing.expect(lastIndexOf(u8, "one two three four", "gour") == null);
398 assert(indexOf(u8, "foo", "foo").? == 0);388 testing.expect(indexOf(u8, "foo", "foo").? == 0);
399 assert(lastIndexOf(u8, "foo", "foo").? == 0);389 testing.expect(lastIndexOf(u8, "foo", "foo").? == 0);
400 assert(indexOf(u8, "foo", "fool") == null);390 testing.expect(indexOf(u8, "foo", "fool") == null);
401 assert(lastIndexOf(u8, "foo", "lfoo") == null);391 testing.expect(lastIndexOf(u8, "foo", "lfoo") == null);
402 assert(lastIndexOf(u8, "foo", "fool") == null);392 testing.expect(lastIndexOf(u8, "foo", "fool") == null);
403393
404 assert(indexOf(u8, "foo foo", "foo").? == 0);394 testing.expect(indexOf(u8, "foo foo", "foo").? == 0);
405 assert(lastIndexOf(u8, "foo foo", "foo").? == 4);395 testing.expect(lastIndexOf(u8, "foo foo", "foo").? == 4);
406 assert(lastIndexOfAny(u8, "boo, cat", "abo").? == 6);396 testing.expect(lastIndexOfAny(u8, "boo, cat", "abo").? == 6);
407 assert(lastIndexOfScalar(u8, "boo", 'o').? == 2);397 testing.expect(lastIndexOfScalar(u8, "boo", 'o').? == 2);
408}398}
409399
410/// Reads an integer from memory with size equal to bytes.len.400/// Reads an integer from memory with size equal to bytes.len.
411/// T specifies the return type, which must be large enough to store401/// T specifies the return type, which must be large enough to store
412/// the result.402/// the result.
413/// See also ::readIntBE or ::readIntLE.403pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: builtin.Endian) ReturnType {
414pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T {404 var result: ReturnType = 0;
415 if (T.bit_count == 8) {
416 return bytes[0];
417 }
418 var result: T = 0;
419 switch (endian) {405 switch (endian) {
420 builtin.Endian.Big => {406 builtin.Endian.Big => {
421 for (bytes) |b| {407 for (bytes) |b| {
...@@ -423,171 +409,262 @@ pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T {...@@ -423,171 +409,262 @@ pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T {
423 }409 }
424 },410 },
425 builtin.Endian.Little => {411 builtin.Endian.Little => {
426 const ShiftType = math.Log2Int(T);412 const ShiftType = math.Log2Int(ReturnType);
427 for (bytes) |b, index| {413 for (bytes) |b, index| {
428 result = result | (T(b) << @intCast(ShiftType, index * 8));414 result = result | (ReturnType(b) << @intCast(ShiftType, index * 8));
429 }415 }
430 },416 },
431 }417 }
432 return result;418 return result;
433}419}
434420
435/// Reads a big-endian int of type T from bytes.421/// Reads an integer from memory with bit count specified by T.
436/// bytes.len must be exactly @sizeOf(T).422/// The bit count of T must be evenly divisible by 8.
437pub fn readIntBE(comptime T: type, bytes: []const u8) T {423/// This function cannot fail and cannot cause undefined behavior.
438 if (T.is_signed) {424/// Assumes the endianness of memory is native. This means the function can
439 return @bitCast(T, readIntBE(@IntType(false, T.bit_count), bytes));425/// simply pointer cast memory.
440 }426pub fn readIntNative(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8) T {
441 assert(bytes.len == @sizeOf(T));427 return @ptrCast(*align(1) const T, bytes).*;
442 if (T == u8) return bytes[0];428}
443 var result: T = 0;429
444 {430/// Reads an integer from memory with bit count specified by T.
445 comptime var i = 0;431/// The bit count of T must be evenly divisible by 8.
446 inline while (i < @sizeOf(T)) : (i += 1) {432/// This function cannot fail and cannot cause undefined behavior.
447 result = (result << 8) | T(bytes[i]);433/// Assumes the endianness of memory is foreign, so it must byte-swap.
448 }434pub fn readIntForeign(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8) T {
435 return @bswap(T, readIntNative(T, bytes));
436}
437
438pub const readIntLittle = switch (builtin.endian) {
439 builtin.Endian.Little => readIntNative,
440 builtin.Endian.Big => readIntForeign,
441};
442
443pub const readIntBig = switch (builtin.endian) {
444 builtin.Endian.Little => readIntForeign,
445 builtin.Endian.Big => readIntNative,
446};
447
448/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0
449/// and ignores extra bytes.
450/// The bit count of T must be evenly divisible by 8.
451/// Assumes the endianness of memory is native. This means the function can
452/// simply pointer cast memory.
453pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T {
454 const n = @divExact(T.bit_count, 8);
455 assert(bytes.len >= n);
456 // TODO https://github.com/ziglang/zig/issues/863
457 return readIntNative(T, @ptrCast(*const [n]u8, bytes.ptr));
458}
459
460/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0
461/// and ignores extra bytes.
462/// The bit count of T must be evenly divisible by 8.
463/// Assumes the endianness of memory is foreign, so it must byte-swap.
464pub fn readIntSliceForeign(comptime T: type, bytes: []const u8) T {
465 return @bswap(T, readIntSliceNative(T, bytes));
466}
467
468pub const readIntSliceLittle = switch (builtin.endian) {
469 builtin.Endian.Little => readIntSliceNative,
470 builtin.Endian.Big => readIntSliceForeign,
471};
472
473pub const readIntSliceBig = switch (builtin.endian) {
474 builtin.Endian.Little => readIntSliceForeign,
475 builtin.Endian.Big => readIntSliceNative,
476};
477
478/// Reads an integer from memory with bit count specified by T.
479/// The bit count of T must be evenly divisible by 8.
480/// This function cannot fail and cannot cause undefined behavior.
481pub fn readInt(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8, endian: builtin.Endian) T {
482 if (endian == builtin.endian) {
483 return readIntNative(T, bytes);
484 } else {
485 return readIntForeign(T, bytes);
449 }486 }
450 return result;
451}487}
452488
453/// Reads a little-endian int of type T from bytes.489/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0
454/// bytes.len must be exactly @sizeOf(T).490/// and ignores extra bytes.
455pub fn readIntLE(comptime T: type, bytes: []const u8) T {491/// The bit count of T must be evenly divisible by 8.
456 if (T.is_signed) {492pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T {
457 return @bitCast(T, readIntLE(@IntType(false, T.bit_count), bytes));493 const n = @divExact(T.bit_count, 8);
494 assert(bytes.len >= n);
495 // TODO https://github.com/ziglang/zig/issues/863
496 return readInt(T, @ptrCast(*const [n]u8, bytes.ptr), endian);
497}
498
499test "comptime read/write int" {
500 comptime {
501 var bytes: [2]u8 = undefined;
502 std.mem.writeIntLittle(u16, &bytes, 0x1234);
503 const result = std.mem.readIntBig(u16, &bytes);
504 testing.expect(result == 0x3412);
458 }505 }
459 assert(bytes.len == @sizeOf(T));506 comptime {
460 if (T == u8) return bytes[0];507 var bytes: [2]u8 = undefined;
461 var result: T = 0;508 std.mem.writeIntBig(u16, &bytes, 0x1234);
462 {509 const result = std.mem.readIntLittle(u16, &bytes);
463 comptime var i = 0;510 testing.expect(result == 0x3412);
464 inline while (i < @sizeOf(T)) : (i += 1) {
465 result |= T(bytes[i]) << i * 8;
466 }
467 }511 }
468 return result;
469}512}
470513
471test "readIntBE/LE" {514test "readIntBig and readIntLittle" {
472 assert(readIntBE(u0, []u8{}) == 0x0);515 testing.expect(readIntSliceBig(u0, []u8{}) == 0x0);
473 assert(readIntLE(u0, []u8{}) == 0x0);516 testing.expect(readIntSliceLittle(u0, []u8{}) == 0x0);
474517
475 assert(readIntBE(u8, []u8{0x32}) == 0x32);518 testing.expect(readIntSliceBig(u8, []u8{0x32}) == 0x32);
476 assert(readIntLE(u8, []u8{0x12}) == 0x12);519 testing.expect(readIntSliceLittle(u8, []u8{0x12}) == 0x12);
477520
478 assert(readIntBE(u16, []u8{ 0x12, 0x34 }) == 0x1234);521 testing.expect(readIntSliceBig(u16, []u8{ 0x12, 0x34 }) == 0x1234);
479 assert(readIntLE(u16, []u8{ 0x12, 0x34 }) == 0x3412);522 testing.expect(readIntSliceLittle(u16, []u8{ 0x12, 0x34 }) == 0x3412);
480523
481 assert(readIntBE(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024);524 testing.expect(readIntSliceBig(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024);
482 assert(readIntLE(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec);525 testing.expect(readIntSliceLittle(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec);
483526
484 assert(readIntBE(i8, []u8{0xff}) == -1);527 testing.expect(readIntSliceBig(i8, []u8{0xff}) == -1);
485 assert(readIntLE(i8, []u8{0xfe}) == -2);528 testing.expect(readIntSliceLittle(i8, []u8{0xfe}) == -2);
486529
487 assert(readIntBE(i16, []u8{ 0xff, 0xfd }) == -3);530 testing.expect(readIntSliceBig(i16, []u8{ 0xff, 0xfd }) == -3);
488 assert(readIntLE(i16, []u8{ 0xfc, 0xff }) == -4);531 testing.expect(readIntSliceLittle(i16, []u8{ 0xfc, 0xff }) == -4);
489}532}
490533
491/// Writes an integer to memory with size equal to bytes.len. Pads with zeroes534/// Writes an integer to memory, storing it in twos-complement.
492/// to fill the entire buffer provided.535/// This function always succeeds, has defined behavior for all inputs, and
493/// value must be an integer.536/// accepts any integer bit width.
494pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void {537/// This function stores in native endian, which means it is implemented as a simple
495 const uint = @IntType(false, @typeOf(value).bit_count);538/// memory store.
496 var bits = @truncate(uint, value);539pub fn writeIntNative(comptime T: type, buf: *[(T.bit_count + 7) / 8]u8, value: T) void {
497 switch (endian) {540 @ptrCast(*align(1) T, buf).* = value;
498 builtin.Endian.Big => {541}
499 var index: usize = buf.len;
500 while (index != 0) {
501 index -= 1;
502542
503 buf[index] = @truncate(u8, bits);543/// Writes an integer to memory, storing it in twos-complement.
504 bits >>= 8;544/// This function always succeeds, has defined behavior for all inputs, but
505 }545/// the integer bit width must be divisible by 8.
506 },546/// This function stores in foreign endian, which means it does a @bswap first.
507 builtin.Endian.Little => {547pub fn writeIntForeign(comptime T: type, buf: *[@divExact(T.bit_count, 8)]u8, value: T) void {
508 for (buf) |*b| {548 writeIntNative(T, buf, @bswap(T, value));
509 b.* = @truncate(u8, bits);549}
510 bits >>= 8;550
511 }551pub const writeIntLittle = switch (builtin.endian) {
512 },552 builtin.Endian.Little => writeIntNative,
553 builtin.Endian.Big => writeIntForeign,
554};
555
556pub const writeIntBig = switch (builtin.endian) {
557 builtin.Endian.Little => writeIntForeign,
558 builtin.Endian.Big => writeIntNative,
559};
560
561/// Writes an integer to memory, storing it in twos-complement.
562/// This function always succeeds, has defined behavior for all inputs, but
563/// the integer bit width must be divisible by 8.
564pub fn writeInt(comptime T: type, buffer: *[@divExact(T.bit_count, 8)]u8, value: T, endian: builtin.Endian) void {
565 if (endian == builtin.endian) {
566 return writeIntNative(T, buffer, value);
567 } else {
568 return writeIntForeign(T, buffer, value);
513 }569 }
514 assert(bits == 0);
515}570}
516571
517pub fn writeIntBE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {572/// Writes a twos-complement little-endian integer to memory.
518 assert(T.bit_count % 8 == 0);573/// Asserts that buf.len >= T.bit_count / 8.
574/// The bit count of T must be divisible by 8.
575/// Any extra bytes in buffer after writing the integer are set to zero. To
576/// avoid the branch to check for extra buffer bytes, use writeIntLittle
577/// instead.
578pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {
579 assert(buffer.len >= @divExact(T.bit_count, 8));
580
581 // TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough
519 const uint = @IntType(false, T.bit_count);582 const uint = @IntType(false, T.bit_count);
520 if (uint == u0) {583 var bits = @truncate(uint, value);
521 return;584 for (buffer) |*b| {
522 }585 b.* = @truncate(u8, bits);
523 var bits = @bitCast(uint, value);586 bits >>= 8;
524 if (uint == u8) {
525 buf[0] = bits;
526 return;
527 }587 }
528 var index: usize = buf.len;588}
589
590/// Writes a twos-complement big-endian integer to memory.
591/// Asserts that buffer.len >= T.bit_count / 8.
592/// The bit count of T must be divisible by 8.
593/// Any extra bytes in buffer before writing the integer are set to zero. To
594/// avoid the branch to check for extra buffer bytes, use writeIntBig instead.
595pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void {
596 assert(buffer.len >= @divExact(T.bit_count, 8));
597
598 // TODO I want to call writeIntBig here but comptime eval facilities aren't good enough
599 const uint = @IntType(false, T.bit_count);
600 var bits = @truncate(uint, value);
601 var index: usize = buffer.len;
529 while (index != 0) {602 while (index != 0) {
530 index -= 1;603 index -= 1;
531604 buffer[index] = @truncate(u8, bits);
532 buf[index] = @truncate(u8, bits);
533 bits >>= 8;605 bits >>= 8;
534 }606 }
535 assert(bits == 0);
536}607}
537608
538pub fn writeIntLE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {609pub const writeIntSliceNative = switch (builtin.endian) {
539 assert(T.bit_count % 8 == 0);610 builtin.Endian.Little => writeIntSliceLittle,
540 const uint = @IntType(false, T.bit_count);611 builtin.Endian.Big => writeIntSliceBig,
541 if (uint == u0) {612};
542 return;613
543 }614pub const writeIntSliceForeign = switch (builtin.endian) {
544 var bits = @bitCast(uint, value);615 builtin.Endian.Little => writeIntSliceBig,
545 if (uint == u8) {616 builtin.Endian.Big => writeIntSliceLittle,
546 buf[0] = bits;617};
547 return;618
548 }619/// Writes a twos-complement integer to memory, with the specified endianness.
549 for (buf) |*b| {620/// Asserts that buf.len >= T.bit_count / 8.
550 b.* = @truncate(u8, bits);621/// The bit count of T must be evenly divisible by 8.
551 bits >>= 8;622/// Any extra bytes in buffer not part of the integer are set to zero, with
623/// respect to endianness. To avoid the branch to check for extra buffer bytes,
624/// use writeInt instead.
625pub fn writeIntSlice(comptime T: type, buffer: []u8, value: T, endian: builtin.Endian) void {
626 comptime assert(T.bit_count % 8 == 0);
627 switch (endian) {
628 builtin.Endian.Little => return writeIntSliceLittle(T, buffer, value),
629 builtin.Endian.Big => return writeIntSliceBig(T, buffer, value),
552 }630 }
553 assert(bits == 0);
554}631}
555632
556test "writeIntBE/LE" {633test "writeIntBig and writeIntLittle" {
557 var buf0: [0]u8 = undefined;634 var buf0: [0]u8 = undefined;
558 var buf1: [1]u8 = undefined;635 var buf1: [1]u8 = undefined;
559 var buf2: [2]u8 = undefined;636 var buf2: [2]u8 = undefined;
560 var buf9: [9]u8 = undefined;637 var buf9: [9]u8 = undefined;
561638
562 writeIntBE(u0, &buf0, 0x0);639 writeIntBig(u0, &buf0, 0x0);
563 assert(eql_slice_u8(buf0[0..], []u8{}));640 testing.expect(eql_slice_u8(buf0[0..], []u8{}));
564 writeIntLE(u0, &buf0, 0x0);641 writeIntLittle(u0, &buf0, 0x0);
565 assert(eql_slice_u8(buf0[0..], []u8{}));642 testing.expect(eql_slice_u8(buf0[0..], []u8{}));
566643
567 writeIntBE(u8, &buf1, 0x12);644 writeIntBig(u8, &buf1, 0x12);
568 assert(eql_slice_u8(buf1[0..], []u8{0x12}));645 testing.expect(eql_slice_u8(buf1[0..], []u8{0x12}));
569 writeIntLE(u8, &buf1, 0x34);646 writeIntLittle(u8, &buf1, 0x34);
570 assert(eql_slice_u8(buf1[0..], []u8{0x34}));647 testing.expect(eql_slice_u8(buf1[0..], []u8{0x34}));
571648
572 writeIntBE(u16, &buf2, 0x1234);649 writeIntBig(u16, &buf2, 0x1234);
573 assert(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 }));650 testing.expect(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 }));
574 writeIntLE(u16, &buf2, 0x5678);651 writeIntLittle(u16, &buf2, 0x5678);
575 assert(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 }));652 testing.expect(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 }));
576653
577 writeIntBE(u72, &buf9, 0x123456789abcdef024);654 writeIntBig(u72, &buf9, 0x123456789abcdef024);
578 assert(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }));655 testing.expect(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }));
579 writeIntLE(u72, &buf9, 0xfedcba9876543210ec);656 writeIntLittle(u72, &buf9, 0xfedcba9876543210ec);
580 assert(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }));657 testing.expect(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }));
581658
582 writeIntBE(i8, &buf1, -1);659 writeIntBig(i8, &buf1, -1);
583 assert(eql_slice_u8(buf1[0..], []u8{0xff}));660 testing.expect(eql_slice_u8(buf1[0..], []u8{0xff}));
584 writeIntLE(i8, &buf1, -2);661 writeIntLittle(i8, &buf1, -2);
585 assert(eql_slice_u8(buf1[0..], []u8{0xfe}));662 testing.expect(eql_slice_u8(buf1[0..], []u8{0xfe}));
586663
587 writeIntBE(i16, &buf2, -3);664 writeIntBig(i16, &buf2, -3);
588 assert(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd }));665 testing.expect(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd }));
589 writeIntLE(i16, &buf2, -4);666 writeIntLittle(i16, &buf2, -4);
590 assert(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff }));667 testing.expect(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff }));
591}668}
592669
593pub fn hash_slice_u8(k: []const u8) u32 {670pub fn hash_slice_u8(k: []const u8) u32 {
...@@ -604,23 +681,114 @@ pub fn eql_slice_u8(a: []const u8, b: []const u8) bool {...@@ -604,23 +681,114 @@ pub fn eql_slice_u8(a: []const u8, b: []const u8) bool {
604}681}
605682
606/// Returns an iterator that iterates over the slices of `buffer` that are not683/// Returns an iterator that iterates over the slices of `buffer` that are not
607/// any of the bytes in `split_bytes`.684/// any of the bytes in `delimiter_bytes`.
608/// split(" abc def ghi ", " ")685/// tokenize(" abc def ghi ", " ")
609/// Will return slices for "abc", "def", "ghi", null, in that order.686/// Will return slices for "abc", "def", "ghi", null, in that order.
610pub fn split(buffer: []const u8, split_bytes: []const u8) SplitIterator {687/// If `buffer` is empty, the iterator will return null.
688/// If `delimiter_bytes` does not exist in buffer,
689/// the iterator will return `buffer`, null, in that order.
690/// See also the related function `separate`.
691pub fn tokenize(buffer: []const u8, delimiter_bytes: []const u8) TokenIterator {
692 return TokenIterator{
693 .index = 0,
694 .buffer = buffer,
695 .delimiter_bytes = delimiter_bytes,
696 };
697}
698
699test "mem.tokenize" {
700 var it = tokenize(" abc def ghi ", " ");
701 testing.expect(eql(u8, it.next().?, "abc"));
702 testing.expect(eql(u8, it.next().?, "def"));
703 testing.expect(eql(u8, it.next().?, "ghi"));
704 testing.expect(it.next() == null);
705
706 it = tokenize("..\\bob", "\\");
707 testing.expect(eql(u8, it.next().?, ".."));
708 testing.expect(eql(u8, "..", "..\\bob"[0..it.index]));
709 testing.expect(eql(u8, it.next().?, "bob"));
710 testing.expect(it.next() == null);
711
712 it = tokenize("//a/b", "/");
713 testing.expect(eql(u8, it.next().?, "a"));
714 testing.expect(eql(u8, it.next().?, "b"));
715 testing.expect(eql(u8, "//a/b", "//a/b"[0..it.index]));
716 testing.expect(it.next() == null);
717
718 it = tokenize("|", "|");
719 testing.expect(it.next() == null);
720
721 it = tokenize("", "|");
722 testing.expect(it.next() == null);
723
724 it = tokenize("hello", "");
725 testing.expect(eql(u8, it.next().?, "hello"));
726 testing.expect(it.next() == null);
727
728 it = tokenize("hello", " ");
729 testing.expect(eql(u8, it.next().?, "hello"));
730 testing.expect(it.next() == null);
731}
732
733test "mem.tokenize (multibyte)" {
734 var it = tokenize("a|b,c/d e", " /,|");
735 testing.expect(eql(u8, it.next().?, "a"));
736 testing.expect(eql(u8, it.next().?, "b"));
737 testing.expect(eql(u8, it.next().?, "c"));
738 testing.expect(eql(u8, it.next().?, "d"));
739 testing.expect(eql(u8, it.next().?, "e"));
740 testing.expect(it.next() == null);
741}
742
743/// Returns an iterator that iterates over the slices of `buffer` that
744/// are separated by bytes in `delimiter`.
745/// separate("abc|def||ghi", "|")
746/// will return slices for "abc", "def", "", "ghi", null, in that order.
747/// If `delimiter` does not exist in buffer,
748/// the iterator will return `buffer`, null, in that order.
749/// The delimiter length must not be zero.
750/// See also the related function `tokenize`.
751/// It is planned to rename this function to `split` before 1.0.0, like this:
752/// pub fn split(buffer: []const u8, delimiter: []const u8) SplitIterator {
753pub fn separate(buffer: []const u8, delimiter: []const u8) SplitIterator {
754 assert(delimiter.len != 0);
611 return SplitIterator{755 return SplitIterator{
612 .index = 0,756 .index = 0,
613 .buffer = buffer,757 .buffer = buffer,
614 .split_bytes = split_bytes,758 .delimiter = delimiter,
615 };759 };
616}760}
617761
618test "mem.split" {762test "mem.separate" {
619 var it = split(" abc def ghi ", " ");763 var it = separate("abc|def||ghi", "|");
620 assert(eql(u8, it.next().?, "abc"));764 testing.expect(eql(u8, it.next().?, "abc"));
621 assert(eql(u8, it.next().?, "def"));765 testing.expect(eql(u8, it.next().?, "def"));
622 assert(eql(u8, it.next().?, "ghi"));766 testing.expect(eql(u8, it.next().?, ""));
623 assert(it.next() == null);767 testing.expect(eql(u8, it.next().?, "ghi"));
768 testing.expect(it.next() == null);
769
770 it = separate("", "|");
771 testing.expect(eql(u8, it.next().?, ""));
772 testing.expect(it.next() == null);
773
774 it = separate("|", "|");
775 testing.expect(eql(u8, it.next().?, ""));
776 testing.expect(eql(u8, it.next().?, ""));
777 testing.expect(it.next() == null);
778
779 it = separate("hello", " ");
780 testing.expect(eql(u8, it.next().?, "hello"));
781 testing.expect(it.next() == null);
782}
783
784test "mem.separate (multibyte)" {
785 var it = separate("a, b ,, c, d, e", ", ");
786 testing.expect(eql(u8, it.next().?, "a"));
787 testing.expect(eql(u8, it.next().?, "b ,"));
788 testing.expect(eql(u8, it.next().?, "c"));
789 testing.expect(eql(u8, it.next().?, "d"));
790 testing.expect(eql(u8, it.next().?, "e"));
791 testing.expect(it.next() == null);
624}792}
625793
626pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool {794pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool {
...@@ -628,8 +796,8 @@ pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool...@@ -628,8 +796,8 @@ pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool
628}796}
629797
630test "mem.startsWith" {798test "mem.startsWith" {
631 assert(startsWith(u8, "Bob", "Bo"));799 testing.expect(startsWith(u8, "Bob", "Bo"));
632 assert(!startsWith(u8, "Needle in haystack", "haystack"));800 testing.expect(!startsWith(u8, "Needle in haystack", "haystack"));
633}801}
634802
635pub fn endsWith(comptime T: type, haystack: []const T, needle: []const T) bool {803pub fn endsWith(comptime T: type, haystack: []const T, needle: []const T) bool {
...@@ -637,16 +805,17 @@ pub fn endsWith(comptime T: type, haystack: []const T, needle: []const T) bool {...@@ -637,16 +805,17 @@ pub fn endsWith(comptime T: type, haystack: []const T, needle: []const T) bool {
637}805}
638806
639test "mem.endsWith" {807test "mem.endsWith" {
640 assert(endsWith(u8, "Needle in haystack", "haystack"));808 testing.expect(endsWith(u8, "Needle in haystack", "haystack"));
641 assert(!endsWith(u8, "Bob", "Bo"));809 testing.expect(!endsWith(u8, "Bob", "Bo"));
642}810}
643811
644pub const SplitIterator = struct {812pub const TokenIterator = struct {
645 buffer: []const u8,813 buffer: []const u8,
646 split_bytes: []const u8,814 delimiter_bytes: []const u8,
647 index: usize,815 index: usize,
648816
649 pub fn next(self: *SplitIterator) ?[]const u8 {817 /// Returns a slice of the next token, or null if tokenization is complete.
818 pub fn next(self: *TokenIterator) ?[]const u8 {
650 // move to beginning of token819 // move to beginning of token
651 while (self.index < self.buffer.len and self.isSplitByte(self.buffer[self.index])) : (self.index += 1) {}820 while (self.index < self.buffer.len and self.isSplitByte(self.buffer[self.index])) : (self.index += 1) {}
652 const start = self.index;821 const start = self.index;
...@@ -662,16 +831,16 @@ pub const SplitIterator = struct {...@@ -662,16 +831,16 @@ pub const SplitIterator = struct {
662 }831 }
663832
664 /// Returns a slice of the remaining bytes. Does not affect iterator state.833 /// Returns a slice of the remaining bytes. Does not affect iterator state.
665 pub fn rest(self: *const SplitIterator) []const u8 {834 pub fn rest(self: TokenIterator) []const u8 {
666 // move to beginning of token835 // move to beginning of token
667 var index: usize = self.index;836 var index: usize = self.index;
668 while (index < self.buffer.len and self.isSplitByte(self.buffer[index])) : (index += 1) {}837 while (index < self.buffer.len and self.isSplitByte(self.buffer[index])) : (index += 1) {}
669 return self.buffer[index..];838 return self.buffer[index..];
670 }839 }
671840
672 fn isSplitByte(self: *const SplitIterator, byte: u8) bool {841 fn isSplitByte(self: TokenIterator, byte: u8) bool {
673 for (self.split_bytes) |split_byte| {842 for (self.delimiter_bytes) |delimiter_byte| {
674 if (byte == split_byte) {843 if (byte == delimiter_byte) {
675 return true;844 return true;
676 }845 }
677 }846 }
...@@ -679,48 +848,72 @@ pub const SplitIterator = struct {...@@ -679,48 +848,72 @@ pub const SplitIterator = struct {
679 }848 }
680};849};
681850
682/// Naively combines a series of strings with a separator.851pub const SplitIterator = struct {
683/// Allocates memory for the result, which must be freed by the caller.852 buffer: []const u8,
684pub fn join(allocator: *Allocator, sep: u8, strings: ...) ![]u8 {853 index: ?usize,
685 comptime assert(strings.len >= 1);854 delimiter: []const u8,
686 var total_strings_len: usize = strings.len; // 1 sep per string855
687 {856 /// Returns a slice of the next field, or null if splitting is complete.
688 comptime var string_i = 0;857 pub fn next(self: *SplitIterator) ?[]const u8 {
689 inline while (string_i < strings.len) : (string_i += 1) {858 const start = self.index orelse return null;
690 const arg = ([]const u8)(strings[string_i]);859 const end = if (indexOfPos(u8, self.buffer, start, self.delimiter)) |delim_start| blk: {
691 total_strings_len += arg.len;860 self.index = delim_start + self.delimiter.len;
692 }861 break :blk delim_start;
862 } else blk: {
863 self.index = null;
864 break :blk self.buffer.len;
865 };
866 return self.buffer[start..end];
693 }867 }
694868
695 const buf = try allocator.alloc(u8, total_strings_len);869 /// Returns a slice of the remaining bytes. Does not affect iterator state.
870 pub fn rest(self: SplitIterator) []const u8 {
871 const end = self.buffer.len;
872 const start = self.index orelse end;
873 return self.buffer[start..end];
874 }
875};
876
877/// Naively combines a series of slices with a separator.
878/// Allocates memory for the result, which must be freed by the caller.
879pub fn join(allocator: *Allocator, separator: []const u8, slices: []const []const u8) ![]u8 {
880 if (slices.len == 0) return (([*]u8)(undefined))[0..0];
881
882 const total_len = blk: {
883 var sum: usize = separator.len * (slices.len - 1);
884 for (slices) |slice|
885 sum += slice.len;
886 break :blk sum;
887 };
888
889 const buf = try allocator.alloc(u8, total_len);
696 errdefer allocator.free(buf);890 errdefer allocator.free(buf);
697891
698 var buf_index: usize = 0;892 copy(u8, buf, slices[0]);
699 comptime var string_i = 0;893 var buf_index: usize = slices[0].len;
700 inline while (true) {894 for (slices[1..]) |slice| {
701 const arg = ([]const u8)(strings[string_i]);895 copy(u8, buf[buf_index..], separator);
702 string_i += 1;896 buf_index += separator.len;
703 copy(u8, buf[buf_index..], arg);897 copy(u8, buf[buf_index..], slice);
704 buf_index += arg.len;898 buf_index += slice.len;
705 if (string_i >= strings.len) break;
706 if (buf[buf_index - 1] != sep) {
707 buf[buf_index] = sep;
708 buf_index += 1;
709 }
710 }899 }
711900
712 return allocator.shrink(u8, buf, buf_index);901 // No need for shrink since buf is exactly the correct size.
902 return buf;
713}903}
714904
715test "mem.join" {905test "mem.join" {
716 assert(eql(u8, try join(debug.global_allocator, ',', "a", "b", "c"), "a,b,c"));906 var buf: [1024]u8 = undefined;
717 assert(eql(u8, try join(debug.global_allocator, ',', "a"), "a"));907 const a = &std.heap.FixedBufferAllocator.init(&buf).allocator;
908 testing.expect(eql(u8, try join(a, ",", [][]const u8{ "a", "b", "c" }), "a,b,c"));
909 testing.expect(eql(u8, try join(a, ",", [][]const u8{"a"}), "a"));
910 testing.expect(eql(u8, try join(a, ",", [][]const u8{ "a", "", "b", "", "c" }), "a,,b,,c"));
718}911}
719912
720test "testStringEquality" {913test "testStringEquality" {
721 assert(eql(u8, "abcd", "abcd"));914 testing.expect(eql(u8, "abcd", "abcd"));
722 assert(!eql(u8, "abcdef", "abZdef"));915 testing.expect(!eql(u8, "abcdef", "abZdef"));
723 assert(!eql(u8, "abcdefg", "abcdef"));916 testing.expect(!eql(u8, "abcdefg", "abcdef"));
724}917}
725918
726test "testReadInt" {919test "testReadInt" {
...@@ -735,12 +928,12 @@ fn testReadIntImpl() void {...@@ -735,12 +928,12 @@ fn testReadIntImpl() void {
735 0x56,928 0x56,
736 0x78,929 0x78,
737 };930 };
738 assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678);931 testing.expect(readInt(u32, &bytes, builtin.Endian.Big) == 0x12345678);
739 assert(readIntBE(u32, bytes) == 0x12345678);932 testing.expect(readIntBig(u32, &bytes) == 0x12345678);
740 assert(readIntBE(i32, bytes) == 0x12345678);933 testing.expect(readIntBig(i32, &bytes) == 0x12345678);
741 assert(readInt(bytes, u32, builtin.Endian.Little) == 0x78563412);934 testing.expect(readInt(u32, &bytes, builtin.Endian.Little) == 0x78563412);
742 assert(readIntLE(u32, bytes) == 0x78563412);935 testing.expect(readIntLittle(u32, &bytes) == 0x78563412);
743 assert(readIntLE(i32, bytes) == 0x78563412);936 testing.expect(readIntLittle(i32, &bytes) == 0x78563412);
744 }937 }
745 {938 {
746 const buf = []u8{939 const buf = []u8{
...@@ -749,8 +942,8 @@ fn testReadIntImpl() void {...@@ -749,8 +942,8 @@ fn testReadIntImpl() void {
749 0x12,942 0x12,
750 0x34,943 0x34,
751 };944 };
752 const answer = readInt(buf, u64, builtin.Endian.Big);945 const answer = readInt(u32, &buf, builtin.Endian.Big);
753 assert(answer == 0x00001234);946 testing.expect(answer == 0x00001234);
754 }947 }
755 {948 {
756 const buf = []u8{949 const buf = []u8{
...@@ -759,30 +952,42 @@ fn testReadIntImpl() void {...@@ -759,30 +952,42 @@ fn testReadIntImpl() void {
759 0x00,952 0x00,
760 0x00,953 0x00,
761 };954 };
762 const answer = readInt(buf, u64, builtin.Endian.Little);955 const answer = readInt(u32, &buf, builtin.Endian.Little);
763 assert(answer == 0x00003412);956 testing.expect(answer == 0x00003412);
764 }957 }
765 {958 {
766 const bytes = []u8{959 const bytes = []u8{
767 0xff,960 0xff,
768 0xfe,961 0xfe,
769 };962 };
770 assert(readIntBE(u16, bytes) == 0xfffe);963 testing.expect(readIntBig(u16, &bytes) == 0xfffe);
771 assert(readIntBE(i16, bytes) == -0x0002);964 testing.expect(readIntBig(i16, &bytes) == -0x0002);
772 assert(readIntLE(u16, bytes) == 0xfeff);965 testing.expect(readIntLittle(u16, &bytes) == 0xfeff);
773 assert(readIntLE(i16, bytes) == -0x0101);966 testing.expect(readIntLittle(i16, &bytes) == -0x0101);
774 }967 }
775}968}
776969
777test "testWriteInt" {970test "std.mem.writeIntSlice" {
778 testWriteIntImpl();971 testWriteIntImpl();
779 comptime testWriteIntImpl();972 comptime testWriteIntImpl();
780}973}
781fn testWriteIntImpl() void {974fn testWriteIntImpl() void {
782 var bytes: [8]u8 = undefined;975 var bytes: [8]u8 = undefined;
783976
784 writeInt(bytes[0..], u64(0x12345678CAFEBABE), builtin.Endian.Big);977 writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Big);
785 assert(eql(u8, bytes, []u8{978 testing.expect(eql(u8, bytes, []u8{
979 0x00, 0x00, 0x00, 0x00,
980 0x00, 0x00, 0x00, 0x00,
981 }));
982
983 writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Little);
984 testing.expect(eql(u8, bytes, []u8{
985 0x00, 0x00, 0x00, 0x00,
986 0x00, 0x00, 0x00, 0x00,
987 }));
988
989 writeIntSlice(u64, bytes[0..], 0x12345678CAFEBABE, builtin.Endian.Big);
990 testing.expect(eql(u8, bytes, []u8{
786 0x12,991 0x12,
787 0x34,992 0x34,
788 0x56,993 0x56,
...@@ -793,8 +998,8 @@ fn testWriteIntImpl() void {...@@ -793,8 +998,8 @@ fn testWriteIntImpl() void {
793 0xBE,998 0xBE,
794 }));999 }));
7951000
796 writeInt(bytes[0..], u64(0xBEBAFECA78563412), builtin.Endian.Little);1001 writeIntSlice(u64, bytes[0..], 0xBEBAFECA78563412, builtin.Endian.Little);
797 assert(eql(u8, bytes, []u8{1002 testing.expect(eql(u8, bytes, []u8{
798 0x12,1003 0x12,
799 0x34,1004 0x34,
800 0x56,1005 0x56,
...@@ -805,8 +1010,8 @@ fn testWriteIntImpl() void {...@@ -805,8 +1010,8 @@ fn testWriteIntImpl() void {
805 0xBE,1010 0xBE,
806 }));1011 }));
8071012
808 writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big);1013 writeIntSlice(u32, bytes[0..], 0x12345678, builtin.Endian.Big);
809 assert(eql(u8, bytes, []u8{1014 testing.expect(eql(u8, bytes, []u8{
810 0x00,1015 0x00,
811 0x00,1016 0x00,
812 0x00,1017 0x00,
...@@ -817,8 +1022,8 @@ fn testWriteIntImpl() void {...@@ -817,8 +1022,8 @@ fn testWriteIntImpl() void {
817 0x78,1022 0x78,
818 }));1023 }));
8191024
820 writeInt(bytes[0..], u32(0x78563412), builtin.Endian.Little);1025 writeIntSlice(u32, bytes[0..], 0x78563412, builtin.Endian.Little);
821 assert(eql(u8, bytes, []u8{1026 testing.expect(eql(u8, bytes, []u8{
822 0x12,1027 0x12,
823 0x34,1028 0x34,
824 0x56,1029 0x56,
...@@ -829,8 +1034,8 @@ fn testWriteIntImpl() void {...@@ -829,8 +1034,8 @@ fn testWriteIntImpl() void {
829 0x00,1034 0x00,
830 }));1035 }));
8311036
832 writeInt(bytes[0..], u16(0x1234), builtin.Endian.Big);1037 writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Big);
833 assert(eql(u8, bytes, []u8{1038 testing.expect(eql(u8, bytes, []u8{
834 0x00,1039 0x00,
835 0x00,1040 0x00,
836 0x00,1041 0x00,
...@@ -841,8 +1046,8 @@ fn testWriteIntImpl() void {...@@ -841,8 +1046,8 @@ fn testWriteIntImpl() void {
841 0x34,1046 0x34,
842 }));1047 }));
8431048
844 writeInt(bytes[0..], u16(0x1234), builtin.Endian.Little);1049 writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Little);
845 assert(eql(u8, bytes, []u8{1050 testing.expect(eql(u8, bytes, []u8{
846 0x34,1051 0x34,
847 0x12,1052 0x12,
848 0x00,1053 0x00,
...@@ -863,7 +1068,7 @@ pub fn min(comptime T: type, slice: []const T) T {...@@ -863,7 +1068,7 @@ pub fn min(comptime T: type, slice: []const T) T {
863}1068}
8641069
865test "mem.min" {1070test "mem.min" {
866 assert(min(u8, "abcdefg") == 'a');1071 testing.expect(min(u8, "abcdefg") == 'a');
867}1072}
8681073
869pub fn max(comptime T: type, slice: []const T) T {1074pub fn max(comptime T: type, slice: []const T) T {
...@@ -875,7 +1080,7 @@ pub fn max(comptime T: type, slice: []const T) T {...@@ -875,7 +1080,7 @@ pub fn max(comptime T: type, slice: []const T) T {
875}1080}
8761081
877test "mem.max" {1082test "mem.max" {
878 assert(max(u8, "abcdefg") == 'g');1083 testing.expect(max(u8, "abcdefg") == 'g');
879}1084}
8801085
881pub fn swap(comptime T: type, a: *T, b: *T) void {1086pub fn swap(comptime T: type, a: *T, b: *T) void {
...@@ -903,7 +1108,7 @@ test "std.mem.reverse" {...@@ -903,7 +1108,7 @@ test "std.mem.reverse" {
903 };1108 };
904 reverse(i32, arr[0..]);1109 reverse(i32, arr[0..]);
9051110
906 assert(eql(i32, arr, []i32{1111 testing.expect(eql(i32, arr, []i32{
907 4,1112 4,
908 2,1113 2,
909 1,1114 1,
...@@ -930,7 +1135,7 @@ test "std.mem.rotate" {...@@ -930,7 +1135,7 @@ test "std.mem.rotate" {
930 };1135 };
931 rotate(i32, arr[0..], 2);1136 rotate(i32, arr[0..], 2);
9321137
933 assert(eql(i32, arr, []i32{1138 testing.expect(eql(i32, arr, []i32{
934 1,1139 1,
935 2,1140 2,
936 4,1141 4,
...@@ -939,29 +1144,52 @@ test "std.mem.rotate" {...@@ -939,29 +1144,52 @@ test "std.mem.rotate" {
939 }));1144 }));
940}1145}
9411146
942// TODO: When https://github.com/ziglang/zig/issues/649 is solved these can be done by1147/// Converts a little-endian integer to host endianness.
943// endian-casting the pointer and then dereferencing1148pub fn littleToNative(comptime T: type, x: T) T {
1149 return switch (builtin.endian) {
1150 builtin.Endian.Little => x,
1151 builtin.Endian.Big => @bswap(T, x),
1152 };
1153}
9441154
945pub fn endianSwapIfLe(comptime T: type, x: T) T {1155/// Converts a big-endian integer to host endianness.
946 return endianSwapIf(builtin.Endian.Little, T, x);1156pub fn bigToNative(comptime T: type, x: T) T {
1157 return switch (builtin.endian) {
1158 builtin.Endian.Little => @bswap(T, x),
1159 builtin.Endian.Big => x,
1160 };
947}1161}
9481162
949pub fn endianSwapIfBe(comptime T: type, x: T) T {1163/// Converts an integer from specified endianness to host endianness.
950 return endianSwapIf(builtin.Endian.Big, T, x);1164pub fn toNative(comptime T: type, x: T, endianness_of_x: builtin.Endian) T {
1165 return switch (endianness_of_x) {
1166 builtin.Endian.Little => littleToNative(T, x),
1167 builtin.Endian.Big => bigToNative(T, x),
1168 };
951}1169}
9521170
953pub fn endianSwapIf(endian: builtin.Endian, comptime T: type, x: T) T {1171/// Converts an integer which has host endianness to the desired endianness.
954 return if (builtin.endian == endian) endianSwap(T, x) else x;1172pub fn nativeTo(comptime T: type, x: T, desired_endianness: builtin.Endian) T {
1173 return switch (desired_endianness) {
1174 builtin.Endian.Little => nativeToLittle(T, x),
1175 builtin.Endian.Big => nativeToBig(T, x),
1176 };
955}1177}
9561178
957pub fn endianSwap(comptime T: type, x: T) T {1179/// Converts an integer which has host endianness to little endian.
958 var buf: [@sizeOf(T)]u8 = undefined;1180pub fn nativeToLittle(comptime T: type, x: T) T {
959 mem.writeInt(buf[0..], x, builtin.Endian.Little);1181 return switch (builtin.endian) {
960 return mem.readInt(buf, T, builtin.Endian.Big);1182 builtin.Endian.Little => x,
1183 builtin.Endian.Big => @bswap(T, x),
1184 };
961}1185}
9621186
963test "std.mem.endianSwap" {1187/// Converts an integer which has host endianness to big endian.
964 assert(endianSwap(u32, 0xDEADBEEF) == 0xEFBEADDE);1188pub fn nativeToBig(comptime T: type, x: T) T {
1189 return switch (builtin.endian) {
1190 builtin.Endian.Little => @bswap(T, x),
1191 builtin.Endian.Big => x,
1192 };
965}1193}
9661194
967fn AsBytesReturnType(comptime P: type) type {1195fn AsBytesReturnType(comptime P: type) type {
...@@ -989,12 +1217,12 @@ test "std.mem.asBytes" {...@@ -989,12 +1217,12 @@ test "std.mem.asBytes" {
989 builtin.Endian.Little => "\xEF\xBE\xAD\xDE",1217 builtin.Endian.Little => "\xEF\xBE\xAD\xDE",
990 };1218 };
9911219
992 debug.assert(std.mem.eql(u8, asBytes(&deadbeef), deadbeef_bytes));1220 testing.expect(std.mem.eql(u8, asBytes(&deadbeef), deadbeef_bytes));
9931221
994 var codeface = u32(0xC0DEFACE);1222 var codeface = u32(0xC0DEFACE);
995 for (asBytes(&codeface).*) |*b|1223 for (asBytes(&codeface).*) |*b|
996 b.* = 0;1224 b.* = 0;
997 debug.assert(codeface == 0);1225 testing.expect(codeface == 0);
9981226
999 const S = packed struct {1227 const S = packed struct {
1000 a: u8,1228 a: u8,
...@@ -1009,7 +1237,7 @@ test "std.mem.asBytes" {...@@ -1009,7 +1237,7 @@ test "std.mem.asBytes" {
1009 .c = 0xDE,1237 .c = 0xDE,
1010 .d = 0xA1,1238 .d = 0xA1,
1011 };1239 };
1012 debug.assert(std.mem.eql(u8, asBytes(&inst), "\xBE\xEF\xDE\xA1"));1240 testing.expect(std.mem.eql(u8, asBytes(&inst), "\xBE\xEF\xDE\xA1"));
1013}1241}
10141242
1015///Given any value, returns a copy of its bytes in an array.1243///Given any value, returns a copy of its bytes in an array.
...@@ -1020,14 +1248,14 @@ pub fn toBytes(value: var) [@sizeOf(@typeOf(value))]u8 {...@@ -1020,14 +1248,14 @@ pub fn toBytes(value: var) [@sizeOf(@typeOf(value))]u8 {
1020test "std.mem.toBytes" {1248test "std.mem.toBytes" {
1021 var my_bytes = toBytes(u32(0x12345678));1249 var my_bytes = toBytes(u32(0x12345678));
1022 switch (builtin.endian) {1250 switch (builtin.endian) {
1023 builtin.Endian.Big => debug.assert(std.mem.eql(u8, my_bytes, "\x12\x34\x56\x78")),1251 builtin.Endian.Big => testing.expect(std.mem.eql(u8, my_bytes, "\x12\x34\x56\x78")),
1024 builtin.Endian.Little => debug.assert(std.mem.eql(u8, my_bytes, "\x78\x56\x34\x12")),1252 builtin.Endian.Little => testing.expect(std.mem.eql(u8, my_bytes, "\x78\x56\x34\x12")),
1025 }1253 }
10261254
1027 my_bytes[0] = '\x99';1255 my_bytes[0] = '\x99';
1028 switch (builtin.endian) {1256 switch (builtin.endian) {
1029 builtin.Endian.Big => debug.assert(std.mem.eql(u8, my_bytes, "\x99\x34\x56\x78")),1257 builtin.Endian.Big => testing.expect(std.mem.eql(u8, my_bytes, "\x99\x34\x56\x78")),
1030 builtin.Endian.Little => debug.assert(std.mem.eql(u8, my_bytes, "\x99\x56\x34\x12")),1258 builtin.Endian.Little => testing.expect(std.mem.eql(u8, my_bytes, "\x99\x56\x34\x12")),
1031 }1259 }
1032}1260}
10331261
...@@ -1056,17 +1284,17 @@ test "std.mem.bytesAsValue" {...@@ -1056,17 +1284,17 @@ test "std.mem.bytesAsValue" {
1056 builtin.Endian.Little => "\xEF\xBE\xAD\xDE",1284 builtin.Endian.Little => "\xEF\xBE\xAD\xDE",
1057 };1285 };
10581286
1059 debug.assert(deadbeef == bytesAsValue(u32, &deadbeef_bytes).*);1287 testing.expect(deadbeef == bytesAsValue(u32, &deadbeef_bytes).*);
10601288
1061 var codeface_bytes = switch (builtin.endian) {1289 var codeface_bytes = switch (builtin.endian) {
1062 builtin.Endian.Big => "\xC0\xDE\xFA\xCE",1290 builtin.Endian.Big => "\xC0\xDE\xFA\xCE",
1063 builtin.Endian.Little => "\xCE\xFA\xDE\xC0",1291 builtin.Endian.Little => "\xCE\xFA\xDE\xC0",
1064 };1292 };
1065 var codeface = bytesAsValue(u32, &codeface_bytes);1293 var codeface = bytesAsValue(u32, &codeface_bytes);
1066 debug.assert(codeface.* == 0xC0DEFACE);1294 testing.expect(codeface.* == 0xC0DEFACE);
1067 codeface.* = 0;1295 codeface.* = 0;
1068 for (codeface_bytes) |b|1296 for (codeface_bytes) |b|
1069 debug.assert(b == 0);1297 testing.expect(b == 0);
10701298
1071 const S = packed struct {1299 const S = packed struct {
1072 a: u8,1300 a: u8,
...@@ -1083,7 +1311,7 @@ test "std.mem.bytesAsValue" {...@@ -1083,7 +1311,7 @@ test "std.mem.bytesAsValue" {
1083 };1311 };
1084 const inst_bytes = "\xBE\xEF\xDE\xA1";1312 const inst_bytes = "\xBE\xEF\xDE\xA1";
1085 const inst2 = bytesAsValue(S, &inst_bytes);1313 const inst2 = bytesAsValue(S, &inst_bytes);
1086 debug.assert(meta.eql(inst, inst2.*));1314 testing.expect(meta.eql(inst, inst2.*));
1087}1315}
10881316
1089///Given a pointer to an array of bytes, returns a value of the specified type backed by a1317///Given a pointer to an array of bytes, returns a value of the specified type backed by a
...@@ -1098,7 +1326,7 @@ test "std.mem.bytesToValue" {...@@ -1098,7 +1326,7 @@ test "std.mem.bytesToValue" {
1098 };1326 };
10991327
1100 const deadbeef = bytesToValue(u32, deadbeef_bytes);1328 const deadbeef = bytesToValue(u32, deadbeef_bytes);
1101 debug.assert(deadbeef == u32(0xDEADBEEF));1329 testing.expect(deadbeef == u32(0xDEADBEEF));
1102}1330}
11031331
1104fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type {1332fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type {
...@@ -1109,7 +1337,7 @@ fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type {...@@ -1109,7 +1337,7 @@ fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type {
11091337
1110///Given a pointer to an array, returns a pointer to a portion of that array, preserving constness.1338///Given a pointer to an array, returns a pointer to a portion of that array, preserving constness.
1111pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubArrayPtrReturnType(@typeOf(ptr), length) {1339pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubArrayPtrReturnType(@typeOf(ptr), length) {
1112 debug.assert(start + length <= ptr.*.len);1340 assert(start + length <= ptr.*.len);
11131341
1114 const ReturnType = SubArrayPtrReturnType(@typeOf(ptr), length);1342 const ReturnType = SubArrayPtrReturnType(@typeOf(ptr), length);
1115 const T = meta.Child(meta.Child(@typeOf(ptr)));1343 const T = meta.Child(meta.Child(@typeOf(ptr)));
...@@ -1119,12 +1347,32 @@ pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubA...@@ -1119,12 +1347,32 @@ pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubA
1119test "std.mem.subArrayPtr" {1347test "std.mem.subArrayPtr" {
1120 const a1 = "abcdef";1348 const a1 = "abcdef";
1121 const sub1 = subArrayPtr(&a1, 2, 3);1349 const sub1 = subArrayPtr(&a1, 2, 3);
1122 debug.assert(std.mem.eql(u8, sub1.*, "cde"));1350 testing.expect(std.mem.eql(u8, sub1.*, "cde"));
11231351
1124 var a2 = "abcdef";1352 var a2 = "abcdef";
1125 var sub2 = subArrayPtr(&a2, 2, 3);1353 var sub2 = subArrayPtr(&a2, 2, 3);
11261354
1127 debug.assert(std.mem.eql(u8, sub2, "cde"));1355 testing.expect(std.mem.eql(u8, sub2, "cde"));
1128 sub2[1] = 'X';1356 sub2[1] = 'X';
1129 debug.assert(std.mem.eql(u8, a2, "abcXef"));1357 testing.expect(std.mem.eql(u8, a2, "abcXef"));
1358}
1359
1360/// Round an address up to the nearest aligned address
1361pub fn alignForward(addr: usize, alignment: usize) usize {
1362 return (addr + alignment - 1) & ~(alignment - 1);
1363}
1364
1365test "std.mem.alignForward" {
1366 testing.expect(alignForward(1, 1) == 1);
1367 testing.expect(alignForward(2, 1) == 2);
1368 testing.expect(alignForward(1, 2) == 2);
1369 testing.expect(alignForward(2, 2) == 2);
1370 testing.expect(alignForward(3, 2) == 4);
1371 testing.expect(alignForward(4, 2) == 4);
1372 testing.expect(alignForward(7, 8) == 8);
1373 testing.expect(alignForward(8, 8) == 8);
1374 testing.expect(alignForward(9, 8) == 16);
1375 testing.expect(alignForward(15, 8) == 16);
1376 testing.expect(alignForward(16, 8) == 16);
1377 testing.expect(alignForward(17, 8) == 24);
1130}1378}
std/meta/index.zig+112-76
...@@ -3,6 +3,7 @@ const builtin = @import("builtin");...@@ -3,6 +3,7 @@ const builtin = @import("builtin");
3const debug = std.debug;3const debug = std.debug;
4const mem = std.mem;4const mem = std.mem;
5const math = std.math;5const math = std.math;
6const testing = std.testing;
67
7pub const trait = @import("trait.zig");8pub const trait = @import("trait.zig");
89
...@@ -64,16 +65,16 @@ test "std.meta.tagName" {...@@ -64,16 +65,16 @@ test "std.meta.tagName" {
64 var u2a = U2{ .C = 0 };65 var u2a = U2{ .C = 0 };
65 var u2b = U2{ .D = 0 };66 var u2b = U2{ .D = 0 };
6667
67 debug.assert(mem.eql(u8, tagName(E1.A), "A"));68 testing.expect(mem.eql(u8, tagName(E1.A), "A"));
68 debug.assert(mem.eql(u8, tagName(E1.B), "B"));69 testing.expect(mem.eql(u8, tagName(E1.B), "B"));
69 debug.assert(mem.eql(u8, tagName(E2.C), "C"));70 testing.expect(mem.eql(u8, tagName(E2.C), "C"));
70 debug.assert(mem.eql(u8, tagName(E2.D), "D"));71 testing.expect(mem.eql(u8, tagName(E2.D), "D"));
71 debug.assert(mem.eql(u8, tagName(error.E), "E"));72 testing.expect(mem.eql(u8, tagName(error.E), "E"));
72 debug.assert(mem.eql(u8, tagName(error.F), "F"));73 testing.expect(mem.eql(u8, tagName(error.F), "F"));
73 debug.assert(mem.eql(u8, tagName(u1g), "G"));74 testing.expect(mem.eql(u8, tagName(u1g), "G"));
74 debug.assert(mem.eql(u8, tagName(u1h), "H"));75 testing.expect(mem.eql(u8, tagName(u1h), "H"));
75 debug.assert(mem.eql(u8, tagName(u2a), "C"));76 testing.expect(mem.eql(u8, tagName(u2a), "C"));
76 debug.assert(mem.eql(u8, tagName(u2b), "D"));77 testing.expect(mem.eql(u8, tagName(u2b), "D"));
77}78}
7879
79pub fn stringToEnum(comptime T: type, str: []const u8) ?T {80pub fn stringToEnum(comptime T: type, str: []const u8) ?T {
...@@ -90,12 +91,12 @@ test "std.meta.stringToEnum" {...@@ -90,12 +91,12 @@ test "std.meta.stringToEnum" {
90 A,91 A,
91 B,92 B,
92 };93 };
93 debug.assert(E1.A == stringToEnum(E1, "A").?);94 testing.expect(E1.A == stringToEnum(E1, "A").?);
94 debug.assert(E1.B == stringToEnum(E1, "B").?);95 testing.expect(E1.B == stringToEnum(E1, "B").?);
95 debug.assert(null == stringToEnum(E1, "C"));96 testing.expect(null == stringToEnum(E1, "C"));
96}97}
9798
98pub fn bitCount(comptime T: type) u32 {99pub fn bitCount(comptime T: type) comptime_int {
99 return switch (@typeInfo(T)) {100 return switch (@typeInfo(T)) {
100 TypeId.Int => |info| info.bits,101 TypeId.Int => |info| info.bits,
101 TypeId.Float => |info| info.bits,102 TypeId.Float => |info| info.bits,
...@@ -104,22 +105,22 @@ pub fn bitCount(comptime T: type) u32 {...@@ -104,22 +105,22 @@ pub fn bitCount(comptime T: type) u32 {
104}105}
105106
106test "std.meta.bitCount" {107test "std.meta.bitCount" {
107 debug.assert(bitCount(u8) == 8);108 testing.expect(bitCount(u8) == 8);
108 debug.assert(bitCount(f32) == 32);109 testing.expect(bitCount(f32) == 32);
109}110}
110111
111pub fn alignment(comptime T: type) u29 {112pub fn alignment(comptime T: type) comptime_int {
112 //@alignOf works on non-pointer types113 //@alignOf works on non-pointer types
113 const P = if (comptime trait.is(TypeId.Pointer)(T)) T else *T;114 const P = if (comptime trait.is(TypeId.Pointer)(T)) T else *T;
114 return @typeInfo(P).Pointer.alignment;115 return @typeInfo(P).Pointer.alignment;
115}116}
116117
117test "std.meta.alignment" {118test "std.meta.alignment" {
118 debug.assert(alignment(u8) == 1);119 testing.expect(alignment(u8) == 1);
119 debug.assert(alignment(*align(1) u8) == 1);120 testing.expect(alignment(*align(1) u8) == 1);
120 debug.assert(alignment(*align(2) u8) == 2);121 testing.expect(alignment(*align(2) u8) == 2);
121 debug.assert(alignment([]align(1) u8) == 1);122 testing.expect(alignment([]align(1) u8) == 1);
122 debug.assert(alignment([]align(2) u8) == 2);123 testing.expect(alignment([]align(2) u8) == 2);
123}124}
124125
125pub fn Child(comptime T: type) type {126pub fn Child(comptime T: type) type {
...@@ -133,11 +134,11 @@ pub fn Child(comptime T: type) type {...@@ -133,11 +134,11 @@ pub fn Child(comptime T: type) type {
133}134}
134135
135test "std.meta.Child" {136test "std.meta.Child" {
136 debug.assert(Child([1]u8) == u8);137 testing.expect(Child([1]u8) == u8);
137 debug.assert(Child(*u8) == u8);138 testing.expect(Child(*u8) == u8);
138 debug.assert(Child([]u8) == u8);139 testing.expect(Child([]u8) == u8);
139 debug.assert(Child(?u8) == u8);140 testing.expect(Child(?u8) == u8);
140 debug.assert(Child(promise->u8) == u8);141 testing.expect(Child(promise->u8) == u8);
141}142}
142143
143pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout {144pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout {
...@@ -172,15 +173,15 @@ test "std.meta.containerLayout" {...@@ -172,15 +173,15 @@ test "std.meta.containerLayout" {
172 a: u8,173 a: u8,
173 };174 };
174175
175 debug.assert(containerLayout(E1) == TypeInfo.ContainerLayout.Auto);176 testing.expect(containerLayout(E1) == TypeInfo.ContainerLayout.Auto);
176 debug.assert(containerLayout(E2) == TypeInfo.ContainerLayout.Packed);177 testing.expect(containerLayout(E2) == TypeInfo.ContainerLayout.Packed);
177 debug.assert(containerLayout(E3) == TypeInfo.ContainerLayout.Extern);178 testing.expect(containerLayout(E3) == TypeInfo.ContainerLayout.Extern);
178 debug.assert(containerLayout(S1) == TypeInfo.ContainerLayout.Auto);179 testing.expect(containerLayout(S1) == TypeInfo.ContainerLayout.Auto);
179 debug.assert(containerLayout(S2) == TypeInfo.ContainerLayout.Packed);180 testing.expect(containerLayout(S2) == TypeInfo.ContainerLayout.Packed);
180 debug.assert(containerLayout(S3) == TypeInfo.ContainerLayout.Extern);181 testing.expect(containerLayout(S3) == TypeInfo.ContainerLayout.Extern);
181 debug.assert(containerLayout(U1) == TypeInfo.ContainerLayout.Auto);182 testing.expect(containerLayout(U1) == TypeInfo.ContainerLayout.Auto);
182 debug.assert(containerLayout(U2) == TypeInfo.ContainerLayout.Packed);183 testing.expect(containerLayout(U2) == TypeInfo.ContainerLayout.Packed);
183 debug.assert(containerLayout(U3) == TypeInfo.ContainerLayout.Extern);184 testing.expect(containerLayout(U3) == TypeInfo.ContainerLayout.Extern);
184}185}
185186
186pub fn definitions(comptime T: type) []TypeInfo.Definition {187pub fn definitions(comptime T: type) []TypeInfo.Definition {
...@@ -214,8 +215,8 @@ test "std.meta.definitions" {...@@ -214,8 +215,8 @@ test "std.meta.definitions" {
214 };215 };
215216
216 inline for (defs) |def| {217 inline for (defs) |def| {
217 debug.assert(def.len == 1);218 testing.expect(def.len == 1);
218 debug.assert(comptime mem.eql(u8, def[0].name, "a"));219 testing.expect(comptime mem.eql(u8, def[0].name, "a"));
219 }220 }
220}221}
221222
...@@ -250,8 +251,8 @@ test "std.meta.definitionInfo" {...@@ -250,8 +251,8 @@ test "std.meta.definitionInfo" {
250 };251 };
251252
252 inline for (infos) |info| {253 inline for (infos) |info| {
253 debug.assert(comptime mem.eql(u8, info.name, "a"));254 testing.expect(comptime mem.eql(u8, info.name, "a"));
254 debug.assert(!info.is_pub);255 testing.expect(!info.is_pub);
255 }256 }
256}257}
257258
...@@ -288,16 +289,16 @@ test "std.meta.fields" {...@@ -288,16 +289,16 @@ test "std.meta.fields" {
288 const sf = comptime fields(S1);289 const sf = comptime fields(S1);
289 const uf = comptime fields(U1);290 const uf = comptime fields(U1);
290291
291 debug.assert(e1f.len == 1);292 testing.expect(e1f.len == 1);
292 debug.assert(e2f.len == 1);293 testing.expect(e2f.len == 1);
293 debug.assert(sf.len == 1);294 testing.expect(sf.len == 1);
294 debug.assert(uf.len == 1);295 testing.expect(uf.len == 1);
295 debug.assert(mem.eql(u8, e1f[0].name, "A"));296 testing.expect(mem.eql(u8, e1f[0].name, "A"));
296 debug.assert(mem.eql(u8, e2f[0].name, "A"));297 testing.expect(mem.eql(u8, e2f[0].name, "A"));
297 debug.assert(mem.eql(u8, sf[0].name, "a"));298 testing.expect(mem.eql(u8, sf[0].name, "a"));
298 debug.assert(mem.eql(u8, uf[0].name, "a"));299 testing.expect(mem.eql(u8, uf[0].name, "a"));
299 debug.assert(comptime sf[0].field_type == u8);300 testing.expect(comptime sf[0].field_type == u8);
300 debug.assert(comptime uf[0].field_type == u8);301 testing.expect(comptime uf[0].field_type == u8);
301}302}
302303
303pub fn fieldInfo(comptime T: type, comptime field_name: []const u8) switch (@typeInfo(T)) {304pub fn fieldInfo(comptime T: type, comptime field_name: []const u8) switch (@typeInfo(T)) {
...@@ -332,12 +333,12 @@ test "std.meta.fieldInfo" {...@@ -332,12 +333,12 @@ test "std.meta.fieldInfo" {
332 const sf = comptime fieldInfo(S1, "a");333 const sf = comptime fieldInfo(S1, "a");
333 const uf = comptime fieldInfo(U1, "a");334 const uf = comptime fieldInfo(U1, "a");
334335
335 debug.assert(mem.eql(u8, e1f.name, "A"));336 testing.expect(mem.eql(u8, e1f.name, "A"));
336 debug.assert(mem.eql(u8, e2f.name, "A"));337 testing.expect(mem.eql(u8, e2f.name, "A"));
337 debug.assert(mem.eql(u8, sf.name, "a"));338 testing.expect(mem.eql(u8, sf.name, "a"));
338 debug.assert(mem.eql(u8, uf.name, "a"));339 testing.expect(mem.eql(u8, uf.name, "a"));
339 debug.assert(comptime sf.field_type == u8);340 testing.expect(comptime sf.field_type == u8);
340 debug.assert(comptime uf.field_type == u8);341 testing.expect(comptime uf.field_type == u8);
341}342}
342343
343pub fn TagType(comptime T: type) type {344pub fn TagType(comptime T: type) type {
...@@ -358,8 +359,8 @@ test "std.meta.TagType" {...@@ -358,8 +359,8 @@ test "std.meta.TagType" {
358 D: u16,359 D: u16,
359 };360 };
360361
361 debug.assert(TagType(E) == u8);362 testing.expect(TagType(E) == u8);
362 debug.assert(TagType(U) == E);363 testing.expect(TagType(U) == E);
363}364}
364365
365///Returns the active tag of a tagged union366///Returns the active tag of a tagged union
...@@ -380,10 +381,37 @@ test "std.meta.activeTag" {...@@ -380,10 +381,37 @@ test "std.meta.activeTag" {
380 };381 };
381382
382 var u = U{ .Int = 32 };383 var u = U{ .Int = 32 };
383 debug.assert(activeTag(u) == UE.Int);384 testing.expect(activeTag(u) == UE.Int);
384385
385 u = U{ .Float = 112.9876 };386 u = U{ .Float = 112.9876 };
386 debug.assert(activeTag(u) == UE.Float);387 testing.expect(activeTag(u) == UE.Float);
388}
389
390///Given a tagged union type, and an enum, return the type of the union
391/// field corresponding to the enum tag.
392pub fn TagPayloadType(comptime U: type, tag: var) type {
393 const Tag = @typeOf(tag);
394 testing.expect(trait.is(builtin.TypeId.Union)(U));
395 testing.expect(trait.is(builtin.TypeId.Enum)(Tag));
396
397 const info = @typeInfo(U).Union;
398
399 inline for (info.fields) |field_info| {
400 if (field_info.enum_field.?.value == @enumToInt(tag)) return field_info.field_type;
401 }
402 unreachable;
403}
404
405test "std.meta.TagPayloadType" {
406 const Event = union(enum) {
407 Moved: struct {
408 from: i32,
409 to: i32,
410 },
411 };
412 const MovedEvent = TagPayloadType(Event, Event.Moved);
413 var e: Event = undefined;
414 testing.expect(MovedEvent == @typeOf(e.Moved));
387}415}
388416
389///Compares two of any type for equality. Containers are compared on a field-by-field basis,417///Compares two of any type for equality. Containers are compared on a field-by-field basis,
...@@ -435,10 +463,18 @@ pub fn eql(a: var, b: @typeOf(a)) bool {...@@ -435,10 +463,18 @@ pub fn eql(a: var, b: @typeOf(a)) bool {
435 builtin.TypeId.Pointer => {463 builtin.TypeId.Pointer => {
436 const info = @typeInfo(T).Pointer;464 const info = @typeInfo(T).Pointer;
437 switch (info.size) {465 switch (info.size) {
438 builtin.TypeInfo.Pointer.Size.One, builtin.TypeInfo.Pointer.Size.Many => return a == b,466 builtin.TypeInfo.Pointer.Size.One,
467 builtin.TypeInfo.Pointer.Size.Many,
468 builtin.TypeInfo.Pointer.Size.C,
469 => return a == b,
439 builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len,470 builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len,
440 }471 }
441 },472 },
473 builtin.TypeId.Optional => {
474 if (a == null and b == null) return true;
475 if (a == null or b == null) return false;
476 return eql(a.?, b.?);
477 },
442 else => return a == b,478 else => return a == b,
443 }479 }
444}480}
...@@ -452,7 +488,7 @@ test "std.meta.eql" {...@@ -452,7 +488,7 @@ test "std.meta.eql" {
452488
453 const U = union(enum) {489 const U = union(enum) {
454 s: S,490 s: S,
455 f: f32,491 f: ?f32,
456 };492 };
457493
458 const s_1 = S{494 const s_1 = S{
...@@ -477,19 +513,19 @@ test "std.meta.eql" {...@@ -477,19 +513,19 @@ test "std.meta.eql" {
477 const u_2 = U{ .s = s_1 };513 const u_2 = U{ .s = s_1 };
478 const u_3 = U{ .f = 24 };514 const u_3 = U{ .f = 24 };
479515
480 debug.assert(eql(s_1, s_3));516 testing.expect(eql(s_1, s_3));
481 debug.assert(eql(&s_1, &s_1));517 testing.expect(eql(&s_1, &s_1));
482 debug.assert(!eql(&s_1, &s_3));518 testing.expect(!eql(&s_1, &s_3));
483 debug.assert(eql(u_1, u_3));519 testing.expect(eql(u_1, u_3));
484 debug.assert(!eql(u_1, u_2));520 testing.expect(!eql(u_1, u_2));
485521
486 var a1 = "abcdef";522 var a1 = "abcdef";
487 var a2 = "abcdef";523 var a2 = "abcdef";
488 var a3 = "ghijkl";524 var a3 = "ghijkl";
489525
490 debug.assert(eql(a1, a2));526 testing.expect(eql(a1, a2));
491 debug.assert(!eql(a1, a3));527 testing.expect(!eql(a1, a3));
492 debug.assert(!eql(a1[0..], a2[0..]));528 testing.expect(!eql(a1[0..], a2[0..]));
493529
494 const EU = struct {530 const EU = struct {
495 fn tst(err: bool) !u8 {531 fn tst(err: bool) !u8 {
...@@ -498,9 +534,9 @@ test "std.meta.eql" {...@@ -498,9 +534,9 @@ test "std.meta.eql" {
498 }534 }
499 };535 };
500536
501 debug.assert(eql(EU.tst(true), EU.tst(true)));537 testing.expect(eql(EU.tst(true), EU.tst(true)));
502 debug.assert(eql(EU.tst(false), EU.tst(false)));538 testing.expect(eql(EU.tst(false), EU.tst(false)));
503 debug.assert(!eql(EU.tst(false), EU.tst(true)));539 testing.expect(!eql(EU.tst(false), EU.tst(true)));
504}540}
505541
506test "intToEnum with error return" {542test "intToEnum with error return" {
...@@ -514,9 +550,9 @@ test "intToEnum with error return" {...@@ -514,9 +550,9 @@ test "intToEnum with error return" {
514550
515 var zero: u8 = 0;551 var zero: u8 = 0;
516 var one: u16 = 1;552 var one: u16 = 1;
517 debug.assert(intToEnum(E1, zero) catch unreachable == E1.A);553 testing.expect(intToEnum(E1, zero) catch unreachable == E1.A);
518 debug.assert(intToEnum(E2, one) catch unreachable == E2.B);554 testing.expect(intToEnum(E2, one) catch unreachable == E2.B);
519 debug.assertError(intToEnum(E1, one), error.InvalidEnumTag);555 testing.expectError(error.InvalidEnumTag, intToEnum(E1, one));
520}556}
521557
522pub const IntToEnumError = error{InvalidEnumTag};558pub const IntToEnumError = error{InvalidEnumTag};
std/meta/trait.zig+90-58
...@@ -2,6 +2,7 @@ const std = @import("../index.zig");...@@ -2,6 +2,7 @@ const std = @import("../index.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const mem = std.mem;3const mem = std.mem;
4const debug = std.debug;4const debug = std.debug;
5const testing = std.testing;
5const warn = debug.warn;6const warn = debug.warn;
67
7const meta = @import("index.zig");8const meta = @import("index.zig");
...@@ -50,8 +51,8 @@ test "std.meta.trait.multiTrait" {...@@ -50,8 +51,8 @@ test "std.meta.trait.multiTrait" {
50 hasField("x"),51 hasField("x"),
51 hasField("y"),52 hasField("y"),
52 });53 });
53 debug.assert(isVector(Vector2));54 testing.expect(isVector(Vector2));
54 debug.assert(!isVector(u8));55 testing.expect(!isVector(u8));
55}56}
5657
57///58///
...@@ -85,12 +86,12 @@ test "std.meta.trait.hasDef" {...@@ -85,12 +86,12 @@ test "std.meta.trait.hasDef" {
85 const value = u8(16);86 const value = u8(16);
86 };87 };
8788
88 debug.assert(hasDef("value")(TestStruct));89 testing.expect(hasDef("value")(TestStruct));
89 debug.assert(!hasDef("value")(TestStructFail));90 testing.expect(!hasDef("value")(TestStructFail));
90 debug.assert(!hasDef("value")(*TestStruct));91 testing.expect(!hasDef("value")(*TestStruct));
91 debug.assert(!hasDef("value")(**TestStructFail));92 testing.expect(!hasDef("value")(**TestStructFail));
92 debug.assert(!hasDef("x")(TestStruct));93 testing.expect(!hasDef("x")(TestStruct));
93 debug.assert(!hasDef("value")(u8));94 testing.expect(!hasDef("value")(u8));
94}95}
9596
96///97///
...@@ -111,9 +112,9 @@ test "std.meta.trait.hasFn" {...@@ -111,9 +112,9 @@ test "std.meta.trait.hasFn" {
111 pub fn useless() void {}112 pub fn useless() void {}
112 };113 };
113114
114 debug.assert(hasFn("useless")(TestStruct));115 testing.expect(hasFn("useless")(TestStruct));
115 debug.assert(!hasFn("append")(TestStruct));116 testing.expect(!hasFn("append")(TestStruct));
116 debug.assert(!hasFn("useless")(u8));117 testing.expect(!hasFn("useless")(u8));
117}118}
118119
119///120///
...@@ -143,11 +144,11 @@ test "std.meta.trait.hasField" {...@@ -143,11 +144,11 @@ test "std.meta.trait.hasField" {
143 value: u32,144 value: u32,
144 };145 };
145146
146 debug.assert(hasField("value")(TestStruct));147 testing.expect(hasField("value")(TestStruct));
147 debug.assert(!hasField("value")(*TestStruct));148 testing.expect(!hasField("value")(*TestStruct));
148 debug.assert(!hasField("x")(TestStruct));149 testing.expect(!hasField("x")(TestStruct));
149 debug.assert(!hasField("x")(**TestStruct));150 testing.expect(!hasField("x")(**TestStruct));
150 debug.assert(!hasField("value")(u8));151 testing.expect(!hasField("value")(u8));
151}152}
152153
153///154///
...@@ -161,11 +162,11 @@ pub fn is(comptime id: builtin.TypeId) TraitFn {...@@ -161,11 +162,11 @@ pub fn is(comptime id: builtin.TypeId) TraitFn {
161}162}
162163
163test "std.meta.trait.is" {164test "std.meta.trait.is" {
164 debug.assert(is(builtin.TypeId.Int)(u8));165 testing.expect(is(builtin.TypeId.Int)(u8));
165 debug.assert(!is(builtin.TypeId.Int)(f32));166 testing.expect(!is(builtin.TypeId.Int)(f32));
166 debug.assert(is(builtin.TypeId.Pointer)(*u8));167 testing.expect(is(builtin.TypeId.Pointer)(*u8));
167 debug.assert(is(builtin.TypeId.Void)(void));168 testing.expect(is(builtin.TypeId.Void)(void));
168 debug.assert(!is(builtin.TypeId.Optional)(anyerror));169 testing.expect(!is(builtin.TypeId.Optional)(anyerror));
169}170}
170171
171///172///
...@@ -180,9 +181,9 @@ pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn {...@@ -180,9 +181,9 @@ pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn {
180}181}
181182
182test "std.meta.trait.isPtrTo" {183test "std.meta.trait.isPtrTo" {
183 debug.assert(!isPtrTo(builtin.TypeId.Struct)(struct {}));184 testing.expect(!isPtrTo(builtin.TypeId.Struct)(struct {}));
184 debug.assert(isPtrTo(builtin.TypeId.Struct)(*struct {}));185 testing.expect(isPtrTo(builtin.TypeId.Struct)(*struct {}));
185 debug.assert(!isPtrTo(builtin.TypeId.Struct)(**struct {}));186 testing.expect(!isPtrTo(builtin.TypeId.Struct)(**struct {}));
186}187}
187188
188///////////Strait trait Fns189///////////Strait trait Fns
...@@ -205,9 +206,9 @@ test "std.meta.trait.isExtern" {...@@ -205,9 +206,9 @@ test "std.meta.trait.isExtern" {
205 const TestExStruct = extern struct {};206 const TestExStruct = extern struct {};
206 const TestStruct = struct {};207 const TestStruct = struct {};
207208
208 debug.assert(isExtern(TestExStruct));209 testing.expect(isExtern(TestExStruct));
209 debug.assert(!isExtern(TestStruct));210 testing.expect(!isExtern(TestStruct));
210 debug.assert(!isExtern(u8));211 testing.expect(!isExtern(u8));
211}212}
212213
213///214///
...@@ -226,9 +227,40 @@ test "std.meta.trait.isPacked" {...@@ -226,9 +227,40 @@ test "std.meta.trait.isPacked" {
226 const TestPStruct = packed struct {};227 const TestPStruct = packed struct {};
227 const TestStruct = struct {};228 const TestStruct = struct {};
228229
229 debug.assert(isPacked(TestPStruct));230 testing.expect(isPacked(TestPStruct));
230 debug.assert(!isPacked(TestStruct));231 testing.expect(!isPacked(TestStruct));
231 debug.assert(!isPacked(u8));232 testing.expect(!isPacked(u8));
233}
234
235///
236pub fn isUnsignedInt(comptime T: type) bool {
237 return switch (@typeId(T)) {
238 builtin.TypeId.Int => !@typeInfo(T).Int.is_signed,
239 else => false,
240 };
241}
242
243test "isUnsignedInt" {
244 testing.expect(isUnsignedInt(u32) == true);
245 testing.expect(isUnsignedInt(comptime_int) == false);
246 testing.expect(isUnsignedInt(i64) == false);
247 testing.expect(isUnsignedInt(f64) == false);
248}
249
250///
251pub fn isSignedInt(comptime T: type) bool {
252 return switch (@typeId(T)) {
253 builtin.TypeId.ComptimeInt => true,
254 builtin.TypeId.Int => @typeInfo(T).Int.is_signed,
255 else => false,
256 };
257}
258
259test "isSignedInt" {
260 testing.expect(isSignedInt(u32) == false);
261 testing.expect(isSignedInt(comptime_int) == true);
262 testing.expect(isSignedInt(i64) == true);
263 testing.expect(isSignedInt(f64) == false);
232}264}
233265
234///266///
...@@ -242,9 +274,9 @@ pub fn isSingleItemPtr(comptime T: type) bool {...@@ -242,9 +274,9 @@ pub fn isSingleItemPtr(comptime T: type) bool {
242274
243test "std.meta.trait.isSingleItemPtr" {275test "std.meta.trait.isSingleItemPtr" {
244 const array = []u8{0} ** 10;276 const array = []u8{0} ** 10;
245 debug.assert(isSingleItemPtr(@typeOf(&array[0])));277 testing.expect(isSingleItemPtr(@typeOf(&array[0])));
246 debug.assert(!isSingleItemPtr(@typeOf(array)));278 testing.expect(!isSingleItemPtr(@typeOf(array)));
247 debug.assert(!isSingleItemPtr(@typeOf(array[0..1])));279 testing.expect(!isSingleItemPtr(@typeOf(array[0..1])));
248}280}
249281
250///282///
...@@ -259,9 +291,9 @@ pub fn isManyItemPtr(comptime T: type) bool {...@@ -259,9 +291,9 @@ pub fn isManyItemPtr(comptime T: type) bool {
259test "std.meta.trait.isManyItemPtr" {291test "std.meta.trait.isManyItemPtr" {
260 const array = []u8{0} ** 10;292 const array = []u8{0} ** 10;
261 const mip = @ptrCast([*]const u8, &array[0]);293 const mip = @ptrCast([*]const u8, &array[0]);
262 debug.assert(isManyItemPtr(@typeOf(mip)));294 testing.expect(isManyItemPtr(@typeOf(mip)));
263 debug.assert(!isManyItemPtr(@typeOf(array)));295 testing.expect(!isManyItemPtr(@typeOf(array)));
264 debug.assert(!isManyItemPtr(@typeOf(array[0..1])));296 testing.expect(!isManyItemPtr(@typeOf(array[0..1])));
265}297}
266298
267///299///
...@@ -275,9 +307,9 @@ pub fn isSlice(comptime T: type) bool {...@@ -275,9 +307,9 @@ pub fn isSlice(comptime T: type) bool {
275307
276test "std.meta.trait.isSlice" {308test "std.meta.trait.isSlice" {
277 const array = []u8{0} ** 10;309 const array = []u8{0} ** 10;
278 debug.assert(isSlice(@typeOf(array[0..])));310 testing.expect(isSlice(@typeOf(array[0..])));
279 debug.assert(!isSlice(@typeOf(array)));311 testing.expect(!isSlice(@typeOf(array)));
280 debug.assert(!isSlice(@typeOf(&array[0])));312 testing.expect(!isSlice(@typeOf(&array[0])));
281}313}
282314
283///315///
...@@ -297,10 +329,10 @@ test "std.meta.trait.isIndexable" {...@@ -297,10 +329,10 @@ test "std.meta.trait.isIndexable" {
297 const array = []u8{0} ** 10;329 const array = []u8{0} ** 10;
298 const slice = array[0..];330 const slice = array[0..];
299331
300 debug.assert(isIndexable(@typeOf(array)));332 testing.expect(isIndexable(@typeOf(array)));
301 debug.assert(isIndexable(@typeOf(&array)));333 testing.expect(isIndexable(@typeOf(&array)));
302 debug.assert(isIndexable(@typeOf(slice)));334 testing.expect(isIndexable(@typeOf(slice)));
303 debug.assert(!isIndexable(meta.Child(@typeOf(slice))));335 testing.expect(!isIndexable(meta.Child(@typeOf(slice))));
304}336}
305337
306///338///
...@@ -316,13 +348,13 @@ test "std.meta.trait.isNumber" {...@@ -316,13 +348,13 @@ test "std.meta.trait.isNumber" {
316 number: u8,348 number: u8,
317 };349 };
318350
319 debug.assert(isNumber(u32));351 testing.expect(isNumber(u32));
320 debug.assert(isNumber(f32));352 testing.expect(isNumber(f32));
321 debug.assert(isNumber(u64));353 testing.expect(isNumber(u64));
322 debug.assert(isNumber(@typeOf(102)));354 testing.expect(isNumber(@typeOf(102)));
323 debug.assert(isNumber(@typeOf(102.123)));355 testing.expect(isNumber(@typeOf(102.123)));
324 debug.assert(!isNumber([]u8));356 testing.expect(!isNumber([]u8));
325 debug.assert(!isNumber(NotANumber));357 testing.expect(!isNumber(NotANumber));
326}358}
327359
328///360///
...@@ -335,10 +367,10 @@ pub fn isConstPtr(comptime T: type) bool {...@@ -335,10 +367,10 @@ pub fn isConstPtr(comptime T: type) bool {
335test "std.meta.trait.isConstPtr" {367test "std.meta.trait.isConstPtr" {
336 var t = u8(0);368 var t = u8(0);
337 const c = u8(0);369 const c = u8(0);
338 debug.assert(isConstPtr(*const @typeOf(t)));370 testing.expect(isConstPtr(*const @typeOf(t)));
339 debug.assert(isConstPtr(@typeOf(&c)));371 testing.expect(isConstPtr(@typeOf(&c)));
340 debug.assert(!isConstPtr(*@typeOf(t)));372 testing.expect(!isConstPtr(*@typeOf(t)));
341 debug.assert(!isConstPtr(@typeOf(6)));373 testing.expect(!isConstPtr(@typeOf(6)));
342}374}
343375
344///376///
...@@ -362,8 +394,8 @@ test "std.meta.trait.isContainer" {...@@ -362,8 +394,8 @@ test "std.meta.trait.isContainer" {
362 B,394 B,
363 };395 };
364396
365 debug.assert(isContainer(TestStruct));397 testing.expect(isContainer(TestStruct));
366 debug.assert(isContainer(TestUnion));398 testing.expect(isContainer(TestUnion));
367 debug.assert(isContainer(TestEnum));399 testing.expect(isContainer(TestEnum));
368 debug.assert(!isContainer(u8));400 testing.expect(!isContainer(u8));
369}401}
std/mutex.zig+105-48
...@@ -2,77 +2,127 @@ const std = @import("index.zig");...@@ -2,77 +2,127 @@ const std = @import("index.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const AtomicOrder = builtin.AtomicOrder;3const AtomicOrder = builtin.AtomicOrder;
4const AtomicRmwOp = builtin.AtomicRmwOp;4const AtomicRmwOp = builtin.AtomicRmwOp;
5const assert = std.debug.assert;5const testing = std.testing;
6const SpinLock = std.SpinLock;6const SpinLock = std.SpinLock;
7const linux = std.os.linux;7const linux = std.os.linux;
8const windows = std.os.windows;
89
9/// Lock may be held only once. If the same thread10/// Lock may be held only once. If the same thread
10/// tries to acquire the same mutex twice, it deadlocks.11/// tries to acquire the same mutex twice, it deadlocks.
12/// This type must be initialized at runtime, and then deinitialized when no
13/// longer needed, to free resources.
14/// If you need static initialization, use std.StaticallyInitializedMutex.
11/// The Linux implementation is based on mutex3 from15/// The Linux implementation is based on mutex3 from
12/// https://www.akkadia.org/drepper/futex.pdf16/// https://www.akkadia.org/drepper/futex.pdf
13pub const Mutex = struct {17/// When an application is built in single threaded release mode, all the functions are
14 /// 0: unlocked18/// no-ops. In single threaded debug mode, there is deadlock detection.
15 /// 1: locked, no waiters19pub const Mutex = if (builtin.single_threaded)
16 /// 2: locked, one or more waiters20 struct {
17 linux_lock: @typeOf(linux_lock_init),21 lock: @typeOf(lock_init),
1822
19 /// TODO better implementation than spin lock23 const lock_init = if (std.debug.runtime_safety) false else {};
20 spin_lock: @typeOf(spin_lock_init),
2124
22 const linux_lock_init = if (builtin.os == builtin.Os.linux) i32(0) else {};25 pub const Held = struct {
23 const spin_lock_init = if (builtin.os != builtin.Os.linux) SpinLock.init() else {};26 mutex: *Mutex,
2427
25 pub const Held = struct {28 pub fn release(self: Held) void {
26 mutex: *Mutex,29 if (std.debug.runtime_safety) {
30 self.mutex.lock = false;
31 }
32 }
33 };
34 pub fn init() Mutex {
35 return Mutex{ .lock = lock_init };
36 }
37 pub fn deinit(self: *Mutex) void {}
2738
28 pub fn release(self: Held) void {39 pub fn acquire(self: *Mutex) Held {
29 if (builtin.os == builtin.Os.linux) {40 if (std.debug.runtime_safety and self.lock) {
30 const c = @atomicRmw(i32, &self.mutex.linux_lock, AtomicRmwOp.Sub, 1, AtomicOrder.Release);41 @panic("deadlock detected");
42 }
43 return Held{ .mutex = self };
44 }
45 }
46else switch (builtin.os) {
47 builtin.Os.linux => struct {
48 /// 0: unlocked
49 /// 1: locked, no waiters
50 /// 2: locked, one or more waiters
51 lock: i32,
52
53 pub const Held = struct {
54 mutex: *Mutex,
55
56 pub fn release(self: Held) void {
57 const c = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Sub, 1, AtomicOrder.Release);
31 if (c != 1) {58 if (c != 1) {
32 _ = @atomicRmw(i32, &self.mutex.linux_lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release);59 _ = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release);
33 const rc = linux.futex_wake(&self.mutex.linux_lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1);60 const rc = linux.futex_wake(&self.mutex.lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1);
34 switch (linux.getErrno(rc)) {61 switch (linux.getErrno(rc)) {
35 0 => {},62 0 => {},
36 linux.EINVAL => unreachable,63 linux.EINVAL => unreachable,
37 else => unreachable,64 else => unreachable,
38 }65 }
39 }66 }
40 } else {
41 SpinLock.Held.release(SpinLock.Held{ .spinlock = &self.mutex.spin_lock });
42 }67 }
68 };
69
70 pub fn init() Mutex {
71 return Mutex{ .lock = 0 };
43 }72 }
44 };
4573
46 pub fn init() Mutex {74 pub fn deinit(self: *Mutex) void {}
47 return Mutex{
48 .linux_lock = linux_lock_init,
49 .spin_lock = spin_lock_init,
50 };
51 }
5275
53 pub fn acquire(self: *Mutex) Held {76 pub fn acquire(self: *Mutex) Held {
54 if (builtin.os == builtin.Os.linux) {77 var c = @cmpxchgWeak(i32, &self.lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse
55 var c = @cmpxchgWeak(i32, &self.linux_lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse
56 return Held{ .mutex = self };78 return Held{ .mutex = self };
57 if (c != 2)79 if (c != 2)
58 c = @atomicRmw(i32, &self.linux_lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);80 c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
59 while (c != 0) {81 while (c != 0) {
60 const rc = linux.futex_wait(&self.linux_lock, linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG, 2, null);82 const rc = linux.futex_wait(&self.lock, linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG, 2, null);
61 switch (linux.getErrno(rc)) {83 switch (linux.getErrno(rc)) {
62 0, linux.EINTR, linux.EAGAIN => {},84 0, linux.EINTR, linux.EAGAIN => {},
63 linux.EINVAL => unreachable,85 linux.EINVAL => unreachable,
64 else => unreachable,86 else => unreachable,
65 }87 }
66 c = @atomicRmw(i32, &self.linux_lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);88 c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
67 }89 }
68 } else {90 return Held{ .mutex = self };
69 _ = self.spin_lock.acquire();
70 }91 }
71 return Held{ .mutex = self };92 },
72 }93 // TODO once https://github.com/ziglang/zig/issues/287 (copy elision) is solved, we can make a
94 // better implementation of this. The problem is we need the init() function to have access to
95 // the address of the CRITICAL_SECTION, and then have it not move.
96 builtin.Os.windows => std.StaticallyInitializedMutex,
97 else => struct {
98 /// TODO better implementation than spin lock.
99 /// When changing this, one must also change the corresponding
100 /// std.StaticallyInitializedMutex code, since it aliases this type,
101 /// under the assumption that it works both statically and at runtime.
102 lock: SpinLock,
103
104 pub const Held = struct {
105 mutex: *Mutex,
106
107 pub fn release(self: Held) void {
108 SpinLock.Held.release(SpinLock.Held{ .spinlock = &self.mutex.lock });
109 }
110 };
111
112 pub fn init() Mutex {
113 return Mutex{ .lock = SpinLock.init() };
114 }
115
116 pub fn deinit(self: *Mutex) void {}
117
118 pub fn acquire(self: *Mutex) Held {
119 _ = self.lock.acquire();
120 return Held{ .mutex = self };
121 }
122 },
73};123};
74124
75const Context = struct {125const TestContext = struct {
76 mutex: *Mutex,126 mutex: *Mutex,
77 data: i128,127 data: i128,
78128
...@@ -90,25 +140,32 @@ test "std.Mutex" {...@@ -90,25 +140,32 @@ test "std.Mutex" {
90 var a = &fixed_buffer_allocator.allocator;140 var a = &fixed_buffer_allocator.allocator;
91141
92 var mutex = Mutex.init();142 var mutex = Mutex.init();
93 var context = Context{143 defer mutex.deinit();
144
145 var context = TestContext{
94 .mutex = &mutex,146 .mutex = &mutex,
95 .data = 0,147 .data = 0,
96 };148 };
97149
98 const thread_count = 10;150 if (builtin.single_threaded) {
99 var threads: [thread_count]*std.os.Thread = undefined;151 worker(&context);
100 for (threads) |*t| {152 testing.expect(context.data == TestContext.incr_count);
101 t.* = try std.os.spawnThread(&context, worker);153 } else {
102 }154 const thread_count = 10;
103 for (threads) |t|155 var threads: [thread_count]*std.os.Thread = undefined;
104 t.wait();156 for (threads) |*t| {
157 t.* = try std.os.spawnThread(&context, worker);
158 }
159 for (threads) |t|
160 t.wait();
105161
106 std.debug.assertOrPanic(context.data == thread_count * Context.incr_count);162 testing.expect(context.data == thread_count * TestContext.incr_count);
163 }
107}164}
108165
109fn worker(ctx: *Context) void {166fn worker(ctx: *TestContext) void {
110 var i: usize = 0;167 var i: usize = 0;
111 while (i != Context.incr_count) : (i += 1) {168 while (i != TestContext.incr_count) : (i += 1) {
112 const held = ctx.mutex.acquire();169 const held = ctx.mutex.acquire();
113 defer held.release();170 defer held.release();
114171
std/net.zig+6-6
...@@ -23,7 +23,7 @@ pub const Address = struct {...@@ -23,7 +23,7 @@ pub const Address = struct {
23 .os_addr = posix.sockaddr{23 .os_addr = posix.sockaddr{
24 .in = posix.sockaddr_in{24 .in = posix.sockaddr_in{
25 .family = posix.AF_INET,25 .family = posix.AF_INET,
26 .port = std.mem.endianSwapIfLe(u16, _port),26 .port = mem.nativeToBig(u16, _port),
27 .addr = ip4,27 .addr = ip4,
28 .zero = []u8{0} ** 8,28 .zero = []u8{0} ** 8,
29 },29 },
...@@ -37,7 +37,7 @@ pub const Address = struct {...@@ -37,7 +37,7 @@ pub const Address = struct {
37 .os_addr = posix.sockaddr{37 .os_addr = posix.sockaddr{
38 .in6 = posix.sockaddr_in6{38 .in6 = posix.sockaddr_in6{
39 .family = posix.AF_INET6,39 .family = posix.AF_INET6,
40 .port = std.mem.endianSwapIfLe(u16, _port),40 .port = mem.nativeToBig(u16, _port),
41 .flowinfo = 0,41 .flowinfo = 0,
42 .addr = ip6.addr,42 .addr = ip6.addr,
43 .scope_id = ip6.scope_id,43 .scope_id = ip6.scope_id,
...@@ -47,7 +47,7 @@ pub const Address = struct {...@@ -47,7 +47,7 @@ pub const Address = struct {
47 }47 }
4848
49 pub fn port(self: Address) u16 {49 pub fn port(self: Address) u16 {
50 return std.mem.endianSwapIfLe(u16, self.os_addr.in.port);50 return mem.bigToNative(u16, self.os_addr.in.port);
51 }51 }
5252
53 pub fn initPosix(addr: posix.sockaddr) Address {53 pub fn initPosix(addr: posix.sockaddr) Address {
...@@ -57,12 +57,12 @@ pub const Address = struct {...@@ -57,12 +57,12 @@ pub const Address = struct {
57 pub fn format(self: *const Address, out_stream: var) !void {57 pub fn format(self: *const Address, out_stream: var) !void {
58 switch (self.os_addr.in.family) {58 switch (self.os_addr.in.family) {
59 posix.AF_INET => {59 posix.AF_INET => {
60 const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in.port);60 const native_endian_port = mem.bigToNative(u16, self.os_addr.in.port);
61 const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]);61 const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]);
62 try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port);62 try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port);
63 },63 },
64 posix.AF_INET6 => {64 posix.AF_INET6 => {
65 const native_endian_port = std.mem.endianSwapIfLe(u16, self.os_addr.in6.port);65 const native_endian_port = mem.bigToNative(u16, self.os_addr.in6.port);
66 try out_stream.print("[TODO render ip6 address]:{}", native_endian_port);66 try out_stream.print("[TODO render ip6 address]:{}", native_endian_port);
67 },67 },
68 else => try out_stream.write("(unrecognized address family)"),68 else => try out_stream.write("(unrecognized address family)"),
...@@ -193,7 +193,7 @@ pub fn parseIp6(buf: []const u8) !Ip6Addr {...@@ -193,7 +193,7 @@ pub fn parseIp6(buf: []const u8) !Ip6Addr {
193}193}
194194
195test "std.net.parseIp4" {195test "std.net.parseIp4" {
196 assert((try parseIp4("127.0.0.1")) == std.mem.endianSwapIfLe(u32, 0x7f000001));196 assert((try parseIp4("127.0.0.1")) == mem.bigToNative(u32, 0x7f000001));
197197
198 testParseIp4Fail("256.0.0.1", error.Overflow);198 testParseIp4Fail("256.0.0.1", error.Overflow);
199 testParseIp4Fail("x.0.0.1", error.InvalidCharacter);199 testParseIp4Fail("x.0.0.1", error.InvalidCharacter);
std/os/child_process.zig+12-9
...@@ -7,7 +7,6 @@ const posix = os.posix;...@@ -7,7 +7,6 @@ const posix = os.posix;
7const windows = os.windows;7const windows = os.windows;
8const mem = std.mem;8const mem = std.mem;
9const debug = std.debug;9const debug = std.debug;
10const assert = debug.assert;
11const BufMap = std.BufMap;10const BufMap = std.BufMap;
12const Buffer = std.Buffer;11const Buffer = std.Buffer;
13const builtin = @import("builtin");12const builtin = @import("builtin");
...@@ -88,7 +87,8 @@ pub const ChildProcess = struct {...@@ -88,7 +87,8 @@ pub const ChildProcess = struct {
88 /// First argument in argv is the executable.87 /// First argument in argv is the executable.
89 /// On success must call deinit.88 /// On success must call deinit.
90 pub fn init(argv: []const []const u8, allocator: *mem.Allocator) !*ChildProcess {89 pub fn init(argv: []const []const u8, allocator: *mem.Allocator) !*ChildProcess {
91 const child = try allocator.create(ChildProcess{90 const child = try allocator.create(ChildProcess);
91 child.* = ChildProcess{
92 .allocator = allocator,92 .allocator = allocator,
93 .argv = argv,93 .argv = argv,
94 .pid = undefined,94 .pid = undefined,
...@@ -109,7 +109,7 @@ pub const ChildProcess = struct {...@@ -109,7 +109,7 @@ pub const ChildProcess = struct {
109 .stdin_behavior = StdIo.Inherit,109 .stdin_behavior = StdIo.Inherit,
110 .stdout_behavior = StdIo.Inherit,110 .stdout_behavior = StdIo.Inherit,
111 .stderr_behavior = StdIo.Inherit,111 .stderr_behavior = StdIo.Inherit,
112 });112 };
113 errdefer allocator.destroy(child);113 errdefer allocator.destroy(child);
114 return child;114 return child;
115 }115 }
...@@ -573,7 +573,7 @@ pub const ChildProcess = struct {...@@ -573,7 +573,7 @@ pub const ChildProcess = struct {
573 // to match posix semantics573 // to match posix semantics
574 const app_name = x: {574 const app_name = x: {
575 if (self.cwd) |cwd| {575 if (self.cwd) |cwd| {
576 const resolved = try os.path.resolve(self.allocator, cwd, self.argv[0]);576 const resolved = try os.path.resolve(self.allocator, [][]const u8{ cwd, self.argv[0] });
577 defer self.allocator.free(resolved);577 defer self.allocator.free(resolved);
578 break :x try cstr.addNullByte(self.allocator, resolved);578 break :x try cstr.addNullByte(self.allocator, resolved);
579 } else {579 } else {
...@@ -594,12 +594,12 @@ pub const ChildProcess = struct {...@@ -594,12 +594,12 @@ pub const ChildProcess = struct {
594 const PATH = try os.getEnvVarOwned(self.allocator, "PATH");594 const PATH = try os.getEnvVarOwned(self.allocator, "PATH");
595 defer self.allocator.free(PATH);595 defer self.allocator.free(PATH);
596596
597 var it = mem.split(PATH, ";");597 var it = mem.tokenize(PATH, ";");
598 while (it.next()) |search_path| {598 while (it.next()) |search_path| {
599 const joined_path = try os.path.join(self.allocator, search_path, app_name);599 const joined_path = try os.path.join(self.allocator, [][]const u8{ search_path, app_name });
600 defer self.allocator.free(joined_path);600 defer self.allocator.free(joined_path);
601601
602 const joined_path_w = try unicode.utf8ToUtf16LeWithNull(self.allocator, app_name);602 const joined_path_w = try unicode.utf8ToUtf16LeWithNull(self.allocator, joined_path);
603 defer self.allocator.free(joined_path_w);603 defer self.allocator.free(joined_path_w);
604604
605 if (windowsCreateProcess(joined_path_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_w_ptr, &siStartInfo, &piProcInfo)) |_| {605 if (windowsCreateProcess(joined_path_w.ptr, cmd_line_w.ptr, envp_ptr, cwd_w_ptr, &siStartInfo, &piProcInfo)) |_| {
...@@ -609,6 +609,9 @@ pub const ChildProcess = struct {...@@ -609,6 +609,9 @@ pub const ChildProcess = struct {
609 } else {609 } else {
610 return err;610 return err;
611 }611 }
612 } else {
613 // Every other error would have been returned earlier.
614 return error.FileNotFound;
612 }615 }
613 };616 };
614617
...@@ -807,10 +810,10 @@ const ErrInt = @IntType(false, @sizeOf(anyerror) * 8);...@@ -807,10 +810,10 @@ const ErrInt = @IntType(false, @sizeOf(anyerror) * 8);
807810
808fn writeIntFd(fd: i32, value: ErrInt) !void {811fn writeIntFd(fd: i32, value: ErrInt) !void {
809 const stream = &os.File.openHandle(fd).outStream().stream;812 const stream = &os.File.openHandle(fd).outStream().stream;
810 stream.writeIntNe(ErrInt, value) catch return error.SystemResources;813 stream.writeIntNative(ErrInt, value) catch return error.SystemResources;
811}814}
812815
813fn readIntFd(fd: i32) !ErrInt {816fn readIntFd(fd: i32) !ErrInt {
814 const stream = &os.File.openHandle(fd).inStream().stream;817 const stream = &os.File.openHandle(fd).inStream().stream;
815 return stream.readIntNe(ErrInt) catch return error.SystemResources;818 return stream.readIntNative(ErrInt) catch return error.SystemResources;
816}819}
std/os/darwin.zig+1-1
...@@ -665,7 +665,7 @@ pub fn pwrite(fd: i32, buf: [*]const u8, nbyte: usize, offset: u64) usize {...@@ -665,7 +665,7 @@ pub fn pwrite(fd: i32, buf: [*]const u8, nbyte: usize, offset: u64) usize {
665665
666pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {666pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
667 const ptr_result = c.mmap(667 const ptr_result = c.mmap(
668 @ptrCast(*c_void, address),668 @ptrCast(?*c_void, address),
669 length,669 length,
670 @bitCast(c_int, @intCast(c_uint, prot)),670 @bitCast(c_int, @intCast(c_uint, prot)),
671 @bitCast(c_int, c_uint(flags)),671 @bitCast(c_int, c_uint(flags)),
std/os/freebsd/index.zig+171-120
...@@ -1,16 +1,20 @@...@@ -1,16 +1,20 @@
1const assert = @import("../debug.zig").assert;
2const builtin = @import("builtin");1const builtin = @import("builtin");
3const arch = switch (builtin.arch) {2
4 builtin.Arch.x86_64 => @import("x86_64.zig"),
5 else => @compileError("unsupported arch"),
6};
7pub use @import("syscall.zig");
8pub use @import("errno.zig");3pub use @import("errno.zig");
94
10const std = @import("../../index.zig");5const std = @import("../../index.zig");
11const c = std.c;6const c = std.c;
7
8const assert = std.debug.assert;
9const maxInt = std.math.maxInt;
12pub const Kevent = c.Kevent;10pub const Kevent = c.Kevent;
1311
12pub const CTL_KERN = 1;
13pub const CTL_DEBUG = 5;
14
15pub const KERN_PROC = 14; // struct: process entries
16pub const KERN_PROC_PATHNAME = 12; // path to executable
17
14pub const PATH_MAX = 1024;18pub const PATH_MAX = 1024;
1519
16pub const STDIN_FILENO = 0;20pub const STDIN_FILENO = 0;
...@@ -22,7 +26,22 @@ pub const PROT_READ = 1;...@@ -22,7 +26,22 @@ pub const PROT_READ = 1;
22pub const PROT_WRITE = 2;26pub const PROT_WRITE = 2;
23pub const PROT_EXEC = 4;27pub const PROT_EXEC = 4;
2428
25pub const MAP_FAILED = @maxValue(usize);29pub const CLOCK_REALTIME = 0;
30pub const CLOCK_VIRTUAL = 1;
31pub const CLOCK_PROF = 2;
32pub const CLOCK_MONOTONIC = 4;
33pub const CLOCK_UPTIME = 5;
34pub const CLOCK_UPTIME_PRECISE = 7;
35pub const CLOCK_UPTIME_FAST = 8;
36pub const CLOCK_REALTIME_PRECISE = 9;
37pub const CLOCK_REALTIME_FAST = 10;
38pub const CLOCK_MONOTONIC_PRECISE = 11;
39pub const CLOCK_MONOTONIC_FAST = 12;
40pub const CLOCK_SECOND = 13;
41pub const CLOCK_THREAD_CPUTIME_ID = 14;
42pub const CLOCK_PROCESS_CPUTIME_ID = 15;
43
44pub const MAP_FAILED = maxInt(usize);
26pub const MAP_SHARED = 0x0001;45pub const MAP_SHARED = 0x0001;
27pub const MAP_PRIVATE = 0x0002;46pub const MAP_PRIVATE = 0x0002;
28pub const MAP_FIXED = 0x0010;47pub const MAP_FIXED = 0x0010;
...@@ -94,26 +113,33 @@ pub const SIGLIBRT = 33;...@@ -94,26 +113,33 @@ pub const SIGLIBRT = 33;
94pub const SIGRTMIN = 65;113pub const SIGRTMIN = 65;
95pub const SIGRTMAX = 126;114pub const SIGRTMAX = 126;
96115
97pub const O_RDONLY = 0o0;116// access function
98pub const O_WRONLY = 0o1;117pub const F_OK = 0; // test for existence of file
99pub const O_RDWR = 0o2;118pub const X_OK = 1; // test for execute or search permission
100pub const O_ACCMODE = 0o3;119pub const W_OK = 2; // test for write permission
101120pub const R_OK = 4; // test for read permission
102pub const O_CREAT = 0o100;121
103pub const O_EXCL = 0o200;122
104pub const O_NOCTTY = 0o400;123pub const O_RDONLY = 0x0000;
105pub const O_TRUNC = 0o1000;124pub const O_WRONLY = 0x0001;
106pub const O_APPEND = 0o2000;125pub const O_RDWR = 0x0002;
107pub const O_NONBLOCK = 0o4000;126pub const O_ACCMODE = 0x0003;
127
128pub const O_CREAT = 0x0200;
129pub const O_EXCL = 0x0800;
130pub const O_NOCTTY = 0x8000;
131pub const O_TRUNC = 0x0400;
132pub const O_APPEND = 0x0008;
133pub const O_NONBLOCK = 0x0004;
108pub const O_DSYNC = 0o10000;134pub const O_DSYNC = 0o10000;
109pub const O_SYNC = 0o4010000;135pub const O_SYNC = 0x0080;
110pub const O_RSYNC = 0o4010000;136pub const O_RSYNC = 0o4010000;
111pub const O_DIRECTORY = 0o200000;137pub const O_DIRECTORY = 0o200000;
112pub const O_NOFOLLOW = 0o400000;138pub const O_NOFOLLOW = 0x0100;
113pub const O_CLOEXEC = 0o2000000;139pub const O_CLOEXEC = 0x00100000;
114140
115pub const O_ASYNC = 0o20000;141pub const O_ASYNC = 0x0040;
116pub const O_DIRECT = 0o40000;142pub const O_DIRECT = 0x00010000;
117pub const O_LARGEFILE = 0;143pub const O_LARGEFILE = 0;
118pub const O_NOATIME = 0o1000000;144pub const O_NOATIME = 0o1000000;
119pub const O_PATH = 0o10000000;145pub const O_PATH = 0o10000000;
...@@ -157,7 +183,6 @@ pub const SOCK_SEQPACKET = 5;...@@ -157,7 +183,6 @@ pub const SOCK_SEQPACKET = 5;
157pub const SOCK_CLOEXEC = 0x10000000;183pub const SOCK_CLOEXEC = 0x10000000;
158pub const SOCK_NONBLOCK = 0x20000000;184pub const SOCK_NONBLOCK = 0x20000000;
159185
160// TODO: From here
161pub const PROTO_ip = 0o000;186pub const PROTO_ip = 0o000;
162pub const PROTO_icmp = 0o001;187pub const PROTO_icmp = 0o001;
163pub const PROTO_igmp = 0o002;188pub const PROTO_igmp = 0o002;
...@@ -500,6 +525,10 @@ pub const TIOCGPKT = 0x80045438;...@@ -500,6 +525,10 @@ pub const TIOCGPKT = 0x80045438;
500pub const TIOCGPTLCK = 0x80045439;525pub const TIOCGPTLCK = 0x80045439;
501pub const TIOCGEXCL = 0x80045440;526pub const TIOCGEXCL = 0x80045440;
502527
528pub const sockaddr = c.sockaddr;
529pub const sockaddr_in = c.sockaddr_in;
530pub const sockaddr_in6 = c.sockaddr_in6;
531
503fn unsigned(s: i32) u32 {532fn unsigned(s: i32) u32 {
504 return @bitCast(u32, s);533 return @bitCast(u32, s);
505}534}
...@@ -539,96 +568,117 @@ pub fn getErrno(r: usize) usize {...@@ -539,96 +568,117 @@ pub fn getErrno(r: usize) usize {
539}568}
540569
541pub fn dup2(old: i32, new: i32) usize {570pub fn dup2(old: i32, new: i32) usize {
542 return arch.syscall2(SYS_dup2, @intCast(usize, old), @intCast(usize, new));571 return errnoWrap(c.dup2(old, new));
543}572}
544573
545pub fn chdir(path: [*]const u8) usize {574pub fn chdir(path: [*]const u8) usize {
546 return arch.syscall1(SYS_chdir, @ptrToInt(path));575 return errnoWrap(c.chdir(path));
547}576}
548577
549pub fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) usize {578pub fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) usize {
550 return arch.syscall3(SYS_execve, @ptrToInt(path), @ptrToInt(argv), @ptrToInt(envp));579 return errnoWrap(c.execve(path, argv, envp));
551}580}
552581
553pub fn fork() usize {582pub fn fork() usize {
554 return arch.syscall0(SYS_fork);583 return errnoWrap(c.fork());
584}
585
586pub fn access(path: [*]const u8, mode: u32) usize {
587 return errnoWrap(c.access(path, mode));
555}588}
556589
557pub fn getcwd(buf: [*]u8, size: usize) usize {590pub fn getcwd(buf: [*]u8, size: usize) usize {
558 return arch.syscall2(SYS___getcwd, @ptrToInt(buf), size);591 return if (c.getcwd(buf, size) == null) @bitCast(usize, -isize(c._errno().*)) else 0;
559}592}
560593
561pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize {594pub fn getdents(fd: i32, dirp: [*]u8, count: usize) usize {
562 return arch.syscall3(SYS_getdents, @intCast(usize, fd), @ptrToInt(dirp), count);595 return errnoWrap(@bitCast(isize, c.getdents(fd, drip, count)));
596}
597
598pub fn getdirentries(fd: i32, buf_ptr: [*]u8, buf_len: usize, basep: *i64) usize {
599 return errnoWrap(@bitCast(isize, c.getdirentries(fd, buf_ptr, buf_len, basep)));
600}
601
602pub fn realpath(noalias filename: [*]const u8, noalias resolved_name: [*]u8) usize {
603 return if (c.realpath(filename, resolved_name) == null) @bitCast(usize, -isize(c._errno().*)) else 0;
563}604}
564605
565pub fn isatty(fd: i32) bool {606pub fn isatty(fd: i32) bool {
566 var wsz: winsize = undefined;607 return c.isatty(fd) != 0;
567 return arch.syscall3(SYS_ioctl, @intCast(usize, fd), TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
568}608}
569609
570pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {610pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
571 return arch.syscall3(SYS_readlink, @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);611 return errnoWrap(c.readlink(path, buf_ptr, buf_len));
572}612}
573613
574pub fn mkdir(path: [*]const u8, mode: u32) usize {614pub fn mkdir(path: [*]const u8, mode: u32) usize {
575 return arch.syscall2(SYS_mkdir, @ptrToInt(path), mode);615 return errnoWrap(c.mkdir(path, mode));
576}616}
577617
578pub fn mmap(address: ?*u8, length: usize, prot: usize, flags: usize, fd: i32, offset: isize) usize {618pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
579 return arch.syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @intCast(usize, fd), @bitCast(usize, offset));619 const ptr_result = c.mmap(
620 @ptrCast(?*c_void, address),
621 length,
622 @bitCast(c_int, @intCast(c_uint, prot)),
623 @bitCast(c_int, c_uint(flags)),
624 fd,
625 offset,
626 );
627 const isize_result = @bitCast(isize, @ptrToInt(ptr_result));
628 return errnoWrap(isize_result);
580}629}
581630
582pub fn munmap(address: usize, length: usize) usize {631pub fn munmap(address: usize, length: usize) usize {
583 return arch.syscall2(SYS_munmap, address, length);632 return errnoWrap(c.munmap(@intToPtr(*c_void, address), length));
584}633}
585634
586pub fn read(fd: i32, buf: [*]u8, count: usize) usize {635pub fn read(fd: i32, buf: [*]u8, nbyte: usize) usize {
587 return arch.syscall3(SYS_read, @intCast(usize, fd), @ptrToInt(buf), count);636 return errnoWrap(c.read(fd, @ptrCast(*c_void, buf), nbyte));
588}637}
589638
590pub fn rmdir(path: [*]const u8) usize {639pub fn rmdir(path: [*]const u8) usize {
591 return arch.syscall1(SYS_rmdir, @ptrToInt(path));640 return errnoWrap(c.rmdir(path));
592}641}
593642
594pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {643pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
595 return arch.syscall2(SYS_symlink, @ptrToInt(existing), @ptrToInt(new));644 return errnoWrap(c.symlink(existing, new));
596}645}
597646
598pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize {647pub fn pread(fd: i32, buf: [*]u8, nbyte: usize, offset: u64) usize {
599 return arch.syscall4(SYS_pread, @intCast(usize, fd), @ptrToInt(buf), count, offset);648 return errnoWrap(c.pread(fd, @ptrCast(*c_void, buf), nbyte, offset));
600}649}
601650
602pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: usize) usize {651pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: usize) usize {
603 return arch.syscall4(SYS_preadv, @intCast(usize, fd), @ptrToInt(iov), count, offset);652 return errnoWrap(c.preadv(fd, @ptrCast(*const c_void, iov), @intCast(c_int, count), offset));
604}653}
605654
606pub fn pipe(fd: *[2]i32) usize {655pub fn pipe(fd: *[2]i32) usize {
607 return pipe2(fd, 0);656 return pipe2(fd, 0);
608}657}
609658
610pub fn pipe2(fd: *[2]i32, flags: usize) usize {659pub fn pipe2(fd: *[2]i32, flags: u32) usize {
611 return arch.syscall2(SYS_pipe2, @ptrToInt(fd), flags);660 comptime assert(i32.bit_count == c_int.bit_count);
661 return errnoWrap(c.pipe2(@ptrCast(*[2]c_int, fd), flags));
612}662}
613663
614pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {664pub fn write(fd: i32, buf: [*]const u8, nbyte: usize) usize {
615 return arch.syscall3(SYS_write, @intCast(usize, fd), @ptrToInt(buf), count);665 return errnoWrap(c.write(fd, @ptrCast(*const c_void, buf), nbyte));
616}666}
617667
618pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {668pub fn pwrite(fd: i32, buf: [*]const u8, nbyte: usize, offset: u64) usize {
619 return arch.syscall4(SYS_pwrite, @intCast(usize, fd), @ptrToInt(buf), count, offset);669 return errnoWrap(c.pwrite(fd, @ptrCast(*const c_void, buf), nbyte, offset));
620}670}
621671
622pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: usize) usize {672pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: usize) usize {
623 return arch.syscall4(SYS_pwritev, @intCast(usize, fd), @ptrToInt(iov), count, offset);673 return errnoWrap(c.pwritev(fd, @ptrCast(*const c_void, iov), @intCast(c_int, count), offset));
624}674}
625675
626pub fn rename(old: [*]const u8, new: [*]const u8) usize {676pub fn rename(old: [*]const u8, new: [*]const u8) usize {
627 return arch.syscall2(SYS_rename, @ptrToInt(old), @ptrToInt(new));677 return errnoWrap(c.rename(old, new));
628}678}
629679
630pub fn open(path: [*]const u8, flags: u32, perm: usize) usize {680pub fn open(path: [*]const u8, flags: u32, mode: usize) usize {
631 return arch.syscall3(SYS_open, @ptrToInt(path), flags, perm);681 return errnoWrap(c.open(path, @bitCast(c_int, flags), mode));
632}682}
633683
634pub fn create(path: [*]const u8, perm: usize) usize {684pub fn create(path: [*]const u8, perm: usize) usize {
...@@ -636,120 +686,114 @@ pub fn create(path: [*]const u8, perm: usize) usize {...@@ -636,120 +686,114 @@ pub fn create(path: [*]const u8, perm: usize) usize {
636}686}
637687
638pub fn openat(dirfd: i32, path: [*]const u8, flags: usize, mode: usize) usize {688pub fn openat(dirfd: i32, path: [*]const u8, flags: usize, mode: usize) usize {
639 return arch.syscall4(SYS_openat, @intCast(usize, dirfd), @ptrToInt(path), flags, mode);689 return errnoWrap(c.openat(@bitCast(usize, isize(dirfd)), @ptrToInt(path), flags, mode));
640}690}
641691
642pub fn close(fd: i32) usize {692pub fn close(fd: i32) usize {
643 return arch.syscall1(SYS_close, @intCast(usize, fd));693 return errnoWrap(c.close(fd));
644}694}
645695
646pub fn lseek(fd: i32, offset: isize, ref_pos: usize) usize {696pub fn lseek(fd: i32, offset: isize, whence: c_int) usize {
647 return arch.syscall3(SYS_lseek, @intCast(usize, fd), @bitCast(usize, offset), ref_pos);697 return errnoWrap(c.lseek(fd, offset, whence));
648}698}
649699
650pub fn exit(status: i32) noreturn {700pub fn exit(code: i32) noreturn {
651 _ = arch.syscall1(SYS_exit, @bitCast(usize, isize(status)));701 c.exit(code);
652 unreachable;
653}
654
655pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
656 return arch.syscall3(SYS_getrandom, @ptrToInt(buf), count, @intCast(usize, flags));
657}702}
658703
659pub fn kill(pid: i32, sig: i32) usize {704pub fn kill(pid: i32, sig: i32) usize {
660 return arch.syscall2(SYS_kill, @bitCast(usize, @intCast(isize, pid)), @intCast(usize, sig));705 return errnoWrap(c.kill(pid, sig));
661}706}
662707
663pub fn unlink(path: [*]const u8) usize {708pub fn unlink(path: [*]const u8) usize {
664 return arch.syscall1(SYS_unlink, @ptrToInt(path));709 return errnoWrap(c.unlink(path));
665}710}
666711
667pub fn waitpid(pid: i32, status: *i32, options: i32) usize {712pub fn waitpid(pid: i32, status: *i32, options: u32) usize {
668 return arch.syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0);713 comptime assert(i32.bit_count == c_int.bit_count);
714 return errnoWrap(c.waitpid(pid, @ptrCast(*c_int, status), @bitCast(c_int, options)));
669}715}
670716
671pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize {717pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize {
672 return arch.syscall2(SYS_nanosleep, @ptrToInt(req), @ptrToInt(rem));718 return errnoWrap(c.nanosleep(req, rem));
719}
720
721pub fn clock_gettime(clk_id: i32, tp: *timespec) usize {
722 return errnoWrap(c.clock_gettime(clk_id, tp));
723}
724
725pub fn clock_getres(clk_id: i32, tp: *timespec) usize {
726 return errnoWrap(c.clock_getres(clk_id, tp));
673}727}
674728
675pub fn setuid(uid: u32) usize {729pub fn setuid(uid: u32) usize {
676 return arch.syscall1(SYS_setuid, uid);730 return errnoWrap(c.setuid(uid));
677}731}
678732
679pub fn setgid(gid: u32) usize {733pub fn setgid(gid: u32) usize {
680 return arch.syscall1(SYS_setgid, gid);734 return errnoWrap(c.setgid(gid));
681}735}
682736
683pub fn setreuid(ruid: u32, euid: u32) usize {737pub fn setreuid(ruid: u32, euid: u32) usize {
684 return arch.syscall2(SYS_setreuid, ruid, euid);738 return errnoWrap(c.setreuid(ruid, euid));
685}739}
686740
687pub fn setregid(rgid: u32, egid: u32) usize {741pub fn setregid(rgid: u32, egid: u32) usize {
688 return arch.syscall2(SYS_setregid, rgid, egid);742 return errnoWrap(c.setregid(rgid, egid));
689}743}
690744
691pub fn sigprocmask(flags: u32, noalias set: *const sigset_t, noalias oldset: ?*sigset_t) usize {745const NSIG = 32;
692 // TODO: Implement
693 return 0;
694}
695
696pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigaction) usize {
697 // TODO: Implement
698 return 0;
699}
700746
701const NSIG = 65;747pub const SIG_ERR = @intToPtr(extern fn (i32) void, maxInt(usize));
702const sigset_t = [128 / @sizeOf(usize)]usize;748pub const SIG_DFL = @intToPtr(extern fn (i32) void, 0);
703const all_mask = []usize{@maxValue(usize)};749pub const SIG_IGN = @intToPtr(extern fn (i32) void, 1);
704const app_mask = []usize{0xfffffffc7fffffff};
705750
706/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.751/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
707pub const Sigaction = struct {752pub const Sigaction = extern struct {
708 // TODO: Adjust to use freebsd struct layout753 /// signal handler
709 handler: extern fn (i32) void,754 __sigaction_u: extern union {
710 mask: sigset_t,755 __sa_handler: extern fn (i32) void,
711 flags: u32,756 __sa_sigaction: extern fn (i32, *__siginfo, usize) void,
757 },
758
759 /// see signal options
760 sa_flags: u32,
761
762 /// signal mask to apply
763 sa_mask: sigset_t,
712};764};
713765
714pub const SIG_ERR = @intToPtr(extern fn (i32) void, @maxValue(usize));766pub const _SIG_WORDS = 4;
715pub const SIG_DFL = @intToPtr(extern fn (i32) void, 0);767pub const _SIG_MAXSIG = 128;
716pub const SIG_IGN = @intToPtr(extern fn (i32) void, 1);
717pub const empty_sigset = []usize{0} ** sigset_t.len;
718768
719pub fn raise(sig: i32) usize {769pub inline fn _SIG_IDX(sig: usize) usize {
720 // TODO implement, see linux equivalent for what we want to try and do770 return sig - 1;
721 return 0;
722}771}
723772pub inline fn _SIG_WORD(sig: usize) usize {
724fn blockAllSignals(set: *sigset_t) void {773 return_SIG_IDX(sig) >> 5;
725 // TODO implement
726}774}
727775pub inline fn _SIG_BIT(sig: usize) usize {
728fn blockAppSignals(set: *sigset_t) void {776 return 1 << (_SIG_IDX(sig) & 31);
729 // TODO implement
730}777}
731778pub inline fn _SIG_VALID(sig: usize) usize {
732fn restoreSignals(set: *sigset_t) void {779 return sig <= _SIG_MAXSIG and sig > 0;
733 // TODO implement
734}780}
735781
736pub fn sigaddset(set: *sigset_t, sig: u6) void {782pub const sigset_t = extern struct {
737 const s = sig - 1;783 __bits: [_SIG_WORDS]u32,
738 (*set)[usize(s) / usize.bit_count] |= usize(1) << (s & (usize.bit_count - 1));784};
739}
740785
741pub fn sigismember(set: *const sigset_t, sig: u6) bool {786pub fn raise(sig: i32) usize {
742 const s = sig - 1;787 return errnoWrap(c.raise(sig));
743 return ((*set)[usize(s) / usize.bit_count] & (usize(1) << (s & (usize.bit_count - 1)))) != 0;
744}788}
745789
746pub const Stat = arch.Stat;790pub const Stat = c.Stat;
747pub const timespec = arch.timespec;791pub const dirent = c.dirent;
792pub const timespec = c.timespec;
748793
749pub fn fstat(fd: i32, stat_buf: *Stat) usize {794pub fn fstat(fd: i32, buf: *c.Stat) usize {
750 return arch.syscall2(SYS_fstat, @intCast(usize, fd), @ptrToInt(stat_buf));795 return errnoWrap(c.fstat(fd, buf));
751}796}
752
753pub const iovec = extern struct {797pub const iovec = extern struct {
754 iov_base: [*]u8,798 iov_base: [*]u8,
755 iov_len: usize,799 iov_len: usize,
...@@ -760,10 +804,12 @@ pub const iovec_const = extern struct {...@@ -760,10 +804,12 @@ pub const iovec_const = extern struct {
760 iov_len: usize,804 iov_len: usize,
761};805};
762806
807// TODO avoid libc dependency
763pub fn kqueue() usize {808pub fn kqueue() usize {
764 return errnoWrap(c.kqueue());809 return errnoWrap(c.kqueue());
765}810}
766811
812// TODO avoid libc dependency
767pub fn kevent(kq: i32, changelist: []const Kevent, eventlist: []Kevent, timeout: ?*const timespec) usize {813pub fn kevent(kq: i32, changelist: []const Kevent, eventlist: []Kevent, timeout: ?*const timespec) usize {
768 return errnoWrap(c.kevent(814 return errnoWrap(c.kevent(
769 kq,815 kq,
...@@ -775,18 +821,23 @@ pub fn kevent(kq: i32, changelist: []const Kevent, eventlist: []Kevent, timeout:...@@ -775,18 +821,23 @@ pub fn kevent(kq: i32, changelist: []const Kevent, eventlist: []Kevent, timeout:
775 ));821 ));
776}822}
777823
824// TODO avoid libc dependency
778pub fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize {825pub fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize {
779 return errnoWrap(c.sysctl(name, namelen, oldp, oldlenp, newp, newlen));826 return errnoWrap(c.sysctl(name, namelen, oldp, oldlenp, newp, newlen));
780}827}
781828
829// TODO avoid libc dependency
782pub fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize {830pub fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize {
783 return errnoWrap(c.sysctlbyname(name, oldp, oldlenp, newp, newlen));831 return errnoWrap(c.sysctlbyname(name, oldp, oldlenp, newp, newlen));
784}832}
785833
834// TODO avoid libc dependency
786pub fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) usize {835pub fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) usize {
787 return errnoWrap(c.sysctlnametomib(name, wibp, sizep));836 return errnoWrap(c.sysctlnametomib(name, wibp, sizep));
788}837}
789838
839// TODO avoid libc dependency
840
790/// Takes the return value from a syscall and formats it back in the way841/// Takes the return value from a syscall and formats it back in the way
791/// that the kernel represents it to libc. Errno was a mistake, let's make842/// that the kernel represents it to libc. Errno was a mistake, let's make
792/// it go away forever.843/// it go away forever.
std/os/freebsd/syscall.zig deleted-493
...@@ -1,493 +0,0 @@
1pub const SYS_syscall = 0;
2pub const SYS_exit = 1;
3pub const SYS_fork = 2;
4pub const SYS_read = 3;
5pub const SYS_write = 4;
6pub const SYS_open = 5;
7pub const SYS_close = 6;
8pub const SYS_wait4 = 7;
9// 8 is old creat
10pub const SYS_link = 9;
11pub const SYS_unlink = 10;
12// 11 is obsolete execv
13pub const SYS_chdir = 12;
14pub const SYS_fchdir = 13;
15pub const SYS_freebsd11_mknod = 14;
16pub const SYS_chmod = 15;
17pub const SYS_chown = 16;
18pub const SYS_break = 17;
19// 18 is freebsd4 getfsstat
20// 19 is old lseek
21pub const SYS_getpid = 20;
22pub const SYS_mount = 21;
23pub const SYS_unmount = 22;
24pub const SYS_setuid = 23;
25pub const SYS_getuid = 24;
26pub const SYS_geteuid = 25;
27pub const SYS_ptrace = 26;
28pub const SYS_recvmsg = 27;
29pub const SYS_sendmsg = 28;
30pub const SYS_recvfrom = 29;
31pub const SYS_accept = 30;
32pub const SYS_getpeername = 31;
33pub const SYS_getsockname = 32;
34pub const SYS_access = 33;
35pub const SYS_chflags = 34;
36pub const SYS_fchflags = 35;
37pub const SYS_sync = 36;
38pub const SYS_kill = 37;
39// 38 is old stat
40pub const SYS_getppid = 39;
41// 40 is old lstat
42pub const SYS_dup = 41;
43pub const SYS_freebsd10_pipe = 42;
44pub const SYS_getegid = 43;
45pub const SYS_profil = 44;
46pub const SYS_ktrace = 45;
47// 46 is old sigaction
48pub const SYS_getgid = 47;
49// 48 is old sigprocmask
50pub const SYS_getlogin = 49;
51pub const SYS_setlogin = 50;
52pub const SYS_acct = 51;
53// 52 is old sigpending
54pub const SYS_sigaltstack = 53;
55pub const SYS_ioctl = 54;
56pub const SYS_reboot = 55;
57pub const SYS_revoke = 56;
58pub const SYS_symlink = 57;
59pub const SYS_readlink = 58;
60pub const SYS_execve = 59;
61pub const SYS_umask = 60;
62pub const SYS_chroot = 61;
63// 62 is old fstat
64// 63 is old getkerninfo
65// 64 is old getpagesize
66pub const SYS_msync = 65;
67pub const SYS_vfork = 66;
68// 67 is obsolete vread
69// 68 is obsolete vwrite
70// 69 is obsolete sbrk (still present on some platforms)
71pub const SYS_sstk = 70;
72// 71 is old mmap
73pub const SYS_vadvise = 72;
74pub const SYS_munmap = 73;
75pub const SYS_mprotect = 74;
76pub const SYS_madvise = 75;
77// 76 is obsolete vhangup
78// 77 is obsolete vlimit
79pub const SYS_mincore = 78;
80pub const SYS_getgroups = 79;
81pub const SYS_setgroups = 80;
82pub const SYS_getpgrp = 81;
83pub const SYS_setpgid = 82;
84pub const SYS_setitimer = 83;
85// 84 is old wait
86pub const SYS_swapon = 85;
87pub const SYS_getitimer = 86;
88// 87 is old gethostname
89// 88 is old sethostname
90pub const SYS_getdtablesize = 89;
91pub const SYS_dup2 = 90;
92pub const SYS_fcntl = 92;
93pub const SYS_select = 93;
94pub const SYS_fsync = 95;
95pub const SYS_setpriority = 96;
96pub const SYS_socket = 97;
97pub const SYS_connect = 98;
98// 99 is old accept
99pub const SYS_getpriority = 100;
100// 101 is old send
101// 102 is old recv
102// 103 is old sigreturn
103pub const SYS_bind = 104;
104pub const SYS_setsockopt = 105;
105pub const SYS_listen = 106;
106// 107 is obsolete vtimes
107// 108 is old sigvec
108// 109 is old sigblock
109// 110 is old sigsetmask
110// 111 is old sigsuspend
111// 112 is old sigstack
112// 113 is old recvmsg
113// 114 is old sendmsg
114// 115 is obsolete vtrace
115pub const SYS_gettimeofday = 116;
116pub const SYS_getrusage = 117;
117pub const SYS_getsockopt = 118;
118pub const SYS_readv = 120;
119pub const SYS_writev = 121;
120pub const SYS_settimeofday = 122;
121pub const SYS_fchown = 123;
122pub const SYS_fchmod = 124;
123// 125 is old recvfrom
124pub const SYS_setreuid = 126;
125pub const SYS_setregid = 127;
126pub const SYS_rename = 128;
127// 129 is old truncate
128// 130 is old ftruncate
129pub const SYS_flock = 131;
130pub const SYS_mkfifo = 132;
131pub const SYS_sendto = 133;
132pub const SYS_shutdown = 134;
133pub const SYS_socketpair = 135;
134pub const SYS_mkdir = 136;
135pub const SYS_rmdir = 137;
136pub const SYS_utimes = 138;
137// 139 is obsolete 4.2 sigreturn
138pub const SYS_adjtime = 140;
139// 141 is old getpeername
140// 142 is old gethostid
141// 143 is old sethostid
142// 144 is old getrlimit
143// 145 is old setrlimit
144// 146 is old killpg
145pub const SYS_setsid = 147;
146pub const SYS_quotactl = 148;
147// 149 is old quota
148// 150 is old getsockname
149pub const SYS_nlm_syscall = 154;
150pub const SYS_nfssvc = 155;
151// 156 is old getdirentries
152// 157 is freebsd4 statfs
153// 158 is freebsd4 fstatfs
154pub const SYS_lgetfh = 160;
155pub const SYS_getfh = 161;
156// 162 is freebsd4 getdomainname
157// 163 is freebsd4 setdomainname
158// 164 is freebsd4 uname
159pub const SYS_sysarch = 165;
160pub const SYS_rtprio = 166;
161pub const SYS_semsys = 169;
162pub const SYS_msgsys = 170;
163pub const SYS_shmsys = 171;
164// 173 is freebsd6 pread
165// 174 is freebsd6 pwrite
166pub const SYS_setfib = 175;
167pub const SYS_ntp_adjtime = 176;
168pub const SYS_setgid = 181;
169pub const SYS_setegid = 182;
170pub const SYS_seteuid = 183;
171// 184 is obsolete lfs_bmapv
172// 185 is obsolete lfs_markv
173// 186 is obsolete lfs_segclean
174// 187 is obsolete lfs_segwait
175pub const SYS_freebsd11_stat = 188;
176pub const SYS_freebsd11_fstat = 189;
177pub const SYS_freebsd11_lstat = 190;
178pub const SYS_pathconf = 191;
179pub const SYS_fpathconf = 192;
180pub const SYS_getrlimit = 194;
181pub const SYS_setrlimit = 195;
182pub const SYS_freebsd11_getdirentries = 196;
183// 197 is freebsd6 mmap
184pub const SYS___syscall = 198;
185// 199 is freebsd6 lseek
186// 200 is freebsd6 truncate
187// 201 is freebsd6 ftruncate
188pub const SYS___sysctl = 202;
189pub const SYS_mlock = 203;
190pub const SYS_munlock = 204;
191pub const SYS_undelete = 205;
192pub const SYS_futimes = 206;
193pub const SYS_getpgid = 207;
194pub const SYS_poll = 209;
195pub const SYS_freebsd7___semctl = 220;
196pub const SYS_semget = 221;
197pub const SYS_semop = 222;
198pub const SYS_freebsd7_msgctl = 224;
199pub const SYS_msgget = 225;
200pub const SYS_msgsnd = 226;
201pub const SYS_msgrcv = 227;
202pub const SYS_shmat = 228;
203pub const SYS_freebsd7_shmctl = 229;
204pub const SYS_shmdt = 230;
205pub const SYS_shmget = 231;
206pub const SYS_clock_gettime = 232;
207pub const SYS_clock_settime = 233;
208pub const SYS_clock_getres = 234;
209pub const SYS_ktimer_create = 235;
210pub const SYS_ktimer_delete = 236;
211pub const SYS_ktimer_settime = 237;
212pub const SYS_ktimer_gettime = 238;
213pub const SYS_ktimer_getoverrun = 239;
214pub const SYS_nanosleep = 240;
215pub const SYS_ffclock_getcounter = 241;
216pub const SYS_ffclock_setestimate = 242;
217pub const SYS_ffclock_getestimate = 243;
218pub const SYS_clock_nanosleep = 244;
219pub const SYS_clock_getcpuclockid2 = 247;
220pub const SYS_ntp_gettime = 248;
221pub const SYS_minherit = 250;
222pub const SYS_rfork = 251;
223// 252 is obsolete openbsd_poll
224pub const SYS_issetugid = 253;
225pub const SYS_lchown = 254;
226pub const SYS_aio_read = 255;
227pub const SYS_aio_write = 256;
228pub const SYS_lio_listio = 257;
229pub const SYS_freebsd11_getdents = 272;
230pub const SYS_lchmod = 274;
231// 275 is obsolete netbsd_lchown
232pub const SYS_lutimes = 276;
233// 277 is obsolete netbsd_msync
234pub const SYS_freebsd11_nstat = 278;
235pub const SYS_freebsd11_nfstat = 279;
236pub const SYS_freebsd11_nlstat = 280;
237pub const SYS_preadv = 289;
238pub const SYS_pwritev = 290;
239// 297 is freebsd4 fhstatfs
240pub const SYS_fhopen = 298;
241pub const SYS_freebsd11_fhstat = 299;
242pub const SYS_modnext = 300;
243pub const SYS_modstat = 301;
244pub const SYS_modfnext = 302;
245pub const SYS_modfind = 303;
246pub const SYS_kldload = 304;
247pub const SYS_kldunload = 305;
248pub const SYS_kldfind = 306;
249pub const SYS_kldnext = 307;
250pub const SYS_kldstat = 308;
251pub const SYS_kldfirstmod = 309;
252pub const SYS_getsid = 310;
253pub const SYS_setresuid = 311;
254pub const SYS_setresgid = 312;
255// 313 is obsolete signanosleep
256pub const SYS_aio_return = 314;
257pub const SYS_aio_suspend = 315;
258pub const SYS_aio_cancel = 316;
259pub const SYS_aio_error = 317;
260// 318 is freebsd6 aio_read
261// 319 is freebsd6 aio_write
262// 320 is freebsd6 lio_listio
263pub const SYS_yield = 321;
264// 322 is obsolete thr_sleep
265// 323 is obsolete thr_wakeup
266pub const SYS_mlockall = 324;
267pub const SYS_munlockall = 325;
268pub const SYS___getcwd = 326;
269pub const SYS_sched_setparam = 327;
270pub const SYS_sched_getparam = 328;
271pub const SYS_sched_setscheduler = 329;
272pub const SYS_sched_getscheduler = 330;
273pub const SYS_sched_yield = 331;
274pub const SYS_sched_get_priority_max = 332;
275pub const SYS_sched_get_priority_min = 333;
276pub const SYS_sched_rr_get_interval = 334;
277pub const SYS_utrace = 335;
278// 336 is freebsd4 sendfile
279pub const SYS_kldsym = 337;
280pub const SYS_jail = 338;
281pub const SYS_nnpfs_syscall = 339;
282pub const SYS_sigprocmask = 340;
283pub const SYS_sigsuspend = 341;
284// 342 is freebsd4 sigaction
285pub const SYS_sigpending = 343;
286// 344 is freebsd4 sigreturn
287pub const SYS_sigtimedwait = 345;
288pub const SYS_sigwaitinfo = 346;
289pub const SYS___acl_get_file = 347;
290pub const SYS___acl_set_file = 348;
291pub const SYS___acl_get_fd = 349;
292pub const SYS___acl_set_fd = 350;
293pub const SYS___acl_delete_file = 351;
294pub const SYS___acl_delete_fd = 352;
295pub const SYS___acl_aclcheck_file = 353;
296pub const SYS___acl_aclcheck_fd = 354;
297pub const SYS_extattrctl = 355;
298pub const SYS_extattr_set_file = 356;
299pub const SYS_extattr_get_file = 357;
300pub const SYS_extattr_delete_file = 358;
301pub const SYS_aio_waitcomplete = 359;
302pub const SYS_getresuid = 360;
303pub const SYS_getresgid = 361;
304pub const SYS_kqueue = 362;
305pub const SYS_freebsd11_kevent = 363;
306// 364 is obsolete __cap_get_proc
307// 365 is obsolete __cap_set_proc
308// 366 is obsolete __cap_get_fd
309// 367 is obsolete __cap_get_file
310// 368 is obsolete __cap_set_fd
311// 369 is obsolete __cap_set_file
312pub const SYS_extattr_set_fd = 371;
313pub const SYS_extattr_get_fd = 372;
314pub const SYS_extattr_delete_fd = 373;
315pub const SYS___setugid = 374;
316pub const SYS_eaccess = 376;
317pub const SYS_afs3_syscall = 377;
318pub const SYS_nmount = 378;
319// 379 is obsolete kse_exit
320// 380 is obsolete kse_wakeup
321// 381 is obsolete kse_create
322// 382 is obsolete kse_thr_interrupt
323// 383 is obsolete kse_release
324pub const SYS___mac_get_proc = 384;
325pub const SYS___mac_set_proc = 385;
326pub const SYS___mac_get_fd = 386;
327pub const SYS___mac_get_file = 387;
328pub const SYS___mac_set_fd = 388;
329pub const SYS___mac_set_file = 389;
330pub const SYS_kenv = 390;
331pub const SYS_lchflags = 391;
332pub const SYS_uuidgen = 392;
333pub const SYS_sendfile = 393;
334pub const SYS_mac_syscall = 394;
335pub const SYS_freebsd11_getfsstat = 395;
336pub const SYS_freebsd11_statfs = 396;
337pub const SYS_freebsd11_fstatfs = 397;
338pub const SYS_freebsd11_fhstatfs = 398;
339pub const SYS_ksem_close = 400;
340pub const SYS_ksem_post = 401;
341pub const SYS_ksem_wait = 402;
342pub const SYS_ksem_trywait = 403;
343pub const SYS_ksem_init = 404;
344pub const SYS_ksem_open = 405;
345pub const SYS_ksem_unlink = 406;
346pub const SYS_ksem_getvalue = 407;
347pub const SYS_ksem_destroy = 408;
348pub const SYS___mac_get_pid = 409;
349pub const SYS___mac_get_link = 410;
350pub const SYS___mac_set_link = 411;
351pub const SYS_extattr_set_link = 412;
352pub const SYS_extattr_get_link = 413;
353pub const SYS_extattr_delete_link = 414;
354pub const SYS___mac_execve = 415;
355pub const SYS_sigaction = 416;
356pub const SYS_sigreturn = 417;
357pub const SYS_getcontext = 421;
358pub const SYS_setcontext = 422;
359pub const SYS_swapcontext = 423;
360pub const SYS_swapoff = 424;
361pub const SYS___acl_get_link = 425;
362pub const SYS___acl_set_link = 426;
363pub const SYS___acl_delete_link = 427;
364pub const SYS___acl_aclcheck_link = 428;
365pub const SYS_sigwait = 429;
366pub const SYS_thr_create = 430;
367pub const SYS_thr_exit = 431;
368pub const SYS_thr_self = 432;
369pub const SYS_thr_kill = 433;
370pub const SYS_jail_attach = 436;
371pub const SYS_extattr_list_fd = 437;
372pub const SYS_extattr_list_file = 438;
373pub const SYS_extattr_list_link = 439;
374// 440 is obsolete kse_switchin
375pub const SYS_ksem_timedwait = 441;
376pub const SYS_thr_suspend = 442;
377pub const SYS_thr_wake = 443;
378pub const SYS_kldunloadf = 444;
379pub const SYS_audit = 445;
380pub const SYS_auditon = 446;
381pub const SYS_getauid = 447;
382pub const SYS_setauid = 448;
383pub const SYS_getaudit = 449;
384pub const SYS_setaudit = 450;
385pub const SYS_getaudit_addr = 451;
386pub const SYS_setaudit_addr = 452;
387pub const SYS_auditctl = 453;
388pub const SYS__umtx_op = 454;
389pub const SYS_thr_new = 455;
390pub const SYS_sigqueue = 456;
391pub const SYS_kmq_open = 457;
392pub const SYS_kmq_setattr = 458;
393pub const SYS_kmq_timedreceive = 459;
394pub const SYS_kmq_timedsend = 460;
395pub const SYS_kmq_notify = 461;
396pub const SYS_kmq_unlink = 462;
397pub const SYS_abort2 = 463;
398pub const SYS_thr_set_name = 464;
399pub const SYS_aio_fsync = 465;
400pub const SYS_rtprio_thread = 466;
401pub const SYS_sctp_peeloff = 471;
402pub const SYS_sctp_generic_sendmsg = 472;
403pub const SYS_sctp_generic_sendmsg_iov = 473;
404pub const SYS_sctp_generic_recvmsg = 474;
405pub const SYS_pread = 475;
406pub const SYS_pwrite = 476;
407pub const SYS_mmap = 477;
408pub const SYS_lseek = 478;
409pub const SYS_truncate = 479;
410pub const SYS_ftruncate = 480;
411pub const SYS_thr_kill2 = 481;
412pub const SYS_shm_open = 482;
413pub const SYS_shm_unlink = 483;
414pub const SYS_cpuset = 484;
415pub const SYS_cpuset_setid = 485;
416pub const SYS_cpuset_getid = 486;
417pub const SYS_cpuset_getaffinity = 487;
418pub const SYS_cpuset_setaffinity = 488;
419pub const SYS_faccessat = 489;
420pub const SYS_fchmodat = 490;
421pub const SYS_fchownat = 491;
422pub const SYS_fexecve = 492;
423pub const SYS_freebsd11_fstatat = 493;
424pub const SYS_futimesat = 494;
425pub const SYS_linkat = 495;
426pub const SYS_mkdirat = 496;
427pub const SYS_mkfifoat = 497;
428pub const SYS_freebsd11_mknodat = 498;
429pub const SYS_openat = 499;
430pub const SYS_readlinkat = 500;
431pub const SYS_renameat = 501;
432pub const SYS_symlinkat = 502;
433pub const SYS_unlinkat = 503;
434pub const SYS_posix_openpt = 504;
435pub const SYS_gssd_syscall = 505;
436pub const SYS_jail_get = 506;
437pub const SYS_jail_set = 507;
438pub const SYS_jail_remove = 508;
439pub const SYS_closefrom = 509;
440pub const SYS___semctl = 510;
441pub const SYS_msgctl = 511;
442pub const SYS_shmctl = 512;
443pub const SYS_lpathconf = 513;
444// 514 is obsolete cap_new
445pub const SYS___cap_rights_get = 515;
446pub const SYS_cap_enter = 516;
447pub const SYS_cap_getmode = 517;
448pub const SYS_pdfork = 518;
449pub const SYS_pdkill = 519;
450pub const SYS_pdgetpid = 520;
451pub const SYS_pselect = 522;
452pub const SYS_getloginclass = 523;
453pub const SYS_setloginclass = 524;
454pub const SYS_rctl_get_racct = 525;
455pub const SYS_rctl_get_rules = 526;
456pub const SYS_rctl_get_limits = 527;
457pub const SYS_rctl_add_rule = 528;
458pub const SYS_rctl_remove_rule = 529;
459pub const SYS_posix_fallocate = 530;
460pub const SYS_posix_fadvise = 531;
461pub const SYS_wait6 = 532;
462pub const SYS_cap_rights_limit = 533;
463pub const SYS_cap_ioctls_limit = 534;
464pub const SYS_cap_ioctls_get = 535;
465pub const SYS_cap_fcntls_limit = 536;
466pub const SYS_cap_fcntls_get = 537;
467pub const SYS_bindat = 538;
468pub const SYS_connectat = 539;
469pub const SYS_chflagsat = 540;
470pub const SYS_accept4 = 541;
471pub const SYS_pipe2 = 542;
472pub const SYS_aio_mlock = 543;
473pub const SYS_procctl = 544;
474pub const SYS_ppoll = 545;
475pub const SYS_futimens = 546;
476pub const SYS_utimensat = 547;
477// 548 is obsolete numa_getaffinity
478// 549 is obsolete numa_setaffinity
479pub const SYS_fdatasync = 550;
480pub const SYS_fstat = 551;
481pub const SYS_fstatat = 552;
482pub const SYS_fhstat = 553;
483pub const SYS_getdirentries = 554;
484pub const SYS_statfs = 555;
485pub const SYS_fstatfs = 556;
486pub const SYS_getfsstat = 557;
487pub const SYS_fhstatfs = 558;
488pub const SYS_mknodat = 559;
489pub const SYS_kevent = 560;
490pub const SYS_cpuset_getdomain = 561;
491pub const SYS_cpuset_setdomain = 562;
492pub const SYS_getrandom = 563;
493pub const SYS_MAXSYSCALL = 564;
std/os/freebsd/x86_64.zig deleted-136
...@@ -1,136 +0,0 @@
1const freebsd = @import("index.zig");
2const socklen_t = freebsd.socklen_t;
3const iovec = freebsd.iovec;
4
5pub const SYS_sbrk = 69;
6
7pub fn syscall0(number: usize) usize {
8 return asm volatile ("syscall"
9 : [ret] "={rax}" (-> usize)
10 : [number] "{rax}" (number)
11 : "rcx", "r11"
12 );
13}
14
15pub fn syscall1(number: usize, arg1: usize) usize {
16 return asm volatile ("syscall"
17 : [ret] "={rax}" (-> usize)
18 : [number] "{rax}" (number),
19 [arg1] "{rdi}" (arg1)
20 : "rcx", "r11"
21 );
22}
23
24pub fn syscall2(number: usize, arg1: usize, arg2: usize) usize {
25 return asm volatile ("syscall"
26 : [ret] "={rax}" (-> usize)
27 : [number] "{rax}" (number),
28 [arg1] "{rdi}" (arg1),
29 [arg2] "{rsi}" (arg2)
30 : "rcx", "r11"
31 );
32}
33
34pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize {
35 return asm volatile ("syscall"
36 : [ret] "={rax}" (-> usize)
37 : [number] "{rax}" (number),
38 [arg1] "{rdi}" (arg1),
39 [arg2] "{rsi}" (arg2),
40 [arg3] "{rdx}" (arg3)
41 : "rcx", "r11"
42 );
43}
44
45pub fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
46 return asm volatile ("syscall"
47 : [ret] "={rax}" (-> usize)
48 : [number] "{rax}" (number),
49 [arg1] "{rdi}" (arg1),
50 [arg2] "{rsi}" (arg2),
51 [arg3] "{rdx}" (arg3),
52 [arg4] "{r10}" (arg4)
53 : "rcx", "r11"
54 );
55}
56
57pub fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
58 return asm volatile ("syscall"
59 : [ret] "={rax}" (-> usize)
60 : [number] "{rax}" (number),
61 [arg1] "{rdi}" (arg1),
62 [arg2] "{rsi}" (arg2),
63 [arg3] "{rdx}" (arg3),
64 [arg4] "{r10}" (arg4),
65 [arg5] "{r8}" (arg5)
66 : "rcx", "r11"
67 );
68}
69
70pub fn syscall6(
71 number: usize,
72 arg1: usize,
73 arg2: usize,
74 arg3: usize,
75 arg4: usize,
76 arg5: usize,
77 arg6: usize,
78) usize {
79 return asm volatile ("syscall"
80 : [ret] "={rax}" (-> usize)
81 : [number] "{rax}" (number),
82 [arg1] "{rdi}" (arg1),
83 [arg2] "{rsi}" (arg2),
84 [arg3] "{rdx}" (arg3),
85 [arg4] "{r10}" (arg4),
86 [arg5] "{r8}" (arg5),
87 [arg6] "{r9}" (arg6)
88 : "rcx", "r11"
89 );
90}
91
92pub nakedcc fn restore_rt() void {
93 asm volatile ("syscall"
94 :
95 : [number] "{rax}" (usize(SYS_rt_sigreturn))
96 : "rcx", "r11"
97 );
98}
99
100pub const msghdr = extern struct {
101 msg_name: &u8,
102 msg_namelen: socklen_t,
103 msg_iov: &iovec,
104 msg_iovlen: i32,
105 __pad1: i32,
106 msg_control: &u8,
107 msg_controllen: socklen_t,
108 __pad2: socklen_t,
109 msg_flags: i32,
110};
111
112/// Renamed to Stat to not conflict with the stat function.
113pub const Stat = extern struct {
114 dev: u64,
115 ino: u64,
116 nlink: usize,
117
118 mode: u32,
119 uid: u32,
120 gid: u32,
121 __pad0: u32,
122 rdev: u64,
123 size: i64,
124 blksize: isize,
125 blocks: i64,
126
127 atim: timespec,
128 mtim: timespec,
129 ctim: timespec,
130 __unused: [3]isize,
131};
132
133pub const timespec = extern struct {
134 tv_sec: isize,
135 tv_nsec: isize,
136};
std/os/get_app_data_dir.zig+3-4
...@@ -30,7 +30,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD...@@ -30,7 +30,7 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD
30 error.OutOfMemory => return error.OutOfMemory,30 error.OutOfMemory => return error.OutOfMemory,
31 };31 };
32 defer allocator.free(global_dir);32 defer allocator.free(global_dir);
33 return os.path.join(allocator, global_dir, appname);33 return os.path.join(allocator, [][]const u8{ global_dir, appname });
34 },34 },
35 os.windows.E_OUTOFMEMORY => return error.OutOfMemory,35 os.windows.E_OUTOFMEMORY => return error.OutOfMemory,
36 else => return error.AppDataDirUnavailable,36 else => return error.AppDataDirUnavailable,
...@@ -41,14 +41,14 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD...@@ -41,14 +41,14 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD
41 // TODO look in /etc/passwd41 // TODO look in /etc/passwd
42 return error.AppDataDirUnavailable;42 return error.AppDataDirUnavailable;
43 };43 };
44 return os.path.join(allocator, home_dir, "Library", "Application Support", appname);44 return os.path.join(allocator, [][]const u8{ home_dir, "Library", "Application Support", appname });
45 },45 },
46 builtin.Os.linux, builtin.Os.freebsd => {46 builtin.Os.linux, builtin.Os.freebsd => {
47 const home_dir = os.getEnvPosix("HOME") orelse {47 const home_dir = os.getEnvPosix("HOME") orelse {
48 // TODO look in /etc/passwd48 // TODO look in /etc/passwd
49 return error.AppDataDirUnavailable;49 return error.AppDataDirUnavailable;
50 };50 };
51 return os.path.join(allocator, home_dir, ".local", "share", appname);51 return os.path.join(allocator, [][]const u8{ home_dir, ".local", "share", appname });
52 },52 },
53 else => @compileError("Unsupported OS"),53 else => @compileError("Unsupported OS"),
54 }54 }
...@@ -67,4 +67,3 @@ test "std.os.getAppDataDir" {...@@ -67,4 +67,3 @@ test "std.os.getAppDataDir" {
67 // We can't actually validate the result67 // We can't actually validate the result
68 _ = getAppDataDir(allocator, "zig") catch return;68 _ = getAppDataDir(allocator, "zig") catch return;
69}69}
70
std/os/index.zig+187-64
...@@ -8,6 +8,10 @@ const is_posix = switch (builtin.os) {...@@ -8,6 +8,10 @@ const is_posix = switch (builtin.os) {
8};8};
9const os = @This();9const os = @This();
1010
11comptime {
12 assert(@import("std") == std); // You have to run the std lib tests with --override-std-dir
13}
14
11test "std.os" {15test "std.os" {
12 _ = @import("child_process.zig");16 _ = @import("child_process.zig");
13 _ = @import("darwin.zig");17 _ = @import("darwin.zig");
...@@ -18,6 +22,7 @@ test "std.os" {...@@ -18,6 +22,7 @@ test "std.os" {
18 _ = @import("test.zig");22 _ = @import("test.zig");
19 _ = @import("time.zig");23 _ = @import("time.zig");
20 _ = @import("windows/index.zig");24 _ = @import("windows/index.zig");
25 _ = @import("uefi.zig");
21 _ = @import("get_app_data_dir.zig");26 _ = @import("get_app_data_dir.zig");
22}27}
2328
...@@ -26,6 +31,8 @@ pub const darwin = @import("darwin.zig");...@@ -26,6 +31,8 @@ pub const darwin = @import("darwin.zig");
26pub const linux = @import("linux/index.zig");31pub const linux = @import("linux/index.zig");
27pub const freebsd = @import("freebsd/index.zig");32pub const freebsd = @import("freebsd/index.zig");
28pub const zen = @import("zen.zig");33pub const zen = @import("zen.zig");
34pub const uefi = @import("uefi.zig");
35
29pub const posix = switch (builtin.os) {36pub const posix = switch (builtin.os) {
30 Os.linux => linux,37 Os.linux => linux,
31 Os.macosx, Os.ios => darwin,38 Os.macosx, Os.ios => darwin,
...@@ -33,6 +40,7 @@ pub const posix = switch (builtin.os) {...@@ -33,6 +40,7 @@ pub const posix = switch (builtin.os) {
33 Os.zen => zen,40 Os.zen => zen,
34 else => @compileError("Unsupported OS"),41 else => @compileError("Unsupported OS"),
35};42};
43
36pub const net = @import("net.zig");44pub const net = @import("net.zig");
3745
38pub const ChildProcess = @import("child_process.zig").ChildProcess;46pub const ChildProcess = @import("child_process.zig").ChildProcess;
...@@ -83,6 +91,7 @@ pub const GetAppDataDirError = @import("get_app_data_dir.zig").GetAppDataDirErro...@@ -83,6 +91,7 @@ pub const GetAppDataDirError = @import("get_app_data_dir.zig").GetAppDataDirErro
8391
84const debug = std.debug;92const debug = std.debug;
85const assert = debug.assert;93const assert = debug.assert;
94const testing = std.testing;
8695
87const c = std.c;96const c = std.c;
8897
...@@ -103,7 +112,7 @@ const math = std.math;...@@ -103,7 +112,7 @@ const math = std.math;
103/// library implementation.112/// library implementation.
104pub fn getRandomBytes(buf: []u8) !void {113pub fn getRandomBytes(buf: []u8) !void {
105 switch (builtin.os) {114 switch (builtin.os) {
106 Os.linux, Os.freebsd => while (true) {115 Os.linux => while (true) {
107 // TODO check libc version and potentially call c.getrandom.116 // TODO check libc version and potentially call c.getrandom.
108 // See #397117 // See #397
109 const errno = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0));118 const errno = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0));
...@@ -116,7 +125,7 @@ pub fn getRandomBytes(buf: []u8) !void {...@@ -116,7 +125,7 @@ pub fn getRandomBytes(buf: []u8) !void {
116 else => return unexpectedErrorPosix(errno),125 else => return unexpectedErrorPosix(errno),
117 }126 }
118 },127 },
119 Os.macosx, Os.ios => return getRandomBytesDevURandom(buf),128 Os.macosx, Os.ios, Os.freebsd => return getRandomBytesDevURandom(buf),
120 Os.windows => {129 Os.windows => {
121 // Call RtlGenRandom() instead of CryptGetRandom() on Windows130 // Call RtlGenRandom() instead of CryptGetRandom() on Windows
122 // https://github.com/rust-lang-nursery/rand/issues/111131 // https://github.com/rust-lang-nursery/rand/issues/111
...@@ -164,7 +173,7 @@ test "os.getRandomBytes" {...@@ -164,7 +173,7 @@ test "os.getRandomBytes" {
164 try getRandomBytes(buf_b[0..]);173 try getRandomBytes(buf_b[0..]);
165174
166 // Check if random (not 100% conclusive)175 // Check if random (not 100% conclusive)
167 assert(!mem.eql(u8, buf_a, buf_b));176 testing.expect(!mem.eql(u8, buf_a, buf_b));
168}177}
169178
170/// Raises a signal in the current kernel thread, ending its execution.179/// Raises a signal in the current kernel thread, ending its execution.
...@@ -187,6 +196,10 @@ pub fn abort() noreturn {...@@ -187,6 +196,10 @@ pub fn abort() noreturn {
187 }196 }
188 windows.ExitProcess(3);197 windows.ExitProcess(3);
189 },198 },
199 Os.uefi => {
200 // TODO there's gotta be a better thing to do here than loop forever
201 while (true) {}
202 },
190 else => @compileError("Unsupported OS"),203 else => @compileError("Unsupported OS"),
191 }204 }
192}205}
...@@ -459,6 +472,7 @@ pub const PosixOpenError = error{...@@ -459,6 +472,7 @@ pub const PosixOpenError = error{
459 NoSpaceLeft,472 NoSpaceLeft,
460 NotDir,473 NotDir,
461 PathAlreadyExists,474 PathAlreadyExists,
475 DeviceBusy,
462476
463 /// See https://github.com/ziglang/zig/issues/1396477 /// See https://github.com/ziglang/zig/issues/1396
464 Unexpected,478 Unexpected,
...@@ -497,6 +511,7 @@ pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 {...@@ -497,6 +511,7 @@ pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 {
497 posix.ENOTDIR => return PosixOpenError.NotDir,511 posix.ENOTDIR => return PosixOpenError.NotDir,
498 posix.EPERM => return PosixOpenError.AccessDenied,512 posix.EPERM => return PosixOpenError.AccessDenied,
499 posix.EEXIST => return PosixOpenError.PathAlreadyExists,513 posix.EEXIST => return PosixOpenError.PathAlreadyExists,
514 posix.EBUSY => return PosixOpenError.DeviceBusy,
500 else => return unexpectedErrorPosix(err),515 else => return unexpectedErrorPosix(err),
501 }516 }
502 }517 }
...@@ -598,7 +613,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: *const BufMap, allocator:...@@ -598,7 +613,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: *const BufMap, allocator:
598 // +1 for the null terminating byte613 // +1 for the null terminating byte
599 const path_buf = try allocator.alloc(u8, PATH.len + exe_path.len + 2);614 const path_buf = try allocator.alloc(u8, PATH.len + exe_path.len + 2);
600 defer allocator.free(path_buf);615 defer allocator.free(path_buf);
601 var it = mem.split(PATH, ":");616 var it = mem.tokenize(PATH, ":");
602 var seen_eacces = false;617 var seen_eacces = false;
603 var err: usize = undefined;618 var err: usize = undefined;
604 while (it.next()) |search_path| {619 while (it.next()) |search_path| {
...@@ -682,12 +697,7 @@ pub fn getBaseAddress() usize {...@@ -682,12 +697,7 @@ pub fn getBaseAddress() usize {
682 return base;697 return base;
683 }698 }
684 const phdr = linuxGetAuxVal(std.elf.AT_PHDR);699 const phdr = linuxGetAuxVal(std.elf.AT_PHDR);
685 const ElfHeader = switch (@sizeOf(usize)) {700 return phdr - @sizeOf(std.elf.Ehdr);
686 4 => std.elf.Elf32_Ehdr,
687 8 => std.elf.Elf64_Ehdr,
688 else => @compileError("Unsupported architecture"),
689 };
690 return phdr - @sizeOf(ElfHeader);
691 },701 },
692 builtin.Os.macosx, builtin.Os.freebsd => return @ptrToInt(&std.c._mh_execute_header),702 builtin.Os.macosx, builtin.Os.freebsd => return @ptrToInt(&std.c._mh_execute_header),
693 builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)),703 builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)),
...@@ -702,8 +712,8 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {...@@ -702,8 +712,8 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
702 errdefer result.deinit();712 errdefer result.deinit();
703713
704 if (is_windows) {714 if (is_windows) {
705 const ptr = windows.GetEnvironmentStringsA() orelse return error.OutOfMemory;715 const ptr = windows.GetEnvironmentStringsW() orelse return error.OutOfMemory;
706 defer assert(windows.FreeEnvironmentStringsA(ptr) != 0);716 defer assert(windows.FreeEnvironmentStringsW(ptr) != 0);
707717
708 var i: usize = 0;718 var i: usize = 0;
709 while (true) {719 while (true) {
...@@ -712,17 +722,21 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {...@@ -712,17 +722,21 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
712 const key_start = i;722 const key_start = i;
713723
714 while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {}724 while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {}
715 const key = ptr[key_start..i];725 const key_w = ptr[key_start..i];
726 const key = try std.unicode.utf16leToUtf8Alloc(allocator, key_w);
727 errdefer allocator.free(key);
716728
717 if (ptr[i] == '=') i += 1;729 if (ptr[i] == '=') i += 1;
718730
719 const value_start = i;731 const value_start = i;
720 while (ptr[i] != 0) : (i += 1) {}732 while (ptr[i] != 0) : (i += 1) {}
721 const value = ptr[value_start..i];733 const value_w = ptr[value_start..i];
734 const value = try std.unicode.utf16leToUtf8Alloc(allocator, value_w);
735 errdefer allocator.free(value);
722736
723 i += 1; // skip over null byte737 i += 1; // skip over null byte
724738
725 try result.set(key, value);739 try result.setMove(key, value);
726 }740 }
727 } else {741 } else {
728 for (posix_environ_raw) |ptr| {742 for (posix_environ_raw) |ptr| {
...@@ -740,6 +754,11 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {...@@ -740,6 +754,11 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
740 }754 }
741}755}
742756
757test "os.getEnvMap" {
758 var env = try getEnvMap(std.debug.global_allocator);
759 defer env.deinit();
760}
761
743/// TODO make this go through libc when we have it762/// TODO make this go through libc when we have it
744pub fn getEnvPosix(key: []const u8) ?[]const u8 {763pub fn getEnvPosix(key: []const u8) ?[]const u8 {
745 for (posix_environ_raw) |ptr| {764 for (posix_environ_raw) |ptr| {
...@@ -760,21 +779,24 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 {...@@ -760,21 +779,24 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 {
760pub const GetEnvVarOwnedError = error{779pub const GetEnvVarOwnedError = error{
761 OutOfMemory,780 OutOfMemory,
762 EnvironmentVariableNotFound,781 EnvironmentVariableNotFound,
782
783 /// See https://github.com/ziglang/zig/issues/1774
784 InvalidUtf8,
763};785};
764786
765/// Caller must free returned memory.787/// Caller must free returned memory.
766/// TODO make this go through libc when we have it788/// TODO make this go through libc when we have it
767pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 {789pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 {
768 if (is_windows) {790 if (is_windows) {
769 const key_with_null = try cstr.addNullByte(allocator, key);791 const key_with_null = try std.unicode.utf8ToUtf16LeWithNull(allocator, key);
770 defer allocator.free(key_with_null);792 defer allocator.free(key_with_null);
771793
772 var buf = try allocator.alloc(u8, 256);794 var buf = try allocator.alloc(u16, 256);
773 errdefer allocator.free(buf);795 defer allocator.free(buf);
774796
775 while (true) {797 while (true) {
776 const windows_buf_len = math.cast(windows.DWORD, buf.len) catch return error.OutOfMemory;798 const windows_buf_len = math.cast(windows.DWORD, buf.len) catch return error.OutOfMemory;
777 const result = windows.GetEnvironmentVariableA(key_with_null.ptr, buf.ptr, windows_buf_len);799 const result = windows.GetEnvironmentVariableW(key_with_null.ptr, buf.ptr, windows_buf_len);
778800
779 if (result == 0) {801 if (result == 0) {
780 const err = windows.GetLastError();802 const err = windows.GetLastError();
...@@ -788,11 +810,16 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned...@@ -788,11 +810,16 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned
788 }810 }
789811
790 if (result > buf.len) {812 if (result > buf.len) {
791 buf = try allocator.realloc(u8, buf, result);813 buf = try allocator.realloc(u16, buf, result);
792 continue;814 continue;
793 }815 }
794816
795 return allocator.shrink(u8, buf, result);817 return std.unicode.utf16leToUtf8Alloc(allocator, buf) catch |err| switch (err) {
818 error.DanglingSurrogateHalf => return error.InvalidUtf8,
819 error.ExpectedSecondSurrogateHalf => return error.InvalidUtf8,
820 error.UnexpectedSecondSurrogateHalf => return error.InvalidUtf8,
821 error.OutOfMemory => return error.OutOfMemory,
822 };
796 }823 }
797 } else {824 } else {
798 const result = getEnvPosix(key) orelse return error.EnvironmentVariableNotFound;825 const result = getEnvPosix(key) orelse return error.EnvironmentVariableNotFound;
...@@ -800,6 +827,11 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned...@@ -800,6 +827,11 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned
800 }827 }
801}828}
802829
830test "os.getEnvVarOwned" {
831 var ga = debug.global_allocator;
832 testing.expectError(error.EnvironmentVariableNotFound, getEnvVarOwned(ga, "BADENV"));
833}
834
803/// Caller must free the returned memory.835/// Caller must free the returned memory.
804pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {836pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {
805 var buf: [MAX_PATH_BYTES]u8 = undefined;837 var buf: [MAX_PATH_BYTES]u8 = undefined;
...@@ -1253,7 +1285,7 @@ pub fn makeDirPosix(dir_path: []const u8) !void {...@@ -1253,7 +1285,7 @@ pub fn makeDirPosix(dir_path: []const u8) !void {
1253/// already exists and is a directory.1285/// already exists and is a directory.
1254/// TODO determine if we can remove the allocator requirement from this function1286/// TODO determine if we can remove the allocator requirement from this function
1255pub fn makePath(allocator: *Allocator, full_path: []const u8) !void {1287pub fn makePath(allocator: *Allocator, full_path: []const u8) !void {
1256 const resolved_path = try path.resolve(allocator, full_path);1288 const resolved_path = try path.resolve(allocator, [][]const u8{full_path});
1257 defer allocator.free(resolved_path);1289 defer allocator.free(resolved_path);
12581290
1259 var end_index: usize = resolved_path.len;1291 var end_index: usize = resolved_path.len;
...@@ -1380,6 +1412,7 @@ const DeleteTreeError = error{...@@ -1380,6 +1412,7 @@ const DeleteTreeError = error{
1380 FileSystem,1412 FileSystem,
1381 FileBusy,1413 FileBusy,
1382 DirNotEmpty,1414 DirNotEmpty,
1415 DeviceBusy,
13831416
1384 /// On Windows, file paths must be valid Unicode.1417 /// On Windows, file paths must be valid Unicode.
1385 InvalidUtf8,1418 InvalidUtf8,
...@@ -1441,6 +1474,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError!...@@ -1441,6 +1474,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError!
1441 error.Unexpected,1474 error.Unexpected,
1442 error.InvalidUtf8,1475 error.InvalidUtf8,
1443 error.BadPathName,1476 error.BadPathName,
1477 error.DeviceBusy,
1444 => return err,1478 => return err,
1445 };1479 };
1446 defer dir.close();1480 defer dir.close();
...@@ -1523,6 +1557,7 @@ pub const Dir = struct {...@@ -1523,6 +1557,7 @@ pub const Dir = struct {
1523 OutOfMemory,1557 OutOfMemory,
1524 InvalidUtf8,1558 InvalidUtf8,
1525 BadPathName,1559 BadPathName,
1560 DeviceBusy,
15261561
1527 /// See https://github.com/ziglang/zig/issues/13961562 /// See https://github.com/ziglang/zig/issues/1396
1528 Unexpected,1563 Unexpected,
...@@ -1731,8 +1766,57 @@ pub const Dir = struct {...@@ -1731,8 +1766,57 @@ pub const Dir = struct {
1731 }1766 }
17321767
1733 fn nextFreebsd(self: *Dir) !?Entry {1768 fn nextFreebsd(self: *Dir) !?Entry {
1734 //self.handle.buf = try self.allocator.alloc(u8, page_size);1769 start_over: while (true) {
1735 @compileError("TODO implement dirs for FreeBSD");1770 if (self.handle.index >= self.handle.end_index) {
1771 if (self.handle.buf.len == 0) {
1772 self.handle.buf = try self.allocator.alloc(u8, page_size);
1773 }
1774
1775 while (true) {
1776 const result = posix.getdirentries(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len, &self.handle.seek);
1777 const err = posix.getErrno(result);
1778 if (err > 0) {
1779 switch (err) {
1780 posix.EBADF, posix.EFAULT, posix.ENOTDIR => unreachable,
1781 posix.EINVAL => {
1782 self.handle.buf = try self.allocator.realloc(u8, self.handle.buf, self.handle.buf.len * 2);
1783 continue;
1784 },
1785 else => return unexpectedErrorPosix(err),
1786 }
1787 }
1788 if (result == 0) return null;
1789 self.handle.index = 0;
1790 self.handle.end_index = result;
1791 break;
1792 }
1793 }
1794 const freebsd_entry = @ptrCast(*align(1) posix.dirent, &self.handle.buf[self.handle.index]);
1795 const next_index = self.handle.index + freebsd_entry.d_reclen;
1796 self.handle.index = next_index;
1797
1798 const name = @ptrCast([*]u8, &freebsd_entry.d_name)[0..freebsd_entry.d_namlen];
1799
1800 if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) {
1801 continue :start_over;
1802 }
1803
1804 const entry_kind = switch (freebsd_entry.d_type) {
1805 posix.DT_BLK => Entry.Kind.BlockDevice,
1806 posix.DT_CHR => Entry.Kind.CharacterDevice,
1807 posix.DT_DIR => Entry.Kind.Directory,
1808 posix.DT_FIFO => Entry.Kind.NamedPipe,
1809 posix.DT_LNK => Entry.Kind.SymLink,
1810 posix.DT_REG => Entry.Kind.File,
1811 posix.DT_SOCK => Entry.Kind.UnixDomainSocket,
1812 posix.DT_WHT => Entry.Kind.Whiteout,
1813 else => Entry.Kind.Unknown,
1814 };
1815 return Entry{
1816 .name = name,
1817 .kind = entry_kind,
1818 };
1819 }
1736 }1820 }
1737};1821};
17381822
...@@ -2136,9 +2220,9 @@ fn testWindowsCmdLine(input_cmd_line: [*]const u8, expected_args: []const []cons...@@ -2136,9 +2220,9 @@ fn testWindowsCmdLine(input_cmd_line: [*]const u8, expected_args: []const []cons
2136 var it = ArgIteratorWindows.initWithCmdLine(input_cmd_line);2220 var it = ArgIteratorWindows.initWithCmdLine(input_cmd_line);
2137 for (expected_args) |expected_arg| {2221 for (expected_args) |expected_arg| {
2138 const arg = it.next(debug.global_allocator).? catch unreachable;2222 const arg = it.next(debug.global_allocator).? catch unreachable;
2139 assert(mem.eql(u8, arg, expected_arg));2223 testing.expectEqualSlices(u8, expected_arg, arg);
2140 }2224 }
2141 assert(it.next(debug.global_allocator) == null);2225 testing.expect(it.next(debug.global_allocator) == null);
2142}2226}
21432227
2144// TODO make this a build variable that you can set2228// TODO make this a build variable that you can set
...@@ -2220,7 +2304,19 @@ pub fn selfExePathW(out_buffer: *[windows_util.PATH_MAX_WIDE]u16) ![]u16 {...@@ -2220,7 +2304,19 @@ pub fn selfExePathW(out_buffer: *[windows_util.PATH_MAX_WIDE]u16) ![]u16 {
2220pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {2304pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
2221 switch (builtin.os) {2305 switch (builtin.os) {
2222 Os.linux => return readLink(out_buffer, "/proc/self/exe"),2306 Os.linux => return readLink(out_buffer, "/proc/self/exe"),
2223 Os.freebsd => return readLink(out_buffer, "/proc/curproc/file"),2307 Os.freebsd => {
2308 var mib = [4]c_int{ posix.CTL_KERN, posix.KERN_PROC, posix.KERN_PROC_PATHNAME, -1 };
2309 var out_len: usize = out_buffer.len;
2310 const err = posix.getErrno(posix.sysctl(&mib, 4, out_buffer, &out_len, null, 0));
2311
2312 if (err == 0) return mem.toSlice(u8, out_buffer);
2313
2314 return switch (err) {
2315 posix.EFAULT => error.BadAdress,
2316 posix.EPERM => error.PermissionDenied,
2317 else => unexpectedErrorPosix(err),
2318 };
2319 },
2224 Os.windows => {2320 Os.windows => {
2225 var utf16le_buf: [windows_util.PATH_MAX_WIDE]u16 = undefined;2321 var utf16le_buf: [windows_util.PATH_MAX_WIDE]u16 = undefined;
2226 const utf16le_slice = try selfExePathW(&utf16le_buf);2322 const utf16le_slice = try selfExePathW(&utf16le_buf);
...@@ -2811,14 +2907,15 @@ pub const Thread = struct {...@@ -2811,14 +2907,15 @@ pub const Thread = struct {
2811 pub const Data = if (use_pthreads)2907 pub const Data = if (use_pthreads)
2812 struct {2908 struct {
2813 handle: Thread.Handle,2909 handle: Thread.Handle,
2814 stack_addr: usize,2910 mmap_addr: usize,
2815 stack_len: usize,2911 mmap_len: usize,
2816 }2912 }
2817 else switch (builtin.os) {2913 else switch (builtin.os) {
2818 builtin.Os.linux => struct {2914 builtin.Os.linux => struct {
2819 handle: Thread.Handle,2915 handle: Thread.Handle,
2820 stack_addr: usize,2916 mmap_addr: usize,
2821 stack_len: usize,2917 mmap_len: usize,
2918 tls_end_addr: usize,
2822 },2919 },
2823 builtin.Os.windows => struct {2920 builtin.Os.windows => struct {
2824 handle: Thread.Handle,2921 handle: Thread.Handle,
...@@ -2858,7 +2955,7 @@ pub const Thread = struct {...@@ -2858,7 +2955,7 @@ pub const Thread = struct {
2858 posix.EDEADLK => unreachable,2955 posix.EDEADLK => unreachable,
2859 else => unreachable,2956 else => unreachable,
2860 }2957 }
2861 assert(posix.munmap(self.data.stack_addr, self.data.stack_len) == 0);2958 assert(posix.munmap(self.data.mmap_addr, self.data.mmap_len) == 0);
2862 } else switch (builtin.os) {2959 } else switch (builtin.os) {
2863 builtin.Os.linux => {2960 builtin.Os.linux => {
2864 while (true) {2961 while (true) {
...@@ -2872,7 +2969,7 @@ pub const Thread = struct {...@@ -2872,7 +2969,7 @@ pub const Thread = struct {
2872 else => unreachable,2969 else => unreachable,
2873 }2970 }
2874 }2971 }
2875 assert(posix.munmap(self.data.stack_addr, self.data.stack_len) == 0);2972 assert(posix.munmap(self.data.mmap_addr, self.data.mmap_len) == 0);
2876 },2973 },
2877 builtin.Os.windows => {2974 builtin.Os.windows => {
2878 assert(windows.WaitForSingleObject(self.data.handle, windows.INFINITE) == windows.WAIT_OBJECT_0);2975 assert(windows.WaitForSingleObject(self.data.handle, windows.INFINITE) == windows.WAIT_OBJECT_0);
...@@ -2911,11 +3008,15 @@ pub const SpawnThreadError = error{...@@ -2911,11 +3008,15 @@ pub const SpawnThreadError = error{
2911 Unexpected,3008 Unexpected,
2912};3009};
29133010
3011pub var linux_tls_phdr: ?*std.elf.Phdr = null;
3012pub var linux_tls_img_src: [*]const u8 = undefined; // defined if linux_tls_phdr is
3013
2914/// caller must call wait on the returned thread3014/// caller must call wait on the returned thread
2915/// fn startFn(@typeOf(context)) T3015/// fn startFn(@typeOf(context)) T
2916/// where T is u8, noreturn, void, or !void3016/// where T is u8, noreturn, void, or !void
2917/// caller must call wait on the returned thread3017/// caller must call wait on the returned thread
2918pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread {3018pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread {
3019 if (builtin.single_threaded) @compileError("cannot spawn thread when building in single-threaded mode");
2919 // TODO compile-time call graph analysis to determine stack upper bound3020 // TODO compile-time call graph analysis to determine stack upper bound
2920 // https://github.com/ziglang/zig/issues/1573021 // https://github.com/ziglang/zig/issues/157
2921 const default_stack_size = 8 * 1024 * 1024;3022 const default_stack_size = 8 * 1024 * 1024;
...@@ -2949,7 +3050,8 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread...@@ -2949,7 +3050,8 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
2949 const bytes_ptr = windows.HeapAlloc(heap_handle, 0, byte_count) orelse return SpawnThreadError.OutOfMemory;3050 const bytes_ptr = windows.HeapAlloc(heap_handle, 0, byte_count) orelse return SpawnThreadError.OutOfMemory;
2950 errdefer assert(windows.HeapFree(heap_handle, 0, bytes_ptr) != 0);3051 errdefer assert(windows.HeapFree(heap_handle, 0, bytes_ptr) != 0);
2951 const bytes = @ptrCast([*]u8, bytes_ptr)[0..byte_count];3052 const bytes = @ptrCast([*]u8, bytes_ptr)[0..byte_count];
2952 const outer_context = std.heap.FixedBufferAllocator.init(bytes).allocator.create(WinThread.OuterContext{3053 const outer_context = std.heap.FixedBufferAllocator.init(bytes).allocator.create(WinThread.OuterContext) catch unreachable;
3054 outer_context.* = WinThread.OuterContext{
2953 .thread = Thread{3055 .thread = Thread{
2954 .data = Thread.Data{3056 .data = Thread.Data{
2955 .heap_handle = heap_handle,3057 .heap_handle = heap_handle,
...@@ -2958,7 +3060,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread...@@ -2958,7 +3060,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
2958 },3060 },
2959 },3061 },
2960 .inner = context,3062 .inner = context,
2961 }) catch unreachable;3063 };
29623064
2963 const parameter = if (@sizeOf(Context) == 0) null else @ptrCast(*c_void, &outer_context.inner);3065 const parameter = if (@sizeOf(Context) == 0) null else @ptrCast(*c_void, &outer_context.inner);
2964 outer_context.thread.data.handle = windows.CreateThread(null, default_stack_size, WinThread.threadMain, parameter, 0, null) orelse {3066 outer_context.thread.data.handle = windows.CreateThread(null, default_stack_size, WinThread.threadMain, parameter, 0, null) orelse {
...@@ -2998,42 +3100,56 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread...@@ -2998,42 +3100,56 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
29983100
2999 const MAP_GROWSDOWN = if (builtin.os == builtin.Os.linux) linux.MAP_GROWSDOWN else 0;3101 const MAP_GROWSDOWN = if (builtin.os == builtin.Os.linux) linux.MAP_GROWSDOWN else 0;
30003102
3001 const mmap_len = default_stack_size;3103 var stack_end_offset: usize = undefined;
3002 const stack_addr = posix.mmap(null, mmap_len, posix.PROT_READ | posix.PROT_WRITE, posix.MAP_PRIVATE | posix.MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0);3104 var thread_start_offset: usize = undefined;
3003 if (stack_addr == posix.MAP_FAILED) return error.OutOfMemory;3105 var context_start_offset: usize = undefined;
3004 errdefer assert(posix.munmap(stack_addr, mmap_len) == 0);3106 var tls_start_offset: usize = undefined;
3107 const mmap_len = blk: {
3108 // First in memory will be the stack, which grows downwards.
3109 var l: usize = mem.alignForward(default_stack_size, os.page_size);
3110 stack_end_offset = l;
3111 // Above the stack, so that it can be in the same mmap call, put the Thread object.
3112 l = mem.alignForward(l, @alignOf(Thread));
3113 thread_start_offset = l;
3114 l += @sizeOf(Thread);
3115 // Next, the Context object.
3116 if (@sizeOf(Context) != 0) {
3117 l = mem.alignForward(l, @alignOf(Context));
3118 context_start_offset = l;
3119 l += @sizeOf(Context);
3120 }
3121 // Finally, the Thread Local Storage, if any.
3122 if (!Thread.use_pthreads) {
3123 if (linux_tls_phdr) |tls_phdr| {
3124 l = mem.alignForward(l, tls_phdr.p_align);
3125 tls_start_offset = l;
3126 l += tls_phdr.p_memsz;
3127 }
3128 }
3129 break :blk l;
3130 };
3131 const mmap_addr = posix.mmap(null, mmap_len, posix.PROT_READ | posix.PROT_WRITE, posix.MAP_PRIVATE | posix.MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0);
3132 if (mmap_addr == posix.MAP_FAILED) return error.OutOfMemory;
3133 errdefer assert(posix.munmap(mmap_addr, mmap_len) == 0);
3134
3135 const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, mmap_addr + thread_start_offset));
3136 thread_ptr.data.mmap_addr = mmap_addr;
3137 thread_ptr.data.mmap_len = mmap_len;
30053138
3006 var stack_end: usize = stack_addr + mmap_len;
3007 var arg: usize = undefined;3139 var arg: usize = undefined;
3008 if (@sizeOf(Context) != 0) {3140 if (@sizeOf(Context) != 0) {
3009 stack_end -= @sizeOf(Context);3141 arg = mmap_addr + context_start_offset;
3010 stack_end -= stack_end % @alignOf(Context);3142 const context_ptr = @alignCast(@alignOf(Context), @intToPtr(*Context, arg));
3011 assert(stack_end >= stack_addr);
3012 const context_ptr = @alignCast(@alignOf(Context), @intToPtr(*Context, stack_end));
3013 context_ptr.* = context;3143 context_ptr.* = context;
3014 arg = stack_end;
3015 }3144 }
30163145
3017 stack_end -= @sizeOf(Thread);3146 if (Thread.use_pthreads) {
3018 stack_end -= stack_end % @alignOf(Thread);
3019 assert(stack_end >= stack_addr);
3020 const thread_ptr = @alignCast(@alignOf(Thread), @intToPtr(*Thread, stack_end));
3021
3022 thread_ptr.data.stack_addr = stack_addr;
3023 thread_ptr.data.stack_len = mmap_len;
3024
3025 if (builtin.os == builtin.Os.windows) {
3026 // use windows API directly
3027 @compileError("TODO support spawnThread for Windows");
3028 } else if (Thread.use_pthreads) {
3029 // use pthreads3147 // use pthreads
3030 var attr: c.pthread_attr_t = undefined;3148 var attr: c.pthread_attr_t = undefined;
3031 if (c.pthread_attr_init(&attr) != 0) return SpawnThreadError.SystemResources;3149 if (c.pthread_attr_init(&attr) != 0) return SpawnThreadError.SystemResources;
3032 defer assert(c.pthread_attr_destroy(&attr) == 0);3150 defer assert(c.pthread_attr_destroy(&attr) == 0);
30333151
3034 // align to page3152 assert(c.pthread_attr_setstack(&attr, @intToPtr(*c_void, mmap_addr), stack_end_offset) == 0);
3035 stack_end -= stack_end % os.page_size;
3036 assert(c.pthread_attr_setstack(&attr, @intToPtr(*c_void, stack_addr), stack_end - stack_addr) == 0);
30373153
3038 const err = c.pthread_create(&thread_ptr.data.handle, &attr, MainFuncs.posixThreadMain, @intToPtr(*c_void, arg));3154 const err = c.pthread_create(&thread_ptr.data.handle, &attr, MainFuncs.posixThreadMain, @intToPtr(*c_void, arg));
3039 switch (err) {3155 switch (err) {
...@@ -3044,10 +3160,17 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread...@@ -3044,10 +3160,17 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
3044 else => return unexpectedErrorPosix(@intCast(usize, err)),3160 else => return unexpectedErrorPosix(@intCast(usize, err)),
3045 }3161 }
3046 } else if (builtin.os == builtin.Os.linux) {3162 } else if (builtin.os == builtin.Os.linux) {
3047 // use linux API directly. TODO use posix.CLONE_SETTLS and initialize thread local storage correctly3163 var flags: u32 = posix.CLONE_VM | posix.CLONE_FS | posix.CLONE_FILES | posix.CLONE_SIGHAND |
3048 const flags = posix.CLONE_VM | posix.CLONE_FS | posix.CLONE_FILES | posix.CLONE_SIGHAND | posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID | posix.CLONE_DETACHED;3164 posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID |
3049 const newtls: usize = 0;3165 posix.CLONE_DETACHED;
3050 const rc = posix.clone(MainFuncs.linuxThreadMain, stack_end, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle);3166 var newtls: usize = undefined;
3167 if (linux_tls_phdr) |tls_phdr| {
3168 @memcpy(@intToPtr([*]u8, mmap_addr + tls_start_offset), linux_tls_img_src, tls_phdr.p_filesz);
3169 thread_ptr.data.tls_end_addr = mmap_addr + mmap_len;
3170 newtls = @ptrToInt(&thread_ptr.data.tls_end_addr);
3171 flags |= posix.CLONE_SETTLS;
3172 }
3173 const rc = posix.clone(MainFuncs.linuxThreadMain, mmap_addr + stack_end_offset, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle);
3051 const err = posix.getErrno(rc);3174 const err = posix.getErrno(rc);
3052 switch (err) {3175 switch (err) {
3053 0 => return thread_ptr,3176 0 => return thread_ptr,
std/os/linux/test.zig+6-6
...@@ -1,19 +1,19 @@...@@ -1,19 +1,19 @@
1const std = @import("../../index.zig");1const std = @import("../../index.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const linux = std.os.linux;3const linux = std.os.linux;
4const assert = std.debug.assert;4const expect = std.testing.expect;
55
6test "getpid" {6test "getpid" {
7 assert(linux.getpid() != 0);7 expect(linux.getpid() != 0);
8}8}
99
10test "timer" {10test "timer" {
11 const epoll_fd = linux.epoll_create();11 const epoll_fd = linux.epoll_create();
12 var err = linux.getErrno(epoll_fd);12 var err = linux.getErrno(epoll_fd);
13 assert(err == 0);13 expect(err == 0);
1414
15 const timer_fd = linux.timerfd_create(linux.CLOCK_MONOTONIC, 0);15 const timer_fd = linux.timerfd_create(linux.CLOCK_MONOTONIC, 0);
16 assert(linux.getErrno(timer_fd) == 0);16 expect(linux.getErrno(timer_fd) == 0);
1717
18 const time_interval = linux.timespec{18 const time_interval = linux.timespec{
19 .tv_sec = 0,19 .tv_sec = 0,
...@@ -26,7 +26,7 @@ test "timer" {...@@ -26,7 +26,7 @@ test "timer" {
26 };26 };
2727
28 err = linux.timerfd_settime(@intCast(i32, timer_fd), 0, &new_time, null);28 err = linux.timerfd_settime(@intCast(i32, timer_fd), 0, &new_time, null);
29 assert(err == 0);29 expect(err == 0);
3030
31 var event = linux.epoll_event{31 var event = linux.epoll_event{
32 .events = linux.EPOLLIN | linux.EPOLLOUT | linux.EPOLLET,32 .events = linux.EPOLLIN | linux.EPOLLOUT | linux.EPOLLET,
...@@ -34,7 +34,7 @@ test "timer" {...@@ -34,7 +34,7 @@ test "timer" {
34 };34 };
3535
36 err = linux.epoll_ctl(@intCast(i32, epoll_fd), linux.EPOLL_CTL_ADD, @intCast(i32, timer_fd), &event);36 err = linux.epoll_ctl(@intCast(i32, epoll_fd), linux.EPOLL_CTL_ADD, @intCast(i32, timer_fd), &event);
37 assert(err == 0);37 expect(err == 0);
3838
39 const events_one: linux.epoll_event = undefined;39 const events_one: linux.epoll_event = undefined;
40 var events = []linux.epoll_event{events_one} ** 8;40 var events = []linux.epoll_event{events_one} ** 8;
std/os/path.zig+168-112
...@@ -3,6 +3,7 @@ const builtin = @import("builtin");...@@ -3,6 +3,7 @@ const builtin = @import("builtin");
3const Os = builtin.Os;3const Os = builtin.Os;
4const debug = std.debug;4const debug = std.debug;
5const assert = debug.assert;5const assert = debug.assert;
6const testing = std.testing;
6const mem = std.mem;7const mem = std.mem;
7const fmt = std.fmt;8const fmt = std.fmt;
8const Allocator = mem.Allocator;9const Allocator = mem.Allocator;
...@@ -33,40 +34,103 @@ pub fn isSep(byte: u8) bool {...@@ -33,40 +34,103 @@ pub fn isSep(byte: u8) bool {
33 }34 }
34}35}
3536
37/// This is different from mem.join in that the separator will not be repeated if
38/// it is found at the end or beginning of a pair of consecutive paths.
39fn joinSep(allocator: *Allocator, separator: u8, paths: []const []const u8) ![]u8 {
40 if (paths.len == 0) return (([*]u8)(undefined))[0..0];
41
42 const total_len = blk: {
43 var sum: usize = paths[0].len;
44 var i: usize = 1;
45 while (i < paths.len) : (i += 1) {
46 const prev_path = paths[i - 1];
47 const this_path = paths[i];
48 const prev_sep = (prev_path.len != 0 and prev_path[prev_path.len - 1] == separator);
49 const this_sep = (this_path.len != 0 and this_path[0] == separator);
50 sum += @boolToInt(!prev_sep and !this_sep);
51 sum += if (prev_sep and this_sep) this_path.len - 1 else this_path.len;
52 }
53 break :blk sum;
54 };
55
56 const buf = try allocator.alloc(u8, total_len);
57 errdefer allocator.free(buf);
58
59 mem.copy(u8, buf, paths[0]);
60 var buf_index: usize = paths[0].len;
61 var i: usize = 1;
62 while (i < paths.len) : (i += 1) {
63 const prev_path = paths[i - 1];
64 const this_path = paths[i];
65 const prev_sep = (prev_path.len != 0 and prev_path[prev_path.len - 1] == separator);
66 const this_sep = (this_path.len != 0 and this_path[0] == separator);
67 if (!prev_sep and !this_sep) {
68 buf[buf_index] = separator;
69 buf_index += 1;
70 }
71 const adjusted_path = if (prev_sep and this_sep) this_path[1..] else this_path;
72 mem.copy(u8, buf[buf_index..], adjusted_path);
73 buf_index += adjusted_path.len;
74 }
75
76 // No need for shrink since buf is exactly the correct size.
77 return buf;
78}
79
80pub const join = if (is_windows) joinWindows else joinPosix;
81
36/// Naively combines a series of paths with the native path seperator.82/// Naively combines a series of paths with the native path seperator.
37/// Allocates memory for the result, which must be freed by the caller.83/// Allocates memory for the result, which must be freed by the caller.
38pub fn join(allocator: *Allocator, paths: ...) ![]u8 {84pub fn joinWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
39 if (is_windows) {85 return joinSep(allocator, sep_windows, paths);
40 return joinWindows(allocator, paths);86}
41 } else {87
42 return joinPosix(allocator, paths);88/// Naively combines a series of paths with the native path seperator.
43 }89/// Allocates memory for the result, which must be freed by the caller.
90pub fn joinPosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
91 return joinSep(allocator, sep_posix, paths);
44}92}
4593
46pub fn joinWindows(allocator: *Allocator, paths: ...) ![]u8 {94fn testJoinWindows(paths: []const []const u8, expected: []const u8) void {
47 return mem.join(allocator, sep_windows, paths);95 var buf: [1024]u8 = undefined;
96 const a = &std.heap.FixedBufferAllocator.init(&buf).allocator;
97 const actual = joinWindows(a, paths) catch @panic("fail");
98 testing.expectEqualSlices(u8, expected, actual);
48}99}
49100
50pub fn joinPosix(allocator: *Allocator, paths: ...) ![]u8 {101fn testJoinPosix(paths: []const []const u8, expected: []const u8) void {
51 return mem.join(allocator, sep_posix, paths);102 var buf: [1024]u8 = undefined;
103 const a = &std.heap.FixedBufferAllocator.init(&buf).allocator;
104 const actual = joinPosix(a, paths) catch @panic("fail");
105 testing.expectEqualSlices(u8, expected, actual);
52}106}
53107
54test "os.path.join" {108test "os.path.join" {
55 assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\a\\b", "c"), "c:\\a\\b\\c"));109 testJoinWindows([][]const u8{ "c:\\a\\b", "c" }, "c:\\a\\b\\c");
56 assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\a\\b\\", "c"), "c:\\a\\b\\c"));110 testJoinWindows([][]const u8{ "c:\\a\\b", "c" }, "c:\\a\\b\\c");
111 testJoinWindows([][]const u8{ "c:\\a\\b\\", "c" }, "c:\\a\\b\\c");
57112
58 assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\", "a", "b\\", "c"), "c:\\a\\b\\c"));113 testJoinWindows([][]const u8{ "c:\\", "a", "b\\", "c" }, "c:\\a\\b\\c");
59 assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\a\\", "b\\", "c"), "c:\\a\\b\\c"));114 testJoinWindows([][]const u8{ "c:\\a\\", "b\\", "c" }, "c:\\a\\b\\c");
60115
61 assert(mem.eql(u8, try joinWindows(debug.global_allocator, "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std", "io.zig"), "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std\\io.zig"));116 testJoinWindows(
117 [][]const u8{ "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std", "io.zig" },
118 "c:\\home\\andy\\dev\\zig\\build\\lib\\zig\\std\\io.zig",
119 );
62120
63 assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/a/b", "c"), "/a/b/c"));121 testJoinPosix([][]const u8{ "/a/b", "c" }, "/a/b/c");
64 assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/a/b/", "c"), "/a/b/c"));122 testJoinPosix([][]const u8{ "/a/b/", "c" }, "/a/b/c");
65123
66 assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/", "a", "b/", "c"), "/a/b/c"));124 testJoinPosix([][]const u8{ "/", "a", "b/", "c" }, "/a/b/c");
67 assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/a/", "b/", "c"), "/a/b/c"));125 testJoinPosix([][]const u8{ "/a/", "b/", "c" }, "/a/b/c");
68126
69 assert(mem.eql(u8, try joinPosix(debug.global_allocator, "/home/andy/dev/zig/build/lib/zig/std", "io.zig"), "/home/andy/dev/zig/build/lib/zig/std/io.zig"));127 testJoinPosix(
128 [][]const u8{ "/home/andy/dev/zig/build/lib/zig/std", "io.zig" },
129 "/home/andy/dev/zig/build/lib/zig/std/io.zig",
130 );
131
132 testJoinPosix([][]const u8{ "a", "/c" }, "a/c");
133 testJoinPosix([][]const u8{ "a/", "/c" }, "a/c");
70}134}
71135
72pub fn isAbsolute(path: []const u8) bool {136pub fn isAbsolute(path: []const u8) bool {
...@@ -130,11 +194,11 @@ test "os.path.isAbsolutePosix" {...@@ -130,11 +194,11 @@ test "os.path.isAbsolutePosix" {
130}194}
131195
132fn testIsAbsoluteWindows(path: []const u8, expected_result: bool) void {196fn testIsAbsoluteWindows(path: []const u8, expected_result: bool) void {
133 assert(isAbsoluteWindows(path) == expected_result);197 testing.expectEqual(expected_result, isAbsoluteWindows(path));
134}198}
135199
136fn testIsAbsolutePosix(path: []const u8, expected_result: bool) void {200fn testIsAbsolutePosix(path: []const u8, expected_result: bool) void {
137 assert(isAbsolutePosix(path) == expected_result);201 testing.expectEqual(expected_result, isAbsolutePosix(path));
138}202}
139203
140pub const WindowsPath = struct {204pub const WindowsPath = struct {
...@@ -184,7 +248,7 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {...@@ -184,7 +248,7 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {
184 return relative_path;248 return relative_path;
185 }249 }
186250
187 var it = mem.split(path, []u8{this_sep});251 var it = mem.tokenize(path, []u8{this_sep});
188 _ = (it.next() orelse return relative_path);252 _ = (it.next() orelse return relative_path);
189 _ = (it.next() orelse return relative_path);253 _ = (it.next() orelse return relative_path);
190 return WindowsPath{254 return WindowsPath{
...@@ -202,7 +266,7 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {...@@ -202,7 +266,7 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {
202 return relative_path;266 return relative_path;
203 }267 }
204268
205 var it = mem.split(path, []u8{this_sep});269 var it = mem.tokenize(path, []u8{this_sep});
206 _ = (it.next() orelse return relative_path);270 _ = (it.next() orelse return relative_path);
207 _ = (it.next() orelse return relative_path);271 _ = (it.next() orelse return relative_path);
208 return WindowsPath{272 return WindowsPath{
...@@ -218,33 +282,33 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {...@@ -218,33 +282,33 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {
218test "os.path.windowsParsePath" {282test "os.path.windowsParsePath" {
219 {283 {
220 const parsed = windowsParsePath("//a/b");284 const parsed = windowsParsePath("//a/b");
221 assert(parsed.is_abs);285 testing.expect(parsed.is_abs);
222 assert(parsed.kind == WindowsPath.Kind.NetworkShare);286 testing.expect(parsed.kind == WindowsPath.Kind.NetworkShare);
223 assert(mem.eql(u8, parsed.disk_designator, "//a/b"));287 testing.expect(mem.eql(u8, parsed.disk_designator, "//a/b"));
224 }288 }
225 {289 {
226 const parsed = windowsParsePath("\\\\a\\b");290 const parsed = windowsParsePath("\\\\a\\b");
227 assert(parsed.is_abs);291 testing.expect(parsed.is_abs);
228 assert(parsed.kind == WindowsPath.Kind.NetworkShare);292 testing.expect(parsed.kind == WindowsPath.Kind.NetworkShare);
229 assert(mem.eql(u8, parsed.disk_designator, "\\\\a\\b"));293 testing.expect(mem.eql(u8, parsed.disk_designator, "\\\\a\\b"));
230 }294 }
231 {295 {
232 const parsed = windowsParsePath("\\\\a\\");296 const parsed = windowsParsePath("\\\\a\\");
233 assert(!parsed.is_abs);297 testing.expect(!parsed.is_abs);
234 assert(parsed.kind == WindowsPath.Kind.None);298 testing.expect(parsed.kind == WindowsPath.Kind.None);
235 assert(mem.eql(u8, parsed.disk_designator, ""));299 testing.expect(mem.eql(u8, parsed.disk_designator, ""));
236 }300 }
237 {301 {
238 const parsed = windowsParsePath("/usr/local");302 const parsed = windowsParsePath("/usr/local");
239 assert(parsed.is_abs);303 testing.expect(parsed.is_abs);
240 assert(parsed.kind == WindowsPath.Kind.None);304 testing.expect(parsed.kind == WindowsPath.Kind.None);
241 assert(mem.eql(u8, parsed.disk_designator, ""));305 testing.expect(mem.eql(u8, parsed.disk_designator, ""));
242 }306 }
243 {307 {
244 const parsed = windowsParsePath("c:../");308 const parsed = windowsParsePath("c:../");
245 assert(!parsed.is_abs);309 testing.expect(!parsed.is_abs);
246 assert(parsed.kind == WindowsPath.Kind.Drive);310 testing.expect(parsed.kind == WindowsPath.Kind.Drive);
247 assert(mem.eql(u8, parsed.disk_designator, "c:"));311 testing.expect(mem.eql(u8, parsed.disk_designator, "c:"));
248 }312 }
249}313}
250314
...@@ -264,8 +328,8 @@ fn networkShareServersEql(ns1: []const u8, ns2: []const u8) bool {...@@ -264,8 +328,8 @@ fn networkShareServersEql(ns1: []const u8, ns2: []const u8) bool {
264 const sep1 = ns1[0];328 const sep1 = ns1[0];
265 const sep2 = ns2[0];329 const sep2 = ns2[0];
266330
267 var it1 = mem.split(ns1, []u8{sep1});331 var it1 = mem.tokenize(ns1, []u8{sep1});
268 var it2 = mem.split(ns2, []u8{sep2});332 var it2 = mem.tokenize(ns2, []u8{sep2});
269333
270 // TODO ASCII is wrong, we actually need full unicode support to compare paths.334 // TODO ASCII is wrong, we actually need full unicode support to compare paths.
271 return asciiEqlIgnoreCase(it1.next().?, it2.next().?);335 return asciiEqlIgnoreCase(it1.next().?, it2.next().?);
...@@ -285,8 +349,8 @@ fn compareDiskDesignators(kind: WindowsPath.Kind, p1: []const u8, p2: []const u8...@@ -285,8 +349,8 @@ fn compareDiskDesignators(kind: WindowsPath.Kind, p1: []const u8, p2: []const u8
285 const sep1 = p1[0];349 const sep1 = p1[0];
286 const sep2 = p2[0];350 const sep2 = p2[0];
287351
288 var it1 = mem.split(p1, []u8{sep1});352 var it1 = mem.tokenize(p1, []u8{sep1});
289 var it2 = mem.split(p2, []u8{sep2});353 var it2 = mem.tokenize(p2, []u8{sep2});
290354
291 // TODO ASCII is wrong, we actually need full unicode support to compare paths.355 // TODO ASCII is wrong, we actually need full unicode support to compare paths.
292 return asciiEqlIgnoreCase(it1.next().?, it2.next().?) and asciiEqlIgnoreCase(it1.next().?, it2.next().?);356 return asciiEqlIgnoreCase(it1.next().?, it2.next().?) and asciiEqlIgnoreCase(it1.next().?, it2.next().?);
...@@ -312,18 +376,8 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool {...@@ -312,18 +376,8 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool {
312 return true;376 return true;
313}377}
314378
315/// Converts the command line arguments into a slice and calls `resolveSlice`.
316pub fn resolve(allocator: *Allocator, args: ...) ![]u8 {
317 var paths: [args.len][]const u8 = undefined;
318 comptime var arg_i = 0;
319 inline while (arg_i < args.len) : (arg_i += 1) {
320 paths[arg_i] = args[arg_i];
321 }
322 return resolveSlice(allocator, paths);
323}
324
325/// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`.379/// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`.
326pub fn resolveSlice(allocator: *Allocator, paths: []const []const u8) ![]u8 {380pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {
327 if (is_windows) {381 if (is_windows) {
328 return resolveWindows(allocator, paths);382 return resolveWindows(allocator, paths);
329 } else {383 } else {
...@@ -337,6 +391,8 @@ pub fn resolveSlice(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -337,6 +391,8 @@ pub fn resolveSlice(allocator: *Allocator, paths: []const []const u8) ![]u8 {
337/// If all paths are relative it uses the current working directory as a starting point.391/// If all paths are relative it uses the current working directory as a starting point.
338/// Each drive has its own current working directory.392/// Each drive has its own current working directory.
339/// Path separators are canonicalized to '\\' and drives are canonicalized to capital letters.393/// Path separators are canonicalized to '\\' and drives are canonicalized to capital letters.
394/// Note: all usage of this function should be audited due to the existence of symlinks.
395/// Without performing actual syscalls, resolving `..` could be incorrect.
340pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {396pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
341 if (paths.len == 0) {397 if (paths.len == 0) {
342 assert(is_windows); // resolveWindows called on non windows can't use getCwd398 assert(is_windows); // resolveWindows called on non windows can't use getCwd
...@@ -416,7 +472,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -416,7 +472,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
416 },472 },
417 WindowsPath.Kind.NetworkShare => {473 WindowsPath.Kind.NetworkShare => {
418 result = try allocator.alloc(u8, max_size);474 result = try allocator.alloc(u8, max_size);
419 var it = mem.split(paths[first_index], "/\\");475 var it = mem.tokenize(paths[first_index], "/\\");
420 const server_name = it.next().?;476 const server_name = it.next().?;
421 const other_name = it.next().?;477 const other_name = it.next().?;
422478
...@@ -483,7 +539,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -483,7 +539,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
483 if (!correct_disk_designator) {539 if (!correct_disk_designator) {
484 continue;540 continue;
485 }541 }
486 var it = mem.split(p[parsed.disk_designator.len..], "/\\");542 var it = mem.tokenize(p[parsed.disk_designator.len..], "/\\");
487 while (it.next()) |component| {543 while (it.next()) |component| {
488 if (mem.eql(u8, component, ".")) {544 if (mem.eql(u8, component, ".")) {
489 continue;545 continue;
...@@ -516,6 +572,8 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -516,6 +572,8 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
516/// It resolves "." and "..".572/// It resolves "." and "..".
517/// The result does not have a trailing path separator.573/// The result does not have a trailing path separator.
518/// If all paths are relative it uses the current working directory as a starting point.574/// If all paths are relative it uses the current working directory as a starting point.
575/// Note: all usage of this function should be audited due to the existence of symlinks.
576/// Without performing actual syscalls, resolving `..` could be incorrect.
519pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {577pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
520 if (paths.len == 0) {578 if (paths.len == 0) {
521 assert(!is_windows); // resolvePosix called on windows can't use getCwd579 assert(!is_windows); // resolvePosix called on windows can't use getCwd
...@@ -550,7 +608,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -550,7 +608,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
550 errdefer allocator.free(result);608 errdefer allocator.free(result);
551609
552 for (paths[first_index..]) |p, i| {610 for (paths[first_index..]) |p, i| {
553 var it = mem.split(p, "/");611 var it = mem.tokenize(p, "/");
554 while (it.next()) |component| {612 while (it.next()) |component| {
555 if (mem.eql(u8, component, ".")) {613 if (mem.eql(u8, component, ".")) {
556 continue;614 continue;
...@@ -585,10 +643,10 @@ test "os.path.resolve" {...@@ -585,10 +643,10 @@ test "os.path.resolve" {
585 if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) {643 if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) {
586 cwd[0] = asciiUpper(cwd[0]);644 cwd[0] = asciiUpper(cwd[0]);
587 }645 }
588 assert(mem.eql(u8, testResolveWindows([][]const u8{"."}), cwd));646 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{"."}), cwd));
589 } else {647 } else {
590 assert(mem.eql(u8, testResolvePosix([][]const u8{ "a/b/c/", "../../.." }), cwd));648 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "a/b/c/", "../../.." }), cwd));
591 assert(mem.eql(u8, testResolvePosix([][]const u8{"."}), cwd));649 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{"."}), cwd));
592 }650 }
593}651}
594652
...@@ -598,48 +656,54 @@ test "os.path.resolveWindows" {...@@ -598,48 +656,54 @@ test "os.path.resolveWindows" {
598 const parsed_cwd = windowsParsePath(cwd);656 const parsed_cwd = windowsParsePath(cwd);
599 {657 {
600 const result = testResolveWindows([][]const u8{ "/usr/local", "lib\\zig\\std\\array_list.zig" });658 const result = testResolveWindows([][]const u8{ "/usr/local", "lib\\zig\\std\\array_list.zig" });
601 const expected = try join(debug.global_allocator, parsed_cwd.disk_designator, "usr\\local\\lib\\zig\\std\\array_list.zig");659 const expected = try join(debug.global_allocator, [][]const u8{
660 parsed_cwd.disk_designator,
661 "usr\\local\\lib\\zig\\std\\array_list.zig",
662 });
602 if (parsed_cwd.kind == WindowsPath.Kind.Drive) {663 if (parsed_cwd.kind == WindowsPath.Kind.Drive) {
603 expected[0] = asciiUpper(parsed_cwd.disk_designator[0]);664 expected[0] = asciiUpper(parsed_cwd.disk_designator[0]);
604 }665 }
605 assert(mem.eql(u8, result, expected));666 testing.expect(mem.eql(u8, result, expected));
606 }667 }
607 {668 {
608 const result = testResolveWindows([][]const u8{ "usr/local", "lib\\zig" });669 const result = testResolveWindows([][]const u8{ "usr/local", "lib\\zig" });
609 const expected = try join(debug.global_allocator, cwd, "usr\\local\\lib\\zig");670 const expected = try join(debug.global_allocator, [][]const u8{
671 cwd,
672 "usr\\local\\lib\\zig",
673 });
610 if (parsed_cwd.kind == WindowsPath.Kind.Drive) {674 if (parsed_cwd.kind == WindowsPath.Kind.Drive) {
611 expected[0] = asciiUpper(parsed_cwd.disk_designator[0]);675 expected[0] = asciiUpper(parsed_cwd.disk_designator[0]);
612 }676 }
613 assert(mem.eql(u8, result, expected));677 testing.expect(mem.eql(u8, result, expected));
614 }678 }
615 }679 }
616680
617 assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:\\a\\b\\c", "/hi", "ok" }), "C:\\hi\\ok"));681 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:\\a\\b\\c", "/hi", "ok" }), "C:\\hi\\ok"));
618 assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/blah\\blah", "d:/games", "c:../a" }), "C:\\blah\\a"));682 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/blah\\blah", "d:/games", "c:../a" }), "C:\\blah\\a"));
619 assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/blah\\blah", "d:/games", "C:../a" }), "C:\\blah\\a"));683 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/blah\\blah", "d:/games", "C:../a" }), "C:\\blah\\a"));
620 assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/ignore", "d:\\a/b\\c/d", "\\e.exe" }), "D:\\e.exe"));684 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/ignore", "d:\\a/b\\c/d", "\\e.exe" }), "D:\\e.exe"));
621 assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/ignore", "c:/some/file" }), "C:\\some\\file"));685 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/ignore", "c:/some/file" }), "C:\\some\\file"));
622 assert(mem.eql(u8, testResolveWindows([][]const u8{ "d:/ignore", "d:some/dir//" }), "D:\\ignore\\some\\dir"));686 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "d:/ignore", "d:some/dir//" }), "D:\\ignore\\some\\dir"));
623 assert(mem.eql(u8, testResolveWindows([][]const u8{ "//server/share", "..", "relative\\" }), "\\\\server\\share\\relative"));687 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "//server/share", "..", "relative\\" }), "\\\\server\\share\\relative"));
624 assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//" }), "C:\\"));688 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//" }), "C:\\"));
625 assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//dir" }), "C:\\dir"));689 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//dir" }), "C:\\dir"));
626 assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//server/share" }), "\\\\server\\share\\"));690 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//server/share" }), "\\\\server\\share\\"));
627 assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//server//share" }), "\\\\server\\share\\"));691 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//server//share" }), "\\\\server\\share\\"));
628 assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "///some//dir" }), "C:\\some\\dir"));692 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "///some//dir" }), "C:\\some\\dir"));
629 assert(mem.eql(u8, testResolveWindows([][]const u8{ "C:\\foo\\tmp.3\\", "..\\tmp.3\\cycles\\root.js" }), "C:\\foo\\tmp.3\\cycles\\root.js"));693 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "C:\\foo\\tmp.3\\", "..\\tmp.3\\cycles\\root.js" }), "C:\\foo\\tmp.3\\cycles\\root.js"));
630}694}
631695
632test "os.path.resolvePosix" {696test "os.path.resolvePosix" {
633 assert(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b", "c" }), "/a/b/c"));697 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b", "c" }), "/a/b/c"));
634 assert(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b", "c", "//d", "e///" }), "/d/e"));698 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b", "c", "//d", "e///" }), "/d/e"));
635 assert(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b/c", "..", "../" }), "/a"));699 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b/c", "..", "../" }), "/a"));
636 assert(mem.eql(u8, testResolvePosix([][]const u8{ "/", "..", ".." }), "/"));700 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/", "..", ".." }), "/"));
637 assert(mem.eql(u8, testResolvePosix([][]const u8{"/a/b/c/"}), "/a/b/c"));701 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{"/a/b/c/"}), "/a/b/c"));
638702
639 assert(mem.eql(u8, testResolvePosix([][]const u8{ "/var/lib", "../", "file/" }), "/var/file"));703 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/var/lib", "../", "file/" }), "/var/file"));
640 assert(mem.eql(u8, testResolvePosix([][]const u8{ "/var/lib", "/../", "file/" }), "/file"));704 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/var/lib", "/../", "file/" }), "/file"));
641 assert(mem.eql(u8, testResolvePosix([][]const u8{ "/some/dir", ".", "/absolute/" }), "/absolute"));705 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/some/dir", ".", "/absolute/" }), "/absolute"));
642 assert(mem.eql(u8, testResolvePosix([][]const u8{ "/foo/tmp.3/", "../tmp.3/cycles/root.js" }), "/foo/tmp.3/cycles/root.js"));706 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/foo/tmp.3/", "../tmp.3/cycles/root.js" }), "/foo/tmp.3/cycles/root.js"));
643}707}
644708
645fn testResolveWindows(paths: []const []const u8) []u8 {709fn testResolveWindows(paths: []const []const u8) []u8 {
...@@ -770,17 +834,17 @@ test "os.path.dirnameWindows" {...@@ -770,17 +834,17 @@ test "os.path.dirnameWindows" {
770834
771fn testDirnamePosix(input: []const u8, expected_output: ?[]const u8) void {835fn testDirnamePosix(input: []const u8, expected_output: ?[]const u8) void {
772 if (dirnamePosix(input)) |output| {836 if (dirnamePosix(input)) |output| {
773 assert(mem.eql(u8, output, expected_output.?));837 testing.expect(mem.eql(u8, output, expected_output.?));
774 } else {838 } else {
775 assert(expected_output == null);839 testing.expect(expected_output == null);
776 }840 }
777}841}
778842
779fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) void {843fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) void {
780 if (dirnameWindows(input)) |output| {844 if (dirnameWindows(input)) |output| {
781 assert(mem.eql(u8, output, expected_output.?));845 testing.expect(mem.eql(u8, output, expected_output.?));
782 } else {846 } else {
783 assert(expected_output == null);847 testing.expect(expected_output == null);
784 }848 }
785}849}
786850
...@@ -885,15 +949,15 @@ test "os.path.basename" {...@@ -885,15 +949,15 @@ test "os.path.basename" {
885}949}
886950
887fn testBasename(input: []const u8, expected_output: []const u8) void {951fn testBasename(input: []const u8, expected_output: []const u8) void {
888 assert(mem.eql(u8, basename(input), expected_output));952 testing.expectEqualSlices(u8, expected_output, basename(input));
889}953}
890954
891fn testBasenamePosix(input: []const u8, expected_output: []const u8) void {955fn testBasenamePosix(input: []const u8, expected_output: []const u8) void {
892 assert(mem.eql(u8, basenamePosix(input), expected_output));956 testing.expectEqualSlices(u8, expected_output, basenamePosix(input));
893}957}
894958
895fn testBasenameWindows(input: []const u8, expected_output: []const u8) void {959fn testBasenameWindows(input: []const u8, expected_output: []const u8) void {
896 assert(mem.eql(u8, basenameWindows(input), expected_output));960 testing.expectEqualSlices(u8, expected_output, basenameWindows(input));
897}961}
898962
899/// Returns the relative path from `from` to `to`. If `from` and `to` each963/// Returns the relative path from `from` to `to`. If `from` and `to` each
...@@ -937,8 +1001,8 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8)...@@ -937,8 +1001,8 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8)
937 return resolved_to;1001 return resolved_to;
938 }1002 }
9391003
940 var from_it = mem.split(resolved_from, "/\\");1004 var from_it = mem.tokenize(resolved_from, "/\\");
941 var to_it = mem.split(resolved_to, "/\\");1005 var to_it = mem.tokenize(resolved_to, "/\\");
942 while (true) {1006 while (true) {
943 const from_component = from_it.next() orelse return mem.dupe(allocator, u8, to_it.rest());1007 const from_component = from_it.next() orelse return mem.dupe(allocator, u8, to_it.rest());
944 const to_rest = to_it.rest();1008 const to_rest = to_it.rest();
...@@ -967,7 +1031,7 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8)...@@ -967,7 +1031,7 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8)
967 // shave off the trailing slash1031 // shave off the trailing slash
968 result_index -= 1;1032 result_index -= 1;
9691033
970 var rest_it = mem.split(to_rest, "/\\");1034 var rest_it = mem.tokenize(to_rest, "/\\");
971 while (rest_it.next()) |to_component| {1035 while (rest_it.next()) |to_component| {
972 result[result_index] = '\\';1036 result[result_index] = '\\';
973 result_index += 1;1037 result_index += 1;
...@@ -988,8 +1052,8 @@ pub fn relativePosix(allocator: *Allocator, from: []const u8, to: []const u8) ![...@@ -988,8 +1052,8 @@ pub fn relativePosix(allocator: *Allocator, from: []const u8, to: []const u8) ![
988 const resolved_to = try resolvePosix(allocator, [][]const u8{to});1052 const resolved_to = try resolvePosix(allocator, [][]const u8{to});
989 defer allocator.free(resolved_to);1053 defer allocator.free(resolved_to);
9901054
991 var from_it = mem.split(resolved_from, "/");1055 var from_it = mem.tokenize(resolved_from, "/");
992 var to_it = mem.split(resolved_to, "/");1056 var to_it = mem.tokenize(resolved_to, "/");
993 while (true) {1057 while (true) {
994 const from_component = from_it.next() orelse return mem.dupe(allocator, u8, to_it.rest());1058 const from_component = from_it.next() orelse return mem.dupe(allocator, u8, to_it.rest());
995 const to_rest = to_it.rest();1059 const to_rest = to_it.rest();
...@@ -1068,12 +1132,12 @@ test "os.path.relative" {...@@ -1068,12 +1132,12 @@ test "os.path.relative" {
10681132
1069fn testRelativePosix(from: []const u8, to: []const u8, expected_output: []const u8) void {1133fn testRelativePosix(from: []const u8, to: []const u8, expected_output: []const u8) void {
1070 const result = relativePosix(debug.global_allocator, from, to) catch unreachable;1134 const result = relativePosix(debug.global_allocator, from, to) catch unreachable;
1071 assert(mem.eql(u8, result, expected_output));1135 testing.expectEqualSlices(u8, expected_output, result);
1072}1136}
10731137
1074fn testRelativeWindows(from: []const u8, to: []const u8, expected_output: []const u8) void {1138fn testRelativeWindows(from: []const u8, to: []const u8, expected_output: []const u8) void {
1075 const result = relativeWindows(debug.global_allocator, from, to) catch unreachable;1139 const result = relativeWindows(debug.global_allocator, from, to) catch unreachable;
1076 assert(mem.eql(u8, result, expected_output));1140 testing.expectEqualSlices(u8, expected_output, result);
1077}1141}
10781142
1079pub const RealError = error{1143pub const RealError = error{
...@@ -1093,6 +1157,7 @@ pub const RealError = error{...@@ -1093,6 +1157,7 @@ pub const RealError = error{
1093 NoSpaceLeft,1157 NoSpaceLeft,
1094 FileSystem,1158 FileSystem,
1095 BadPathName,1159 BadPathName,
1160 DeviceBusy,
10961161
1097 /// On Windows, file paths must be valid Unicode.1162 /// On Windows, file paths must be valid Unicode.
1098 InvalidUtf8,1163 InvalidUtf8,
...@@ -1161,7 +1226,7 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro...@@ -1161,7 +1226,7 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro
1161 const pathname_w = try windows_util.cStrToPrefixedFileW(pathname);1226 const pathname_w = try windows_util.cStrToPrefixedFileW(pathname);
1162 return realW(out_buffer, pathname_w);1227 return realW(out_buffer, pathname_w);
1163 },1228 },
1164 Os.macosx, Os.ios => {1229 Os.freebsd, Os.macosx, Os.ios => {
1165 // TODO instead of calling the libc function here, port the implementation to Zig1230 // TODO instead of calling the libc function here, port the implementation to Zig
1166 const err = posix.getErrno(posix.realpath(pathname, out_buffer));1231 const err = posix.getErrno(posix.realpath(pathname, out_buffer));
1167 switch (err) {1232 switch (err) {
...@@ -1188,15 +1253,6 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro...@@ -1188,15 +1253,6 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro
11881253
1189 return os.readLinkC(out_buffer, proc_path.ptr);1254 return os.readLinkC(out_buffer, proc_path.ptr);
1190 },1255 },
1191 Os.freebsd => { // XXX requires fdescfs
1192 const fd = try os.posixOpenC(pathname, posix.O_PATH | posix.O_NONBLOCK | posix.O_CLOEXEC, 0);
1193 defer os.close(fd);
1194
1195 var buf: ["/dev/fd/-2147483648\x00".len]u8 = undefined;
1196 const proc_path = fmt.bufPrint(buf[0..], "/dev/fd/{}\x00", fd) catch unreachable;
1197
1198 return os.readLinkC(out_buffer, proc_path.ptr);
1199 },
1200 else => @compileError("TODO implement os.path.real for " ++ @tagName(builtin.os)),1256 else => @compileError("TODO implement os.path.real for " ++ @tagName(builtin.os)),
1201 }1257 }
1202}1258}
...@@ -1228,5 +1284,5 @@ pub fn realAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 {...@@ -1228,5 +1284,5 @@ pub fn realAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 {
1228test "os.path.real" {1284test "os.path.real" {
1229 // at least call it so it gets compiled1285 // at least call it so it gets compiled
1230 var buf: [os.MAX_PATH_BYTES]u8 = undefined;1286 var buf: [os.MAX_PATH_BYTES]u8 = undefined;
1231 std.debug.assertError(real(&buf, "definitely_bogus_does_not_exist1234"), error.FileNotFound);1287 testing.expectError(error.FileNotFound, real(&buf, "definitely_bogus_does_not_exist1234"));
1232}1288}
std/os/test.zig+28-8
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const std = @import("../index.zig");1const std = @import("../index.zig");
2const os = std.os;2const os = std.os;
3const assert = std.debug.assert;3const expect = std.testing.expect;
4const io = std.io;4const io = std.io;
5const mem = std.mem;5const mem = std.mem;
66
...@@ -18,7 +18,7 @@ test "makePath, put some files in it, deleteTree" {...@@ -18,7 +18,7 @@ test "makePath, put some files in it, deleteTree" {
18 if (os.Dir.open(a, "os_test_tmp")) |dir| {18 if (os.Dir.open(a, "os_test_tmp")) |dir| {
19 @panic("expected error");19 @panic("expected error");
20 } else |err| {20 } else |err| {
21 assert(err == error.FileNotFound);21 expect(err == error.FileNotFound);
22 }22 }
23}23}
2424
...@@ -27,7 +27,7 @@ test "access file" {...@@ -27,7 +27,7 @@ test "access file" {
27 if (os.File.access("os_test_tmp" ++ os.path.sep_str ++ "file.txt")) |ok| {27 if (os.File.access("os_test_tmp" ++ os.path.sep_str ++ "file.txt")) |ok| {
28 @panic("expected error");28 @panic("expected error");
29 } else |err| {29 } else |err| {
30 assert(err == error.FileNotFound);30 expect(err == error.FileNotFound);
31 }31 }
3232
33 try io.writeFile("os_test_tmp" ++ os.path.sep_str ++ "file.txt", "");33 try io.writeFile("os_test_tmp" ++ os.path.sep_str ++ "file.txt", "");
...@@ -40,19 +40,23 @@ fn testThreadIdFn(thread_id: *os.Thread.Id) void {...@@ -40,19 +40,23 @@ fn testThreadIdFn(thread_id: *os.Thread.Id) void {
40}40}
4141
42test "std.os.Thread.getCurrentId" {42test "std.os.Thread.getCurrentId" {
43 if (builtin.single_threaded) return error.SkipZigTest;
44
43 var thread_current_id: os.Thread.Id = undefined;45 var thread_current_id: os.Thread.Id = undefined;
44 const thread = try os.spawnThread(&thread_current_id, testThreadIdFn);46 const thread = try os.spawnThread(&thread_current_id, testThreadIdFn);
45 const thread_id = thread.handle();47 const thread_id = thread.handle();
46 thread.wait();48 thread.wait();
47 switch (builtin.os) {49 switch (builtin.os) {
48 builtin.Os.windows => assert(os.Thread.getCurrentId() != thread_current_id),50 builtin.Os.windows => expect(os.Thread.getCurrentId() != thread_current_id),
49 else => {51 else => {
50 assert(thread_current_id == thread_id);52 expect(thread_current_id == thread_id);
51 },53 },
52 }54 }
53}55}
5456
55test "spawn threads" {57test "spawn threads" {
58 if (builtin.single_threaded) return error.SkipZigTest;
59
56 var shared_ctx: i32 = 1;60 var shared_ctx: i32 = 1;
5761
58 const thread1 = try std.os.spawnThread({}, start1);62 const thread1 = try std.os.spawnThread({}, start1);
...@@ -65,7 +69,7 @@ test "spawn threads" {...@@ -65,7 +69,7 @@ test "spawn threads" {
65 thread3.wait();69 thread3.wait();
66 thread4.wait();70 thread4.wait();
6771
68 assert(shared_ctx == 4);72 expect(shared_ctx == 4);
69}73}
7074
71fn start1(ctx: void) u8 {75fn start1(ctx: void) u8 {
...@@ -79,7 +83,7 @@ fn start2(ctx: *i32) u8 {...@@ -79,7 +83,7 @@ fn start2(ctx: *i32) u8 {
7983
80test "cpu count" {84test "cpu count" {
81 const cpu_count = try std.os.cpuCount(a);85 const cpu_count = try std.os.cpuCount(a);
82 assert(cpu_count >= 1);86 expect(cpu_count >= 1);
83}87}
8488
85test "AtomicFile" {89test "AtomicFile" {
...@@ -97,7 +101,23 @@ test "AtomicFile" {...@@ -97,7 +101,23 @@ test "AtomicFile" {
97 try af.finish();101 try af.finish();
98 }102 }
99 const content = try io.readFileAlloc(allocator, test_out_file);103 const content = try io.readFileAlloc(allocator, test_out_file);
100 assert(mem.eql(u8, content, test_content));104 expect(mem.eql(u8, content, test_content));
101105
102 try os.deleteFile(test_out_file);106 try os.deleteFile(test_out_file);
103}107}
108
109test "thread local storage" {
110 if (builtin.single_threaded) return error.SkipZigTest;
111 const thread1 = try std.os.spawnThread({}, testTls);
112 const thread2 = try std.os.spawnThread({}, testTls);
113 testTls({});
114 thread1.wait();
115 thread2.wait();
116}
117
118threadlocal var x: i32 = 1234;
119fn testTls(context: void) void {
120 if (x != 1234) @panic("bad start value");
121 x += 1;
122 if (x != 1235) @panic("bad end value");
123}
std/os/time.zig+13-14
...@@ -2,6 +2,7 @@ const std = @import("../index.zig");...@@ -2,6 +2,7 @@ const std = @import("../index.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const Os = builtin.Os;3const Os = builtin.Os;
4const debug = std.debug;4const debug = std.debug;
5const testing = std.testing;
56
6const windows = std.os.windows;7const windows = std.os.windows;
7const linux = std.os.linux;8const linux = std.os.linux;
...@@ -13,7 +14,7 @@ pub const epoch = @import("epoch.zig");...@@ -13,7 +14,7 @@ pub const epoch = @import("epoch.zig");
13/// Sleep for the specified duration14/// Sleep for the specified duration
14pub fn sleep(nanoseconds: u64) void {15pub fn sleep(nanoseconds: u64) void {
15 switch (builtin.os) {16 switch (builtin.os) {
16 Os.linux, Os.macosx, Os.ios => {17 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
17 const s = nanoseconds / ns_per_s;18 const s = nanoseconds / ns_per_s;
18 const ns = nanoseconds % ns_per_s;19 const ns = nanoseconds % ns_per_s;
19 posixSleep(@intCast(u63, s), @intCast(u63, ns));20 posixSleep(@intCast(u63, s), @intCast(u63, ns));
...@@ -61,7 +62,7 @@ pub fn timestamp() u64 {...@@ -61,7 +62,7 @@ pub fn timestamp() u64 {
61/// Get the posix timestamp, UTC, in milliseconds62/// Get the posix timestamp, UTC, in milliseconds
62pub const milliTimestamp = switch (builtin.os) {63pub const milliTimestamp = switch (builtin.os) {
63 Os.windows => milliTimestampWindows,64 Os.windows => milliTimestampWindows,
64 Os.linux => milliTimestampPosix,65 Os.linux, Os.freebsd => milliTimestampPosix,
65 Os.macosx, Os.ios => milliTimestampDarwin,66 Os.macosx, Os.ios => milliTimestampDarwin,
66 else => @compileError("Unsupported OS"),67 else => @compileError("Unsupported OS"),
67};68};
...@@ -79,14 +80,12 @@ fn milliTimestampWindows() u64 {...@@ -79,14 +80,12 @@ fn milliTimestampWindows() u64 {
79}80}
8081
81fn milliTimestampDarwin() u64 {82fn milliTimestampDarwin() u64 {
82 //Sources suggest MacOS 10.12 has support for
83 // posix clock_gettime.
84 var tv: darwin.timeval = undefined;83 var tv: darwin.timeval = undefined;
85 var err = darwin.gettimeofday(&tv, null);84 var err = darwin.gettimeofday(&tv, null);
86 debug.assert(err == 0);85 debug.assert(err == 0);
87 const sec_ms = @intCast(u64, tv.tv_sec) * ms_per_s;86 const sec_ms = tv.tv_sec * ms_per_s;
88 const usec_ms = @divFloor(@intCast(u64, tv.tv_usec), us_per_s / ms_per_s);87 const usec_ms = @divFloor(tv.tv_usec, us_per_s / ms_per_s);
89 return u64(sec_ms) + u64(usec_ms);88 return @intCast(u64, sec_ms + usec_ms);
90}89}
9190
92fn milliTimestampPosix() u64 {91fn milliTimestampPosix() u64 {
...@@ -179,7 +178,7 @@ pub const Timer = struct {...@@ -179,7 +178,7 @@ pub const Timer = struct {
179 debug.assert(err != windows.FALSE);178 debug.assert(err != windows.FALSE);
180 self.start_time = @intCast(u64, start_time);179 self.start_time = @intCast(u64, start_time);
181 },180 },
182 Os.linux => {181 Os.linux, Os.freebsd => {
183 //On Linux, seccomp can do arbitrary things to our ability to call182 //On Linux, seccomp can do arbitrary things to our ability to call
184 // syscalls, including return any errno value it wants and183 // syscalls, including return any errno value it wants and
185 // inconsistently throwing errors. Since we can't account for184 // inconsistently throwing errors. Since we can't account for
...@@ -215,7 +214,7 @@ pub const Timer = struct {...@@ -215,7 +214,7 @@ pub const Timer = struct {
215 var clock = clockNative() - self.start_time;214 var clock = clockNative() - self.start_time;
216 return switch (builtin.os) {215 return switch (builtin.os) {
217 Os.windows => @divFloor(clock * ns_per_s, self.frequency),216 Os.windows => @divFloor(clock * ns_per_s, self.frequency),
218 Os.linux => clock,217 Os.linux, Os.freebsd => clock,
219 Os.macosx, Os.ios => @divFloor(clock * self.frequency.numer, self.frequency.denom),218 Os.macosx, Os.ios => @divFloor(clock * self.frequency.numer, self.frequency.denom),
220 else => @compileError("Unsupported OS"),219 else => @compileError("Unsupported OS"),
221 };220 };
...@@ -236,7 +235,7 @@ pub const Timer = struct {...@@ -236,7 +235,7 @@ pub const Timer = struct {
236235
237 const clockNative = switch (builtin.os) {236 const clockNative = switch (builtin.os) {
238 Os.windows => clockWindows,237 Os.windows => clockWindows,
239 Os.linux => clockLinux,238 Os.linux, Os.freebsd => clockLinux,
240 Os.macosx, Os.ios => clockDarwin,239 Os.macosx, Os.ios => clockDarwin,
241 else => @compileError("Unsupported OS"),240 else => @compileError("Unsupported OS"),
242 };241 };
...@@ -272,7 +271,7 @@ test "os.time.timestamp" {...@@ -272,7 +271,7 @@ test "os.time.timestamp" {
272 sleep(ns_per_ms);271 sleep(ns_per_ms);
273 const time_1 = milliTimestamp();272 const time_1 = milliTimestamp();
274 const interval = time_1 - time_0;273 const interval = time_1 - time_0;
275 debug.assert(interval > 0 and interval < margin);274 testing.expect(interval > 0 and interval < margin);
276}275}
277276
278test "os.time.Timer" {277test "os.time.Timer" {
...@@ -282,11 +281,11 @@ test "os.time.Timer" {...@@ -282,11 +281,11 @@ test "os.time.Timer" {
282 var timer = try Timer.start();281 var timer = try Timer.start();
283 sleep(10 * ns_per_ms);282 sleep(10 * ns_per_ms);
284 const time_0 = timer.read();283 const time_0 = timer.read();
285 debug.assert(time_0 > 0 and time_0 < margin);284 testing.expect(time_0 > 0 and time_0 < margin);
286285
287 const time_1 = timer.lap();286 const time_1 = timer.lap();
288 debug.assert(time_1 >= time_0);287 testing.expect(time_1 >= time_0);
289288
290 timer.reset();289 timer.reset();
291 debug.assert(timer.read() < time_1);290 testing.expect(timer.read() < time_1);
292}291}
std/os/uefi.zig created+2
...@@ -0,0 +1,2 @@
1// TODO this is where the extern declarations go. For example, see
2// inc/efilib.h in gnu-efi-code
std/os/windows/index.zig+18
...@@ -49,6 +49,10 @@ pub const UNICODE = false;...@@ -49,6 +49,10 @@ pub const UNICODE = false;
49pub const WCHAR = u16;49pub const WCHAR = u16;
50pub const WORD = u16;50pub const WORD = u16;
51pub const LARGE_INTEGER = i64;51pub const LARGE_INTEGER = i64;
52pub const ULONG = u32;
53pub const LONG = i32;
54pub const ULONGLONG = u64;
55pub const LONGLONG = i64;
5256
53pub const TRUE = 1;57pub const TRUE = 1;
54pub const FALSE = 0;58pub const FALSE = 0;
...@@ -379,3 +383,17 @@ pub const COORD = extern struct {...@@ -379,3 +383,17 @@ pub const COORD = extern struct {
379};383};
380384
381pub const CREATE_UNICODE_ENVIRONMENT = 1024;385pub const CREATE_UNICODE_ENVIRONMENT = 1024;
386
387pub const TLS_OUT_OF_INDEXES = 4294967295;
388pub const IMAGE_TLS_DIRECTORY = extern struct {
389 StartAddressOfRawData: usize,
390 EndAddressOfRawData: usize,
391 AddressOfIndex: usize,
392 AddressOfCallBacks: usize,
393 SizeOfZeroFill: u32,
394 Characteristics: u32,
395};
396pub const IMAGE_TLS_DIRECTORY64 = IMAGE_TLS_DIRECTORY;
397pub const IMAGE_TLS_DIRECTORY32 = IMAGE_TLS_DIRECTORY;
398
399pub const PIMAGE_TLS_CALLBACK = ?extern fn(PVOID, DWORD, PVOID) void;
std/os/windows/kernel32.zig+54-3
...@@ -50,7 +50,7 @@ pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFi...@@ -50,7 +50,7 @@ pub extern "kernel32" stdcallcc fn FindFirstFileW(lpFileName: [*]const u16, lpFi
50pub extern "kernel32" stdcallcc fn FindClose(hFindFile: HANDLE) BOOL;50pub extern "kernel32" stdcallcc fn FindClose(hFindFile: HANDLE) BOOL;
51pub extern "kernel32" stdcallcc fn FindNextFileW(hFindFile: HANDLE, lpFindFileData: *WIN32_FIND_DATAW) BOOL;51pub extern "kernel32" stdcallcc fn FindNextFileW(hFindFile: HANDLE, lpFindFileData: *WIN32_FIND_DATAW) BOOL;
5252
53pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsA(penv: [*]u8) BOOL;53pub extern "kernel32" stdcallcc fn FreeEnvironmentStringsW(penv: [*]u16) BOOL;
5454
55pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR;55pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR;
5656
...@@ -63,9 +63,9 @@ pub extern "kernel32" stdcallcc fn GetCurrentDirectoryW(nBufferLength: DWORD, lp...@@ -63,9 +63,9 @@ pub extern "kernel32" stdcallcc fn GetCurrentDirectoryW(nBufferLength: DWORD, lp
63pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE;63pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE;
64pub extern "kernel32" stdcallcc fn GetCurrentThreadId() DWORD;64pub extern "kernel32" stdcallcc fn GetCurrentThreadId() DWORD;
6565
66pub extern "kernel32" stdcallcc fn GetEnvironmentStringsA() ?[*]u8;66pub extern "kernel32" stdcallcc fn GetEnvironmentStringsW() ?[*]u16;
6767
68pub extern "kernel32" stdcallcc fn GetEnvironmentVariableA(lpName: LPCSTR, lpBuffer: LPSTR, nSize: DWORD) DWORD;68pub extern "kernel32" stdcallcc fn GetEnvironmentVariableW(lpName: LPWSTR, lpBuffer: LPWSTR, nSize: DWORD) DWORD;
6969
70pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: *DWORD) BOOL;70pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: *DWORD) BOOL;
7171
...@@ -164,6 +164,10 @@ pub extern "kernel32" stdcallcc fn Sleep(dwMilliseconds: DWORD) void;...@@ -164,6 +164,10 @@ pub extern "kernel32" stdcallcc fn Sleep(dwMilliseconds: DWORD) void;
164164
165pub extern "kernel32" stdcallcc fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) BOOL;165pub extern "kernel32" stdcallcc fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) BOOL;
166166
167pub extern "kernel32" stdcallcc fn TlsAlloc() DWORD;
168
169pub extern "kernel32" stdcallcc fn TlsFree(dwTlsIndex: DWORD) BOOL;
170
167pub extern "kernel32" stdcallcc fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) DWORD;171pub extern "kernel32" stdcallcc fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) DWORD;
168172
169pub extern "kernel32" stdcallcc fn WriteFile(173pub extern "kernel32" stdcallcc fn WriteFile(
...@@ -220,3 +224,50 @@ pub const FOREGROUND_BLUE = 1;...@@ -220,3 +224,50 @@ pub const FOREGROUND_BLUE = 1;
220pub const FOREGROUND_GREEN = 2;224pub const FOREGROUND_GREEN = 2;
221pub const FOREGROUND_RED = 4;225pub const FOREGROUND_RED = 4;
222pub const FOREGROUND_INTENSITY = 8;226pub const FOREGROUND_INTENSITY = 8;
227
228pub extern "kernel32" stdcallcc fn InitializeCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
229pub extern "kernel32" stdcallcc fn EnterCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
230pub extern "kernel32" stdcallcc fn LeaveCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
231pub extern "kernel32" stdcallcc fn DeleteCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
232
233pub const LIST_ENTRY = extern struct {
234 Flink: *LIST_ENTRY,
235 Blink: *LIST_ENTRY,
236};
237
238pub const RTL_CRITICAL_SECTION_DEBUG = extern struct {
239 Type: WORD,
240 CreatorBackTraceIndex: WORD,
241 CriticalSection: *RTL_CRITICAL_SECTION,
242 ProcessLocksList: LIST_ENTRY,
243 EntryCount: DWORD,
244 ContentionCount: DWORD,
245 Flags: DWORD,
246 CreatorBackTraceIndexHigh: WORD,
247 SpareWORD: WORD,
248};
249
250pub const RTL_CRITICAL_SECTION = extern struct {
251 DebugInfo: *RTL_CRITICAL_SECTION_DEBUG,
252 LockCount: LONG,
253 RecursionCount: LONG,
254 OwningThread: HANDLE,
255 LockSemaphore: HANDLE,
256 SpinCount: ULONG_PTR,
257};
258
259pub const CRITICAL_SECTION = RTL_CRITICAL_SECTION;
260pub const INIT_ONCE = RTL_RUN_ONCE;
261pub const INIT_ONCE_STATIC_INIT = RTL_RUN_ONCE_INIT;
262
263pub extern "kernel32" stdcallcc fn InitOnceExecuteOnce(InitOnce: *INIT_ONCE, InitFn: INIT_ONCE_FN, Parameter: ?*c_void, Context: ?*c_void) BOOL;
264
265pub const INIT_ONCE_FN = extern fn(InitOnce: *INIT_ONCE, Parameter: ?*c_void, Context: ?*c_void) BOOL;
266
267pub const RTL_RUN_ONCE = extern struct {
268 Ptr: ?*c_void,
269};
270
271pub const RTL_RUN_ONCE_INIT = RTL_RUN_ONCE {
272 .Ptr = null,
273};
std/os/windows/tls.zig created+36
...@@ -0,0 +1,36 @@
1const std = @import("../../index.zig");
2
3export var _tls_index: u32 = std.os.windows.TLS_OUT_OF_INDEXES;
4export var _tls_start: u8 linksection(".tls") = 0;
5export var _tls_end: u8 linksection(".tls$ZZZ") = 0;
6export var __xl_a: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLA") = null;
7export var __xl_z: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLZ") = null;
8
9// TODO this is how I would like it to be expressed
10// TODO also note, ReactOS has a +1 on StartAddressOfRawData and AddressOfCallBacks. Investigate
11// why they do that.
12//export const _tls_used linksection(".rdata$T") = std.os.windows.IMAGE_TLS_DIRECTORY {
13// .StartAddressOfRawData = @ptrToInt(&_tls_start),
14// .EndAddressOfRawData = @ptrToInt(&_tls_end),
15// .AddressOfIndex = @ptrToInt(&_tls_index),
16// .AddressOfCallBacks = @ptrToInt(__xl_a),
17// .SizeOfZeroFill = 0,
18// .Characteristics = 0,
19//};
20// This is the workaround because we can't do @ptrToInt at comptime like that.
21pub const IMAGE_TLS_DIRECTORY = extern struct {
22 StartAddressOfRawData: *c_void,
23 EndAddressOfRawData: *c_void,
24 AddressOfIndex: *c_void,
25 AddressOfCallBacks: *c_void,
26 SizeOfZeroFill: u32,
27 Characteristics: u32,
28};
29export const _tls_used linksection(".rdata$T") = IMAGE_TLS_DIRECTORY {
30 .StartAddressOfRawData = &_tls_start,
31 .EndAddressOfRawData = &_tls_end,
32 .AddressOfIndex = &_tls_index,
33 .AddressOfCallBacks = &__xl_a,
34 .SizeOfZeroFill = 0,
35 .Characteristics = 0,
36};
std/pdb.zig+15-3
...@@ -9,6 +9,10 @@ const coff = std.coff;...@@ -9,6 +9,10 @@ const coff = std.coff;
99
10const ArrayList = std.ArrayList;10const ArrayList = std.ArrayList;
1111
12// Note: most of this is based on information gathered from LLVM source code,
13// documentation and/or contributors.
14
15
12// https://llvm.org/docs/PDB/DbiStream.html#stream-header16// https://llvm.org/docs/PDB/DbiStream.html#stream-header
13pub const DbiStreamHeader = packed struct {17pub const DbiStreamHeader = packed struct {
14 VersionSignature: i32,18 VersionSignature: i32,
...@@ -345,6 +349,10 @@ pub const RecordPrefix = packed struct {...@@ -345,6 +349,10 @@ pub const RecordPrefix = packed struct {
345 RecordKind: SymbolKind,349 RecordKind: SymbolKind,
346};350};
347351
352/// The following variable length array appears immediately after the header.
353/// The structure definition follows.
354/// LineBlockFragmentHeader Blocks[]
355/// Each `LineBlockFragmentHeader` as specified below.
348pub const LineFragmentHeader = packed struct {356pub const LineFragmentHeader = packed struct {
349 /// Code offset of line contribution.357 /// Code offset of line contribution.
350 RelocOffset: u32,358 RelocOffset: u32,
...@@ -386,7 +394,11 @@ pub const LineNumberEntry = packed struct {...@@ -386,7 +394,11 @@ pub const LineNumberEntry = packed struct {
386394
387 /// TODO runtime crash when I make the actual type of Flags this395 /// TODO runtime crash when I make the actual type of Flags this
388 const Flags = packed struct {396 const Flags = packed struct {
397 /// Start line number
389 Start: u24,398 Start: u24,
399
400 /// Delta of lines to the end of the expression. Still unclear.
401 // TODO figure out the point of this field.
390 End: u7,402 End: u7,
391 IsStatement: bool,403 IsStatement: bool,
392 };404 };
...@@ -508,11 +520,11 @@ const Msf = struct {...@@ -508,11 +520,11 @@ const Msf = struct {
508 allocator,520 allocator,
509 );521 );
510522
511 const stream_count = try self.directory.stream.readIntLe(u32);523 const stream_count = try self.directory.stream.readIntLittle(u32);
512524
513 const stream_sizes = try allocator.alloc(u32, stream_count);525 const stream_sizes = try allocator.alloc(u32, stream_count);
514 for (stream_sizes) |*s| {526 for (stream_sizes) |*s| {
515 const size = try self.directory.stream.readIntLe(u32);527 const size = try self.directory.stream.readIntLittle(u32);
516 s.* = blockCountFromSize(size, superblock.BlockSize);528 s.* = blockCountFromSize(size, superblock.BlockSize);
517 }529 }
518530
...@@ -603,7 +615,7 @@ const MsfStream = struct {...@@ -603,7 +615,7 @@ const MsfStream = struct {
603615
604 var i: u32 = 0;616 var i: u32 = 0;
605 while (i < block_count) : (i += 1) {617 while (i < block_count) : (i += 1) {
606 stream.blocks[i] = try in.readIntLe(u32);618 stream.blocks[i] = try in.readIntLittle(u32);
607 }619 }
608620
609 return stream;621 return stream;
std/rand/index.zig+87-82
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5// ```5// ```
6// var buf: [8]u8 = undefined;6// var buf: [8]u8 = undefined;
7// try std.os.getRandomBytes(buf[0..]);7// try std.os.getRandomBytes(buf[0..]);
8// const seed = mem.readIntLE(u64, buf[0..8]);8// const seed = mem.readIntSliceLittle(u64, buf[0..8]);
9//9//
10// var r = DefaultPrng.init(seed);10// var r = DefaultPrng.init(seed);
11//11//
...@@ -17,6 +17,7 @@...@@ -17,6 +17,7 @@
17const std = @import("../index.zig");17const std = @import("../index.zig");
18const builtin = @import("builtin");18const builtin = @import("builtin");
19const assert = std.debug.assert;19const assert = std.debug.assert;
20const expect = std.testing.expect;
20const mem = std.mem;21const mem = std.mem;
21const math = std.math;22const math = std.math;
22const ziggurat = @import("ziggurat.zig");23const ziggurat = @import("ziggurat.zig");
...@@ -52,7 +53,7 @@ pub const Random = struct {...@@ -52,7 +53,7 @@ pub const Random = struct {
52 // use LE instead of native endian for better portability maybe?53 // use LE instead of native endian for better portability maybe?
53 // TODO: endian portability is pointless if the underlying prng isn't endian portable.54 // TODO: endian portability is pointless if the underlying prng isn't endian portable.
54 // TODO: document the endian portability of this library.55 // TODO: document the endian portability of this library.
55 const byte_aligned_result = mem.readIntLE(ByteAlignedT, rand_bytes);56 const byte_aligned_result = mem.readIntSliceLittle(ByteAlignedT, rand_bytes);
56 const unsigned_result = @truncate(UnsignedT, byte_aligned_result);57 const unsigned_result = @truncate(UnsignedT, byte_aligned_result);
57 return @bitCast(T, unsigned_result);58 return @bitCast(T, unsigned_result);
58 }59 }
...@@ -69,6 +70,7 @@ pub const Random = struct {...@@ -69,6 +70,7 @@ pub const Random = struct {
69 return @intCast(T, limitRangeBiased(u64, r.int(u64), less_than));70 return @intCast(T, limitRangeBiased(u64, r.int(u64), less_than));
70 }71 }
71 }72 }
73
72 /// Returns an evenly distributed random unsigned integer `0 <= i < less_than`.74 /// Returns an evenly distributed random unsigned integer `0 <= i < less_than`.
73 /// This function assumes that the underlying ::fillFn produces evenly distributed values.75 /// This function assumes that the underlying ::fillFn produces evenly distributed values.
74 /// Within this assumption, the runtime of this function is exponentially distributed.76 /// Within this assumption, the runtime of this function is exponentially distributed.
...@@ -123,6 +125,7 @@ pub const Random = struct {...@@ -123,6 +125,7 @@ pub const Random = struct {
123 }125 }
124 return r.uintLessThanBiased(T, at_most + 1);126 return r.uintLessThanBiased(T, at_most + 1);
125 }127 }
128
126 /// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`.129 /// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`.
127 /// See ::uintLessThan, which this function uses in most cases,130 /// See ::uintLessThan, which this function uses in most cases,
128 /// for commentary on the runtime of this function.131 /// for commentary on the runtime of this function.
...@@ -151,6 +154,7 @@ pub const Random = struct {...@@ -151,6 +154,7 @@ pub const Random = struct {
151 return at_least + r.uintLessThanBiased(T, less_than - at_least);154 return at_least + r.uintLessThanBiased(T, less_than - at_least);
152 }155 }
153 }156 }
157
154 /// Returns an evenly distributed random integer `at_least <= i < less_than`.158 /// Returns an evenly distributed random integer `at_least <= i < less_than`.
155 /// See ::uintLessThan, which this function uses in most cases,159 /// See ::uintLessThan, which this function uses in most cases,
156 /// for commentary on the runtime of this function.160 /// for commentary on the runtime of this function.
...@@ -185,6 +189,7 @@ pub const Random = struct {...@@ -185,6 +189,7 @@ pub const Random = struct {
185 return at_least + r.uintAtMostBiased(T, at_most - at_least);189 return at_least + r.uintAtMostBiased(T, at_most - at_least);
186 }190 }
187 }191 }
192
188 /// Returns an evenly distributed random integer `at_least <= i <= at_most`.193 /// Returns an evenly distributed random integer `at_least <= i <= at_most`.
189 /// See ::uintLessThan, which this function uses in most cases,194 /// See ::uintLessThan, which this function uses in most cases,
190 /// for commentary on the runtime of this function.195 /// for commentary on the runtime of this function.
...@@ -312,43 +317,43 @@ test "Random int" {...@@ -312,43 +317,43 @@ test "Random int" {
312fn testRandomInt() void {317fn testRandomInt() void {
313 var r = SequentialPrng.init();318 var r = SequentialPrng.init();
314319
315 assert(r.random.int(u0) == 0);320 expect(r.random.int(u0) == 0);
316321
317 r.next_value = 0;322 r.next_value = 0;
318 assert(r.random.int(u1) == 0);323 expect(r.random.int(u1) == 0);
319 assert(r.random.int(u1) == 1);324 expect(r.random.int(u1) == 1);
320 assert(r.random.int(u2) == 2);325 expect(r.random.int(u2) == 2);
321 assert(r.random.int(u2) == 3);326 expect(r.random.int(u2) == 3);
322 assert(r.random.int(u2) == 0);327 expect(r.random.int(u2) == 0);
323328
324 r.next_value = 0xff;329 r.next_value = 0xff;
325 assert(r.random.int(u8) == 0xff);330 expect(r.random.int(u8) == 0xff);
326 r.next_value = 0x11;331 r.next_value = 0x11;
327 assert(r.random.int(u8) == 0x11);332 expect(r.random.int(u8) == 0x11);
328333
329 r.next_value = 0xff;334 r.next_value = 0xff;
330 assert(r.random.int(u32) == 0xffffffff);335 expect(r.random.int(u32) == 0xffffffff);
331 r.next_value = 0x11;336 r.next_value = 0x11;
332 assert(r.random.int(u32) == 0x11111111);337 expect(r.random.int(u32) == 0x11111111);
333338
334 r.next_value = 0xff;339 r.next_value = 0xff;
335 assert(r.random.int(i32) == -1);340 expect(r.random.int(i32) == -1);
336 r.next_value = 0x11;341 r.next_value = 0x11;
337 assert(r.random.int(i32) == 0x11111111);342 expect(r.random.int(i32) == 0x11111111);
338343
339 r.next_value = 0xff;344 r.next_value = 0xff;
340 assert(r.random.int(i8) == -1);345 expect(r.random.int(i8) == -1);
341 r.next_value = 0x11;346 r.next_value = 0x11;
342 assert(r.random.int(i8) == 0x11);347 expect(r.random.int(i8) == 0x11);
343348
344 r.next_value = 0xff;349 r.next_value = 0xff;
345 assert(r.random.int(u33) == 0x1ffffffff);350 expect(r.random.int(u33) == 0x1ffffffff);
346 r.next_value = 0xff;351 r.next_value = 0xff;
347 assert(r.random.int(i1) == -1);352 expect(r.random.int(i1) == -1);
348 r.next_value = 0xff;353 r.next_value = 0xff;
349 assert(r.random.int(i2) == -1);354 expect(r.random.int(i2) == -1);
350 r.next_value = 0xff;355 r.next_value = 0xff;
351 assert(r.random.int(i33) == -1);356 expect(r.random.int(i33) == -1);
352}357}
353358
354test "Random boolean" {359test "Random boolean" {
...@@ -357,10 +362,10 @@ test "Random boolean" {...@@ -357,10 +362,10 @@ test "Random boolean" {
357}362}
358fn testRandomBoolean() void {363fn testRandomBoolean() void {
359 var r = SequentialPrng.init();364 var r = SequentialPrng.init();
360 assert(r.random.boolean() == false);365 expect(r.random.boolean() == false);
361 assert(r.random.boolean() == true);366 expect(r.random.boolean() == true);
362 assert(r.random.boolean() == false);367 expect(r.random.boolean() == false);
363 assert(r.random.boolean() == true);368 expect(r.random.boolean() == true);
364}369}
365370
366test "Random intLessThan" {371test "Random intLessThan" {
...@@ -371,36 +376,36 @@ test "Random intLessThan" {...@@ -371,36 +376,36 @@ test "Random intLessThan" {
371fn testRandomIntLessThan() void {376fn testRandomIntLessThan() void {
372 var r = SequentialPrng.init();377 var r = SequentialPrng.init();
373 r.next_value = 0xff;378 r.next_value = 0xff;
374 assert(r.random.uintLessThan(u8, 4) == 3);379 expect(r.random.uintLessThan(u8, 4) == 3);
375 assert(r.next_value == 0);380 expect(r.next_value == 0);
376 assert(r.random.uintLessThan(u8, 4) == 0);381 expect(r.random.uintLessThan(u8, 4) == 0);
377 assert(r.next_value == 1);382 expect(r.next_value == 1);
378383
379 r.next_value = 0;384 r.next_value = 0;
380 assert(r.random.uintLessThan(u64, 32) == 0);385 expect(r.random.uintLessThan(u64, 32) == 0);
381386
382 // trigger the bias rejection code path387 // trigger the bias rejection code path
383 r.next_value = 0;388 r.next_value = 0;
384 assert(r.random.uintLessThan(u8, 3) == 0);389 expect(r.random.uintLessThan(u8, 3) == 0);
385 // verify we incremented twice390 // verify we incremented twice
386 assert(r.next_value == 2);391 expect(r.next_value == 2);
387392
388 r.next_value = 0xff;393 r.next_value = 0xff;
389 assert(r.random.intRangeLessThan(u8, 0, 0x80) == 0x7f);394 expect(r.random.intRangeLessThan(u8, 0, 0x80) == 0x7f);
390 r.next_value = 0xff;395 r.next_value = 0xff;
391 assert(r.random.intRangeLessThan(u8, 0x7f, 0xff) == 0xfe);396 expect(r.random.intRangeLessThan(u8, 0x7f, 0xff) == 0xfe);
392397
393 r.next_value = 0xff;398 r.next_value = 0xff;
394 assert(r.random.intRangeLessThan(i8, 0, 0x40) == 0x3f);399 expect(r.random.intRangeLessThan(i8, 0, 0x40) == 0x3f);
395 r.next_value = 0xff;400 r.next_value = 0xff;
396 assert(r.random.intRangeLessThan(i8, -0x40, 0x40) == 0x3f);401 expect(r.random.intRangeLessThan(i8, -0x40, 0x40) == 0x3f);
397 r.next_value = 0xff;402 r.next_value = 0xff;
398 assert(r.random.intRangeLessThan(i8, -0x80, 0) == -1);403 expect(r.random.intRangeLessThan(i8, -0x80, 0) == -1);
399404
400 r.next_value = 0xff;405 r.next_value = 0xff;
401 assert(r.random.intRangeLessThan(i3, -4, 0) == -1);406 expect(r.random.intRangeLessThan(i3, -4, 0) == -1);
402 r.next_value = 0xff;407 r.next_value = 0xff;
403 assert(r.random.intRangeLessThan(i3, -2, 2) == 1);408 expect(r.random.intRangeLessThan(i3, -2, 2) == 1);
404}409}
405410
406test "Random intAtMost" {411test "Random intAtMost" {
...@@ -411,34 +416,34 @@ test "Random intAtMost" {...@@ -411,34 +416,34 @@ test "Random intAtMost" {
411fn testRandomIntAtMost() void {416fn testRandomIntAtMost() void {
412 var r = SequentialPrng.init();417 var r = SequentialPrng.init();
413 r.next_value = 0xff;418 r.next_value = 0xff;
414 assert(r.random.uintAtMost(u8, 3) == 3);419 expect(r.random.uintAtMost(u8, 3) == 3);
415 assert(r.next_value == 0);420 expect(r.next_value == 0);
416 assert(r.random.uintAtMost(u8, 3) == 0);421 expect(r.random.uintAtMost(u8, 3) == 0);
417422
418 // trigger the bias rejection code path423 // trigger the bias rejection code path
419 r.next_value = 0;424 r.next_value = 0;
420 assert(r.random.uintAtMost(u8, 2) == 0);425 expect(r.random.uintAtMost(u8, 2) == 0);
421 // verify we incremented twice426 // verify we incremented twice
422 assert(r.next_value == 2);427 expect(r.next_value == 2);
423428
424 r.next_value = 0xff;429 r.next_value = 0xff;
425 assert(r.random.intRangeAtMost(u8, 0, 0x7f) == 0x7f);430 expect(r.random.intRangeAtMost(u8, 0, 0x7f) == 0x7f);
426 r.next_value = 0xff;431 r.next_value = 0xff;
427 assert(r.random.intRangeAtMost(u8, 0x7f, 0xfe) == 0xfe);432 expect(r.random.intRangeAtMost(u8, 0x7f, 0xfe) == 0xfe);
428433
429 r.next_value = 0xff;434 r.next_value = 0xff;
430 assert(r.random.intRangeAtMost(i8, 0, 0x3f) == 0x3f);435 expect(r.random.intRangeAtMost(i8, 0, 0x3f) == 0x3f);
431 r.next_value = 0xff;436 r.next_value = 0xff;
432 assert(r.random.intRangeAtMost(i8, -0x40, 0x3f) == 0x3f);437 expect(r.random.intRangeAtMost(i8, -0x40, 0x3f) == 0x3f);
433 r.next_value = 0xff;438 r.next_value = 0xff;
434 assert(r.random.intRangeAtMost(i8, -0x80, -1) == -1);439 expect(r.random.intRangeAtMost(i8, -0x80, -1) == -1);
435440
436 r.next_value = 0xff;441 r.next_value = 0xff;
437 assert(r.random.intRangeAtMost(i3, -4, -1) == -1);442 expect(r.random.intRangeAtMost(i3, -4, -1) == -1);
438 r.next_value = 0xff;443 r.next_value = 0xff;
439 assert(r.random.intRangeAtMost(i3, -2, 1) == 1);444 expect(r.random.intRangeAtMost(i3, -2, 1) == 1);
440445
441 assert(r.random.uintAtMost(u0, 0) == 0);446 expect(r.random.uintAtMost(u0, 0) == 0);
442}447}
443448
444test "Random Biased" {449test "Random Biased" {
...@@ -446,30 +451,30 @@ test "Random Biased" {...@@ -446,30 +451,30 @@ test "Random Biased" {
446 // Not thoroughly checking the logic here.451 // Not thoroughly checking the logic here.
447 // Just want to execute all the paths with different types.452 // Just want to execute all the paths with different types.
448453
449 assert(r.random.uintLessThanBiased(u1, 1) == 0);454 expect(r.random.uintLessThanBiased(u1, 1) == 0);
450 assert(r.random.uintLessThanBiased(u32, 10) < 10);455 expect(r.random.uintLessThanBiased(u32, 10) < 10);
451 assert(r.random.uintLessThanBiased(u64, 20) < 20);456 expect(r.random.uintLessThanBiased(u64, 20) < 20);
452457
453 assert(r.random.uintAtMostBiased(u0, 0) == 0);458 expect(r.random.uintAtMostBiased(u0, 0) == 0);
454 assert(r.random.uintAtMostBiased(u1, 0) <= 0);459 expect(r.random.uintAtMostBiased(u1, 0) <= 0);
455 assert(r.random.uintAtMostBiased(u32, 10) <= 10);460 expect(r.random.uintAtMostBiased(u32, 10) <= 10);
456 assert(r.random.uintAtMostBiased(u64, 20) <= 20);461 expect(r.random.uintAtMostBiased(u64, 20) <= 20);
457462
458 assert(r.random.intRangeLessThanBiased(u1, 0, 1) == 0);463 expect(r.random.intRangeLessThanBiased(u1, 0, 1) == 0);
459 assert(r.random.intRangeLessThanBiased(i1, -1, 0) == -1);464 expect(r.random.intRangeLessThanBiased(i1, -1, 0) == -1);
460 assert(r.random.intRangeLessThanBiased(u32, 10, 20) >= 10);465 expect(r.random.intRangeLessThanBiased(u32, 10, 20) >= 10);
461 assert(r.random.intRangeLessThanBiased(i32, 10, 20) >= 10);466 expect(r.random.intRangeLessThanBiased(i32, 10, 20) >= 10);
462 assert(r.random.intRangeLessThanBiased(u64, 20, 40) >= 20);467 expect(r.random.intRangeLessThanBiased(u64, 20, 40) >= 20);
463 assert(r.random.intRangeLessThanBiased(i64, 20, 40) >= 20);468 expect(r.random.intRangeLessThanBiased(i64, 20, 40) >= 20);
464469
465 // uncomment for broken module error:470 // uncomment for broken module error:
466 //assert(r.random.intRangeAtMostBiased(u0, 0, 0) == 0);471 //expect(r.random.intRangeAtMostBiased(u0, 0, 0) == 0);
467 assert(r.random.intRangeAtMostBiased(u1, 0, 1) >= 0);472 expect(r.random.intRangeAtMostBiased(u1, 0, 1) >= 0);
468 assert(r.random.intRangeAtMostBiased(i1, -1, 0) >= -1);473 expect(r.random.intRangeAtMostBiased(i1, -1, 0) >= -1);
469 assert(r.random.intRangeAtMostBiased(u32, 10, 20) >= 10);474 expect(r.random.intRangeAtMostBiased(u32, 10, 20) >= 10);
470 assert(r.random.intRangeAtMostBiased(i32, 10, 20) >= 10);475 expect(r.random.intRangeAtMostBiased(i32, 10, 20) >= 10);
471 assert(r.random.intRangeAtMostBiased(u64, 20, 40) >= 20);476 expect(r.random.intRangeAtMostBiased(u64, 20, 40) >= 20);
472 assert(r.random.intRangeAtMostBiased(i64, 20, 40) >= 20);477 expect(r.random.intRangeAtMostBiased(i64, 20, 40) >= 20);
473}478}
474479
475// Generator to extend 64-bit seed values into longer sequences.480// Generator to extend 64-bit seed values into longer sequences.
...@@ -506,7 +511,7 @@ test "splitmix64 sequence" {...@@ -506,7 +511,7 @@ test "splitmix64 sequence" {
506 };511 };
507512
508 for (seq) |s| {513 for (seq) |s| {
509 std.debug.assert(s == r.next());514 expect(s == r.next());
510 }515 }
511}516}
512517
...@@ -599,7 +604,7 @@ test "pcg sequence" {...@@ -599,7 +604,7 @@ test "pcg sequence" {
599 };604 };
600605
601 for (seq) |s| {606 for (seq) |s| {
602 std.debug.assert(s == r.next());607 expect(s == r.next());
603 }608 }
604}609}
605610
...@@ -708,7 +713,7 @@ test "xoroshiro sequence" {...@@ -708,7 +713,7 @@ test "xoroshiro sequence" {
708 };713 };
709714
710 for (seq1) |s| {715 for (seq1) |s| {
711 std.debug.assert(s == r.next());716 expect(s == r.next());
712 }717 }
713718
714 r.jump();719 r.jump();
...@@ -723,7 +728,7 @@ test "xoroshiro sequence" {...@@ -723,7 +728,7 @@ test "xoroshiro sequence" {
723 };728 };
724729
725 for (seq2) |s| {730 for (seq2) |s| {
726 std.debug.assert(s == r.next());731 expect(s == r.next());
727 }732 }
728}733}
729734
...@@ -926,7 +931,7 @@ test "isaac64 sequence" {...@@ -926,7 +931,7 @@ test "isaac64 sequence" {
926 };931 };
927932
928 for (seq) |s| {933 for (seq) |s| {
929 std.debug.assert(s == r.next());934 expect(s == r.next());
930 }935 }
931}936}
932937
...@@ -937,12 +942,12 @@ test "Random float" {...@@ -937,12 +942,12 @@ test "Random float" {
937 var i: usize = 0;942 var i: usize = 0;
938 while (i < 1000) : (i += 1) {943 while (i < 1000) : (i += 1) {
939 const val1 = prng.random.float(f32);944 const val1 = prng.random.float(f32);
940 std.debug.assert(val1 >= 0.0);945 expect(val1 >= 0.0);
941 std.debug.assert(val1 < 1.0);946 expect(val1 < 1.0);
942947
943 const val2 = prng.random.float(f64);948 const val2 = prng.random.float(f64);
944 std.debug.assert(val2 >= 0.0);949 expect(val2 >= 0.0);
945 std.debug.assert(val2 < 1.0);950 expect(val2 < 1.0);
946 }951 }
947}952}
948953
...@@ -956,12 +961,12 @@ test "Random shuffle" {...@@ -956,12 +961,12 @@ test "Random shuffle" {
956 while (i < 1000) : (i += 1) {961 while (i < 1000) : (i += 1) {
957 prng.random.shuffle(u8, seq[0..]);962 prng.random.shuffle(u8, seq[0..]);
958 seen[seq[0]] = true;963 seen[seq[0]] = true;
959 std.debug.assert(sumArray(seq[0..]) == 10);964 expect(sumArray(seq[0..]) == 10);
960 }965 }
961966
962 // we should see every entry at the head at least once967 // we should see every entry at the head at least once
963 for (seen) |e| {968 for (seen) |e| {
964 std.debug.assert(e == true);969 expect(e == true);
965 }970 }
966}971}
967972
std/rb.zig+3-2
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const std = @import("index.zig");1const std = @import("index.zig");
2const assert = std.debug.assert;2const assert = std.debug.assert;
3const testing = std.testing;
3const mem = std.mem; // For mem.Compare4const mem = std.mem; // For mem.Compare
45
5const Color = enum(u1) {6const Color = enum(u1) {
...@@ -533,13 +534,13 @@ test "rb" {...@@ -533,13 +534,13 @@ test "rb" {
533 _ = tree.insert(&ns[8].node);534 _ = tree.insert(&ns[8].node);
534 _ = tree.insert(&ns[9].node);535 _ = tree.insert(&ns[9].node);
535 tree.remove(&ns[3].node);536 tree.remove(&ns[3].node);
536 assert(tree.insert(&dup.node) == &ns[7].node);537 testing.expect(tree.insert(&dup.node) == &ns[7].node);
537 try tree.replace(&ns[7].node, &dup.node);538 try tree.replace(&ns[7].node, &dup.node);
538539
539 var num: *testNumber = undefined;540 var num: *testNumber = undefined;
540 num = testGetNumber(tree.first().?);541 num = testGetNumber(tree.first().?);
541 while (num.node.next() != null) {542 while (num.node.next() != null) {
542 assert(testGetNumber(num.node.next().?).value > num.value);543 testing.expect(testGetNumber(num.node.next().?).value > num.value);
543 num = testGetNumber(num.node.next().?);544 num = testGetNumber(num.node.next().?);
544 }545 }
545}546}
std/segmented_list.zig+16-15
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const std = @import("index.zig");1const std = @import("index.zig");
2const assert = std.debug.assert;2const assert = std.debug.assert;
3const testing = std.testing;
3const Allocator = std.mem.Allocator;4const Allocator = std.mem.Allocator;
45
5// Imagine that `fn at(self: *Self, index: usize) &T` is a customer asking for a box6// Imagine that `fn at(self: *Self, index: usize) &T` is a customer asking for a box
...@@ -352,14 +353,14 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void {...@@ -352,14 +353,14 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void {
352 var i: usize = 0;353 var i: usize = 0;
353 while (i < 100) : (i += 1) {354 while (i < 100) : (i += 1) {
354 try list.push(@intCast(i32, i + 1));355 try list.push(@intCast(i32, i + 1));
355 assert(list.len == i + 1);356 testing.expect(list.len == i + 1);
356 }357 }
357 }358 }
358359
359 {360 {
360 var i: usize = 0;361 var i: usize = 0;
361 while (i < 100) : (i += 1) {362 while (i < 100) : (i += 1) {
362 assert(list.at(i).* == @intCast(i32, i + 1));363 testing.expect(list.at(i).* == @intCast(i32, i + 1));
363 }364 }
364 }365 }
365366
...@@ -368,35 +369,35 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void {...@@ -368,35 +369,35 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void {
368 var x: i32 = 0;369 var x: i32 = 0;
369 while (it.next()) |item| {370 while (it.next()) |item| {
370 x += 1;371 x += 1;
371 assert(item.* == x);372 testing.expect(item.* == x);
372 }373 }
373 assert(x == 100);374 testing.expect(x == 100);
374 while (it.prev()) |item| : (x -= 1) {375 while (it.prev()) |item| : (x -= 1) {
375 assert(item.* == x);376 testing.expect(item.* == x);
376 }377 }
377 assert(x == 0);378 testing.expect(x == 0);
378 }379 }
379380
380 assert(list.pop().? == 100);381 testing.expect(list.pop().? == 100);
381 assert(list.len == 99);382 testing.expect(list.len == 99);
382383
383 try list.pushMany([]i32{384 try list.pushMany([]i32{
384 1,385 1,
385 2,386 2,
386 3,387 3,
387 });388 });
388 assert(list.len == 102);389 testing.expect(list.len == 102);
389 assert(list.pop().? == 3);390 testing.expect(list.pop().? == 3);
390 assert(list.pop().? == 2);391 testing.expect(list.pop().? == 2);
391 assert(list.pop().? == 1);392 testing.expect(list.pop().? == 1);
392 assert(list.len == 99);393 testing.expect(list.len == 99);
393394
394 try list.pushMany([]const i32{});395 try list.pushMany([]const i32{});
395 assert(list.len == 99);396 testing.expect(list.len == 99);
396397
397 var i: i32 = 99;398 var i: i32 = 99;
398 while (list.pop()) |item| : (i -= 1) {399 while (list.pop()) |item| : (i -= 1) {
399 assert(item == i);400 testing.expect(item == i);
400 list.shrinkCapacity(list.len);401 list.shrinkCapacity(list.len);
401 }402 }
402}403}
std/sort.zig+9-8
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const std = @import("index.zig");1const std = @import("index.zig");
2const assert = std.debug.assert;2const assert = std.debug.assert;
3const testing = std.testing;
3const mem = std.mem;4const mem = std.mem;
4const math = std.math;5const math = std.math;
5const builtin = @import("builtin");6const builtin = @import("builtin");
...@@ -1031,8 +1032,8 @@ fn testStableSort() void {...@@ -1031,8 +1032,8 @@ fn testStableSort() void {
1031 for (cases) |*case| {1032 for (cases) |*case| {
1032 insertionSort(IdAndValue, (case.*)[0..], cmpByValue);1033 insertionSort(IdAndValue, (case.*)[0..], cmpByValue);
1033 for (case.*) |item, i| {1034 for (case.*) |item, i| {
1034 assert(item.id == expected[i].id);1035 testing.expect(item.id == expected[i].id);
1035 assert(item.value == expected[i].value);1036 testing.expect(item.value == expected[i].value);
1036 }1037 }
1037 }1038 }
1038}1039}
...@@ -1077,7 +1078,7 @@ test "std.sort" {...@@ -1077,7 +1078,7 @@ test "std.sort" {
1077 const slice = buf[0..case[0].len];1078 const slice = buf[0..case[0].len];
1078 mem.copy(u8, slice, case[0]);1079 mem.copy(u8, slice, case[0]);
1079 sort(u8, slice, asc(u8));1080 sort(u8, slice, asc(u8));
1080 assert(mem.eql(u8, slice, case[1]));1081 testing.expect(mem.eql(u8, slice, case[1]));
1081 }1082 }
10821083
1083 const i32cases = [][]const []const i32{1084 const i32cases = [][]const []const i32{
...@@ -1112,7 +1113,7 @@ test "std.sort" {...@@ -1112,7 +1113,7 @@ test "std.sort" {
1112 const slice = buf[0..case[0].len];1113 const slice = buf[0..case[0].len];
1113 mem.copy(i32, slice, case[0]);1114 mem.copy(i32, slice, case[0]);
1114 sort(i32, slice, asc(i32));1115 sort(i32, slice, asc(i32));
1115 assert(mem.eql(i32, slice, case[1]));1116 testing.expect(mem.eql(i32, slice, case[1]));
1116 }1117 }
1117}1118}
11181119
...@@ -1149,7 +1150,7 @@ test "std.sort descending" {...@@ -1149,7 +1150,7 @@ test "std.sort descending" {
1149 const slice = buf[0..case[0].len];1150 const slice = buf[0..case[0].len];
1150 mem.copy(i32, slice, case[0]);1151 mem.copy(i32, slice, case[0]);
1151 sort(i32, slice, desc(i32));1152 sort(i32, slice, desc(i32));
1152 assert(mem.eql(i32, slice, case[1]));1153 testing.expect(mem.eql(i32, slice, case[1]));
1153 }1154 }
1154}1155}
11551156
...@@ -1157,7 +1158,7 @@ test "another sort case" {...@@ -1157,7 +1158,7 @@ test "another sort case" {
1157 var arr = []i32{ 5, 3, 1, 2, 4 };1158 var arr = []i32{ 5, 3, 1, 2, 4 };
1158 sort(i32, arr[0..], asc(i32));1159 sort(i32, arr[0..], asc(i32));
11591160
1160 assert(mem.eql(i32, arr, []i32{ 1, 2, 3, 4, 5 }));1161 testing.expect(mem.eql(i32, arr, []i32{ 1, 2, 3, 4, 5 }));
1161}1162}
11621163
1163test "sort fuzz testing" {1164test "sort fuzz testing" {
...@@ -1185,9 +1186,9 @@ fn fuzzTest(rng: *std.rand.Random) void {...@@ -1185,9 +1186,9 @@ fn fuzzTest(rng: *std.rand.Random) void {
1185 var index: usize = 1;1186 var index: usize = 1;
1186 while (index < array.len) : (index += 1) {1187 while (index < array.len) : (index += 1) {
1187 if (array[index].value == array[index - 1].value) {1188 if (array[index].value == array[index - 1].value) {
1188 assert(array[index].id > array[index - 1].id);1189 testing.expect(array[index].id > array[index - 1].id);
1189 } else {1190 } else {
1190 assert(array[index].value > array[index - 1].value);1191 testing.expect(array[index].value > array[index - 1].value);
1191 }1192 }
1192 }1193 }
1193}1194}
std/special/bootstrap.zig+63-15
...@@ -4,6 +4,7 @@...@@ -4,6 +4,7 @@
4const root = @import("@root");4const root = @import("@root");
5const std = @import("std");5const std = @import("std");
6const builtin = @import("builtin");6const builtin = @import("builtin");
7const assert = std.debug.assert;
78
8var argc_ptr: [*]usize = undefined;9var argc_ptr: [*]usize = undefined;
910
...@@ -20,17 +21,10 @@ comptime {...@@ -20,17 +21,10 @@ comptime {
2021
21nakedcc fn _start() noreturn {22nakedcc fn _start() noreturn {
22 switch (builtin.arch) {23 switch (builtin.arch) {
23 builtin.Arch.x86_64 => switch (builtin.os) {24 builtin.Arch.x86_64 => {
24 builtin.Os.freebsd => {25 argc_ptr = asm ("lea (%%rsp), %[argc]"
25 argc_ptr = asm ("lea (%%rdi), %[argc]"26 : [argc] "=r" (-> [*]usize)
26 : [argc] "=r" (-> [*]usize)27 );
27 );
28 },
29 else => {
30 argc_ptr = asm ("lea (%%rsp), %[argc]"
31 : [argc] "=r" (-> [*]usize)
32 );
33 },
34 },28 },
35 builtin.Arch.i386 => {29 builtin.Arch.i386 => {
36 argc_ptr = asm ("lea (%%esp), %[argc]"30 argc_ptr = asm ("lea (%%esp), %[argc]"
...@@ -51,7 +45,9 @@ nakedcc fn _start() noreturn {...@@ -51,7 +45,9 @@ nakedcc fn _start() noreturn {
5145
52extern fn WinMainCRTStartup() noreturn {46extern fn WinMainCRTStartup() noreturn {
53 @setAlignStack(16);47 @setAlignStack(16);
5448 if (!builtin.single_threaded) {
49 _ = @import("../os/windows/tls.zig");
50 }
55 std.os.windows.ExitProcess(callMain());51 std.os.windows.ExitProcess(callMain());
56}52}
5753
...@@ -68,9 +64,23 @@ fn posixCallMainAndExit() noreturn {...@@ -68,9 +64,23 @@ fn posixCallMainAndExit() noreturn {
68 while (envp_optional[envp_count]) |_| : (envp_count += 1) {}64 while (envp_optional[envp_count]) |_| : (envp_count += 1) {}
69 const envp = @ptrCast([*][*]u8, envp_optional)[0..envp_count];65 const envp = @ptrCast([*][*]u8, envp_optional)[0..envp_count];
70 if (builtin.os == builtin.Os.linux) {66 if (builtin.os == builtin.Os.linux) {
71 const auxv = @ptrCast([*]usize, envp.ptr + envp_count + 1);67 // Scan auxiliary vector.
72 std.os.linux_elf_aux_maybe = @ptrCast([*]std.elf.Auxv, auxv);68 const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1);
73 std.debug.assert(std.os.linuxGetAuxVal(std.elf.AT_PAGESZ) == std.os.page_size);69 std.os.linux_elf_aux_maybe = auxv;
70 var i: usize = 0;
71 var at_phdr: usize = 0;
72 var at_phnum: usize = 0;
73 var at_phent: usize = 0;
74 while (auxv[i].a_un.a_val != 0) : (i += 1) {
75 switch (auxv[i].a_type) {
76 std.elf.AT_PAGESZ => assert(auxv[i].a_un.a_val == std.os.page_size),
77 std.elf.AT_PHDR => at_phdr = auxv[i].a_un.a_val,
78 std.elf.AT_PHNUM => at_phnum = auxv[i].a_un.a_val,
79 std.elf.AT_PHENT => at_phent = auxv[i].a_un.a_val,
80 else => {},
81 }
82 }
83 if (!builtin.single_threaded) linuxInitializeThreadLocalStorage(at_phdr, at_phnum, at_phent);
74 }84 }
7585
76 std.os.posix.exit(callMainWithArgs(argc, argv, envp));86 std.os.posix.exit(callMainWithArgs(argc, argv, envp));
...@@ -123,3 +133,41 @@ inline fn callMain() u8 {...@@ -123,3 +133,41 @@ inline fn callMain() u8 {
123 else => @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'"),133 else => @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'"),
124 }134 }
125}135}
136
137var tls_end_addr: usize = undefined;
138const main_thread_tls_align = 32;
139var main_thread_tls_bytes: [64]u8 align(main_thread_tls_align) = [1]u8{0} ** 64;
140
141fn linuxInitializeThreadLocalStorage(at_phdr: usize, at_phnum: usize, at_phent: usize) void {
142 var phdr_addr = at_phdr;
143 var n = at_phnum;
144 var base: usize = 0;
145 while (n != 0) : ({n -= 1; phdr_addr += at_phent;}) {
146 const phdr = @intToPtr(*std.elf.Phdr, phdr_addr);
147 // TODO look for PT_DYNAMIC when we have https://github.com/ziglang/zig/issues/1917
148 switch (phdr.p_type) {
149 std.elf.PT_PHDR => base = at_phdr - phdr.p_vaddr,
150 std.elf.PT_TLS => std.os.linux_tls_phdr = phdr,
151 else => continue,
152 }
153 }
154 const tls_phdr = std.os.linux_tls_phdr orelse return;
155 std.os.linux_tls_img_src = @intToPtr([*]const u8, base + tls_phdr.p_vaddr);
156 assert(main_thread_tls_bytes.len >= tls_phdr.p_memsz); // not enough preallocated Thread Local Storage
157 assert(main_thread_tls_align >= tls_phdr.p_align); // preallocated Thread Local Storage not aligned enough
158 @memcpy(&main_thread_tls_bytes, std.os.linux_tls_img_src, tls_phdr.p_filesz);
159 tls_end_addr = @ptrToInt(&main_thread_tls_bytes) + tls_phdr.p_memsz;
160 linuxSetThreadArea(@ptrToInt(&tls_end_addr));
161}
162
163fn linuxSetThreadArea(addr: usize) void {
164 switch (builtin.arch) {
165 builtin.Arch.x86_64 => {
166 const ARCH_SET_FS = 0x1002;
167 const rc = std.os.linux.syscall2(std.os.linux.SYS_arch_prctl, ARCH_SET_FS, addr);
168 // acrh_prctl is documented to never fail
169 assert(rc == 0);
170 },
171 else => @compileError("Unsupported architecture"),
172 }
173}
std/special/compiler_rt/addXf3.zig created+191
...@@ -0,0 +1,191 @@
1// Ported from:
2//
3// https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/lib/builtins/fp_add_impl.inc
4
5const std = @import("std");
6const builtin = @import("builtin");
7const compiler_rt = @import("index.zig");
8
9pub extern fn __addtf3(a: f128, b: f128) f128 {
10 return addXf3(f128, a, b);
11}
12
13pub extern fn __subtf3(a: f128, b: f128) f128 {
14 const neg_b = @bitCast(f128, @bitCast(u128, b) ^ (u128(1) << 127));
15 return addXf3(f128, a, neg_b);
16}
17
18inline fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 {
19 const Z = @IntType(false, T.bit_count);
20 const significandBits = std.math.floatMantissaBits(T);
21 const implicitBit = Z(1) << significandBits;
22
23 const shift = @clz(significand.*) - @clz(implicitBit);
24 significand.* <<= @intCast(u7, shift);
25 return 1 - shift;
26}
27
28inline fn addXf3(comptime T: type, a: T, b: T) T {
29 const Z = @IntType(false, T.bit_count);
30
31 const typeWidth = T.bit_count;
32 const significandBits = std.math.floatMantissaBits(T);
33 const exponentBits = std.math.floatExponentBits(T);
34
35 const signBit = (Z(1) << (significandBits + exponentBits));
36 const maxExponent = ((1 << exponentBits) - 1);
37 const exponentBias = (maxExponent >> 1);
38
39 const implicitBit = (Z(1) << significandBits);
40 const quietBit = implicitBit >> 1;
41 const significandMask = implicitBit - 1;
42
43 const absMask = signBit - 1;
44 const exponentMask = absMask ^ significandMask;
45 const qnanRep = exponentMask | quietBit;
46
47 var aRep = @bitCast(Z, a);
48 var bRep = @bitCast(Z, b);
49 const aAbs = aRep & absMask;
50 const bAbs = bRep & absMask;
51
52 const negative = (aRep & signBit) != 0;
53 const exponent = @intCast(i32, aAbs >> significandBits) - exponentBias;
54 const significand = (aAbs & significandMask) | implicitBit;
55
56 const infRep = @bitCast(Z, std.math.inf(T));
57
58 // Detect if a or b is zero, infinity, or NaN.
59 if (aAbs - Z(1) >= infRep - Z(1) or
60 bAbs - Z(1) >= infRep - Z(1))
61 {
62 // NaN + anything = qNaN
63 if (aAbs > infRep) return @bitCast(T, @bitCast(Z, a) | quietBit);
64 // anything + NaN = qNaN
65 if (bAbs > infRep) return @bitCast(T, @bitCast(Z, b) | quietBit);
66
67 if (aAbs == infRep) {
68 // +/-infinity + -/+infinity = qNaN
69 if ((@bitCast(Z, a) ^ @bitCast(Z, b)) == signBit) {
70 return @bitCast(T, qnanRep);
71 }
72 // +/-infinity + anything remaining = +/- infinity
73 else {
74 return a;
75 }
76 }
77
78 // anything remaining + +/-infinity = +/-infinity
79 if (bAbs == infRep) return b;
80
81 // zero + anything = anything
82 if (aAbs == 0) {
83 // but we need to get the sign right for zero + zero
84 if (bAbs == 0) {
85 return @bitCast(T, @bitCast(Z, a) & @bitCast(Z, b));
86 } else {
87 return b;
88 }
89 }
90
91 // anything + zero = anything
92 if (bAbs == 0) return a;
93 }
94
95 // Swap a and b if necessary so that a has the larger absolute value.
96 if (bAbs > aAbs) {
97 const temp = aRep;
98 aRep = bRep;
99 bRep = temp;
100 }
101
102 // Extract the exponent and significand from the (possibly swapped) a and b.
103 var aExponent = @intCast(i32, (aRep >> significandBits) & maxExponent);
104 var bExponent = @intCast(i32, (bRep >> significandBits) & maxExponent);
105 var aSignificand = aRep & significandMask;
106 var bSignificand = bRep & significandMask;
107
108 // Normalize any denormals, and adjust the exponent accordingly.
109 if (aExponent == 0) aExponent = normalize(T, &aSignificand);
110 if (bExponent == 0) bExponent = normalize(T, &bSignificand);
111
112 // The sign of the result is the sign of the larger operand, a. If they
113 // have opposite signs, we are performing a subtraction; otherwise addition.
114 const resultSign = aRep & signBit;
115 const subtraction = (aRep ^ bRep) & signBit != 0;
116
117 // Shift the significands to give us round, guard and sticky, and or in the
118 // implicit significand bit. (If we fell through from the denormal path it
119 // was already set by normalize( ), but setting it twice won't hurt
120 // anything.)
121 aSignificand = (aSignificand | implicitBit) << 3;
122 bSignificand = (bSignificand | implicitBit) << 3;
123
124 // Shift the significand of b by the difference in exponents, with a sticky
125 // bottom bit to get rounding correct.
126 const @"align" = @intCast(Z, aExponent - bExponent);
127 if (@"align" != 0) {
128 if (@"align" < typeWidth) {
129 const sticky = if (bSignificand << @intCast(u7, typeWidth - @"align") != 0) Z(1) else 0;
130 bSignificand = (bSignificand >> @truncate(u7, @"align")) | sticky;
131 } else {
132 bSignificand = 1; // sticky; b is known to be non-zero.
133 }
134 }
135 if (subtraction) {
136 aSignificand -= bSignificand;
137 // If a == -b, return +zero.
138 if (aSignificand == 0) return @bitCast(T, Z(0));
139
140 // If partial cancellation occured, we need to left-shift the result
141 // and adjust the exponent:
142 if (aSignificand < implicitBit << 3) {
143 const shift = @intCast(i32, @clz(aSignificand)) - @intCast(i32, @clz(implicitBit << 3));
144 aSignificand <<= @intCast(u7, shift);
145 aExponent -= shift;
146 }
147 } else { // addition
148 aSignificand += bSignificand;
149
150 // If the addition carried up, we need to right-shift the result and
151 // adjust the exponent:
152 if (aSignificand & (implicitBit << 4) != 0) {
153 const sticky = aSignificand & 1;
154 aSignificand = aSignificand >> 1 | sticky;
155 aExponent += 1;
156 }
157 }
158
159 // If we have overflowed the type, return +/- infinity:
160 if (aExponent >= maxExponent) return @bitCast(T, infRep | resultSign);
161
162 if (aExponent <= 0) {
163 // Result is denormal before rounding; the exponent is zero and we
164 // need to shift the significand.
165 const shift = @intCast(Z, 1 - aExponent);
166 const sticky = if (aSignificand << @intCast(u7, typeWidth - shift) != 0) Z(1) else 0;
167 aSignificand = aSignificand >> @intCast(u7, shift | sticky);
168 aExponent = 0;
169 }
170
171 // Low three bits are round, guard, and sticky.
172 const roundGuardSticky = aSignificand & 0x7;
173
174 // Shift the significand into place, and mask off the implicit bit.
175 var result = (aSignificand >> 3) & significandMask;
176
177 // Insert the exponent and sign.
178 result |= @intCast(Z, aExponent) << significandBits;
179 result |= resultSign;
180
181 // Final rounding. The result may overflow to infinity, but that is the
182 // correct result in that case.
183 if (roundGuardSticky > 0x4) result += 1;
184 if (roundGuardSticky == 0x4) result += result & 1;
185
186 return @bitCast(T, result);
187}
188
189test "import addXf3" {
190 _ = @import("addXf3_test.zig");
191}
std/special/compiler_rt/addXf3_test.zig created+85
...@@ -0,0 +1,85 @@
1// Ported from:
2//
3// https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/test/builtins/Unit/addtf3_test.c
4// https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/test/builtins/Unit/subtf3_test.c
5
6const qnan128 = @bitCast(f128, u128(0x7fff800000000000) << 64);
7const inf128 = @bitCast(f128, u128(0x7fff000000000000) << 64);
8
9const __addtf3 = @import("addXf3.zig").__addtf3;
10
11fn test__addtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) void {
12 const x = __addtf3(a, b);
13
14 const rep = @bitCast(u128, x);
15 const hi = @intCast(u64, rep >> 64);
16 const lo = @truncate(u64, rep);
17
18 if (hi == expected_hi and lo == expected_lo) {
19 return;
20 }
21 // test other possible NaN representation (signal NaN)
22 else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {
23 if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and
24 ((hi & 0xffffffffffff) > 0 or lo > 0))
25 {
26 return;
27 }
28 }
29
30 @panic("__addtf3 test failure");
31}
32
33test "addtf3" {
34 test__addtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
35
36 // NaN + any = NaN
37 test__addtf3(@bitCast(f128, (u128(0x7fff000000000000) << 64) | u128(0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
38
39 // inf + inf = inf
40 test__addtf3(inf128, inf128, 0x7fff000000000000, 0x0);
41
42 // inf + any = inf
43 test__addtf3(inf128, 0x1.2335653452436234723489432abcdefp+5, 0x7fff000000000000, 0x0);
44
45 // any + any
46 test__addtf3(0x1.23456734245345543849abcdefp+5, 0x1.edcba52449872455634654321fp-1, 0x40042afc95c8b579, 0x61e58dd6c51eb77c);
47}
48
49const __subtf3 = @import("addXf3.zig").__subtf3;
50
51fn test__subtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) void {
52 const x = __subtf3(a, b);
53
54 const rep = @bitCast(u128, x);
55 const hi = @intCast(u64, rep >> 64);
56 const lo = @truncate(u64, rep);
57
58 if (hi == expected_hi and lo == expected_lo) {
59 return;
60 }
61 // test other possible NaN representation (signal NaN)
62 else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {
63 if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and
64 ((hi & 0xffffffffffff) > 0 or lo > 0))
65 {
66 return;
67 }
68 }
69
70 @panic("__subtf3 test failure");
71}
72
73test "subtf3" {
74 // qNaN - any = qNaN
75 test__subtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
76
77 // NaN + any = NaN
78 test__subtf3(@bitCast(f128, (u128(0x7fff000000000000) << 64) | u128(0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0);
79
80 // inf - any = inf
81 test__subtf3(inf128, 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0);
82
83 // any + any
84 test__subtf3(0x1.234567829a3bcdef5678ade36734p+5, 0x1.ee9d7c52354a6936ab8d7654321fp-1, 0x40041b8af1915166, 0xa44a7bca780a166c);
85}
std/special/compiler_rt/divti3_test.zig+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const __divti3 = @import("divti3.zig").__divti3;1const __divti3 = @import("divti3.zig").__divti3;
2const assert = @import("std").debug.assert;2const testing = @import("std").testing;
33
4fn test__divti3(a: i128, b: i128, expected: i128) void {4fn test__divti3(a: i128, b: i128, expected: i128) void {
5 const x = __divti3(a, b);5 const x = __divti3(a, b);
6 assert(x == expected);6 testing.expect(x == expected);
7}7}
88
9test "divti3" {9test "divti3" {
std/special/compiler_rt/extendXfYf2_test.zig-1
...@@ -1,7 +1,6 @@...@@ -1,7 +1,6 @@
1const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2;1const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2;
2const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2;2const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2;
3const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2;3const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2;
4const assert = @import("std").debug.assert;
54
6fn test__extenddftf2(a: f64, expectedHi: u64, expectedLo: u64) void {5fn test__extenddftf2(a: f64, expectedHi: u64, expectedLo: u64) void {
7 const x = __extenddftf2(a);6 const x = __extenddftf2(a);
std/special/compiler_rt/fixdfdi.zig created+11
...@@ -0,0 +1,11 @@
1const fixint = @import("fixint.zig").fixint;
2const builtin = @import("builtin");
3
4pub extern fn __fixdfdi(a: f64) i64 {
5 @setRuntimeSafety(builtin.is_test);
6 return fixint(f64, i64, a);
7}
8
9test "import fixdfdi" {
10 _ = @import("fixdfdi_test.zig");
11}
std/special/compiler_rt/fixdfdi_test.zig created+66
...@@ -0,0 +1,66 @@
1const __fixdfdi = @import("fixdfdi.zig").__fixdfdi;
2const std = @import("std");
3const math = std.math;
4const testing = std.testing;
5const warn = std.debug.warn;
6
7fn test__fixdfdi(a: f64, expected: i64) void {
8 const x = __fixdfdi(a);
9 //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u64, expected));
10 testing.expect(x == expected);
11}
12
13test "fixdfdi" {
14 //warn("\n");
15
16 test__fixdfdi(-math.f64_max, math.minInt(i64));
17
18 test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
19 test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
20
21 test__fixdfdi(-0x1.0000000000000p+127, -0x8000000000000000);
22 test__fixdfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
23 test__fixdfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
24
25 test__fixdfdi(-0x1.0000000000001p+63, -0x8000000000000000);
26 test__fixdfdi(-0x1.0000000000000p+63, -0x8000000000000000);
27 test__fixdfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
28 test__fixdfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
29
30 test__fixdfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000);
31 test__fixdfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000);
32
33 test__fixdfdi(-2.01, -2);
34 test__fixdfdi(-2.0, -2);
35 test__fixdfdi(-1.99, -1);
36 test__fixdfdi(-1.0, -1);
37 test__fixdfdi(-0.99, 0);
38 test__fixdfdi(-0.5, 0);
39 test__fixdfdi(-math.f64_min, 0);
40 test__fixdfdi(0.0, 0);
41 test__fixdfdi(math.f64_min, 0);
42 test__fixdfdi(0.5, 0);
43 test__fixdfdi(0.99, 0);
44 test__fixdfdi(1.0, 1);
45 test__fixdfdi(1.5, 1);
46 test__fixdfdi(1.99, 1);
47 test__fixdfdi(2.0, 2);
48 test__fixdfdi(2.01, 2);
49
50 test__fixdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
51 test__fixdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
52
53 test__fixdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
54 test__fixdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
55 test__fixdfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
56 test__fixdfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
57
58 test__fixdfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
59 test__fixdfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
60 test__fixdfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
61
62 test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
63 test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
64
65 test__fixdfdi(math.f64_max, math.maxInt(i64));
66}
std/special/compiler_rt/fixdfsi.zig created+11
...@@ -0,0 +1,11 @@
1const fixint = @import("fixint.zig").fixint;
2const builtin = @import("builtin");
3
4pub extern fn __fixdfsi(a: f64) i32 {
5 @setRuntimeSafety(builtin.is_test);
6 return fixint(f64, i32, a);
7}
8
9test "import fixdfsi" {
10 _ = @import("fixdfsi_test.zig");
11}
std/special/compiler_rt/fixdfsi_test.zig created+74
...@@ -0,0 +1,74 @@
1const __fixdfsi = @import("fixdfsi.zig").__fixdfsi;
2const std = @import("std");
3const math = std.math;
4const testing = std.testing;
5const warn = std.debug.warn;
6
7fn test__fixdfsi(a: f64, expected: i32) void {
8 const x = __fixdfsi(a);
9 //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u32, expected));
10 testing.expect(x == expected);
11}
12
13test "fixdfsi" {
14 //warn("\n");
15
16 test__fixdfsi(-math.f64_max, math.minInt(i32));
17
18 test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
19 test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
20
21 test__fixdfsi(-0x1.0000000000000p+127, -0x80000000);
22 test__fixdfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
23 test__fixdfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
24
25 test__fixdfsi(-0x1.0000000000001p+63, -0x80000000);
26 test__fixdfsi(-0x1.0000000000000p+63, -0x80000000);
27 test__fixdfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
28 test__fixdfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
29
30 test__fixdfsi(-0x1.FFFFFEp+62, -0x80000000);
31 test__fixdfsi(-0x1.FFFFFCp+62, -0x80000000);
32
33 test__fixdfsi(-0x1.000000p+31, -0x80000000);
34 test__fixdfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0);
35 test__fixdfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);
36
37 test__fixdfsi(-2.01, -2);
38 test__fixdfsi(-2.0, -2);
39 test__fixdfsi(-1.99, -1);
40 test__fixdfsi(-1.0, -1);
41 test__fixdfsi(-0.99, 0);
42 test__fixdfsi(-0.5, 0);
43 test__fixdfsi(-math.f64_min, 0);
44 test__fixdfsi(0.0, 0);
45 test__fixdfsi(math.f64_min, 0);
46 test__fixdfsi(0.5, 0);
47 test__fixdfsi(0.99, 0);
48 test__fixdfsi(1.0, 1);
49 test__fixdfsi(1.5, 1);
50 test__fixdfsi(1.99, 1);
51 test__fixdfsi(2.0, 2);
52 test__fixdfsi(2.01, 2);
53
54 test__fixdfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
55 test__fixdfsi(0x1.FFFFFFp+30, 0x7FFFFFC0);
56 test__fixdfsi(0x1.000000p+31, 0x7FFFFFFF);
57
58 test__fixdfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);
59 test__fixdfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);
60
61 test__fixdfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
62 test__fixdfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
63 test__fixdfsi(0x1.0000000000000p+63, 0x7FFFFFFF);
64 test__fixdfsi(0x1.0000000000001p+63, 0x7FFFFFFF);
65
66 test__fixdfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
67 test__fixdfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
68 test__fixdfsi(0x1.0000000000000p+127, 0x7FFFFFFF);
69
70 test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
71 test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
72
73 test__fixdfsi(math.f64_max, math.maxInt(i32));
74}
std/special/compiler_rt/fixdfti.zig created+11
...@@ -0,0 +1,11 @@
1const fixint = @import("fixint.zig").fixint;
2const builtin = @import("builtin");
3
4pub extern fn __fixdfti(a: f64) i128 {
5 @setRuntimeSafety(builtin.is_test);
6 return fixint(f64, i128, a);
7}
8
9test "import fixdfti" {
10 _ = @import("fixdfti_test.zig");
11}
std/special/compiler_rt/fixdfti_test.zig created+66
...@@ -0,0 +1,66 @@
1const __fixdfti = @import("fixdfti.zig").__fixdfti;
2const std = @import("std");
3const math = std.math;
4const testing = std.testing;
5const warn = std.debug.warn;
6
7fn test__fixdfti(a: f64, expected: i128) void {
8 const x = __fixdfti(a);
9 //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u64, a), x, x, expected, expected, @bitCast(u128, expected));
10 testing.expect(x == expected);
11}
12
13test "fixdfti" {
14 //warn("\n");
15
16 test__fixdfti(-math.f64_max, math.minInt(i128));
17
18 test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
19 test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
20
21 test__fixdfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
22 test__fixdfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
23 test__fixdfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);
24
25 test__fixdfti(-0x1.0000000000001p+63, -0x8000000000000800);
26 test__fixdfti(-0x1.0000000000000p+63, -0x8000000000000000);
27 test__fixdfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
28 test__fixdfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
29
30 test__fixdfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);
31 test__fixdfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);
32
33 test__fixdfti(-2.01, -2);
34 test__fixdfti(-2.0, -2);
35 test__fixdfti(-1.99, -1);
36 test__fixdfti(-1.0, -1);
37 test__fixdfti(-0.99, 0);
38 test__fixdfti(-0.5, 0);
39 test__fixdfti(-math.f64_min, 0);
40 test__fixdfti(0.0, 0);
41 test__fixdfti(math.f64_min, 0);
42 test__fixdfti(0.5, 0);
43 test__fixdfti(0.99, 0);
44 test__fixdfti(1.0, 1);
45 test__fixdfti(1.5, 1);
46 test__fixdfti(1.99, 1);
47 test__fixdfti(2.0, 2);
48 test__fixdfti(2.01, 2);
49
50 test__fixdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
51 test__fixdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
52
53 test__fixdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
54 test__fixdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
55 test__fixdfti(0x1.0000000000000p+63, 0x8000000000000000);
56 test__fixdfti(0x1.0000000000001p+63, 0x8000000000000800);
57
58 test__fixdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
59 test__fixdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
60 test__fixdfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
61
62 test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
63 test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
64
65 test__fixdfti(math.f64_max, math.maxInt(i128));
66}
std/special/compiler_rt/fixint.zig created+74
...@@ -0,0 +1,74 @@
1const is_test = @import("builtin").is_test;
2const std = @import("std");
3const math = std.math;
4const Log2Int = std.math.Log2Int;
5const maxInt = std.math.maxInt;
6const minInt = std.math.minInt;
7
8const DBG = false;
9
10pub fn fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t) fixint_t {
11 @setRuntimeSafety(is_test);
12
13 const rep_t = switch (fp_t) {
14 f32 => u32,
15 f64 => u64,
16 f128 => u128,
17 else => unreachable,
18 };
19 const significandBits = switch (fp_t) {
20 f32 => 23,
21 f64 => 52,
22 f128 => 112,
23 else => unreachable,
24 };
25
26 const typeWidth = rep_t.bit_count;
27 const exponentBits = (typeWidth - significandBits - 1);
28 const signBit = (rep_t(1) << (significandBits + exponentBits));
29 const maxExponent = ((1 << exponentBits) - 1);
30 const exponentBias = (maxExponent >> 1);
31
32 const implicitBit = (rep_t(1) << significandBits);
33 const significandMask = (implicitBit - 1);
34
35 // Break a into sign, exponent, significand
36 const aRep: rep_t = @bitCast(rep_t, a);
37 const absMask = signBit - 1;
38 const aAbs: rep_t = aRep & absMask;
39
40 const negative = (aRep & signBit) != 0;
41 const exponent = @intCast(i32, aAbs >> significandBits) - exponentBias;
42 const significand: rep_t = (aAbs & significandMask) | implicitBit;
43
44 // If exponent is negative, the uint_result is zero.
45 if (exponent < 0) return 0;
46
47 // The unsigned result needs to be large enough to handle an fixint_t or rep_t
48 const fixuint_t = @IntType(false, fixint_t.bit_count);
49 const UintResultType = if (fixint_t.bit_count > rep_t.bit_count) fixuint_t else rep_t;
50 var uint_result: UintResultType = undefined;
51
52 // If the value is too large for the integer type, saturate.
53 if (@intCast(usize, exponent) >= fixint_t.bit_count) {
54 return if (negative) fixint_t(minInt(fixint_t)) else fixint_t(maxInt(fixint_t));
55 }
56
57 // If 0 <= exponent < significandBits, right shift else left shift
58 if (exponent < significandBits) {
59 uint_result = @intCast(UintResultType, significand) >> @intCast(Log2Int(UintResultType), significandBits - exponent);
60 } else {
61 uint_result = @intCast(UintResultType, significand) << @intCast(Log2Int(UintResultType), exponent - significandBits);
62 }
63
64 // Cast to final signed result
65 if (negative) {
66 return if (uint_result >= -math.minInt(fixint_t)) math.minInt(fixint_t) else -@intCast(fixint_t, uint_result);
67 } else {
68 return if (uint_result >= math.maxInt(fixint_t)) math.maxInt(fixint_t) else @intCast(fixint_t, uint_result);
69 }
70}
71
72test "import fixint" {
73 _ = @import("fixint_test.zig");
74}
std/special/compiler_rt/fixint_test.zig created+152
...@@ -0,0 +1,152 @@
1const is_test = @import("builtin").is_test;
2const std = @import("std");
3const math = std.math;
4const testing = std.testing;
5const warn = std.debug.warn;
6
7const fixint = @import("fixint.zig").fixint;
8
9fn test__fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t, expected: fixint_t) void {
10 const x = fixint(fp_t, fixint_t, a);
11 //warn("a={} x={}:{x} expected={}:{x})\n", a, x, x, expected, expected);
12 testing.expect(x == expected);
13}
14
15test "fixint.i1" {
16 test__fixint(f32, i1, -math.inf_f32, -1);
17 test__fixint(f32, i1, -math.f32_max, -1);
18 test__fixint(f32, i1, -2.0, -1);
19 test__fixint(f32, i1, -1.1, -1);
20 test__fixint(f32, i1, -1.0, -1);
21 test__fixint(f32, i1, -0.9, 0);
22 test__fixint(f32, i1, -0.1, 0);
23 test__fixint(f32, i1, -math.f32_min, 0);
24 test__fixint(f32, i1, -0.0, 0);
25 test__fixint(f32, i1, 0.0, 0);
26 test__fixint(f32, i1, math.f32_min, 0);
27 test__fixint(f32, i1, 0.1, 0);
28 test__fixint(f32, i1, 0.9, 0);
29 test__fixint(f32, i1, 1.0, 0);
30 test__fixint(f32, i1, 2.0, 0);
31 test__fixint(f32, i1, math.f32_max, 0);
32 test__fixint(f32, i1, math.inf_f32, 0);
33}
34
35test "fixint.i2" {
36 test__fixint(f32, i2, -math.inf_f32, -2);
37 test__fixint(f32, i2, -math.f32_max, -2);
38 test__fixint(f32, i2, -2.0, -2);
39 test__fixint(f32, i2, -1.9, -1);
40 test__fixint(f32, i2, -1.1, -1);
41 test__fixint(f32, i2, -1.0, -1);
42 test__fixint(f32, i2, -0.9, 0);
43 test__fixint(f32, i2, -0.1, 0);
44 test__fixint(f32, i2, -math.f32_min, 0);
45 test__fixint(f32, i2, -0.0, 0);
46 test__fixint(f32, i2, 0.0, 0);
47 test__fixint(f32, i2, math.f32_min, 0);
48 test__fixint(f32, i2, 0.1, 0);
49 test__fixint(f32, i2, 0.9, 0);
50 test__fixint(f32, i2, 1.0, 1);
51 test__fixint(f32, i2, 2.0, 1);
52 test__fixint(f32, i2, math.f32_max, 1);
53 test__fixint(f32, i2, math.inf_f32, 1);
54}
55
56test "fixint.i3" {
57 test__fixint(f32, i3, -math.inf_f32, -4);
58 test__fixint(f32, i3, -math.f32_max, -4);
59 test__fixint(f32, i3, -4.0, -4);
60 test__fixint(f32, i3, -3.0, -3);
61 test__fixint(f32, i3, -2.0, -2);
62 test__fixint(f32, i3, -1.9, -1);
63 test__fixint(f32, i3, -1.1, -1);
64 test__fixint(f32, i3, -1.0, -1);
65 test__fixint(f32, i3, -0.9, 0);
66 test__fixint(f32, i3, -0.1, 0);
67 test__fixint(f32, i3, -math.f32_min, 0);
68 test__fixint(f32, i3, -0.0, 0);
69 test__fixint(f32, i3, 0.0, 0);
70 test__fixint(f32, i3, math.f32_min, 0);
71 test__fixint(f32, i3, 0.1, 0);
72 test__fixint(f32, i3, 0.9, 0);
73 test__fixint(f32, i3, 1.0, 1);
74 test__fixint(f32, i3, 2.0, 2);
75 test__fixint(f32, i3, 3.0, 3);
76 test__fixint(f32, i3, 4.0, 3);
77 test__fixint(f32, i3, math.f32_max, 3);
78 test__fixint(f32, i3, math.inf_f32, 3);
79}
80
81test "fixint.i32" {
82 test__fixint(f64, i32, -math.inf_f64, math.minInt(i32));
83 test__fixint(f64, i32, -math.f64_max, math.minInt(i32));
84 test__fixint(f64, i32, f64(math.minInt(i32)), math.minInt(i32));
85 test__fixint(f64, i32, f64(math.minInt(i32))+1, math.minInt(i32)+1);
86 test__fixint(f64, i32, -2.0, -2);
87 test__fixint(f64, i32, -1.9, -1);
88 test__fixint(f64, i32, -1.1, -1);
89 test__fixint(f64, i32, -1.0, -1);
90 test__fixint(f64, i32, -0.9, 0);
91 test__fixint(f64, i32, -0.1, 0);
92 test__fixint(f64, i32, -math.f32_min, 0);
93 test__fixint(f64, i32, -0.0, 0);
94 test__fixint(f64, i32, 0.0, 0);
95 test__fixint(f64, i32, math.f32_min, 0);
96 test__fixint(f64, i32, 0.1, 0);
97 test__fixint(f64, i32, 0.9, 0);
98 test__fixint(f64, i32, 1.0, 1);
99 test__fixint(f64, i32, f64(math.maxInt(i32))-1, math.maxInt(i32)-1);
100 test__fixint(f64, i32, f64(math.maxInt(i32)), math.maxInt(i32));
101 test__fixint(f64, i32, math.f64_max, math.maxInt(i32));
102 test__fixint(f64, i32, math.inf_f64, math.maxInt(i32));
103}
104
105test "fixint.i64" {
106 test__fixint(f64, i64, -math.inf_f64, math.minInt(i64));
107 test__fixint(f64, i64, -math.f64_max, math.minInt(i64));
108 test__fixint(f64, i64, f64(math.minInt(i64)), math.minInt(i64));
109 test__fixint(f64, i64, f64(math.minInt(i64))+1, math.minInt(i64));
110 test__fixint(f64, i64, f64(math.minInt(i64)/2), math.minInt(i64)/2);
111 test__fixint(f64, i64, -2.0, -2);
112 test__fixint(f64, i64, -1.9, -1);
113 test__fixint(f64, i64, -1.1, -1);
114 test__fixint(f64, i64, -1.0, -1);
115 test__fixint(f64, i64, -0.9, 0);
116 test__fixint(f64, i64, -0.1, 0);
117 test__fixint(f64, i64, -math.f32_min, 0);
118 test__fixint(f64, i64, -0.0, 0);
119 test__fixint(f64, i64, 0.0, 0);
120 test__fixint(f64, i64, math.f32_min, 0);
121 test__fixint(f64, i64, 0.1, 0);
122 test__fixint(f64, i64, 0.9, 0);
123 test__fixint(f64, i64, 1.0, 1);
124 test__fixint(f64, i64, f64(math.maxInt(i64))-1, math.maxInt(i64));
125 test__fixint(f64, i64, f64(math.maxInt(i64)), math.maxInt(i64));
126 test__fixint(f64, i64, math.f64_max, math.maxInt(i64));
127 test__fixint(f64, i64, math.inf_f64, math.maxInt(i64));
128}
129
130test "fixint.i128" {
131 test__fixint(f64, i128, -math.inf_f64, math.minInt(i128));
132 test__fixint(f64, i128, -math.f64_max, math.minInt(i128));
133 test__fixint(f64, i128, f64(math.minInt(i128)), math.minInt(i128));
134 test__fixint(f64, i128, f64(math.minInt(i128))+1, math.minInt(i128));
135 test__fixint(f64, i128, -2.0, -2);
136 test__fixint(f64, i128, -1.9, -1);
137 test__fixint(f64, i128, -1.1, -1);
138 test__fixint(f64, i128, -1.0, -1);
139 test__fixint(f64, i128, -0.9, 0);
140 test__fixint(f64, i128, -0.1, 0);
141 test__fixint(f64, i128, -math.f32_min, 0);
142 test__fixint(f64, i128, -0.0, 0);
143 test__fixint(f64, i128, 0.0, 0);
144 test__fixint(f64, i128, math.f32_min, 0);
145 test__fixint(f64, i128, 0.1, 0);
146 test__fixint(f64, i128, 0.9, 0);
147 test__fixint(f64, i128, 1.0, 1);
148 test__fixint(f64, i128, f64(math.maxInt(i128))-1, math.maxInt(i128));
149 test__fixint(f64, i128, f64(math.maxInt(i128)), math.maxInt(i128));
150 test__fixint(f64, i128, math.f64_max, math.maxInt(i128));
151 test__fixint(f64, i128, math.inf_f64, math.maxInt(i128));
152}
std/special/compiler_rt/fixsfdi.zig created+11
...@@ -0,0 +1,11 @@
1const fixint = @import("fixint.zig").fixint;
2const builtin = @import("builtin");
3
4pub extern fn __fixsfdi(a: f32) i64 {
5 @setRuntimeSafety(builtin.is_test);
6 return fixint(f32, i64, a);
7}
8
9test "import fixsfdi" {
10 _ = @import("fixsfdi_test.zig");
11}
std/special/compiler_rt/fixsfdi_test.zig created+68
...@@ -0,0 +1,68 @@
1const __fixsfdi = @import("fixsfdi.zig").__fixsfdi;
2const std = @import("std");
3const math = std.math;
4const testing = std.testing;
5const warn = std.debug.warn;
6
7fn test__fixsfdi(a: f32, expected: i64) void {
8 const x = __fixsfdi(a);
9 //warn("a={}:{x} x={}:{x} expected={}:{x}:u32({x})\n", a, @bitCast(u32, a), x, x, expected, expected, @bitCast(u64, expected));
10 testing.expect(x == expected);
11}
12
13test "fixsfdi" {
14 //warn("\n");
15
16 test__fixsfdi(-math.f32_max, math.minInt(i64));
17
18 test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
19 test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
20
21 test__fixsfdi(-0x1.0000000000000p+127, -0x8000000000000000);
22 test__fixsfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
23 test__fixsfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
24
25 test__fixsfdi(-0x1.0000000000001p+63, -0x8000000000000000);
26 test__fixsfdi(-0x1.0000000000000p+63, -0x8000000000000000);
27 test__fixsfdi(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000);
28 test__fixsfdi(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000);
29
30 test__fixsfdi(-0x1.FFFFFFp+62, -0x8000000000000000);
31 test__fixsfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000);
32 test__fixsfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000);
33
34 test__fixsfdi(-2.01, -2);
35 test__fixsfdi(-2.0, -2);
36 test__fixsfdi(-1.99, -1);
37 test__fixsfdi(-1.0, -1);
38 test__fixsfdi(-0.99, 0);
39 test__fixsfdi(-0.5, 0);
40 test__fixsfdi(-math.f32_min, 0);
41 test__fixsfdi(0.0, 0);
42 test__fixsfdi(math.f32_min, 0);
43 test__fixsfdi(0.5, 0);
44 test__fixsfdi(0.99, 0);
45 test__fixsfdi(1.0, 1);
46 test__fixsfdi(1.5, 1);
47 test__fixsfdi(1.99, 1);
48 test__fixsfdi(2.0, 2);
49 test__fixsfdi(2.01, 2);
50
51 test__fixsfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
52 test__fixsfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
53 test__fixsfdi(0x1.FFFFFFp+62, 0x7FFFFFFFFFFFFFFF);
54
55 test__fixsfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFFFFF);
56 test__fixsfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFFFF);
57 test__fixsfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
58 test__fixsfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
59
60 test__fixsfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
61 test__fixsfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
62 test__fixsfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
63
64 test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
65 test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
66
67 test__fixsfdi(math.f64_max, math.maxInt(i64));
68}
std/special/compiler_rt/fixsfsi.zig created+11
...@@ -0,0 +1,11 @@
1const fixint = @import("fixint.zig").fixint;
2const builtin = @import("builtin");
3
4pub extern fn __fixsfsi(a: f32) i32 {
5 @setRuntimeSafety(builtin.is_test);
6 return fixint(f32, i32, a);
7}
8
9test "import fixsfsi" {
10 _ = @import("fixsfsi_test.zig");
11}
std/special/compiler_rt/fixsfsi_test.zig created+76
...@@ -0,0 +1,76 @@
1const __fixsfsi = @import("fixsfsi.zig").__fixsfsi;
2const std = @import("std");
3const math = std.math;
4const testing = std.testing;
5const warn = std.debug.warn;
6
7fn test__fixsfsi(a: f32, expected: i32) void {
8 const x = __fixsfsi(a);
9 //warn("a={}:{x} x={}:{x} expected={}:{x}:u32({x})\n", a, @bitCast(u32, a), x, x, expected, expected, @bitCast(u32, expected));
10 testing.expect(x == expected);
11}
12
13test "fixsfsi" {
14 //warn("\n");
15
16 test__fixsfsi(-math.f32_max, math.minInt(i32));
17
18 test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
19 test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
20
21 test__fixsfsi(-0x1.0000000000000p+127, -0x80000000);
22 test__fixsfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
23 test__fixsfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
24
25 test__fixsfsi(-0x1.0000000000001p+63, -0x80000000);
26 test__fixsfsi(-0x1.0000000000000p+63, -0x80000000);
27 test__fixsfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
28 test__fixsfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
29
30 test__fixsfsi(-0x1.FFFFFEp+62, -0x80000000);
31 test__fixsfsi(-0x1.FFFFFCp+62, -0x80000000);
32
33 test__fixsfsi(-0x1.000000p+31, -0x80000000);
34 test__fixsfsi(-0x1.FFFFFFp+30, -0x80000000);
35 test__fixsfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);
36 test__fixsfsi(-0x1.FFFFFCp+30, -0x7FFFFF00);
37
38 test__fixsfsi(-2.01, -2);
39 test__fixsfsi(-2.0, -2);
40 test__fixsfsi(-1.99, -1);
41 test__fixsfsi(-1.0, -1);
42 test__fixsfsi(-0.99, 0);
43 test__fixsfsi(-0.5, 0);
44 test__fixsfsi(-math.f32_min, 0);
45 test__fixsfsi(0.0, 0);
46 test__fixsfsi(math.f32_min, 0);
47 test__fixsfsi(0.5, 0);
48 test__fixsfsi(0.99, 0);
49 test__fixsfsi(1.0, 1);
50 test__fixsfsi(1.5, 1);
51 test__fixsfsi(1.99, 1);
52 test__fixsfsi(2.0, 2);
53 test__fixsfsi(2.01, 2);
54
55 test__fixsfsi(0x1.FFFFFCp+30, 0x7FFFFF00);
56 test__fixsfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
57 test__fixsfsi(0x1.FFFFFFp+30, 0x7FFFFFFF);
58 test__fixsfsi(0x1.000000p+31, 0x7FFFFFFF);
59
60 test__fixsfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);
61 test__fixsfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);
62
63 test__fixsfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
64 test__fixsfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
65 test__fixsfsi(0x1.0000000000000p+63, 0x7FFFFFFF);
66 test__fixsfsi(0x1.0000000000001p+63, 0x7FFFFFFF);
67
68 test__fixsfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
69 test__fixsfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
70 test__fixsfsi(0x1.0000000000000p+127, 0x7FFFFFFF);
71
72 test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
73 test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
74
75 test__fixsfsi(math.f32_max, math.maxInt(i32));
76}
std/special/compiler_rt/fixsfti.zig created+11
...@@ -0,0 +1,11 @@
1const fixint = @import("fixint.zig").fixint;
2const builtin = @import("builtin");
3
4pub extern fn __fixsfti(a: f32) i128 {
5 @setRuntimeSafety(builtin.is_test);
6 return fixint(f32, i128, a);
7}
8
9test "import fixsfti" {
10 _ = @import("fixsfti_test.zig");
11}
std/special/compiler_rt/fixsfti_test.zig created+84
...@@ -0,0 +1,84 @@
1const __fixsfti = @import("fixsfti.zig").__fixsfti;
2const std = @import("std");
3const math = std.math;
4const testing = std.testing;
5const warn = std.debug.warn;
6
7fn test__fixsfti(a: f32, expected: i128) void {
8 const x = __fixsfti(a);
9 //warn("a={}:{x} x={}:{x} expected={}:{x}:u128({x})\n", a, @bitCast(u32, a), x, x, expected, expected, @bitCast(u128, expected));
10 testing.expect(x == expected);
11}
12
13test "fixsfti" {
14 //warn("\n");
15
16 test__fixsfti(-math.f32_max, math.minInt(i128));
17
18 test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
19 test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
20
21 test__fixsfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
22 test__fixsfti(-0x1.FFFFFFFFFFFFFp+126, -0x80000000000000000000000000000000);
23 test__fixsfti(-0x1.FFFFFFFFFFFFEp+126, -0x80000000000000000000000000000000);
24 test__fixsfti(-0x1.FFFFFF0000000p+126, -0x80000000000000000000000000000000);
25 test__fixsfti(-0x1.FFFFFE0000000p+126, -0x7FFFFF80000000000000000000000000);
26 test__fixsfti(-0x1.FFFFFC0000000p+126, -0x7FFFFF00000000000000000000000000);
27
28 test__fixsfti(-0x1.0000000000001p+63, -0x8000000000000000);
29 test__fixsfti(-0x1.0000000000000p+63, -0x8000000000000000);
30 test__fixsfti(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000);
31 test__fixsfti(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000);
32
33 test__fixsfti(-0x1.FFFFFFp+62, -0x8000000000000000);
34 test__fixsfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);
35 test__fixsfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);
36
37 test__fixsfti(-0x1.000000p+31, -0x80000000);
38 test__fixsfti(-0x1.FFFFFFp+30, -0x80000000);
39 test__fixsfti(-0x1.FFFFFEp+30, -0x7FFFFF80);
40 test__fixsfti(-0x1.FFFFFCp+30, -0x7FFFFF00);
41
42 test__fixsfti(-2.01, -2);
43 test__fixsfti(-2.0, -2);
44 test__fixsfti(-1.99, -1);
45 test__fixsfti(-1.0, -1);
46 test__fixsfti(-0.99, 0);
47 test__fixsfti(-0.5, 0);
48 test__fixsfti(-math.f32_min, 0);
49 test__fixsfti(0.0, 0);
50 test__fixsfti(math.f32_min, 0);
51 test__fixsfti(0.5, 0);
52 test__fixsfti(0.99, 0);
53 test__fixsfti(1.0, 1);
54 test__fixsfti(1.5, 1);
55 test__fixsfti(1.99, 1);
56 test__fixsfti(2.0, 2);
57 test__fixsfti(2.01, 2);
58
59 test__fixsfti(0x1.FFFFFCp+30, 0x7FFFFF00);
60 test__fixsfti(0x1.FFFFFEp+30, 0x7FFFFF80);
61 test__fixsfti(0x1.FFFFFFp+30, 0x80000000);
62 test__fixsfti(0x1.000000p+31, 0x80000000);
63
64 test__fixsfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
65 test__fixsfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
66 test__fixsfti(0x1.FFFFFFp+62, 0x8000000000000000);
67
68 test__fixsfti(0x1.FFFFFFFFFFFFEp+62, 0x8000000000000000);
69 test__fixsfti(0x1.FFFFFFFFFFFFFp+62, 0x8000000000000000);
70 test__fixsfti(0x1.0000000000000p+63, 0x8000000000000000);
71 test__fixsfti(0x1.0000000000001p+63, 0x8000000000000000);
72
73 test__fixsfti(0x1.FFFFFC0000000p+126, 0x7FFFFF00000000000000000000000000);
74 test__fixsfti(0x1.FFFFFE0000000p+126, 0x7FFFFF80000000000000000000000000);
75 test__fixsfti(0x1.FFFFFF0000000p+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
76 test__fixsfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
77 test__fixsfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
78 test__fixsfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
79
80 test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
81 test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
82
83 test__fixsfti(math.f32_max, math.maxInt(i128));
84}
std/special/compiler_rt/fixtfdi.zig created+11
...@@ -0,0 +1,11 @@
1const fixint = @import("fixint.zig").fixint;
2const builtin = @import("builtin");
3
4pub extern fn __fixtfdi(a: f128) i64 {
5 @setRuntimeSafety(builtin.is_test);
6 return fixint(f128, i64, a);
7}
8
9test "import fixtfdi" {
10 _ = @import("fixtfdi_test.zig");
11}
std/special/compiler_rt/fixtfdi_test.zig created+76
...@@ -0,0 +1,76 @@
1const __fixtfdi = @import("fixtfdi.zig").__fixtfdi;
2const std = @import("std");
3const math = std.math;
4const testing = std.testing;
5const warn = std.debug.warn;
6
7fn test__fixtfdi(a: f128, expected: i64) void {
8 const x = __fixtfdi(a);
9 //warn("a={}:{x} x={}:{x} expected={}:{x}:u64({x})\n", a, @bitCast(u128, a), x, x, expected, expected, @bitCast(u64, expected));
10 testing.expect(x == expected);
11}
12
13test "fixtfdi" {
14 //warn("\n");
15
16 test__fixtfdi(-math.f128_max, math.minInt(i64));
17
18 test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64));
19 test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000);
20
21 test__fixtfdi(-0x1.0000000000000p+127, -0x8000000000000000);
22 test__fixtfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000);
23 test__fixtfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000);
24
25 test__fixtfdi(-0x1.0000000000001p+63, -0x8000000000000000);
26 test__fixtfdi(-0x1.0000000000000p+63, -0x8000000000000000);
27 test__fixtfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
28 test__fixtfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
29
30 test__fixtfdi(-0x1.FFFFFEp+62, -0x7FFFFF8000000000);
31 test__fixtfdi(-0x1.FFFFFCp+62, -0x7FFFFF0000000000);
32
33 test__fixtfdi(-0x1.000000p+31, -0x80000000);
34 test__fixtfdi(-0x1.FFFFFFp+30, -0x7FFFFFC0);
35 test__fixtfdi(-0x1.FFFFFEp+30, -0x7FFFFF80);
36 test__fixtfdi(-0x1.FFFFFCp+30, -0x7FFFFF00);
37
38 test__fixtfdi(-2.01, -2);
39 test__fixtfdi(-2.0, -2);
40 test__fixtfdi(-1.99, -1);
41 test__fixtfdi(-1.0, -1);
42 test__fixtfdi(-0.99, 0);
43 test__fixtfdi(-0.5, 0);
44 test__fixtfdi(-math.f64_min, 0);
45 test__fixtfdi(0.0, 0);
46 test__fixtfdi(math.f64_min, 0);
47 test__fixtfdi(0.5, 0);
48 test__fixtfdi(0.99, 0);
49 test__fixtfdi(1.0, 1);
50 test__fixtfdi(1.5, 1);
51 test__fixtfdi(1.99, 1);
52 test__fixtfdi(2.0, 2);
53 test__fixtfdi(2.01, 2);
54
55 test__fixtfdi(0x1.FFFFFCp+30, 0x7FFFFF00);
56 test__fixtfdi(0x1.FFFFFEp+30, 0x7FFFFF80);
57 test__fixtfdi(0x1.FFFFFFp+30, 0x7FFFFFC0);
58 test__fixtfdi(0x1.000000p+31, 0x80000000);
59
60 test__fixtfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
61 test__fixtfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
62
63 test__fixtfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
64 test__fixtfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
65 test__fixtfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF);
66 test__fixtfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF);
67
68 test__fixtfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF);
69 test__fixtfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF);
70 test__fixtfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF);
71
72 test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF);
73 test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64));
74
75 test__fixtfdi(math.f128_max, math.maxInt(i64));
76}
std/special/compiler_rt/fixtfsi.zig created+11
...@@ -0,0 +1,11 @@
1const fixint = @import("fixint.zig").fixint;
2const builtin = @import("builtin");
3
4pub extern fn __fixtfsi(a: f128) i32 {
5 @setRuntimeSafety(builtin.is_test);
6 return fixint(f128, i32, a);
7}
8
9test "import fixtfsi" {
10 _ = @import("fixtfsi_test.zig");
11}
std/special/compiler_rt/fixtfsi_test.zig created+76
...@@ -0,0 +1,76 @@
1const __fixtfsi = @import("fixtfsi.zig").__fixtfsi;
2const std = @import("std");
3const math = std.math;
4const testing = std.testing;
5const warn = std.debug.warn;
6
7fn test__fixtfsi(a: f128, expected: i32) void {
8 const x = __fixtfsi(a);
9 //warn("a={}:{x} x={}:{x} expected={}:{x}:u32({x})\n", a, @bitCast(u128, a), x, x, expected, expected, @bitCast(u32, expected));
10 testing.expect(x == expected);
11}
12
13test "fixtfsi" {
14 //warn("\n");
15
16 test__fixtfsi(-math.f128_max, math.minInt(i32));
17
18 test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32));
19 test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000);
20
21 test__fixtfsi(-0x1.0000000000000p+127, -0x80000000);
22 test__fixtfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000);
23 test__fixtfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000);
24
25 test__fixtfsi(-0x1.0000000000001p+63, -0x80000000);
26 test__fixtfsi(-0x1.0000000000000p+63, -0x80000000);
27 test__fixtfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000);
28 test__fixtfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000);
29
30 test__fixtfsi(-0x1.FFFFFEp+62, -0x80000000);
31 test__fixtfsi(-0x1.FFFFFCp+62, -0x80000000);
32
33 test__fixtfsi(-0x1.000000p+31, -0x80000000);
34 test__fixtfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0);
35 test__fixtfsi(-0x1.FFFFFEp+30, -0x7FFFFF80);
36 test__fixtfsi(-0x1.FFFFFCp+30, -0x7FFFFF00);
37
38 test__fixtfsi(-2.01, -2);
39 test__fixtfsi(-2.0, -2);
40 test__fixtfsi(-1.99, -1);
41 test__fixtfsi(-1.0, -1);
42 test__fixtfsi(-0.99, 0);
43 test__fixtfsi(-0.5, 0);
44 test__fixtfsi(-math.f32_min, 0);
45 test__fixtfsi(0.0, 0);
46 test__fixtfsi(math.f32_min, 0);
47 test__fixtfsi(0.5, 0);
48 test__fixtfsi(0.99, 0);
49 test__fixtfsi(1.0, 1);
50 test__fixtfsi(1.5, 1);
51 test__fixtfsi(1.99, 1);
52 test__fixtfsi(2.0, 2);
53 test__fixtfsi(2.01, 2);
54
55 test__fixtfsi(0x1.FFFFFCp+30, 0x7FFFFF00);
56 test__fixtfsi(0x1.FFFFFEp+30, 0x7FFFFF80);
57 test__fixtfsi(0x1.FFFFFFp+30, 0x7FFFFFC0);
58 test__fixtfsi(0x1.000000p+31, 0x7FFFFFFF);
59
60 test__fixtfsi(0x1.FFFFFCp+62, 0x7FFFFFFF);
61 test__fixtfsi(0x1.FFFFFEp+62, 0x7FFFFFFF);
62
63 test__fixtfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF);
64 test__fixtfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF);
65 test__fixtfsi(0x1.0000000000000p+63, 0x7FFFFFFF);
66 test__fixtfsi(0x1.0000000000001p+63, 0x7FFFFFFF);
67
68 test__fixtfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF);
69 test__fixtfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF);
70 test__fixtfsi(0x1.0000000000000p+127, 0x7FFFFFFF);
71
72 test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF);
73 test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32));
74
75 test__fixtfsi(math.f128_max, math.maxInt(i32));
76}
std/special/compiler_rt/fixtfti.zig created+11
...@@ -0,0 +1,11 @@
1const fixint = @import("fixint.zig").fixint;
2const builtin = @import("builtin");
3
4pub extern fn __fixtfti(a: f128) i128 {
5 @setRuntimeSafety(builtin.is_test);
6 return fixint(f128, i128, a);
7}
8
9test "import fixtfti" {
10 _ = @import("fixtfti_test.zig");
11}
std/special/compiler_rt/fixtfti_test.zig created+66
...@@ -0,0 +1,66 @@
1const __fixtfti = @import("fixtfti.zig").__fixtfti;
2const std = @import("std");
3const math = std.math;
4const testing = std.testing;
5const warn = std.debug.warn;
6
7fn test__fixtfti(a: f128, expected: i128) void {
8 const x = __fixtfti(a);
9 //warn("a={}:{x} x={}:{x} expected={}:{x}:u128({x})\n", a, @bitCast(u128, a), x, x, expected, expected, @bitCast(u128, expected));
10 testing.expect(x == expected);
11}
12
13test "fixtfti" {
14 //warn("\n");
15
16 test__fixtfti(-math.f128_max, math.minInt(i128));
17
18 test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128));
19 test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000);
20
21 test__fixtfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000);
22 test__fixtfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000);
23 test__fixtfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000);
24
25 test__fixtfti(-0x1.0000000000001p+63, -0x8000000000000800);
26 test__fixtfti(-0x1.0000000000000p+63, -0x8000000000000000);
27 test__fixtfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00);
28 test__fixtfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800);
29
30 test__fixtfti(-0x1.FFFFFEp+62, -0x7fffff8000000000);
31 test__fixtfti(-0x1.FFFFFCp+62, -0x7fffff0000000000);
32
33 test__fixtfti(-2.01, -2);
34 test__fixtfti(-2.0, -2);
35 test__fixtfti(-1.99, -1);
36 test__fixtfti(-1.0, -1);
37 test__fixtfti(-0.99, 0);
38 test__fixtfti(-0.5, 0);
39 test__fixtfti(-math.f128_min, 0);
40 test__fixtfti(0.0, 0);
41 test__fixtfti(math.f128_min, 0);
42 test__fixtfti(0.5, 0);
43 test__fixtfti(0.99, 0);
44 test__fixtfti(1.0, 1);
45 test__fixtfti(1.5, 1);
46 test__fixtfti(1.99, 1);
47 test__fixtfti(2.0, 2);
48 test__fixtfti(2.01, 2);
49
50 test__fixtfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000);
51 test__fixtfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000);
52
53 test__fixtfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800);
54 test__fixtfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00);
55 test__fixtfti(0x1.0000000000000p+63, 0x8000000000000000);
56 test__fixtfti(0x1.0000000000001p+63, 0x8000000000000800);
57
58 test__fixtfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000);
59 test__fixtfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000);
60 test__fixtfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
61
62 test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
63 test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128));
64
65 test__fixtfti(math.f128_max, math.maxInt(i128));
66}
std/special/compiler_rt/fixunsdfdi_test.zig+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi;1const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi;
2const assert = @import("std").debug.assert;2const testing = @import("std").testing;
33
4fn test__fixunsdfdi(a: f64, expected: u64) void {4fn test__fixunsdfdi(a: f64, expected: u64) void {
5 const x = __fixunsdfdi(a);5 const x = __fixunsdfdi(a);
6 assert(x == expected);6 testing.expect(x == expected);
7}7}
88
9test "fixunsdfdi" {9test "fixunsdfdi" {
std/special/compiler_rt/fixunsdfsi_test.zig+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi;1const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi;
2const assert = @import("std").debug.assert;2const testing = @import("std").testing;
33
4fn test__fixunsdfsi(a: f64, expected: u32) void {4fn test__fixunsdfsi(a: f64, expected: u32) void {
5 const x = __fixunsdfsi(a);5 const x = __fixunsdfsi(a);
6 assert(x == expected);6 testing.expect(x == expected);
7}7}
88
9test "fixunsdfsi" {9test "fixunsdfsi" {
std/special/compiler_rt/fixunsdfti_test.zig+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti;1const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti;
2const assert = @import("std").debug.assert;2const testing = @import("std").testing;
33
4fn test__fixunsdfti(a: f64, expected: u128) void {4fn test__fixunsdfti(a: f64, expected: u128) void {
5 const x = __fixunsdfti(a);5 const x = __fixunsdfti(a);
6 assert(x == expected);6 testing.expect(x == expected);
7}7}
88
9test "fixunsdfti" {9test "fixunsdfti" {
std/special/compiler_rt/fixunssfdi_test.zig+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi;1const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi;
2const assert = @import("std").debug.assert;2const testing = @import("std").testing;
33
4fn test__fixunssfdi(a: f32, expected: u64) void {4fn test__fixunssfdi(a: f32, expected: u64) void {
5 const x = __fixunssfdi(a);5 const x = __fixunssfdi(a);
6 assert(x == expected);6 testing.expect(x == expected);
7}7}
88
9test "fixunssfdi" {9test "fixunssfdi" {
std/special/compiler_rt/fixunssfsi_test.zig+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi;1const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi;
2const assert = @import("std").debug.assert;2const testing = @import("std").testing;
33
4fn test__fixunssfsi(a: f32, expected: u32) void {4fn test__fixunssfsi(a: f32, expected: u32) void {
5 const x = __fixunssfsi(a);5 const x = __fixunssfsi(a);
6 assert(x == expected);6 testing.expect(x == expected);
7}7}
88
9test "fixunssfsi" {9test "fixunssfsi" {
std/special/compiler_rt/fixunssfti_test.zig+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const __fixunssfti = @import("fixunssfti.zig").__fixunssfti;1const __fixunssfti = @import("fixunssfti.zig").__fixunssfti;
2const assert = @import("std").debug.assert;2const testing = @import("std").testing;
33
4fn test__fixunssfti(a: f32, expected: u128) void {4fn test__fixunssfti(a: f32, expected: u128) void {
5 const x = __fixunssfti(a);5 const x = __fixunssfti(a);
6 assert(x == expected);6 testing.expect(x == expected);
7}7}
88
9test "fixunssfti" {9test "fixunssfti" {
std/special/compiler_rt/fixunstfdi_test.zig+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi;1const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi;
2const assert = @import("std").debug.assert;2const testing = @import("std").testing;
33
4fn test__fixunstfdi(a: f128, expected: u64) void {4fn test__fixunstfdi(a: f128, expected: u64) void {
5 const x = __fixunstfdi(a);5 const x = __fixunstfdi(a);
6 assert(x == expected);6 testing.expect(x == expected);
7}7}
88
9test "fixunstfdi" {9test "fixunstfdi" {
std/special/compiler_rt/fixunstfsi_test.zig+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi;1const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi;
2const assert = @import("std").debug.assert;2const testing = @import("std").testing;
33
4fn test__fixunstfsi(a: f128, expected: u32) void {4fn test__fixunstfsi(a: f128, expected: u32) void {
5 const x = __fixunstfsi(a);5 const x = __fixunstfsi(a);
6 assert(x == expected);6 testing.expect(x == expected);
7}7}
88
9const inf128 = @bitCast(f128, u128(0x7fff0000000000000000000000000000));9const inf128 = @bitCast(f128, u128(0x7fff0000000000000000000000000000));
std/special/compiler_rt/fixunstfti_test.zig+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const __fixunstfti = @import("fixunstfti.zig").__fixunstfti;1const __fixunstfti = @import("fixunstfti.zig").__fixunstfti;
2const assert = @import("std").debug.assert;2const testing = @import("std").testing;
33
4fn test__fixunstfti(a: f128, expected: u128) void {4fn test__fixunstfti(a: f128, expected: u128) void {
5 const x = __fixunstfti(a);5 const x = __fixunstfti(a);
6 assert(x == expected);6 testing.expect(x == expected);
7}7}
88
9const inf128 = @bitCast(f128, u128(0x7fff0000000000000000000000000000));9const inf128 = @bitCast(f128, u128(0x7fff0000000000000000000000000000));
std/special/compiler_rt/floattidf_test.zig+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const __floattidf = @import("floattidf.zig").__floattidf;1const __floattidf = @import("floattidf.zig").__floattidf;
2const assert = @import("std").debug.assert;2const testing = @import("std").testing;
33
4fn test__floattidf(a: i128, expected: f64) void {4fn test__floattidf(a: i128, expected: f64) void {
5 const x = __floattidf(a);5 const x = __floattidf(a);
6 assert(x == expected);6 testing.expect(x == expected);
7}7}
88
9test "floattidf" {9test "floattidf" {
std/special/compiler_rt/floattisf_test.zig+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const __floattisf = @import("floattisf.zig").__floattisf;1const __floattisf = @import("floattisf.zig").__floattisf;
2const assert = @import("std").debug.assert;2const testing = @import("std").testing;
33
4fn test__floattisf(a: i128, expected: f32) void {4fn test__floattisf(a: i128, expected: f32) void {
5 const x = __floattisf(a);5 const x = __floattisf(a);
6 assert(x == expected);6 testing.expect(x == expected);
7}7}
88
9test "floattisf" {9test "floattisf" {
std/special/compiler_rt/floattitf_test.zig+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const __floattitf = @import("floattitf.zig").__floattitf;1const __floattitf = @import("floattitf.zig").__floattitf;
2const assert = @import("std").debug.assert;2const testing = @import("std").testing;
33
4fn test__floattitf(a: i128, expected: f128) void {4fn test__floattitf(a: i128, expected: f128) void {
5 const x = __floattitf(a);5 const x = __floattitf(a);
6 assert(x == expected);6 testing.expect(x == expected);
7}7}
88
9test "floattitf" {9test "floattitf" {
std/special/compiler_rt/floatunditf_test.zig-1
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1const __floatunditf = @import("floatunditf.zig").__floatunditf;1const __floatunditf = @import("floatunditf.zig").__floatunditf;
2const assert = @import("std").debug.assert;
32
4fn test__floatunditf(a: u128, expected_hi: u64, expected_lo: u64) void {3fn test__floatunditf(a: u128, expected_hi: u64, expected_lo: u64) void {
5 const x = __floatunditf(a);4 const x = __floatunditf(a);
std/special/compiler_rt/floatunsitf_test.zig-1
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1const __floatunsitf = @import("floatunsitf.zig").__floatunsitf;1const __floatunsitf = @import("floatunsitf.zig").__floatunsitf;
2const assert = @import("std").debug.assert;
32
4fn test__floatunsitf(a: u64, expected_hi: u64, expected_lo: u64) void {3fn test__floatunsitf(a: u64, expected_hi: u64, expected_lo: u64) void {
5 const x = __floatunsitf(a);4 const x = __floatunsitf(a);
std/special/compiler_rt/floatuntidf_test.zig+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const __floatuntidf = @import("floatuntidf.zig").__floatuntidf;1const __floatuntidf = @import("floatuntidf.zig").__floatuntidf;
2const assert = @import("std").debug.assert;2const testing = @import("std").testing;
33
4fn test__floatuntidf(a: u128, expected: f64) void {4fn test__floatuntidf(a: u128, expected: f64) void {
5 const x = __floatuntidf(a);5 const x = __floatuntidf(a);
6 assert(x == expected);6 testing.expect(x == expected);
7}7}
88
9test "floatuntidf" {9test "floatuntidf" {
std/special/compiler_rt/floatuntisf_test.zig+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const __floatuntisf = @import("floatuntisf.zig").__floatuntisf;1const __floatuntisf = @import("floatuntisf.zig").__floatuntisf;
2const assert = @import("std").debug.assert;2const testing = @import("std").testing;
33
4fn test__floatuntisf(a: u128, expected: f32) void {4fn test__floatuntisf(a: u128, expected: f32) void {
5 const x = __floatuntisf(a);5 const x = __floatuntisf(a);
6 assert(x == expected);6 testing.expect(x == expected);
7}7}
88
9test "floatuntisf" {9test "floatuntisf" {
std/special/compiler_rt/floatuntitf_test.zig+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const __floatuntitf = @import("floatuntitf.zig").__floatuntitf;1const __floatuntitf = @import("floatuntitf.zig").__floatuntitf;
2const assert = @import("std").debug.assert;2const testing = @import("std").testing;
33
4fn test__floatuntitf(a: u128, expected: f128) void {4fn test__floatuntitf(a: u128, expected: f128) void {
5 const x = __floatuntitf(a);5 const x = __floatuntitf(a);
6 assert(x == expected);6 testing.expect(x == expected);
7}7}
88
9test "floatuntitf" {9test "floatuntitf" {
std/special/compiler_rt/index.zig+17-2
...@@ -21,6 +21,9 @@ comptime {...@@ -21,6 +21,9 @@ comptime {
2121
22 @export("__unordtf2", @import("comparetf2.zig").__unordtf2, linkage);22 @export("__unordtf2", @import("comparetf2.zig").__unordtf2, linkage);
2323
24 @export("__addtf3", @import("addXf3.zig").__addtf3, linkage);
25 @export("__subtf3", @import("addXf3.zig").__subtf3, linkage);
26
24 @export("__floattitf", @import("floattitf.zig").__floattitf, linkage);27 @export("__floattitf", @import("floattitf.zig").__floattitf, linkage);
25 @export("__floattidf", @import("floattidf.zig").__floattidf, linkage);28 @export("__floattidf", @import("floattidf.zig").__floattidf, linkage);
26 @export("__floattisf", @import("floattisf.zig").__floattisf, linkage);29 @export("__floattisf", @import("floattisf.zig").__floattisf, linkage);
...@@ -37,6 +40,7 @@ comptime {...@@ -37,6 +40,7 @@ comptime {
37 @export("__extendhfsf2", @import("extendXfYf2.zig").__extendhfsf2, linkage);40 @export("__extendhfsf2", @import("extendXfYf2.zig").__extendhfsf2, linkage);
3841
39 @export("__truncsfhf2", @import("truncXfYf2.zig").__truncsfhf2, linkage);42 @export("__truncsfhf2", @import("truncXfYf2.zig").__truncsfhf2, linkage);
43 @export("__truncdfhf2", @import("truncXfYf2.zig").__truncdfhf2, linkage);
40 @export("__trunctfdf2", @import("truncXfYf2.zig").__trunctfdf2, linkage);44 @export("__trunctfdf2", @import("truncXfYf2.zig").__trunctfdf2, linkage);
41 @export("__trunctfsf2", @import("truncXfYf2.zig").__trunctfsf2, linkage);45 @export("__trunctfsf2", @import("truncXfYf2.zig").__trunctfsf2, linkage);
4246
...@@ -52,6 +56,16 @@ comptime {...@@ -52,6 +56,16 @@ comptime {
52 @export("__fixunstfdi", @import("fixunstfdi.zig").__fixunstfdi, linkage);56 @export("__fixunstfdi", @import("fixunstfdi.zig").__fixunstfdi, linkage);
53 @export("__fixunstfti", @import("fixunstfti.zig").__fixunstfti, linkage);57 @export("__fixunstfti", @import("fixunstfti.zig").__fixunstfti, linkage);
5458
59 @export("__fixdfdi", @import("fixdfdi.zig").__fixdfdi, linkage);
60 @export("__fixdfsi", @import("fixdfsi.zig").__fixdfsi, linkage);
61 @export("__fixdfti", @import("fixdfti.zig").__fixdfti, linkage);
62 @export("__fixsfdi", @import("fixsfdi.zig").__fixsfdi, linkage);
63 @export("__fixsfsi", @import("fixsfsi.zig").__fixsfsi, linkage);
64 @export("__fixsfti", @import("fixsfti.zig").__fixsfti, linkage);
65 @export("__fixtfdi", @import("fixtfdi.zig").__fixtfdi, linkage);
66 @export("__fixtfsi", @import("fixtfsi.zig").__fixtfsi, linkage);
67 @export("__fixtfti", @import("fixtfti.zig").__fixtfti, linkage);
68
55 @export("__udivmoddi4", @import("udivmoddi4.zig").__udivmoddi4, linkage);69 @export("__udivmoddi4", @import("udivmoddi4.zig").__udivmoddi4, linkage);
5670
57 @export("__udivsi3", __udivsi3, linkage);71 @export("__udivsi3", __udivsi3, linkage);
...@@ -100,6 +114,7 @@ comptime {...@@ -100,6 +114,7 @@ comptime {
100114
101const std = @import("std");115const std = @import("std");
102const assert = std.debug.assert;116const assert = std.debug.assert;
117const testing = std.testing;
103118
104const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4;119const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4;
105120
...@@ -407,7 +422,7 @@ test "test_umoddi3" {...@@ -407,7 +422,7 @@ test "test_umoddi3" {
407422
408fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) void {423fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) void {
409 const r = __umoddi3(a, b);424 const r = __umoddi3(a, b);
410 assert(r == expected_r);425 testing.expect(r == expected_r);
411}426}
412427
413test "test_udivsi3" {428test "test_udivsi3" {
...@@ -1081,5 +1096,5 @@ test "test_udivsi3" {...@@ -1081,5 +1096,5 @@ test "test_udivsi3" {
10811096
1082fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) void {1097fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) void {
1083 const q: u32 = __udivsi3(a, b);1098 const q: u32 = __udivsi3(a, b);
1084 assert(q == expected_q);1099 testing.expect(q == expected_q);
1085}1100}
std/special/compiler_rt/muloti4_test.zig+2-2
...@@ -1,10 +1,10 @@...@@ -1,10 +1,10 @@
1const __muloti4 = @import("muloti4.zig").__muloti4;1const __muloti4 = @import("muloti4.zig").__muloti4;
2const assert = @import("std").debug.assert;2const testing = @import("std").testing;
33
4fn test__muloti4(a: i128, b: i128, expected: i128, expected_overflow: c_int) void {4fn test__muloti4(a: i128, b: i128, expected: i128, expected_overflow: c_int) void {
5 var overflow: c_int = undefined;5 var overflow: c_int = undefined;
6 const x = __muloti4(a, b, &overflow);6 const x = __muloti4(a, b, &overflow);
7 assert(overflow == expected_overflow and (expected_overflow != 0 or x == expected));7 testing.expect(overflow == expected_overflow and (expected_overflow != 0 or x == expected));
8}8}
99
10test "muloti4" {10test "muloti4" {
std/special/compiler_rt/multi3_test.zig+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1const __multi3 = @import("multi3.zig").__multi3;1const __multi3 = @import("multi3.zig").__multi3;
2const assert = @import("std").debug.assert;2const testing = @import("std").testing;
33
4fn test__multi3(a: i128, b: i128, expected: i128) void {4fn test__multi3(a: i128, b: i128, expected: i128) void {
5 const x = __multi3(a, b);5 const x = __multi3(a, b);
6 assert(x == expected);6 testing.expect(x == expected);
7}7}
88
9test "multi3" {9test "multi3" {
std/special/compiler_rt/truncXfYf2.zig+4
...@@ -4,6 +4,10 @@ pub extern fn __truncsfhf2(a: f32) u16 {...@@ -4,6 +4,10 @@ pub extern fn __truncsfhf2(a: f32) u16 {
4 return @bitCast(u16, truncXfYf2(f16, f32, a));4 return @bitCast(u16, truncXfYf2(f16, f32, a));
5}5}
66
7pub extern fn __truncdfhf2(a: f64) u16 {
8 return @bitCast(u16, truncXfYf2(f16, f64, a));
9}
10
7pub extern fn __trunctfsf2(a: f128) f32 {11pub extern fn __trunctfsf2(a: f128) f32 {
8 return truncXfYf2(f32, f128, a);12 return truncXfYf2(f32, f128, a);
9}13}
std/special/compiler_rt/truncXfYf2_test.zig+68
...@@ -63,6 +63,74 @@ test "truncsfhf2" {...@@ -63,6 +63,74 @@ test "truncsfhf2" {
63 test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero63 test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero
64}64}
6565
66const __truncdfhf2 = @import("truncXfYf2.zig").__truncdfhf2;
67
68fn test__truncdfhf2(a: f64, expected: u16) void {
69 const rep = @bitCast(u16, __truncdfhf2(a));
70
71 if (rep == expected) {
72 return;
73 }
74 // test other possible NaN representation(signal NaN)
75 else if (expected == 0x7e00) {
76 if ((rep & 0x7c00) == 0x7c00 and (rep & 0x3ff) > 0) {
77 return;
78 }
79 }
80
81 @panic("__truncdfhf2 test failure");
82}
83
84fn test__truncdfhf2_raw(a: u64, expected: u16) void {
85 const actual = __truncdfhf2(@bitCast(f64, a));
86
87 if (actual == expected) {
88 return;
89 }
90
91 @panic("__truncdfhf2 test failure");
92}
93
94test "truncdfhf2" {
95 test__truncdfhf2_raw(0x7ff8000000000000, 0x7e00); // qNaN
96 test__truncdfhf2_raw(0x7ff0000000008000, 0x7e00); // NaN
97
98 test__truncdfhf2_raw(0x7ff0000000000000, 0x7c00); //inf
99 test__truncdfhf2_raw(0xfff0000000000000, 0xfc00); // -inf
100
101 test__truncdfhf2(0.0, 0x0); // zero
102 test__truncdfhf2_raw(0x80000000 << 32, 0x8000); // -zero
103
104 test__truncdfhf2(3.1415926535, 0x4248);
105 test__truncdfhf2(-3.1415926535, 0xc248);
106
107 test__truncdfhf2(0x1.987124876876324p+1000, 0x7c00);
108 test__truncdfhf2(0x1.987124876876324p+12, 0x6e62);
109 test__truncdfhf2(0x1.0p+0, 0x3c00);
110 test__truncdfhf2(0x1.0p-14, 0x0400);
111
112 // denormal
113 test__truncdfhf2(0x1.0p-20, 0x0010);
114 test__truncdfhf2(0x1.0p-24, 0x0001);
115 test__truncdfhf2(-0x1.0p-24, 0x8001);
116 test__truncdfhf2(0x1.5p-25, 0x0001);
117
118 // and back to zero
119 test__truncdfhf2(0x1.0p-25, 0x0000);
120 test__truncdfhf2(-0x1.0p-25, 0x8000);
121
122 // max (precise)
123 test__truncdfhf2(65504.0, 0x7bff);
124
125 // max (rounded)
126 test__truncdfhf2(65519.0, 0x7bff);
127
128 // max (to +inf)
129 test__truncdfhf2(65520.0, 0x7c00);
130 test__truncdfhf2(-65520.0, 0xfc00);
131 test__truncdfhf2(65536.0, 0x7c00);
132}
133
66const __trunctfsf2 = @import("truncXfYf2.zig").__trunctfsf2;134const __trunctfsf2 = @import("truncXfYf2.zig").__trunctfsf2;
67135
68fn test__trunctfsf2(a: f128, expected: u32) void {136fn test__trunctfsf2(a: f128, expected: u32) void {
std/special/compiler_rt/udivmoddi4_test.zig+3-3
...@@ -1,13 +1,13 @@...@@ -1,13 +1,13 @@
1// Disable formatting to avoid unnecessary source repository bloat.1// Disable formatting to avoid unnecessary source repository bloat.
2// zig fmt: off2// zig fmt: off
3const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4;3const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4;
4const assert = @import("std").debug.assert;4const testing = @import("std").testing;
55
6fn test__udivmoddi4(a: u64, b: u64, expected_q: u64, expected_r: u64) void {6fn test__udivmoddi4(a: u64, b: u64, expected_q: u64, expected_r: u64) void {
7 var r: u64 = undefined;7 var r: u64 = undefined;
8 const q = __udivmoddi4(a, b, &r);8 const q = __udivmoddi4(a, b, &r);
9 assert(q == expected_q);9 testing.expect(q == expected_q);
10 assert(r == expected_r);10 testing.expect(r == expected_r);
11}11}
1212
13test "udivmoddi4" {13test "udivmoddi4" {
std/special/compiler_rt/udivmodti4_test.zig+3-3
...@@ -1,13 +1,13 @@...@@ -1,13 +1,13 @@
1// Disable formatting to avoid unnecessary source repository bloat.1// Disable formatting to avoid unnecessary source repository bloat.
2// zig fmt: off2// zig fmt: off
3const __udivmodti4 = @import("udivmodti4.zig").__udivmodti4;3const __udivmodti4 = @import("udivmodti4.zig").__udivmodti4;
4const assert = @import("std").debug.assert;4const testing = @import("std").testing;
55
6fn test__udivmodti4(a: u128, b: u128, expected_q: u128, expected_r: u128) void {6fn test__udivmodti4(a: u128, b: u128, expected_q: u128, expected_r: u128) void {
7 var r: u128 = undefined;7 var r: u128 = undefined;
8 const q = __udivmodti4(a, b, &r);8 const q = __udivmodti4(a, b, &r);
9 assert(q == expected_q);9 testing.expect(q == expected_q);
10 assert(r == expected_r);10 testing.expect(r == expected_r);
11}11}
1212
13test "udivmodti4" {13test "udivmodti4" {
std/special/fmt_runner.zig created+260
...@@ -0,0 +1,260 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4const os = std.os;
5const io = std.io;
6const mem = std.mem;
7const Allocator = mem.Allocator;
8const ArrayList = std.ArrayList;
9const Buffer = std.Buffer;
10const ast = std.zig.ast;
11
12const arg = @import("fmt/arg.zig");
13const self_hosted_main = @import("fmt/main.zig");
14const Args = arg.Args;
15const Flag = arg.Flag;
16const errmsg = @import("fmt/errmsg.zig");
17
18var stderr_file: os.File = undefined;
19var stderr: *io.OutStream(os.File.WriteError) = undefined;
20var stdout: *io.OutStream(os.File.WriteError) = undefined;
21
22// This brings `zig fmt` to stage 1.
23pub fn main() !void {
24 // Here we use an ArenaAllocator backed by a DirectAllocator because `zig fmt` is a short-lived,
25 // one shot program. We don't need to waste time freeing memory and finding places to squish
26 // bytes into. So we free everything all at once at the very end.
27 var direct_allocator = std.heap.DirectAllocator.init();
28 var arena = std.heap.ArenaAllocator.init(&direct_allocator.allocator);
29 const allocator = &arena.allocator;
30
31 var stdout_file = try std.io.getStdOut();
32 var stdout_out_stream = stdout_file.outStream();
33 stdout = &stdout_out_stream.stream;
34
35 stderr_file = try std.io.getStdErr();
36 var stderr_out_stream = stderr_file.outStream();
37 stderr = &stderr_out_stream.stream;
38 const args = try std.os.argsAlloc(allocator);
39
40 var flags = try Args.parse(allocator, self_hosted_main.args_fmt_spec, args);
41 defer flags.deinit();
42
43 if (flags.present("help")) {
44 try stdout.write(self_hosted_main.usage_fmt);
45 os.exit(0);
46 }
47
48 const color = blk: {
49 if (flags.single("color")) |color_flag| {
50 if (mem.eql(u8, color_flag, "auto")) {
51 break :blk errmsg.Color.Auto;
52 } else if (mem.eql(u8, color_flag, "on")) {
53 break :blk errmsg.Color.On;
54 } else if (mem.eql(u8, color_flag, "off")) {
55 break :blk errmsg.Color.Off;
56 } else unreachable;
57 } else {
58 break :blk errmsg.Color.Auto;
59 }
60 };
61
62 if (flags.present("stdin")) {
63 if (flags.positionals.len != 0) {
64 try stderr.write("cannot use --stdin with positional arguments\n");
65 os.exit(1);
66 }
67
68 var stdin_file = try io.getStdIn();
69 var stdin = stdin_file.inStream();
70
71 const source_code = try stdin.stream.readAllAlloc(allocator, self_hosted_main.max_src_size);
72 defer allocator.free(source_code);
73
74 var tree = std.zig.parse(allocator, source_code) catch |err| {
75 try stderr.print("error parsing stdin: {}\n", err);
76 os.exit(1);
77 };
78 defer tree.deinit();
79
80 var error_it = tree.errors.iterator(0);
81 while (error_it.next()) |parse_error| {
82 try printErrMsgToFile(allocator, parse_error, &tree, "<stdin>", stderr_file, color);
83 }
84 if (tree.errors.len != 0) {
85 os.exit(1);
86 }
87 if (flags.present("check")) {
88 const anything_changed = try std.zig.render(allocator, io.null_out_stream, &tree);
89 const code = if (anything_changed) u8(1) else u8(0);
90 os.exit(code);
91 }
92
93 _ = try std.zig.render(allocator, stdout, &tree);
94 return;
95 }
96
97 if (flags.positionals.len == 0) {
98 try stderr.write("expected at least one source file argument\n");
99 os.exit(1);
100 }
101
102 var fmt = Fmt{
103 .seen = Fmt.SeenMap.init(allocator),
104 .any_error = false,
105 .color = color,
106 .allocator = allocator,
107 };
108
109 const check_mode = flags.present("check");
110
111 for (flags.positionals.toSliceConst()) |file_path| {
112 try fmtPath(&fmt, file_path, check_mode);
113 }
114 if (fmt.any_error) {
115 os.exit(1);
116 }
117}
118
119const FmtError = error{
120 SystemResources,
121 OperationAborted,
122 IoPending,
123 BrokenPipe,
124 Unexpected,
125 WouldBlock,
126 FileClosed,
127 DestinationAddressRequired,
128 DiskQuota,
129 FileTooBig,
130 InputOutput,
131 NoSpaceLeft,
132 AccessDenied,
133 OutOfMemory,
134 RenameAcrossMountPoints,
135 ReadOnlyFileSystem,
136 LinkQuotaExceeded,
137 FileBusy,
138} || os.File.OpenError;
139
140fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void {
141 const file_path = try std.mem.dupe(fmt.allocator, u8, file_path_ref);
142 defer fmt.allocator.free(file_path);
143
144 if (try fmt.seen.put(file_path, {})) |_| return;
145
146 const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) {
147 error.IsDir, error.AccessDenied => {
148 // TODO make event based (and dir.next())
149 var dir = try std.os.Dir.open(fmt.allocator, file_path);
150 defer dir.close();
151
152 while (try dir.next()) |entry| {
153 if (entry.kind == std.os.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) {
154 const full_path = try os.path.join(fmt.allocator, [][]const u8{ file_path, entry.name });
155 try fmtPath(fmt, full_path, check_mode);
156 }
157 }
158 return;
159 },
160 else => {
161 // TODO lock stderr printing
162 try stderr.print("unable to open '{}': {}\n", file_path, err);
163 fmt.any_error = true;
164 return;
165 },
166 };
167 defer fmt.allocator.free(source_code);
168
169 var tree = std.zig.parse(fmt.allocator, source_code) catch |err| {
170 try stderr.print("error parsing file '{}': {}\n", file_path, err);
171 fmt.any_error = true;
172 return;
173 };
174 defer tree.deinit();
175
176 var error_it = tree.errors.iterator(0);
177 while (error_it.next()) |parse_error| {
178 try printErrMsgToFile(fmt.allocator, parse_error, &tree, file_path, stderr_file, fmt.color);
179 }
180 if (tree.errors.len != 0) {
181 fmt.any_error = true;
182 return;
183 }
184
185 if (check_mode) {
186 const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, &tree);
187 if (anything_changed) {
188 try stderr.print("{}\n", file_path);
189 fmt.any_error = true;
190 }
191 } else {
192 // TODO make this evented
193 const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path);
194 defer baf.destroy();
195
196 const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), &tree);
197 if (anything_changed) {
198 try stderr.print("{}\n", file_path);
199 try baf.finish();
200 }
201 }
202}
203
204const Fmt = struct {
205 seen: SeenMap,
206 any_error: bool,
207 color: errmsg.Color,
208 allocator: *mem.Allocator,
209
210 const SeenMap = std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8);
211};
212
213fn printErrMsgToFile(allocator: *mem.Allocator, parse_error: *const ast.Error, tree: *ast.Tree,
214 path: []const u8, file: os.File, color: errmsg.Color,) !void
215{
216 const color_on = switch (color) {
217 errmsg.Color.Auto => file.isTty(),
218 errmsg.Color.On => true,
219 errmsg.Color.Off => false,
220 };
221 const lok_token = parse_error.loc();
222 const span = errmsg.Span{
223 .first = lok_token,
224 .last = lok_token,
225 };
226
227 const first_token = tree.tokens.at(span.first);
228 const last_token = tree.tokens.at(span.last);
229 const start_loc = tree.tokenLocationPtr(0, first_token);
230 const end_loc = tree.tokenLocationPtr(first_token.end, last_token);
231
232 var text_buf = try std.Buffer.initSize(allocator, 0);
233 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
234 try parse_error.render(&tree.tokens, out_stream);
235 const text = text_buf.toOwnedSlice();
236
237 const stream = &file.outStream().stream;
238 if (!color_on) {
239 try stream.print(
240 "{}:{}:{}: error: {}\n",
241 path,
242 start_loc.line + 1,
243 start_loc.column + 1,
244 text,
245 );
246 return;
247 }
248
249 try stream.print(
250 "{}:{}:{}: error: {}\n{}\n",
251 path,
252 start_loc.line + 1,
253 start_loc.column + 1,
254 text,
255 tree.source[start_loc.line_start..start_loc.line_end],
256 );
257 try stream.writeByteNTimes(' ', start_loc.column);
258 try stream.writeByteNTimes('~', last_token.end - first_token.start);
259 try stream.write("\n");
260}
std/special/init-lib/src/main.zig+2-2
...@@ -1,10 +1,10 @@...@@ -1,10 +1,10 @@
1const std = @import("std");1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;2const testing = std.testing;
33
4export fn add(a: i32, b: i32) i32 {4export fn add(a: i32, b: i32) i32 {
5 return a + b;5 return a + b;
6}6}
77
8test "basic add functionality" {8test "basic add functionality" {
9 assertOrPanic(add(3, 7) == 10);9 testing.expect(add(3, 7) == 10);
10}10}
std/special/panic.zig+4
...@@ -13,6 +13,10 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn...@@ -13,6 +13,10 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn
13 builtin.Os.freestanding, builtin.Os.zen => {13 builtin.Os.freestanding, builtin.Os.zen => {
14 while (true) {}14 while (true) {}
15 },15 },
16 builtin.Os.uefi => {
17 // TODO look into using the debug info and logging helpful messages
18 std.os.abort();
19 },
16 else => {20 else => {
17 const first_trace_addr = @ptrToInt(@returnAddress());21 const first_trace_addr = @ptrToInt(@returnAddress());
18 std.debug.panicExtra(error_return_trace, first_trace_addr, "{}", msg);22 std.debug.panicExtra(error_return_trace, first_trace_addr, "{}", msg);
std/statically_initialized_mutex.zig created+111
...@@ -0,0 +1,111 @@
1const std = @import("index.zig");
2const builtin = @import("builtin");
3const AtomicOrder = builtin.AtomicOrder;
4const AtomicRmwOp = builtin.AtomicRmwOp;
5const assert = std.debug.assert;
6const expect = std.testing.expect;
7const windows = std.os.windows;
8
9/// Lock may be held only once. If the same thread
10/// tries to acquire the same mutex twice, it deadlocks.
11/// This type is intended to be initialized statically. If you don't
12/// require static initialization, use std.Mutex.
13/// On Windows, this mutex allocates resources when it is
14/// first used, and the resources cannot be freed.
15/// On Linux, this is an alias of std.Mutex.
16pub const StaticallyInitializedMutex = switch(builtin.os) {
17 builtin.Os.linux => std.Mutex,
18 builtin.Os.windows => struct {
19 lock: windows.CRITICAL_SECTION,
20 init_once: windows.RTL_RUN_ONCE,
21
22 pub const Held = struct {
23 mutex: *StaticallyInitializedMutex,
24
25 pub fn release(self: Held) void {
26 windows.LeaveCriticalSection(&self.mutex.lock);
27 }
28 };
29
30 pub fn init() StaticallyInitializedMutex {
31 return StaticallyInitializedMutex {
32 .lock = undefined,
33 .init_once = windows.INIT_ONCE_STATIC_INIT,
34 };
35 }
36
37 extern fn initCriticalSection(
38 InitOnce: *windows.RTL_RUN_ONCE,
39 Parameter: ?*c_void,
40 Context: ?*c_void,
41 ) windows.BOOL {
42 const lock = @ptrCast(*windows.CRITICAL_SECTION, @alignCast(@alignOf(windows.CRITICAL_SECTION), Parameter));
43 windows.InitializeCriticalSection(lock);
44 return windows.TRUE;
45 }
46
47 /// TODO: once https://github.com/ziglang/zig/issues/287 is solved and std.Mutex has a better
48 /// implementation of a runtime initialized mutex, remove this function.
49 pub fn deinit(self: *StaticallyInitializedMutex) void {
50 assert(windows.InitOnceExecuteOnce(&self.init_once, initCriticalSection, &self.lock, null) != 0);
51 windows.DeleteCriticalSection(&self.lock);
52 }
53
54 pub fn acquire(self: *StaticallyInitializedMutex) Held {
55 assert(windows.InitOnceExecuteOnce(&self.init_once, initCriticalSection, &self.lock, null) != 0);
56 windows.EnterCriticalSection(&self.lock);
57 return Held { .mutex = self };
58 }
59 },
60 else => std.Mutex,
61};
62
63test "std.StaticallyInitializedMutex" {
64 const TestContext = struct {
65 data: i128,
66
67 const TestContext = @This();
68 const incr_count = 10000;
69
70 var mutex = StaticallyInitializedMutex.init();
71
72 fn worker(ctx: *TestContext) void {
73 var i: usize = 0;
74 while (i != TestContext.incr_count) : (i += 1) {
75 const held = mutex.acquire();
76 defer held.release();
77
78 ctx.data += 1;
79 }
80 }
81 };
82
83 var direct_allocator = std.heap.DirectAllocator.init();
84 defer direct_allocator.deinit();
85
86 var plenty_of_memory = try direct_allocator.allocator.alloc(u8, 300 * 1024);
87 defer direct_allocator.allocator.free(plenty_of_memory);
88
89 var fixed_buffer_allocator = std.heap.ThreadSafeFixedBufferAllocator.init(plenty_of_memory);
90 var a = &fixed_buffer_allocator.allocator;
91
92
93 var context = TestContext{
94 .data = 0,
95 };
96
97 if (builtin.single_threaded) {
98 TestContext.worker(&context);
99 expect(context.data == TestContext.incr_count);
100 } else {
101 const thread_count = 10;
102 var threads: [thread_count]*std.os.Thread = undefined;
103 for (threads) |*t| {
104 t.* = try std.os.spawnThread(&context, TestContext.worker);
105 }
106 for (threads) |t|
107 t.wait();
108
109 expect(context.data == thread_count * TestContext.incr_count);
110 }
111}
std/testing.zig created+147
...@@ -0,0 +1,147 @@
1const builtin = @import("builtin");
2const TypeId = builtin.TypeId;
3const std = @import("index.zig");
4
5/// This function is intended to be used only in tests. It prints diagnostics to stderr
6/// and then aborts when actual_error_union is not expected_error.
7pub fn expectError(expected_error: anyerror, actual_error_union: var) void {
8 // TODO remove the workaround here for https://github.com/ziglang/zig/issues/1936
9 if (actual_error_union) |actual_payload| {
10 // TODO remove workaround here for https://github.com/ziglang/zig/issues/557
11 if (@sizeOf(@typeOf(actual_payload)) == 0) {
12 std.debug.panic("expected error.{}, found {} value", @errorName(expected_error), @typeName(@typeOf(actual_payload)));
13 } else {
14 std.debug.panic("expected error.{}, found {}", @errorName(expected_error), actual_payload);
15 }
16 } else |actual_error| {
17 if (expected_error != actual_error) {
18 std.debug.panic("expected error.{}, found error.{}", @errorName(expected_error), @errorName(actual_error));
19 }
20 }
21}
22
23/// This function is intended to be used only in tests. When the two values are not
24/// equal, prints diagnostics to stderr to show exactly how they are not equal,
25/// then aborts.
26/// The types must match exactly.
27pub fn expectEqual(expected: var, actual: @typeOf(expected)) void {
28 switch (@typeInfo(@typeOf(actual))) {
29 TypeId.NoReturn,
30 TypeId.BoundFn,
31 TypeId.ArgTuple,
32 TypeId.Opaque,
33 => @compileError("value of type " ++ @typeName(@typeOf(actual)) ++ " encountered"),
34
35 TypeId.Undefined,
36 TypeId.Null,
37 TypeId.Void,
38 => return,
39
40 TypeId.Type,
41 TypeId.Bool,
42 TypeId.Int,
43 TypeId.Float,
44 TypeId.ComptimeFloat,
45 TypeId.ComptimeInt,
46 TypeId.Enum,
47 TypeId.Namespace,
48 TypeId.Fn,
49 TypeId.Promise,
50 TypeId.Vector,
51 TypeId.ErrorSet,
52 => {
53 if (actual != expected) {
54 std.debug.panic("expected {}, found {}", expected, actual);
55 }
56 },
57
58 TypeId.Pointer => |pointer| {
59 switch (pointer.size) {
60 builtin.TypeInfo.Pointer.Size.One,
61 builtin.TypeInfo.Pointer.Size.Many,
62 => {
63 if (actual != expected) {
64 std.debug.panic("expected {}, found {}", expected, actual);
65 }
66 },
67
68 builtin.TypeInfo.Pointer.Size.Slice => {
69 if (actual.ptr != expected.ptr) {
70 std.debug.panic("expected slice ptr {}, found {}", expected.ptr, actual.ptr);
71 }
72 if (actual.len != expected.len) {
73 std.debug.panic("expected slice len {}, found {}", expected.len, actual.len);
74 }
75 },
76 }
77 },
78
79 TypeId.Array => |array| expectEqualSlices(array.child, &expected, &actual),
80
81 TypeId.Struct => {
82 @compileError("TODO implement testing.expectEqual for structs");
83 },
84
85 TypeId.Union => |union_info| {
86 if (union_info.tag_type == null) {
87 @compileError("Unable to compare untagged union values");
88 }
89 @compileError("TODO implement testing.expectEqual for tagged unions");
90 },
91
92 TypeId.Optional => {
93 if (expected) |expected_payload| {
94 if (actual) |actual_payload| {
95 expectEqual(expected_payload, actual_payload);
96 } else {
97 std.debug.panic("expected {}, found null", expected_payload);
98 }
99 } else {
100 if (actual) |actual_payload| {
101 std.debug.panic("expected null, found {}", actual_payload);
102 }
103 }
104 },
105
106 TypeId.ErrorUnion => {
107 if (expected) |expected_payload| {
108 if (actual) |actual_payload| {
109 expectEqual(expected_payload, actual_payload);
110 } else |actual_err| {
111 std.debug.panic("expected {}, found {}", expected_payload, actual_err);
112 }
113 } else |expected_err| {
114 if (actual) |actual_payload| {
115 std.debug.panic("expected {}, found {}", expected_err, actual_payload);
116 } else |actual_err| {
117 expectEqual(expected_err, actual_err);
118 }
119 }
120 },
121 }
122}
123
124/// This function is intended to be used only in tests. When the two slices are not
125/// equal, prints diagnostics to stderr to show exactly how they are not equal,
126/// then aborts.
127pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const T) void {
128 // TODO better printing of the difference
129 // If the arrays are small enough we could print the whole thing
130 // If the child type is u8 and no weird bytes, we could print it as strings
131 // Even for the length difference, it would be useful to see the values of the slices probably.
132 if (expected.len != actual.len) {
133 std.debug.panic("slice lengths differ. expected {}, found {}", expected.len, actual.len);
134 }
135 var i: usize = 0;
136 while (i < expected.len) : (i += 1) {
137 if (expected[i] != actual[i]) {
138 std.debug.panic("index {} incorrect. expected {}, found {}", i, expected[i], actual[i]);
139 }
140 }
141}
142
143/// This function is intended to be used only in tests. When `ok` is false, the test fails.
144/// A message is printed to stderr and then abort is called.
145pub fn expect(ok: bool) void {
146 if (!ok) @panic("test failure");
147}
std/unicode.zig+68-81
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1const std = @import("./index.zig");1const std = @import("./index.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const debug = std.debug;
4const assert = std.debug.assert;3const assert = std.debug.assert;
4const testing = std.testing;
5const mem = std.mem;5const mem = std.mem;
66
7/// Returns how many bytes the UTF-8 representation would require7/// Returns how many bytes the UTF-8 representation would require
...@@ -32,7 +32,7 @@ pub fn utf8ByteSequenceLength(first_byte: u8) !u3 {...@@ -32,7 +32,7 @@ pub fn utf8ByteSequenceLength(first_byte: u8) !u3 {
32/// Returns: the number of bytes written to out.32/// Returns: the number of bytes written to out.
33pub fn utf8Encode(c: u32, out: []u8) !u3 {33pub fn utf8Encode(c: u32, out: []u8) !u3 {
34 const length = try utf8CodepointSequenceLength(c);34 const length = try utf8CodepointSequenceLength(c);
35 debug.assert(out.len >= length);35 assert(out.len >= length);
36 switch (length) {36 switch (length) {
37 // The pattern for each is the same37 // The pattern for each is the same
38 // - Increasing the initial shift by 6 each time38 // - Increasing the initial shift by 6 each time
...@@ -81,8 +81,8 @@ const Utf8Decode2Error = error{...@@ -81,8 +81,8 @@ const Utf8Decode2Error = error{
81 Utf8OverlongEncoding,81 Utf8OverlongEncoding,
82};82};
83pub fn utf8Decode2(bytes: []const u8) Utf8Decode2Error!u32 {83pub fn utf8Decode2(bytes: []const u8) Utf8Decode2Error!u32 {
84 debug.assert(bytes.len == 2);84 assert(bytes.len == 2);
85 debug.assert(bytes[0] & 0b11100000 == 0b11000000);85 assert(bytes[0] & 0b11100000 == 0b11000000);
86 var value: u32 = bytes[0] & 0b00011111;86 var value: u32 = bytes[0] & 0b00011111;
8787
88 if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation;88 if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation;
...@@ -100,8 +100,8 @@ const Utf8Decode3Error = error{...@@ -100,8 +100,8 @@ const Utf8Decode3Error = error{
100 Utf8EncodesSurrogateHalf,100 Utf8EncodesSurrogateHalf,
101};101};
102pub fn utf8Decode3(bytes: []const u8) Utf8Decode3Error!u32 {102pub fn utf8Decode3(bytes: []const u8) Utf8Decode3Error!u32 {
103 debug.assert(bytes.len == 3);103 assert(bytes.len == 3);
104 debug.assert(bytes[0] & 0b11110000 == 0b11100000);104 assert(bytes[0] & 0b11110000 == 0b11100000);
105 var value: u32 = bytes[0] & 0b00001111;105 var value: u32 = bytes[0] & 0b00001111;
106106
107 if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation;107 if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation;
...@@ -124,8 +124,8 @@ const Utf8Decode4Error = error{...@@ -124,8 +124,8 @@ const Utf8Decode4Error = error{
124 Utf8CodepointTooLarge,124 Utf8CodepointTooLarge,
125};125};
126pub fn utf8Decode4(bytes: []const u8) Utf8Decode4Error!u32 {126pub fn utf8Decode4(bytes: []const u8) Utf8Decode4Error!u32 {
127 debug.assert(bytes.len == 4);127 assert(bytes.len == 4);
128 debug.assert(bytes[0] & 0b11111000 == 0b11110000);128 assert(bytes[0] & 0b11111000 == 0b11110000);
129 var value: u32 = bytes[0] & 0b00000111;129 var value: u32 = bytes[0] & 0b00000111;
130130
131 if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation;131 if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation;
...@@ -249,12 +249,12 @@ pub const Utf16LeIterator = struct {...@@ -249,12 +249,12 @@ pub const Utf16LeIterator = struct {
249 pub fn nextCodepoint(it: *Utf16LeIterator) !?u32 {249 pub fn nextCodepoint(it: *Utf16LeIterator) !?u32 {
250 assert(it.i <= it.bytes.len);250 assert(it.i <= it.bytes.len);
251 if (it.i == it.bytes.len) return null;251 if (it.i == it.bytes.len) return null;
252 const c0: u32 = mem.readIntLE(u16, it.bytes[it.i .. it.i + 2]);252 const c0: u32 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]);
253 if (c0 & ~u32(0x03ff) == 0xd800) {253 if (c0 & ~u32(0x03ff) == 0xd800) {
254 // surrogate pair254 // surrogate pair
255 it.i += 2;255 it.i += 2;
256 if (it.i >= it.bytes.len) return error.DanglingSurrogateHalf;256 if (it.i >= it.bytes.len) return error.DanglingSurrogateHalf;
257 const c1: u32 = mem.readIntLE(u16, it.bytes[it.i .. it.i + 2]);257 const c1: u32 = mem.readIntSliceLittle(u16, it.bytes[it.i .. it.i + 2]);
258 if (c1 & ~u32(0x03ff) != 0xdc00) return error.ExpectedSecondSurrogateHalf;258 if (c1 & ~u32(0x03ff) != 0xdc00) return error.ExpectedSecondSurrogateHalf;
259 it.i += 2;259 it.i += 2;
260 return 0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff));260 return 0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff));
...@@ -274,23 +274,23 @@ test "utf8 encode" {...@@ -274,23 +274,23 @@ test "utf8 encode" {
274fn testUtf8Encode() !void {274fn testUtf8Encode() !void {
275 // A few taken from wikipedia a few taken elsewhere275 // A few taken from wikipedia a few taken elsewhere
276 var array: [4]u8 = undefined;276 var array: [4]u8 = undefined;
277 debug.assert((try utf8Encode(try utf8Decode("€"), array[0..])) == 3);277 testing.expect((try utf8Encode(try utf8Decode("€"), array[0..])) == 3);
278 debug.assert(array[0] == 0b11100010);278 testing.expect(array[0] == 0b11100010);
279 debug.assert(array[1] == 0b10000010);279 testing.expect(array[1] == 0b10000010);
280 debug.assert(array[2] == 0b10101100);280 testing.expect(array[2] == 0b10101100);
281281
282 debug.assert((try utf8Encode(try utf8Decode("$"), array[0..])) == 1);282 testing.expect((try utf8Encode(try utf8Decode("$"), array[0..])) == 1);
283 debug.assert(array[0] == 0b00100100);283 testing.expect(array[0] == 0b00100100);
284284
285 debug.assert((try utf8Encode(try utf8Decode("¢"), array[0..])) == 2);285 testing.expect((try utf8Encode(try utf8Decode("¢"), array[0..])) == 2);
286 debug.assert(array[0] == 0b11000010);286 testing.expect(array[0] == 0b11000010);
287 debug.assert(array[1] == 0b10100010);287 testing.expect(array[1] == 0b10100010);
288288
289 debug.assert((try utf8Encode(try utf8Decode("𐍈"), array[0..])) == 4);289 testing.expect((try utf8Encode(try utf8Decode("𐍈"), array[0..])) == 4);
290 debug.assert(array[0] == 0b11110000);290 testing.expect(array[0] == 0b11110000);
291 debug.assert(array[1] == 0b10010000);291 testing.expect(array[1] == 0b10010000);
292 debug.assert(array[2] == 0b10001101);292 testing.expect(array[2] == 0b10001101);
293 debug.assert(array[3] == 0b10001000);293 testing.expect(array[3] == 0b10001000);
294}294}
295295
296test "utf8 encode error" {296test "utf8 encode error" {
...@@ -306,11 +306,7 @@ fn testUtf8EncodeError() void {...@@ -306,11 +306,7 @@ fn testUtf8EncodeError() void {
306}306}
307307
308fn testErrorEncode(codePoint: u32, array: []u8, expectedErr: anyerror) void {308fn testErrorEncode(codePoint: u32, array: []u8, expectedErr: anyerror) void {
309 if (utf8Encode(codePoint, array)) |_| {309 testing.expectError(expectedErr, utf8Encode(codePoint, array));
310 unreachable;
311 } else |err| {
312 debug.assert(err == expectedErr);
313 }
314}310}
315311
316test "utf8 iterator on ascii" {312test "utf8 iterator on ascii" {
...@@ -321,16 +317,16 @@ fn testUtf8IteratorOnAscii() void {...@@ -321,16 +317,16 @@ fn testUtf8IteratorOnAscii() void {
321 const s = Utf8View.initComptime("abc");317 const s = Utf8View.initComptime("abc");
322318
323 var it1 = s.iterator();319 var it1 = s.iterator();
324 debug.assert(std.mem.eql(u8, "a", it1.nextCodepointSlice().?));320 testing.expect(std.mem.eql(u8, "a", it1.nextCodepointSlice().?));
325 debug.assert(std.mem.eql(u8, "b", it1.nextCodepointSlice().?));321 testing.expect(std.mem.eql(u8, "b", it1.nextCodepointSlice().?));
326 debug.assert(std.mem.eql(u8, "c", it1.nextCodepointSlice().?));322 testing.expect(std.mem.eql(u8, "c", it1.nextCodepointSlice().?));
327 debug.assert(it1.nextCodepointSlice() == null);323 testing.expect(it1.nextCodepointSlice() == null);
328324
329 var it2 = s.iterator();325 var it2 = s.iterator();
330 debug.assert(it2.nextCodepoint().? == 'a');326 testing.expect(it2.nextCodepoint().? == 'a');
331 debug.assert(it2.nextCodepoint().? == 'b');327 testing.expect(it2.nextCodepoint().? == 'b');
332 debug.assert(it2.nextCodepoint().? == 'c');328 testing.expect(it2.nextCodepoint().? == 'c');
333 debug.assert(it2.nextCodepoint() == null);329 testing.expect(it2.nextCodepoint() == null);
334}330}
335331
336test "utf8 view bad" {332test "utf8 view bad" {
...@@ -340,12 +336,7 @@ test "utf8 view bad" {...@@ -340,12 +336,7 @@ test "utf8 view bad" {
340fn testUtf8ViewBad() void {336fn testUtf8ViewBad() void {
341 // Compile-time error.337 // Compile-time error.
342 // const s3 = Utf8View.initComptime("\xfe\xf2");338 // const s3 = Utf8View.initComptime("\xfe\xf2");
343 const s = Utf8View.init("hel\xadlo");339 testing.expectError(error.InvalidUtf8, Utf8View.init("hel\xadlo"));
344 if (s) |_| {
345 unreachable;
346 } else |err| {
347 debug.assert(err == error.InvalidUtf8);
348 }
349}340}
350341
351test "utf8 view ok" {342test "utf8 view ok" {
...@@ -356,16 +347,16 @@ fn testUtf8ViewOk() void {...@@ -356,16 +347,16 @@ fn testUtf8ViewOk() void {
356 const s = Utf8View.initComptime("東京市");347 const s = Utf8View.initComptime("東京市");
357348
358 var it1 = s.iterator();349 var it1 = s.iterator();
359 debug.assert(std.mem.eql(u8, "東", it1.nextCodepointSlice().?));350 testing.expect(std.mem.eql(u8, "東", it1.nextCodepointSlice().?));
360 debug.assert(std.mem.eql(u8, "京", it1.nextCodepointSlice().?));351 testing.expect(std.mem.eql(u8, "京", it1.nextCodepointSlice().?));
361 debug.assert(std.mem.eql(u8, "市", it1.nextCodepointSlice().?));352 testing.expect(std.mem.eql(u8, "市", it1.nextCodepointSlice().?));
362 debug.assert(it1.nextCodepointSlice() == null);353 testing.expect(it1.nextCodepointSlice() == null);
363354
364 var it2 = s.iterator();355 var it2 = s.iterator();
365 debug.assert(it2.nextCodepoint().? == 0x6771);356 testing.expect(it2.nextCodepoint().? == 0x6771);
366 debug.assert(it2.nextCodepoint().? == 0x4eac);357 testing.expect(it2.nextCodepoint().? == 0x4eac);
367 debug.assert(it2.nextCodepoint().? == 0x5e02);358 testing.expect(it2.nextCodepoint().? == 0x5e02);
368 debug.assert(it2.nextCodepoint() == null);359 testing.expect(it2.nextCodepoint() == null);
369}360}
370361
371test "bad utf8 slice" {362test "bad utf8 slice" {
...@@ -373,10 +364,10 @@ test "bad utf8 slice" {...@@ -373,10 +364,10 @@ test "bad utf8 slice" {
373 testBadUtf8Slice();364 testBadUtf8Slice();
374}365}
375fn testBadUtf8Slice() void {366fn testBadUtf8Slice() void {
376 debug.assert(utf8ValidateSlice("abc"));367 testing.expect(utf8ValidateSlice("abc"));
377 debug.assert(!utf8ValidateSlice("abc\xc0"));368 testing.expect(!utf8ValidateSlice("abc\xc0"));
378 debug.assert(!utf8ValidateSlice("abc\xc0abc"));369 testing.expect(!utf8ValidateSlice("abc\xc0abc"));
379 debug.assert(utf8ValidateSlice("abc\xdf\xbf"));370 testing.expect(utf8ValidateSlice("abc\xdf\xbf"));
380}371}
381372
382test "valid utf8" {373test "valid utf8" {
...@@ -459,21 +450,17 @@ fn testMiscInvalidUtf8() void {...@@ -459,21 +450,17 @@ fn testMiscInvalidUtf8() void {
459}450}
460451
461fn testError(bytes: []const u8, expected_err: anyerror) void {452fn testError(bytes: []const u8, expected_err: anyerror) void {
462 if (testDecode(bytes)) |_| {453 testing.expectError(expected_err, testDecode(bytes));
463 unreachable;
464 } else |err| {
465 debug.assert(err == expected_err);
466 }
467}454}
468455
469fn testValid(bytes: []const u8, expected_codepoint: u32) void {456fn testValid(bytes: []const u8, expected_codepoint: u32) void {
470 debug.assert((testDecode(bytes) catch unreachable) == expected_codepoint);457 testing.expect((testDecode(bytes) catch unreachable) == expected_codepoint);
471}458}
472459
473fn testDecode(bytes: []const u8) !u32 {460fn testDecode(bytes: []const u8) !u32 {
474 const length = try utf8ByteSequenceLength(bytes[0]);461 const length = try utf8ByteSequenceLength(bytes[0]);
475 if (bytes.len < length) return error.UnexpectedEof;462 if (bytes.len < length) return error.UnexpectedEof;
476 debug.assert(bytes.len == length);463 testing.expect(bytes.len == length);
477 return utf8Decode(bytes);464 return utf8Decode(bytes);
478}465}
479466
...@@ -510,48 +497,48 @@ test "utf16leToUtf8" {...@@ -510,48 +497,48 @@ test "utf16leToUtf8" {
510 const utf16le_as_bytes = @sliceToBytes(utf16le[0..]);497 const utf16le_as_bytes = @sliceToBytes(utf16le[0..]);
511498
512 {499 {
513 mem.writeInt(utf16le_as_bytes[0..], u16('A'), builtin.Endian.Little);500 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 'A');
514 mem.writeInt(utf16le_as_bytes[2..], u16('a'), builtin.Endian.Little);501 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 'a');
515 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);502 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
516 assert(mem.eql(u8, utf8, "Aa"));503 testing.expect(mem.eql(u8, utf8, "Aa"));
517 }504 }
518505
519 {506 {
520 mem.writeInt(utf16le_as_bytes[0..], u16(0x80), builtin.Endian.Little);507 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0x80);
521 mem.writeInt(utf16le_as_bytes[2..], u16(0xffff), builtin.Endian.Little);508 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xffff);
522 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);509 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
523 assert(mem.eql(u8, utf8, "\xc2\x80" ++ "\xef\xbf\xbf"));510 testing.expect(mem.eql(u8, utf8, "\xc2\x80" ++ "\xef\xbf\xbf"));
524 }511 }
525512
526 {513 {
527 // the values just outside the surrogate half range514 // the values just outside the surrogate half range
528 mem.writeInt(utf16le_as_bytes[0..], u16(0xd7ff), builtin.Endian.Little);515 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd7ff);
529 mem.writeInt(utf16le_as_bytes[2..], u16(0xe000), builtin.Endian.Little);516 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xe000);
530 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);517 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
531 assert(mem.eql(u8, utf8, "\xed\x9f\xbf" ++ "\xee\x80\x80"));518 testing.expect(mem.eql(u8, utf8, "\xed\x9f\xbf" ++ "\xee\x80\x80"));
532 }519 }
533520
534 {521 {
535 // smallest surrogate pair522 // smallest surrogate pair
536 mem.writeInt(utf16le_as_bytes[0..], u16(0xd800), builtin.Endian.Little);523 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd800);
537 mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little);524 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00);
538 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);525 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
539 assert(mem.eql(u8, utf8, "\xf0\x90\x80\x80"));526 testing.expect(mem.eql(u8, utf8, "\xf0\x90\x80\x80"));
540 }527 }
541528
542 {529 {
543 // largest surrogate pair530 // largest surrogate pair
544 mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little);531 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff);
545 mem.writeInt(utf16le_as_bytes[2..], u16(0xdfff), builtin.Endian.Little);532 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdfff);
546 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);533 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
547 assert(mem.eql(u8, utf8, "\xf4\x8f\xbf\xbf"));534 testing.expect(mem.eql(u8, utf8, "\xf4\x8f\xbf\xbf"));
548 }535 }
549536
550 {537 {
551 mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little);538 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff);
552 mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little);539 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00);
553 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);540 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
554 assert(mem.eql(u8, utf8, "\xf4\x8f\xb0\x80"));541 testing.expect(mem.eql(u8, utf8, "\xf4\x8f\xb0\x80"));
555 }542 }
556}543}
557544
...@@ -583,7 +570,7 @@ pub fn utf8ToUtf16Le(utf16le: []u16, utf8: []const u8) !usize {...@@ -583,7 +570,7 @@ pub fn utf8ToUtf16Le(utf16le: []u16, utf8: []const u8) !usize {
583 while (it.nextCodepoint()) |codepoint| {570 while (it.nextCodepoint()) |codepoint| {
584 if (end_index == utf16le_as_bytes.len) return (end_index / 2) + 1;571 if (end_index == utf16le_as_bytes.len) return (end_index / 2) + 1;
585 // TODO surrogate pairs572 // TODO surrogate pairs
586 mem.writeInt(utf16le_as_bytes[end_index..], @intCast(u16, codepoint), builtin.Endian.Little);573 mem.writeIntSliceLittle(u16, utf16le_as_bytes[end_index..], @intCast(u16, codepoint));
587 end_index += 2;574 end_index += 2;
588 }575 }
589 return end_index / 2;576 return end_index / 2;
std/zig/ast.zig+8-1
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const std = @import("../index.zig");1const std = @import("../index.zig");
2const assert = std.debug.assert;2const assert = std.debug.assert;
3const testing = std.testing;
3const SegmentedList = std.SegmentedList;4const SegmentedList = std.SegmentedList;
4const mem = std.mem;5const mem = std.mem;
5const Token = std.zig.Token;6const Token = std.zig.Token;
...@@ -109,6 +110,7 @@ pub const Tree = struct {...@@ -109,6 +110,7 @@ pub const Tree = struct {
109pub const Error = union(enum) {110pub const Error = union(enum) {
110 InvalidToken: InvalidToken,111 InvalidToken: InvalidToken,
111 ExpectedVarDeclOrFn: ExpectedVarDeclOrFn,112 ExpectedVarDeclOrFn: ExpectedVarDeclOrFn,
113 ExpectedVarDecl: ExpectedVarDecl,
112 ExpectedAggregateKw: ExpectedAggregateKw,114 ExpectedAggregateKw: ExpectedAggregateKw,
113 UnattachedDocComment: UnattachedDocComment,115 UnattachedDocComment: UnattachedDocComment,
114 ExpectedEqOrSemi: ExpectedEqOrSemi,116 ExpectedEqOrSemi: ExpectedEqOrSemi,
...@@ -132,6 +134,7 @@ pub const Error = union(enum) {...@@ -132,6 +134,7 @@ pub const Error = union(enum) {
132 // TODO https://github.com/ziglang/zig/issues/683134 // TODO https://github.com/ziglang/zig/issues/683
133 @TagType(Error).InvalidToken => |*x| return x.render(tokens, stream),135 @TagType(Error).InvalidToken => |*x| return x.render(tokens, stream),
134 @TagType(Error).ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream),136 @TagType(Error).ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream),
137 @TagType(Error).ExpectedVarDecl => |*x| return x.render(tokens, stream),
135 @TagType(Error).ExpectedAggregateKw => |*x| return x.render(tokens, stream),138 @TagType(Error).ExpectedAggregateKw => |*x| return x.render(tokens, stream),
136 @TagType(Error).UnattachedDocComment => |*x| return x.render(tokens, stream),139 @TagType(Error).UnattachedDocComment => |*x| return x.render(tokens, stream),
137 @TagType(Error).ExpectedEqOrSemi => |*x| return x.render(tokens, stream),140 @TagType(Error).ExpectedEqOrSemi => |*x| return x.render(tokens, stream),
...@@ -157,6 +160,7 @@ pub const Error = union(enum) {...@@ -157,6 +160,7 @@ pub const Error = union(enum) {
157 // TODO https://github.com/ziglang/zig/issues/683160 // TODO https://github.com/ziglang/zig/issues/683
158 @TagType(Error).InvalidToken => |x| return x.token,161 @TagType(Error).InvalidToken => |x| return x.token,
159 @TagType(Error).ExpectedVarDeclOrFn => |x| return x.token,162 @TagType(Error).ExpectedVarDeclOrFn => |x| return x.token,
163 @TagType(Error).ExpectedVarDecl => |x| return x.token,
160 @TagType(Error).ExpectedAggregateKw => |x| return x.token,164 @TagType(Error).ExpectedAggregateKw => |x| return x.token,
161 @TagType(Error).UnattachedDocComment => |x| return x.token,165 @TagType(Error).UnattachedDocComment => |x| return x.token,
162 @TagType(Error).ExpectedEqOrSemi => |x| return x.token,166 @TagType(Error).ExpectedEqOrSemi => |x| return x.token,
...@@ -179,6 +183,7 @@ pub const Error = union(enum) {...@@ -179,6 +183,7 @@ pub const Error = union(enum) {
179183
180 pub const InvalidToken = SingleTokenError("Invalid token {}");184 pub const InvalidToken = SingleTokenError("Invalid token {}");
181 pub const ExpectedVarDeclOrFn = SingleTokenError("Expected variable declaration or function, found {}");185 pub const ExpectedVarDeclOrFn = SingleTokenError("Expected variable declaration or function, found {}");
186 pub const ExpectedVarDecl = SingleTokenError("Expected variable declaration, found {}");
182 pub const ExpectedAggregateKw = SingleTokenError("Expected " ++ @tagName(Token.Id.Keyword_struct) ++ ", " ++ @tagName(Token.Id.Keyword_union) ++ ", or " ++ @tagName(Token.Id.Keyword_enum) ++ ", found {}");187 pub const ExpectedAggregateKw = SingleTokenError("Expected " ++ @tagName(Token.Id.Keyword_struct) ++ ", " ++ @tagName(Token.Id.Keyword_union) ++ ", or " ++ @tagName(Token.Id.Keyword_enum) ++ ", found {}");
183 pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found {}");188 pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found {}");
184 pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found {}");189 pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found {}");
...@@ -495,6 +500,7 @@ pub const Node = struct {...@@ -495,6 +500,7 @@ pub const Node = struct {
495 base: Node,500 base: Node,
496 doc_comments: ?*DocComment,501 doc_comments: ?*DocComment,
497 visib_token: ?TokenIndex,502 visib_token: ?TokenIndex,
503 thread_local_token: ?TokenIndex,
498 name_token: TokenIndex,504 name_token: TokenIndex,
499 eq_token: TokenIndex,505 eq_token: TokenIndex,
500 mut_token: TokenIndex,506 mut_token: TokenIndex,
...@@ -535,6 +541,7 @@ pub const Node = struct {...@@ -535,6 +541,7 @@ pub const Node = struct {
535541
536 pub fn firstToken(self: *const VarDecl) TokenIndex {542 pub fn firstToken(self: *const VarDecl) TokenIndex {
537 if (self.visib_token) |visib_token| return visib_token;543 if (self.visib_token) |visib_token| return visib_token;
544 if (self.thread_local_token) |thread_local_token| return thread_local_token;
538 if (self.comptime_token) |comptime_token| return comptime_token;545 if (self.comptime_token) |comptime_token| return comptime_token;
539 if (self.extern_export_token) |extern_export_token| return extern_export_token;546 if (self.extern_export_token) |extern_export_token| return extern_export_token;
540 assert(self.lib_name == null);547 assert(self.lib_name == null);
...@@ -2224,5 +2231,5 @@ test "iterate" {...@@ -2224,5 +2231,5 @@ test "iterate" {
2224 .shebang = null,2231 .shebang = null,
2225 };2232 };
2226 var base = &root.base;2233 var base = &root.base;
2227 assert(base.iterate(0) == null);2234 testing.expect(base.iterate(0) == null);
2228}2235}
std/zig/parse.zig+286-151
...@@ -17,14 +17,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -17,14 +17,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
17 defer stack.deinit();17 defer stack.deinit();
1818
19 const arena = &tree_arena.allocator;19 const arena = &tree_arena.allocator;
20 const root_node = try arena.create(ast.Node.Root{20 const root_node = try arena.create(ast.Node.Root);
21 root_node.* = ast.Node.Root{
21 .base = ast.Node{ .id = ast.Node.Id.Root },22 .base = ast.Node{ .id = ast.Node.Id.Root },
22 .decls = ast.Node.Root.DeclList.init(arena),23 .decls = ast.Node.Root.DeclList.init(arena),
23 .doc_comments = null,24 .doc_comments = null,
24 .shebang = null,25 .shebang = null,
25 // initialized when we get the eof token26 // initialized when we get the eof token
26 .eof_token = undefined,27 .eof_token = undefined,
27 });28 };
2829
29 var tree = ast.Tree{30 var tree = ast.Tree{
30 .source = source,31 .source = source,
...@@ -75,20 +76,22 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -75,20 +76,22 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
75 Token.Id.Keyword_test => {76 Token.Id.Keyword_test => {
76 stack.append(State.TopLevel) catch unreachable;77 stack.append(State.TopLevel) catch unreachable;
7778
78 const block = try arena.create(ast.Node.Block{79 const block = try arena.create(ast.Node.Block);
80 block.* = ast.Node.Block{
79 .base = ast.Node{ .id = ast.Node.Id.Block },81 .base = ast.Node{ .id = ast.Node.Id.Block },
80 .label = null,82 .label = null,
81 .lbrace = undefined,83 .lbrace = undefined,
82 .statements = ast.Node.Block.StatementList.init(arena),84 .statements = ast.Node.Block.StatementList.init(arena),
83 .rbrace = undefined,85 .rbrace = undefined,
84 });86 };
85 const test_node = try arena.create(ast.Node.TestDecl{87 const test_node = try arena.create(ast.Node.TestDecl);
88 test_node.* = ast.Node.TestDecl{
86 .base = ast.Node{ .id = ast.Node.Id.TestDecl },89 .base = ast.Node{ .id = ast.Node.Id.TestDecl },
87 .doc_comments = comments,90 .doc_comments = comments,
88 .test_token = token_index,91 .test_token = token_index,
89 .name = undefined,92 .name = undefined,
90 .body_node = &block.base,93 .body_node = &block.base,
91 });94 };
92 try root_node.decls.push(&test_node.base);95 try root_node.decls.push(&test_node.base);
93 try stack.append(State{ .Block = block });96 try stack.append(State{ .Block = block });
94 try stack.append(State{97 try stack.append(State{
...@@ -119,19 +122,21 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -119,19 +122,21 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
119 continue;122 continue;
120 },123 },
121 Token.Id.Keyword_comptime => {124 Token.Id.Keyword_comptime => {
122 const block = try arena.create(ast.Node.Block{125 const block = try arena.create(ast.Node.Block);
126 block.* = ast.Node.Block{
123 .base = ast.Node{ .id = ast.Node.Id.Block },127 .base = ast.Node{ .id = ast.Node.Id.Block },
124 .label = null,128 .label = null,
125 .lbrace = undefined,129 .lbrace = undefined,
126 .statements = ast.Node.Block.StatementList.init(arena),130 .statements = ast.Node.Block.StatementList.init(arena),
127 .rbrace = undefined,131 .rbrace = undefined,
128 });132 };
129 const node = try arena.create(ast.Node.Comptime{133 const node = try arena.create(ast.Node.Comptime);
134 node.* = ast.Node.Comptime{
130 .base = ast.Node{ .id = ast.Node.Id.Comptime },135 .base = ast.Node{ .id = ast.Node.Id.Comptime },
131 .comptime_token = token_index,136 .comptime_token = token_index,
132 .expr = &block.base,137 .expr = &block.base,
133 .doc_comments = comments,138 .doc_comments = comments,
134 });139 };
135 try root_node.decls.push(&node.base);140 try root_node.decls.push(&node.base);
136141
137 stack.append(State.TopLevel) catch unreachable;142 stack.append(State.TopLevel) catch unreachable;
...@@ -224,6 +229,32 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -224,6 +229,32 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
224 }) catch unreachable;229 }) catch unreachable;
225 continue;230 continue;
226 },231 },
232 State.ThreadLocal => |ctx| {
233 const token = nextToken(&tok_it, &tree);
234 const token_index = token.index;
235 const token_ptr = token.ptr;
236 switch (token_ptr.id) {
237 Token.Id.Keyword_var, Token.Id.Keyword_const => {
238 try stack.append(State{
239 .VarDecl = VarDeclCtx{
240 .comments = ctx.comments,
241 .visib_token = ctx.visib_token,
242 .thread_local_token = ctx.thread_local_token,
243 .lib_name = ctx.lib_name,
244 .comptime_token = ctx.comptime_token,
245 .extern_export_token = ctx.extern_export_token,
246 .mut_token = token_index,
247 .list = ctx.list,
248 },
249 });
250 continue;
251 },
252 else => {
253 ((try tree.errors.addOne())).* = Error{ .ExpectedVarDecl = Error.ExpectedVarDecl{ .token = token_index } };
254 return tree;
255 },
256 }
257 },
227 State.TopLevelDecl => |ctx| {258 State.TopLevelDecl => |ctx| {
228 const token = nextToken(&tok_it, &tree);259 const token = nextToken(&tok_it, &tree);
229 const token_index = token.index;260 const token_index = token.index;
...@@ -235,14 +266,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -235,14 +266,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
235 return tree;266 return tree;
236 }267 }
237268
238 const node = try arena.create(ast.Node.Use{269 const node = try arena.create(ast.Node.Use);
270 node.* = ast.Node.Use{
239 .base = ast.Node{ .id = ast.Node.Id.Use },271 .base = ast.Node{ .id = ast.Node.Id.Use },
240 .use_token = token_index,272 .use_token = token_index,
241 .visib_token = ctx.visib_token,273 .visib_token = ctx.visib_token,
242 .expr = undefined,274 .expr = undefined,
243 .semicolon_token = undefined,275 .semicolon_token = undefined,
244 .doc_comments = ctx.comments,276 .doc_comments = ctx.comments,
245 });277 };
246 try ctx.decls.push(&node.base);278 try ctx.decls.push(&node.base);
247279
248 stack.append(State{280 stack.append(State{
...@@ -254,6 +286,28 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -254,6 +286,28 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
254 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } });286 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } });
255 continue;287 continue;
256 },288 },
289 Token.Id.Keyword_threadlocal => {
290 if (ctx.extern_export_inline_token) |annotated_token| {
291 if (annotated_token.ptr.id == Token.Id.Keyword_inline) {
292 ((try tree.errors.addOne())).* = Error{ .InvalidToken = Error.InvalidToken{ .token = annotated_token.index } };
293 return tree;
294 }
295 }
296
297 try stack.append(State{
298 .ThreadLocal = VarDeclCtx{
299 .comments = ctx.comments,
300 .visib_token = ctx.visib_token,
301 .thread_local_token = token_index,
302 .lib_name = ctx.lib_name,
303 .comptime_token = null,
304 .extern_export_token = if (ctx.extern_export_inline_token) |at| at.index else null,
305 .mut_token = undefined,
306 .list = ctx.decls,
307 },
308 });
309 continue;
310 },
257 Token.Id.Keyword_var, Token.Id.Keyword_const => {311 Token.Id.Keyword_var, Token.Id.Keyword_const => {
258 if (ctx.extern_export_inline_token) |annotated_token| {312 if (ctx.extern_export_inline_token) |annotated_token| {
259 if (annotated_token.ptr.id == Token.Id.Keyword_inline) {313 if (annotated_token.ptr.id == Token.Id.Keyword_inline) {
...@@ -266,6 +320,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -266,6 +320,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
266 .VarDecl = VarDeclCtx{320 .VarDecl = VarDeclCtx{
267 .comments = ctx.comments,321 .comments = ctx.comments,
268 .visib_token = ctx.visib_token,322 .visib_token = ctx.visib_token,
323 .thread_local_token = null,
269 .lib_name = ctx.lib_name,324 .lib_name = ctx.lib_name,
270 .comptime_token = null,325 .comptime_token = null,
271 .extern_export_token = if (ctx.extern_export_inline_token) |at| at.index else null,326 .extern_export_token = if (ctx.extern_export_inline_token) |at| at.index else null,
...@@ -276,7 +331,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -276,7 +331,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
276 continue;331 continue;
277 },332 },
278 Token.Id.Keyword_fn, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc, Token.Id.Keyword_async => {333 Token.Id.Keyword_fn, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc, Token.Id.Keyword_async => {
279 const fn_proto = try arena.create(ast.Node.FnProto{334 const fn_proto = try arena.create(ast.Node.FnProto);
335 fn_proto.* = ast.Node.FnProto{
280 .base = ast.Node{ .id = ast.Node.Id.FnProto },336 .base = ast.Node{ .id = ast.Node.Id.FnProto },
281 .doc_comments = ctx.comments,337 .doc_comments = ctx.comments,
282 .visib_token = ctx.visib_token,338 .visib_token = ctx.visib_token,
...@@ -292,7 +348,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -292,7 +348,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
292 .lib_name = ctx.lib_name,348 .lib_name = ctx.lib_name,
293 .align_expr = null,349 .align_expr = null,
294 .section_expr = null,350 .section_expr = null,
295 });351 };
296 try ctx.decls.push(&fn_proto.base);352 try ctx.decls.push(&fn_proto.base);
297 stack.append(State{ .FnDef = fn_proto }) catch unreachable;353 stack.append(State{ .FnDef = fn_proto }) catch unreachable;
298 try stack.append(State{ .FnProto = fn_proto });354 try stack.append(State{ .FnProto = fn_proto });
...@@ -309,12 +365,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -309,12 +365,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
309 continue;365 continue;
310 },366 },
311 Token.Id.Keyword_async => {367 Token.Id.Keyword_async => {
312 const async_node = try arena.create(ast.Node.AsyncAttribute{368 const async_node = try arena.create(ast.Node.AsyncAttribute);
369 async_node.* = ast.Node.AsyncAttribute{
313 .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },370 .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },
314 .async_token = token_index,371 .async_token = token_index,
315 .allocator_type = null,372 .allocator_type = null,
316 .rangle_bracket = null,373 .rangle_bracket = null,
317 });374 };
318 fn_proto.async_attr = async_node;375 fn_proto.async_attr = async_node;
319376
320 try stack.append(State{377 try stack.append(State{
...@@ -341,13 +398,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -341,13 +398,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
341 },398 },
342 State.TopLevelExternOrField => |ctx| {399 State.TopLevelExternOrField => |ctx| {
343 if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |identifier| {400 if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |identifier| {
344 const node = try arena.create(ast.Node.StructField{401 const node = try arena.create(ast.Node.StructField);
402 node.* = ast.Node.StructField{
345 .base = ast.Node{ .id = ast.Node.Id.StructField },403 .base = ast.Node{ .id = ast.Node.Id.StructField },
346 .doc_comments = ctx.comments,404 .doc_comments = ctx.comments,
347 .visib_token = ctx.visib_token,405 .visib_token = ctx.visib_token,
348 .name_token = identifier,406 .name_token = identifier,
349 .type_expr = undefined,407 .type_expr = undefined,
350 });408 };
351 const node_ptr = try ctx.container_decl.fields_and_decls.addOne();409 const node_ptr = try ctx.container_decl.fields_and_decls.addOne();
352 node_ptr.* = &node.base;410 node_ptr.* = &node.base;
353411
...@@ -391,7 +449,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -391,7 +449,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
391 const token = nextToken(&tok_it, &tree);449 const token = nextToken(&tok_it, &tree);
392 const token_index = token.index;450 const token_index = token.index;
393 const token_ptr = token.ptr;451 const token_ptr = token.ptr;
394 const node = try arena.create(ast.Node.ContainerDecl{452 const node = try arena.create(ast.Node.ContainerDecl);
453 node.* = ast.Node.ContainerDecl{
395 .base = ast.Node{ .id = ast.Node.Id.ContainerDecl },454 .base = ast.Node{ .id = ast.Node.Id.ContainerDecl },
396 .layout_token = ctx.layout_token,455 .layout_token = ctx.layout_token,
397 .kind_token = switch (token_ptr.id) {456 .kind_token = switch (token_ptr.id) {
...@@ -405,7 +464,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -405,7 +464,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
405 .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(arena),464 .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(arena),
406 .lbrace_token = undefined,465 .lbrace_token = undefined,
407 .rbrace_token = undefined,466 .rbrace_token = undefined,
408 });467 };
409 ctx.opt_ctx.store(&node.base);468 ctx.opt_ctx.store(&node.base);
410469
411 stack.append(State{ .ContainerDecl = node }) catch unreachable;470 stack.append(State{ .ContainerDecl = node }) catch unreachable;
...@@ -464,13 +523,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -464,13 +523,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
464 Token.Id.Identifier => {523 Token.Id.Identifier => {
465 switch (tree.tokens.at(container_decl.kind_token).id) {524 switch (tree.tokens.at(container_decl.kind_token).id) {
466 Token.Id.Keyword_struct => {525 Token.Id.Keyword_struct => {
467 const node = try arena.create(ast.Node.StructField{526 const node = try arena.create(ast.Node.StructField);
527 node.* = ast.Node.StructField{
468 .base = ast.Node{ .id = ast.Node.Id.StructField },528 .base = ast.Node{ .id = ast.Node.Id.StructField },
469 .doc_comments = comments,529 .doc_comments = comments,
470 .visib_token = null,530 .visib_token = null,
471 .name_token = token_index,531 .name_token = token_index,
472 .type_expr = undefined,532 .type_expr = undefined,
473 });533 };
474 const node_ptr = try container_decl.fields_and_decls.addOne();534 const node_ptr = try container_decl.fields_and_decls.addOne();
475 node_ptr.* = &node.base;535 node_ptr.* = &node.base;
476536
...@@ -485,13 +545,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -485,13 +545,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
485 continue;545 continue;
486 },546 },
487 Token.Id.Keyword_union => {547 Token.Id.Keyword_union => {
488 const node = try arena.create(ast.Node.UnionTag{548 const node = try arena.create(ast.Node.UnionTag);
549 node.* = ast.Node.UnionTag{
489 .base = ast.Node{ .id = ast.Node.Id.UnionTag },550 .base = ast.Node{ .id = ast.Node.Id.UnionTag },
490 .name_token = token_index,551 .name_token = token_index,
491 .type_expr = null,552 .type_expr = null,
492 .value_expr = null,553 .value_expr = null,
493 .doc_comments = comments,554 .doc_comments = comments,
494 });555 };
495 try container_decl.fields_and_decls.push(&node.base);556 try container_decl.fields_and_decls.push(&node.base);
496557
497 try stack.append(State{558 try stack.append(State{
...@@ -506,12 +567,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -506,12 +567,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
506 continue;567 continue;
507 },568 },
508 Token.Id.Keyword_enum => {569 Token.Id.Keyword_enum => {
509 const node = try arena.create(ast.Node.EnumTag{570 const node = try arena.create(ast.Node.EnumTag);
571 node.* = ast.Node.EnumTag{
510 .base = ast.Node{ .id = ast.Node.Id.EnumTag },572 .base = ast.Node{ .id = ast.Node.Id.EnumTag },
511 .name_token = token_index,573 .name_token = token_index,
512 .value = null,574 .value = null,
513 .doc_comments = comments,575 .doc_comments = comments,
514 });576 };
515 try container_decl.fields_and_decls.push(&node.base);577 try container_decl.fields_and_decls.push(&node.base);
516578
517 try stack.append(State{579 try stack.append(State{
...@@ -593,10 +655,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -593,10 +655,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
593 },655 },
594656
595 State.VarDecl => |ctx| {657 State.VarDecl => |ctx| {
596 const var_decl = try arena.create(ast.Node.VarDecl{658 const var_decl = try arena.create(ast.Node.VarDecl);
659 var_decl.* = ast.Node.VarDecl{
597 .base = ast.Node{ .id = ast.Node.Id.VarDecl },660 .base = ast.Node{ .id = ast.Node.Id.VarDecl },
598 .doc_comments = ctx.comments,661 .doc_comments = ctx.comments,
599 .visib_token = ctx.visib_token,662 .visib_token = ctx.visib_token,
663 .thread_local_token = ctx.thread_local_token,
600 .mut_token = ctx.mut_token,664 .mut_token = ctx.mut_token,
601 .comptime_token = ctx.comptime_token,665 .comptime_token = ctx.comptime_token,
602 .extern_export_token = ctx.extern_export_token,666 .extern_export_token = ctx.extern_export_token,
...@@ -609,7 +673,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -609,7 +673,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
609 .name_token = undefined,673 .name_token = undefined,
610 .eq_token = undefined,674 .eq_token = undefined,
611 .semicolon_token = undefined,675 .semicolon_token = undefined,
612 });676 };
613 try ctx.list.push(&var_decl.base);677 try ctx.list.push(&var_decl.base);
614678
615 try stack.append(State{ .VarDeclAlign = var_decl });679 try stack.append(State{ .VarDeclAlign = var_decl });
...@@ -708,13 +772,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -708,13 +772,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
708 const token_ptr = token.ptr;772 const token_ptr = token.ptr;
709 switch (token_ptr.id) {773 switch (token_ptr.id) {
710 Token.Id.LBrace => {774 Token.Id.LBrace => {
711 const block = try arena.create(ast.Node.Block{775 const block = try arena.create(ast.Node.Block);
776 block.* = ast.Node.Block{
712 .base = ast.Node{ .id = ast.Node.Id.Block },777 .base = ast.Node{ .id = ast.Node.Id.Block },
713 .label = null,778 .label = null,
714 .lbrace = token_index,779 .lbrace = token_index,
715 .statements = ast.Node.Block.StatementList.init(arena),780 .statements = ast.Node.Block.StatementList.init(arena),
716 .rbrace = undefined,781 .rbrace = undefined,
717 });782 };
718 fn_proto.body_node = &block.base;783 fn_proto.body_node = &block.base;
719 stack.append(State{ .Block = block }) catch unreachable;784 stack.append(State{ .Block = block }) catch unreachable;
720 continue;785 continue;
...@@ -770,10 +835,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -770,10 +835,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
770 // TODO: this is a special case. Remove this when #760 is fixed835 // TODO: this is a special case. Remove this when #760 is fixed
771 if (token_ptr.id == Token.Id.Keyword_anyerror) {836 if (token_ptr.id == Token.Id.Keyword_anyerror) {
772 if (tok_it.peek().?.id == Token.Id.LBrace) {837 if (tok_it.peek().?.id == Token.Id.LBrace) {
773 const error_type_node = try arena.create(ast.Node.ErrorType{838 const error_type_node = try arena.create(ast.Node.ErrorType);
839 error_type_node.* = ast.Node.ErrorType{
774 .base = ast.Node{ .id = ast.Node.Id.ErrorType },840 .base = ast.Node{ .id = ast.Node.Id.ErrorType },
775 .token = token_index,841 .token = token_index,
776 });842 };
777 fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = &error_type_node.base };843 fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = &error_type_node.base };
778 continue;844 continue;
779 }845 }
...@@ -791,14 +857,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -791,14 +857,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
791 if (eatToken(&tok_it, &tree, Token.Id.RParen)) |_| {857 if (eatToken(&tok_it, &tree, Token.Id.RParen)) |_| {
792 continue;858 continue;
793 }859 }
794 const param_decl = try arena.create(ast.Node.ParamDecl{860 const param_decl = try arena.create(ast.Node.ParamDecl);
861 param_decl.* = ast.Node.ParamDecl{
795 .base = ast.Node{ .id = ast.Node.Id.ParamDecl },862 .base = ast.Node{ .id = ast.Node.Id.ParamDecl },
796 .comptime_token = null,863 .comptime_token = null,
797 .noalias_token = null,864 .noalias_token = null,
798 .name_token = null,865 .name_token = null,
799 .type_node = undefined,866 .type_node = undefined,
800 .var_args_token = null,867 .var_args_token = null,
801 });868 };
802 try fn_proto.params.push(&param_decl.base);869 try fn_proto.params.push(&param_decl.base);
803870
804 stack.append(State{871 stack.append(State{
...@@ -877,13 +944,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -877,13 +944,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
877 const token_ptr = token.ptr;944 const token_ptr = token.ptr;
878 switch (token_ptr.id) {945 switch (token_ptr.id) {
879 Token.Id.LBrace => {946 Token.Id.LBrace => {
880 const block = try arena.create(ast.Node.Block{947 const block = try arena.create(ast.Node.Block);
948 block.* = ast.Node.Block{
881 .base = ast.Node{ .id = ast.Node.Id.Block },949 .base = ast.Node{ .id = ast.Node.Id.Block },
882 .label = ctx.label,950 .label = ctx.label,
883 .lbrace = token_index,951 .lbrace = token_index,
884 .statements = ast.Node.Block.StatementList.init(arena),952 .statements = ast.Node.Block.StatementList.init(arena),
885 .rbrace = undefined,953 .rbrace = undefined,
886 });954 };
887 ctx.opt_ctx.store(&block.base);955 ctx.opt_ctx.store(&block.base);
888 stack.append(State{ .Block = block }) catch unreachable;956 stack.append(State{ .Block = block }) catch unreachable;
889 continue;957 continue;
...@@ -970,7 +1038,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -970,7 +1038,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
970 }1038 }
971 },1039 },
972 State.While => |ctx| {1040 State.While => |ctx| {
973 const node = try arena.create(ast.Node.While{1041 const node = try arena.create(ast.Node.While);
1042 node.* = ast.Node.While{
974 .base = ast.Node{ .id = ast.Node.Id.While },1043 .base = ast.Node{ .id = ast.Node.Id.While },
975 .label = ctx.label,1044 .label = ctx.label,
976 .inline_token = ctx.inline_token,1045 .inline_token = ctx.inline_token,
...@@ -980,7 +1049,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -980,7 +1049,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
980 .continue_expr = null,1049 .continue_expr = null,
981 .body = undefined,1050 .body = undefined,
982 .@"else" = null,1051 .@"else" = null,
983 });1052 };
984 ctx.opt_ctx.store(&node.base);1053 ctx.opt_ctx.store(&node.base);
985 stack.append(State{ .Else = &node.@"else" }) catch unreachable;1054 stack.append(State{ .Else = &node.@"else" }) catch unreachable;
986 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } });1055 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } });
...@@ -999,7 +1068,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -999,7 +1068,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
999 continue;1068 continue;
1000 },1069 },
1001 State.For => |ctx| {1070 State.For => |ctx| {
1002 const node = try arena.create(ast.Node.For{1071 const node = try arena.create(ast.Node.For);
1072 node.* = ast.Node.For{
1003 .base = ast.Node{ .id = ast.Node.Id.For },1073 .base = ast.Node{ .id = ast.Node.Id.For },
1004 .label = ctx.label,1074 .label = ctx.label,
1005 .inline_token = ctx.inline_token,1075 .inline_token = ctx.inline_token,
...@@ -1008,7 +1078,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1008,7 +1078,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1008 .payload = null,1078 .payload = null,
1009 .body = undefined,1079 .body = undefined,
1010 .@"else" = null,1080 .@"else" = null,
1011 });1081 };
1012 ctx.opt_ctx.store(&node.base);1082 ctx.opt_ctx.store(&node.base);
1013 stack.append(State{ .Else = &node.@"else" }) catch unreachable;1083 stack.append(State{ .Else = &node.@"else" }) catch unreachable;
1014 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } });1084 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } });
...@@ -1020,12 +1090,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1020,12 +1090,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1020 },1090 },
1021 State.Else => |dest| {1091 State.Else => |dest| {
1022 if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| {1092 if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| {
1023 const node = try arena.create(ast.Node.Else{1093 const node = try arena.create(ast.Node.Else);
1094 node.* = ast.Node.Else{
1024 .base = ast.Node{ .id = ast.Node.Id.Else },1095 .base = ast.Node{ .id = ast.Node.Id.Else },
1025 .else_token = else_token,1096 .else_token = else_token,
1026 .payload = null,1097 .payload = null,
1027 .body = undefined,1098 .body = undefined,
1028 });1099 };
1029 dest.* = node;1100 dest.* = node;
10301101
1031 stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }) catch unreachable;1102 stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }) catch unreachable;
...@@ -1073,6 +1144,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1073,6 +1144,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1073 .VarDecl = VarDeclCtx{1144 .VarDecl = VarDeclCtx{
1074 .comments = null,1145 .comments = null,
1075 .visib_token = null,1146 .visib_token = null,
1147 .thread_local_token = null,
1076 .comptime_token = null,1148 .comptime_token = null,
1077 .extern_export_token = null,1149 .extern_export_token = null,
1078 .lib_name = null,1150 .lib_name = null,
...@@ -1083,11 +1155,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1083,11 +1155,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1083 continue;1155 continue;
1084 },1156 },
1085 Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => {1157 Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => {
1086 const node = try arena.create(ast.Node.Defer{1158 const node = try arena.create(ast.Node.Defer);
1159 node.* = ast.Node.Defer{
1087 .base = ast.Node{ .id = ast.Node.Id.Defer },1160 .base = ast.Node{ .id = ast.Node.Id.Defer },
1088 .defer_token = token_index,1161 .defer_token = token_index,
1089 .expr = undefined,1162 .expr = undefined,
1090 });1163 };
1091 const node_ptr = try block.statements.addOne();1164 const node_ptr = try block.statements.addOne();
1092 node_ptr.* = &node.base;1165 node_ptr.* = &node.base;
10931166
...@@ -1096,13 +1169,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1096,13 +1169,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1096 continue;1169 continue;
1097 },1170 },
1098 Token.Id.LBrace => {1171 Token.Id.LBrace => {
1099 const inner_block = try arena.create(ast.Node.Block{1172 const inner_block = try arena.create(ast.Node.Block);
1173 inner_block.* = ast.Node.Block{
1100 .base = ast.Node{ .id = ast.Node.Id.Block },1174 .base = ast.Node{ .id = ast.Node.Id.Block },
1101 .label = null,1175 .label = null,
1102 .lbrace = token_index,1176 .lbrace = token_index,
1103 .statements = ast.Node.Block.StatementList.init(arena),1177 .statements = ast.Node.Block.StatementList.init(arena),
1104 .rbrace = undefined,1178 .rbrace = undefined,
1105 });1179 };
1106 try block.statements.push(&inner_block.base);1180 try block.statements.push(&inner_block.base);
11071181
1108 stack.append(State{ .Block = inner_block }) catch unreachable;1182 stack.append(State{ .Block = inner_block }) catch unreachable;
...@@ -1127,6 +1201,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1127,6 +1201,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1127 .VarDecl = VarDeclCtx{1201 .VarDecl = VarDeclCtx{
1128 .comments = null,1202 .comments = null,
1129 .visib_token = null,1203 .visib_token = null,
1204 .thread_local_token = null,
1130 .comptime_token = ctx.comptime_token,1205 .comptime_token = ctx.comptime_token,
1131 .extern_export_token = null,1206 .extern_export_token = null,
1132 .lib_name = null,1207 .lib_name = null,
...@@ -1164,14 +1239,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1164,14 +1239,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1164 continue;1239 continue;
1165 }1240 }
11661241
1167 const node = try arena.create(ast.Node.AsmOutput{1242 const node = try arena.create(ast.Node.AsmOutput);
1243 node.* = ast.Node.AsmOutput{
1168 .base = ast.Node{ .id = ast.Node.Id.AsmOutput },1244 .base = ast.Node{ .id = ast.Node.Id.AsmOutput },
1169 .lbracket = lbracket_index,1245 .lbracket = lbracket_index,
1170 .symbolic_name = undefined,1246 .symbolic_name = undefined,
1171 .constraint = undefined,1247 .constraint = undefined,
1172 .kind = undefined,1248 .kind = undefined,
1173 .rparen = undefined,1249 .rparen = undefined,
1174 });1250 };
1175 try items.push(node);1251 try items.push(node);
11761252
1177 stack.append(State{ .AsmOutputItems = items }) catch unreachable;1253 stack.append(State{ .AsmOutputItems = items }) catch unreachable;
...@@ -1218,14 +1294,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1218,14 +1294,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1218 continue;1294 continue;
1219 }1295 }
12201296
1221 const node = try arena.create(ast.Node.AsmInput{1297 const node = try arena.create(ast.Node.AsmInput);
1298 node.* = ast.Node.AsmInput{
1222 .base = ast.Node{ .id = ast.Node.Id.AsmInput },1299 .base = ast.Node{ .id = ast.Node.Id.AsmInput },
1223 .lbracket = lbracket_index,1300 .lbracket = lbracket_index,
1224 .symbolic_name = undefined,1301 .symbolic_name = undefined,
1225 .constraint = undefined,1302 .constraint = undefined,
1226 .expr = undefined,1303 .expr = undefined,
1227 .rparen = undefined,1304 .rparen = undefined,
1228 });1305 };
1229 try items.push(node);1306 try items.push(node);
12301307
1231 stack.append(State{ .AsmInputItems = items }) catch unreachable;1308 stack.append(State{ .AsmInputItems = items }) catch unreachable;
...@@ -1283,12 +1360,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1283,12 +1360,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1283 continue;1360 continue;
1284 }1361 }
12851362
1286 const node = try arena.create(ast.Node.FieldInitializer{1363 const node = try arena.create(ast.Node.FieldInitializer);
1364 node.* = ast.Node.FieldInitializer{
1287 .base = ast.Node{ .id = ast.Node.Id.FieldInitializer },1365 .base = ast.Node{ .id = ast.Node.Id.FieldInitializer },
1288 .period_token = undefined,1366 .period_token = undefined,
1289 .name_token = undefined,1367 .name_token = undefined,
1290 .expr = undefined,1368 .expr = undefined,
1291 });1369 };
1292 try list_state.list.push(&node.base);1370 try list_state.list.push(&node.base);
12931371
1294 stack.append(State{ .FieldInitListCommaOrEnd = list_state }) catch unreachable;1372 stack.append(State{ .FieldInitListCommaOrEnd = list_state }) catch unreachable;
...@@ -1390,13 +1468,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1390,13 +1468,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1390 }1468 }
13911469
1392 const comments = try eatDocComments(arena, &tok_it, &tree);1470 const comments = try eatDocComments(arena, &tok_it, &tree);
1393 const node = try arena.create(ast.Node.SwitchCase{1471 const node = try arena.create(ast.Node.SwitchCase);
1472 node.* = ast.Node.SwitchCase{
1394 .base = ast.Node{ .id = ast.Node.Id.SwitchCase },1473 .base = ast.Node{ .id = ast.Node.Id.SwitchCase },
1395 .items = ast.Node.SwitchCase.ItemList.init(arena),1474 .items = ast.Node.SwitchCase.ItemList.init(arena),
1396 .payload = null,1475 .payload = null,
1397 .expr = undefined,1476 .expr = undefined,
1398 .arrow_token = undefined,1477 .arrow_token = undefined,
1399 });1478 };
1400 try list_state.list.push(&node.base);1479 try list_state.list.push(&node.base);
1401 try stack.append(State{ .SwitchCaseCommaOrEnd = list_state });1480 try stack.append(State{ .SwitchCaseCommaOrEnd = list_state });
1402 try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } });1481 try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } });
...@@ -1427,10 +1506,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1427,10 +1506,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1427 const token_index = token.index;1506 const token_index = token.index;
1428 const token_ptr = token.ptr;1507 const token_ptr = token.ptr;
1429 if (token_ptr.id == Token.Id.Keyword_else) {1508 if (token_ptr.id == Token.Id.Keyword_else) {
1430 const else_node = try arena.create(ast.Node.SwitchElse{1509 const else_node = try arena.create(ast.Node.SwitchElse);
1510 else_node.* = ast.Node.SwitchElse{
1431 .base = ast.Node{ .id = ast.Node.Id.SwitchElse },1511 .base = ast.Node{ .id = ast.Node.Id.SwitchElse },
1432 .token = token_index,1512 .token = token_index,
1433 });1513 };
1434 try switch_case.items.push(&else_node.base);1514 try switch_case.items.push(&else_node.base);
14351515
1436 try stack.append(State{1516 try stack.append(State{
...@@ -1537,7 +1617,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1537,7 +1617,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
15371617
1538 State.ExternType => |ctx| {1618 State.ExternType => |ctx| {
1539 if (eatToken(&tok_it, &tree, Token.Id.Keyword_fn)) |fn_token| {1619 if (eatToken(&tok_it, &tree, Token.Id.Keyword_fn)) |fn_token| {
1540 const fn_proto = try arena.create(ast.Node.FnProto{1620 const fn_proto = try arena.create(ast.Node.FnProto);
1621 fn_proto.* = ast.Node.FnProto{
1541 .base = ast.Node{ .id = ast.Node.Id.FnProto },1622 .base = ast.Node{ .id = ast.Node.Id.FnProto },
1542 .doc_comments = ctx.comments,1623 .doc_comments = ctx.comments,
1543 .visib_token = null,1624 .visib_token = null,
...@@ -1553,7 +1634,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1553,7 +1634,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1553 .lib_name = null,1634 .lib_name = null,
1554 .align_expr = null,1635 .align_expr = null,
1555 .section_expr = null,1636 .section_expr = null,
1556 });1637 };
1557 ctx.opt_ctx.store(&fn_proto.base);1638 ctx.opt_ctx.store(&fn_proto.base);
1558 stack.append(State{ .FnProto = fn_proto }) catch unreachable;1639 stack.append(State{ .FnProto = fn_proto }) catch unreachable;
1559 continue;1640 continue;
...@@ -1711,12 +1792,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1711,12 +1792,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1711 continue;1792 continue;
1712 }1793 }
17131794
1714 const node = try arena.create(ast.Node.Payload{1795 const node = try arena.create(ast.Node.Payload);
1796 node.* = ast.Node.Payload{
1715 .base = ast.Node{ .id = ast.Node.Id.Payload },1797 .base = ast.Node{ .id = ast.Node.Id.Payload },
1716 .lpipe = token_index,1798 .lpipe = token_index,
1717 .error_symbol = undefined,1799 .error_symbol = undefined,
1718 .rpipe = undefined,1800 .rpipe = undefined,
1719 });1801 };
1720 opt_ctx.store(&node.base);1802 opt_ctx.store(&node.base);
17211803
1722 stack.append(State{1804 stack.append(State{
...@@ -1747,13 +1829,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1747,13 +1829,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1747 continue;1829 continue;
1748 }1830 }
17491831
1750 const node = try arena.create(ast.Node.PointerPayload{1832 const node = try arena.create(ast.Node.PointerPayload);
1833 node.* = ast.Node.PointerPayload{
1751 .base = ast.Node{ .id = ast.Node.Id.PointerPayload },1834 .base = ast.Node{ .id = ast.Node.Id.PointerPayload },
1752 .lpipe = token_index,1835 .lpipe = token_index,
1753 .ptr_token = null,1836 .ptr_token = null,
1754 .value_symbol = undefined,1837 .value_symbol = undefined,
1755 .rpipe = undefined,1838 .rpipe = undefined,
1756 });1839 };
1757 opt_ctx.store(&node.base);1840 opt_ctx.store(&node.base);
17581841
1759 try stack.append(State{1842 try stack.append(State{
...@@ -1790,14 +1873,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1790,14 +1873,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1790 continue;1873 continue;
1791 }1874 }
17921875
1793 const node = try arena.create(ast.Node.PointerIndexPayload{1876 const node = try arena.create(ast.Node.PointerIndexPayload);
1877 node.* = ast.Node.PointerIndexPayload{
1794 .base = ast.Node{ .id = ast.Node.Id.PointerIndexPayload },1878 .base = ast.Node{ .id = ast.Node.Id.PointerIndexPayload },
1795 .lpipe = token_index,1879 .lpipe = token_index,
1796 .ptr_token = null,1880 .ptr_token = null,
1797 .value_symbol = undefined,1881 .value_symbol = undefined,
1798 .index_symbol = null,1882 .index_symbol = null,
1799 .rpipe = undefined,1883 .rpipe = undefined,
1800 });1884 };
1801 opt_ctx.store(&node.base);1885 opt_ctx.store(&node.base);
18021886
1803 stack.append(State{1887 stack.append(State{
...@@ -1824,12 +1908,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1824,12 +1908,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1824 const token_ptr = token.ptr;1908 const token_ptr = token.ptr;
1825 switch (token_ptr.id) {1909 switch (token_ptr.id) {
1826 Token.Id.Keyword_return, Token.Id.Keyword_break, Token.Id.Keyword_continue => {1910 Token.Id.Keyword_return, Token.Id.Keyword_break, Token.Id.Keyword_continue => {
1827 const node = try arena.create(ast.Node.ControlFlowExpression{1911 const node = try arena.create(ast.Node.ControlFlowExpression);
1912 node.* = ast.Node.ControlFlowExpression{
1828 .base = ast.Node{ .id = ast.Node.Id.ControlFlowExpression },1913 .base = ast.Node{ .id = ast.Node.Id.ControlFlowExpression },
1829 .ltoken = token_index,1914 .ltoken = token_index,
1830 .kind = undefined,1915 .kind = undefined,
1831 .rhs = null,1916 .rhs = null,
1832 });1917 };
1833 opt_ctx.store(&node.base);1918 opt_ctx.store(&node.base);
18341919
1835 stack.append(State{ .Expression = OptionalCtx{ .Optional = &node.rhs } }) catch unreachable;1920 stack.append(State{ .Expression = OptionalCtx{ .Optional = &node.rhs } }) catch unreachable;
...@@ -1853,7 +1938,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1853,7 +1938,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1853 continue;1938 continue;
1854 },1939 },
1855 Token.Id.Keyword_try, Token.Id.Keyword_cancel, Token.Id.Keyword_resume => {1940 Token.Id.Keyword_try, Token.Id.Keyword_cancel, Token.Id.Keyword_resume => {
1856 const node = try arena.create(ast.Node.PrefixOp{1941 const node = try arena.create(ast.Node.PrefixOp);
1942 node.* = ast.Node.PrefixOp{
1857 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },1943 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
1858 .op_token = token_index,1944 .op_token = token_index,
1859 .op = switch (token_ptr.id) {1945 .op = switch (token_ptr.id) {
...@@ -1863,7 +1949,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1863,7 +1949,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1863 else => unreachable,1949 else => unreachable,
1864 },1950 },
1865 .rhs = undefined,1951 .rhs = undefined,
1866 });1952 };
1867 opt_ctx.store(&node.base);1953 opt_ctx.store(&node.base);
18681954
1869 stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;1955 stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
...@@ -1887,13 +1973,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1887,13 +1973,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1887 const lhs = opt_ctx.get() orelse continue;1973 const lhs = opt_ctx.get() orelse continue;
18881974
1889 if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| {1975 if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| {
1890 const node = try arena.create(ast.Node.InfixOp{1976 const node = try arena.create(ast.Node.InfixOp);
1977 node.* = ast.Node.InfixOp{
1891 .base = ast.Node{ .id = ast.Node.Id.InfixOp },1978 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
1892 .lhs = lhs,1979 .lhs = lhs,
1893 .op_token = ellipsis3,1980 .op_token = ellipsis3,
1894 .op = ast.Node.InfixOp.Op.Range,1981 .op = ast.Node.InfixOp.Op.Range,
1895 .rhs = undefined,1982 .rhs = undefined,
1896 });1983 };
1897 opt_ctx.store(&node.base);1984 opt_ctx.store(&node.base);
1898 stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;1985 stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
1899 continue;1986 continue;
...@@ -1912,13 +1999,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1912,13 +1999,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1912 const token_index = token.index;1999 const token_index = token.index;
1913 const token_ptr = token.ptr;2000 const token_ptr = token.ptr;
1914 if (tokenIdToAssignment(token_ptr.id)) |ass_id| {2001 if (tokenIdToAssignment(token_ptr.id)) |ass_id| {
1915 const node = try arena.create(ast.Node.InfixOp{2002 const node = try arena.create(ast.Node.InfixOp);
2003 node.* = ast.Node.InfixOp{
1916 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2004 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
1917 .lhs = lhs,2005 .lhs = lhs,
1918 .op_token = token_index,2006 .op_token = token_index,
1919 .op = ass_id,2007 .op = ass_id,
1920 .rhs = undefined,2008 .rhs = undefined,
1921 });2009 };
1922 opt_ctx.store(&node.base);2010 opt_ctx.store(&node.base);
1923 stack.append(State{ .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2011 stack.append(State{ .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1924 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } });2012 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } });
...@@ -1942,13 +2030,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1942,13 +2030,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1942 const token_index = token.index;2030 const token_index = token.index;
1943 const token_ptr = token.ptr;2031 const token_ptr = token.ptr;
1944 if (tokenIdToUnwrapExpr(token_ptr.id)) |unwrap_id| {2032 if (tokenIdToUnwrapExpr(token_ptr.id)) |unwrap_id| {
1945 const node = try arena.create(ast.Node.InfixOp{2033 const node = try arena.create(ast.Node.InfixOp);
2034 node.* = ast.Node.InfixOp{
1946 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2035 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
1947 .lhs = lhs,2036 .lhs = lhs,
1948 .op_token = token_index,2037 .op_token = token_index,
1949 .op = unwrap_id,2038 .op = unwrap_id,
1950 .rhs = undefined,2039 .rhs = undefined,
1951 });2040 };
1952 opt_ctx.store(&node.base);2041 opt_ctx.store(&node.base);
19532042
1954 stack.append(State{ .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2043 stack.append(State{ .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
...@@ -1974,13 +2063,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1974,13 +2063,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1974 const lhs = opt_ctx.get() orelse continue;2063 const lhs = opt_ctx.get() orelse continue;
19752064
1976 if (eatToken(&tok_it, &tree, Token.Id.Keyword_or)) |or_token| {2065 if (eatToken(&tok_it, &tree, Token.Id.Keyword_or)) |or_token| {
1977 const node = try arena.create(ast.Node.InfixOp{2066 const node = try arena.create(ast.Node.InfixOp);
2067 node.* = ast.Node.InfixOp{
1978 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2068 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
1979 .lhs = lhs,2069 .lhs = lhs,
1980 .op_token = or_token,2070 .op_token = or_token,
1981 .op = ast.Node.InfixOp.Op.BoolOr,2071 .op = ast.Node.InfixOp.Op.BoolOr,
1982 .rhs = undefined,2072 .rhs = undefined,
1983 });2073 };
1984 opt_ctx.store(&node.base);2074 opt_ctx.store(&node.base);
1985 stack.append(State{ .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2075 stack.append(State{ .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1986 try stack.append(State{ .BoolAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2076 try stack.append(State{ .BoolAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
...@@ -1998,13 +2088,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1998,13 +2088,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1998 const lhs = opt_ctx.get() orelse continue;2088 const lhs = opt_ctx.get() orelse continue;
19992089
2000 if (eatToken(&tok_it, &tree, Token.Id.Keyword_and)) |and_token| {2090 if (eatToken(&tok_it, &tree, Token.Id.Keyword_and)) |and_token| {
2001 const node = try arena.create(ast.Node.InfixOp{2091 const node = try arena.create(ast.Node.InfixOp);
2092 node.* = ast.Node.InfixOp{
2002 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2093 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2003 .lhs = lhs,2094 .lhs = lhs,
2004 .op_token = and_token,2095 .op_token = and_token,
2005 .op = ast.Node.InfixOp.Op.BoolAnd,2096 .op = ast.Node.InfixOp.Op.BoolAnd,
2006 .rhs = undefined,2097 .rhs = undefined,
2007 });2098 };
2008 opt_ctx.store(&node.base);2099 opt_ctx.store(&node.base);
2009 stack.append(State{ .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2100 stack.append(State{ .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2010 try stack.append(State{ .ComparisonExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2101 try stack.append(State{ .ComparisonExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
...@@ -2025,13 +2116,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2025,13 +2116,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2025 const token_index = token.index;2116 const token_index = token.index;
2026 const token_ptr = token.ptr;2117 const token_ptr = token.ptr;
2027 if (tokenIdToComparison(token_ptr.id)) |comp_id| {2118 if (tokenIdToComparison(token_ptr.id)) |comp_id| {
2028 const node = try arena.create(ast.Node.InfixOp{2119 const node = try arena.create(ast.Node.InfixOp);
2120 node.* = ast.Node.InfixOp{
2029 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2121 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2030 .lhs = lhs,2122 .lhs = lhs,
2031 .op_token = token_index,2123 .op_token = token_index,
2032 .op = comp_id,2124 .op = comp_id,
2033 .rhs = undefined,2125 .rhs = undefined,
2034 });2126 };
2035 opt_ctx.store(&node.base);2127 opt_ctx.store(&node.base);
2036 stack.append(State{ .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2128 stack.append(State{ .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2037 try stack.append(State{ .BinaryOrExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2129 try stack.append(State{ .BinaryOrExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
...@@ -2052,13 +2144,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2052,13 +2144,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2052 const lhs = opt_ctx.get() orelse continue;2144 const lhs = opt_ctx.get() orelse continue;
20532145
2054 if (eatToken(&tok_it, &tree, Token.Id.Pipe)) |pipe| {2146 if (eatToken(&tok_it, &tree, Token.Id.Pipe)) |pipe| {
2055 const node = try arena.create(ast.Node.InfixOp{2147 const node = try arena.create(ast.Node.InfixOp);
2148 node.* = ast.Node.InfixOp{
2056 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2149 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2057 .lhs = lhs,2150 .lhs = lhs,
2058 .op_token = pipe,2151 .op_token = pipe,
2059 .op = ast.Node.InfixOp.Op.BitOr,2152 .op = ast.Node.InfixOp.Op.BitOr,
2060 .rhs = undefined,2153 .rhs = undefined,
2061 });2154 };
2062 opt_ctx.store(&node.base);2155 opt_ctx.store(&node.base);
2063 stack.append(State{ .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2156 stack.append(State{ .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2064 try stack.append(State{ .BinaryXorExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2157 try stack.append(State{ .BinaryXorExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
...@@ -2076,13 +2169,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2076,13 +2169,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2076 const lhs = opt_ctx.get() orelse continue;2169 const lhs = opt_ctx.get() orelse continue;
20772170
2078 if (eatToken(&tok_it, &tree, Token.Id.Caret)) |caret| {2171 if (eatToken(&tok_it, &tree, Token.Id.Caret)) |caret| {
2079 const node = try arena.create(ast.Node.InfixOp{2172 const node = try arena.create(ast.Node.InfixOp);
2173 node.* = ast.Node.InfixOp{
2080 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2174 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2081 .lhs = lhs,2175 .lhs = lhs,
2082 .op_token = caret,2176 .op_token = caret,
2083 .op = ast.Node.InfixOp.Op.BitXor,2177 .op = ast.Node.InfixOp.Op.BitXor,
2084 .rhs = undefined,2178 .rhs = undefined,
2085 });2179 };
2086 opt_ctx.store(&node.base);2180 opt_ctx.store(&node.base);
2087 stack.append(State{ .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2181 stack.append(State{ .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2088 try stack.append(State{ .BinaryAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2182 try stack.append(State{ .BinaryAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
...@@ -2100,13 +2194,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2100,13 +2194,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2100 const lhs = opt_ctx.get() orelse continue;2194 const lhs = opt_ctx.get() orelse continue;
21012195
2102 if (eatToken(&tok_it, &tree, Token.Id.Ampersand)) |ampersand| {2196 if (eatToken(&tok_it, &tree, Token.Id.Ampersand)) |ampersand| {
2103 const node = try arena.create(ast.Node.InfixOp{2197 const node = try arena.create(ast.Node.InfixOp);
2198 node.* = ast.Node.InfixOp{
2104 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2199 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2105 .lhs = lhs,2200 .lhs = lhs,
2106 .op_token = ampersand,2201 .op_token = ampersand,
2107 .op = ast.Node.InfixOp.Op.BitAnd,2202 .op = ast.Node.InfixOp.Op.BitAnd,
2108 .rhs = undefined,2203 .rhs = undefined,
2109 });2204 };
2110 opt_ctx.store(&node.base);2205 opt_ctx.store(&node.base);
2111 stack.append(State{ .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2206 stack.append(State{ .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2112 try stack.append(State{ .BitShiftExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2207 try stack.append(State{ .BitShiftExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
...@@ -2127,13 +2222,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2127,13 +2222,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2127 const token_index = token.index;2222 const token_index = token.index;
2128 const token_ptr = token.ptr;2223 const token_ptr = token.ptr;
2129 if (tokenIdToBitShift(token_ptr.id)) |bitshift_id| {2224 if (tokenIdToBitShift(token_ptr.id)) |bitshift_id| {
2130 const node = try arena.create(ast.Node.InfixOp{2225 const node = try arena.create(ast.Node.InfixOp);
2226 node.* = ast.Node.InfixOp{
2131 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2227 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2132 .lhs = lhs,2228 .lhs = lhs,
2133 .op_token = token_index,2229 .op_token = token_index,
2134 .op = bitshift_id,2230 .op = bitshift_id,
2135 .rhs = undefined,2231 .rhs = undefined,
2136 });2232 };
2137 opt_ctx.store(&node.base);2233 opt_ctx.store(&node.base);
2138 stack.append(State{ .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2234 stack.append(State{ .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2139 try stack.append(State{ .AdditionExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2235 try stack.append(State{ .AdditionExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
...@@ -2157,13 +2253,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2157,13 +2253,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2157 const token_index = token.index;2253 const token_index = token.index;
2158 const token_ptr = token.ptr;2254 const token_ptr = token.ptr;
2159 if (tokenIdToAddition(token_ptr.id)) |add_id| {2255 if (tokenIdToAddition(token_ptr.id)) |add_id| {
2160 const node = try arena.create(ast.Node.InfixOp{2256 const node = try arena.create(ast.Node.InfixOp);
2257 node.* = ast.Node.InfixOp{
2161 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2258 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2162 .lhs = lhs,2259 .lhs = lhs,
2163 .op_token = token_index,2260 .op_token = token_index,
2164 .op = add_id,2261 .op = add_id,
2165 .rhs = undefined,2262 .rhs = undefined,
2166 });2263 };
2167 opt_ctx.store(&node.base);2264 opt_ctx.store(&node.base);
2168 stack.append(State{ .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2265 stack.append(State{ .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2169 try stack.append(State{ .MultiplyExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2266 try stack.append(State{ .MultiplyExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
...@@ -2187,13 +2284,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2187,13 +2284,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2187 const token_index = token.index;2284 const token_index = token.index;
2188 const token_ptr = token.ptr;2285 const token_ptr = token.ptr;
2189 if (tokenIdToMultiply(token_ptr.id)) |mult_id| {2286 if (tokenIdToMultiply(token_ptr.id)) |mult_id| {
2190 const node = try arena.create(ast.Node.InfixOp{2287 const node = try arena.create(ast.Node.InfixOp);
2288 node.* = ast.Node.InfixOp{
2191 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2289 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2192 .lhs = lhs,2290 .lhs = lhs,
2193 .op_token = token_index,2291 .op_token = token_index,
2194 .op = mult_id,2292 .op = mult_id,
2195 .rhs = undefined,2293 .rhs = undefined,
2196 });2294 };
2197 opt_ctx.store(&node.base);2295 opt_ctx.store(&node.base);
2198 stack.append(State{ .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2296 stack.append(State{ .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2199 try stack.append(State{ .CurlySuffixExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2297 try stack.append(State{ .CurlySuffixExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
...@@ -2215,12 +2313,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2215,12 +2313,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2215 const lhs = opt_ctx.get() orelse continue;2313 const lhs = opt_ctx.get() orelse continue;
22162314
2217 if (tok_it.peek().?.id == Token.Id.Period) {2315 if (tok_it.peek().?.id == Token.Id.Period) {
2218 const node = try arena.create(ast.Node.SuffixOp{2316 const node = try arena.create(ast.Node.SuffixOp);
2317 node.* = ast.Node.SuffixOp{
2219 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },2318 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
2220 .lhs = lhs,2319 .lhs = lhs,
2221 .op = ast.Node.SuffixOp.Op{ .StructInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) },2320 .op = ast.Node.SuffixOp.Op{ .StructInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) },
2222 .rtoken = undefined,2321 .rtoken = undefined,
2223 });2322 };
2224 opt_ctx.store(&node.base);2323 opt_ctx.store(&node.base);
22252324
2226 stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2325 stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
...@@ -2234,12 +2333,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2234,12 +2333,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2234 continue;2333 continue;
2235 }2334 }
22362335
2237 const node = try arena.create(ast.Node.SuffixOp{2336 const node = try arena.create(ast.Node.SuffixOp);
2337 node.* = ast.Node.SuffixOp{
2238 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },2338 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
2239 .lhs = lhs,2339 .lhs = lhs,
2240 .op = ast.Node.SuffixOp.Op{ .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) },2340 .op = ast.Node.SuffixOp.Op{ .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) },
2241 .rtoken = undefined,2341 .rtoken = undefined,
2242 });2342 };
2243 opt_ctx.store(&node.base);2343 opt_ctx.store(&node.base);
2244 stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2344 stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2245 try stack.append(State{ .IfToken = Token.Id.LBrace });2345 try stack.append(State{ .IfToken = Token.Id.LBrace });
...@@ -2263,13 +2363,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2263,13 +2363,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2263 const lhs = opt_ctx.get() orelse continue;2363 const lhs = opt_ctx.get() orelse continue;
22642364
2265 if (eatToken(&tok_it, &tree, Token.Id.Bang)) |bang| {2365 if (eatToken(&tok_it, &tree, Token.Id.Bang)) |bang| {
2266 const node = try arena.create(ast.Node.InfixOp{2366 const node = try arena.create(ast.Node.InfixOp);
2367 node.* = ast.Node.InfixOp{
2267 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2368 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2268 .lhs = lhs,2369 .lhs = lhs,
2269 .op_token = bang,2370 .op_token = bang,
2270 .op = ast.Node.InfixOp.Op.ErrorUnion,2371 .op = ast.Node.InfixOp.Op.ErrorUnion,
2271 .rhs = undefined,2372 .rhs = undefined,
2272 });2373 };
2273 opt_ctx.store(&node.base);2374 opt_ctx.store(&node.base);
2274 stack.append(State{ .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable;2375 stack.append(State{ .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable;
2275 try stack.append(State{ .PrefixOpExpression = OptionalCtx{ .Required = &node.rhs } });2376 try stack.append(State{ .PrefixOpExpression = OptionalCtx{ .Required = &node.rhs } });
...@@ -2282,22 +2383,24 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2282,22 +2383,24 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2282 const token_index = token.index;2383 const token_index = token.index;
2283 const token_ptr = token.ptr;2384 const token_ptr = token.ptr;
2284 if (tokenIdToPrefixOp(token_ptr.id)) |prefix_id| {2385 if (tokenIdToPrefixOp(token_ptr.id)) |prefix_id| {
2285 var node = try arena.create(ast.Node.PrefixOp{2386 var node = try arena.create(ast.Node.PrefixOp);
2387 node.* = ast.Node.PrefixOp{
2286 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },2388 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
2287 .op_token = token_index,2389 .op_token = token_index,
2288 .op = prefix_id,2390 .op = prefix_id,
2289 .rhs = undefined,2391 .rhs = undefined,
2290 });2392 };
2291 opt_ctx.store(&node.base);2393 opt_ctx.store(&node.base);
22922394
2293 // Treat '**' token as two pointer types2395 // Treat '**' token as two pointer types
2294 if (token_ptr.id == Token.Id.AsteriskAsterisk) {2396 if (token_ptr.id == Token.Id.AsteriskAsterisk) {
2295 const child = try arena.create(ast.Node.PrefixOp{2397 const child = try arena.create(ast.Node.PrefixOp);
2398 child.* = ast.Node.PrefixOp{
2296 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },2399 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
2297 .op_token = token_index,2400 .op_token = token_index,
2298 .op = prefix_id,2401 .op = prefix_id,
2299 .rhs = undefined,2402 .rhs = undefined,
2300 });2403 };
2301 node.rhs = &child.base;2404 node.rhs = &child.base;
2302 node = child;2405 node = child;
2303 }2406 }
...@@ -2316,12 +2419,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2316,12 +2419,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
23162419
2317 State.SuffixOpExpressionBegin => |opt_ctx| {2420 State.SuffixOpExpressionBegin => |opt_ctx| {
2318 if (eatToken(&tok_it, &tree, Token.Id.Keyword_async)) |async_token| {2421 if (eatToken(&tok_it, &tree, Token.Id.Keyword_async)) |async_token| {
2319 const async_node = try arena.create(ast.Node.AsyncAttribute{2422 const async_node = try arena.create(ast.Node.AsyncAttribute);
2423 async_node.* = ast.Node.AsyncAttribute{
2320 .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },2424 .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },
2321 .async_token = async_token,2425 .async_token = async_token,
2322 .allocator_type = null,2426 .allocator_type = null,
2323 .rangle_bracket = null,2427 .rangle_bracket = null,
2324 });2428 };
2325 stack.append(State{2429 stack.append(State{
2326 .AsyncEnd = AsyncEndCtx{2430 .AsyncEnd = AsyncEndCtx{
2327 .ctx = opt_ctx,2431 .ctx = opt_ctx,
...@@ -2347,7 +2451,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2347,7 +2451,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2347 const token_ptr = token.ptr;2451 const token_ptr = token.ptr;
2348 switch (token_ptr.id) {2452 switch (token_ptr.id) {
2349 Token.Id.LParen => {2453 Token.Id.LParen => {
2350 const node = try arena.create(ast.Node.SuffixOp{2454 const node = try arena.create(ast.Node.SuffixOp);
2455 node.* = ast.Node.SuffixOp{
2351 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },2456 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
2352 .lhs = lhs,2457 .lhs = lhs,
2353 .op = ast.Node.SuffixOp.Op{2458 .op = ast.Node.SuffixOp.Op{
...@@ -2357,7 +2462,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2357,7 +2462,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2357 },2462 },
2358 },2463 },
2359 .rtoken = undefined,2464 .rtoken = undefined,
2360 });2465 };
2361 opt_ctx.store(&node.base);2466 opt_ctx.store(&node.base);
23622467
2363 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2468 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
...@@ -2371,12 +2476,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2371,12 +2476,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2371 continue;2476 continue;
2372 },2477 },
2373 Token.Id.LBracket => {2478 Token.Id.LBracket => {
2374 const node = try arena.create(ast.Node.SuffixOp{2479 const node = try arena.create(ast.Node.SuffixOp);
2480 node.* = ast.Node.SuffixOp{
2375 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },2481 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
2376 .lhs = lhs,2482 .lhs = lhs,
2377 .op = ast.Node.SuffixOp.Op{ .ArrayAccess = undefined },2483 .op = ast.Node.SuffixOp.Op{ .ArrayAccess = undefined },
2378 .rtoken = undefined,2484 .rtoken = undefined,
2379 });2485 };
2380 opt_ctx.store(&node.base);2486 opt_ctx.store(&node.base);
23812487
2382 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2488 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
...@@ -2386,34 +2492,37 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2386,34 +2492,37 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2386 },2492 },
2387 Token.Id.Period => {2493 Token.Id.Period => {
2388 if (eatToken(&tok_it, &tree, Token.Id.Asterisk)) |asterisk_token| {2494 if (eatToken(&tok_it, &tree, Token.Id.Asterisk)) |asterisk_token| {
2389 const node = try arena.create(ast.Node.SuffixOp{2495 const node = try arena.create(ast.Node.SuffixOp);
2496 node.* = ast.Node.SuffixOp{
2390 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },2497 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
2391 .lhs = lhs,2498 .lhs = lhs,
2392 .op = ast.Node.SuffixOp.Op.Deref,2499 .op = ast.Node.SuffixOp.Op.Deref,
2393 .rtoken = asterisk_token,2500 .rtoken = asterisk_token,
2394 });2501 };
2395 opt_ctx.store(&node.base);2502 opt_ctx.store(&node.base);
2396 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2503 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2397 continue;2504 continue;
2398 }2505 }
2399 if (eatToken(&tok_it, &tree, Token.Id.QuestionMark)) |question_token| {2506 if (eatToken(&tok_it, &tree, Token.Id.QuestionMark)) |question_token| {
2400 const node = try arena.create(ast.Node.SuffixOp{2507 const node = try arena.create(ast.Node.SuffixOp);
2508 node.* = ast.Node.SuffixOp{
2401 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },2509 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
2402 .lhs = lhs,2510 .lhs = lhs,
2403 .op = ast.Node.SuffixOp.Op.UnwrapOptional,2511 .op = ast.Node.SuffixOp.Op.UnwrapOptional,
2404 .rtoken = question_token,2512 .rtoken = question_token,
2405 });2513 };
2406 opt_ctx.store(&node.base);2514 opt_ctx.store(&node.base);
2407 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2515 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2408 continue;2516 continue;
2409 }2517 }
2410 const node = try arena.create(ast.Node.InfixOp{2518 const node = try arena.create(ast.Node.InfixOp);
2519 node.* = ast.Node.InfixOp{
2411 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2520 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2412 .lhs = lhs,2521 .lhs = lhs,
2413 .op_token = token_index,2522 .op_token = token_index,
2414 .op = ast.Node.InfixOp.Op.Period,2523 .op = ast.Node.InfixOp.Op.Period,
2415 .rhs = undefined,2524 .rhs = undefined,
2416 });2525 };
2417 opt_ctx.store(&node.base);2526 opt_ctx.store(&node.base);
24182527
2419 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2528 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
...@@ -2467,11 +2576,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2467,11 +2576,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2467 continue;2576 continue;
2468 },2577 },
2469 Token.Id.Keyword_promise => {2578 Token.Id.Keyword_promise => {
2470 const node = try arena.create(ast.Node.PromiseType{2579 const node = try arena.create(ast.Node.PromiseType);
2580 node.* = ast.Node.PromiseType{
2471 .base = ast.Node{ .id = ast.Node.Id.PromiseType },2581 .base = ast.Node{ .id = ast.Node.Id.PromiseType },
2472 .promise_token = token.index,2582 .promise_token = token.index,
2473 .result = null,2583 .result = null,
2474 });2584 };
2475 opt_ctx.store(&node.base);2585 opt_ctx.store(&node.base);
2476 const next_token = nextToken(&tok_it, &tree);2586 const next_token = nextToken(&tok_it, &tree);
2477 const next_token_index = next_token.index;2587 const next_token_index = next_token.index;
...@@ -2493,12 +2603,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2493,12 +2603,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2493 continue;2603 continue;
2494 },2604 },
2495 Token.Id.LParen => {2605 Token.Id.LParen => {
2496 const node = try arena.create(ast.Node.GroupedExpression{2606 const node = try arena.create(ast.Node.GroupedExpression);
2607 node.* = ast.Node.GroupedExpression{
2497 .base = ast.Node{ .id = ast.Node.Id.GroupedExpression },2608 .base = ast.Node{ .id = ast.Node.Id.GroupedExpression },
2498 .lparen = token.index,2609 .lparen = token.index,
2499 .expr = undefined,2610 .expr = undefined,
2500 .rparen = undefined,2611 .rparen = undefined,
2501 });2612 };
2502 opt_ctx.store(&node.base);2613 opt_ctx.store(&node.base);
25032614
2504 stack.append(State{2615 stack.append(State{
...@@ -2511,12 +2622,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2511,12 +2622,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2511 continue;2622 continue;
2512 },2623 },
2513 Token.Id.Builtin => {2624 Token.Id.Builtin => {
2514 const node = try arena.create(ast.Node.BuiltinCall{2625 const node = try arena.create(ast.Node.BuiltinCall);
2626 node.* = ast.Node.BuiltinCall{
2515 .base = ast.Node{ .id = ast.Node.Id.BuiltinCall },2627 .base = ast.Node{ .id = ast.Node.Id.BuiltinCall },
2516 .builtin_token = token.index,2628 .builtin_token = token.index,
2517 .params = ast.Node.BuiltinCall.ParamList.init(arena),2629 .params = ast.Node.BuiltinCall.ParamList.init(arena),
2518 .rparen_token = undefined,2630 .rparen_token = undefined,
2519 });2631 };
2520 opt_ctx.store(&node.base);2632 opt_ctx.store(&node.base);
25212633
2522 stack.append(State{2634 stack.append(State{
...@@ -2530,12 +2642,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2530,12 +2642,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2530 continue;2642 continue;
2531 },2643 },
2532 Token.Id.LBracket => {2644 Token.Id.LBracket => {
2533 const node = try arena.create(ast.Node.PrefixOp{2645 const node = try arena.create(ast.Node.PrefixOp);
2646 node.* = ast.Node.PrefixOp{
2534 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },2647 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
2535 .op_token = token.index,2648 .op_token = token.index,
2536 .op = undefined,2649 .op = undefined,
2537 .rhs = undefined,2650 .rhs = undefined,
2538 });2651 };
2539 opt_ctx.store(&node.base);2652 opt_ctx.store(&node.base);
25402653
2541 stack.append(State{ .SliceOrArrayType = node }) catch unreachable;2654 stack.append(State{ .SliceOrArrayType = node }) catch unreachable;
...@@ -2593,7 +2706,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2593,7 +2706,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2593 continue;2706 continue;
2594 },2707 },
2595 Token.Id.Keyword_fn => {2708 Token.Id.Keyword_fn => {
2596 const fn_proto = try arena.create(ast.Node.FnProto{2709 const fn_proto = try arena.create(ast.Node.FnProto);
2710 fn_proto.* = ast.Node.FnProto{
2597 .base = ast.Node{ .id = ast.Node.Id.FnProto },2711 .base = ast.Node{ .id = ast.Node.Id.FnProto },
2598 .doc_comments = null,2712 .doc_comments = null,
2599 .visib_token = null,2713 .visib_token = null,
...@@ -2609,13 +2723,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2609,13 +2723,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2609 .lib_name = null,2723 .lib_name = null,
2610 .align_expr = null,2724 .align_expr = null,
2611 .section_expr = null,2725 .section_expr = null,
2612 });2726 };
2613 opt_ctx.store(&fn_proto.base);2727 opt_ctx.store(&fn_proto.base);
2614 stack.append(State{ .FnProto = fn_proto }) catch unreachable;2728 stack.append(State{ .FnProto = fn_proto }) catch unreachable;
2615 continue;2729 continue;
2616 },2730 },
2617 Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {2731 Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
2618 const fn_proto = try arena.create(ast.Node.FnProto{2732 const fn_proto = try arena.create(ast.Node.FnProto);
2733 fn_proto.* = ast.Node.FnProto{
2619 .base = ast.Node{ .id = ast.Node.Id.FnProto },2734 .base = ast.Node{ .id = ast.Node.Id.FnProto },
2620 .doc_comments = null,2735 .doc_comments = null,
2621 .visib_token = null,2736 .visib_token = null,
...@@ -2631,7 +2746,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2631,7 +2746,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2631 .lib_name = null,2746 .lib_name = null,
2632 .align_expr = null,2747 .align_expr = null,
2633 .section_expr = null,2748 .section_expr = null,
2634 });2749 };
2635 opt_ctx.store(&fn_proto.base);2750 opt_ctx.store(&fn_proto.base);
2636 stack.append(State{ .FnProto = fn_proto }) catch unreachable;2751 stack.append(State{ .FnProto = fn_proto }) catch unreachable;
2637 try stack.append(State{2752 try stack.append(State{
...@@ -2643,7 +2758,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2643,7 +2758,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2643 continue;2758 continue;
2644 },2759 },
2645 Token.Id.Keyword_asm => {2760 Token.Id.Keyword_asm => {
2646 const node = try arena.create(ast.Node.Asm{2761 const node = try arena.create(ast.Node.Asm);
2762 node.* = ast.Node.Asm{
2647 .base = ast.Node{ .id = ast.Node.Id.Asm },2763 .base = ast.Node{ .id = ast.Node.Id.Asm },
2648 .asm_token = token.index,2764 .asm_token = token.index,
2649 .volatile_token = null,2765 .volatile_token = null,
...@@ -2652,7 +2768,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2652,7 +2768,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2652 .inputs = ast.Node.Asm.InputList.init(arena),2768 .inputs = ast.Node.Asm.InputList.init(arena),
2653 .clobbers = ast.Node.Asm.ClobberList.init(arena),2769 .clobbers = ast.Node.Asm.ClobberList.init(arena),
2654 .rparen = undefined,2770 .rparen = undefined,
2655 });2771 };
2656 opt_ctx.store(&node.base);2772 opt_ctx.store(&node.base);
26572773
2658 stack.append(State{2774 stack.append(State{
...@@ -2701,13 +2817,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2701,13 +2817,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
27012817
2702 State.ErrorTypeOrSetDecl => |ctx| {2818 State.ErrorTypeOrSetDecl => |ctx| {
2703 if (eatToken(&tok_it, &tree, Token.Id.LBrace) == null) {2819 if (eatToken(&tok_it, &tree, Token.Id.LBrace) == null) {
2704 const node = try arena.create(ast.Node.InfixOp{2820 const node = try arena.create(ast.Node.InfixOp);
2821 node.* = ast.Node.InfixOp{
2705 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2822 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2706 .lhs = &(try createLiteral(arena, ast.Node.ErrorType, ctx.error_token)).base,2823 .lhs = &(try createLiteral(arena, ast.Node.ErrorType, ctx.error_token)).base,
2707 .op_token = undefined,2824 .op_token = undefined,
2708 .op = ast.Node.InfixOp.Op.Period,2825 .op = ast.Node.InfixOp.Op.Period,
2709 .rhs = undefined,2826 .rhs = undefined,
2710 });2827 };
2711 ctx.opt_ctx.store(&node.base);2828 ctx.opt_ctx.store(&node.base);
2712 stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;2829 stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
2713 try stack.append(State{2830 try stack.append(State{
...@@ -2719,12 +2836,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2719,12 +2836,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2719 continue;2836 continue;
2720 }2837 }
27212838
2722 const node = try arena.create(ast.Node.ErrorSetDecl{2839 const node = try arena.create(ast.Node.ErrorSetDecl);
2840 node.* = ast.Node.ErrorSetDecl{
2723 .base = ast.Node{ .id = ast.Node.Id.ErrorSetDecl },2841 .base = ast.Node{ .id = ast.Node.Id.ErrorSetDecl },
2724 .error_token = ctx.error_token,2842 .error_token = ctx.error_token,
2725 .decls = ast.Node.ErrorSetDecl.DeclList.init(arena),2843 .decls = ast.Node.ErrorSetDecl.DeclList.init(arena),
2726 .rbrace_token = undefined,2844 .rbrace_token = undefined,
2727 });2845 };
2728 ctx.opt_ctx.store(&node.base);2846 ctx.opt_ctx.store(&node.base);
27292847
2730 stack.append(State{2848 stack.append(State{
...@@ -2785,11 +2903,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2785,11 +2903,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2785 return tree;2903 return tree;
2786 }2904 }
27872905
2788 const node = try arena.create(ast.Node.ErrorTag{2906 const node = try arena.create(ast.Node.ErrorTag);
2907 node.* = ast.Node.ErrorTag{
2789 .base = ast.Node{ .id = ast.Node.Id.ErrorTag },2908 .base = ast.Node{ .id = ast.Node.Id.ErrorTag },
2790 .doc_comments = comments,2909 .doc_comments = comments,
2791 .name_token = ident_token_index,2910 .name_token = ident_token_index,
2792 });2911 };
2793 node_ptr.* = &node.base;2912 node_ptr.* = &node.base;
2794 continue;2913 continue;
2795 },2914 },
...@@ -2870,6 +2989,7 @@ const TopLevelDeclCtx = struct {...@@ -2870,6 +2989,7 @@ const TopLevelDeclCtx = struct {
2870const VarDeclCtx = struct {2989const VarDeclCtx = struct {
2871 mut_token: TokenIndex,2990 mut_token: TokenIndex,
2872 visib_token: ?TokenIndex,2991 visib_token: ?TokenIndex,
2992 thread_local_token: ?TokenIndex,
2873 comptime_token: ?TokenIndex,2993 comptime_token: ?TokenIndex,
2874 extern_export_token: ?TokenIndex,2994 extern_export_token: ?TokenIndex,
2875 lib_name: ?*ast.Node,2995 lib_name: ?*ast.Node,
...@@ -3014,6 +3134,7 @@ const State = union(enum) {...@@ -3014,6 +3134,7 @@ const State = union(enum) {
3014 ContainerInitArg: *ast.Node.ContainerDecl,3134 ContainerInitArg: *ast.Node.ContainerDecl,
3015 ContainerDecl: *ast.Node.ContainerDecl,3135 ContainerDecl: *ast.Node.ContainerDecl,
30163136
3137 ThreadLocal: VarDeclCtx,
3017 VarDecl: VarDeclCtx,3138 VarDecl: VarDeclCtx,
3018 VarDeclAlign: *ast.Node.VarDecl,3139 VarDeclAlign: *ast.Node.VarDecl,
3019 VarDeclSection: *ast.Node.VarDecl,3140 VarDeclSection: *ast.Node.VarDecl,
...@@ -3129,10 +3250,11 @@ fn pushDocComment(arena: *mem.Allocator, line_comment: TokenIndex, result: *?*as...@@ -3129,10 +3250,11 @@ fn pushDocComment(arena: *mem.Allocator, line_comment: TokenIndex, result: *?*as
3129 if (result.*) |comment_node| {3250 if (result.*) |comment_node| {
3130 break :blk comment_node;3251 break :blk comment_node;
3131 } else {3252 } else {
3132 const comment_node = try arena.create(ast.Node.DocComment{3253 const comment_node = try arena.create(ast.Node.DocComment);
3254 comment_node.* = ast.Node.DocComment{
3133 .base = ast.Node{ .id = ast.Node.Id.DocComment },3255 .base = ast.Node{ .id = ast.Node.Id.DocComment },
3134 .lines = ast.Node.DocComment.LineList.init(arena),3256 .lines = ast.Node.DocComment.LineList.init(arena),
3135 });3257 };
3136 result.* = comment_node;3258 result.* = comment_node;
3137 break :blk comment_node;3259 break :blk comment_node;
3138 }3260 }
...@@ -3158,10 +3280,11 @@ fn parseStringLiteral(arena: *mem.Allocator, tok_it: *ast.Tree.TokenList.Iterato...@@ -3158,10 +3280,11 @@ fn parseStringLiteral(arena: *mem.Allocator, tok_it: *ast.Tree.TokenList.Iterato
3158 return &(try createLiteral(arena, ast.Node.StringLiteral, token_index)).base;3280 return &(try createLiteral(arena, ast.Node.StringLiteral, token_index)).base;
3159 },3281 },
3160 Token.Id.MultilineStringLiteralLine => {3282 Token.Id.MultilineStringLiteralLine => {
3161 const node = try arena.create(ast.Node.MultilineStringLiteral{3283 const node = try arena.create(ast.Node.MultilineStringLiteral);
3284 node.* = ast.Node.MultilineStringLiteral{
3162 .base = ast.Node{ .id = ast.Node.Id.MultilineStringLiteral },3285 .base = ast.Node{ .id = ast.Node.Id.MultilineStringLiteral },
3163 .lines = ast.Node.MultilineStringLiteral.LineList.init(arena),3286 .lines = ast.Node.MultilineStringLiteral.LineList.init(arena),
3164 });3287 };
3165 try node.lines.push(token_index);3288 try node.lines.push(token_index);
3166 while (true) {3289 while (true) {
3167 const multiline_str = nextToken(tok_it, tree);3290 const multiline_str = nextToken(tok_it, tree);
...@@ -3186,25 +3309,27 @@ fn parseStringLiteral(arena: *mem.Allocator, tok_it: *ast.Tree.TokenList.Iterato...@@ -3186,25 +3309,27 @@ fn parseStringLiteral(arena: *mem.Allocator, tok_it: *ast.Tree.TokenList.Iterato
3186fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: OptionalCtx, token_ptr: Token, token_index: TokenIndex) !bool {3309fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: OptionalCtx, token_ptr: Token, token_index: TokenIndex) !bool {
3187 switch (token_ptr.id) {3310 switch (token_ptr.id) {
3188 Token.Id.Keyword_suspend => {3311 Token.Id.Keyword_suspend => {
3189 const node = try arena.create(ast.Node.Suspend{3312 const node = try arena.create(ast.Node.Suspend);
3313 node.* = ast.Node.Suspend{
3190 .base = ast.Node{ .id = ast.Node.Id.Suspend },3314 .base = ast.Node{ .id = ast.Node.Id.Suspend },
3191 .suspend_token = token_index,3315 .suspend_token = token_index,
3192 .body = null,3316 .body = null,
3193 });3317 };
3194 ctx.store(&node.base);3318 ctx.store(&node.base);
31953319
3196 stack.append(State{ .SuspendBody = node }) catch unreachable;3320 stack.append(State{ .SuspendBody = node }) catch unreachable;
3197 return true;3321 return true;
3198 },3322 },
3199 Token.Id.Keyword_if => {3323 Token.Id.Keyword_if => {
3200 const node = try arena.create(ast.Node.If{3324 const node = try arena.create(ast.Node.If);
3325 node.* = ast.Node.If{
3201 .base = ast.Node{ .id = ast.Node.Id.If },3326 .base = ast.Node{ .id = ast.Node.Id.If },
3202 .if_token = token_index,3327 .if_token = token_index,
3203 .condition = undefined,3328 .condition = undefined,
3204 .payload = null,3329 .payload = null,
3205 .body = undefined,3330 .body = undefined,
3206 .@"else" = null,3331 .@"else" = null,
3207 });3332 };
3208 ctx.store(&node.base);3333 ctx.store(&node.base);
32093334
3210 stack.append(State{ .Else = &node.@"else" }) catch unreachable;3335 stack.append(State{ .Else = &node.@"else" }) catch unreachable;
...@@ -3238,13 +3363,14 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: Opti...@@ -3238,13 +3363,14 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: Opti
3238 return true;3363 return true;
3239 },3364 },
3240 Token.Id.Keyword_switch => {3365 Token.Id.Keyword_switch => {
3241 const node = try arena.create(ast.Node.Switch{3366 const node = try arena.create(ast.Node.Switch);
3367 node.* = ast.Node.Switch{
3242 .base = ast.Node{ .id = ast.Node.Id.Switch },3368 .base = ast.Node{ .id = ast.Node.Id.Switch },
3243 .switch_token = token_index,3369 .switch_token = token_index,
3244 .expr = undefined,3370 .expr = undefined,
3245 .cases = ast.Node.Switch.CaseList.init(arena),3371 .cases = ast.Node.Switch.CaseList.init(arena),
3246 .rbrace = undefined,3372 .rbrace = undefined,
3247 });3373 };
3248 ctx.store(&node.base);3374 ctx.store(&node.base);
32493375
3250 stack.append(State{3376 stack.append(State{
...@@ -3260,25 +3386,27 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: Opti...@@ -3260,25 +3386,27 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: Opti
3260 return true;3386 return true;
3261 },3387 },
3262 Token.Id.Keyword_comptime => {3388 Token.Id.Keyword_comptime => {
3263 const node = try arena.create(ast.Node.Comptime{3389 const node = try arena.create(ast.Node.Comptime);
3390 node.* = ast.Node.Comptime{
3264 .base = ast.Node{ .id = ast.Node.Id.Comptime },3391 .base = ast.Node{ .id = ast.Node.Id.Comptime },
3265 .comptime_token = token_index,3392 .comptime_token = token_index,
3266 .expr = undefined,3393 .expr = undefined,
3267 .doc_comments = null,3394 .doc_comments = null,
3268 });3395 };
3269 ctx.store(&node.base);3396 ctx.store(&node.base);
32703397
3271 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } });3398 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } });
3272 return true;3399 return true;
3273 },3400 },
3274 Token.Id.LBrace => {3401 Token.Id.LBrace => {
3275 const block = try arena.create(ast.Node.Block{3402 const block = try arena.create(ast.Node.Block);
3403 block.* = ast.Node.Block{
3276 .base = ast.Node{ .id = ast.Node.Id.Block },3404 .base = ast.Node{ .id = ast.Node.Id.Block },
3277 .label = null,3405 .label = null,
3278 .lbrace = token_index,3406 .lbrace = token_index,
3279 .statements = ast.Node.Block.StatementList.init(arena),3407 .statements = ast.Node.Block.StatementList.init(arena),
3280 .rbrace = undefined,3408 .rbrace = undefined,
3281 });3409 };
3282 ctx.store(&block.base);3410 ctx.store(&block.base);
3283 stack.append(State{ .Block = block }) catch unreachable;3411 stack.append(State{ .Block = block }) catch unreachable;
3284 return true;3412 return true;
...@@ -3397,7 +3525,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {...@@ -3397,7 +3525,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {
3397 Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} },3525 Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} },
3398 Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} },3526 Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} },
3399 Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddressOf = void{} },3527 Token.Id.Ampersand => ast.Node.PrefixOp.Op{ .AddressOf = void{} },
3400 Token.Id.Asterisk, Token.Id.AsteriskAsterisk, Token.Id.BracketStarBracket => ast.Node.PrefixOp.Op{3528
3529 Token.Id.Asterisk,
3530 Token.Id.AsteriskAsterisk,
3531 Token.Id.BracketStarBracket,
3532 Token.Id.BracketStarCBracket,
3533 => ast.Node.PrefixOp.Op{
3401 .PtrType = ast.Node.PrefixOp.PtrInfo{3534 .PtrType = ast.Node.PrefixOp.PtrInfo{
3402 .align_info = null,3535 .align_info = null,
3403 .const_token = null,3536 .const_token = null,
...@@ -3412,10 +3545,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {...@@ -3412,10 +3545,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {
3412}3545}
34133546
3414fn createLiteral(arena: *mem.Allocator, comptime T: type, token_index: TokenIndex) !*T {3547fn createLiteral(arena: *mem.Allocator, comptime T: type, token_index: TokenIndex) !*T {
3415 return arena.create(T{3548 const result = try arena.create(T);
3549 result.* = T{
3416 .base = ast.Node{ .id = ast.Node.typeToId(T) },3550 .base = ast.Node{ .id = ast.Node.typeToId(T) },
3417 .token = token_index,3551 .token = token_index,
3418 });3552 };
3553 return result;
3419}3554}
34203555
3421fn createToCtxLiteral(arena: *mem.Allocator, opt_ctx: OptionalCtx, comptime T: type, token_index: TokenIndex) !*T {3556fn createToCtxLiteral(arena: *mem.Allocator, opt_ctx: OptionalCtx, comptime T: type, token_index: TokenIndex) !*T {
std/zig/parser_test.zig+16-1
...@@ -1,3 +1,17 @@...@@ -1,3 +1,17 @@
1test "zig fmt: C pointers" {
2 try testCanonical(
3 \\const Ptr = [*c]i32;
4 \\
5 );
6}
7
8test "zig fmt: threadlocal" {
9 try testCanonical(
10 \\threadlocal var x: i32 = 1234;
11 \\
12 );
13}
14
1test "zig fmt: linksection" {15test "zig fmt: linksection" {
2 try testCanonical(16 try testCanonical(
3 \\export var aoeu: u64 linksection(".text.derp") = 1234;17 \\export var aoeu: u64 linksection(".text.derp") = 1234;
...@@ -5,6 +19,7 @@ test "zig fmt: linksection" {...@@ -5,6 +19,7 @@ test "zig fmt: linksection" {
5 \\19 \\
6 );20 );
7}21}
22
8test "zig fmt: shebang line" {23test "zig fmt: shebang line" {
9 try testCanonical(24 try testCanonical(
10 \\#!/usr/bin/env zig25 \\#!/usr/bin/env zig
...@@ -1940,7 +1955,7 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {...@@ -1940,7 +1955,7 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {
1940 warn("std.zig.render returned {} instead of {}\n", anything_changed, changes_expected);1955 warn("std.zig.render returned {} instead of {}\n", anything_changed, changes_expected);
1941 return error.TestFailed;1956 return error.TestFailed;
1942 }1957 }
1943 std.debug.assert(anything_changed == changes_expected);1958 std.testing.expect(anything_changed == changes_expected);
1944 failing_allocator.allocator.free(result_source);1959 failing_allocator.allocator.free(result_source);
1945 break :x failing_allocator.index;1960 break :x failing_allocator.index;
1946 };1961 };
std/zig/render.zig+3
...@@ -1706,6 +1706,9 @@ fn renderVarDecl(...@@ -1706,6 +1706,9 @@ fn renderVarDecl(
1706 try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space); // comptime1706 try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space); // comptime
1707 }1707 }
17081708
1709 if (var_decl.thread_local_token) |thread_local_token| {
1710 try renderToken(tree, stream, thread_local_token, indent, start_col, Space.Space); // threadlocal
1711 }
1709 try renderToken(tree, stream, var_decl.mut_token, indent, start_col, Space.Space); // var1712 try renderToken(tree, stream, var_decl.mut_token, indent, start_col, Space.Space); // var
17101713
1711 const name_space = if (var_decl.type_node == null and (var_decl.align_node != null or1714 const name_space = if (var_decl.type_node == null and (var_decl.align_node != null or
std/zig/tokenizer.zig+25-2
...@@ -53,6 +53,7 @@ pub const Token = struct {...@@ -53,6 +53,7 @@ pub const Token = struct {
53 Keyword{ .bytes = "switch", .id = Id.Keyword_switch },53 Keyword{ .bytes = "switch", .id = Id.Keyword_switch },
54 Keyword{ .bytes = "test", .id = Id.Keyword_test },54 Keyword{ .bytes = "test", .id = Id.Keyword_test },
55 Keyword{ .bytes = "this", .id = Id.Keyword_this },55 Keyword{ .bytes = "this", .id = Id.Keyword_this },
56 Keyword{ .bytes = "threadlocal", .id = Id.Keyword_threadlocal },
56 Keyword{ .bytes = "true", .id = Id.Keyword_true },57 Keyword{ .bytes = "true", .id = Id.Keyword_true },
57 Keyword{ .bytes = "try", .id = Id.Keyword_try },58 Keyword{ .bytes = "try", .id = Id.Keyword_try },
58 Keyword{ .bytes = "undefined", .id = Id.Keyword_undefined },59 Keyword{ .bytes = "undefined", .id = Id.Keyword_undefined },
...@@ -140,6 +141,7 @@ pub const Token = struct {...@@ -140,6 +141,7 @@ pub const Token = struct {
140 LineComment,141 LineComment,
141 DocComment,142 DocComment,
142 BracketStarBracket,143 BracketStarBracket,
144 BracketStarCBracket,
143 ShebangLine,145 ShebangLine,
144 Keyword_align,146 Keyword_align,
145 Keyword_and,147 Keyword_and,
...@@ -182,6 +184,7 @@ pub const Token = struct {...@@ -182,6 +184,7 @@ pub const Token = struct {
182 Keyword_switch,184 Keyword_switch,
183 Keyword_test,185 Keyword_test,
184 Keyword_this,186 Keyword_this,
187 Keyword_threadlocal,
185 Keyword_true,188 Keyword_true,
186 Keyword_try,189 Keyword_try,
187 Keyword_undefined,190 Keyword_undefined,
...@@ -277,6 +280,7 @@ pub const Tokenizer = struct {...@@ -277,6 +280,7 @@ pub const Tokenizer = struct {
277 SawAtSign,280 SawAtSign,
278 LBracket,281 LBracket,
279 LBracketStar,282 LBracketStar,
283 LBracketStarC,
280 };284 };
281285
282 pub fn next(self: *Tokenizer) Token {286 pub fn next(self: *Tokenizer) Token {
...@@ -454,6 +458,9 @@ pub const Tokenizer = struct {...@@ -454,6 +458,9 @@ pub const Tokenizer = struct {
454 },458 },
455459
456 State.LBracketStar => switch (c) {460 State.LBracketStar => switch (c) {
461 'c' => {
462 state = State.LBracketStarC;
463 },
457 ']' => {464 ']' => {
458 result.id = Token.Id.BracketStarBracket;465 result.id = Token.Id.BracketStarBracket;
459 self.index += 1;466 self.index += 1;
...@@ -465,6 +472,18 @@ pub const Tokenizer = struct {...@@ -465,6 +472,18 @@ pub const Tokenizer = struct {
465 },472 },
466 },473 },
467474
475 State.LBracketStarC => switch (c) {
476 ']' => {
477 result.id = Token.Id.BracketStarCBracket;
478 self.index += 1;
479 break;
480 },
481 else => {
482 result.id = Token.Id.Invalid;
483 break;
484 },
485 },
486
468 State.Ampersand => switch (c) {487 State.Ampersand => switch (c) {
469 '=' => {488 '=' => {
470 result.id = Token.Id.AmpersandEqual;489 result.id = Token.Id.AmpersandEqual;
...@@ -1033,6 +1052,7 @@ pub const Tokenizer = struct {...@@ -1033,6 +1052,7 @@ pub const Tokenizer = struct {
1033 State.CharLiteralEnd,1052 State.CharLiteralEnd,
1034 State.StringLiteralBackslash,1053 State.StringLiteralBackslash,
1035 State.LBracketStar,1054 State.LBracketStar,
1055 State.LBracketStarC,
1036 => {1056 => {
1037 result.id = Token.Id.Invalid;1057 result.id = Token.Id.Invalid;
1038 },1058 },
...@@ -1167,12 +1187,15 @@ test "tokenizer" {...@@ -1167,12 +1187,15 @@ test "tokenizer" {
1167 testTokenize("test", []Token.Id{Token.Id.Keyword_test});1187 testTokenize("test", []Token.Id{Token.Id.Keyword_test});
1168}1188}
11691189
1170test "tokenizer - unknown length pointer" {1190test "tokenizer - unknown length pointer and then c pointer" {
1171 testTokenize(1191 testTokenize(
1172 \\[*]u81192 \\[*]u8
1193 \\[*c]u8
1173 , []Token.Id{1194 , []Token.Id{
1174 Token.Id.BracketStarBracket,1195 Token.Id.BracketStarBracket,
1175 Token.Id.Identifier,1196 Token.Id.Identifier,
1197 Token.Id.BracketStarCBracket,
1198 Token.Id.Identifier,
1176 });1199 });
1177}1200}
11781201
...@@ -1345,5 +1368,5 @@ fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void {...@@ -1345,5 +1368,5 @@ fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void {
1345 }1368 }
1346 }1369 }
1347 const last_token = tokenizer.next();1370 const last_token = tokenizer.next();
1348 std.debug.assert(last_token.id == Token.Id.Eof);1371 std.testing.expect(last_token.id == Token.Id.Eof);
1349}1372}
test/behavior.zig deleted-77
...@@ -1,77 +0,0 @@
1const builtin = @import("builtin");
2
3comptime {
4 _ = @import("cases/align.zig");
5 _ = @import("cases/alignof.zig");
6 _ = @import("cases/array.zig");
7 _ = @import("cases/asm.zig");
8 _ = @import("cases/atomics.zig");
9 _ = @import("cases/bitcast.zig");
10 _ = @import("cases/bool.zig");
11 _ = @import("cases/bugs/1076.zig");
12 _ = @import("cases/bugs/1111.zig");
13 _ = @import("cases/bugs/1277.zig");
14 _ = @import("cases/bugs/1322.zig");
15 _ = @import("cases/bugs/1381.zig");
16 _ = @import("cases/bugs/1421.zig");
17 _ = @import("cases/bugs/1442.zig");
18 _ = @import("cases/bugs/1486.zig");
19 _ = @import("cases/bugs/394.zig");
20 _ = @import("cases/bugs/655.zig");
21 _ = @import("cases/bugs/656.zig");
22 _ = @import("cases/bugs/726.zig");
23 _ = @import("cases/bugs/828.zig");
24 _ = @import("cases/bugs/920.zig");
25 _ = @import("cases/byval_arg_var.zig");
26 _ = @import("cases/cancel.zig");
27 _ = @import("cases/cast.zig");
28 _ = @import("cases/const_slice_child.zig");
29 _ = @import("cases/coroutine_await_struct.zig");
30 _ = @import("cases/coroutines.zig");
31 _ = @import("cases/defer.zig");
32 _ = @import("cases/enum.zig");
33 _ = @import("cases/enum_with_members.zig");
34 _ = @import("cases/error.zig");
35 _ = @import("cases/eval.zig");
36 _ = @import("cases/field_parent_ptr.zig");
37 _ = @import("cases/fn.zig");
38 _ = @import("cases/fn_in_struct_in_comptime.zig");
39 _ = @import("cases/for.zig");
40 _ = @import("cases/generics.zig");
41 _ = @import("cases/if.zig");
42 _ = @import("cases/import.zig");
43 _ = @import("cases/incomplete_struct_param_tld.zig");
44 _ = @import("cases/ir_block_deps.zig");
45 _ = @import("cases/math.zig");
46 _ = @import("cases/merge_error_sets.zig");
47 _ = @import("cases/misc.zig");
48 _ = @import("cases/namespace_depends_on_compile_var/index.zig");
49 _ = @import("cases/new_stack_call.zig");
50 _ = @import("cases/null.zig");
51 _ = @import("cases/optional.zig");
52 _ = @import("cases/pointers.zig");
53 _ = @import("cases/popcount.zig");
54 _ = @import("cases/pub_enum/index.zig");
55 _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
56 _ = @import("cases/reflection.zig");
57 _ = @import("cases/sizeof_and_typeof.zig");
58 _ = @import("cases/slice.zig");
59 _ = @import("cases/struct.zig");
60 _ = @import("cases/struct_contains_null_ptr_itself.zig");
61 _ = @import("cases/struct_contains_slice_of_itself.zig");
62 _ = @import("cases/switch.zig");
63 _ = @import("cases/switch_prong_err_enum.zig");
64 _ = @import("cases/switch_prong_implicit_cast.zig");
65 _ = @import("cases/syntax.zig");
66 _ = @import("cases/this.zig");
67 _ = @import("cases/try.zig");
68 _ = @import("cases/type_info.zig");
69 _ = @import("cases/undefined.zig");
70 _ = @import("cases/underscore.zig");
71 _ = @import("cases/union.zig");
72 _ = @import("cases/var_args.zig");
73 _ = @import("cases/void.zig");
74 _ = @import("cases/while.zig");
75 _ = @import("cases/widening.zig");
76 _ = @import("cases/bit_shifting.zig");
77}
test/cases/align.zig deleted-230
...@@ -1,230 +0,0 @@
1const assert = @import("std").debug.assert;
2const builtin = @import("builtin");
3
4var foo: u8 align(4) = 100;
5
6test "global variable alignment" {
7 assert(@typeOf(&foo).alignment == 4);
8 assert(@typeOf(&foo) == *align(4) u8);
9 const slice = (*[1]u8)(&foo)[0..];
10 assert(@typeOf(slice) == []align(4) u8);
11}
12
13fn derp() align(@sizeOf(usize) * 2) i32 {
14 return 1234;
15}
16fn noop1() align(1) void {}
17fn noop4() align(4) void {}
18
19test "function alignment" {
20 assert(derp() == 1234);
21 assert(@typeOf(noop1) == fn () align(1) void);
22 assert(@typeOf(noop4) == fn () align(4) void);
23 noop1();
24 noop4();
25}
26
27var baz: packed struct {
28 a: u32,
29 b: u32,
30} = undefined;
31
32test "packed struct alignment" {
33 assert(@typeOf(&baz.b) == *align(1) u32);
34}
35
36const blah: packed struct {
37 a: u3,
38 b: u3,
39 c: u2,
40} = undefined;
41
42test "bit field alignment" {
43 assert(@typeOf(&blah.b) == *align(1:3:1) const u3);
44}
45
46test "default alignment allows unspecified in type syntax" {
47 assert(*u32 == *align(@alignOf(u32)) u32);
48}
49
50test "implicitly decreasing pointer alignment" {
51 const a: u32 align(4) = 3;
52 const b: u32 align(8) = 4;
53 assert(addUnaligned(&a, &b) == 7);
54}
55
56fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
57 return a.* + b.*;
58}
59
60test "implicitly decreasing slice alignment" {
61 const a: u32 align(4) = 3;
62 const b: u32 align(8) = 4;
63 assert(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7);
64}
65fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
66 return a[0] + b[0];
67}
68
69test "specifying alignment allows pointer cast" {
70 testBytesAlign(0x33);
71}
72fn testBytesAlign(b: u8) void {
73 var bytes align(4) = []u8{
74 b,
75 b,
76 b,
77 b,
78 };
79 const ptr = @ptrCast(*u32, &bytes[0]);
80 assert(ptr.* == 0x33333333);
81}
82
83test "specifying alignment allows slice cast" {
84 testBytesAlignSlice(0x33);
85}
86fn testBytesAlignSlice(b: u8) void {
87 var bytes align(4) = []u8{
88 b,
89 b,
90 b,
91 b,
92 };
93 const slice: []u32 = @bytesToSlice(u32, bytes[0..]);
94 assert(slice[0] == 0x33333333);
95}
96
97test "@alignCast pointers" {
98 var x: u32 align(4) = 1;
99 expectsOnly1(&x);
100 assert(x == 2);
101}
102fn expectsOnly1(x: *align(1) u32) void {
103 expects4(@alignCast(4, x));
104}
105fn expects4(x: *align(4) u32) void {
106 x.* += 1;
107}
108
109test "@alignCast slices" {
110 var array align(4) = []u32{
111 1,
112 1,
113 };
114 const slice = array[0..];
115 sliceExpectsOnly1(slice);
116 assert(slice[0] == 2);
117}
118fn sliceExpectsOnly1(slice: []align(1) u32) void {
119 sliceExpects4(@alignCast(4, slice));
120}
121fn sliceExpects4(slice: []align(4) u32) void {
122 slice[0] += 1;
123}
124
125test "implicitly decreasing fn alignment" {
126 testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
127 testImplicitlyDecreaseFnAlign(alignedBig, 5678);
128}
129
130fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void {
131 assert(ptr() == answer);
132}
133
134fn alignedSmall() align(8) i32 {
135 return 1234;
136}
137fn alignedBig() align(16) i32 {
138 return 5678;
139}
140
141test "@alignCast functions" {
142 assert(fnExpectsOnly1(simple4) == 0x19);
143}
144fn fnExpectsOnly1(ptr: fn () align(1) i32) i32 {
145 return fnExpects4(@alignCast(4, ptr));
146}
147fn fnExpects4(ptr: fn () align(4) i32) i32 {
148 return ptr();
149}
150fn simple4() align(4) i32 {
151 return 0x19;
152}
153
154test "generic function with align param" {
155 assert(whyWouldYouEverDoThis(1) == 0x1);
156 assert(whyWouldYouEverDoThis(4) == 0x1);
157 assert(whyWouldYouEverDoThis(8) == 0x1);
158}
159
160fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
161 return 0x1;
162}
163
164test "@ptrCast preserves alignment of bigger source" {
165 var x: u32 align(16) = 1234;
166 const ptr = @ptrCast(*u8, &x);
167 assert(@typeOf(ptr) == *align(16) u8);
168}
169
170test "runtime known array index has best alignment possible" {
171 // take full advantage of over-alignment
172 var array align(4) = []u8{ 1, 2, 3, 4 };
173 assert(@typeOf(&array[0]) == *align(4) u8);
174 assert(@typeOf(&array[1]) == *u8);
175 assert(@typeOf(&array[2]) == *align(2) u8);
176 assert(@typeOf(&array[3]) == *u8);
177
178 // because align is too small but we still figure out to use 2
179 var bigger align(2) = []u64{ 1, 2, 3, 4 };
180 assert(@typeOf(&bigger[0]) == *align(2) u64);
181 assert(@typeOf(&bigger[1]) == *align(2) u64);
182 assert(@typeOf(&bigger[2]) == *align(2) u64);
183 assert(@typeOf(&bigger[3]) == *align(2) u64);
184
185 // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2
186 var smaller align(2) = []u32{ 1, 2, 3, 4 };
187 comptime assert(@typeOf(smaller[0..]) == []align(2) u32);
188 comptime assert(@typeOf(smaller[0..].ptr) == [*]align(2) u32);
189 testIndex(smaller[0..].ptr, 0, *align(2) u32);
190 testIndex(smaller[0..].ptr, 1, *align(2) u32);
191 testIndex(smaller[0..].ptr, 2, *align(2) u32);
192 testIndex(smaller[0..].ptr, 3, *align(2) u32);
193
194 // has to use ABI alignment because index known at runtime only
195 testIndex2(array[0..].ptr, 0, *u8);
196 testIndex2(array[0..].ptr, 1, *u8);
197 testIndex2(array[0..].ptr, 2, *u8);
198 testIndex2(array[0..].ptr, 3, *u8);
199}
200fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void {
201 comptime assert(@typeOf(&smaller[index]) == T);
202}
203fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) void {
204 comptime assert(@typeOf(&ptr[index]) == T);
205}
206
207test "alignstack" {
208 assert(fnWithAlignedStack() == 1234);
209}
210
211fn fnWithAlignedStack() i32 {
212 @setAlignStack(256);
213 return 1234;
214}
215
216test "alignment of structs" {
217 assert(@alignOf(struct {
218 a: i32,
219 b: *i32,
220 }) == @alignOf(usize));
221}
222
223test "alignment of extern() void" {
224 var runtime_nothing = nothing;
225 const casted1 = @ptrCast(*const u8, runtime_nothing);
226 const casted2 = @ptrCast(extern fn () void, casted1);
227 casted2();
228}
229
230extern fn nothing() void {}
test/cases/alignof.zig deleted-17
...@@ -1,17 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const builtin = @import("builtin");
4const maxInt = std.math.maxInt;
5
6const Foo = struct {
7 x: u32,
8 y: u32,
9 z: u32,
10};
11
12test "@alignOf(T) before referencing T" {
13 comptime assert(@alignOf(Foo) != maxInt(usize));
14 if (builtin.arch == builtin.Arch.x86_64) {
15 comptime assert(@alignOf(Foo) == 4);
16 }
17}
test/cases/array.zig deleted-173
...@@ -1,173 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3
4test "arrays" {
5 var array: [5]u32 = undefined;
6
7 var i: u32 = 0;
8 while (i < 5) {
9 array[i] = i + 1;
10 i = array[i];
11 }
12
13 i = 0;
14 var accumulator = u32(0);
15 while (i < 5) {
16 accumulator += array[i];
17
18 i += 1;
19 }
20
21 assert(accumulator == 15);
22 assert(getArrayLen(array) == 5);
23}
24fn getArrayLen(a: []const u32) usize {
25 return a.len;
26}
27
28test "void arrays" {
29 var array: [4]void = undefined;
30 array[0] = void{};
31 array[1] = array[2];
32 assert(@sizeOf(@typeOf(array)) == 0);
33 assert(array.len == 4);
34}
35
36test "array literal" {
37 const hex_mult = []u16{
38 4096,
39 256,
40 16,
41 1,
42 };
43
44 assert(hex_mult.len == 4);
45 assert(hex_mult[1] == 256);
46}
47
48test "array dot len const expr" {
49 assert(comptime x: {
50 break :x some_array.len == 4;
51 });
52}
53
54const ArrayDotLenConstExpr = struct {
55 y: [some_array.len]u8,
56};
57const some_array = []u8{
58 0,
59 1,
60 2,
61 3,
62};
63
64test "nested arrays" {
65 const array_of_strings = [][]const u8{
66 "hello",
67 "this",
68 "is",
69 "my",
70 "thing",
71 };
72 for (array_of_strings) |s, i| {
73 if (i == 0) assert(mem.eql(u8, s, "hello"));
74 if (i == 1) assert(mem.eql(u8, s, "this"));
75 if (i == 2) assert(mem.eql(u8, s, "is"));
76 if (i == 3) assert(mem.eql(u8, s, "my"));
77 if (i == 4) assert(mem.eql(u8, s, "thing"));
78 }
79}
80
81var s_array: [8]Sub = undefined;
82const Sub = struct {
83 b: u8,
84};
85const Str = struct {
86 a: []Sub,
87};
88test "set global var array via slice embedded in struct" {
89 var s = Str{ .a = s_array[0..] };
90
91 s.a[0].b = 1;
92 s.a[1].b = 2;
93 s.a[2].b = 3;
94
95 assert(s_array[0].b == 1);
96 assert(s_array[1].b == 2);
97 assert(s_array[2].b == 3);
98}
99
100test "array literal with specified size" {
101 var array = [2]u8{
102 1,
103 2,
104 };
105 assert(array[0] == 1);
106 assert(array[1] == 2);
107}
108
109test "array child property" {
110 var x: [5]i32 = undefined;
111 assert(@typeOf(x).Child == i32);
112}
113
114test "array len property" {
115 var x: [5]i32 = undefined;
116 assert(@typeOf(x).len == 5);
117}
118
119test "array len field" {
120 var arr = [4]u8{ 0, 0, 0, 0 };
121 var ptr = &arr;
122 assert(arr.len == 4);
123 comptime assert(arr.len == 4);
124 assert(ptr.len == 4);
125 comptime assert(ptr.len == 4);
126}
127
128test "single-item pointer to array indexing and slicing" {
129 testSingleItemPtrArrayIndexSlice();
130 comptime testSingleItemPtrArrayIndexSlice();
131}
132
133fn testSingleItemPtrArrayIndexSlice() void {
134 var array = "aaaa";
135 doSomeMangling(&array);
136 assert(mem.eql(u8, "azya", array));
137}
138
139fn doSomeMangling(array: *[4]u8) void {
140 array[1] = 'z';
141 array[2..3][0] = 'y';
142}
143
144test "implicit cast single-item pointer" {
145 testImplicitCastSingleItemPtr();
146 comptime testImplicitCastSingleItemPtr();
147}
148
149fn testImplicitCastSingleItemPtr() void {
150 var byte: u8 = 100;
151 const slice = (*[1]u8)(&byte)[0..];
152 slice[0] += 1;
153 assert(byte == 101);
154}
155
156fn testArrayByValAtComptime(b: [2]u8) u8 {
157 return b[0];
158}
159
160test "comptime evalutating function that takes array by value" {
161 const arr = []u8{ 0, 1 };
162 _ = comptime testArrayByValAtComptime(arr);
163 _ = comptime testArrayByValAtComptime(arr);
164}
165
166test "implicit comptime in array type size" {
167 var arr: [plusOne(10)]bool = undefined;
168 assert(arr.len == 11);
169}
170
171fn plusOne(x: u32) u32 {
172 return x + 1;
173}
test/cases/asm.zig deleted-48
...@@ -1,48 +0,0 @@
1const config = @import("builtin");
2const assert = @import("std").debug.assert;
3
4comptime {
5 if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
6 asm volatile (
7 \\.globl aoeu;
8 \\.type aoeu, @function;
9 \\.set aoeu, derp;
10 );
11 }
12}
13
14test "module level assembly" {
15 if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
16 assert(aoeu() == 1234);
17 }
18}
19
20test "output constraint modifiers" {
21 // This is only testing compilation.
22 var a: u32 = 3;
23 asm volatile ("" : [_]"=m,r"(a) : : "");
24 asm volatile ("" : [_]"=r,m"(a) : : "");
25}
26
27test "alternative constraints" {
28 // Make sure we allow commas as a separator for alternative constraints.
29 var a: u32 = 3;
30 asm volatile ("" : [_]"=r,m"(a) : [_]"r,m"(a) : "");
31}
32
33test "sized integer/float in asm input" {
34 asm volatile ("" : : [_]"m"(usize(3)) : "");
35 asm volatile ("" : : [_]"m"(i15(-3)) : "");
36 asm volatile ("" : : [_]"m"(u3(3)) : "");
37 asm volatile ("" : : [_]"m"(i3(3)) : "");
38 asm volatile ("" : : [_]"m"(u121(3)) : "");
39 asm volatile ("" : : [_]"m"(i121(3)) : "");
40 asm volatile ("" : : [_]"m"(f32(3.17)) : "");
41 asm volatile ("" : : [_]"m"(f64(3.17)) : "");
42}
43
44extern fn aoeu() i32;
45
46export fn derp() i32 {
47 return 1234;
48}
test/cases/atomics.zig deleted-71
...@@ -1,71 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const builtin = @import("builtin");
4const AtomicRmwOp = builtin.AtomicRmwOp;
5const AtomicOrder = builtin.AtomicOrder;
6
7test "cmpxchg" {
8 var x: i32 = 1234;
9 if (@cmpxchgWeak(i32, &x, 99, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
10 assert(x1 == 1234);
11 } else {
12 @panic("cmpxchg should have failed");
13 }
14
15 while (@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
16 assert(x1 == 1234);
17 }
18 assert(x == 5678);
19
20 assert(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
21 assert(x == 42);
22}
23
24test "fence" {
25 var x: i32 = 1234;
26 @fence(AtomicOrder.SeqCst);
27 x = 5678;
28}
29
30test "atomicrmw and atomicload" {
31 var data: u8 = 200;
32 testAtomicRmw(&data);
33 assert(data == 42);
34 testAtomicLoad(&data);
35}
36
37fn testAtomicRmw(ptr: *u8) void {
38 const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst);
39 assert(prev_value == 200);
40 comptime {
41 var x: i32 = 1234;
42 const y: i32 = 12345;
43 assert(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234);
44 assert(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345);
45 }
46}
47
48fn testAtomicLoad(ptr: *u8) void {
49 const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst);
50 assert(x == 42);
51}
52
53test "cmpxchg with ptr" {
54 var data1: i32 = 1234;
55 var data2: i32 = 5678;
56 var data3: i32 = 9101;
57 var x: *i32 = &data1;
58 if (@cmpxchgWeak(*i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
59 assert(x1 == &data1);
60 } else {
61 @panic("cmpxchg should have failed");
62 }
63
64 while (@cmpxchgWeak(*i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
65 assert(x1 == &data1);
66 }
67 assert(x == &data3);
68
69 assert(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
70 assert(x == &data2);
71}
test/cases/bit_shifting.zig deleted-88
...@@ -1,88 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type {
5 assert(Key == @IntType(false, Key.bit_count));
6 assert(Key.bit_count >= mask_bit_count);
7 const ShardKey = @IntType(false, mask_bit_count);
8 const shift_amount = Key.bit_count - ShardKey.bit_count;
9 return struct {
10 const Self = @This();
11 shards: [1 << ShardKey.bit_count]?*Node,
12
13 pub fn create() Self {
14 return Self{ .shards = []?*Node{null} ** (1 << ShardKey.bit_count) };
15 }
16
17 fn getShardKey(key: Key) ShardKey {
18 // https://github.com/ziglang/zig/issues/1544
19 // this special case is needed because you can't u32 >> 32.
20 if (ShardKey == u0) return 0;
21
22 // this can be u1 >> u0
23 const shard_key = key >> shift_amount;
24
25 // TODO: https://github.com/ziglang/zig/issues/1544
26 // This cast could be implicit if we teach the compiler that
27 // u32 >> 30 -> u2
28 return @intCast(ShardKey, shard_key);
29 }
30
31 pub fn put(self: *Self, node: *Node) void {
32 const shard_key = Self.getShardKey(node.key);
33 node.next = self.shards[shard_key];
34 self.shards[shard_key] = node;
35 }
36
37 pub fn get(self: *Self, key: Key) ?*Node {
38 const shard_key = Self.getShardKey(key);
39 var maybe_node = self.shards[shard_key];
40 while (maybe_node) |node| : (maybe_node = node.next) {
41 if (node.key == key) return node;
42 }
43 return null;
44 }
45
46 pub const Node = struct {
47 key: Key,
48 value: V,
49 next: ?*Node,
50
51 pub fn init(self: *Node, key: Key, value: V) void {
52 self.key = key;
53 self.value = value;
54 self.next = null;
55 }
56 };
57 };
58}
59
60test "sharded table" {
61 // realistic 16-way sharding
62 testShardedTable(u32, 4, 8);
63
64 testShardedTable(u5, 0, 32); // ShardKey == u0
65 testShardedTable(u5, 2, 32);
66 testShardedTable(u5, 5, 32);
67
68 testShardedTable(u1, 0, 2);
69 testShardedTable(u1, 1, 2); // this does u1 >> u0
70
71 testShardedTable(u0, 0, 1);
72}
73fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime node_count: comptime_int) void {
74 const Table = ShardedTable(Key, mask_bit_count, void);
75
76 var table = Table.create();
77 var node_buffer: [node_count]Table.Node = undefined;
78 for (node_buffer) |*node, i| {
79 const key = @intCast(Key, i);
80 assert(table.get(key) == null);
81 node.init(key, {});
82 table.put(node);
83 }
84
85 for (node_buffer) |*node, i| {
86 assert(table.get(@intCast(Key, i)) == node);
87 }
88}
test/cases/bitcast.zig deleted-37
...@@ -1,37 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const maxInt = std.math.maxInt;
4
5test "@bitCast i32 -> u32" {
6 testBitCast_i32_u32();
7 comptime testBitCast_i32_u32();
8}
9
10fn testBitCast_i32_u32() void {
11 assert(conv(-1) == maxInt(u32));
12 assert(conv2(maxInt(u32)) == -1);
13}
14
15fn conv(x: i32) u32 {
16 return @bitCast(u32, x);
17}
18fn conv2(x: u32) i32 {
19 return @bitCast(i32, x);
20}
21
22test "@bitCast extern enum to its integer type" {
23 const SOCK = extern enum {
24 A,
25 B,
26
27 fn testBitCastExternEnum() void {
28 var SOCK_DGRAM = @This().B;
29 var sock_dgram = @bitCast(c_int, SOCK_DGRAM);
30 assert(sock_dgram == 1);
31 }
32 };
33
34 SOCK.testBitCastExternEnum();
35 comptime SOCK.testBitCastExternEnum();
36}
37
test/cases/bool.zig deleted-35
...@@ -1,35 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "bool literals" {
4 assert(true);
5 assert(!false);
6}
7
8test "cast bool to int" {
9 const t = true;
10 const f = false;
11 assert(@boolToInt(t) == u32(1));
12 assert(@boolToInt(f) == u32(0));
13 nonConstCastBoolToInt(t, f);
14}
15
16fn nonConstCastBoolToInt(t: bool, f: bool) void {
17 assert(@boolToInt(t) == u32(1));
18 assert(@boolToInt(f) == u32(0));
19}
20
21test "bool cmp" {
22 assert(testBoolCmp(true, false) == false);
23}
24fn testBoolCmp(a: bool, b: bool) bool {
25 return a == b;
26}
27
28const global_f = false;
29const global_t = true;
30const not_global_f = !global_f;
31const not_global_t = !global_t;
32test "compile time bool not" {
33 assert(not_global_f);
34 assert(!not_global_t);
35}
test/cases/bugs/1076.zig deleted-16
...@@ -1,16 +0,0 @@
1const std = @import("std");
2const mem = std.mem;
3const assert = std.debug.assert;
4
5test "comptime code should not modify constant data" {
6 testCastPtrOfArrayToSliceAndPtr();
7 comptime testCastPtrOfArrayToSliceAndPtr();
8}
9
10fn testCastPtrOfArrayToSliceAndPtr() void {
11 var array = "aoeu";
12 const x: [*]u8 = &array;
13 x[0] += 1;
14 assert(mem.eql(u8, array[0..], "boeu"));
15}
16
test/cases/bugs/1111.zig deleted-12
...@@ -1,12 +0,0 @@
1const Foo = extern enum {
2 Bar = -1,
3};
4
5test "issue 1111 fixed" {
6 const v = Foo.Bar;
7
8 switch (v) {
9 Foo.Bar => return,
10 else => return,
11 }
12}
test/cases/bugs/1277.zig deleted-15
...@@ -1,15 +0,0 @@
1const std = @import("std");
2
3const S = struct {
4 f: ?fn () i32,
5};
6
7const s = S{ .f = f };
8
9fn f() i32 {
10 return 1234;
11}
12
13test "don't emit an LLVM global for a const function when it's in an optional in a struct" {
14 std.debug.assertOrPanic(s.f.?() == 1234);
15}
test/cases/bugs/1322.zig deleted-19
...@@ -1,19 +0,0 @@
1const std = @import("std");
2
3const B = union(enum) {
4 c: C,
5 None,
6};
7
8const A = struct {
9 b: B,
10};
11
12const C = struct {};
13
14test "tagged union with all void fields but a meaningful tag" {
15 var a: A = A{ .b = B{ .c = C{} } };
16 std.debug.assert(@TagType(B)(a.b) == @TagType(B).c);
17 a = A{ .b = B.None };
18 std.debug.assert(@TagType(B)(a.b) == @TagType(B).None);
19}
test/cases/bugs/1381.zig deleted-21
...@@ -1,21 +0,0 @@
1const std = @import("std");
2
3const B = union(enum) {
4 D: u8,
5 E: u16,
6};
7
8const A = union(enum) {
9 B: B,
10 C: u8,
11};
12
13test "union that needs padding bytes inside an array" {
14 var as = []A{
15 A{ .B = B{ .D = 1 } },
16 A{ .B = B{ .D = 1 } },
17 };
18
19 const a = as[0].B;
20 std.debug.assertOrPanic(a.D == 1);
21}
test/cases/bugs/1421.zig deleted-14
...@@ -1,14 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assert = std.debug.assert;
4
5const S = struct {
6 fn method() builtin.TypeInfo {
7 return @typeInfo(S);
8 }
9};
10
11test "functions with return type required to be comptime are generic" {
12 const ti = S.method();
13 assert(builtin.TypeId(ti) == builtin.TypeId.Struct);
14}
test/cases/bugs/1442.zig deleted-11
...@@ -1,11 +0,0 @@
1const std = @import("std");
2
3const Union = union(enum) {
4 Text: []const u8,
5 Color: u32,
6};
7
8test "const error union field alignment" {
9 var union_or_err: anyerror!Union = Union{ .Color = 1234 };
10 std.debug.assertOrPanic((union_or_err catch unreachable).Color == 1234);
11}
test/cases/bugs/1486.zig deleted-11
...@@ -1,11 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const ptr = &global;
4var global: u64 = 123;
5
6test "constant pointer to global variable causes runtime load" {
7 global = 1234;
8 assert(&global == ptr);
9 assert(ptr.* == 1234);
10}
11
test/cases/bugs/394.zig deleted-18
...@@ -1,18 +0,0 @@
1const E = union(enum) {
2 A: [9]u8,
3 B: u64,
4};
5const S = struct {
6 x: u8,
7 y: E,
8};
9
10const assert = @import("std").debug.assert;
11
12test "bug 394 fixed" {
13 const x = S{
14 .x = 3,
15 .y = E{ .B = 1 },
16 };
17 assert(x.x == 3);
18}
test/cases/bugs/655.zig deleted-12
...@@ -1,12 +0,0 @@
1const std = @import("std");
2const other_file = @import("655_other_file.zig");
3
4test "function with *const parameter with type dereferenced by namespace" {
5 const x: other_file.Integer = 1234;
6 comptime std.debug.assert(@typeOf(&x) == *const other_file.Integer);
7 foo(&x);
8}
9
10fn foo(x: *const other_file.Integer) void {
11 std.debug.assert(x.* == 1234);
12}
test/cases/bugs/655_other_file.zig deleted-1
...@@ -1 +0,0 @@
1pub const Integer = u32;
test/cases/bugs/656.zig deleted-31
...@@ -1,31 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const PrefixOp = union(enum) {
4 Return,
5 AddrOf: Value,
6};
7
8const Value = struct {
9 align_expr: ?u32,
10};
11
12test "optional if after an if in a switch prong of a switch with 2 prongs in an else" {
13 foo(false, true);
14}
15
16fn foo(a: bool, b: bool) void {
17 var prefix_op = PrefixOp{
18 .AddrOf = Value{ .align_expr = 1234 },
19 };
20 if (a) {} else {
21 switch (prefix_op) {
22 PrefixOp.AddrOf => |addr_of_info| {
23 if (b) {}
24 if (addr_of_info.align_expr) |align_expr| {
25 assert(align_expr == 1234);
26 }
27 },
28 PrefixOp.Return => {},
29 }
30 }
31}
test/cases/bugs/726.zig deleted-16
...@@ -1,16 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "@ptrCast from const to nullable" {
4 const c: u8 = 4;
5 var x: ?*const u8 = @ptrCast(?*const u8, &c);
6 assert(x.?.* == 4);
7}
8
9test "@ptrCast from var in empty struct to nullable" {
10 const container = struct {
11 var c: u8 = 4;
12 };
13 var x: ?*const u8 = @ptrCast(?*const u8, &container.c);
14 assert(x.?.* == 4);
15}
16
test/cases/bugs/828.zig deleted-33
...@@ -1,33 +0,0 @@
1const CountBy = struct {
2 a: usize,
3
4 const One = CountBy{ .a = 1 };
5
6 pub fn counter(self: *const CountBy) Counter {
7 return Counter{ .i = 0 };
8 }
9};
10
11const Counter = struct {
12 i: usize,
13
14 pub fn count(self: *Counter) bool {
15 self.i += 1;
16 return self.i <= 10;
17 }
18};
19
20fn constCount(comptime cb: *const CountBy, comptime unused: u32) void {
21 comptime {
22 var cnt = cb.counter();
23 if (cnt.i != 0) @compileError("Counter instance reused!");
24 while (cnt.count()) {}
25 }
26}
27
28test "comptime struct return should not return the same instance" {
29 //the first parameter must be passed by reference to trigger the bug
30 //a second parameter is required to trigger the bug
31 const ValA = constCount(&CountBy.One, 12);
32 const ValB = constCount(&CountBy.One, 15);
33}
test/cases/bugs/920.zig deleted-65
...@@ -1,65 +0,0 @@
1const std = @import("std");
2const math = std.math;
3const Random = std.rand.Random;
4
5const ZigTable = struct {
6 r: f64,
7 x: [257]f64,
8 f: [257]f64,
9
10 pdf: fn (f64) f64,
11 is_symmetric: bool,
12 zero_case: fn (*Random, f64) f64,
13};
14
15fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn (f64) f64, comptime f_inv: fn (f64) f64, comptime zero_case: fn (*Random, f64) f64) ZigTable {
16 var tables: ZigTable = undefined;
17
18 tables.is_symmetric = is_symmetric;
19 tables.r = r;
20 tables.pdf = f;
21 tables.zero_case = zero_case;
22
23 tables.x[0] = v / f(r);
24 tables.x[1] = r;
25
26 for (tables.x[2..256]) |*entry, i| {
27 const last = tables.x[2 + i - 1];
28 entry.* = f_inv(v / last + f(last));
29 }
30 tables.x[256] = 0;
31
32 for (tables.f[0..]) |*entry, i| {
33 entry.* = f(tables.x[i]);
34 }
35
36 return tables;
37}
38
39const norm_r = 3.6541528853610088;
40const norm_v = 0.00492867323399;
41
42fn norm_f(x: f64) f64 {
43 return math.exp(-x * x / 2.0);
44}
45fn norm_f_inv(y: f64) f64 {
46 return math.sqrt(-2.0 * math.ln(y));
47}
48fn norm_zero_case(random: *Random, u: f64) f64 {
49 return 0.0;
50}
51
52const NormalDist = blk: {
53 @setEvalBranchQuota(30000);
54 break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case);
55};
56
57test "bug 920 fixed" {
58 const NormalDist1 = blk: {
59 break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case);
60 };
61
62 for (NormalDist1.f) |_, i| {
63 std.debug.assert(NormalDist1.f[i] == NormalDist.f[i]);
64 }
65}
test/cases/byval_arg_var.zig deleted-27
...@@ -1,27 +0,0 @@
1const std = @import("std");
2
3var result: []const u8 = "wrong";
4
5test "aoeu" {
6 start();
7 blowUpStack(10);
8
9 std.debug.assert(std.mem.eql(u8, result, "string literal"));
10}
11
12fn start() void {
13 foo("string literal");
14}
15
16fn foo(x: var) void {
17 bar(x);
18}
19
20fn bar(x: var) void {
21 result = x;
22}
23
24fn blowUpStack(x: u32) void {
25 if (x == 0) return;
26 blowUpStack(x - 1);
27}
test/cases/cancel.zig deleted-92
...@@ -1,92 +0,0 @@
1const std = @import("std");
2
3var defer_f1: bool = false;
4var defer_f2: bool = false;
5var defer_f3: bool = false;
6
7test "cancel forwards" {
8 var da = std.heap.DirectAllocator.init();
9 defer da.deinit();
10
11 const p = async<&da.allocator> f1() catch unreachable;
12 cancel p;
13 std.debug.assert(defer_f1);
14 std.debug.assert(defer_f2);
15 std.debug.assert(defer_f3);
16}
17
18async fn f1() void {
19 defer {
20 defer_f1 = true;
21 }
22 await (async f2() catch unreachable);
23}
24
25async fn f2() void {
26 defer {
27 defer_f2 = true;
28 }
29 await (async f3() catch unreachable);
30}
31
32async fn f3() void {
33 defer {
34 defer_f3 = true;
35 }
36 suspend;
37}
38
39var defer_b1: bool = false;
40var defer_b2: bool = false;
41var defer_b3: bool = false;
42var defer_b4: bool = false;
43
44test "cancel backwards" {
45 var da = std.heap.DirectAllocator.init();
46 defer da.deinit();
47
48 const p = async<&da.allocator> b1() catch unreachable;
49 cancel p;
50 std.debug.assert(defer_b1);
51 std.debug.assert(defer_b2);
52 std.debug.assert(defer_b3);
53 std.debug.assert(defer_b4);
54}
55
56async fn b1() void {
57 defer {
58 defer_b1 = true;
59 }
60 await (async b2() catch unreachable);
61}
62
63var b4_handle: promise = undefined;
64
65async fn b2() void {
66 const b3_handle = async b3() catch unreachable;
67 resume b4_handle;
68 cancel b4_handle;
69 defer {
70 defer_b2 = true;
71 }
72 const value = await b3_handle;
73 @panic("unreachable");
74}
75
76async fn b3() i32 {
77 defer {
78 defer_b3 = true;
79 }
80 await (async b4() catch unreachable);
81 return 1234;
82}
83
84async fn b4() void {
85 defer {
86 defer_b4 = true;
87 }
88 suspend {
89 b4_handle = @handle();
90 }
91 suspend;
92}
test/cases/cast.zig deleted-472
...@@ -1,472 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const mem = std.mem;
4const maxInt = std.math.maxInt;
5
6test "int to ptr cast" {
7 const x = usize(13);
8 const y = @intToPtr(*u8, x);
9 const z = @ptrToInt(y);
10 assert(z == 13);
11}
12
13test "integer literal to pointer cast" {
14 const vga_mem = @intToPtr(*u16, 0xB8000);
15 assert(@ptrToInt(vga_mem) == 0xB8000);
16}
17
18test "pointer reinterpret const float to int" {
19 const float: f64 = 5.99999999999994648725e-01;
20 const float_ptr = &float;
21 const int_ptr = @ptrCast(*const i32, float_ptr);
22 const int_val = int_ptr.*;
23 assert(int_val == 858993411);
24}
25
26test "implicitly cast indirect pointer to maybe-indirect pointer" {
27 const S = struct {
28 const Self = @This();
29 x: u8,
30 fn constConst(p: *const *const Self) u8 {
31 return p.*.x;
32 }
33 fn maybeConstConst(p: ?*const *const Self) u8 {
34 return p.?.*.x;
35 }
36 fn constConstConst(p: *const *const *const Self) u8 {
37 return p.*.*.x;
38 }
39 fn maybeConstConstConst(p: ?*const *const *const Self) u8 {
40 return p.?.*.*.x;
41 }
42 };
43 const s = S{ .x = 42 };
44 const p = &s;
45 const q = &p;
46 const r = &q;
47 assert(42 == S.constConst(q));
48 assert(42 == S.maybeConstConst(q));
49 assert(42 == S.constConstConst(r));
50 assert(42 == S.maybeConstConstConst(r));
51}
52
53test "explicit cast from integer to error type" {
54 testCastIntToErr(error.ItBroke);
55 comptime testCastIntToErr(error.ItBroke);
56}
57fn testCastIntToErr(err: anyerror) void {
58 const x = @errorToInt(err);
59 const y = @intToError(x);
60 assert(error.ItBroke == y);
61}
62
63test "peer resolve arrays of different size to const slice" {
64 assert(mem.eql(u8, boolToStr(true), "true"));
65 assert(mem.eql(u8, boolToStr(false), "false"));
66 comptime assert(mem.eql(u8, boolToStr(true), "true"));
67 comptime assert(mem.eql(u8, boolToStr(false), "false"));
68}
69fn boolToStr(b: bool) []const u8 {
70 return if (b) "true" else "false";
71}
72
73test "peer resolve array and const slice" {
74 testPeerResolveArrayConstSlice(true);
75 comptime testPeerResolveArrayConstSlice(true);
76}
77fn testPeerResolveArrayConstSlice(b: bool) void {
78 const value1 = if (b) "aoeu" else ([]const u8)("zz");
79 const value2 = if (b) ([]const u8)("zz") else "aoeu";
80 assert(mem.eql(u8, value1, "aoeu"));
81 assert(mem.eql(u8, value2, "zz"));
82}
83
84test "implicitly cast from T to anyerror!?T" {
85 castToOptionalTypeError(1);
86 comptime castToOptionalTypeError(1);
87}
88const A = struct {
89 a: i32,
90};
91fn castToOptionalTypeError(z: i32) void {
92 const x = i32(1);
93 const y: anyerror!?i32 = x;
94 assert((try y).? == 1);
95
96 const f = z;
97 const g: anyerror!?i32 = f;
98
99 const a = A{ .a = z };
100 const b: anyerror!?A = a;
101 assert((b catch unreachable).?.a == 1);
102}
103
104test "implicitly cast from int to anyerror!?T" {
105 implicitIntLitToOptional();
106 comptime implicitIntLitToOptional();
107}
108fn implicitIntLitToOptional() void {
109 const f: ?i32 = 1;
110 const g: anyerror!?i32 = 1;
111}
112
113test "return null from fn() anyerror!?&T" {
114 const a = returnNullFromOptionalTypeErrorRef();
115 const b = returnNullLitFromOptionalTypeErrorRef();
116 assert((try a) == null and (try b) == null);
117}
118fn returnNullFromOptionalTypeErrorRef() anyerror!?*A {
119 const a: ?*A = null;
120 return a;
121}
122fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
123 return null;
124}
125
126test "peer type resolution: ?T and T" {
127 assert(peerTypeTAndOptionalT(true, false).? == 0);
128 assert(peerTypeTAndOptionalT(false, false).? == 3);
129 comptime {
130 assert(peerTypeTAndOptionalT(true, false).? == 0);
131 assert(peerTypeTAndOptionalT(false, false).? == 3);
132 }
133}
134fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
135 if (c) {
136 return if (b) null else usize(0);
137 }
138
139 return usize(3);
140}
141
142test "peer type resolution: [0]u8 and []const u8" {
143 assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
144 assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
145 comptime {
146 assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
147 assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
148 }
149}
150fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
151 if (a) {
152 return []const u8{};
153 }
154
155 return slice[0..1];
156}
157
158test "implicitly cast from [N]T to ?[]const T" {
159 assert(mem.eql(u8, castToOptionalSlice().?, "hi"));
160 comptime assert(mem.eql(u8, castToOptionalSlice().?, "hi"));
161}
162
163fn castToOptionalSlice() ?[]const u8 {
164 return "hi";
165}
166
167test "implicitly cast from [0]T to anyerror![]T" {
168 testCastZeroArrayToErrSliceMut();
169 comptime testCastZeroArrayToErrSliceMut();
170}
171
172fn testCastZeroArrayToErrSliceMut() void {
173 assert((gimmeErrOrSlice() catch unreachable).len == 0);
174}
175
176fn gimmeErrOrSlice() anyerror![]u8 {
177 return []u8{};
178}
179
180test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
181 {
182 var data = "hi";
183 const slice = data[0..];
184 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
185 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
186 }
187 comptime {
188 var data = "hi";
189 const slice = data[0..];
190 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
191 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
192 }
193}
194fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
195 if (a) {
196 return []u8{};
197 }
198
199 return slice[0..1];
200}
201
202test "resolve undefined with integer" {
203 testResolveUndefWithInt(true, 1234);
204 comptime testResolveUndefWithInt(true, 1234);
205}
206fn testResolveUndefWithInt(b: bool, x: i32) void {
207 const value = if (b) x else undefined;
208 if (b) {
209 assert(value == x);
210 }
211}
212
213test "implicit cast from &const [N]T to []const T" {
214 testCastConstArrayRefToConstSlice();
215 comptime testCastConstArrayRefToConstSlice();
216}
217
218fn testCastConstArrayRefToConstSlice() void {
219 const blah = "aoeu";
220 const const_array_ref = &blah;
221 assert(@typeOf(const_array_ref) == *const [4]u8);
222 const slice: []const u8 = const_array_ref;
223 assert(mem.eql(u8, slice, "aoeu"));
224}
225
226test "peer type resolution: error and [N]T" {
227 // TODO: implicit error!T to error!U where T can implicitly cast to U
228 //assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
229 //comptime assert(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
230 assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
231 comptime assert(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
232}
233
234//fn testPeerErrorAndArray(x: u8) error![]const u8 {
235// return switch (x) {
236// 0x00 => "OK",
237// else => error.BadValue,
238// };
239//}
240fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
241 return switch (x) {
242 0x00 => "OK",
243 0x01 => "OKK",
244 else => error.BadValue,
245 };
246}
247
248test "@floatToInt" {
249 testFloatToInts();
250 comptime testFloatToInts();
251}
252
253fn testFloatToInts() void {
254 const x = i32(1e4);
255 assert(x == 10000);
256 const y = @floatToInt(i32, f32(1e4));
257 assert(y == 10000);
258 expectFloatToInt(f16, 255.1, u8, 255);
259 expectFloatToInt(f16, 127.2, i8, 127);
260 expectFloatToInt(f16, -128.2, i8, -128);
261 expectFloatToInt(f32, 255.1, u8, 255);
262 expectFloatToInt(f32, 127.2, i8, 127);
263 expectFloatToInt(f32, -128.2, i8, -128);
264 expectFloatToInt(comptime_int, 1234, i16, 1234);
265}
266
267fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) void {
268 assert(@floatToInt(I, f) == i);
269}
270
271test "cast u128 to f128 and back" {
272 comptime testCast128();
273 testCast128();
274}
275
276fn testCast128() void {
277 assert(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000);
278}
279
280fn cast128Int(x: f128) u128 {
281 return @bitCast(u128, x);
282}
283
284fn cast128Float(x: u128) f128 {
285 return @bitCast(f128, x);
286}
287
288test "const slice widen cast" {
289 const bytes align(4) = []u8{
290 0x12,
291 0x12,
292 0x12,
293 0x12,
294 };
295
296 const u32_value = @bytesToSlice(u32, bytes[0..])[0];
297 assert(u32_value == 0x12121212);
298
299 assert(@bitCast(u32, bytes) == 0x12121212);
300}
301
302test "single-item pointer of array to slice and to unknown length pointer" {
303 testCastPtrOfArrayToSliceAndPtr();
304 comptime testCastPtrOfArrayToSliceAndPtr();
305}
306
307fn testCastPtrOfArrayToSliceAndPtr() void {
308 var array = "aoeu";
309 const x: [*]u8 = &array;
310 x[0] += 1;
311 assert(mem.eql(u8, array[0..], "boeu"));
312 const y: []u8 = &array;
313 y[0] += 1;
314 assert(mem.eql(u8, array[0..], "coeu"));
315}
316
317test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
318 const window_name = [1][*]const u8{c"window name"};
319 const x: [*]const ?[*]const u8 = &window_name;
320 assert(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name"));
321}
322
323test "@intCast comptime_int" {
324 const result = @intCast(i32, 1234);
325 assert(@typeOf(result) == i32);
326 assert(result == 1234);
327}
328
329test "@floatCast comptime_int and comptime_float" {
330 {
331 const result = @floatCast(f16, 1234);
332 assert(@typeOf(result) == f16);
333 assert(result == 1234.0);
334 }
335 {
336 const result = @floatCast(f16, 1234.0);
337 assert(@typeOf(result) == f16);
338 assert(result == 1234.0);
339 }
340 {
341 const result = @floatCast(f32, 1234);
342 assert(@typeOf(result) == f32);
343 assert(result == 1234.0);
344 }
345 {
346 const result = @floatCast(f32, 1234.0);
347 assert(@typeOf(result) == f32);
348 assert(result == 1234.0);
349 }
350}
351
352test "comptime_int @intToFloat" {
353 {
354 const result = @intToFloat(f16, 1234);
355 assert(@typeOf(result) == f16);
356 assert(result == 1234.0);
357 }
358 {
359 const result = @intToFloat(f32, 1234);
360 assert(@typeOf(result) == f32);
361 assert(result == 1234.0);
362 }
363}
364
365test "@bytesToSlice keeps pointer alignment" {
366 var bytes = []u8{ 0x01, 0x02, 0x03, 0x04 };
367 const numbers = @bytesToSlice(u32, bytes[0..]);
368 comptime assert(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32);
369}
370
371test "@intCast i32 to u7" {
372 var x: u128 = maxInt(u128);
373 var y: i32 = 120;
374 var z = x >> @intCast(u7, y);
375 assert(z == 0xff);
376}
377
378test "implicit cast undefined to optional" {
379 assert(MakeType(void).getNull() == null);
380 assert(MakeType(void).getNonNull() != null);
381}
382
383fn MakeType(comptime T: type) type {
384 return struct {
385 fn getNull() ?T {
386 return null;
387 }
388
389 fn getNonNull() ?T {
390 return T(undefined);
391 }
392 };
393}
394
395test "implicit cast from *[N]T to ?[*]T" {
396 var x: ?[*]u16 = null;
397 var y: [4]u16 = [4]u16{ 0, 1, 2, 3 };
398
399 x = &y;
400 assert(std.mem.eql(u16, x.?[0..4], y[0..4]));
401 x.?[0] = 8;
402 y[3] = 6;
403 assert(std.mem.eql(u16, x.?[0..4], y[0..4]));
404}
405
406test "implicit cast from *T to ?*c_void" {
407 var a: u8 = 1;
408 incrementVoidPtrValue(&a);
409 std.debug.assert(a == 2);
410}
411
412fn incrementVoidPtrValue(value: ?*c_void) void {
413 @ptrCast(*u8, value.?).* += 1;
414}
415
416test "implicit cast from [*]T to ?*c_void" {
417 var a = []u8{ 3, 2, 1 };
418 incrementVoidPtrArray(a[0..].ptr, 3);
419 assert(std.mem.eql(u8, a, []u8{ 4, 3, 2 }));
420}
421
422fn incrementVoidPtrArray(array: ?*c_void, len: usize) void {
423 var n: usize = 0;
424 while (n < len) : (n += 1) {
425 @ptrCast([*]u8, array.?)[n] += 1;
426 }
427}
428
429test "*usize to *void" {
430 var i = usize(0);
431 var v = @ptrCast(*void, &i);
432 v.* = {};
433}
434
435test "compile time int to ptr of function" {
436 foobar(FUNCTION_CONSTANT);
437}
438
439pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize));
440pub const PFN_void = extern fn (*c_void) void;
441
442fn foobar(func: PFN_void) void {
443 std.debug.assert(@ptrToInt(func) == maxInt(usize));
444}
445
446test "implicit ptr to *c_void" {
447 var a: u32 = 1;
448 var ptr: *c_void = &a;
449 var b: *u32 = @ptrCast(*u32, ptr);
450 assert(b.* == 1);
451 var ptr2: ?*c_void = &a;
452 var c: *u32 = @ptrCast(*u32, ptr2.?);
453 assert(c.* == 1);
454}
455
456test "@intCast to comptime_int" {
457 assert(@intCast(comptime_int, 0) == 0);
458}
459
460test "implicit cast comptime numbers to any type when the value fits" {
461 const a: u64 = 255;
462 var b: u8 = a;
463 assert(b == 255);
464}
465
466test "@intToEnum passed a comptime_int to an enum with one item" {
467 const E = enum {
468 A,
469 };
470 const x = @intToEnum(E, 0);
471 assert(x == E.A);
472}
test/cases/const_slice_child.zig deleted-45
...@@ -1,45 +0,0 @@
1const debug = @import("std").debug;
2const assert = debug.assert;
3
4var argv: [*]const [*]const u8 = undefined;
5
6test "const slice child" {
7 const strs = ([][*]const u8){
8 c"one",
9 c"two",
10 c"three",
11 };
12 // TODO this should implicitly cast
13 argv = @ptrCast([*]const [*]const u8, &strs);
14 bar(strs.len);
15}
16
17fn foo(args: [][]const u8) void {
18 assert(args.len == 3);
19 assert(streql(args[0], "one"));
20 assert(streql(args[1], "two"));
21 assert(streql(args[2], "three"));
22}
23
24fn bar(argc: usize) void {
25 const args = debug.global_allocator.alloc([]const u8, argc) catch unreachable;
26 for (args) |_, i| {
27 const ptr = argv[i];
28 args[i] = ptr[0..strlen(ptr)];
29 }
30 foo(args);
31}
32
33fn strlen(ptr: [*]const u8) usize {
34 var count: usize = 0;
35 while (ptr[count] != 0) : (count += 1) {}
36 return count;
37}
38
39fn streql(a: []const u8, b: []const u8) bool {
40 if (a.len != b.len) return false;
41 for (a) |item, index| {
42 if (b[index] != item) return false;
43 }
44 return true;
45}
test/cases/coroutine_await_struct.zig deleted-47
...@@ -1,47 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assert = std.debug.assert;
4
5const Foo = struct {
6 x: i32,
7};
8
9var await_a_promise: promise = undefined;
10var await_final_result = Foo{ .x = 0 };
11
12test "coroutine await struct" {
13 var da = std.heap.DirectAllocator.init();
14 defer da.deinit();
15
16 await_seq('a');
17 const p = async<&da.allocator> await_amain() catch unreachable;
18 await_seq('f');
19 resume await_a_promise;
20 await_seq('i');
21 assert(await_final_result.x == 1234);
22 assert(std.mem.eql(u8, await_points, "abcdefghi"));
23}
24async fn await_amain() void {
25 await_seq('b');
26 const p = async await_another() catch unreachable;
27 await_seq('e');
28 await_final_result = await p;
29 await_seq('h');
30}
31async fn await_another() Foo {
32 await_seq('c');
33 suspend {
34 await_seq('d');
35 await_a_promise = @handle();
36 }
37 await_seq('g');
38 return Foo{ .x = 1234 };
39}
40
41var await_points = []u8{0} ** "abcdefghi".len;
42var await_seq_index: usize = 0;
43
44fn await_seq(c: u8) void {
45 await_points[await_seq_index] = c;
46 await_seq_index += 1;
47}
test/cases/coroutines.zig deleted-258
...@@ -1,258 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assert = std.debug.assert;
4
5var x: i32 = 1;
6
7test "create a coroutine and cancel it" {
8 var da = std.heap.DirectAllocator.init();
9 defer da.deinit();
10
11 const p = try async<&da.allocator> simpleAsyncFn();
12 comptime assert(@typeOf(p) == promise->void);
13 cancel p;
14 assert(x == 2);
15}
16async fn simpleAsyncFn() void {
17 x += 1;
18 suspend;
19 x += 1;
20}
21
22test "coroutine suspend, resume, cancel" {
23 var da = std.heap.DirectAllocator.init();
24 defer da.deinit();
25
26 seq('a');
27 const p = try async<&da.allocator> testAsyncSeq();
28 seq('c');
29 resume p;
30 seq('f');
31 cancel p;
32 seq('g');
33
34 assert(std.mem.eql(u8, points, "abcdefg"));
35}
36async fn testAsyncSeq() void {
37 defer seq('e');
38
39 seq('b');
40 suspend;
41 seq('d');
42}
43var points = []u8{0} ** "abcdefg".len;
44var index: usize = 0;
45
46fn seq(c: u8) void {
47 points[index] = c;
48 index += 1;
49}
50
51test "coroutine suspend with block" {
52 var da = std.heap.DirectAllocator.init();
53 defer da.deinit();
54
55 const p = try async<&da.allocator> testSuspendBlock();
56 std.debug.assert(!result);
57 resume a_promise;
58 std.debug.assert(result);
59 cancel p;
60}
61
62var a_promise: promise = undefined;
63var result = false;
64async fn testSuspendBlock() void {
65 suspend {
66 comptime assert(@typeOf(@handle()) == promise->void);
67 a_promise = @handle();
68 }
69
70 //Test to make sure that @handle() works as advertised (issue #1296)
71 //var our_handle: promise = @handle();
72 assert( a_promise == @handle() );
73
74 result = true;
75}
76
77var await_a_promise: promise = undefined;
78var await_final_result: i32 = 0;
79
80test "coroutine await" {
81 var da = std.heap.DirectAllocator.init();
82 defer da.deinit();
83
84 await_seq('a');
85 const p = async<&da.allocator> await_amain() catch unreachable;
86 await_seq('f');
87 resume await_a_promise;
88 await_seq('i');
89 assert(await_final_result == 1234);
90 assert(std.mem.eql(u8, await_points, "abcdefghi"));
91}
92async fn await_amain() void {
93 await_seq('b');
94 const p = async await_another() catch unreachable;
95 await_seq('e');
96 await_final_result = await p;
97 await_seq('h');
98}
99async fn await_another() i32 {
100 await_seq('c');
101 suspend {
102 await_seq('d');
103 await_a_promise = @handle();
104 }
105 await_seq('g');
106 return 1234;
107}
108
109var await_points = []u8{0} ** "abcdefghi".len;
110var await_seq_index: usize = 0;
111
112fn await_seq(c: u8) void {
113 await_points[await_seq_index] = c;
114 await_seq_index += 1;
115}
116
117var early_final_result: i32 = 0;
118
119test "coroutine await early return" {
120 var da = std.heap.DirectAllocator.init();
121 defer da.deinit();
122
123 early_seq('a');
124 const p = async<&da.allocator> early_amain() catch @panic("out of memory");
125 early_seq('f');
126 assert(early_final_result == 1234);
127 assert(std.mem.eql(u8, early_points, "abcdef"));
128}
129async fn early_amain() void {
130 early_seq('b');
131 const p = async early_another() catch @panic("out of memory");
132 early_seq('d');
133 early_final_result = await p;
134 early_seq('e');
135}
136async fn early_another() i32 {
137 early_seq('c');
138 return 1234;
139}
140
141var early_points = []u8{0} ** "abcdef".len;
142var early_seq_index: usize = 0;
143
144fn early_seq(c: u8) void {
145 early_points[early_seq_index] = c;
146 early_seq_index += 1;
147}
148
149test "coro allocation failure" {
150 var failing_allocator = std.debug.FailingAllocator.init(std.debug.global_allocator, 0);
151 if (async<&failing_allocator.allocator> asyncFuncThatNeverGetsRun()) {
152 @panic("expected allocation failure");
153 } else |err| switch (err) {
154 error.OutOfMemory => {},
155 }
156}
157async fn asyncFuncThatNeverGetsRun() void {
158 @panic("coro frame allocation should fail");
159}
160
161test "async function with dot syntax" {
162 const S = struct {
163 var y: i32 = 1;
164 async fn foo() void {
165 y += 1;
166 suspend;
167 }
168 };
169 var da = std.heap.DirectAllocator.init();
170 defer da.deinit();
171 const p = try async<&da.allocator> S.foo();
172 cancel p;
173 assert(S.y == 2);
174}
175
176test "async fn pointer in a struct field" {
177 var data: i32 = 1;
178 const Foo = struct {
179 bar: async<*std.mem.Allocator> fn (*i32) void,
180 };
181 var foo = Foo{ .bar = simpleAsyncFn2 };
182 var da = std.heap.DirectAllocator.init();
183 defer da.deinit();
184 const p = (async<&da.allocator> foo.bar(&data)) catch unreachable;
185 assert(data == 2);
186 cancel p;
187 assert(data == 4);
188}
189async<*std.mem.Allocator> fn simpleAsyncFn2(y: *i32) void {
190 defer y.* += 2;
191 y.* += 1;
192 suspend;
193}
194
195test "async fn with inferred error set" {
196 var da = std.heap.DirectAllocator.init();
197 defer da.deinit();
198 const p = (async<&da.allocator> failing()) catch unreachable;
199 resume p;
200 cancel p;
201}
202async fn failing() !void {
203 suspend;
204 return error.Fail;
205}
206
207test "error return trace across suspend points - early return" {
208 const p = nonFailing();
209 resume p;
210 var da = std.heap.DirectAllocator.init();
211 defer da.deinit();
212 const p2 = try async<&da.allocator> printTrace(p);
213 cancel p2;
214}
215
216test "error return trace across suspend points - async return" {
217 const p = nonFailing();
218 const p2 = try async<std.debug.global_allocator> printTrace(p);
219 resume p;
220 cancel p2;
221}
222
223// TODO https://github.com/ziglang/zig/issues/760
224fn nonFailing() promise->(anyerror!void) {
225 return async<std.debug.global_allocator> suspendThenFail() catch unreachable;
226}
227async fn suspendThenFail() anyerror!void {
228 suspend;
229 return error.Fail;
230}
231async fn printTrace(p: promise->(anyerror!void)) void {
232 (await p) catch |e| {
233 std.debug.assert(e == error.Fail);
234 if (@errorReturnTrace()) |trace| {
235 assert(trace.index == 1);
236 } else switch (builtin.mode) {
237 builtin.Mode.Debug, builtin.Mode.ReleaseSafe => @panic("expected return trace"),
238 builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {},
239 }
240 };
241}
242
243test "break from suspend" {
244 var buf: [500]u8 = undefined;
245 var a = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator;
246 var my_result: i32 = 1;
247 const p = try async<a> testBreakFromSuspend(&my_result);
248 cancel p;
249 std.debug.assert(my_result == 2);
250}
251async fn testBreakFromSuspend(my_result: *i32) void {
252 suspend {
253 resume @handle();
254 }
255 my_result.* += 1;
256 suspend;
257 my_result.* += 1;
258}
test/cases/defer.zig deleted-78
...@@ -1,78 +0,0 @@
1const assert = @import("std").debug.assert;
2
3var result: [3]u8 = undefined;
4var index: usize = undefined;
5
6fn runSomeErrorDefers(x: bool) !bool {
7 index = 0;
8 defer {
9 result[index] = 'a';
10 index += 1;
11 }
12 errdefer {
13 result[index] = 'b';
14 index += 1;
15 }
16 defer {
17 result[index] = 'c';
18 index += 1;
19 }
20 return if (x) x else error.FalseNotAllowed;
21}
22
23test "mixing normal and error defers" {
24 assert(runSomeErrorDefers(true) catch unreachable);
25 assert(result[0] == 'c');
26 assert(result[1] == 'a');
27
28 const ok = runSomeErrorDefers(false) catch |err| x: {
29 assert(err == error.FalseNotAllowed);
30 break :x true;
31 };
32 assert(ok);
33 assert(result[0] == 'c');
34 assert(result[1] == 'b');
35 assert(result[2] == 'a');
36}
37
38test "break and continue inside loop inside defer expression" {
39 testBreakContInDefer(10);
40 comptime testBreakContInDefer(10);
41}
42
43fn testBreakContInDefer(x: usize) void {
44 defer {
45 var i: usize = 0;
46 while (i < x) : (i += 1) {
47 if (i < 5) continue;
48 if (i == 5) break;
49 }
50 assert(i == 5);
51 }
52}
53
54test "defer and labeled break" {
55 var i = usize(0);
56
57 blk: {
58 defer i += 1;
59 break :blk;
60 }
61
62 assert(i == 1);
63}
64
65test "errdefer does not apply to fn inside fn" {
66 if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| assert(e == error.Bad);
67}
68
69fn testNestedFnErrDefer() anyerror!void {
70 var a: i32 = 0;
71 errdefer a += 1;
72 const S = struct {
73 fn baz() anyerror {
74 return error.Bad;
75 }
76 };
77 return S.baz();
78}
test/cases/enum.zig deleted-894
...@@ -1,894 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3
4test "enum type" {
5 const foo1 = Foo{ .One = 13 };
6 const foo2 = Foo{
7 .Two = Point{
8 .x = 1234,
9 .y = 5678,
10 },
11 };
12 const bar = Bar.B;
13
14 assert(bar == Bar.B);
15 assert(@memberCount(Foo) == 3);
16 assert(@memberCount(Bar) == 4);
17 assert(@sizeOf(Foo) == @sizeOf(FooNoVoid));
18 assert(@sizeOf(Bar) == 1);
19}
20
21test "enum as return value" {
22 switch (returnAnInt(13)) {
23 Foo.One => |value| assert(value == 13),
24 else => unreachable,
25 }
26}
27
28const Point = struct {
29 x: u64,
30 y: u64,
31};
32const Foo = union(enum) {
33 One: i32,
34 Two: Point,
35 Three: void,
36};
37const FooNoVoid = union(enum) {
38 One: i32,
39 Two: Point,
40};
41const Bar = enum {
42 A,
43 B,
44 C,
45 D,
46};
47
48fn returnAnInt(x: i32) Foo {
49 return Foo{ .One = x };
50}
51
52test "constant enum with payload" {
53 var empty = AnEnumWithPayload{ .Empty = {} };
54 var full = AnEnumWithPayload{ .Full = 13 };
55 shouldBeEmpty(empty);
56 shouldBeNotEmpty(full);
57}
58
59fn shouldBeEmpty(x: AnEnumWithPayload) void {
60 switch (x) {
61 AnEnumWithPayload.Empty => {},
62 else => unreachable,
63 }
64}
65
66fn shouldBeNotEmpty(x: AnEnumWithPayload) void {
67 switch (x) {
68 AnEnumWithPayload.Empty => unreachable,
69 else => {},
70 }
71}
72
73const AnEnumWithPayload = union(enum) {
74 Empty: void,
75 Full: i32,
76};
77
78const Number = enum {
79 Zero,
80 One,
81 Two,
82 Three,
83 Four,
84};
85
86test "enum to int" {
87 shouldEqual(Number.Zero, 0);
88 shouldEqual(Number.One, 1);
89 shouldEqual(Number.Two, 2);
90 shouldEqual(Number.Three, 3);
91 shouldEqual(Number.Four, 4);
92}
93
94fn shouldEqual(n: Number, expected: u3) void {
95 assert(@enumToInt(n) == expected);
96}
97
98test "int to enum" {
99 testIntToEnumEval(3);
100}
101fn testIntToEnumEval(x: i32) void {
102 assert(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three);
103}
104const IntToEnumNumber = enum {
105 Zero,
106 One,
107 Two,
108 Three,
109 Four,
110};
111
112test "@tagName" {
113 assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
114 comptime assert(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
115}
116
117fn testEnumTagNameBare(n: BareNumber) []const u8 {
118 return @tagName(n);
119}
120
121const BareNumber = enum {
122 One,
123 Two,
124 Three,
125};
126
127test "enum alignment" {
128 comptime {
129 assert(@alignOf(AlignTestEnum) >= @alignOf([9]u8));
130 assert(@alignOf(AlignTestEnum) >= @alignOf(u64));
131 }
132}
133
134const AlignTestEnum = union(enum) {
135 A: [9]u8,
136 B: u64,
137};
138
139const ValueCount1 = enum {
140 I0,
141};
142const ValueCount2 = enum {
143 I0,
144 I1,
145};
146const ValueCount256 = enum {
147 I0,
148 I1,
149 I2,
150 I3,
151 I4,
152 I5,
153 I6,
154 I7,
155 I8,
156 I9,
157 I10,
158 I11,
159 I12,
160 I13,
161 I14,
162 I15,
163 I16,
164 I17,
165 I18,
166 I19,
167 I20,
168 I21,
169 I22,
170 I23,
171 I24,
172 I25,
173 I26,
174 I27,
175 I28,
176 I29,
177 I30,
178 I31,
179 I32,
180 I33,
181 I34,
182 I35,
183 I36,
184 I37,
185 I38,
186 I39,
187 I40,
188 I41,
189 I42,
190 I43,
191 I44,
192 I45,
193 I46,
194 I47,
195 I48,
196 I49,
197 I50,
198 I51,
199 I52,
200 I53,
201 I54,
202 I55,
203 I56,
204 I57,
205 I58,
206 I59,
207 I60,
208 I61,
209 I62,
210 I63,
211 I64,
212 I65,
213 I66,
214 I67,
215 I68,
216 I69,
217 I70,
218 I71,
219 I72,
220 I73,
221 I74,
222 I75,
223 I76,
224 I77,
225 I78,
226 I79,
227 I80,
228 I81,
229 I82,
230 I83,
231 I84,
232 I85,
233 I86,
234 I87,
235 I88,
236 I89,
237 I90,
238 I91,
239 I92,
240 I93,
241 I94,
242 I95,
243 I96,
244 I97,
245 I98,
246 I99,
247 I100,
248 I101,
249 I102,
250 I103,
251 I104,
252 I105,
253 I106,
254 I107,
255 I108,
256 I109,
257 I110,
258 I111,
259 I112,
260 I113,
261 I114,
262 I115,
263 I116,
264 I117,
265 I118,
266 I119,
267 I120,
268 I121,
269 I122,
270 I123,
271 I124,
272 I125,
273 I126,
274 I127,
275 I128,
276 I129,
277 I130,
278 I131,
279 I132,
280 I133,
281 I134,
282 I135,
283 I136,
284 I137,
285 I138,
286 I139,
287 I140,
288 I141,
289 I142,
290 I143,
291 I144,
292 I145,
293 I146,
294 I147,
295 I148,
296 I149,
297 I150,
298 I151,
299 I152,
300 I153,
301 I154,
302 I155,
303 I156,
304 I157,
305 I158,
306 I159,
307 I160,
308 I161,
309 I162,
310 I163,
311 I164,
312 I165,
313 I166,
314 I167,
315 I168,
316 I169,
317 I170,
318 I171,
319 I172,
320 I173,
321 I174,
322 I175,
323 I176,
324 I177,
325 I178,
326 I179,
327 I180,
328 I181,
329 I182,
330 I183,
331 I184,
332 I185,
333 I186,
334 I187,
335 I188,
336 I189,
337 I190,
338 I191,
339 I192,
340 I193,
341 I194,
342 I195,
343 I196,
344 I197,
345 I198,
346 I199,
347 I200,
348 I201,
349 I202,
350 I203,
351 I204,
352 I205,
353 I206,
354 I207,
355 I208,
356 I209,
357 I210,
358 I211,
359 I212,
360 I213,
361 I214,
362 I215,
363 I216,
364 I217,
365 I218,
366 I219,
367 I220,
368 I221,
369 I222,
370 I223,
371 I224,
372 I225,
373 I226,
374 I227,
375 I228,
376 I229,
377 I230,
378 I231,
379 I232,
380 I233,
381 I234,
382 I235,
383 I236,
384 I237,
385 I238,
386 I239,
387 I240,
388 I241,
389 I242,
390 I243,
391 I244,
392 I245,
393 I246,
394 I247,
395 I248,
396 I249,
397 I250,
398 I251,
399 I252,
400 I253,
401 I254,
402 I255,
403};
404const ValueCount257 = enum {
405 I0,
406 I1,
407 I2,
408 I3,
409 I4,
410 I5,
411 I6,
412 I7,
413 I8,
414 I9,
415 I10,
416 I11,
417 I12,
418 I13,
419 I14,
420 I15,
421 I16,
422 I17,
423 I18,
424 I19,
425 I20,
426 I21,
427 I22,
428 I23,
429 I24,
430 I25,
431 I26,
432 I27,
433 I28,
434 I29,
435 I30,
436 I31,
437 I32,
438 I33,
439 I34,
440 I35,
441 I36,
442 I37,
443 I38,
444 I39,
445 I40,
446 I41,
447 I42,
448 I43,
449 I44,
450 I45,
451 I46,
452 I47,
453 I48,
454 I49,
455 I50,
456 I51,
457 I52,
458 I53,
459 I54,
460 I55,
461 I56,
462 I57,
463 I58,
464 I59,
465 I60,
466 I61,
467 I62,
468 I63,
469 I64,
470 I65,
471 I66,
472 I67,
473 I68,
474 I69,
475 I70,
476 I71,
477 I72,
478 I73,
479 I74,
480 I75,
481 I76,
482 I77,
483 I78,
484 I79,
485 I80,
486 I81,
487 I82,
488 I83,
489 I84,
490 I85,
491 I86,
492 I87,
493 I88,
494 I89,
495 I90,
496 I91,
497 I92,
498 I93,
499 I94,
500 I95,
501 I96,
502 I97,
503 I98,
504 I99,
505 I100,
506 I101,
507 I102,
508 I103,
509 I104,
510 I105,
511 I106,
512 I107,
513 I108,
514 I109,
515 I110,
516 I111,
517 I112,
518 I113,
519 I114,
520 I115,
521 I116,
522 I117,
523 I118,
524 I119,
525 I120,
526 I121,
527 I122,
528 I123,
529 I124,
530 I125,
531 I126,
532 I127,
533 I128,
534 I129,
535 I130,
536 I131,
537 I132,
538 I133,
539 I134,
540 I135,
541 I136,
542 I137,
543 I138,
544 I139,
545 I140,
546 I141,
547 I142,
548 I143,
549 I144,
550 I145,
551 I146,
552 I147,
553 I148,
554 I149,
555 I150,
556 I151,
557 I152,
558 I153,
559 I154,
560 I155,
561 I156,
562 I157,
563 I158,
564 I159,
565 I160,
566 I161,
567 I162,
568 I163,
569 I164,
570 I165,
571 I166,
572 I167,
573 I168,
574 I169,
575 I170,
576 I171,
577 I172,
578 I173,
579 I174,
580 I175,
581 I176,
582 I177,
583 I178,
584 I179,
585 I180,
586 I181,
587 I182,
588 I183,
589 I184,
590 I185,
591 I186,
592 I187,
593 I188,
594 I189,
595 I190,
596 I191,
597 I192,
598 I193,
599 I194,
600 I195,
601 I196,
602 I197,
603 I198,
604 I199,
605 I200,
606 I201,
607 I202,
608 I203,
609 I204,
610 I205,
611 I206,
612 I207,
613 I208,
614 I209,
615 I210,
616 I211,
617 I212,
618 I213,
619 I214,
620 I215,
621 I216,
622 I217,
623 I218,
624 I219,
625 I220,
626 I221,
627 I222,
628 I223,
629 I224,
630 I225,
631 I226,
632 I227,
633 I228,
634 I229,
635 I230,
636 I231,
637 I232,
638 I233,
639 I234,
640 I235,
641 I236,
642 I237,
643 I238,
644 I239,
645 I240,
646 I241,
647 I242,
648 I243,
649 I244,
650 I245,
651 I246,
652 I247,
653 I248,
654 I249,
655 I250,
656 I251,
657 I252,
658 I253,
659 I254,
660 I255,
661 I256,
662};
663
664test "enum sizes" {
665 comptime {
666 assert(@sizeOf(ValueCount1) == 0);
667 assert(@sizeOf(ValueCount2) == 1);
668 assert(@sizeOf(ValueCount256) == 1);
669 assert(@sizeOf(ValueCount257) == 2);
670 }
671}
672
673const Small2 = enum(u2) {
674 One,
675 Two,
676};
677const Small = enum(u2) {
678 One,
679 Two,
680 Three,
681 Four,
682};
683
684test "set enum tag type" {
685 {
686 var x = Small.One;
687 x = Small.Two;
688 comptime assert(@TagType(Small) == u2);
689 }
690 {
691 var x = Small2.One;
692 x = Small2.Two;
693 comptime assert(@TagType(Small2) == u2);
694 }
695}
696
697const A = enum(u3) {
698 One,
699 Two,
700 Three,
701 Four,
702 One2,
703 Two2,
704 Three2,
705 Four2,
706};
707
708const B = enum(u3) {
709 One3,
710 Two3,
711 Three3,
712 Four3,
713 One23,
714 Two23,
715 Three23,
716 Four23,
717};
718
719const C = enum(u2) {
720 One4,
721 Two4,
722 Three4,
723 Four4,
724};
725
726const BitFieldOfEnums = packed struct {
727 a: A,
728 b: B,
729 c: C,
730};
731
732const bit_field_1 = BitFieldOfEnums{
733 .a = A.Two,
734 .b = B.Three3,
735 .c = C.Four4,
736};
737
738test "bit field access with enum fields" {
739 var data = bit_field_1;
740 assert(getA(&data) == A.Two);
741 assert(getB(&data) == B.Three3);
742 assert(getC(&data) == C.Four4);
743 comptime assert(@sizeOf(BitFieldOfEnums) == 1);
744
745 data.b = B.Four3;
746 assert(data.b == B.Four3);
747
748 data.a = A.Three;
749 assert(data.a == A.Three);
750 assert(data.b == B.Four3);
751}
752
753fn getA(data: *const BitFieldOfEnums) A {
754 return data.a;
755}
756
757fn getB(data: *const BitFieldOfEnums) B {
758 return data.b;
759}
760
761fn getC(data: *const BitFieldOfEnums) C {
762 return data.c;
763}
764
765test "casting enum to its tag type" {
766 testCastEnumToTagType(Small2.Two);
767 comptime testCastEnumToTagType(Small2.Two);
768}
769
770fn testCastEnumToTagType(value: Small2) void {
771 assert(@enumToInt(value) == 1);
772}
773
774const MultipleChoice = enum(u32) {
775 A = 20,
776 B = 40,
777 C = 60,
778 D = 1000,
779};
780
781test "enum with specified tag values" {
782 testEnumWithSpecifiedTagValues(MultipleChoice.C);
783 comptime testEnumWithSpecifiedTagValues(MultipleChoice.C);
784}
785
786fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void {
787 assert(@enumToInt(x) == 60);
788 assert(1234 == switch (x) {
789 MultipleChoice.A => 1,
790 MultipleChoice.B => 2,
791 MultipleChoice.C => u32(1234),
792 MultipleChoice.D => 4,
793 });
794}
795
796const MultipleChoice2 = enum(u32) {
797 Unspecified1,
798 A = 20,
799 Unspecified2,
800 B = 40,
801 Unspecified3,
802 C = 60,
803 Unspecified4,
804 D = 1000,
805 Unspecified5,
806};
807
808test "enum with specified and unspecified tag values" {
809 testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
810 comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
811}
812
813fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
814 assert(@enumToInt(x) == 1000);
815 assert(1234 == switch (x) {
816 MultipleChoice2.A => 1,
817 MultipleChoice2.B => 2,
818 MultipleChoice2.C => 3,
819 MultipleChoice2.D => u32(1234),
820 MultipleChoice2.Unspecified1 => 5,
821 MultipleChoice2.Unspecified2 => 6,
822 MultipleChoice2.Unspecified3 => 7,
823 MultipleChoice2.Unspecified4 => 8,
824 MultipleChoice2.Unspecified5 => 9,
825 });
826}
827
828test "cast integer literal to enum" {
829 assert(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
830 assert(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);
831}
832
833const EnumWithOneMember = enum {
834 Eof,
835};
836
837fn doALoopThing(id: EnumWithOneMember) void {
838 while (true) {
839 if (id == EnumWithOneMember.Eof) {
840 break;
841 }
842 @compileError("above if condition should be comptime");
843 }
844}
845
846test "comparison operator on enum with one member is comptime known" {
847 doALoopThing(EnumWithOneMember.Eof);
848}
849
850const State = enum {
851 Start,
852};
853test "switch on enum with one member is comptime known" {
854 var state = State.Start;
855 switch (state) {
856 State.Start => return,
857 }
858 @compileError("analysis should not reach here");
859}
860
861const EnumWithTagValues = enum(u4) {
862 A = 1 << 0,
863 B = 1 << 1,
864 C = 1 << 2,
865 D = 1 << 3,
866};
867test "enum with tag values don't require parens" {
868 assert(@enumToInt(EnumWithTagValues.C) == 0b0100);
869}
870
871test "enum with 1 field but explicit tag type should still have the tag type" {
872 const Enum = enum(u8) {
873 B = 2,
874 };
875 comptime @import("std").debug.assert(@sizeOf(Enum) == @sizeOf(u8));
876}
877
878test "empty extern enum with members" {
879 const E = extern enum {
880 A,
881 B,
882 C,
883 };
884 assert(@sizeOf(E) == @sizeOf(c_int));
885}
886
887test "aoeu" {
888 const LocalFoo = enum {
889 A = 1,
890 B = 0,
891 };
892 var b = LocalFoo.B;
893 assert(mem.eql(u8, @tagName(b), "B"));
894}
test/cases/enum_with_members.zig deleted-27
...@@ -1,27 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3const fmt = @import("std").fmt;
4
5const ET = union(enum) {
6 SINT: i32,
7 UINT: u32,
8
9 pub fn print(a: *const ET, buf: []u8) anyerror!usize {
10 return switch (a.*) {
11 ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
12 ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
13 };
14 }
15};
16
17test "enum with members" {
18 const a = ET{ .SINT = -42 };
19 const b = ET{ .UINT = 42 };
20 var buf: [20]u8 = undefined;
21
22 assert((a.print(buf[0..]) catch unreachable) == 3);
23 assert(mem.eql(u8, buf[0..3], "-42"));
24
25 assert((b.print(buf[0..]) catch unreachable) == 2);
26 assert(mem.eql(u8, buf[0..2], "42"));
27}
test/cases/error.zig deleted-245
...@@ -1,245 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const mem = std.mem;
4const builtin = @import("builtin");
5
6pub fn foo() anyerror!i32 {
7 const x = try bar();
8 return x + 1;
9}
10
11pub fn bar() anyerror!i32 {
12 return 13;
13}
14
15pub fn baz() anyerror!i32 {
16 const y = foo() catch 1234;
17 return y + 1;
18}
19
20test "error wrapping" {
21 assert((baz() catch unreachable) == 15);
22}
23
24fn gimmeItBroke() []const u8 {
25 return @errorName(error.ItBroke);
26}
27
28test "@errorName" {
29 assert(mem.eql(u8, @errorName(error.AnError), "AnError"));
30 assert(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName"));
31}
32
33test "error values" {
34 const a = @errorToInt(error.err1);
35 const b = @errorToInt(error.err2);
36 assert(a != b);
37}
38
39test "redefinition of error values allowed" {
40 shouldBeNotEqual(error.AnError, error.SecondError);
41}
42fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
43 if (a == b) unreachable;
44}
45
46test "error binary operator" {
47 const a = errBinaryOperatorG(true) catch 3;
48 const b = errBinaryOperatorG(false) catch 3;
49 assert(a == 3);
50 assert(b == 10);
51}
52fn errBinaryOperatorG(x: bool) anyerror!isize {
53 return if (x) error.ItBroke else isize(10);
54}
55
56test "unwrap simple value from error" {
57 const i = unwrapSimpleValueFromErrorDo() catch unreachable;
58 assert(i == 13);
59}
60fn unwrapSimpleValueFromErrorDo() anyerror!isize {
61 return 13;
62}
63
64test "error return in assignment" {
65 doErrReturnInAssignment() catch unreachable;
66}
67
68fn doErrReturnInAssignment() anyerror!void {
69 var x: i32 = undefined;
70 x = try makeANonErr();
71}
72
73fn makeANonErr() anyerror!i32 {
74 return 1;
75}
76
77test "error union type " {
78 testErrorUnionType();
79 comptime testErrorUnionType();
80}
81
82fn testErrorUnionType() void {
83 const x: anyerror!i32 = 1234;
84 if (x) |value| assert(value == 1234) else |_| unreachable;
85 assert(@typeId(@typeOf(x)) == builtin.TypeId.ErrorUnion);
86 assert(@typeId(@typeOf(x).ErrorSet) == builtin.TypeId.ErrorSet);
87 assert(@typeOf(x).ErrorSet == anyerror);
88}
89
90test "error set type " {
91 testErrorSetType();
92 comptime testErrorSetType();
93}
94
95const MyErrSet = error{
96 OutOfMemory,
97 FileNotFound,
98};
99
100fn testErrorSetType() void {
101 assert(@memberCount(MyErrSet) == 2);
102
103 const a: MyErrSet!i32 = 5678;
104 const b: MyErrSet!i32 = MyErrSet.OutOfMemory;
105
106 if (a) |value| assert(value == 5678) else |err| switch (err) {
107 error.OutOfMemory => unreachable,
108 error.FileNotFound => unreachable,
109 }
110}
111
112test "explicit error set cast" {
113 testExplicitErrorSetCast(Set1.A);
114 comptime testExplicitErrorSetCast(Set1.A);
115}
116
117const Set1 = error{
118 A,
119 B,
120};
121const Set2 = error{
122 A,
123 C,
124};
125
126fn testExplicitErrorSetCast(set1: Set1) void {
127 var x = @errSetCast(Set2, set1);
128 var y = @errSetCast(Set1, x);
129 assert(y == error.A);
130}
131
132test "comptime test error for empty error set" {
133 testComptimeTestErrorEmptySet(1234);
134 comptime testComptimeTestErrorEmptySet(1234);
135}
136
137const EmptyErrorSet = error{};
138
139fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void {
140 if (x) |v| assert(v == 1234) else |err| @compileError("bad");
141}
142
143test "syntax: optional operator in front of error union operator" {
144 comptime {
145 assert(?(anyerror!i32) == ?(anyerror!i32));
146 }
147}
148
149test "comptime err to int of error set with only 1 possible value" {
150 testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
151 comptime testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
152}
153fn testErrToIntWithOnePossibleValue(
154 x: error{A},
155 comptime value: u32,
156) void {
157 if (@errorToInt(x) != value) {
158 @compileError("bad");
159 }
160}
161
162test "error union peer type resolution" {
163 testErrorUnionPeerTypeResolution(1);
164 comptime testErrorUnionPeerTypeResolution(1);
165}
166
167fn testErrorUnionPeerTypeResolution(x: i32) void {
168 const y = switch (x) {
169 1 => bar_1(),
170 2 => baz_1(),
171 else => quux_1(),
172 };
173}
174
175fn bar_1() anyerror {
176 return error.A;
177}
178
179fn baz_1() !i32 {
180 return error.B;
181}
182
183fn quux_1() !i32 {
184 return error.C;
185}
186
187test "error: fn returning empty error set can be passed as fn returning any error" {
188 entry();
189 comptime entry();
190}
191
192fn entry() void {
193 foo2(bar2);
194}
195
196fn foo2(f: fn () anyerror!void) void {
197 const x = f();
198}
199
200fn bar2() (error{}!void) {}
201
202test "error: Zero sized error set returned with value payload crash" {
203 _ = foo3(0);
204 _ = comptime foo3(0);
205}
206
207const Error = error{};
208fn foo3(b: usize) Error!usize {
209 return b;
210}
211
212test "error: Infer error set from literals" {
213 _ = nullLiteral("n") catch |err| handleErrors(err);
214 _ = floatLiteral("n") catch |err| handleErrors(err);
215 _ = intLiteral("n") catch |err| handleErrors(err);
216 _ = comptime nullLiteral("n") catch |err| handleErrors(err);
217 _ = comptime floatLiteral("n") catch |err| handleErrors(err);
218 _ = comptime intLiteral("n") catch |err| handleErrors(err);
219}
220
221fn handleErrors(err: var) noreturn {
222 switch (err) {
223 error.T => {},
224 }
225
226 unreachable;
227}
228
229fn nullLiteral(str: []const u8) !?i64 {
230 if (str[0] == 'n') return null;
231
232 return error.T;
233}
234
235fn floatLiteral(str: []const u8) !?f64 {
236 if (str[0] == 'n') return 1.0;
237
238 return error.T;
239}
240
241fn intLiteral(str: []const u8) !?i64 {
242 if (str[0] == 'n') return 1;
243
244 return error.T;
245}
test/cases/eval.zig deleted-782
...@@ -1,782 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const builtin = @import("builtin");
4
5test "compile time recursion" {
6 assert(some_data.len == 21);
7}
8var some_data: [@intCast(usize, fibonacci(7))]u8 = undefined;
9fn fibonacci(x: i32) i32 {
10 if (x <= 1) return 1;
11 return fibonacci(x - 1) + fibonacci(x - 2);
12}
13
14fn unwrapAndAddOne(blah: ?i32) i32 {
15 return blah.? + 1;
16}
17const should_be_1235 = unwrapAndAddOne(1234);
18test "static add one" {
19 assert(should_be_1235 == 1235);
20}
21
22test "inlined loop" {
23 comptime var i = 0;
24 comptime var sum = 0;
25 inline while (i <= 5) : (i += 1)
26 sum += i;
27 assert(sum == 15);
28}
29
30fn gimme1or2(comptime a: bool) i32 {
31 const x: i32 = 1;
32 const y: i32 = 2;
33 comptime var z: i32 = if (a) x else y;
34 return z;
35}
36test "inline variable gets result of const if" {
37 assert(gimme1or2(true) == 1);
38 assert(gimme1or2(false) == 2);
39}
40
41test "static function evaluation" {
42 assert(statically_added_number == 3);
43}
44const statically_added_number = staticAdd(1, 2);
45fn staticAdd(a: i32, b: i32) i32 {
46 return a + b;
47}
48
49test "const expr eval on single expr blocks" {
50 assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
51}
52
53fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
54 const literal = 3;
55
56 const result = if (b) b: {
57 break :b literal;
58 } else b: {
59 break :b x;
60 };
61
62 return result;
63}
64
65test "statically initialized list" {
66 assert(static_point_list[0].x == 1);
67 assert(static_point_list[0].y == 2);
68 assert(static_point_list[1].x == 3);
69 assert(static_point_list[1].y == 4);
70}
71const Point = struct {
72 x: i32,
73 y: i32,
74};
75const static_point_list = []Point{
76 makePoint(1, 2),
77 makePoint(3, 4),
78};
79fn makePoint(x: i32, y: i32) Point {
80 return Point{
81 .x = x,
82 .y = y,
83 };
84}
85
86test "static eval list init" {
87 assert(static_vec3.data[2] == 1.0);
88 assert(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
89}
90const static_vec3 = vec3(0.0, 0.0, 1.0);
91pub const Vec3 = struct {
92 data: [3]f32,
93};
94pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
95 return Vec3{ .data = []f32{
96 x,
97 y,
98 z,
99 } };
100}
101
102test "constant expressions" {
103 var array: [array_size]u8 = undefined;
104 assert(@sizeOf(@typeOf(array)) == 20);
105}
106const array_size: u8 = 20;
107
108test "constant struct with negation" {
109 assert(vertices[0].x == -0.6);
110}
111const Vertex = struct {
112 x: f32,
113 y: f32,
114 r: f32,
115 g: f32,
116 b: f32,
117};
118const vertices = []Vertex{
119 Vertex{
120 .x = -0.6,
121 .y = -0.4,
122 .r = 1.0,
123 .g = 0.0,
124 .b = 0.0,
125 },
126 Vertex{
127 .x = 0.6,
128 .y = -0.4,
129 .r = 0.0,
130 .g = 1.0,
131 .b = 0.0,
132 },
133 Vertex{
134 .x = 0.0,
135 .y = 0.6,
136 .r = 0.0,
137 .g = 0.0,
138 .b = 1.0,
139 },
140};
141
142test "statically initialized struct" {
143 st_init_str_foo.x += 1;
144 assert(st_init_str_foo.x == 14);
145}
146const StInitStrFoo = struct {
147 x: i32,
148 y: bool,
149};
150var st_init_str_foo = StInitStrFoo{
151 .x = 13,
152 .y = true,
153};
154
155test "statically initalized array literal" {
156 const y: [4]u8 = st_init_arr_lit_x;
157 assert(y[3] == 4);
158}
159const st_init_arr_lit_x = []u8{
160 1,
161 2,
162 3,
163 4,
164};
165
166test "const slice" {
167 comptime {
168 const a = "1234567890";
169 assert(a.len == 10);
170 const b = a[1..2];
171 assert(b.len == 1);
172 assert(b[0] == '2');
173 }
174}
175
176test "try to trick eval with runtime if" {
177 assert(testTryToTrickEvalWithRuntimeIf(true) == 10);
178}
179
180fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
181 comptime var i: usize = 0;
182 inline while (i < 10) : (i += 1) {
183 const result = if (b) false else true;
184 }
185 comptime {
186 return i;
187 }
188}
189
190fn max(comptime T: type, a: T, b: T) T {
191 if (T == bool) {
192 return a or b;
193 } else if (a > b) {
194 return a;
195 } else {
196 return b;
197 }
198}
199fn letsTryToCompareBools(a: bool, b: bool) bool {
200 return max(bool, a, b);
201}
202test "inlined block and runtime block phi" {
203 assert(letsTryToCompareBools(true, true));
204 assert(letsTryToCompareBools(true, false));
205 assert(letsTryToCompareBools(false, true));
206 assert(!letsTryToCompareBools(false, false));
207
208 comptime {
209 assert(letsTryToCompareBools(true, true));
210 assert(letsTryToCompareBools(true, false));
211 assert(letsTryToCompareBools(false, true));
212 assert(!letsTryToCompareBools(false, false));
213 }
214}
215
216const CmdFn = struct {
217 name: []const u8,
218 func: fn (i32) i32,
219};
220
221const cmd_fns = []CmdFn{
222 CmdFn{
223 .name = "one",
224 .func = one,
225 },
226 CmdFn{
227 .name = "two",
228 .func = two,
229 },
230 CmdFn{
231 .name = "three",
232 .func = three,
233 },
234};
235fn one(value: i32) i32 {
236 return value + 1;
237}
238fn two(value: i32) i32 {
239 return value + 2;
240}
241fn three(value: i32) i32 {
242 return value + 3;
243}
244
245fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
246 var result: i32 = start_value;
247 comptime var i = 0;
248 inline while (i < cmd_fns.len) : (i += 1) {
249 if (cmd_fns[i].name[0] == prefix_char) {
250 result = cmd_fns[i].func(result);
251 }
252 }
253 return result;
254}
255
256test "comptime iterate over fn ptr list" {
257 assert(performFn('t', 1) == 6);
258 assert(performFn('o', 0) == 1);
259 assert(performFn('w', 99) == 99);
260}
261
262test "eval @setRuntimeSafety at compile-time" {
263 const result = comptime fnWithSetRuntimeSafety();
264 assert(result == 1234);
265}
266
267fn fnWithSetRuntimeSafety() i32 {
268 @setRuntimeSafety(true);
269 return 1234;
270}
271
272test "eval @setFloatMode at compile-time" {
273 const result = comptime fnWithFloatMode();
274 assert(result == 1234.0);
275}
276
277fn fnWithFloatMode() f32 {
278 @setFloatMode(builtin.FloatMode.Strict);
279 return 1234.0;
280}
281
282const SimpleStruct = struct {
283 field: i32,
284
285 fn method(self: *const SimpleStruct) i32 {
286 return self.field + 3;
287 }
288};
289
290var simple_struct = SimpleStruct{ .field = 1234 };
291
292const bound_fn = simple_struct.method;
293
294test "call method on bound fn referring to var instance" {
295 assert(bound_fn() == 1237);
296}
297
298test "ptr to local array argument at comptime" {
299 comptime {
300 var bytes: [10]u8 = undefined;
301 modifySomeBytes(bytes[0..]);
302 assert(bytes[0] == 'a');
303 assert(bytes[9] == 'b');
304 }
305}
306
307fn modifySomeBytes(bytes: []u8) void {
308 bytes[0] = 'a';
309 bytes[9] = 'b';
310}
311
312test "comparisons 0 <= uint and 0 > uint should be comptime" {
313 testCompTimeUIntComparisons(1234);
314}
315fn testCompTimeUIntComparisons(x: u32) void {
316 if (!(0 <= x)) {
317 @compileError("this condition should be comptime known");
318 }
319 if (0 > x) {
320 @compileError("this condition should be comptime known");
321 }
322 if (!(x >= 0)) {
323 @compileError("this condition should be comptime known");
324 }
325 if (x < 0) {
326 @compileError("this condition should be comptime known");
327 }
328}
329
330test "const ptr to variable data changes at runtime" {
331 assert(foo_ref.name[0] == 'a');
332 foo_ref.name = "b";
333 assert(foo_ref.name[0] == 'b');
334}
335
336const Foo = struct {
337 name: []const u8,
338};
339
340var foo_contents = Foo{ .name = "a" };
341const foo_ref = &foo_contents;
342
343test "create global array with for loop" {
344 assert(global_array[5] == 5 * 5);
345 assert(global_array[9] == 9 * 9);
346}
347
348const global_array = x: {
349 var result: [10]usize = undefined;
350 for (result) |*item, index| {
351 item.* = index * index;
352 }
353 break :x result;
354};
355
356test "compile-time downcast when the bits fit" {
357 comptime {
358 const spartan_count: u16 = 255;
359 const byte = @intCast(u8, spartan_count);
360 assert(byte == 255);
361 }
362}
363
364const hi1 = "hi";
365const hi2 = hi1;
366test "const global shares pointer with other same one" {
367 assertEqualPtrs(&hi1[0], &hi2[0]);
368 comptime assert(&hi1[0] == &hi2[0]);
369}
370fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) void {
371 assert(ptr1 == ptr2);
372}
373
374test "@setEvalBranchQuota" {
375 comptime {
376 // 1001 for the loop and then 1 more for the assert fn call
377 @setEvalBranchQuota(1002);
378 var i = 0;
379 var sum = 0;
380 while (i < 1001) : (i += 1) {
381 sum += i;
382 }
383 assert(sum == 500500);
384 }
385}
386
387// TODO test "float literal at compile time not lossy" {
388// TODO assert(16777216.0 + 1.0 == 16777217.0);
389// TODO assert(9007199254740992.0 + 1.0 == 9007199254740993.0);
390// TODO }
391
392test "f32 at compile time is lossy" {
393 assert(f32(1 << 24) + 1 == 1 << 24);
394}
395
396test "f64 at compile time is lossy" {
397 assert(f64(1 << 53) + 1 == 1 << 53);
398}
399
400test "f128 at compile time is lossy" {
401 assert(f128(10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
402}
403
404// TODO need a better implementation of bigfloat_init_bigint
405// assert(f128(1 << 113) == 10384593717069655257060992658440192);
406
407pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
408 return struct {
409 pub const Node = struct {};
410 };
411}
412
413test "string literal used as comptime slice is memoized" {
414 const a = "link";
415 const b = "link";
416 comptime assert(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
417 comptime assert(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
418}
419
420test "comptime slice of undefined pointer of length 0" {
421 const slice1 = ([*]i32)(undefined)[0..0];
422 assert(slice1.len == 0);
423 const slice2 = ([*]i32)(undefined)[100..100];
424 assert(slice2.len == 0);
425}
426
427fn copyWithPartialInline(s: []u32, b: []u8) void {
428 comptime var i: usize = 0;
429 inline while (i < 4) : (i += 1) {
430 s[i] = 0;
431 s[i] |= u32(b[i * 4 + 0]) << 24;
432 s[i] |= u32(b[i * 4 + 1]) << 16;
433 s[i] |= u32(b[i * 4 + 2]) << 8;
434 s[i] |= u32(b[i * 4 + 3]) << 0;
435 }
436}
437
438test "binary math operator in partially inlined function" {
439 var s: [4]u32 = undefined;
440 var b: [16]u8 = undefined;
441
442 for (b) |*r, i|
443 r.* = @intCast(u8, i + 1);
444
445 copyWithPartialInline(s[0..], b[0..]);
446 assert(s[0] == 0x1020304);
447 assert(s[1] == 0x5060708);
448 assert(s[2] == 0x90a0b0c);
449 assert(s[3] == 0xd0e0f10);
450}
451
452test "comptime function with the same args is memoized" {
453 comptime {
454 assert(MakeType(i32) == MakeType(i32));
455 assert(MakeType(i32) != MakeType(f64));
456 }
457}
458
459fn MakeType(comptime T: type) type {
460 return struct {
461 field: T,
462 };
463}
464
465test "comptime function with mutable pointer is not memoized" {
466 comptime {
467 var x: i32 = 1;
468 const ptr = &x;
469 increment(ptr);
470 increment(ptr);
471 assert(x == 3);
472 }
473}
474
475fn increment(value: *i32) void {
476 value.* += 1;
477}
478
479fn generateTable(comptime T: type) [1010]T {
480 var res: [1010]T = undefined;
481 var i: usize = 0;
482 while (i < 1010) : (i += 1) {
483 res[i] = @intCast(T, i);
484 }
485 return res;
486}
487
488fn doesAlotT(comptime T: type, value: usize) T {
489 @setEvalBranchQuota(5000);
490 const table = comptime blk: {
491 break :blk generateTable(T);
492 };
493 return table[value];
494}
495
496test "@setEvalBranchQuota at same scope as generic function call" {
497 assert(doesAlotT(u32, 2) == 2);
498}
499
500test "comptime slice of slice preserves comptime var" {
501 comptime {
502 var buff: [10]u8 = undefined;
503 buff[0..][0..][0] = 1;
504 assert(buff[0..][0..][0] == 1);
505 }
506}
507
508test "comptime slice of pointer preserves comptime var" {
509 comptime {
510 var buff: [10]u8 = undefined;
511 var a = buff[0..].ptr;
512 a[0..1][0] = 1;
513 assert(buff[0..][0..][0] == 1);
514 }
515}
516
517const SingleFieldStruct = struct {
518 x: i32,
519
520 fn read_x(self: *const SingleFieldStruct) i32 {
521 return self.x;
522 }
523};
524test "const ptr to comptime mutable data is not memoized" {
525 comptime {
526 var foo = SingleFieldStruct{ .x = 1 };
527 assert(foo.read_x() == 1);
528 foo.x = 2;
529 assert(foo.read_x() == 2);
530 }
531}
532
533test "array concat of slices gives slice" {
534 comptime {
535 var a: []const u8 = "aoeu";
536 var b: []const u8 = "asdf";
537 const c = a ++ b;
538 assert(std.mem.eql(u8, c, "aoeuasdf"));
539 }
540}
541
542test "comptime shlWithOverflow" {
543 const ct_shifted: u64 = comptime amt: {
544 var amt = u64(0);
545 _ = @shlWithOverflow(u64, ~u64(0), 16, &amt);
546 break :amt amt;
547 };
548
549 const rt_shifted: u64 = amt: {
550 var amt = u64(0);
551 _ = @shlWithOverflow(u64, ~u64(0), 16, &amt);
552 break :amt amt;
553 };
554
555 assert(ct_shifted == rt_shifted);
556}
557
558test "runtime 128 bit integer division" {
559 var a: u128 = 152313999999999991610955792383;
560 var b: u128 = 10000000000000000000;
561 var c = a / b;
562 assert(c == 15231399999);
563}
564
565pub const Info = struct {
566 version: u8,
567};
568
569pub const diamond_info = Info{ .version = 0 };
570
571test "comptime modification of const struct field" {
572 comptime {
573 var res = diamond_info;
574 res.version = 1;
575 assert(diamond_info.version == 0);
576 assert(res.version == 1);
577 }
578}
579
580test "pointer to type" {
581 comptime {
582 var T: type = i32;
583 assert(T == i32);
584 var ptr = &T;
585 assert(@typeOf(ptr) == *type);
586 ptr.* = f32;
587 assert(T == f32);
588 assert(*T == *f32);
589 }
590}
591
592test "slice of type" {
593 comptime {
594 var types_array = []type{ i32, f64, type };
595 for (types_array) |T, i| {
596 switch (i) {
597 0 => assert(T == i32),
598 1 => assert(T == f64),
599 2 => assert(T == type),
600 else => unreachable,
601 }
602 }
603 for (types_array[0..]) |T, i| {
604 switch (i) {
605 0 => assert(T == i32),
606 1 => assert(T == f64),
607 2 => assert(T == type),
608 else => unreachable,
609 }
610 }
611 }
612}
613
614const Wrapper = struct {
615 T: type,
616};
617
618fn wrap(comptime T: type) Wrapper {
619 return Wrapper{ .T = T };
620}
621
622test "function which returns struct with type field causes implicit comptime" {
623 const ty = wrap(i32).T;
624 assert(ty == i32);
625}
626
627test "call method with comptime pass-by-non-copying-value self parameter" {
628 const S = struct {
629 a: u8,
630
631 fn b(comptime s: @This()) u8 {
632 return s.a;
633 }
634 };
635
636 const s = S{ .a = 2 };
637 var b = s.b();
638 assert(b == 2);
639}
640
641test "@tagName of @typeId" {
642 const str = @tagName(@typeId(u8));
643 assert(std.mem.eql(u8, str, "Int"));
644}
645
646test "setting backward branch quota just before a generic fn call" {
647 @setEvalBranchQuota(1001);
648 loopNTimes(1001);
649}
650
651fn loopNTimes(comptime n: usize) void {
652 comptime var i = 0;
653 inline while (i < n) : (i += 1) {}
654}
655
656test "variable inside inline loop that has different types on different iterations" {
657 testVarInsideInlineLoop(true, u32(42));
658}
659
660fn testVarInsideInlineLoop(args: ...) void {
661 comptime var i = 0;
662 inline while (i < args.len) : (i += 1) {
663 const x = args[i];
664 if (i == 0) assert(x);
665 if (i == 1) assert(x == 42);
666 }
667}
668
669test "inline for with same type but different values" {
670 var res: usize = 0;
671 inline for ([]type{ [2]u8, [1]u8, [2]u8 }) |T| {
672 var a: T = undefined;
673 res += a.len;
674 }
675 assert(res == 5);
676}
677
678test "refer to the type of a generic function" {
679 const Func = fn (type) void;
680 const f: Func = doNothingWithType;
681 f(i32);
682}
683
684fn doNothingWithType(comptime T: type) void {}
685
686test "zero extend from u0 to u1" {
687 var zero_u0: u0 = 0;
688 var zero_u1: u1 = zero_u0;
689 assert(zero_u1 == 0);
690}
691
692test "bit shift a u1" {
693 var x: u1 = 1;
694 var y = x << 0;
695 assert(y == 1);
696}
697
698test "@intCast to a u0" {
699 var x: u8 = 0;
700 var y: u0 = @intCast(u0, x);
701 assert(y == 0);
702}
703
704test "@bytesToslice on a packed struct" {
705 const F = packed struct {
706 a: u8,
707 };
708
709 var b = [1]u8{9};
710 var f = @bytesToSlice(F, b);
711 assert(f[0].a == 9);
712}
713
714test "comptime pointer cast array and then slice" {
715 const array = []u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
716
717 const ptrA: [*]const u8 = @ptrCast([*]const u8, &array);
718 const sliceA: []const u8 = ptrA[0..2];
719
720 const ptrB: [*]const u8 = &array;
721 const sliceB: []const u8 = ptrB[0..2];
722
723 assert(sliceA[1] == 2);
724 assert(sliceB[1] == 2);
725}
726
727test "slice bounds in comptime concatenation" {
728 const bs = comptime blk: {
729 const b = c"11";
730 break :blk b[0..1];
731 };
732 const str = "" ++ bs;
733 assert(str.len == 1);
734 assert(std.mem.eql(u8, str, "1"));
735
736 const str2 = bs ++ "";
737 assert(str2.len == 1);
738 assert(std.mem.eql(u8, str2, "1"));
739}
740
741test "comptime bitwise operators" {
742 comptime {
743 assert(3 & 1 == 1);
744 assert(3 & -1 == 3);
745 assert(-3 & -1 == -3);
746 assert(3 | -1 == -1);
747 assert(-3 | -1 == -1);
748 assert(3 ^ -1 == -4);
749 assert(-3 ^ -1 == 2);
750 assert(~i8(-1) == 0);
751 assert(~i128(-1) == 0);
752 assert(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
753 assert(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
754 assert(~u128(0) == 0xffffffffffffffffffffffffffffffff);
755 }
756}
757
758test "*align(1) u16 is the same as *align(1:0:2) u16" {
759 comptime {
760 assert(*align(1:0:2) u16 == *align(1) u16);
761 // TODO add parsing support for this syntax
762 //assert(*align(:0:2) u16 == *u16);
763 }
764}
765
766test "array concatenation forces comptime" {
767 var a = oneItem(3) ++ oneItem(4);
768 assert(std.mem.eql(i32, a, []i32{3, 4}));
769}
770
771test "array multiplication forces comptime" {
772 var a = oneItem(3) ** scalar(2);
773 assert(std.mem.eql(i32, a, []i32{3, 3}));
774}
775
776fn oneItem(x: i32) [1]i32 {
777 return []i32{x};
778}
779
780fn scalar(x: u32) u32 {
781 return x;
782}
test/cases/field_parent_ptr.zig deleted-41
...@@ -1,41 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "@fieldParentPtr non-first field" {
4 testParentFieldPtr(&foo.c);
5 comptime testParentFieldPtr(&foo.c);
6}
7
8test "@fieldParentPtr first field" {
9 testParentFieldPtrFirst(&foo.a);
10 comptime testParentFieldPtrFirst(&foo.a);
11}
12
13const Foo = struct {
14 a: bool,
15 b: f32,
16 c: i32,
17 d: i32,
18};
19
20const foo = Foo{
21 .a = true,
22 .b = 0.123,
23 .c = 1234,
24 .d = -10,
25};
26
27fn testParentFieldPtr(c: *const i32) void {
28 assert(c == &foo.c);
29
30 const base = @fieldParentPtr(Foo, "c", c);
31 assert(base == &foo);
32 assert(&base.c == c);
33}
34
35fn testParentFieldPtrFirst(a: *const bool) void {
36 assert(a == &foo.a);
37
38 const base = @fieldParentPtr(Foo, "a", a);
39 assert(base == &foo);
40 assert(&base.a == a);
41}
test/cases/fn.zig deleted-207
...@@ -1,207 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "params" {
4 assert(testParamsAdd(22, 11) == 33);
5}
6fn testParamsAdd(a: i32, b: i32) i32 {
7 return a + b;
8}
9
10test "local variables" {
11 testLocVars(2);
12}
13fn testLocVars(b: i32) void {
14 const a: i32 = 1;
15 if (a + b != 3) unreachable;
16}
17
18test "void parameters" {
19 voidFun(1, void{}, 2, {});
20}
21fn voidFun(a: i32, b: void, c: i32, d: void) void {
22 const v = b;
23 const vv: void = if (a == 1) v else {};
24 assert(a + c == 3);
25 return vv;
26}
27
28test "mutable local variables" {
29 var zero: i32 = 0;
30 assert(zero == 0);
31
32 var i = i32(0);
33 while (i != 3) {
34 i += 1;
35 }
36 assert(i == 3);
37}
38
39test "separate block scopes" {
40 {
41 const no_conflict: i32 = 5;
42 assert(no_conflict == 5);
43 }
44
45 const c = x: {
46 const no_conflict = i32(10);
47 break :x no_conflict;
48 };
49 assert(c == 10);
50}
51
52test "call function with empty string" {
53 acceptsString("");
54}
55
56fn acceptsString(foo: []u8) void {}
57
58fn @"weird function name"() i32 {
59 return 1234;
60}
61test "weird function name" {
62 assert(@"weird function name"() == 1234);
63}
64
65test "implicit cast function unreachable return" {
66 wantsFnWithVoid(fnWithUnreachable);
67}
68
69fn wantsFnWithVoid(f: fn () void) void {}
70
71fn fnWithUnreachable() noreturn {
72 unreachable;
73}
74
75test "function pointers" {
76 const fns = []@typeOf(fn1){
77 fn1,
78 fn2,
79 fn3,
80 fn4,
81 };
82 for (fns) |f, i| {
83 assert(f() == @intCast(u32, i) + 5);
84 }
85}
86fn fn1() u32 {
87 return 5;
88}
89fn fn2() u32 {
90 return 6;
91}
92fn fn3() u32 {
93 return 7;
94}
95fn fn4() u32 {
96 return 8;
97}
98
99test "inline function call" {
100 assert(@inlineCall(add, 3, 9) == 12);
101}
102
103fn add(a: i32, b: i32) i32 {
104 return a + b;
105}
106
107test "number literal as an argument" {
108 numberLiteralArg(3);
109 comptime numberLiteralArg(3);
110}
111
112fn numberLiteralArg(a: var) void {
113 assert(a == 3);
114}
115
116test "assign inline fn to const variable" {
117 const a = inlineFn;
118 a();
119}
120
121inline fn inlineFn() void {}
122
123test "pass by non-copying value" {
124 assert(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
125}
126
127const Point = struct {
128 x: i32,
129 y: i32,
130};
131
132fn addPointCoords(pt: Point) i32 {
133 return pt.x + pt.y;
134}
135
136test "pass by non-copying value through var arg" {
137 assert(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3);
138}
139
140fn addPointCoordsVar(pt: var) i32 {
141 comptime assert(@typeOf(pt) == Point);
142 return pt.x + pt.y;
143}
144
145test "pass by non-copying value as method" {
146 var pt = Point2{ .x = 1, .y = 2 };
147 assert(pt.addPointCoords() == 3);
148}
149
150const Point2 = struct {
151 x: i32,
152 y: i32,
153
154 fn addPointCoords(self: Point2) i32 {
155 return self.x + self.y;
156 }
157};
158
159test "pass by non-copying value as method, which is generic" {
160 var pt = Point3{ .x = 1, .y = 2 };
161 assert(pt.addPointCoords(i32) == 3);
162}
163
164const Point3 = struct {
165 x: i32,
166 y: i32,
167
168 fn addPointCoords(self: Point3, comptime T: type) i32 {
169 return self.x + self.y;
170 }
171};
172
173test "pass by non-copying value as method, at comptime" {
174 comptime {
175 var pt = Point2{ .x = 1, .y = 2 };
176 assert(pt.addPointCoords() == 3);
177 }
178}
179
180fn outer(y: u32) fn (u32) u32 {
181 const Y = @typeOf(y);
182 const st = struct {
183 fn get(z: u32) u32 {
184 return z + @sizeOf(Y);
185 }
186 };
187 return st.get;
188}
189
190test "return inner function which references comptime variable of outer function" {
191 var func = outer(10);
192 assert(func(3) == 7);
193}
194
195test "extern struct with stdcallcc fn pointer" {
196 const S = extern struct {
197 ptr: stdcallcc fn () i32,
198
199 stdcallcc fn foo() i32 {
200 return 1234;
201 }
202 };
203
204 var s: S = undefined;
205 s.ptr = S.foo;
206 assert(s.ptr() == 1234);
207}
test/cases/fn_in_struct_in_comptime.zig deleted-17
...@@ -1,17 +0,0 @@
1const assert = @import("std").debug.assert;
2
3fn get_foo() fn (*u8) usize {
4 comptime {
5 return struct {
6 fn func(ptr: *u8) usize {
7 var u = @ptrToInt(ptr);
8 return u;
9 }
10 }.func;
11 }
12}
13
14test "define a function in an anonymous struct in comptime" {
15 const foo = get_foo();
16 assert(foo(@intToPtr(*u8, 12345)) == 12345);
17}
test/cases/for.zig deleted-106
...@@ -1,106 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const mem = std.mem;
4
5test "continue in for loop" {
6 const array = []i32{
7 1,
8 2,
9 3,
10 4,
11 5,
12 };
13 var sum: i32 = 0;
14 for (array) |x| {
15 sum += x;
16 if (x < 3) {
17 continue;
18 }
19 break;
20 }
21 if (sum != 6) unreachable;
22}
23
24test "for loop with pointer elem var" {
25 const source = "abcdefg";
26 var target: [source.len]u8 = undefined;
27 mem.copy(u8, target[0..], source);
28 mangleString(target[0..]);
29 assert(mem.eql(u8, target, "bcdefgh"));
30}
31fn mangleString(s: []u8) void {
32 for (s) |*c| {
33 c.* += 1;
34 }
35}
36
37test "basic for loop" {
38 const expected_result = []u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3;
39
40 var buffer: [expected_result.len]u8 = undefined;
41 var buf_index: usize = 0;
42
43 const array = []u8{ 9, 8, 7, 6 };
44 for (array) |item| {
45 buffer[buf_index] = item;
46 buf_index += 1;
47 }
48 for (array) |item, index| {
49 buffer[buf_index] = @intCast(u8, index);
50 buf_index += 1;
51 }
52 const array_ptr = &array;
53 for (array_ptr) |item| {
54 buffer[buf_index] = item;
55 buf_index += 1;
56 }
57 for (array_ptr) |item, index| {
58 buffer[buf_index] = @intCast(u8, index);
59 buf_index += 1;
60 }
61 const unknown_size: []const u8 = array;
62 for (unknown_size) |item| {
63 buffer[buf_index] = item;
64 buf_index += 1;
65 }
66 for (unknown_size) |item, index| {
67 buffer[buf_index] = @intCast(u8, index);
68 buf_index += 1;
69 }
70
71 assert(mem.eql(u8, buffer[0..buf_index], expected_result));
72}
73
74test "break from outer for loop" {
75 testBreakOuter();
76 comptime testBreakOuter();
77}
78
79fn testBreakOuter() void {
80 var array = "aoeu";
81 var count: usize = 0;
82 outer: for (array) |_| {
83 for (array) |_| {
84 count += 1;
85 break :outer;
86 }
87 }
88 assert(count == 1);
89}
90
91test "continue outer for loop" {
92 testContinueOuter();
93 comptime testContinueOuter();
94}
95
96fn testContinueOuter() void {
97 var array = "aoeu";
98 var counter: usize = 0;
99 outer: for (array) |_| {
100 for (array) |_| {
101 counter += 1;
102 continue :outer;
103 }
104 }
105 assert(counter == array.len);
106}
test/cases/generics.zig deleted-151
...@@ -1,151 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "simple generic fn" {
4 assert(max(i32, 3, -1) == 3);
5 assert(max(f32, 0.123, 0.456) == 0.456);
6 assert(add(2, 3) == 5);
7}
8
9fn max(comptime T: type, a: T, b: T) T {
10 return if (a > b) a else b;
11}
12
13fn add(comptime a: i32, b: i32) i32 {
14 return (comptime a) + b;
15}
16
17const the_max = max(u32, 1234, 5678);
18test "compile time generic eval" {
19 assert(the_max == 5678);
20}
21
22fn gimmeTheBigOne(a: u32, b: u32) u32 {
23 return max(u32, a, b);
24}
25
26fn shouldCallSameInstance(a: u32, b: u32) u32 {
27 return max(u32, a, b);
28}
29
30fn sameButWithFloats(a: f64, b: f64) f64 {
31 return max(f64, a, b);
32}
33
34test "fn with comptime args" {
35 assert(gimmeTheBigOne(1234, 5678) == 5678);
36 assert(shouldCallSameInstance(34, 12) == 34);
37 assert(sameButWithFloats(0.43, 0.49) == 0.49);
38}
39
40test "var params" {
41 assert(max_i32(12, 34) == 34);
42 assert(max_f64(1.2, 3.4) == 3.4);
43}
44
45comptime {
46 assert(max_i32(12, 34) == 34);
47 assert(max_f64(1.2, 3.4) == 3.4);
48}
49
50fn max_var(a: var, b: var) @typeOf(a + b) {
51 return if (a > b) a else b;
52}
53
54fn max_i32(a: i32, b: i32) i32 {
55 return max_var(a, b);
56}
57
58fn max_f64(a: f64, b: f64) f64 {
59 return max_var(a, b);
60}
61
62pub fn List(comptime T: type) type {
63 return SmallList(T, 8);
64}
65
66pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type {
67 return struct {
68 items: []T,
69 length: usize,
70 prealloc_items: [STATIC_SIZE]T,
71 };
72}
73
74test "function with return type type" {
75 var list: List(i32) = undefined;
76 var list2: List(i32) = undefined;
77 list.length = 10;
78 list2.length = 10;
79 assert(list.prealloc_items.len == 8);
80 assert(list2.prealloc_items.len == 8);
81}
82
83test "generic struct" {
84 var a1 = GenNode(i32){
85 .value = 13,
86 .next = null,
87 };
88 var b1 = GenNode(bool){
89 .value = true,
90 .next = null,
91 };
92 assert(a1.value == 13);
93 assert(a1.value == a1.getVal());
94 assert(b1.getVal());
95}
96fn GenNode(comptime T: type) type {
97 return struct {
98 value: T,
99 next: ?*GenNode(T),
100 fn getVal(n: *const GenNode(T)) T {
101 return n.value;
102 }
103 };
104}
105
106test "const decls in struct" {
107 assert(GenericDataThing(3).count_plus_one == 4);
108}
109fn GenericDataThing(comptime count: isize) type {
110 return struct {
111 const count_plus_one = count + 1;
112 };
113}
114
115test "use generic param in generic param" {
116 assert(aGenericFn(i32, 3, 4) == 7);
117}
118fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
119 return a + b;
120}
121
122test "generic fn with implicit cast" {
123 assert(getFirstByte(u8, []u8{13}) == 13);
124 assert(getFirstByte(u16, []u16{
125 0,
126 13,
127 }) == 0);
128}
129fn getByte(ptr: ?*const u8) u8 {
130 return ptr.?.*;
131}
132fn getFirstByte(comptime T: type, mem: []const T) u8 {
133 return getByte(@ptrCast(*const u8, &mem[0]));
134}
135
136const foos = []fn (var) bool{
137 foo1,
138 foo2,
139};
140
141fn foo1(arg: var) bool {
142 return arg;
143}
144fn foo2(arg: var) bool {
145 return !arg;
146}
147
148test "array of generic fns" {
149 assert(foos[0](true));
150 assert(!foos[1](true));
151}
test/cases/if.zig deleted-37
...@@ -1,37 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "if statements" {
4 shouldBeEqual(1, 1);
5 firstEqlThird(2, 1, 2);
6}
7fn shouldBeEqual(a: i32, b: i32) void {
8 if (a != b) {
9 unreachable;
10 } else {
11 return;
12 }
13}
14fn firstEqlThird(a: i32, b: i32, c: i32) void {
15 if (a == b) {
16 unreachable;
17 } else if (b == c) {
18 unreachable;
19 } else if (a == c) {
20 return;
21 } else {
22 unreachable;
23 }
24}
25
26test "else if expression" {
27 assert(elseIfExpressionF(1) == 1);
28}
29fn elseIfExpressionF(c: u8) u8 {
30 if (c == 0) {
31 return 0;
32 } else if (c == 1) {
33 return 1;
34 } else {
35 return u8(2);
36 }
37}
test/cases/import.zig deleted-10
...@@ -1,10 +0,0 @@
1const assert = @import("std").debug.assert;
2const a_namespace = @import("import/a_namespace.zig");
3
4test "call fn via namespace lookup" {
5 assert(a_namespace.foo() == 1234);
6}
7
8test "importing the same thing gives the same import" {
9 assert(@import("std") == @import("std"));
10}
test/cases/import/a_namespace.zig deleted-3
...@@ -1,3 +0,0 @@
1pub fn foo() i32 {
2 return 1234;
3}
test/cases/incomplete_struct_param_tld.zig deleted-30
...@@ -1,30 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const A = struct {
4 b: B,
5};
6
7const B = struct {
8 c: C,
9};
10
11const C = struct {
12 x: i32,
13
14 fn d(c: *const C) i32 {
15 return c.x;
16 }
17};
18
19fn foo(a: A) i32 {
20 return a.b.c.d();
21}
22
23test "incomplete struct param top level declaration" {
24 const a = A{
25 .b = B{
26 .c = C{ .x = 13 },
27 },
28 };
29 assert(foo(a) == 13);
30}
test/cases/ir_block_deps.zig deleted-21
...@@ -1,21 +0,0 @@
1const assert = @import("std").debug.assert;
2
3fn foo(id: u64) !i32 {
4 return switch (id) {
5 1 => getErrInt(),
6 2 => {
7 const size = try getErrInt();
8 return try getErrInt();
9 },
10 else => error.ItBroke,
11 };
12}
13
14fn getErrInt() anyerror!i32 {
15 return 0;
16}
17
18test "ir block deps" {
19 assert((foo(1) catch unreachable) == 0);
20 assert((foo(2) catch unreachable) == 0);
21}
test/cases/math.zig deleted-500
...@@ -1,500 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const maxInt = std.math.maxInt;
4const minInt = std.math.minInt;
5
6test "division" {
7 testDivision();
8 comptime testDivision();
9}
10fn testDivision() void {
11 assert(div(u32, 13, 3) == 4);
12 assert(div(f16, 1.0, 2.0) == 0.5);
13 assert(div(f32, 1.0, 2.0) == 0.5);
14
15 assert(divExact(u32, 55, 11) == 5);
16 assert(divExact(i32, -55, 11) == -5);
17 assert(divExact(f16, 55.0, 11.0) == 5.0);
18 assert(divExact(f16, -55.0, 11.0) == -5.0);
19 assert(divExact(f32, 55.0, 11.0) == 5.0);
20 assert(divExact(f32, -55.0, 11.0) == -5.0);
21
22 assert(divFloor(i32, 5, 3) == 1);
23 assert(divFloor(i32, -5, 3) == -2);
24 assert(divFloor(f16, 5.0, 3.0) == 1.0);
25 assert(divFloor(f16, -5.0, 3.0) == -2.0);
26 assert(divFloor(f32, 5.0, 3.0) == 1.0);
27 assert(divFloor(f32, -5.0, 3.0) == -2.0);
28 assert(divFloor(i32, -0x80000000, -2) == 0x40000000);
29 assert(divFloor(i32, 0, -0x80000000) == 0);
30 assert(divFloor(i32, -0x40000001, 0x40000000) == -2);
31 assert(divFloor(i32, -0x80000000, 1) == -0x80000000);
32
33 assert(divTrunc(i32, 5, 3) == 1);
34 assert(divTrunc(i32, -5, 3) == -1);
35 assert(divTrunc(f16, 5.0, 3.0) == 1.0);
36 assert(divTrunc(f16, -5.0, 3.0) == -1.0);
37 assert(divTrunc(f32, 5.0, 3.0) == 1.0);
38 assert(divTrunc(f32, -5.0, 3.0) == -1.0);
39 assert(divTrunc(f64, 5.0, 3.0) == 1.0);
40 assert(divTrunc(f64, -5.0, 3.0) == -1.0);
41
42 comptime {
43 assert(
44 1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600,
45 );
46 assert(
47 @rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600,
48 );
49 assert(
50 1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2,
51 );
52 assert(
53 @divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2,
54 );
55 assert(
56 @divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2,
57 );
58 assert(
59 @divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2,
60 );
61 assert(
62 4126227191251978491697987544882340798050766755606969681711 % 10 == 1,
63 );
64 }
65}
66fn div(comptime T: type, a: T, b: T) T {
67 return a / b;
68}
69fn divExact(comptime T: type, a: T, b: T) T {
70 return @divExact(a, b);
71}
72fn divFloor(comptime T: type, a: T, b: T) T {
73 return @divFloor(a, b);
74}
75fn divTrunc(comptime T: type, a: T, b: T) T {
76 return @divTrunc(a, b);
77}
78
79test "@addWithOverflow" {
80 var result: u8 = undefined;
81 assert(@addWithOverflow(u8, 250, 100, &result));
82 assert(!@addWithOverflow(u8, 100, 150, &result));
83 assert(result == 250);
84}
85
86// TODO test mulWithOverflow
87// TODO test subWithOverflow
88
89test "@shlWithOverflow" {
90 var result: u16 = undefined;
91 assert(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));
92 assert(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result));
93 assert(result == 0b1011111111111100);
94}
95
96test "@clz" {
97 testClz();
98 comptime testClz();
99}
100
101fn testClz() void {
102 assert(clz(u8(0b00001010)) == 4);
103 assert(clz(u8(0b10001010)) == 0);
104 assert(clz(u8(0b00000000)) == 8);
105 assert(clz(u128(0xffffffffffffffff)) == 64);
106 assert(clz(u128(0x10000000000000000)) == 63);
107}
108
109fn clz(x: var) usize {
110 return @clz(x);
111}
112
113test "@ctz" {
114 testCtz();
115 comptime testCtz();
116}
117
118fn testCtz() void {
119 assert(ctz(u8(0b10100000)) == 5);
120 assert(ctz(u8(0b10001010)) == 1);
121 assert(ctz(u8(0b00000000)) == 8);
122}
123
124fn ctz(x: var) usize {
125 return @ctz(x);
126}
127
128test "assignment operators" {
129 var i: u32 = 0;
130 i += 5;
131 assert(i == 5);
132 i -= 2;
133 assert(i == 3);
134 i *= 20;
135 assert(i == 60);
136 i /= 3;
137 assert(i == 20);
138 i %= 11;
139 assert(i == 9);
140 i <<= 1;
141 assert(i == 18);
142 i >>= 2;
143 assert(i == 4);
144 i = 6;
145 i &= 5;
146 assert(i == 4);
147 i ^= 6;
148 assert(i == 2);
149 i = 6;
150 i |= 3;
151 assert(i == 7);
152}
153
154test "three expr in a row" {
155 testThreeExprInARow(false, true);
156 comptime testThreeExprInARow(false, true);
157}
158fn testThreeExprInARow(f: bool, t: bool) void {
159 assertFalse(f or f or f);
160 assertFalse(t and t and f);
161 assertFalse(1 | 2 | 4 != 7);
162 assertFalse(3 ^ 6 ^ 8 != 13);
163 assertFalse(7 & 14 & 28 != 4);
164 assertFalse(9 << 1 << 2 != 9 << 3);
165 assertFalse(90 >> 1 >> 2 != 90 >> 3);
166 assertFalse(100 - 1 + 1000 != 1099);
167 assertFalse(5 * 4 / 2 % 3 != 1);
168 assertFalse(i32(i32(5)) != 5);
169 assertFalse(!!false);
170 assertFalse(i32(7) != --(i32(7)));
171}
172fn assertFalse(b: bool) void {
173 assert(!b);
174}
175
176test "const number literal" {
177 const one = 1;
178 const eleven = ten + one;
179
180 assert(eleven == 11);
181}
182const ten = 10;
183
184test "unsigned wrapping" {
185 testUnsignedWrappingEval(maxInt(u32));
186 comptime testUnsignedWrappingEval(maxInt(u32));
187}
188fn testUnsignedWrappingEval(x: u32) void {
189 const zero = x +% 1;
190 assert(zero == 0);
191 const orig = zero -% 1;
192 assert(orig == maxInt(u32));
193}
194
195test "signed wrapping" {
196 testSignedWrappingEval(maxInt(i32));
197 comptime testSignedWrappingEval(maxInt(i32));
198}
199fn testSignedWrappingEval(x: i32) void {
200 const min_val = x +% 1;
201 assert(min_val == minInt(i32));
202 const max_val = min_val -% 1;
203 assert(max_val == maxInt(i32));
204}
205
206test "negation wrapping" {
207 testNegationWrappingEval(minInt(i16));
208 comptime testNegationWrappingEval(minInt(i16));
209}
210fn testNegationWrappingEval(x: i16) void {
211 assert(x == -32768);
212 const neg = -%x;
213 assert(neg == -32768);
214}
215
216test "unsigned 64-bit division" {
217 test_u64_div();
218 comptime test_u64_div();
219}
220fn test_u64_div() void {
221 const result = divWithResult(1152921504606846976, 34359738365);
222 assert(result.quotient == 33554432);
223 assert(result.remainder == 100663296);
224}
225fn divWithResult(a: u64, b: u64) DivResult {
226 return DivResult{
227 .quotient = a / b,
228 .remainder = a % b,
229 };
230}
231const DivResult = struct {
232 quotient: u64,
233 remainder: u64,
234};
235
236test "binary not" {
237 assert(comptime x: {
238 break :x ~u16(0b1010101010101010) == 0b0101010101010101;
239 });
240 assert(comptime x: {
241 break :x ~u64(2147483647) == 18446744071562067968;
242 });
243 testBinaryNot(0b1010101010101010);
244}
245
246fn testBinaryNot(x: u16) void {
247 assert(~x == 0b0101010101010101);
248}
249
250test "small int addition" {
251 var x: @IntType(false, 2) = 0;
252 assert(x == 0);
253
254 x += 1;
255 assert(x == 1);
256
257 x += 1;
258 assert(x == 2);
259
260 x += 1;
261 assert(x == 3);
262
263 var result: @typeOf(x) = 3;
264 assert(@addWithOverflow(@typeOf(x), x, 1, &result));
265
266 assert(result == 0);
267}
268
269test "float equality" {
270 const x: f64 = 0.012;
271 const y: f64 = x + 1.0;
272
273 testFloatEqualityImpl(x, y);
274 comptime testFloatEqualityImpl(x, y);
275}
276
277fn testFloatEqualityImpl(x: f64, y: f64) void {
278 const y2 = x + 1.0;
279 assert(y == y2);
280}
281
282test "allow signed integer division/remainder when values are comptime known and positive or exact" {
283 assert(5 / 3 == 1);
284 assert(-5 / -3 == 1);
285 assert(-6 / 3 == -2);
286
287 assert(5 % 3 == 2);
288 assert(-6 % 3 == 0);
289}
290
291test "hex float literal parsing" {
292 comptime assert(0x1.0 == 1.0);
293}
294
295test "quad hex float literal parsing in range" {
296 const a = 0x1.af23456789bbaaab347645365cdep+5;
297 const b = 0x1.dedafcff354b6ae9758763545432p-9;
298 const c = 0x1.2f34dd5f437e849b4baab754cdefp+4534;
299 const d = 0x1.edcbff8ad76ab5bf46463233214fp-435;
300}
301
302test "quad hex float literal parsing accurate" {
303 const a: f128 = 0x1.1111222233334444555566667777p+0;
304
305 // implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing.
306 const expected: u128 = 0x3fff1111222233334444555566667777;
307 assert(@bitCast(u128, a) == expected);
308}
309
310test "hex float literal within range" {
311 const a = 0x1.0p16383;
312 const b = 0x0.1p16387;
313 const c = 0x1.0p-16382;
314}
315
316test "truncating shift left" {
317 testShlTrunc(maxInt(u16));
318 comptime testShlTrunc(maxInt(u16));
319}
320fn testShlTrunc(x: u16) void {
321 const shifted = x << 1;
322 assert(shifted == 65534);
323}
324
325test "truncating shift right" {
326 testShrTrunc(maxInt(u16));
327 comptime testShrTrunc(maxInt(u16));
328}
329fn testShrTrunc(x: u16) void {
330 const shifted = x >> 1;
331 assert(shifted == 32767);
332}
333
334test "exact shift left" {
335 testShlExact(0b00110101);
336 comptime testShlExact(0b00110101);
337}
338fn testShlExact(x: u8) void {
339 const shifted = @shlExact(x, 2);
340 assert(shifted == 0b11010100);
341}
342
343test "exact shift right" {
344 testShrExact(0b10110100);
345 comptime testShrExact(0b10110100);
346}
347fn testShrExact(x: u8) void {
348 const shifted = @shrExact(x, 2);
349 assert(shifted == 0b00101101);
350}
351
352test "comptime_int addition" {
353 comptime {
354 assert(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
355 assert(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
356 }
357}
358
359test "comptime_int multiplication" {
360 comptime {
361 assert(
362 45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567,
363 );
364 assert(
365 594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016,
366 );
367 }
368}
369
370test "comptime_int shifting" {
371 comptime {
372 assert((u128(1) << 127) == 0x80000000000000000000000000000000);
373 }
374}
375
376test "comptime_int multi-limb shift and mask" {
377 comptime {
378 var a = 0xefffffffa0000001eeeeeeefaaaaaaab;
379
380 assert(u32(a & 0xffffffff) == 0xaaaaaaab);
381 a >>= 32;
382 assert(u32(a & 0xffffffff) == 0xeeeeeeef);
383 a >>= 32;
384 assert(u32(a & 0xffffffff) == 0xa0000001);
385 a >>= 32;
386 assert(u32(a & 0xffffffff) == 0xefffffff);
387 a >>= 32;
388
389 assert(a == 0);
390 }
391}
392
393test "comptime_int multi-limb partial shift right" {
394 comptime {
395 var a = 0x1ffffffffeeeeeeee;
396 a >>= 16;
397 assert(a == 0x1ffffffffeeee);
398 }
399}
400
401test "xor" {
402 test_xor();
403 comptime test_xor();
404}
405
406fn test_xor() void {
407 assert(0xFF ^ 0x00 == 0xFF);
408 assert(0xF0 ^ 0x0F == 0xFF);
409 assert(0xFF ^ 0xF0 == 0x0F);
410 assert(0xFF ^ 0x0F == 0xF0);
411 assert(0xFF ^ 0xFF == 0x00);
412}
413
414test "comptime_int xor" {
415 comptime {
416 assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
417 assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
418 assert(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF);
419 assert(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000);
420 assert(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000);
421 assert(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
422 assert(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF);
423 assert(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000);
424 }
425}
426
427test "f128" {
428 test_f128();
429 comptime test_f128();
430}
431
432fn make_f128(x: f128) f128 {
433 return x;
434}
435
436fn test_f128() void {
437 assert(@sizeOf(f128) == 16);
438 assert(make_f128(1.0) == 1.0);
439 assert(make_f128(1.0) != 1.1);
440 assert(make_f128(1.0) > 0.9);
441 assert(make_f128(1.0) >= 0.9);
442 assert(make_f128(1.0) >= 1.0);
443 should_not_be_zero(1.0);
444}
445
446fn should_not_be_zero(x: f128) void {
447 assert(x != 0.0);
448}
449
450test "comptime float rem int" {
451 comptime {
452 var x = f32(1) % 2;
453 assert(x == 1.0);
454 }
455}
456
457test "remainder division" {
458 comptime remdiv(f16);
459 comptime remdiv(f32);
460 comptime remdiv(f64);
461 comptime remdiv(f128);
462 remdiv(f16);
463 remdiv(f64);
464 remdiv(f128);
465}
466
467fn remdiv(comptime T: type) void {
468 assert(T(1) == T(1) % T(2));
469 assert(T(1) == T(7) % T(3));
470}
471
472test "@sqrt" {
473 testSqrt(f64, 12.0);
474 comptime testSqrt(f64, 12.0);
475 testSqrt(f32, 13.0);
476 comptime testSqrt(f32, 13.0);
477 testSqrt(f16, 13.0);
478 comptime testSqrt(f16, 13.0);
479
480 const x = 14.0;
481 const y = x * x;
482 const z = @sqrt(@typeOf(y), y);
483 comptime assert(z == x);
484}
485
486fn testSqrt(comptime T: type, x: T) void {
487 assert(@sqrt(T, x * x) == x);
488}
489
490test "comptime_int param and return" {
491 const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702);
492 assert(a == 137114567242441932203689521744947848950);
493
494 const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768);
495 assert(b == 985095453608931032642182098849559179469148836107390954364380);
496}
497
498fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int {
499 return a + b;
500}
test/cases/merge_error_sets.zig deleted-21
...@@ -1,21 +0,0 @@
1const A = error{
2 FileNotFound,
3 NotDir,
4};
5const B = error{OutOfMemory};
6
7const C = A || B;
8
9fn foo() C!void {
10 return error.NotDir;
11}
12
13test "merge error sets" {
14 if (foo()) {
15 @panic("unexpected");
16 } else |err| switch (err) {
17 error.OutOfMemory => @panic("unexpected"),
18 error.FileNotFound => @panic("unexpected"),
19 error.NotDir => {},
20 }
21}
test/cases/misc.zig deleted-681
...@@ -1,681 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const mem = std.mem;
4const cstr = std.cstr;
5const builtin = @import("builtin");
6const maxInt = std.math.maxInt;
7
8// normal comment
9
10/// this is a documentation comment
11/// doc comment line 2
12fn emptyFunctionWithComments() void {}
13
14test "empty function with comments" {
15 emptyFunctionWithComments();
16}
17
18comptime {
19 @export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal);
20}
21
22extern fn disabledExternFn() void {}
23
24test "call disabled extern fn" {
25 disabledExternFn();
26}
27
28test "@IntType builtin" {
29 assert(@IntType(true, 8) == i8);
30 assert(@IntType(true, 16) == i16);
31 assert(@IntType(true, 32) == i32);
32 assert(@IntType(true, 64) == i64);
33
34 assert(@IntType(false, 8) == u8);
35 assert(@IntType(false, 16) == u16);
36 assert(@IntType(false, 32) == u32);
37 assert(@IntType(false, 64) == u64);
38
39 assert(i8.bit_count == 8);
40 assert(i16.bit_count == 16);
41 assert(i32.bit_count == 32);
42 assert(i64.bit_count == 64);
43
44 assert(i8.is_signed);
45 assert(i16.is_signed);
46 assert(i32.is_signed);
47 assert(i64.is_signed);
48 assert(isize.is_signed);
49
50 assert(!u8.is_signed);
51 assert(!u16.is_signed);
52 assert(!u32.is_signed);
53 assert(!u64.is_signed);
54 assert(!usize.is_signed);
55}
56
57test "floating point primitive bit counts" {
58 assert(f16.bit_count == 16);
59 assert(f32.bit_count == 32);
60 assert(f64.bit_count == 64);
61}
62
63test "short circuit" {
64 testShortCircuit(false, true);
65 comptime testShortCircuit(false, true);
66}
67
68fn testShortCircuit(f: bool, t: bool) void {
69 var hit_1 = f;
70 var hit_2 = f;
71 var hit_3 = f;
72 var hit_4 = f;
73
74 if (t or x: {
75 assert(f);
76 break :x f;
77 }) {
78 hit_1 = t;
79 }
80 if (f or x: {
81 hit_2 = t;
82 break :x f;
83 }) {
84 assert(f);
85 }
86
87 if (t and x: {
88 hit_3 = t;
89 break :x f;
90 }) {
91 assert(f);
92 }
93 if (f and x: {
94 assert(f);
95 break :x f;
96 }) {
97 assert(f);
98 } else {
99 hit_4 = t;
100 }
101 assert(hit_1);
102 assert(hit_2);
103 assert(hit_3);
104 assert(hit_4);
105}
106
107test "truncate" {
108 assert(testTruncate(0x10fd) == 0xfd);
109}
110fn testTruncate(x: u32) u8 {
111 return @truncate(u8, x);
112}
113
114fn first4KeysOfHomeRow() []const u8 {
115 return "aoeu";
116}
117
118test "return string from function" {
119 assert(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
120}
121
122const g1: i32 = 1233 + 1;
123var g2: i32 = 0;
124
125test "global variables" {
126 assert(g2 == 0);
127 g2 = g1;
128 assert(g2 == 1234);
129}
130
131test "memcpy and memset intrinsics" {
132 var foo: [20]u8 = undefined;
133 var bar: [20]u8 = undefined;
134
135 @memset(foo[0..].ptr, 'A', foo.len);
136 @memcpy(bar[0..].ptr, foo[0..].ptr, bar.len);
137
138 if (bar[11] != 'A') unreachable;
139}
140
141test "builtin static eval" {
142 const x: i32 = comptime x: {
143 break :x 1 + 2 + 3;
144 };
145 assert(x == comptime 6);
146}
147
148test "slicing" {
149 var array: [20]i32 = undefined;
150
151 array[5] = 1234;
152
153 var slice = array[5..10];
154
155 if (slice.len != 5) unreachable;
156
157 const ptr = &slice[0];
158 if (ptr.* != 1234) unreachable;
159
160 var slice_rest = array[10..];
161 if (slice_rest.len != 10) unreachable;
162}
163
164test "constant equal function pointers" {
165 const alias = emptyFn;
166 assert(comptime x: {
167 break :x emptyFn == alias;
168 });
169}
170
171fn emptyFn() void {}
172
173test "hex escape" {
174 assert(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
175}
176
177test "string concatenation" {
178 assert(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
179}
180
181test "array mult operator" {
182 assert(mem.eql(u8, "ab" ** 5, "ababababab"));
183}
184
185test "string escapes" {
186 assert(mem.eql(u8, "\"", "\x22"));
187 assert(mem.eql(u8, "\'", "\x27"));
188 assert(mem.eql(u8, "\n", "\x0a"));
189 assert(mem.eql(u8, "\r", "\x0d"));
190 assert(mem.eql(u8, "\t", "\x09"));
191 assert(mem.eql(u8, "\\", "\x5c"));
192 assert(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69"));
193}
194
195test "multiline string" {
196 const s1 =
197 \\one
198 \\two)
199 \\three
200 ;
201 const s2 = "one\ntwo)\nthree";
202 assert(mem.eql(u8, s1, s2));
203}
204
205test "multiline C string" {
206 const s1 =
207 c\\one
208 c\\two)
209 c\\three
210 ;
211 const s2 = c"one\ntwo)\nthree";
212 assert(cstr.cmp(s1, s2) == 0);
213}
214
215test "type equality" {
216 assert(*const u8 != *u8);
217}
218
219const global_a: i32 = 1234;
220const global_b: *const i32 = &global_a;
221const global_c: *const f32 = @ptrCast(*const f32, global_b);
222test "compile time global reinterpret" {
223 const d = @ptrCast(*const i32, global_c);
224 assert(d.* == 1234);
225}
226
227test "explicit cast maybe pointers" {
228 const a: ?*i32 = undefined;
229 const b: ?*f32 = @ptrCast(?*f32, a);
230}
231
232test "generic malloc free" {
233 const a = memAlloc(u8, 10) catch unreachable;
234 memFree(u8, a);
235}
236var some_mem: [100]u8 = undefined;
237fn memAlloc(comptime T: type, n: usize) anyerror![]T {
238 return @ptrCast([*]T, &some_mem[0])[0..n];
239}
240fn memFree(comptime T: type, memory: []T) void {}
241
242test "cast undefined" {
243 const array: [100]u8 = undefined;
244 const slice = ([]const u8)(array);
245 testCastUndefined(slice);
246}
247fn testCastUndefined(x: []const u8) void {}
248
249test "cast small unsigned to larger signed" {
250 assert(castSmallUnsignedToLargerSigned1(200) == i16(200));
251 assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999));
252}
253fn castSmallUnsignedToLargerSigned1(x: u8) i16 {
254 return x;
255}
256fn castSmallUnsignedToLargerSigned2(x: u16) i64 {
257 return x;
258}
259
260test "implicit cast after unreachable" {
261 assert(outer() == 1234);
262}
263fn inner() i32 {
264 return 1234;
265}
266fn outer() i64 {
267 return inner();
268}
269
270test "pointer dereferencing" {
271 var x = i32(3);
272 const y = &x;
273
274 y.* += 1;
275
276 assert(x == 4);
277 assert(y.* == 4);
278}
279
280test "call result of if else expression" {
281 assert(mem.eql(u8, f2(true), "a"));
282 assert(mem.eql(u8, f2(false), "b"));
283}
284fn f2(x: bool) []const u8 {
285 return (if (x) fA else fB)();
286}
287fn fA() []const u8 {
288 return "a";
289}
290fn fB() []const u8 {
291 return "b";
292}
293
294test "const expression eval handling of variables" {
295 var x = true;
296 while (x) {
297 x = false;
298 }
299}
300
301test "constant enum initialization with differing sizes" {
302 test3_1(test3_foo);
303 test3_2(test3_bar);
304}
305const Test3Foo = union(enum) {
306 One: void,
307 Two: f32,
308 Three: Test3Point,
309};
310const Test3Point = struct {
311 x: i32,
312 y: i32,
313};
314const test3_foo = Test3Foo{
315 .Three = Test3Point{
316 .x = 3,
317 .y = 4,
318 },
319};
320const test3_bar = Test3Foo{ .Two = 13 };
321fn test3_1(f: Test3Foo) void {
322 switch (f) {
323 Test3Foo.Three => |pt| {
324 assert(pt.x == 3);
325 assert(pt.y == 4);
326 },
327 else => unreachable,
328 }
329}
330fn test3_2(f: Test3Foo) void {
331 switch (f) {
332 Test3Foo.Two => |x| {
333 assert(x == 13);
334 },
335 else => unreachable,
336 }
337}
338
339test "character literals" {
340 assert('\'' == single_quote);
341}
342const single_quote = '\'';
343
344test "take address of parameter" {
345 testTakeAddressOfParameter(12.34);
346}
347fn testTakeAddressOfParameter(f: f32) void {
348 const f_ptr = &f;
349 assert(f_ptr.* == 12.34);
350}
351
352test "pointer comparison" {
353 const a = ([]const u8)("a");
354 const b = &a;
355 assert(ptrEql(b, b));
356}
357fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
358 return a == b;
359}
360
361test "C string concatenation" {
362 const a = c"OK" ++ c" IT " ++ c"WORKED";
363 const b = c"OK IT WORKED";
364
365 const len = cstr.len(b);
366 const len_with_null = len + 1;
367 {
368 var i: u32 = 0;
369 while (i < len_with_null) : (i += 1) {
370 assert(a[i] == b[i]);
371 }
372 }
373 assert(a[len] == 0);
374 assert(b[len] == 0);
375}
376
377test "cast slice to u8 slice" {
378 assert(@sizeOf(i32) == 4);
379 var big_thing_array = []i32{
380 1,
381 2,
382 3,
383 4,
384 };
385 const big_thing_slice: []i32 = big_thing_array[0..];
386 const bytes = @sliceToBytes(big_thing_slice);
387 assert(bytes.len == 4 * 4);
388 bytes[4] = 0;
389 bytes[5] = 0;
390 bytes[6] = 0;
391 bytes[7] = 0;
392 assert(big_thing_slice[1] == 0);
393 const big_thing_again = @bytesToSlice(i32, bytes);
394 assert(big_thing_again[2] == 3);
395 big_thing_again[2] = -1;
396 assert(bytes[8] == maxInt(u8));
397 assert(bytes[9] == maxInt(u8));
398 assert(bytes[10] == maxInt(u8));
399 assert(bytes[11] == maxInt(u8));
400}
401
402test "pointer to void return type" {
403 testPointerToVoidReturnType() catch unreachable;
404}
405fn testPointerToVoidReturnType() anyerror!void {
406 const a = testPointerToVoidReturnType2();
407 return a.*;
408}
409const test_pointer_to_void_return_type_x = void{};
410fn testPointerToVoidReturnType2() *const void {
411 return &test_pointer_to_void_return_type_x;
412}
413
414test "non const ptr to aliased type" {
415 const int = i32;
416 assert(?*int == ?*i32);
417}
418
419test "array 2D const double ptr" {
420 const rect_2d_vertexes = [][1]f32{
421 []f32{1.0},
422 []f32{2.0},
423 };
424 testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
425}
426
427fn testArray2DConstDoublePtr(ptr: *const f32) void {
428 const ptr2 = @ptrCast([*]const f32, ptr);
429 assert(ptr2[0] == 1.0);
430 assert(ptr2[1] == 2.0);
431}
432
433const Tid = builtin.TypeId;
434const AStruct = struct {
435 x: i32,
436};
437const AnEnum = enum {
438 One,
439 Two,
440};
441const AUnionEnum = union(enum) {
442 One: i32,
443 Two: void,
444};
445const AUnion = union {
446 One: void,
447 Two: void,
448};
449
450test "@typeId" {
451 comptime {
452 assert(@typeId(type) == Tid.Type);
453 assert(@typeId(void) == Tid.Void);
454 assert(@typeId(bool) == Tid.Bool);
455 assert(@typeId(noreturn) == Tid.NoReturn);
456 assert(@typeId(i8) == Tid.Int);
457 assert(@typeId(u8) == Tid.Int);
458 assert(@typeId(i64) == Tid.Int);
459 assert(@typeId(u64) == Tid.Int);
460 assert(@typeId(f32) == Tid.Float);
461 assert(@typeId(f64) == Tid.Float);
462 assert(@typeId(*f32) == Tid.Pointer);
463 assert(@typeId([2]u8) == Tid.Array);
464 assert(@typeId(AStruct) == Tid.Struct);
465 assert(@typeId(@typeOf(1)) == Tid.ComptimeInt);
466 assert(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat);
467 assert(@typeId(@typeOf(undefined)) == Tid.Undefined);
468 assert(@typeId(@typeOf(null)) == Tid.Null);
469 assert(@typeId(?i32) == Tid.Optional);
470 assert(@typeId(anyerror!i32) == Tid.ErrorUnion);
471 assert(@typeId(anyerror) == Tid.ErrorSet);
472 assert(@typeId(AnEnum) == Tid.Enum);
473 assert(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum);
474 assert(@typeId(AUnionEnum) == Tid.Union);
475 assert(@typeId(AUnion) == Tid.Union);
476 assert(@typeId(fn () void) == Tid.Fn);
477 assert(@typeId(@typeOf(builtin)) == Tid.Namespace);
478 // TODO bound fn
479 // TODO arg tuple
480 // TODO opaque
481 }
482}
483
484test "@typeName" {
485 const Struct = struct {};
486 const Union = union {
487 unused: u8,
488 };
489 const Enum = enum {
490 Unused,
491 };
492 comptime {
493 assert(mem.eql(u8, @typeName(i64), "i64"));
494 assert(mem.eql(u8, @typeName(*usize), "*usize"));
495 // https://github.com/ziglang/zig/issues/675
496 assert(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)"));
497 assert(mem.eql(u8, @typeName(Struct), "Struct"));
498 assert(mem.eql(u8, @typeName(Union), "Union"));
499 assert(mem.eql(u8, @typeName(Enum), "Enum"));
500 }
501}
502
503fn TypeFromFn(comptime T: type) type {
504 return struct {};
505}
506
507test "volatile load and store" {
508 var number: i32 = 1234;
509 const ptr = (*volatile i32)(&number);
510 ptr.* += 1;
511 assert(ptr.* == 1235);
512}
513
514test "slice string literal has type []const u8" {
515 comptime {
516 assert(@typeOf("aoeu"[0..]) == []const u8);
517 const array = []i32{
518 1,
519 2,
520 3,
521 4,
522 };
523 assert(@typeOf(array[0..]) == []const i32);
524 }
525}
526
527test "global variable initialized to global variable array element" {
528 assert(global_ptr == &gdt[0]);
529}
530const GDTEntry = struct {
531 field: i32,
532};
533var gdt = []GDTEntry{
534 GDTEntry{ .field = 1 },
535 GDTEntry{ .field = 2 },
536};
537var global_ptr = &gdt[0];
538
539// can't really run this test but we can make sure it has no compile error
540// and generates code
541const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000];
542export fn writeToVRam() void {
543 vram[0] = 'X';
544}
545
546test "pointer child field" {
547 assert((*u32).Child == u32);
548}
549
550const OpaqueA = @OpaqueType();
551const OpaqueB = @OpaqueType();
552test "@OpaqueType" {
553 assert(*OpaqueA != *OpaqueB);
554 assert(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
555 assert(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
556}
557
558test "variable is allowed to be a pointer to an opaque type" {
559 var x: i32 = 1234;
560 _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x));
561}
562fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
563 var a = ptr;
564 return a;
565}
566
567test "comptime if inside runtime while which unconditionally breaks" {
568 testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
569 comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
570}
571fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void {
572 while (cond) {
573 if (false) {}
574 break;
575 }
576}
577
578test "implicit comptime while" {
579 while (false) {
580 @compileError("bad");
581 }
582}
583
584test "struct inside function" {
585 testStructInFn();
586 comptime testStructInFn();
587}
588
589fn testStructInFn() void {
590 const BlockKind = u32;
591
592 const Block = struct {
593 kind: BlockKind,
594 };
595
596 var block = Block{ .kind = 1234 };
597
598 block.kind += 1;
599
600 assert(block.kind == 1235);
601}
602
603fn fnThatClosesOverLocalConst() type {
604 const c = 1;
605 return struct {
606 fn g() i32 {
607 return c;
608 }
609 };
610}
611
612test "function closes over local const" {
613 const x = fnThatClosesOverLocalConst().g();
614 assert(x == 1);
615}
616
617test "cold function" {
618 thisIsAColdFn();
619 comptime thisIsAColdFn();
620}
621
622fn thisIsAColdFn() void {
623 @setCold(true);
624}
625
626const PackedStruct = packed struct {
627 a: u8,
628 b: u8,
629};
630const PackedUnion = packed union {
631 a: u8,
632 b: u32,
633};
634const PackedEnum = packed enum {
635 A,
636 B,
637};
638
639test "packed struct, enum, union parameters in extern function" {
640 testPackedStuff(&(PackedStruct{
641 .a = 1,
642 .b = 2,
643 }), &(PackedUnion{ .a = 1 }), PackedEnum.A);
644}
645
646export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion, c: PackedEnum) void {}
647
648test "slicing zero length array" {
649 const s1 = ""[0..];
650 const s2 = ([]u32{})[0..];
651 assert(s1.len == 0);
652 assert(s2.len == 0);
653 assert(mem.eql(u8, s1, ""));
654 assert(mem.eql(u32, s2, []u32{}));
655}
656
657const addr1 = @ptrCast(*const u8, emptyFn);
658test "comptime cast fn to ptr" {
659 const addr2 = @ptrCast(*const u8, emptyFn);
660 comptime assert(addr1 == addr2);
661}
662
663test "equality compare fn ptrs" {
664 var a = emptyFn;
665 assert(a == a);
666}
667
668test "self reference through fn ptr field" {
669 const S = struct {
670 const A = struct {
671 f: fn (A) u8,
672 };
673
674 fn foo(a: A) u8 {
675 return 12;
676 }
677 };
678 var a: S.A = undefined;
679 a.f = S.foo;
680 assert(a.f(a) == 12);
681}
test/cases/namespace_depends_on_compile_var/a.zig deleted-1
...@@ -1 +0,0 @@
1pub const a_bool = true;
test/cases/namespace_depends_on_compile_var/b.zig deleted-1
...@@ -1 +0,0 @@
1pub const a_bool = false;
test/cases/namespace_depends_on_compile_var/index.zig deleted-14
...@@ -1,14 +0,0 @@
1const builtin = @import("builtin");
2const assert = @import("std").debug.assert;
3
4test "namespace depends on compile var" {
5 if (some_namespace.a_bool) {
6 assert(some_namespace.a_bool);
7 } else {
8 assert(!some_namespace.a_bool);
9 }
10}
11const some_namespace = switch (builtin.os) {
12 builtin.Os.linux => @import("a.zig"),
13 else => @import("b.zig"),
14};
test/cases/new_stack_call.zig deleted-26
...@@ -1,26 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4var new_stack_bytes: [1024]u8 = undefined;
5
6test "calling a function with a new stack" {
7 const arg = 1234;
8
9 const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg);
10 const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg);
11 _ = targetFunction(arg);
12
13 assert(arg == 1234);
14 assert(a < b);
15}
16
17fn targetFunction(x: i32) usize {
18 assert(x == 1234);
19
20 var local_variable: i32 = 42;
21 const ptr = &local_variable;
22 ptr.* += 1;
23
24 assert(local_variable == 43);
25 return @ptrToInt(ptr);
26}
test/cases/null.zig deleted-162
...@@ -1,162 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "optional type" {
4 const x: ?bool = true;
5
6 if (x) |y| {
7 if (y) {
8 // OK
9 } else {
10 unreachable;
11 }
12 } else {
13 unreachable;
14 }
15
16 const next_x: ?i32 = null;
17
18 const z = next_x orelse 1234;
19
20 assert(z == 1234);
21
22 const final_x: ?i32 = 13;
23
24 const num = final_x orelse unreachable;
25
26 assert(num == 13);
27}
28
29test "test maybe object and get a pointer to the inner value" {
30 var maybe_bool: ?bool = true;
31
32 if (maybe_bool) |*b| {
33 b.* = false;
34 }
35
36 assert(maybe_bool.? == false);
37}
38
39test "rhs maybe unwrap return" {
40 const x: ?bool = true;
41 const y = x orelse return;
42}
43
44test "maybe return" {
45 maybeReturnImpl();
46 comptime maybeReturnImpl();
47}
48
49fn maybeReturnImpl() void {
50 assert(foo(1235).?);
51 if (foo(null) != null) unreachable;
52 assert(!foo(1234).?);
53}
54
55fn foo(x: ?i32) ?bool {
56 const value = x orelse return null;
57 return value > 1234;
58}
59
60test "if var maybe pointer" {
61 assert(shouldBeAPlus1(Particle{
62 .a = 14,
63 .b = 1,
64 .c = 1,
65 .d = 1,
66 }) == 15);
67}
68fn shouldBeAPlus1(p: Particle) u64 {
69 var maybe_particle: ?Particle = p;
70 if (maybe_particle) |*particle| {
71 particle.a += 1;
72 }
73 if (maybe_particle) |particle| {
74 return particle.a;
75 }
76 return 0;
77}
78const Particle = struct {
79 a: u64,
80 b: u64,
81 c: u64,
82 d: u64,
83};
84
85test "null literal outside function" {
86 const is_null = here_is_a_null_literal.context == null;
87 assert(is_null);
88
89 const is_non_null = here_is_a_null_literal.context != null;
90 assert(!is_non_null);
91}
92const SillyStruct = struct {
93 context: ?i32,
94};
95const here_is_a_null_literal = SillyStruct{ .context = null };
96
97test "test null runtime" {
98 testTestNullRuntime(null);
99}
100fn testTestNullRuntime(x: ?i32) void {
101 assert(x == null);
102 assert(!(x != null));
103}
104
105test "optional void" {
106 optionalVoidImpl();
107 comptime optionalVoidImpl();
108}
109
110fn optionalVoidImpl() void {
111 assert(bar(null) == null);
112 assert(bar({}) != null);
113}
114
115fn bar(x: ?void) ?void {
116 if (x) |_| {
117 return {};
118 } else {
119 return null;
120 }
121}
122
123const StructWithOptional = struct {
124 field: ?i32,
125};
126
127var struct_with_optional: StructWithOptional = undefined;
128
129test "unwrap optional which is field of global var" {
130 struct_with_optional.field = null;
131 if (struct_with_optional.field) |payload| {
132 unreachable;
133 }
134 struct_with_optional.field = 1234;
135 if (struct_with_optional.field) |payload| {
136 assert(payload == 1234);
137 } else {
138 unreachable;
139 }
140}
141
142test "null with default unwrap" {
143 const x: i32 = null orelse 1;
144 assert(x == 1);
145}
146
147test "optional types" {
148 comptime {
149 const opt_type_struct = StructWithOptionalType{ .t = u8 };
150 assert(opt_type_struct.t != null and opt_type_struct.t.? == u8);
151 }
152}
153
154const StructWithOptionalType = struct {
155 t: ?type,
156};
157
158test "optional pointer to 0 bit type null value at runtime" {
159 const EmptyStruct = struct {};
160 var x: ?*EmptyStruct = null;
161 assert(x == null);
162}
test/cases/optional.zig deleted-30
...@@ -1,30 +0,0 @@
1const assert = @import("std").debug.assert;
2
3pub const EmptyStruct = struct {};
4
5test "optional pointer to size zero struct" {
6 var e = EmptyStruct{};
7 var o: ?*EmptyStruct = &e;
8 assert(o != null);
9}
10
11test "equality compare nullable pointers" {
12 testNullPtrsEql();
13 comptime testNullPtrsEql();
14}
15
16fn testNullPtrsEql() void {
17 var number: i32 = 1234;
18
19 var x: ?*i32 = null;
20 var y: ?*i32 = null;
21 assert(x == y);
22 y = &number;
23 assert(x != y);
24 assert(x != &number);
25 assert(&number != x);
26 x = &number;
27 assert(x == y);
28 assert(x == &number);
29 assert(&number == x);
30}
test/cases/pointers.zig deleted-44
...@@ -1,44 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "dereference pointer" {
5 comptime testDerefPtr();
6 testDerefPtr();
7}
8
9fn testDerefPtr() void {
10 var x: i32 = 1234;
11 var y = &x;
12 y.* += 1;
13 assert(x == 1235);
14}
15
16test "pointer arithmetic" {
17 var ptr = c"abcd";
18
19 assert(ptr[0] == 'a');
20 ptr += 1;
21 assert(ptr[0] == 'b');
22 ptr += 1;
23 assert(ptr[0] == 'c');
24 ptr += 1;
25 assert(ptr[0] == 'd');
26 ptr += 1;
27 assert(ptr[0] == 0);
28 ptr -= 1;
29 assert(ptr[0] == 'd');
30 ptr -= 1;
31 assert(ptr[0] == 'c');
32 ptr -= 1;
33 assert(ptr[0] == 'b');
34 ptr -= 1;
35 assert(ptr[0] == 'a');
36}
37
38test "double pointer parsing" {
39 comptime assert(PtrOf(PtrOf(i32)) == **i32);
40}
41
42fn PtrOf(comptime T: type) type {
43 return *T;
44}
test/cases/popcount.zig deleted-24
...@@ -1,24 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "@popCount" {
4 comptime testPopCount();
5 testPopCount();
6}
7
8fn testPopCount() void {
9 {
10 var x: u32 = 0xaa;
11 assert(@popCount(x) == 4);
12 }
13 {
14 var x: u32 = 0xaaaaaaaa;
15 assert(@popCount(x) == 16);
16 }
17 {
18 var x: i16 = -1;
19 assert(@popCount(x) == 16);
20 }
21 comptime {
22 assert(@popCount(0b11111111000110001100010000100001000011000011100101010001) == 24);
23 }
24}
test/cases/pub_enum/index.zig deleted-13
...@@ -1,13 +0,0 @@
1const other = @import("other.zig");
2const assert = @import("std").debug.assert;
3
4test "pub enum" {
5 pubEnumTest(other.APubEnum.Two);
6}
7fn pubEnumTest(foo: other.APubEnum) void {
8 assert(foo == other.APubEnum.Two);
9}
10
11test "cast with imported symbol" {
12 assert(other.size_t(42) == 42);
13}
test/cases/pub_enum/other.zig deleted-6
...@@ -1,6 +0,0 @@
1pub const APubEnum = enum {
2 One,
3 Two,
4 Three,
5};
6pub const size_t = u64;
test/cases/ref_var_in_if_after_if_2nd_switch_prong.zig deleted-37
...@@ -1,37 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3
4var ok: bool = false;
5test "reference a variable in an if after an if in the 2nd switch prong" {
6 foo(true, Num.Two, false, "aoeu");
7 assert(!ok);
8 foo(false, Num.One, false, "aoeu");
9 assert(!ok);
10 foo(true, Num.One, false, "aoeu");
11 assert(ok);
12}
13
14const Num = enum {
15 One,
16 Two,
17};
18
19fn foo(c: bool, k: Num, c2: bool, b: []const u8) void {
20 switch (k) {
21 Num.Two => {},
22 Num.One => {
23 if (c) {
24 const output_path = b;
25
26 if (c2) {}
27
28 a(output_path);
29 }
30 },
31 }
32}
33
34fn a(x: []const u8) void {
35 assert(mem.eql(u8, x, "aoeu"));
36 ok = true;
37}
test/cases/reflection.zig deleted-95
...@@ -1,95 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3const reflection = @This();
4
5test "reflection: array, pointer, optional, error union type child" {
6 comptime {
7 assert(([10]u8).Child == u8);
8 assert((*u8).Child == u8);
9 assert((anyerror!u8).Payload == u8);
10 assert((?u8).Child == u8);
11 }
12}
13
14test "reflection: function return type, var args, and param types" {
15 comptime {
16 assert(@typeOf(dummy).ReturnType == i32);
17 assert(!@typeOf(dummy).is_var_args);
18 assert(@typeOf(dummy_varargs).is_var_args);
19 assert(@typeOf(dummy).arg_count == 3);
20 assert(@ArgType(@typeOf(dummy), 0) == bool);
21 assert(@ArgType(@typeOf(dummy), 1) == i32);
22 assert(@ArgType(@typeOf(dummy), 2) == f32);
23 }
24}
25
26fn dummy(a: bool, b: i32, c: f32) i32 {
27 return 1234;
28}
29fn dummy_varargs(args: ...) void {}
30
31test "reflection: struct member types and names" {
32 comptime {
33 assert(@memberCount(Foo) == 3);
34
35 assert(@memberType(Foo, 0) == i32);
36 assert(@memberType(Foo, 1) == bool);
37 assert(@memberType(Foo, 2) == void);
38
39 assert(mem.eql(u8, @memberName(Foo, 0), "one"));
40 assert(mem.eql(u8, @memberName(Foo, 1), "two"));
41 assert(mem.eql(u8, @memberName(Foo, 2), "three"));
42 }
43}
44
45test "reflection: enum member types and names" {
46 comptime {
47 assert(@memberCount(Bar) == 4);
48
49 assert(@memberType(Bar, 0) == void);
50 assert(@memberType(Bar, 1) == i32);
51 assert(@memberType(Bar, 2) == bool);
52 assert(@memberType(Bar, 3) == f64);
53
54 assert(mem.eql(u8, @memberName(Bar, 0), "One"));
55 assert(mem.eql(u8, @memberName(Bar, 1), "Two"));
56 assert(mem.eql(u8, @memberName(Bar, 2), "Three"));
57 assert(mem.eql(u8, @memberName(Bar, 3), "Four"));
58 }
59}
60
61test "reflection: @field" {
62 var f = Foo{
63 .one = 42,
64 .two = true,
65 .three = void{},
66 };
67
68 assert(f.one == f.one);
69 assert(@field(f, "o" ++ "ne") == f.one);
70 assert(@field(f, "t" ++ "wo") == f.two);
71 assert(@field(f, "th" ++ "ree") == f.three);
72 assert(@field(Foo, "const" ++ "ant") == Foo.constant);
73 assert(@field(Bar, "O" ++ "ne") == Bar.One);
74 assert(@field(Bar, "T" ++ "wo") == Bar.Two);
75 assert(@field(Bar, "Th" ++ "ree") == Bar.Three);
76 assert(@field(Bar, "F" ++ "our") == Bar.Four);
77 assert(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2));
78 @field(f, "o" ++ "ne") = 4;
79 assert(f.one == 4);
80}
81
82const Foo = struct {
83 const constant = 52;
84
85 one: i32,
86 two: bool,
87 three: void,
88};
89
90const Bar = union(enum) {
91 One: void,
92 Two: i32,
93 Three: bool,
94 Four: f64,
95};
test/cases/sizeof_and_typeof.zig deleted-69
...@@ -1,69 +0,0 @@
1const builtin = @import("builtin");
2const assert = @import("std").debug.assert;
3
4test "@sizeOf and @typeOf" {
5 const y: @typeOf(x) = 120;
6 assert(@sizeOf(@typeOf(y)) == 2);
7}
8const x: u16 = 13;
9const z: @typeOf(x) = 19;
10
11const A = struct {
12 a: u8,
13 b: u32,
14 c: u8,
15 d: u3,
16 e: u5,
17 f: u16,
18 g: u16,
19};
20
21const P = packed struct {
22 a: u8,
23 b: u32,
24 c: u8,
25 d: u3,
26 e: u5,
27 f: u16,
28 g: u16,
29};
30
31test "@byteOffsetOf" {
32 // Packed structs have fixed memory layout
33 assert(@byteOffsetOf(P, "a") == 0);
34 assert(@byteOffsetOf(P, "b") == 1);
35 assert(@byteOffsetOf(P, "c") == 5);
36 assert(@byteOffsetOf(P, "d") == 6);
37 assert(@byteOffsetOf(P, "e") == 6);
38 assert(@byteOffsetOf(P, "f") == 7);
39 assert(@byteOffsetOf(P, "g") == 9);
40
41 // Normal struct fields can be moved/padded
42 var a: A = undefined;
43 assert(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a"));
44 assert(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b"));
45 assert(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c"));
46 assert(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d"));
47 assert(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e"));
48 assert(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f"));
49 assert(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g"));
50}
51
52test "@bitOffsetOf" {
53 // Packed structs have fixed memory layout
54 assert(@bitOffsetOf(P, "a") == 0);
55 assert(@bitOffsetOf(P, "b") == 8);
56 assert(@bitOffsetOf(P, "c") == 40);
57 assert(@bitOffsetOf(P, "d") == 48);
58 assert(@bitOffsetOf(P, "e") == 51);
59 assert(@bitOffsetOf(P, "f") == 56);
60 assert(@bitOffsetOf(P, "g") == 72);
61
62 assert(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a"));
63 assert(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b"));
64 assert(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c"));
65 assert(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d"));
66 assert(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e"));
67 assert(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
68 assert(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
69}
test/cases/slice.zig deleted-40
...@@ -1,40 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3
4const x = @intToPtr([*]i32, 0x1000)[0..0x500];
5const y = x[0x100..];
6test "compile time slice of pointer to hard coded address" {
7 assert(@ptrToInt(x.ptr) == 0x1000);
8 assert(x.len == 0x500);
9
10 assert(@ptrToInt(y.ptr) == 0x1100);
11 assert(y.len == 0x400);
12}
13
14test "slice child property" {
15 var array: [5]i32 = undefined;
16 var slice = array[0..];
17 assert(@typeOf(slice).Child == i32);
18}
19
20test "runtime safety lets us slice from len..len" {
21 var an_array = []u8{
22 1,
23 2,
24 3,
25 };
26 assert(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
27}
28
29fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
30 return a_slice[start..end];
31}
32
33test "implicitly cast array of size 0 to slice" {
34 var msg = []u8{};
35 assertLenIsZero(msg);
36}
37
38fn assertLenIsZero(msg: []const u8) void {
39 assert(msg.len == 0);
40}
test/cases/struct.zig deleted-470
...@@ -1,470 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const builtin = @import("builtin");
4const maxInt = std.math.maxInt;
5
6const StructWithNoFields = struct {
7 fn add(a: i32, b: i32) i32 {
8 return a + b;
9 }
10};
11const empty_global_instance = StructWithNoFields{};
12
13test "call struct static method" {
14 const result = StructWithNoFields.add(3, 4);
15 assert(result == 7);
16}
17
18test "return empty struct instance" {
19 _ = returnEmptyStructInstance();
20}
21fn returnEmptyStructInstance() StructWithNoFields {
22 return empty_global_instance;
23}
24
25const should_be_11 = StructWithNoFields.add(5, 6);
26
27test "invake static method in global scope" {
28 assert(should_be_11 == 11);
29}
30
31test "void struct fields" {
32 const foo = VoidStructFieldsFoo{
33 .a = void{},
34 .b = 1,
35 .c = void{},
36 };
37 assert(foo.b == 1);
38 assert(@sizeOf(VoidStructFieldsFoo) == 4);
39}
40const VoidStructFieldsFoo = struct {
41 a: void,
42 b: i32,
43 c: void,
44};
45
46test "structs" {
47 var foo: StructFoo = undefined;
48 @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo));
49 foo.a += 1;
50 foo.b = foo.a == 1;
51 testFoo(foo);
52 testMutation(&foo);
53 assert(foo.c == 100);
54}
55const StructFoo = struct {
56 a: i32,
57 b: bool,
58 c: f32,
59};
60fn testFoo(foo: StructFoo) void {
61 assert(foo.b);
62}
63fn testMutation(foo: *StructFoo) void {
64 foo.c = 100;
65}
66
67const Node = struct {
68 val: Val,
69 next: *Node,
70};
71
72const Val = struct {
73 x: i32,
74};
75
76test "struct point to self" {
77 var root: Node = undefined;
78 root.val.x = 1;
79
80 var node: Node = undefined;
81 node.next = &root;
82 node.val.x = 2;
83
84 root.next = &node;
85
86 assert(node.next.next.next.val.x == 1);
87}
88
89test "struct byval assign" {
90 var foo1: StructFoo = undefined;
91 var foo2: StructFoo = undefined;
92
93 foo1.a = 1234;
94 foo2.a = 0;
95 assert(foo2.a == 0);
96 foo2 = foo1;
97 assert(foo2.a == 1234);
98}
99
100fn structInitializer() void {
101 const val = Val{ .x = 42 };
102 assert(val.x == 42);
103}
104
105test "fn call of struct field" {
106 assert(callStructField(Foo{ .ptr = aFunc }) == 13);
107}
108
109const Foo = struct {
110 ptr: fn () i32,
111};
112
113fn aFunc() i32 {
114 return 13;
115}
116
117fn callStructField(foo: Foo) i32 {
118 return foo.ptr();
119}
120
121test "store member function in variable" {
122 const instance = MemberFnTestFoo{ .x = 1234 };
123 const memberFn = MemberFnTestFoo.member;
124 const result = memberFn(instance);
125 assert(result == 1234);
126}
127const MemberFnTestFoo = struct {
128 x: i32,
129 fn member(foo: MemberFnTestFoo) i32 {
130 return foo.x;
131 }
132};
133
134test "call member function directly" {
135 const instance = MemberFnTestFoo{ .x = 1234 };
136 const result = MemberFnTestFoo.member(instance);
137 assert(result == 1234);
138}
139
140test "member functions" {
141 const r = MemberFnRand{ .seed = 1234 };
142 assert(r.getSeed() == 1234);
143}
144const MemberFnRand = struct {
145 seed: u32,
146 pub fn getSeed(r: *const MemberFnRand) u32 {
147 return r.seed;
148 }
149};
150
151test "return struct byval from function" {
152 const bar = makeBar(1234, 5678);
153 assert(bar.y == 5678);
154}
155const Bar = struct {
156 x: i32,
157 y: i32,
158};
159fn makeBar(x: i32, y: i32) Bar {
160 return Bar{
161 .x = x,
162 .y = y,
163 };
164}
165
166test "empty struct method call" {
167 const es = EmptyStruct{};
168 assert(es.method() == 1234);
169}
170const EmptyStruct = struct {
171 fn method(es: *const EmptyStruct) i32 {
172 return 1234;
173 }
174};
175
176test "return empty struct from fn" {
177 _ = testReturnEmptyStructFromFn();
178}
179const EmptyStruct2 = struct {};
180fn testReturnEmptyStructFromFn() EmptyStruct2 {
181 return EmptyStruct2{};
182}
183
184test "pass slice of empty struct to fn" {
185 assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{EmptyStruct2{}}) == 1);
186}
187fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize {
188 return slice.len;
189}
190
191const APackedStruct = packed struct {
192 x: u8,
193 y: u8,
194};
195
196test "packed struct" {
197 var foo = APackedStruct{
198 .x = 1,
199 .y = 2,
200 };
201 foo.y += 1;
202 const four = foo.x + foo.y;
203 assert(four == 4);
204}
205
206const BitField1 = packed struct {
207 a: u3,
208 b: u3,
209 c: u2,
210};
211
212const bit_field_1 = BitField1{
213 .a = 1,
214 .b = 2,
215 .c = 3,
216};
217
218test "bit field access" {
219 var data = bit_field_1;
220 assert(getA(&data) == 1);
221 assert(getB(&data) == 2);
222 assert(getC(&data) == 3);
223 comptime assert(@sizeOf(BitField1) == 1);
224
225 data.b += 1;
226 assert(data.b == 3);
227
228 data.a += 1;
229 assert(data.a == 2);
230 assert(data.b == 3);
231}
232
233fn getA(data: *const BitField1) u3 {
234 return data.a;
235}
236
237fn getB(data: *const BitField1) u3 {
238 return data.b;
239}
240
241fn getC(data: *const BitField1) u2 {
242 return data.c;
243}
244
245const Foo24Bits = packed struct {
246 field: u24,
247};
248const Foo96Bits = packed struct {
249 a: u24,
250 b: u24,
251 c: u24,
252 d: u24,
253};
254
255test "packed struct 24bits" {
256 comptime {
257 assert(@sizeOf(Foo24Bits) == 3);
258 assert(@sizeOf(Foo96Bits) == 12);
259 }
260
261 var value = Foo96Bits{
262 .a = 0,
263 .b = 0,
264 .c = 0,
265 .d = 0,
266 };
267 value.a += 1;
268 assert(value.a == 1);
269 assert(value.b == 0);
270 assert(value.c == 0);
271 assert(value.d == 0);
272
273 value.b += 1;
274 assert(value.a == 1);
275 assert(value.b == 1);
276 assert(value.c == 0);
277 assert(value.d == 0);
278
279 value.c += 1;
280 assert(value.a == 1);
281 assert(value.b == 1);
282 assert(value.c == 1);
283 assert(value.d == 0);
284
285 value.d += 1;
286 assert(value.a == 1);
287 assert(value.b == 1);
288 assert(value.c == 1);
289 assert(value.d == 1);
290}
291
292const FooArray24Bits = packed struct {
293 a: u16,
294 b: [2]Foo24Bits,
295 c: u16,
296};
297
298test "packed array 24bits" {
299 comptime {
300 assert(@sizeOf([9]Foo24Bits) == 9 * 3);
301 assert(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2);
302 }
303
304 var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1);
305 bytes[bytes.len - 1] = 0xaa;
306 const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0];
307 assert(ptr.a == 0);
308 assert(ptr.b[0].field == 0);
309 assert(ptr.b[1].field == 0);
310 assert(ptr.c == 0);
311
312 ptr.a = maxInt(u16);
313 assert(ptr.a == maxInt(u16));
314 assert(ptr.b[0].field == 0);
315 assert(ptr.b[1].field == 0);
316 assert(ptr.c == 0);
317
318 ptr.b[0].field = maxInt(u24);
319 assert(ptr.a == maxInt(u16));
320 assert(ptr.b[0].field == maxInt(u24));
321 assert(ptr.b[1].field == 0);
322 assert(ptr.c == 0);
323
324 ptr.b[1].field = maxInt(u24);
325 assert(ptr.a == maxInt(u16));
326 assert(ptr.b[0].field == maxInt(u24));
327 assert(ptr.b[1].field == maxInt(u24));
328 assert(ptr.c == 0);
329
330 ptr.c = maxInt(u16);
331 assert(ptr.a == maxInt(u16));
332 assert(ptr.b[0].field == maxInt(u24));
333 assert(ptr.b[1].field == maxInt(u24));
334 assert(ptr.c == maxInt(u16));
335
336 assert(bytes[bytes.len - 1] == 0xaa);
337}
338
339const FooStructAligned = packed struct {
340 a: u8,
341 b: u8,
342};
343
344const FooArrayOfAligned = packed struct {
345 a: [2]FooStructAligned,
346};
347
348test "aligned array of packed struct" {
349 comptime {
350 assert(@sizeOf(FooStructAligned) == 2);
351 assert(@sizeOf(FooArrayOfAligned) == 2 * 2);
352 }
353
354 var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned);
355 const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0];
356
357 assert(ptr.a[0].a == 0xbb);
358 assert(ptr.a[0].b == 0xbb);
359 assert(ptr.a[1].a == 0xbb);
360 assert(ptr.a[1].b == 0xbb);
361}
362
363test "runtime struct initialization of bitfield" {
364 const s1 = Nibbles{
365 .x = x1,
366 .y = x1,
367 };
368 const s2 = Nibbles{
369 .x = @intCast(u4, x2),
370 .y = @intCast(u4, x2),
371 };
372
373 assert(s1.x == x1);
374 assert(s1.y == x1);
375 assert(s2.x == @intCast(u4, x2));
376 assert(s2.y == @intCast(u4, x2));
377}
378
379var x1 = u4(1);
380var x2 = u8(2);
381
382const Nibbles = packed struct {
383 x: u4,
384 y: u4,
385};
386
387const Bitfields = packed struct {
388 f1: u16,
389 f2: u16,
390 f3: u8,
391 f4: u8,
392 f5: u4,
393 f6: u4,
394 f7: u8,
395};
396
397test "native bit field understands endianness" {
398 var all: u64 = 0x7765443322221111;
399 var bytes: [8]u8 = undefined;
400 @memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8);
401 var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*;
402
403 assert(bitfields.f1 == 0x1111);
404 assert(bitfields.f2 == 0x2222);
405 assert(bitfields.f3 == 0x33);
406 assert(bitfields.f4 == 0x44);
407 assert(bitfields.f5 == 0x5);
408 assert(bitfields.f6 == 0x6);
409 assert(bitfields.f7 == 0x77);
410}
411
412test "align 1 field before self referential align 8 field as slice return type" {
413 const result = alloc(Expr);
414 assert(result.len == 0);
415}
416
417const Expr = union(enum) {
418 Literal: u8,
419 Question: *Expr,
420};
421
422fn alloc(comptime T: type) []T {
423 return []T{};
424}
425
426test "call method with mutable reference to struct with no fields" {
427 const S = struct {
428 fn doC(s: *const @This()) bool {
429 return true;
430 }
431 fn do(s: *@This()) bool {
432 return true;
433 }
434 };
435
436 var s = S{};
437 assert(S.doC(&s));
438 assert(s.doC());
439 assert(S.do(&s));
440 assert(s.do());
441}
442
443test "implicit cast packed struct field to const ptr" {
444 const LevelUpMove = packed struct {
445 move_id: u9,
446 level: u7,
447
448 fn toInt(value: u7) u7 {
449 return value;
450 }
451 };
452
453 var lup: LevelUpMove = undefined;
454 lup.level = 12;
455 const res = LevelUpMove.toInt(lup.level);
456 assert(res == 12);
457}
458
459test "pointer to packed struct member in a stack variable" {
460 const S = packed struct {
461 a: u2,
462 b: u2,
463 };
464
465 var s = S{ .a = 2, .b = 0 };
466 var b_ptr = &s.b;
467 assert(s.b == 0);
468 b_ptr.* = 2;
469 assert(s.b == 2);
470}
test/cases/struct_contains_null_ptr_itself.zig deleted-21
...@@ -1,21 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "struct contains null pointer which contains original struct" {
5 var x: ?*NodeLineComment = null;
6 assert(x == null);
7}
8
9pub const Node = struct {
10 id: Id,
11 comment: ?*NodeLineComment,
12
13 pub const Id = enum {
14 Root,
15 LineComment,
16 };
17};
18
19pub const NodeLineComment = struct {
20 base: Node,
21};
test/cases/struct_contains_slice_of_itself.zig deleted-43
...@@ -1,43 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const Node = struct {
4 payload: i32,
5 children: []Node,
6};
7
8test "struct contains slice of itself" {
9 var other_nodes = []Node{
10 Node{
11 .payload = 31,
12 .children = []Node{},
13 },
14 Node{
15 .payload = 32,
16 .children = []Node{},
17 },
18 };
19 var nodes = []Node{
20 Node{
21 .payload = 1,
22 .children = []Node{},
23 },
24 Node{
25 .payload = 2,
26 .children = []Node{},
27 },
28 Node{
29 .payload = 3,
30 .children = other_nodes[0..],
31 },
32 };
33 const root = Node{
34 .payload = 1234,
35 .children = nodes[0..],
36 };
37 assert(root.payload == 1234);
38 assert(root.children[0].payload == 1);
39 assert(root.children[1].payload == 2);
40 assert(root.children[2].payload == 3);
41 assert(root.children[2].children[0].payload == 31);
42 assert(root.children[2].children[1].payload == 32);
43}
test/cases/switch.zig deleted-234
...@@ -1,234 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "switch with numbers" {
4 testSwitchWithNumbers(13);
5}
6
7fn testSwitchWithNumbers(x: u32) void {
8 const result = switch (x) {
9 1, 2, 3, 4...8 => false,
10 13 => true,
11 else => false,
12 };
13 assert(result);
14}
15
16test "switch with all ranges" {
17 assert(testSwitchWithAllRanges(50, 3) == 1);
18 assert(testSwitchWithAllRanges(101, 0) == 2);
19 assert(testSwitchWithAllRanges(300, 5) == 3);
20 assert(testSwitchWithAllRanges(301, 6) == 6);
21}
22
23fn testSwitchWithAllRanges(x: u32, y: u32) u32 {
24 return switch (x) {
25 0...100 => 1,
26 101...200 => 2,
27 201...300 => 3,
28 else => y,
29 };
30}
31
32test "implicit comptime switch" {
33 const x = 3 + 4;
34 const result = switch (x) {
35 3 => 10,
36 4 => 11,
37 5, 6 => 12,
38 7, 8 => 13,
39 else => 14,
40 };
41
42 comptime {
43 assert(result + 1 == 14);
44 }
45}
46
47test "switch on enum" {
48 const fruit = Fruit.Orange;
49 nonConstSwitchOnEnum(fruit);
50}
51const Fruit = enum {
52 Apple,
53 Orange,
54 Banana,
55};
56fn nonConstSwitchOnEnum(fruit: Fruit) void {
57 switch (fruit) {
58 Fruit.Apple => unreachable,
59 Fruit.Orange => {},
60 Fruit.Banana => unreachable,
61 }
62}
63
64test "switch statement" {
65 nonConstSwitch(SwitchStatmentFoo.C);
66}
67fn nonConstSwitch(foo: SwitchStatmentFoo) void {
68 const val = switch (foo) {
69 SwitchStatmentFoo.A => i32(1),
70 SwitchStatmentFoo.B => 2,
71 SwitchStatmentFoo.C => 3,
72 SwitchStatmentFoo.D => 4,
73 };
74 assert(val == 3);
75}
76const SwitchStatmentFoo = enum {
77 A,
78 B,
79 C,
80 D,
81};
82
83test "switch prong with variable" {
84 switchProngWithVarFn(SwitchProngWithVarEnum{ .One = 13 });
85 switchProngWithVarFn(SwitchProngWithVarEnum{ .Two = 13.0 });
86 switchProngWithVarFn(SwitchProngWithVarEnum{ .Meh = {} });
87}
88const SwitchProngWithVarEnum = union(enum) {
89 One: i32,
90 Two: f32,
91 Meh: void,
92};
93fn switchProngWithVarFn(a: SwitchProngWithVarEnum) void {
94 switch (a) {
95 SwitchProngWithVarEnum.One => |x| {
96 assert(x == 13);
97 },
98 SwitchProngWithVarEnum.Two => |x| {
99 assert(x == 13.0);
100 },
101 SwitchProngWithVarEnum.Meh => |x| {
102 const v: void = x;
103 },
104 }
105}
106
107test "switch on enum using pointer capture" {
108 testSwitchEnumPtrCapture();
109 comptime testSwitchEnumPtrCapture();
110}
111
112fn testSwitchEnumPtrCapture() void {
113 var value = SwitchProngWithVarEnum{ .One = 1234 };
114 switch (value) {
115 SwitchProngWithVarEnum.One => |*x| x.* += 1,
116 else => unreachable,
117 }
118 switch (value) {
119 SwitchProngWithVarEnum.One => |x| assert(x == 1235),
120 else => unreachable,
121 }
122}
123
124test "switch with multiple expressions" {
125 const x = switch (returnsFive()) {
126 1, 2, 3 => 1,
127 4, 5, 6 => 2,
128 else => i32(3),
129 };
130 assert(x == 2);
131}
132fn returnsFive() i32 {
133 return 5;
134}
135
136const Number = union(enum) {
137 One: u64,
138 Two: u8,
139 Three: f32,
140};
141
142const number = Number{ .Three = 1.23 };
143
144fn returnsFalse() bool {
145 switch (number) {
146 Number.One => |x| return x > 1234,
147 Number.Two => |x| return x == 'a',
148 Number.Three => |x| return x > 12.34,
149 }
150}
151test "switch on const enum with var" {
152 assert(!returnsFalse());
153}
154
155test "switch on type" {
156 assert(trueIfBoolFalseOtherwise(bool));
157 assert(!trueIfBoolFalseOtherwise(i32));
158}
159
160fn trueIfBoolFalseOtherwise(comptime T: type) bool {
161 return switch (T) {
162 bool => true,
163 else => false,
164 };
165}
166
167test "switch handles all cases of number" {
168 testSwitchHandleAllCases();
169 comptime testSwitchHandleAllCases();
170}
171
172fn testSwitchHandleAllCases() void {
173 assert(testSwitchHandleAllCasesExhaustive(0) == 3);
174 assert(testSwitchHandleAllCasesExhaustive(1) == 2);
175 assert(testSwitchHandleAllCasesExhaustive(2) == 1);
176 assert(testSwitchHandleAllCasesExhaustive(3) == 0);
177
178 assert(testSwitchHandleAllCasesRange(100) == 0);
179 assert(testSwitchHandleAllCasesRange(200) == 1);
180 assert(testSwitchHandleAllCasesRange(201) == 2);
181 assert(testSwitchHandleAllCasesRange(202) == 4);
182 assert(testSwitchHandleAllCasesRange(230) == 3);
183}
184
185fn testSwitchHandleAllCasesExhaustive(x: u2) u2 {
186 return switch (x) {
187 0 => u2(3),
188 1 => 2,
189 2 => 1,
190 3 => 0,
191 };
192}
193
194fn testSwitchHandleAllCasesRange(x: u8) u8 {
195 return switch (x) {
196 0...100 => u8(0),
197 101...200 => 1,
198 201, 203 => 2,
199 202 => 4,
200 204...255 => 3,
201 };
202}
203
204test "switch all prongs unreachable" {
205 testAllProngsUnreachable();
206 comptime testAllProngsUnreachable();
207}
208
209fn testAllProngsUnreachable() void {
210 assert(switchWithUnreachable(1) == 2);
211 assert(switchWithUnreachable(2) == 10);
212}
213
214fn switchWithUnreachable(x: i32) i32 {
215 while (true) {
216 switch (x) {
217 1 => return 2,
218 2 => break,
219 else => continue,
220 }
221 }
222 return 10;
223}
224
225fn return_a_number() anyerror!i32 {
226 return 1;
227}
228
229test "capture value of switch with all unreachable prongs" {
230 const x = return_a_number() catch |err| switch (err) {
231 else => unreachable,
232 };
233 assert(x == 1);
234}
test/cases/switch_prong_err_enum.zig deleted-30
...@@ -1,30 +0,0 @@
1const assert = @import("std").debug.assert;
2
3var read_count: u64 = 0;
4
5fn readOnce() anyerror!u64 {
6 read_count += 1;
7 return read_count;
8}
9
10const FormValue = union(enum) {
11 Address: u64,
12 Other: bool,
13};
14
15fn doThing(form_id: u64) anyerror!FormValue {
16 return switch (form_id) {
17 17 => FormValue{ .Address = try readOnce() },
18 else => error.InvalidDebugInfo,
19 };
20}
21
22test "switch prong returns error enum" {
23 switch (doThing(17) catch unreachable) {
24 FormValue.Address => |payload| {
25 assert(payload == 1);
26 },
27 else => unreachable,
28 }
29 assert(read_count == 1);
30}
test/cases/switch_prong_implicit_cast.zig deleted-22
...@@ -1,22 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const FormValue = union(enum) {
4 One: void,
5 Two: bool,
6};
7
8fn foo(id: u64) !FormValue {
9 return switch (id) {
10 2 => FormValue{ .Two = true },
11 1 => FormValue{ .One = {} },
12 else => return error.Whatever,
13 };
14}
15
16test "switch prong implicit cast" {
17 const result = switch (foo(2) catch unreachable) {
18 FormValue.One => false,
19 FormValue.Two => |x| x,
20 };
21 assert(result);
22}
test/cases/syntax.zig deleted-59
...@@ -1,59 +0,0 @@
1// Test trailing comma syntax
2// zig fmt: off
3
4const struct_trailing_comma = struct { x: i32, y: i32, };
5const struct_no_comma = struct { x: i32, y: i32 };
6const struct_fn_no_comma = struct { fn m() void {} y: i32 };
7
8const enum_no_comma = enum { A, B };
9
10fn container_init() void {
11 const S = struct { x: i32, y: i32 };
12 _ = S { .x = 1, .y = 2 };
13 _ = S { .x = 1, .y = 2, };
14}
15
16fn type_expr_return1() if (true) A {}
17fn type_expr_return2() for (true) |_| A {}
18fn type_expr_return3() while (true) A {}
19fn type_expr_return4() comptime A {}
20
21fn switch_cases(x: i32) void {
22 switch (x) {
23 1,2,3 => {},
24 4,5, => {},
25 6...8, => {},
26 else => {},
27 }
28}
29
30fn switch_prongs(x: i32) void {
31 switch (x) {
32 0 => {},
33 else => {},
34 }
35 switch (x) {
36 0 => {},
37 else => {}
38 }
39}
40
41const fn_no_comma = fn(i32, i32)void;
42const fn_trailing_comma = fn(i32, i32,)void;
43
44fn fn_calls() void {
45 fn add(x: i32, y: i32,) i32 { x + y };
46 _ = add(1, 2);
47 _ = add(1, 2,);
48}
49
50fn asm_lists() void {
51 if (false) { // Build AST but don't analyze
52 asm ("not real assembly"
53 :[a] "x" (x),);
54 asm ("not real assembly"
55 :[a] "x" (->i32),:[a] "x" (1),);
56 asm ("still not real assembly"
57 :::"a","b",);
58 }
59}
test/cases/this.zig deleted-34
...@@ -1,34 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const module = @This();
4
5fn Point(comptime T: type) type {
6 return struct {
7 const Self = @This();
8 x: T,
9 y: T,
10
11 fn addOne(self: *Self) void {
12 self.x += 1;
13 self.y += 1;
14 }
15 };
16}
17
18fn add(x: i32, y: i32) i32 {
19 return x + y;
20}
21
22test "this refer to module call private fn" {
23 assert(module.add(1, 2) == 3);
24}
25
26test "this refer to container" {
27 var pt = Point(i32){
28 .x = 12,
29 .y = 34,
30 };
31 pt.addOne();
32 assert(pt.x == 13);
33 assert(pt.y == 35);
34}
test/cases/try.zig deleted-43
...@@ -1,43 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "try on error union" {
4 tryOnErrorUnionImpl();
5 comptime tryOnErrorUnionImpl();
6}
7
8fn tryOnErrorUnionImpl() void {
9 const x = if (returnsTen()) |val| val + 1 else |err| switch (err) {
10 error.ItBroke, error.NoMem => 1,
11 error.CrappedOut => i32(2),
12 else => unreachable,
13 };
14 assert(x == 11);
15}
16
17fn returnsTen() anyerror!i32 {
18 return 10;
19}
20
21test "try without vars" {
22 const result1 = if (failIfTrue(true)) 1 else |_| i32(2);
23 assert(result1 == 2);
24
25 const result2 = if (failIfTrue(false)) 1 else |_| i32(2);
26 assert(result2 == 1);
27}
28
29fn failIfTrue(ok: bool) anyerror!void {
30 if (ok) {
31 return error.ItBroke;
32 } else {
33 return;
34 }
35}
36
37test "try then not executed with assignment" {
38 if (failIfTrue(true)) {
39 unreachable;
40 } else |err| {
41 assert(err == error.ItBroke);
42 }
43}
test/cases/type_info.zig deleted-259
...@@ -1,259 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3const TypeInfo = @import("builtin").TypeInfo;
4const TypeId = @import("builtin").TypeId;
5
6test "type info: tag type, void info" {
7 testBasic();
8 comptime testBasic();
9}
10
11fn testBasic() void {
12 assert(@TagType(TypeInfo) == TypeId);
13 const void_info = @typeInfo(void);
14 assert(TypeId(void_info) == TypeId.Void);
15 assert(void_info.Void == {});
16}
17
18test "type info: integer, floating point type info" {
19 testIntFloat();
20 comptime testIntFloat();
21}
22
23fn testIntFloat() void {
24 const u8_info = @typeInfo(u8);
25 assert(TypeId(u8_info) == TypeId.Int);
26 assert(!u8_info.Int.is_signed);
27 assert(u8_info.Int.bits == 8);
28
29 const f64_info = @typeInfo(f64);
30 assert(TypeId(f64_info) == TypeId.Float);
31 assert(f64_info.Float.bits == 64);
32}
33
34test "type info: pointer type info" {
35 testPointer();
36 comptime testPointer();
37}
38
39fn testPointer() void {
40 const u32_ptr_info = @typeInfo(*u32);
41 assert(TypeId(u32_ptr_info) == TypeId.Pointer);
42 assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One);
43 assert(u32_ptr_info.Pointer.is_const == false);
44 assert(u32_ptr_info.Pointer.is_volatile == false);
45 assert(u32_ptr_info.Pointer.alignment == @alignOf(u32));
46 assert(u32_ptr_info.Pointer.child == u32);
47}
48
49test "type info: unknown length pointer type info" {
50 testUnknownLenPtr();
51 comptime testUnknownLenPtr();
52}
53
54fn testUnknownLenPtr() void {
55 const u32_ptr_info = @typeInfo([*]const volatile f64);
56 assert(TypeId(u32_ptr_info) == TypeId.Pointer);
57 assert(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
58 assert(u32_ptr_info.Pointer.is_const == true);
59 assert(u32_ptr_info.Pointer.is_volatile == true);
60 assert(u32_ptr_info.Pointer.alignment == @alignOf(f64));
61 assert(u32_ptr_info.Pointer.child == f64);
62}
63
64test "type info: slice type info" {
65 testSlice();
66 comptime testSlice();
67}
68
69fn testSlice() void {
70 const u32_slice_info = @typeInfo([]u32);
71 assert(TypeId(u32_slice_info) == TypeId.Pointer);
72 assert(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice);
73 assert(u32_slice_info.Pointer.is_const == false);
74 assert(u32_slice_info.Pointer.is_volatile == false);
75 assert(u32_slice_info.Pointer.alignment == 4);
76 assert(u32_slice_info.Pointer.child == u32);
77}
78
79test "type info: array type info" {
80 testArray();
81 comptime testArray();
82}
83
84fn testArray() void {
85 const arr_info = @typeInfo([42]bool);
86 assert(TypeId(arr_info) == TypeId.Array);
87 assert(arr_info.Array.len == 42);
88 assert(arr_info.Array.child == bool);
89}
90
91test "type info: optional type info" {
92 testOptional();
93 comptime testOptional();
94}
95
96fn testOptional() void {
97 const null_info = @typeInfo(?void);
98 assert(TypeId(null_info) == TypeId.Optional);
99 assert(null_info.Optional.child == void);
100}
101
102test "type info: promise info" {
103 testPromise();
104 comptime testPromise();
105}
106
107fn testPromise() void {
108 const null_promise_info = @typeInfo(promise);
109 assert(TypeId(null_promise_info) == TypeId.Promise);
110 assert(null_promise_info.Promise.child == null);
111
112 const promise_info = @typeInfo(promise->usize);
113 assert(TypeId(promise_info) == TypeId.Promise);
114 assert(promise_info.Promise.child.? == usize);
115}
116
117test "type info: error set, error union info" {
118 testErrorSet();
119 comptime testErrorSet();
120}
121
122fn testErrorSet() void {
123 const TestErrorSet = error{
124 First,
125 Second,
126 Third,
127 };
128
129 const error_set_info = @typeInfo(TestErrorSet);
130 assert(TypeId(error_set_info) == TypeId.ErrorSet);
131 assert(error_set_info.ErrorSet.errors.len == 3);
132 assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
133 assert(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third));
134
135 const error_union_info = @typeInfo(TestErrorSet!usize);
136 assert(TypeId(error_union_info) == TypeId.ErrorUnion);
137 assert(error_union_info.ErrorUnion.error_set == TestErrorSet);
138 assert(error_union_info.ErrorUnion.payload == usize);
139}
140
141test "type info: enum info" {
142 testEnum();
143 comptime testEnum();
144}
145
146fn testEnum() void {
147 const Os = @import("builtin").Os;
148
149 const os_info = @typeInfo(Os);
150 assert(TypeId(os_info) == TypeId.Enum);
151 assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
152 assert(os_info.Enum.fields.len == 32);
153 assert(mem.eql(u8, os_info.Enum.fields[1].name, "ananas"));
154 assert(os_info.Enum.fields[10].value == 10);
155 assert(os_info.Enum.tag_type == u5);
156 assert(os_info.Enum.defs.len == 0);
157}
158
159test "type info: union info" {
160 testUnion();
161 comptime testUnion();
162}
163
164fn testUnion() void {
165 const typeinfo_info = @typeInfo(TypeInfo);
166 assert(TypeId(typeinfo_info) == TypeId.Union);
167 assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
168 assert(typeinfo_info.Union.tag_type.? == TypeId);
169 assert(typeinfo_info.Union.fields.len == 24);
170 assert(typeinfo_info.Union.fields[4].enum_field != null);
171 assert(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
172 assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
173 assert(typeinfo_info.Union.defs.len == 20);
174
175 const TestNoTagUnion = union {
176 Foo: void,
177 Bar: u32,
178 };
179
180 const notag_union_info = @typeInfo(TestNoTagUnion);
181 assert(TypeId(notag_union_info) == TypeId.Union);
182 assert(notag_union_info.Union.tag_type == null);
183 assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
184 assert(notag_union_info.Union.fields.len == 2);
185 assert(notag_union_info.Union.fields[0].enum_field == null);
186 assert(notag_union_info.Union.fields[1].field_type == u32);
187
188 const TestExternUnion = extern union {
189 foo: *c_void,
190 };
191
192 const extern_union_info = @typeInfo(TestExternUnion);
193 assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
194 assert(extern_union_info.Union.tag_type == null);
195 assert(extern_union_info.Union.fields[0].enum_field == null);
196 assert(extern_union_info.Union.fields[0].field_type == *c_void);
197}
198
199test "type info: struct info" {
200 testStruct();
201 comptime testStruct();
202}
203
204fn testStruct() void {
205 const struct_info = @typeInfo(TestStruct);
206 assert(TypeId(struct_info) == TypeId.Struct);
207 assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
208 assert(struct_info.Struct.fields.len == 3);
209 assert(struct_info.Struct.fields[1].offset == null);
210 assert(struct_info.Struct.fields[2].field_type == *TestStruct);
211 assert(struct_info.Struct.defs.len == 2);
212 assert(struct_info.Struct.defs[0].is_pub);
213 assert(!struct_info.Struct.defs[0].data.Fn.is_extern);
214 assert(struct_info.Struct.defs[0].data.Fn.lib_name == null);
215 assert(struct_info.Struct.defs[0].data.Fn.return_type == void);
216 assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void);
217}
218
219const TestStruct = packed struct {
220 const Self = @This();
221
222 fieldA: usize,
223 fieldB: void,
224 fieldC: *Self,
225
226 pub fn foo(self: *const Self) void {}
227};
228
229test "type info: function type info" {
230 testFunction();
231 comptime testFunction();
232}
233
234fn testFunction() void {
235 const fn_info = @typeInfo(@typeOf(foo));
236 assert(TypeId(fn_info) == TypeId.Fn);
237 assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
238 assert(fn_info.Fn.is_generic);
239 assert(fn_info.Fn.args.len == 2);
240 assert(fn_info.Fn.is_var_args);
241 assert(fn_info.Fn.return_type == null);
242 assert(fn_info.Fn.async_allocator_type == null);
243
244 const test_instance: TestStruct = undefined;
245 const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
246 assert(TypeId(bound_fn_info) == TypeId.BoundFn);
247 assert(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
248}
249
250fn foo(comptime a: usize, b: bool, args: ...) usize {
251 return 0;
252}
253
254test "typeInfo with comptime parameter in struct fn def" {
255 const S = struct {
256 pub fn func(comptime x: f32) void {}
257 };
258 comptime var info = @typeInfo(S);
259}
test/cases/undefined.zig deleted-68
...@@ -1,68 +0,0 @@
1const assert = @import("std").debug.assert;
2const mem = @import("std").mem;
3
4fn initStaticArray() [10]i32 {
5 var array: [10]i32 = undefined;
6 array[0] = 1;
7 array[4] = 2;
8 array[7] = 3;
9 array[9] = 4;
10 return array;
11}
12const static_array = initStaticArray();
13test "init static array to undefined" {
14 assert(static_array[0] == 1);
15 assert(static_array[4] == 2);
16 assert(static_array[7] == 3);
17 assert(static_array[9] == 4);
18
19 comptime {
20 assert(static_array[0] == 1);
21 assert(static_array[4] == 2);
22 assert(static_array[7] == 3);
23 assert(static_array[9] == 4);
24 }
25}
26
27const Foo = struct {
28 x: i32,
29
30 fn setFooXMethod(foo: *Foo) void {
31 foo.x = 3;
32 }
33};
34
35fn setFooX(foo: *Foo) void {
36 foo.x = 2;
37}
38
39test "assign undefined to struct" {
40 comptime {
41 var foo: Foo = undefined;
42 setFooX(&foo);
43 assert(foo.x == 2);
44 }
45 {
46 var foo: Foo = undefined;
47 setFooX(&foo);
48 assert(foo.x == 2);
49 }
50}
51
52test "assign undefined to struct with method" {
53 comptime {
54 var foo: Foo = undefined;
55 foo.setFooXMethod();
56 assert(foo.x == 3);
57 }
58 {
59 var foo: Foo = undefined;
60 foo.setFooXMethod();
61 assert(foo.x == 3);
62 }
63}
64
65test "type name of undefined" {
66 const x = undefined;
67 assert(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)"));
68}
test/cases/underscore.zig deleted-28
...@@ -1,28 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "ignore lval with underscore" {
5 _ = false;
6}
7
8test "ignore lval with underscore (for loop)" {
9 for ([]void{}) |_, i| {
10 for ([]void{}) |_, j| {
11 break;
12 }
13 break;
14 }
15}
16
17test "ignore lval with underscore (while loop)" {
18 while (optionalReturnError()) |_| {
19 while (optionalReturnError()) |_| {
20 break;
21 } else |_| {}
22 break;
23 } else |_| {}
24}
25
26fn optionalReturnError() !?u32 {
27 return error.optionalReturnError;
28}
test/cases/union.zig deleted-352
...@@ -1,352 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const Value = union(enum) {
4 Int: u64,
5 Array: [9]u8,
6};
7
8const Agg = struct {
9 val1: Value,
10 val2: Value,
11};
12
13const v1 = Value{ .Int = 1234 };
14const v2 = Value{ .Array = []u8{3} ** 9 };
15
16const err = (anyerror!Agg)(Agg{
17 .val1 = v1,
18 .val2 = v2,
19});
20
21const array = []Value{
22 v1,
23 v2,
24 v1,
25 v2,
26};
27
28test "unions embedded in aggregate types" {
29 switch (array[1]) {
30 Value.Array => |arr| assert(arr[4] == 3),
31 else => unreachable,
32 }
33 switch ((err catch unreachable).val1) {
34 Value.Int => |x| assert(x == 1234),
35 else => unreachable,
36 }
37}
38
39const Foo = union {
40 float: f64,
41 int: i32,
42};
43
44test "basic unions" {
45 var foo = Foo{ .int = 1 };
46 assert(foo.int == 1);
47 foo = Foo{ .float = 12.34 };
48 assert(foo.float == 12.34);
49}
50
51test "comptime union field access" {
52 comptime {
53 var foo = Foo{ .int = 0 };
54 assert(foo.int == 0);
55
56 foo = Foo{ .float = 42.42 };
57 assert(foo.float == 42.42);
58 }
59}
60
61test "init union with runtime value" {
62 var foo: Foo = undefined;
63
64 setFloat(&foo, 12.34);
65 assert(foo.float == 12.34);
66
67 setInt(&foo, 42);
68 assert(foo.int == 42);
69}
70
71fn setFloat(foo: *Foo, x: f64) void {
72 foo.* = Foo{ .float = x };
73}
74
75fn setInt(foo: *Foo, x: i32) void {
76 foo.* = Foo{ .int = x };
77}
78
79const FooExtern = extern union {
80 float: f64,
81 int: i32,
82};
83
84test "basic extern unions" {
85 var foo = FooExtern{ .int = 1 };
86 assert(foo.int == 1);
87 foo.float = 12.34;
88 assert(foo.float == 12.34);
89}
90
91const Letter = enum {
92 A,
93 B,
94 C,
95};
96const Payload = union(Letter) {
97 A: i32,
98 B: f64,
99 C: bool,
100};
101
102test "union with specified enum tag" {
103 doTest();
104 comptime doTest();
105}
106
107fn doTest() void {
108 assert(bar(Payload{ .A = 1234 }) == -10);
109}
110
111fn bar(value: Payload) i32 {
112 assert(Letter(value) == Letter.A);
113 return switch (value) {
114 Payload.A => |x| return x - 1244,
115 Payload.B => |x| if (x == 12.34) i32(20) else 21,
116 Payload.C => |x| if (x) i32(30) else 31,
117 };
118}
119
120const MultipleChoice = union(enum(u32)) {
121 A = 20,
122 B = 40,
123 C = 60,
124 D = 1000,
125};
126test "simple union(enum(u32))" {
127 var x = MultipleChoice.C;
128 assert(x == MultipleChoice.C);
129 assert(@enumToInt(@TagType(MultipleChoice)(x)) == 60);
130}
131
132const MultipleChoice2 = union(enum(u32)) {
133 Unspecified1: i32,
134 A: f32 = 20,
135 Unspecified2: void,
136 B: bool = 40,
137 Unspecified3: i32,
138 C: i8 = 60,
139 Unspecified4: void,
140 D: void = 1000,
141 Unspecified5: i32,
142};
143
144test "union(enum(u32)) with specified and unspecified tag values" {
145 comptime assert(@TagType(@TagType(MultipleChoice2)) == u32);
146 testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
147 comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
148}
149
150fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
151 assert(@enumToInt(@TagType(MultipleChoice2)(x)) == 60);
152 assert(1123 == switch (x) {
153 MultipleChoice2.A => 1,
154 MultipleChoice2.B => 2,
155 MultipleChoice2.C => |v| i32(1000) + v,
156 MultipleChoice2.D => 4,
157 MultipleChoice2.Unspecified1 => 5,
158 MultipleChoice2.Unspecified2 => 6,
159 MultipleChoice2.Unspecified3 => 7,
160 MultipleChoice2.Unspecified4 => 8,
161 MultipleChoice2.Unspecified5 => 9,
162 });
163}
164
165const ExternPtrOrInt = extern union {
166 ptr: *u8,
167 int: u64,
168};
169test "extern union size" {
170 comptime assert(@sizeOf(ExternPtrOrInt) == 8);
171}
172
173const PackedPtrOrInt = packed union {
174 ptr: *u8,
175 int: u64,
176};
177test "extern union size" {
178 comptime assert(@sizeOf(PackedPtrOrInt) == 8);
179}
180
181const ZeroBits = union {
182 OnlyField: void,
183};
184test "union with only 1 field which is void should be zero bits" {
185 comptime assert(@sizeOf(ZeroBits) == 0);
186}
187
188const TheTag = enum {
189 A,
190 B,
191 C,
192};
193const TheUnion = union(TheTag) {
194 A: i32,
195 B: i32,
196 C: i32,
197};
198test "union field access gives the enum values" {
199 assert(TheUnion.A == TheTag.A);
200 assert(TheUnion.B == TheTag.B);
201 assert(TheUnion.C == TheTag.C);
202}
203
204test "cast union to tag type of union" {
205 testCastUnionToTagType(TheUnion{ .B = 1234 });
206 comptime testCastUnionToTagType(TheUnion{ .B = 1234 });
207}
208
209fn testCastUnionToTagType(x: TheUnion) void {
210 assert(TheTag(x) == TheTag.B);
211}
212
213test "cast tag type of union to union" {
214 var x: Value2 = Letter2.B;
215 assert(Letter2(x) == Letter2.B);
216}
217const Letter2 = enum {
218 A,
219 B,
220 C,
221};
222const Value2 = union(Letter2) {
223 A: i32,
224 B,
225 C,
226};
227
228test "implicit cast union to its tag type" {
229 var x: Value2 = Letter2.B;
230 assert(x == Letter2.B);
231 giveMeLetterB(x);
232}
233fn giveMeLetterB(x: Letter2) void {
234 assert(x == Value2.B);
235}
236
237pub const PackThis = union(enum) {
238 Invalid: bool,
239 StringLiteral: u2,
240};
241
242test "constant packed union" {
243 testConstPackedUnion([]PackThis{PackThis{ .StringLiteral = 1 }});
244}
245
246fn testConstPackedUnion(expected_tokens: []const PackThis) void {
247 assert(expected_tokens[0].StringLiteral == 1);
248}
249
250test "switch on union with only 1 field" {
251 var r: PartialInst = undefined;
252 r = PartialInst.Compiled;
253 switch (r) {
254 PartialInst.Compiled => {
255 var z: PartialInstWithPayload = undefined;
256 z = PartialInstWithPayload{ .Compiled = 1234 };
257 switch (z) {
258 PartialInstWithPayload.Compiled => |x| {
259 assert(x == 1234);
260 return;
261 },
262 }
263 },
264 }
265 unreachable;
266}
267
268const PartialInst = union(enum) {
269 Compiled,
270};
271
272const PartialInstWithPayload = union(enum) {
273 Compiled: i32,
274};
275
276test "access a member of tagged union with conflicting enum tag name" {
277 const Bar = union(enum) {
278 A: A,
279 B: B,
280
281 const A = u8;
282 const B = void;
283 };
284
285 comptime assert(Bar.A == u8);
286}
287
288test "tagged union initialization with runtime void" {
289 assert(testTaggedUnionInit({}));
290}
291
292const TaggedUnionWithAVoid = union(enum) {
293 A,
294 B: i32,
295};
296
297fn testTaggedUnionInit(x: var) bool {
298 const y = TaggedUnionWithAVoid{ .A = x };
299 return @TagType(TaggedUnionWithAVoid)(y) == TaggedUnionWithAVoid.A;
300}
301
302pub const UnionEnumNoPayloads = union(enum) {
303 A,
304 B,
305};
306
307test "tagged union with no payloads" {
308 const a = UnionEnumNoPayloads{ .B = {} };
309 switch (a) {
310 @TagType(UnionEnumNoPayloads).A => @panic("wrong"),
311 @TagType(UnionEnumNoPayloads).B => {},
312 }
313}
314
315test "union with only 1 field casted to its enum type" {
316 const Literal = union(enum) {
317 Number: f64,
318 Bool: bool,
319 };
320
321 const Expr = union(enum) {
322 Literal: Literal,
323 };
324
325 var e = Expr{ .Literal = Literal{ .Bool = true } };
326 const Tag = @TagType(Expr);
327 comptime assert(@TagType(Tag) == comptime_int);
328 var t = Tag(e);
329 assert(t == Expr.Literal);
330}
331
332test "union with only 1 field casted to its enum type which has enum value specified" {
333 const Literal = union(enum) {
334 Number: f64,
335 Bool: bool,
336 };
337
338 const Tag = enum {
339 Literal = 33,
340 };
341
342 const Expr = union(Tag) {
343 Literal: Literal,
344 };
345
346 var e = Expr{ .Literal = Literal{ .Bool = true } };
347 comptime assert(@TagType(Tag) == comptime_int);
348 var t = Tag(e);
349 assert(t == Expr.Literal);
350 assert(@enumToInt(t) == 33);
351 comptime assert(@enumToInt(t) == 33);
352}
test/cases/var_args.zig deleted-84
...@@ -1,84 +0,0 @@
1const assert = @import("std").debug.assert;
2
3fn add(args: ...) i32 {
4 var sum = i32(0);
5 {
6 comptime var i: usize = 0;
7 inline while (i < args.len) : (i += 1) {
8 sum += args[i];
9 }
10 }
11 return sum;
12}
13
14test "add arbitrary args" {
15 assert(add(i32(1), i32(2), i32(3), i32(4)) == 10);
16 assert(add(i32(1234)) == 1234);
17 assert(add() == 0);
18}
19
20fn readFirstVarArg(args: ...) void {
21 const value = args[0];
22}
23
24test "send void arg to var args" {
25 readFirstVarArg({});
26}
27
28test "pass args directly" {
29 assert(addSomeStuff(i32(1), i32(2), i32(3), i32(4)) == 10);
30 assert(addSomeStuff(i32(1234)) == 1234);
31 assert(addSomeStuff() == 0);
32}
33
34fn addSomeStuff(args: ...) i32 {
35 return add(args);
36}
37
38test "runtime parameter before var args" {
39 assert(extraFn(10) == 0);
40 assert(extraFn(10, false) == 1);
41 assert(extraFn(10, false, true) == 2);
42
43 // TODO issue #313
44 //comptime {
45 // assert(extraFn(10) == 0);
46 // assert(extraFn(10, false) == 1);
47 // assert(extraFn(10, false, true) == 2);
48 //}
49}
50
51fn extraFn(extra: u32, args: ...) usize {
52 if (args.len >= 1) {
53 assert(args[0] == false);
54 }
55 if (args.len >= 2) {
56 assert(args[1] == true);
57 }
58 return args.len;
59}
60
61const foos = []fn (...) bool{
62 foo1,
63 foo2,
64};
65
66fn foo1(args: ...) bool {
67 return true;
68}
69fn foo2(args: ...) bool {
70 return false;
71}
72
73test "array of var args functions" {
74 assert(foos[0]());
75 assert(!foos[1]());
76}
77
78test "pass zero length array to var args param" {
79 doNothingWithFirstArg("");
80}
81
82fn doNothingWithFirstArg(args: ...) void {
83 const a = args[0];
84}
test/cases/void.zig deleted-30
...@@ -1,30 +0,0 @@
1const assert = @import("std").debug.assert;
2
3const Foo = struct {
4 a: void,
5 b: i32,
6 c: void,
7};
8
9test "compare void with void compile time known" {
10 comptime {
11 const foo = Foo{
12 .a = {},
13 .b = 1,
14 .c = {},
15 };
16 assert(foo.a == {});
17 }
18}
19
20test "iterate over a void slice" {
21 var j: usize = 0;
22 for (times(10)) |_, i| {
23 assert(i == j);
24 j += 1;
25 }
26}
27
28fn times(n: usize) []const void {
29 return ([*]void)(undefined)[0..n];
30}
test/cases/while.zig deleted-227
...@@ -1,227 +0,0 @@
1const assert = @import("std").debug.assert;
2
3test "while loop" {
4 var i: i32 = 0;
5 while (i < 4) {
6 i += 1;
7 }
8 assert(i == 4);
9 assert(whileLoop1() == 1);
10}
11fn whileLoop1() i32 {
12 return whileLoop2();
13}
14fn whileLoop2() i32 {
15 while (true) {
16 return 1;
17 }
18}
19test "static eval while" {
20 assert(static_eval_while_number == 1);
21}
22const static_eval_while_number = staticWhileLoop1();
23fn staticWhileLoop1() i32 {
24 return whileLoop2();
25}
26fn staticWhileLoop2() i32 {
27 while (true) {
28 return 1;
29 }
30}
31
32test "continue and break" {
33 runContinueAndBreakTest();
34 assert(continue_and_break_counter == 8);
35}
36var continue_and_break_counter: i32 = 0;
37fn runContinueAndBreakTest() void {
38 var i: i32 = 0;
39 while (true) {
40 continue_and_break_counter += 2;
41 i += 1;
42 if (i < 4) {
43 continue;
44 }
45 break;
46 }
47 assert(i == 4);
48}
49
50test "return with implicit cast from while loop" {
51 returnWithImplicitCastFromWhileLoopTest() catch unreachable;
52}
53fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {
54 while (true) {
55 return;
56 }
57}
58
59test "while with continue expression" {
60 var sum: i32 = 0;
61 {
62 var i: i32 = 0;
63 while (i < 10) : (i += 1) {
64 if (i == 5) continue;
65 sum += i;
66 }
67 }
68 assert(sum == 40);
69}
70
71test "while with else" {
72 var sum: i32 = 0;
73 var i: i32 = 0;
74 var got_else: i32 = 0;
75 while (i < 10) : (i += 1) {
76 sum += 1;
77 } else {
78 got_else += 1;
79 }
80 assert(sum == 10);
81 assert(got_else == 1);
82}
83
84test "while with optional as condition" {
85 numbers_left = 10;
86 var sum: i32 = 0;
87 while (getNumberOrNull()) |value| {
88 sum += value;
89 }
90 assert(sum == 45);
91}
92
93test "while with optional as condition with else" {
94 numbers_left = 10;
95 var sum: i32 = 0;
96 var got_else: i32 = 0;
97 while (getNumberOrNull()) |value| {
98 sum += value;
99 assert(got_else == 0);
100 } else {
101 got_else += 1;
102 }
103 assert(sum == 45);
104 assert(got_else == 1);
105}
106
107test "while with error union condition" {
108 numbers_left = 10;
109 var sum: i32 = 0;
110 var got_else: i32 = 0;
111 while (getNumberOrErr()) |value| {
112 sum += value;
113 } else |err| {
114 assert(err == error.OutOfNumbers);
115 got_else += 1;
116 }
117 assert(sum == 45);
118 assert(got_else == 1);
119}
120
121var numbers_left: i32 = undefined;
122fn getNumberOrErr() anyerror!i32 {
123 return if (numbers_left == 0) error.OutOfNumbers else x: {
124 numbers_left -= 1;
125 break :x numbers_left;
126 };
127}
128fn getNumberOrNull() ?i32 {
129 return if (numbers_left == 0) null else x: {
130 numbers_left -= 1;
131 break :x numbers_left;
132 };
133}
134
135test "while on optional with else result follow else prong" {
136 const result = while (returnNull()) |value| {
137 break value;
138 } else
139 i32(2);
140 assert(result == 2);
141}
142
143test "while on optional with else result follow break prong" {
144 const result = while (returnOptional(10)) |value| {
145 break value;
146 } else
147 i32(2);
148 assert(result == 10);
149}
150
151test "while on error union with else result follow else prong" {
152 const result = while (returnError()) |value| {
153 break value;
154 } else |err|
155 i32(2);
156 assert(result == 2);
157}
158
159test "while on error union with else result follow break prong" {
160 const result = while (returnSuccess(10)) |value| {
161 break value;
162 } else |err|
163 i32(2);
164 assert(result == 10);
165}
166
167test "while on bool with else result follow else prong" {
168 const result = while (returnFalse()) {
169 break i32(10);
170 } else
171 i32(2);
172 assert(result == 2);
173}
174
175test "while on bool with else result follow break prong" {
176 const result = while (returnTrue()) {
177 break i32(10);
178 } else
179 i32(2);
180 assert(result == 10);
181}
182
183test "break from outer while loop" {
184 testBreakOuter();
185 comptime testBreakOuter();
186}
187
188fn testBreakOuter() void {
189 outer: while (true) {
190 while (true) {
191 break :outer;
192 }
193 }
194}
195
196test "continue outer while loop" {
197 testContinueOuter();
198 comptime testContinueOuter();
199}
200
201fn testContinueOuter() void {
202 var i: usize = 0;
203 outer: while (i < 10) : (i += 1) {
204 while (true) {
205 continue :outer;
206 }
207 }
208}
209
210fn returnNull() ?i32 {
211 return null;
212}
213fn returnOptional(x: i32) ?i32 {
214 return x;
215}
216fn returnError() anyerror!i32 {
217 return error.YouWantedAnError;
218}
219fn returnSuccess(x: i32) anyerror!i32 {
220 return x;
221}
222fn returnFalse() bool {
223 return false;
224}
225fn returnTrue() bool {
226 return true;
227}
test/cases/widening.zig deleted-27
...@@ -1,27 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const mem = std.mem;
4
5test "integer widening" {
6 var a: u8 = 250;
7 var b: u16 = a;
8 var c: u32 = b;
9 var d: u64 = c;
10 var e: u64 = d;
11 var f: u128 = e;
12 assert(f == a);
13}
14
15test "implicit unsigned integer to signed integer" {
16 var a: u8 = 250;
17 var b: i16 = a;
18 assert(b == 250);
19}
20
21test "float widening" {
22 var a: f16 = 12.34;
23 var b: f32 = a;
24 var c: f64 = b;
25 var d: f128 = c;
26 assert(d == a);
27}
test/cli.zig+9-9
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const os = std.os;3const os = std.os;
4const assertOrPanic = std.debug.assertOrPanic;4const testing = std.testing;
55
6var a: *std.mem.Allocator = undefined;6var a: *std.mem.Allocator = undefined;
77
...@@ -27,9 +27,9 @@ pub fn main() !void {...@@ -27,9 +27,9 @@ pub fn main() !void {
27 std.debug.warn("Expected second argument to be cache root directory path\n");27 std.debug.warn("Expected second argument to be cache root directory path\n");
28 return error.InvalidArgs;28 return error.InvalidArgs;
29 });29 });
30 const zig_exe = try os.path.resolve(a, zig_exe_rel);30 const zig_exe = try os.path.resolve(a, [][]const u8{zig_exe_rel});
3131
32 const dir_path = try os.path.join(a, cache_root, "clitest");32 const dir_path = try os.path.join(a, [][]const u8{ cache_root, "clitest" });
33 const TestFn = fn ([]const u8, []const u8) anyerror!void;33 const TestFn = fn ([]const u8, []const u8) anyerror!void;
34 const test_fns = []TestFn{34 const test_fns = []TestFn{
35 testZigInitLib,35 testZigInitLib,
...@@ -87,20 +87,20 @@ fn exec(cwd: []const u8, argv: []const []const u8) !os.ChildProcess.ExecResult {...@@ -87,20 +87,20 @@ fn exec(cwd: []const u8, argv: []const []const u8) !os.ChildProcess.ExecResult {
87fn testZigInitLib(zig_exe: []const u8, dir_path: []const u8) !void {87fn testZigInitLib(zig_exe: []const u8, dir_path: []const u8) !void {
88 _ = try exec(dir_path, [][]const u8{ zig_exe, "init-lib" });88 _ = try exec(dir_path, [][]const u8{ zig_exe, "init-lib" });
89 const test_result = try exec(dir_path, [][]const u8{ zig_exe, "build", "test" });89 const test_result = try exec(dir_path, [][]const u8{ zig_exe, "build", "test" });
90 assertOrPanic(std.mem.endsWith(u8, test_result.stderr, "All tests passed.\n"));90 testing.expect(std.mem.endsWith(u8, test_result.stderr, "All tests passed.\n"));
91}91}
9292
93fn testZigInitExe(zig_exe: []const u8, dir_path: []const u8) !void {93fn testZigInitExe(zig_exe: []const u8, dir_path: []const u8) !void {
94 _ = try exec(dir_path, [][]const u8{ zig_exe, "init-exe" });94 _ = try exec(dir_path, [][]const u8{ zig_exe, "init-exe" });
95 const run_result = try exec(dir_path, [][]const u8{ zig_exe, "build", "run" });95 const run_result = try exec(dir_path, [][]const u8{ zig_exe, "build", "run" });
96 assertOrPanic(std.mem.eql(u8, run_result.stderr, "All your base are belong to us.\n"));96 testing.expect(std.mem.eql(u8, run_result.stderr, "All your base are belong to us.\n"));
97}97}
9898
99fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void {99fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void {
100 if (builtin.os != builtin.Os.linux or builtin.arch != builtin.Arch.x86_64) return;100 if (builtin.os != builtin.Os.linux or builtin.arch != builtin.Arch.x86_64) return;
101101
102 const example_zig_path = try os.path.join(a, dir_path, "example.zig");102 const example_zig_path = try os.path.join(a, [][]const u8{ dir_path, "example.zig" });
103 const example_s_path = try os.path.join(a, dir_path, "example.s");103 const example_s_path = try os.path.join(a, [][]const u8{ dir_path, "example.s" });
104104
105 try std.io.writeFile(example_zig_path,105 try std.io.writeFile(example_zig_path,
106 \\// Type your code here, or load an example.106 \\// Type your code here, or load an example.
...@@ -126,6 +126,6 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void {...@@ -126,6 +126,6 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void {
126 _ = try exec(dir_path, args);126 _ = try exec(dir_path, args);
127127
128 const out_asm = try std.io.readFileAlloc(a, example_s_path);128 const out_asm = try std.io.readFileAlloc(a, example_s_path);
129 assertOrPanic(std.mem.indexOf(u8, out_asm, "square:") != null);129 testing.expect(std.mem.indexOf(u8, out_asm, "square:") != null);
130 assertOrPanic(std.mem.indexOf(u8, out_asm, "imul\tedi, edi") != null);130 testing.expect(std.mem.indexOf(u8, out_asm, "imul\tedi, edi") != null);
131}131}
test/compile_errors.zig+366-66
...@@ -1,6 +1,270 @@...@@ -1,6 +1,270 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
22
3pub fn addCases(cases: *tests.CompileErrorContext) void {3pub fn addCases(cases: *tests.CompileErrorContext) void {
4 cases.addTest(
5 "C pointer to c_void",
6 \\export fn a() void {
7 \\ var x: *c_void = undefined;
8 \\ var y: [*c]c_void = x;
9 \\}
10 ,
11 ".tmp_source.zig:3:12: error: C pointers cannot point opaque types",
12 );
13
14 cases.addTest(
15 "directly embedding opaque type in struct and union",
16 \\const O = @OpaqueType();
17 \\const Foo = struct {
18 \\ o: O,
19 \\};
20 \\const Bar = union {
21 \\ One: i32,
22 \\ Two: O,
23 \\};
24 \\export fn a() void {
25 \\ var foo: Foo = undefined;
26 \\}
27 \\export fn b() void {
28 \\ var bar: Bar = undefined;
29 \\}
30 ,
31 ".tmp_source.zig:3:8: error: opaque types have unknown size and therefore cannot be directly embedded in structs",
32 ".tmp_source.zig:7:10: error: opaque types have unknown size and therefore cannot be directly embedded in unions",
33 );
34
35 cases.addTest(
36 "implicit cast between C pointer and Zig pointer - bad const/align/child",
37 \\export fn a() void {
38 \\ var x: [*c]u8 = undefined;
39 \\ var y: *align(4) u8 = x;
40 \\}
41 \\export fn b() void {
42 \\ var x: [*c]const u8 = undefined;
43 \\ var y: *u8 = x;
44 \\}
45 \\export fn c() void {
46 \\ var x: [*c]u8 = undefined;
47 \\ var y: *u32 = x;
48 \\}
49 \\export fn d() void {
50 \\ var y: *align(1) u32 = undefined;
51 \\ var x: [*c]u32 = y;
52 \\}
53 \\export fn e() void {
54 \\ var y: *const u8 = undefined;
55 \\ var x: [*c]u8 = y;
56 \\}
57 \\export fn f() void {
58 \\ var y: *u8 = undefined;
59 \\ var x: [*c]u32 = y;
60 \\}
61 ,
62 ".tmp_source.zig:3:27: error: cast increases pointer alignment",
63 ".tmp_source.zig:7:18: error: cast discards const qualifier",
64 ".tmp_source.zig:11:19: error: expected type '*u32', found '[*c]u8'",
65 ".tmp_source.zig:11:19: note: pointer type child 'u8' cannot cast into pointer type child 'u32'",
66 ".tmp_source.zig:15:22: error: cast increases pointer alignment",
67 ".tmp_source.zig:19:21: error: cast discards const qualifier",
68 ".tmp_source.zig:23:22: error: expected type '[*c]u32', found '*u8'",
69 );
70
71 cases.addTest(
72 "implicit casting null c pointer to zig pointer",
73 \\comptime {
74 \\ var c_ptr: [*c]u8 = 0;
75 \\ var zig_ptr: *u8 = c_ptr;
76 \\}
77 ,
78 ".tmp_source.zig:3:24: error: null pointer casted to type '*u8'",
79 );
80
81 cases.addTest(
82 "implicit casting undefined c pointer to zig pointer",
83 \\comptime {
84 \\ var c_ptr: [*c]u8 = undefined;
85 \\ var zig_ptr: *u8 = c_ptr;
86 \\}
87 ,
88 ".tmp_source.zig:3:24: error: use of undefined value here causes undefined behavior",
89 );
90
91 cases.addTest(
92 "implicit casting C pointers which would mess up null semantics",
93 \\export fn entry() void {
94 \\ var slice: []const u8 = "aoeu";
95 \\ const opt_many_ptr: [*]const u8 = slice.ptr;
96 \\ var ptr_opt_many_ptr = &opt_many_ptr;
97 \\ var c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr;
98 \\ ptr_opt_many_ptr = c_ptr;
99 \\}
100 \\export fn entry2() void {
101 \\ var buf: [4]u8 = "aoeu";
102 \\ var slice: []u8 = &buf;
103 \\ var opt_many_ptr: [*]u8 = slice.ptr;
104 \\ var ptr_opt_many_ptr = &opt_many_ptr;
105 \\ var c_ptr: [*c][*c]const u8 = ptr_opt_many_ptr;
106 \\}
107 ,
108 ".tmp_source.zig:6:24: error: expected type '*const [*]const u8', found '[*c]const [*c]const u8'",
109 ".tmp_source.zig:6:24: note: pointer type child '[*c]const u8' cannot cast into pointer type child '[*]const u8'",
110 ".tmp_source.zig:6:24: note: '[*c]const u8' could have null values which are illegal in type '[*]const u8'",
111 ".tmp_source.zig:13:35: error: expected type '[*c][*c]const u8', found '*[*]u8'",
112 ".tmp_source.zig:13:35: note: pointer type child '[*]u8' cannot cast into pointer type child '[*c]const u8'",
113 ".tmp_source.zig:13:35: note: mutable '[*c]const u8' allows illegal null values stored to type '[*]u8'",
114 );
115
116 cases.addTest(
117 "implicit casting too big integers to C pointers",
118 \\export fn a() void {
119 \\ var ptr: [*c]u8 = (1 << 64) + 1;
120 \\}
121 \\export fn b() void {
122 \\ var x: @IntType(false, 65) = 0x1234;
123 \\ var ptr: [*c]u8 = x;
124 \\}
125 ,
126 ".tmp_source.zig:2:33: error: integer value 71615590737044764481 cannot be implicitly casted to type 'usize'",
127 ".tmp_source.zig:6:23: error: integer type 'u65' too big for implicit @intToPtr to type '[*c]u8'",
128 );
129
130 cases.addTest(
131 "C pointer pointing to non C ABI compatible type or has align attr",
132 \\const Foo = struct {};
133 \\export fn a() void {
134 \\ const T = [*c]Foo;
135 \\}
136 ,
137 ".tmp_source.zig:3:15: error: C pointers cannot point to non-C-ABI-compatible type 'Foo'",
138 );
139
140 cases.addTest(
141 "@truncate undefined value",
142 \\export fn entry() void {
143 \\ var z = @truncate(u8, u16(undefined));
144 \\}
145 ,
146 ".tmp_source.zig:2:30: error: use of undefined value here causes undefined behavior",
147 );
148
149 cases.addTest(
150 "return invalid type from test",
151 \\test "example" { return 1; }
152 ,
153 ".tmp_source.zig:1:25: error: integer value 1 cannot be implicitly casted to type 'void'",
154 );
155
156 cases.add(
157 "threadlocal qualifier on const",
158 \\threadlocal const x: i32 = 1234;
159 \\export fn entry() i32 {
160 \\ return x;
161 \\}
162 ,
163 ".tmp_source.zig:1:13: error: threadlocal variable cannot be constant",
164 );
165
166 cases.add(
167 "threadlocal qualifier on local variable",
168 \\export fn entry() void {
169 \\ threadlocal var x: i32 = 1234;
170 \\}
171 ,
172 ".tmp_source.zig:2:5: error: function-local variable 'x' cannot be threadlocal",
173 );
174
175 cases.add(
176 "@bitCast same size but bit count mismatch",
177 \\export fn entry(byte: u8) void {
178 \\ var oops = @bitCast(u7, byte);
179 \\}
180 ,
181 ".tmp_source.zig:2:16: error: destination type 'u7' has 7 bits but source type 'u8' has 8 bits",
182 );
183
184 cases.add(
185 "attempted `&&`",
186 \\export fn entry(a: bool, b: bool) i32 {
187 \\ if (a && b) {
188 \\ return 1234;
189 \\ }
190 \\ return 5678;
191 \\}
192 ,
193 ".tmp_source.zig:2:12: error: `&&` is invalid. Note that `and` is boolean AND.",
194 );
195
196 cases.add(
197 "attempted `||` on boolean values",
198 \\export fn entry(a: bool, b: bool) i32 {
199 \\ if (a || b) {
200 \\ return 1234;
201 \\ }
202 \\ return 5678;
203 \\}
204 ,
205 ".tmp_source.zig:2:9: error: expected error set type, found 'bool'",
206 ".tmp_source.zig:2:11: note: `||` merges error sets; `or` performs boolean OR",
207 );
208
209 cases.add(
210 "compile log a pointer to an opaque value",
211 \\export fn entry() void {
212 \\ @compileLog(@ptrCast(*const c_void, &entry));
213 \\}
214 ,
215 ".tmp_source.zig:2:5: error: found compile log statement",
216 );
217
218 cases.add(
219 "duplicate boolean switch value",
220 \\comptime {
221 \\ const x = switch (true) {
222 \\ true => false,
223 \\ false => true,
224 \\ true => false,
225 \\ };
226 \\}
227 \\comptime {
228 \\ const x = switch (true) {
229 \\ false => true,
230 \\ true => false,
231 \\ false => true,
232 \\ };
233 \\}
234 ,
235 ".tmp_source.zig:5:9: error: duplicate switch value",
236 ".tmp_source.zig:12:9: error: duplicate switch value",
237 );
238
239 cases.add(
240 "missing boolean switch value",
241 \\comptime {
242 \\ const x = switch (true) {
243 \\ true => false,
244 \\ };
245 \\}
246 \\comptime {
247 \\ const x = switch (true) {
248 \\ false => true,
249 \\ };
250 \\}
251 ,
252 ".tmp_source.zig:2:15: error: switch must handle all possibilities",
253 ".tmp_source.zig:7:15: error: switch must handle all possibilities",
254 );
255
256 cases.add(
257 "reading past end of pointer casted array",
258 \\comptime {
259 \\ const array = "aoeu";
260 \\ const slice = array[2..];
261 \\ const int_ptr = @ptrCast(*const u24, slice.ptr);
262 \\ const deref = int_ptr.*;
263 \\}
264 ,
265 ".tmp_source.zig:5:26: error: attempt to read 3 bytes from [4]u8 at index 2 which is 2 bytes",
266 );
267
4 cases.add(268 cases.add(
5 "error note for function parameter incompatibility",269 "error note for function parameter incompatibility",
6 \\fn do_the_thing(func: fn (arg: i32) void) void {}270 \\fn do_the_thing(func: fn (arg: i32) void) void {}
...@@ -82,13 +346,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -82,13 +346,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
82 );346 );
83347
84 cases.add(348 cases.add(
85 "Panic declared with wrong type signature in tests",349 "wrong panic signature, runtime function",
86 \\test "" {}350 \\test "" {}
87 \\351 \\
88 \\pub fn panic() void {}352 \\pub fn panic() void {}
89 \\353 \\
90 ,354 ,
91 ".tmp_source.zig:3:5: error: expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found 'fn() void'",355 ".tmp_source.zig:3:5: error: expected type 'fn([]const u8, ?*StackTrace) noreturn', found 'fn() void'",
356 );
357
358 cases.add(
359 "wrong panic signature, generic function",
360 \\pub fn panic(comptime msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
361 \\ while (true) {}
362 \\}
363 ,
364 ".tmp_source.zig:1:5: error: expected type 'fn([]const u8, ?*StackTrace) noreturn', found 'fn([]const u8,var)var'",
365 ".tmp_source.zig:1:5: note: only one of the functions is generic",
92 );366 );
93367
94 cases.add(368 cases.add(
...@@ -208,8 +482,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -208,8 +482,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
208 \\ const Errors = error{} || u16;482 \\ const Errors = error{} || u16;
209 \\}483 \\}
210 ,484 ,
211 ".tmp_source.zig:2:20: error: expected error set type, found 'u8'",485 ".tmp_source.zig:2:20: error: expected error set type, found type 'u8'",
212 ".tmp_source.zig:5:31: error: expected error set type, found 'u16'",486 ".tmp_source.zig:2:23: note: `||` merges error sets; `or` performs boolean OR",
487 ".tmp_source.zig:5:31: error: expected error set type, found type 'u16'",
488 ".tmp_source.zig:5:28: note: `||` merges error sets; `or` performs boolean OR",
213 );489 );
214490
215 cases.add(491 cases.add(
...@@ -238,7 +514,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -238,7 +514,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
238 \\ f(i32);514 \\ f(i32);
239 \\}515 \\}
240 ,516 ,
241 ".tmp_source.zig:4:5: error: use of undefined value",517 ".tmp_source.zig:4:5: error: use of undefined value here causes undefined behavior",
242 );518 );
243519
244 cases.add(520 cases.add(
...@@ -638,7 +914,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -638,7 +914,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
638 \\ command.exec();914 \\ command.exec();
639 \\}915 \\}
640 ,916 ,
641 ".tmp_source.zig:6:12: error: use of undefined value",917 ".tmp_source.zig:6:12: error: use of undefined value here causes undefined behavior",
642 );918 );
643919
644 cases.add(920 cases.add(
...@@ -651,7 +927,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -651,7 +927,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
651 \\ command.exec();927 \\ command.exec();
652 \\}928 \\}
653 ,929 ,
654 ".tmp_source.zig:6:12: error: use of undefined value",930 ".tmp_source.zig:6:12: error: use of undefined value here causes undefined behavior",
655 );931 );
656932
657 cases.add(933 cases.add(
...@@ -2559,7 +2835,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2559,7 +2835,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2559 \\2835 \\
2560 \\export fn entry() usize { return @sizeOf(@typeOf(foo)); }2836 \\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
2561 ,2837 ,
2562 ".tmp_source.zig:1:13: error: newline not allowed in string literal",2838 ".tmp_source.zig:1:15: error: newline not allowed in string literal",
2563 );2839 );
25642840
2565 cases.add(2841 cases.add(
...@@ -2622,7 +2898,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2622,7 +2898,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2622 \\2898 \\
2623 \\export fn entry() usize { return @sizeOf(@typeOf(x)); }2899 \\export fn entry() usize { return @sizeOf(@typeOf(x)); }
2624 ,2900 ,
2625 ".tmp_source.zig:1:15: error: use of undefined value",2901 ".tmp_source.zig:1:15: error: use of undefined value here causes undefined behavior",
2626 );2902 );
26272903
2628 cases.add(2904 cases.add(
...@@ -2632,7 +2908,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2632,7 +2908,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2632 \\ _ = a / a;2908 \\ _ = a / a;
2633 \\}2909 \\}
2634 ,2910 ,
2635 ".tmp_source.zig:3:9: error: use of undefined value",2911 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2636 );2912 );
26372913
2638 cases.add(2914 cases.add(
...@@ -2642,7 +2918,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2642,7 +2918,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2642 \\ a /= a;2918 \\ a /= a;
2643 \\}2919 \\}
2644 ,2920 ,
2645 ".tmp_source.zig:3:5: error: use of undefined value",2921 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
2646 );2922 );
26472923
2648 cases.add(2924 cases.add(
...@@ -2652,7 +2928,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2652,7 +2928,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2652 \\ _ = a % a;2928 \\ _ = a % a;
2653 \\}2929 \\}
2654 ,2930 ,
2655 ".tmp_source.zig:3:9: error: use of undefined value",2931 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2656 );2932 );
26572933
2658 cases.add(2934 cases.add(
...@@ -2662,7 +2938,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2662,7 +2938,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2662 \\ a %= a;2938 \\ a %= a;
2663 \\}2939 \\}
2664 ,2940 ,
2665 ".tmp_source.zig:3:5: error: use of undefined value",2941 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
2666 );2942 );
26672943
2668 cases.add(2944 cases.add(
...@@ -2672,7 +2948,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2672,7 +2948,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2672 \\ _ = a + a;2948 \\ _ = a + a;
2673 \\}2949 \\}
2674 ,2950 ,
2675 ".tmp_source.zig:3:9: error: use of undefined value",2951 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2676 );2952 );
26772953
2678 cases.add(2954 cases.add(
...@@ -2682,7 +2958,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2682,7 +2958,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2682 \\ a += a;2958 \\ a += a;
2683 \\}2959 \\}
2684 ,2960 ,
2685 ".tmp_source.zig:3:5: error: use of undefined value",2961 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
2686 );2962 );
26872963
2688 cases.add(2964 cases.add(
...@@ -2692,7 +2968,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2692,7 +2968,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2692 \\ _ = a +% a;2968 \\ _ = a +% a;
2693 \\}2969 \\}
2694 ,2970 ,
2695 ".tmp_source.zig:3:9: error: use of undefined value",2971 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2696 );2972 );
26972973
2698 cases.add(2974 cases.add(
...@@ -2702,7 +2978,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2702,7 +2978,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2702 \\ a +%= a;2978 \\ a +%= a;
2703 \\}2979 \\}
2704 ,2980 ,
2705 ".tmp_source.zig:3:5: error: use of undefined value",2981 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
2706 );2982 );
27072983
2708 cases.add(2984 cases.add(
...@@ -2712,7 +2988,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2712,7 +2988,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2712 \\ _ = a - a;2988 \\ _ = a - a;
2713 \\}2989 \\}
2714 ,2990 ,
2715 ".tmp_source.zig:3:9: error: use of undefined value",2991 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2716 );2992 );
27172993
2718 cases.add(2994 cases.add(
...@@ -2722,7 +2998,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2722,7 +2998,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2722 \\ a -= a;2998 \\ a -= a;
2723 \\}2999 \\}
2724 ,3000 ,
2725 ".tmp_source.zig:3:5: error: use of undefined value",3001 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
2726 );3002 );
27273003
2728 cases.add(3004 cases.add(
...@@ -2732,7 +3008,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2732,7 +3008,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2732 \\ _ = a -% a;3008 \\ _ = a -% a;
2733 \\}3009 \\}
2734 ,3010 ,
2735 ".tmp_source.zig:3:9: error: use of undefined value",3011 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2736 );3012 );
27373013
2738 cases.add(3014 cases.add(
...@@ -2742,7 +3018,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2742,7 +3018,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2742 \\ a -%= a;3018 \\ a -%= a;
2743 \\}3019 \\}
2744 ,3020 ,
2745 ".tmp_source.zig:3:5: error: use of undefined value",3021 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
2746 );3022 );
27473023
2748 cases.add(3024 cases.add(
...@@ -2752,7 +3028,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2752,7 +3028,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2752 \\ _ = a * a;3028 \\ _ = a * a;
2753 \\}3029 \\}
2754 ,3030 ,
2755 ".tmp_source.zig:3:9: error: use of undefined value",3031 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2756 );3032 );
27573033
2758 cases.add(3034 cases.add(
...@@ -2762,7 +3038,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2762,7 +3038,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2762 \\ a *= a;3038 \\ a *= a;
2763 \\}3039 \\}
2764 ,3040 ,
2765 ".tmp_source.zig:3:5: error: use of undefined value",3041 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
2766 );3042 );
27673043
2768 cases.add(3044 cases.add(
...@@ -2772,7 +3048,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2772,7 +3048,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2772 \\ _ = a *% a;3048 \\ _ = a *% a;
2773 \\}3049 \\}
2774 ,3050 ,
2775 ".tmp_source.zig:3:9: error: use of undefined value",3051 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2776 );3052 );
27773053
2778 cases.add(3054 cases.add(
...@@ -2782,7 +3058,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2782,7 +3058,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2782 \\ a *%= a;3058 \\ a *%= a;
2783 \\}3059 \\}
2784 ,3060 ,
2785 ".tmp_source.zig:3:5: error: use of undefined value",3061 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
2786 );3062 );
27873063
2788 cases.add(3064 cases.add(
...@@ -2792,7 +3068,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2792,7 +3068,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2792 \\ _ = a << 2;3068 \\ _ = a << 2;
2793 \\}3069 \\}
2794 ,3070 ,
2795 ".tmp_source.zig:3:9: error: use of undefined value",3071 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2796 );3072 );
27973073
2798 cases.add(3074 cases.add(
...@@ -2802,7 +3078,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2802,7 +3078,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2802 \\ a <<= 2;3078 \\ a <<= 2;
2803 \\}3079 \\}
2804 ,3080 ,
2805 ".tmp_source.zig:3:5: error: use of undefined value",3081 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
2806 );3082 );
28073083
2808 cases.add(3084 cases.add(
...@@ -2812,7 +3088,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2812,7 +3088,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2812 \\ _ = a >> 2;3088 \\ _ = a >> 2;
2813 \\}3089 \\}
2814 ,3090 ,
2815 ".tmp_source.zig:3:9: error: use of undefined value",3091 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2816 );3092 );
28173093
2818 cases.add(3094 cases.add(
...@@ -2822,7 +3098,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2822,7 +3098,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2822 \\ a >>= 2;3098 \\ a >>= 2;
2823 \\}3099 \\}
2824 ,3100 ,
2825 ".tmp_source.zig:3:5: error: use of undefined value",3101 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
2826 );3102 );
28273103
2828 cases.add(3104 cases.add(
...@@ -2832,7 +3108,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2832,7 +3108,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2832 \\ _ = a & a;3108 \\ _ = a & a;
2833 \\}3109 \\}
2834 ,3110 ,
2835 ".tmp_source.zig:3:9: error: use of undefined value",3111 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2836 );3112 );
28373113
2838 cases.add(3114 cases.add(
...@@ -2842,7 +3118,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2842,7 +3118,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2842 \\ a &= a;3118 \\ a &= a;
2843 \\}3119 \\}
2844 ,3120 ,
2845 ".tmp_source.zig:3:5: error: use of undefined value",3121 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
2846 );3122 );
28473123
2848 cases.add(3124 cases.add(
...@@ -2852,7 +3128,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2852,7 +3128,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2852 \\ _ = a | a;3128 \\ _ = a | a;
2853 \\}3129 \\}
2854 ,3130 ,
2855 ".tmp_source.zig:3:9: error: use of undefined value",3131 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2856 );3132 );
28573133
2858 cases.add(3134 cases.add(
...@@ -2862,7 +3138,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2862,7 +3138,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2862 \\ a |= a;3138 \\ a |= a;
2863 \\}3139 \\}
2864 ,3140 ,
2865 ".tmp_source.zig:3:5: error: use of undefined value",3141 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
2866 );3142 );
28673143
2868 cases.add(3144 cases.add(
...@@ -2872,7 +3148,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2872,7 +3148,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2872 \\ _ = a ^ a;3148 \\ _ = a ^ a;
2873 \\}3149 \\}
2874 ,3150 ,
2875 ".tmp_source.zig:3:9: error: use of undefined value",3151 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2876 );3152 );
28773153
2878 cases.add(3154 cases.add(
...@@ -2882,7 +3158,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2882,7 +3158,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2882 \\ a ^= a;3158 \\ a ^= a;
2883 \\}3159 \\}
2884 ,3160 ,
2885 ".tmp_source.zig:3:5: error: use of undefined value",3161 ".tmp_source.zig:3:5: error: use of undefined value here causes undefined behavior",
2886 );3162 );
28873163
2888 cases.add(3164 cases.add(
...@@ -2892,7 +3168,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2892,7 +3168,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2892 \\ _ = a == a;3168 \\ _ = a == a;
2893 \\}3169 \\}
2894 ,3170 ,
2895 ".tmp_source.zig:3:9: error: use of undefined value",3171 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2896 );3172 );
28973173
2898 cases.add(3174 cases.add(
...@@ -2902,7 +3178,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2902,7 +3178,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2902 \\ _ = a != a;3178 \\ _ = a != a;
2903 \\}3179 \\}
2904 ,3180 ,
2905 ".tmp_source.zig:3:9: error: use of undefined value",3181 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2906 );3182 );
29073183
2908 cases.add(3184 cases.add(
...@@ -2912,7 +3188,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2912,7 +3188,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2912 \\ _ = a > a;3188 \\ _ = a > a;
2913 \\}3189 \\}
2914 ,3190 ,
2915 ".tmp_source.zig:3:9: error: use of undefined value",3191 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2916 );3192 );
29173193
2918 cases.add(3194 cases.add(
...@@ -2922,7 +3198,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2922,7 +3198,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2922 \\ _ = a >= a;3198 \\ _ = a >= a;
2923 \\}3199 \\}
2924 ,3200 ,
2925 ".tmp_source.zig:3:9: error: use of undefined value",3201 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2926 );3202 );
29273203
2928 cases.add(3204 cases.add(
...@@ -2932,7 +3208,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2932,7 +3208,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2932 \\ _ = a < a;3208 \\ _ = a < a;
2933 \\}3209 \\}
2934 ,3210 ,
2935 ".tmp_source.zig:3:9: error: use of undefined value",3211 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2936 );3212 );
29373213
2938 cases.add(3214 cases.add(
...@@ -2942,7 +3218,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2942,7 +3218,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2942 \\ _ = a <= a;3218 \\ _ = a <= a;
2943 \\}3219 \\}
2944 ,3220 ,
2945 ".tmp_source.zig:3:9: error: use of undefined value",3221 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2946 );3222 );
29473223
2948 cases.add(3224 cases.add(
...@@ -2952,7 +3228,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2952,7 +3228,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2952 \\ _ = a and a;3228 \\ _ = a and a;
2953 \\}3229 \\}
2954 ,3230 ,
2955 ".tmp_source.zig:3:9: error: use of undefined value",3231 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2956 );3232 );
29573233
2958 cases.add(3234 cases.add(
...@@ -2962,7 +3238,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2962,7 +3238,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2962 \\ _ = a or a;3238 \\ _ = a or a;
2963 \\}3239 \\}
2964 ,3240 ,
2965 ".tmp_source.zig:3:9: error: use of undefined value",3241 ".tmp_source.zig:3:9: error: use of undefined value here causes undefined behavior",
2966 );3242 );
29673243
2968 cases.add(3244 cases.add(
...@@ -2972,7 +3248,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2972,7 +3248,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2972 \\ _ = -a;3248 \\ _ = -a;
2973 \\}3249 \\}
2974 ,3250 ,
2975 ".tmp_source.zig:3:10: error: use of undefined value",3251 ".tmp_source.zig:3:10: error: use of undefined value here causes undefined behavior",
2976 );3252 );
29773253
2978 cases.add(3254 cases.add(
...@@ -2982,7 +3258,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2982,7 +3258,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2982 \\ _ = -%a;3258 \\ _ = -%a;
2983 \\}3259 \\}
2984 ,3260 ,
2985 ".tmp_source.zig:3:11: error: use of undefined value",3261 ".tmp_source.zig:3:11: error: use of undefined value here causes undefined behavior",
2986 );3262 );
29873263
2988 cases.add(3264 cases.add(
...@@ -2992,7 +3268,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2992,7 +3268,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2992 \\ _ = ~a;3268 \\ _ = ~a;
2993 \\}3269 \\}
2994 ,3270 ,
2995 ".tmp_source.zig:3:10: error: use of undefined value",3271 ".tmp_source.zig:3:10: error: use of undefined value here causes undefined behavior",
2996 );3272 );
29973273
2998 cases.add(3274 cases.add(
...@@ -3002,7 +3278,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3002,7 +3278,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3002 \\ _ = !a;3278 \\ _ = !a;
3003 \\}3279 \\}
3004 ,3280 ,
3005 ".tmp_source.zig:3:10: error: use of undefined value",3281 ".tmp_source.zig:3:10: error: use of undefined value here causes undefined behavior",
3006 );3282 );
30073283
3008 cases.add(3284 cases.add(
...@@ -3012,7 +3288,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3012,7 +3288,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3012 \\ _ = a orelse false;3288 \\ _ = a orelse false;
3013 \\}3289 \\}
3014 ,3290 ,
3015 ".tmp_source.zig:3:11: error: use of undefined value",3291 ".tmp_source.zig:3:11: error: use of undefined value here causes undefined behavior",
3016 );3292 );
30173293
3018 cases.add(3294 cases.add(
...@@ -3022,7 +3298,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3022,7 +3298,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3022 \\ _ = a catch |err| false;3298 \\ _ = a catch |err| false;
3023 \\}3299 \\}
3024 ,3300 ,
3025 ".tmp_source.zig:3:11: error: use of undefined value",3301 ".tmp_source.zig:3:11: error: use of undefined value here causes undefined behavior",
3026 );3302 );
30273303
3028 cases.add(3304 cases.add(
...@@ -3134,7 +3410,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3134,7 +3410,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3134 \\ return 2;3410 \\ return 2;
3135 \\}3411 \\}
3136 ,3412 ,
3137 ".tmp_source.zig:2:15: error: unable to infer expression type",3413 ".tmp_source.zig:2:15: error: values of type 'comptime_int' must be comptime known",
3138 );3414 );
31393415
3140 cases.add(3416 cases.add(
...@@ -3214,7 +3490,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3214,7 +3490,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3214 cases.add(3490 cases.add(
3215 "truncate sign mismatch",3491 "truncate sign mismatch",
3216 \\fn f() i8 {3492 \\fn f() i8 {
3217 \\ const x: u32 = 10;3493 \\ var x: u32 = 10;
3218 \\ return @truncate(i8, x);3494 \\ return @truncate(i8, x);
3219 \\}3495 \\}
3220 \\3496 \\
...@@ -3480,7 +3756,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3480,7 +3756,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3480 \\3756 \\
3481 \\export fn entry() usize { return @sizeOf(@typeOf(a)); }3757 \\export fn entry() usize { return @sizeOf(@typeOf(a)); }
3482 ,3758 ,
3483 ".tmp_source.zig:2:11: error: expected type, found 'i32'",3759 ".tmp_source.zig:2:11: error: expected type 'type', found 'i32'",
3484 );3760 );
34853761
3486 cases.add(3762 cases.add(
...@@ -4424,20 +4700,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4424,20 +4700,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4424 ".tmp_source.zig:2:24: error: expected [2]u8 literal, found [3]u8 literal",4700 ".tmp_source.zig:2:24: error: expected [2]u8 literal, found [3]u8 literal",
4425 );4701 );
44264702
4427 cases.add(
4428 "@setEvalBranchQuota in non-root comptime execution context",
4429 \\comptime {
4430 \\ foo();
4431 \\}
4432 \\fn foo() void {
4433 \\ @setEvalBranchQuota(1001);
4434 \\}
4435 ,
4436 ".tmp_source.zig:5:5: error: @setEvalBranchQuota must be called from the top of the comptime stack",
4437 ".tmp_source.zig:2:8: note: called from here",
4438 ".tmp_source.zig:1:10: note: called from here",
4439 );
4440
4441 cases.add(4703 cases.add(
4442 "wrong pointer implicitly casted to pointer to @OpaqueType()",4704 "wrong pointer implicitly casted to pointer to @OpaqueType()",
4443 \\const Derp = @OpaqueType();4705 \\const Derp = @OpaqueType();
...@@ -5272,4 +5534,42 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5272,4 +5534,42 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5272 ,5534 ,
5273 ".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_float",5535 ".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_float",
5274 );5536 );
5537
5538 cases.add(
5539 "runtime assignment to comptime struct type",
5540 \\const Foo = struct {
5541 \\ Bar: u8,
5542 \\ Baz: type,
5543 \\};
5544 \\export fn f() void {
5545 \\ var x: u8 = 0;
5546 \\ const foo = Foo { .Bar = x, .Baz = u8 };
5547 \\}
5548 ,
5549 ".tmp_source.zig:7:30: error: unable to evaluate constant expression",
5550 );
5551
5552 cases.add(
5553 "runtime assignment to comptime union type",
5554 \\const Foo = union {
5555 \\ Bar: u8,
5556 \\ Baz: type,
5557 \\};
5558 \\export fn f() void {
5559 \\ var x: u8 = 0;
5560 \\ const foo = Foo { .Bar = x };
5561 \\}
5562 ,
5563 ".tmp_source.zig:7:30: error: unable to evaluate constant expression",
5564 );
5565
5566 cases.addTest(
5567 "nested vectors",
5568 \\export fn entry() void {
5569 \\ const V = @Vector(4, @Vector(4, u8));
5570 \\ var v: V = undefined;
5571 \\}
5572 ,
5573 ".tmp_source.zig:2:26: error: vector element type must be integer, float, or pointer; '@Vector(4, u8)' is invalid",
5574 );
5275}5575}
test/runtime_safety.zig+41
...@@ -1,6 +1,16 @@...@@ -1,6 +1,16 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
22
3pub fn addCases(cases: *tests.CompareOutputContext) void {3pub fn addCases(cases: *tests.CompareOutputContext) void {
4 cases.addRuntimeSafety("pointer casting null to non-optional pointer",
5 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
6 \\ @import("std").os.exit(126);
7 \\}
8 \\pub fn main() void {
9 \\ var c_ptr: [*c]u8 = 0;
10 \\ var zig_ptr: *u8 = c_ptr;
11 \\}
12 );
13
4 cases.addRuntimeSafety("@intToEnum - no matching tag value",14 cases.addRuntimeSafety("@intToEnum - no matching tag value",
5 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {15 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
6 \\ @import("std").os.exit(126);16 \\ @import("std").os.exit(126);
...@@ -94,6 +104,20 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -94,6 +104,20 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
94 \\}104 \\}
95 );105 );
96106
107 cases.addRuntimeSafety("vector integer addition overflow",
108 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
109 \\ @import("std").os.exit(126);
110 \\}
111 \\pub fn main() void {
112 \\ var a: @Vector(4, i32) = []i32{ 1, 2, 2147483643, 4 };
113 \\ var b: @Vector(4, i32) = []i32{ 5, 6, 7, 8 };
114 \\ const x = add(a, b);
115 \\}
116 \\fn add(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
117 \\ return a + b;
118 \\}
119 );
120
97 cases.addRuntimeSafety("integer subtraction overflow",121 cases.addRuntimeSafety("integer subtraction overflow",
98 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {122 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
99 \\ @import("std").os.exit(126);123 \\ @import("std").os.exit(126);
...@@ -362,6 +386,23 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -362,6 +386,23 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
362 \\}386 \\}
363 );387 );
364388
389 // @intCast a runtime integer to u0 actually results in a comptime-known value,
390 // but we still emit a safety check to ensure the integer was 0 and thus
391 // did not truncate information.
392 cases.addRuntimeSafety("@intCast to u0",
393 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
394 \\ @import("std").os.exit(126);
395 \\}
396 \\
397 \\pub fn main() void {
398 \\ bar(1, 1);
399 \\}
400 \\
401 \\fn bar(one: u1, not_zero: i32) void {
402 \\ var x = one << @intCast(u0, not_zero);
403 \\}
404 );
405
365 // This case makes sure that the code compiles and runs. There is not actually a special406 // This case makes sure that the code compiles and runs. There is not actually a special
366 // runtime safety check having to do specifically with error return traces across suspend points.407 // runtime safety check having to do specifically with error return traces across suspend points.
367 cases.addRuntimeSafety("error return trace across suspend points",408 cases.addRuntimeSafety("error return trace across suspend points",
test/stage1/behavior.zig created+82
...@@ -0,0 +1,82 @@
1comptime {
2 _ = @import("behavior/align.zig");
3 _ = @import("behavior/alignof.zig");
4 _ = @import("behavior/array.zig");
5 _ = @import("behavior/asm.zig");
6 _ = @import("behavior/atomics.zig");
7 _ = @import("behavior/bit_shifting.zig");
8 _ = @import("behavior/bitcast.zig");
9 _ = @import("behavior/bitreverse.zig");
10 _ = @import("behavior/bool.zig");
11 _ = @import("behavior/bswap.zig");
12 _ = @import("behavior/bugs/1076.zig");
13 _ = @import("behavior/bugs/1111.zig");
14 _ = @import("behavior/bugs/1277.zig");
15 _ = @import("behavior/bugs/1322.zig");
16 _ = @import("behavior/bugs/1381.zig");
17 _ = @import("behavior/bugs/1421.zig");
18 _ = @import("behavior/bugs/1442.zig");
19 _ = @import("behavior/bugs/1486.zig");
20 _ = @import("behavior/bugs/1851.zig");
21 _ = @import("behavior/bugs/394.zig");
22 _ = @import("behavior/bugs/655.zig");
23 _ = @import("behavior/bugs/656.zig");
24 _ = @import("behavior/bugs/726.zig");
25 _ = @import("behavior/bugs/828.zig");
26 _ = @import("behavior/bugs/920.zig");
27 _ = @import("behavior/byval_arg_var.zig");
28 _ = @import("behavior/cancel.zig");
29 _ = @import("behavior/cast.zig");
30 _ = @import("behavior/const_slice_child.zig");
31 _ = @import("behavior/coroutine_await_struct.zig");
32 _ = @import("behavior/coroutines.zig");
33 _ = @import("behavior/defer.zig");
34 _ = @import("behavior/enum.zig");
35 _ = @import("behavior/enum_with_members.zig");
36 _ = @import("behavior/error.zig");
37 _ = @import("behavior/eval.zig");
38 _ = @import("behavior/field_parent_ptr.zig");
39 _ = @import("behavior/fn.zig");
40 _ = @import("behavior/fn_in_struct_in_comptime.zig");
41 _ = @import("behavior/for.zig");
42 _ = @import("behavior/generics.zig");
43 _ = @import("behavior/if.zig");
44 _ = @import("behavior/import.zig");
45 _ = @import("behavior/incomplete_struct_param_tld.zig");
46 _ = @import("behavior/inttoptr.zig");
47 _ = @import("behavior/ir_block_deps.zig");
48 _ = @import("behavior/math.zig");
49 _ = @import("behavior/merge_error_sets.zig");
50 _ = @import("behavior/misc.zig");
51 _ = @import("behavior/namespace_depends_on_compile_var/index.zig");
52 _ = @import("behavior/new_stack_call.zig");
53 _ = @import("behavior/null.zig");
54 _ = @import("behavior/optional.zig");
55 _ = @import("behavior/pointers.zig");
56 _ = @import("behavior/popcount.zig");
57 _ = @import("behavior/ptrcast.zig");
58 _ = @import("behavior/pub_enum/index.zig");
59 _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
60 _ = @import("behavior/reflection.zig");
61 _ = @import("behavior/sizeof_and_typeof.zig");
62 _ = @import("behavior/slice.zig");
63 _ = @import("behavior/struct.zig");
64 _ = @import("behavior/struct_contains_null_ptr_itself.zig");
65 _ = @import("behavior/struct_contains_slice_of_itself.zig");
66 _ = @import("behavior/switch.zig");
67 _ = @import("behavior/switch_prong_err_enum.zig");
68 _ = @import("behavior/switch_prong_implicit_cast.zig");
69 _ = @import("behavior/syntax.zig");
70 _ = @import("behavior/this.zig");
71 _ = @import("behavior/truncate.zig");
72 _ = @import("behavior/try.zig");
73 _ = @import("behavior/type_info.zig");
74 _ = @import("behavior/undefined.zig");
75 _ = @import("behavior/underscore.zig");
76 _ = @import("behavior/union.zig");
77 _ = @import("behavior/var_args.zig");
78 _ = @import("behavior/vector.zig");
79 _ = @import("behavior/void.zig");
80 _ = @import("behavior/while.zig");
81 _ = @import("behavior/widening.zig");
82}
test/stage1/behavior/align.zig created+230
...@@ -0,0 +1,230 @@
1const expect = @import("std").testing.expect;
2const builtin = @import("builtin");
3
4var foo: u8 align(4) = 100;
5
6test "global variable alignment" {
7 expect(@typeOf(&foo).alignment == 4);
8 expect(@typeOf(&foo) == *align(4) u8);
9 const slice = (*[1]u8)(&foo)[0..];
10 expect(@typeOf(slice) == []align(4) u8);
11}
12
13fn derp() align(@sizeOf(usize) * 2) i32 {
14 return 1234;
15}
16fn noop1() align(1) void {}
17fn noop4() align(4) void {}
18
19test "function alignment" {
20 expect(derp() == 1234);
21 expect(@typeOf(noop1) == fn () align(1) void);
22 expect(@typeOf(noop4) == fn () align(4) void);
23 noop1();
24 noop4();
25}
26
27var baz: packed struct {
28 a: u32,
29 b: u32,
30} = undefined;
31
32test "packed struct alignment" {
33 expect(@typeOf(&baz.b) == *align(1) u32);
34}
35
36const blah: packed struct {
37 a: u3,
38 b: u3,
39 c: u2,
40} = undefined;
41
42test "bit field alignment" {
43 expect(@typeOf(&blah.b) == *align(1:3:1) const u3);
44}
45
46test "default alignment allows unspecified in type syntax" {
47 expect(*u32 == *align(@alignOf(u32)) u32);
48}
49
50test "implicitly decreasing pointer alignment" {
51 const a: u32 align(4) = 3;
52 const b: u32 align(8) = 4;
53 expect(addUnaligned(&a, &b) == 7);
54}
55
56fn addUnaligned(a: *align(1) const u32, b: *align(1) const u32) u32 {
57 return a.* + b.*;
58}
59
60test "implicitly decreasing slice alignment" {
61 const a: u32 align(4) = 3;
62 const b: u32 align(8) = 4;
63 expect(addUnalignedSlice((*[1]u32)(&a)[0..], (*[1]u32)(&b)[0..]) == 7);
64}
65fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
66 return a[0] + b[0];
67}
68
69test "specifying alignment allows pointer cast" {
70 testBytesAlign(0x33);
71}
72fn testBytesAlign(b: u8) void {
73 var bytes align(4) = []u8{
74 b,
75 b,
76 b,
77 b,
78 };
79 const ptr = @ptrCast(*u32, &bytes[0]);
80 expect(ptr.* == 0x33333333);
81}
82
83test "specifying alignment allows slice cast" {
84 testBytesAlignSlice(0x33);
85}
86fn testBytesAlignSlice(b: u8) void {
87 var bytes align(4) = []u8{
88 b,
89 b,
90 b,
91 b,
92 };
93 const slice: []u32 = @bytesToSlice(u32, bytes[0..]);
94 expect(slice[0] == 0x33333333);
95}
96
97test "@alignCast pointers" {
98 var x: u32 align(4) = 1;
99 expectsOnly1(&x);
100 expect(x == 2);
101}
102fn expectsOnly1(x: *align(1) u32) void {
103 expects4(@alignCast(4, x));
104}
105fn expects4(x: *align(4) u32) void {
106 x.* += 1;
107}
108
109test "@alignCast slices" {
110 var array align(4) = []u32{
111 1,
112 1,
113 };
114 const slice = array[0..];
115 sliceExpectsOnly1(slice);
116 expect(slice[0] == 2);
117}
118fn sliceExpectsOnly1(slice: []align(1) u32) void {
119 sliceExpects4(@alignCast(4, slice));
120}
121fn sliceExpects4(slice: []align(4) u32) void {
122 slice[0] += 1;
123}
124
125test "implicitly decreasing fn alignment" {
126 testImplicitlyDecreaseFnAlign(alignedSmall, 1234);
127 testImplicitlyDecreaseFnAlign(alignedBig, 5678);
128}
129
130fn testImplicitlyDecreaseFnAlign(ptr: fn () align(1) i32, answer: i32) void {
131 expect(ptr() == answer);
132}
133
134fn alignedSmall() align(8) i32 {
135 return 1234;
136}
137fn alignedBig() align(16) i32 {
138 return 5678;
139}
140
141test "@alignCast functions" {
142 expect(fnExpectsOnly1(simple4) == 0x19);
143}
144fn fnExpectsOnly1(ptr: fn () align(1) i32) i32 {
145 return fnExpects4(@alignCast(4, ptr));
146}
147fn fnExpects4(ptr: fn () align(4) i32) i32 {
148 return ptr();
149}
150fn simple4() align(4) i32 {
151 return 0x19;
152}
153
154test "generic function with align param" {
155 expect(whyWouldYouEverDoThis(1) == 0x1);
156 expect(whyWouldYouEverDoThis(4) == 0x1);
157 expect(whyWouldYouEverDoThis(8) == 0x1);
158}
159
160fn whyWouldYouEverDoThis(comptime align_bytes: u8) align(align_bytes) u8 {
161 return 0x1;
162}
163
164test "@ptrCast preserves alignment of bigger source" {
165 var x: u32 align(16) = 1234;
166 const ptr = @ptrCast(*u8, &x);
167 expect(@typeOf(ptr) == *align(16) u8);
168}
169
170test "runtime known array index has best alignment possible" {
171 // take full advantage of over-alignment
172 var array align(4) = []u8{ 1, 2, 3, 4 };
173 expect(@typeOf(&array[0]) == *align(4) u8);
174 expect(@typeOf(&array[1]) == *u8);
175 expect(@typeOf(&array[2]) == *align(2) u8);
176 expect(@typeOf(&array[3]) == *u8);
177
178 // because align is too small but we still figure out to use 2
179 var bigger align(2) = []u64{ 1, 2, 3, 4 };
180 expect(@typeOf(&bigger[0]) == *align(2) u64);
181 expect(@typeOf(&bigger[1]) == *align(2) u64);
182 expect(@typeOf(&bigger[2]) == *align(2) u64);
183 expect(@typeOf(&bigger[3]) == *align(2) u64);
184
185 // because pointer is align 2 and u32 align % 2 == 0 we can assume align 2
186 var smaller align(2) = []u32{ 1, 2, 3, 4 };
187 comptime expect(@typeOf(smaller[0..]) == []align(2) u32);
188 comptime expect(@typeOf(smaller[0..].ptr) == [*]align(2) u32);
189 testIndex(smaller[0..].ptr, 0, *align(2) u32);
190 testIndex(smaller[0..].ptr, 1, *align(2) u32);
191 testIndex(smaller[0..].ptr, 2, *align(2) u32);
192 testIndex(smaller[0..].ptr, 3, *align(2) u32);
193
194 // has to use ABI alignment because index known at runtime only
195 testIndex2(array[0..].ptr, 0, *u8);
196 testIndex2(array[0..].ptr, 1, *u8);
197 testIndex2(array[0..].ptr, 2, *u8);
198 testIndex2(array[0..].ptr, 3, *u8);
199}
200fn testIndex(smaller: [*]align(2) u32, index: usize, comptime T: type) void {
201 comptime expect(@typeOf(&smaller[index]) == T);
202}
203fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) void {
204 comptime expect(@typeOf(&ptr[index]) == T);
205}
206
207test "alignstack" {
208 expect(fnWithAlignedStack() == 1234);
209}
210
211fn fnWithAlignedStack() i32 {
212 @setAlignStack(256);
213 return 1234;
214}
215
216test "alignment of structs" {
217 expect(@alignOf(struct {
218 a: i32,
219 b: *i32,
220 }) == @alignOf(usize));
221}
222
223test "alignment of extern() void" {
224 var runtime_nothing = nothing;
225 const casted1 = @ptrCast(*const u8, runtime_nothing);
226 const casted2 = @ptrCast(extern fn () void, casted1);
227 casted2();
228}
229
230extern fn nothing() void {}
test/stage1/behavior/alignof.zig created+18
...@@ -0,0 +1,18 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const builtin = @import("builtin");
4const maxInt = std.math.maxInt;
5
6const Foo = struct {
7 x: u32,
8 y: u32,
9 z: u32,
10};
11
12test "@alignOf(T) before referencing T" {
13 comptime expect(@alignOf(Foo) != maxInt(usize));
14 if (builtin.arch == builtin.Arch.x86_64) {
15 comptime expect(@alignOf(Foo) == 4);
16 }
17}
18
test/stage1/behavior/array.zig created+270
...@@ -0,0 +1,270 @@
1const expect = @import("std").testing.expect;
2const mem = @import("std").mem;
3
4test "arrays" {
5 var array: [5]u32 = undefined;
6
7 var i: u32 = 0;
8 while (i < 5) {
9 array[i] = i + 1;
10 i = array[i];
11 }
12
13 i = 0;
14 var accumulator = u32(0);
15 while (i < 5) {
16 accumulator += array[i];
17
18 i += 1;
19 }
20
21 expect(accumulator == 15);
22 expect(getArrayLen(array) == 5);
23}
24fn getArrayLen(a: []const u32) usize {
25 return a.len;
26}
27
28test "void arrays" {
29 var array: [4]void = undefined;
30 array[0] = void{};
31 array[1] = array[2];
32 expect(@sizeOf(@typeOf(array)) == 0);
33 expect(array.len == 4);
34}
35
36test "array literal" {
37 const hex_mult = []u16{
38 4096,
39 256,
40 16,
41 1,
42 };
43
44 expect(hex_mult.len == 4);
45 expect(hex_mult[1] == 256);
46}
47
48test "array dot len const expr" {
49 expect(comptime x: {
50 break :x some_array.len == 4;
51 });
52}
53
54const ArrayDotLenConstExpr = struct {
55 y: [some_array.len]u8,
56};
57const some_array = []u8{
58 0,
59 1,
60 2,
61 3,
62};
63
64test "nested arrays" {
65 const array_of_strings = [][]const u8{
66 "hello",
67 "this",
68 "is",
69 "my",
70 "thing",
71 };
72 for (array_of_strings) |s, i| {
73 if (i == 0) expect(mem.eql(u8, s, "hello"));
74 if (i == 1) expect(mem.eql(u8, s, "this"));
75 if (i == 2) expect(mem.eql(u8, s, "is"));
76 if (i == 3) expect(mem.eql(u8, s, "my"));
77 if (i == 4) expect(mem.eql(u8, s, "thing"));
78 }
79}
80
81var s_array: [8]Sub = undefined;
82const Sub = struct {
83 b: u8,
84};
85const Str = struct {
86 a: []Sub,
87};
88test "set global var array via slice embedded in struct" {
89 var s = Str{ .a = s_array[0..] };
90
91 s.a[0].b = 1;
92 s.a[1].b = 2;
93 s.a[2].b = 3;
94
95 expect(s_array[0].b == 1);
96 expect(s_array[1].b == 2);
97 expect(s_array[2].b == 3);
98}
99
100test "array literal with specified size" {
101 var array = [2]u8{
102 1,
103 2,
104 };
105 expect(array[0] == 1);
106 expect(array[1] == 2);
107}
108
109test "array child property" {
110 var x: [5]i32 = undefined;
111 expect(@typeOf(x).Child == i32);
112}
113
114test "array len property" {
115 var x: [5]i32 = undefined;
116 expect(@typeOf(x).len == 5);
117}
118
119test "array len field" {
120 var arr = [4]u8{ 0, 0, 0, 0 };
121 var ptr = &arr;
122 expect(arr.len == 4);
123 comptime expect(arr.len == 4);
124 expect(ptr.len == 4);
125 comptime expect(ptr.len == 4);
126}
127
128test "single-item pointer to array indexing and slicing" {
129 testSingleItemPtrArrayIndexSlice();
130 comptime testSingleItemPtrArrayIndexSlice();
131}
132
133fn testSingleItemPtrArrayIndexSlice() void {
134 var array = "aaaa";
135 doSomeMangling(&array);
136 expect(mem.eql(u8, "azya", array));
137}
138
139fn doSomeMangling(array: *[4]u8) void {
140 array[1] = 'z';
141 array[2..3][0] = 'y';
142}
143
144test "implicit cast single-item pointer" {
145 testImplicitCastSingleItemPtr();
146 comptime testImplicitCastSingleItemPtr();
147}
148
149fn testImplicitCastSingleItemPtr() void {
150 var byte: u8 = 100;
151 const slice = (*[1]u8)(&byte)[0..];
152 slice[0] += 1;
153 expect(byte == 101);
154}
155
156fn testArrayByValAtComptime(b: [2]u8) u8 {
157 return b[0];
158}
159
160test "comptime evalutating function that takes array by value" {
161 const arr = []u8{ 0, 1 };
162 _ = comptime testArrayByValAtComptime(arr);
163 _ = comptime testArrayByValAtComptime(arr);
164}
165
166test "implicit comptime in array type size" {
167 var arr: [plusOne(10)]bool = undefined;
168 expect(arr.len == 11);
169}
170
171fn plusOne(x: u32) u32 {
172 return x + 1;
173}
174
175test "array literal as argument to function" {
176 const S = struct {
177 fn entry(two: i32) void {
178 foo([]i32{
179 1,
180 2,
181 3,
182 });
183 foo([]i32{
184 1,
185 two,
186 3,
187 });
188 foo2(true, []i32{
189 1,
190 2,
191 3,
192 });
193 foo2(true, []i32{
194 1,
195 two,
196 3,
197 });
198 }
199 fn foo(x: []const i32) void {
200 expect(x[0] == 1);
201 expect(x[1] == 2);
202 expect(x[2] == 3);
203 }
204 fn foo2(trash: bool, x: []const i32) void {
205 expect(trash);
206 expect(x[0] == 1);
207 expect(x[1] == 2);
208 expect(x[2] == 3);
209 }
210 };
211 S.entry(2);
212 comptime S.entry(2);
213}
214
215test "double nested array to const slice cast in array literal" {
216 const S = struct {
217 fn entry(two: i32) void {
218 const cases = [][]const []const i32{
219 [][]const i32{[]i32{1}},
220 [][]const i32{[]i32{ 2, 3 }},
221 [][]const i32{
222 []i32{4},
223 []i32{ 5, 6, 7 },
224 },
225 };
226 check(cases);
227
228 const cases2 = [][]const i32{
229 []i32{1},
230 []i32{ two, 3 },
231 };
232 expect(cases2.len == 2);
233 expect(cases2[0].len == 1);
234 expect(cases2[0][0] == 1);
235 expect(cases2[1].len == 2);
236 expect(cases2[1][0] == 2);
237 expect(cases2[1][1] == 3);
238
239 const cases3 = [][]const []const i32{
240 [][]const i32{[]i32{1}},
241 [][]const i32{[]i32{ two, 3 }},
242 [][]const i32{
243 []i32{4},
244 []i32{ 5, 6, 7 },
245 },
246 };
247 check(cases3);
248 }
249
250 fn check(cases: []const []const []const i32) void {
251 expect(cases.len == 3);
252 expect(cases[0].len == 1);
253 expect(cases[0][0].len == 1);
254 expect(cases[0][0][0] == 1);
255 expect(cases[1].len == 1);
256 expect(cases[1][0].len == 2);
257 expect(cases[1][0][0] == 2);
258 expect(cases[1][0][1] == 3);
259 expect(cases[2].len == 2);
260 expect(cases[2][0].len == 1);
261 expect(cases[2][0][0] == 4);
262 expect(cases[2][1].len == 3);
263 expect(cases[2][1][0] == 5);
264 expect(cases[2][1][1] == 6);
265 expect(cases[2][1][2] == 7);
266 }
267 };
268 S.entry(2);
269 comptime S.entry(2);
270}
test/stage1/behavior/asm.zig created+92
...@@ -0,0 +1,92 @@
1const config = @import("builtin");
2const expect = @import("std").testing.expect;
3
4comptime {
5 if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
6 asm volatile (
7 \\.globl aoeu;
8 \\.type aoeu, @function;
9 \\.set aoeu, derp;
10 );
11 }
12}
13
14test "module level assembly" {
15 if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {
16 expect(aoeu() == 1234);
17 }
18}
19
20test "output constraint modifiers" {
21 // This is only testing compilation.
22 var a: u32 = 3;
23 asm volatile (""
24 : [_] "=m,r" (a)
25 :
26 : ""
27 );
28 asm volatile (""
29 : [_] "=r,m" (a)
30 :
31 : ""
32 );
33}
34
35test "alternative constraints" {
36 // Make sure we allow commas as a separator for alternative constraints.
37 var a: u32 = 3;
38 asm volatile (""
39 : [_] "=r,m" (a)
40 : [_] "r,m" (a)
41 : ""
42 );
43}
44
45test "sized integer/float in asm input" {
46 asm volatile (""
47 :
48 : [_] "m" (usize(3))
49 : ""
50 );
51 asm volatile (""
52 :
53 : [_] "m" (i15(-3))
54 : ""
55 );
56 asm volatile (""
57 :
58 : [_] "m" (u3(3))
59 : ""
60 );
61 asm volatile (""
62 :
63 : [_] "m" (i3(3))
64 : ""
65 );
66 asm volatile (""
67 :
68 : [_] "m" (u121(3))
69 : ""
70 );
71 asm volatile (""
72 :
73 : [_] "m" (i121(3))
74 : ""
75 );
76 asm volatile (""
77 :
78 : [_] "m" (f32(3.17))
79 : ""
80 );
81 asm volatile (""
82 :
83 : [_] "m" (f64(3.17))
84 : ""
85 );
86}
87
88extern fn aoeu() i32;
89
90export fn derp() i32 {
91 return 1234;
92}
test/stage1/behavior/atomics.zig created+71
...@@ -0,0 +1,71 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const builtin = @import("builtin");
4const AtomicRmwOp = builtin.AtomicRmwOp;
5const AtomicOrder = builtin.AtomicOrder;
6
7test "cmpxchg" {
8 var x: i32 = 1234;
9 if (@cmpxchgWeak(i32, &x, 99, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
10 expect(x1 == 1234);
11 } else {
12 @panic("cmpxchg should have failed");
13 }
14
15 while (@cmpxchgWeak(i32, &x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
16 expect(x1 == 1234);
17 }
18 expect(x == 5678);
19
20 expect(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
21 expect(x == 42);
22}
23
24test "fence" {
25 var x: i32 = 1234;
26 @fence(AtomicOrder.SeqCst);
27 x = 5678;
28}
29
30test "atomicrmw and atomicload" {
31 var data: u8 = 200;
32 testAtomicRmw(&data);
33 expect(data == 42);
34 testAtomicLoad(&data);
35}
36
37fn testAtomicRmw(ptr: *u8) void {
38 const prev_value = @atomicRmw(u8, ptr, AtomicRmwOp.Xchg, 42, AtomicOrder.SeqCst);
39 expect(prev_value == 200);
40 comptime {
41 var x: i32 = 1234;
42 const y: i32 = 12345;
43 expect(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234);
44 expect(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345);
45 }
46}
47
48fn testAtomicLoad(ptr: *u8) void {
49 const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst);
50 expect(x == 42);
51}
52
53test "cmpxchg with ptr" {
54 var data1: i32 = 1234;
55 var data2: i32 = 5678;
56 var data3: i32 = 9101;
57 var x: *i32 = &data1;
58 if (@cmpxchgWeak(*i32, &x, &data2, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
59 expect(x1 == &data1);
60 } else {
61 @panic("cmpxchg should have failed");
62 }
63
64 while (@cmpxchgWeak(*i32, &x, &data1, &data3, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) |x1| {
65 expect(x1 == &data1);
66 }
67 expect(x == &data3);
68
69 expect(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
70 expect(x == &data2);
71}
test/stage1/behavior/bit_shifting.zig created+88
...@@ -0,0 +1,88 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type {
5 expect(Key == @IntType(false, Key.bit_count));
6 expect(Key.bit_count >= mask_bit_count);
7 const ShardKey = @IntType(false, mask_bit_count);
8 const shift_amount = Key.bit_count - ShardKey.bit_count;
9 return struct {
10 const Self = @This();
11 shards: [1 << ShardKey.bit_count]?*Node,
12
13 pub fn create() Self {
14 return Self{ .shards = []?*Node{null} ** (1 << ShardKey.bit_count) };
15 }
16
17 fn getShardKey(key: Key) ShardKey {
18 // https://github.com/ziglang/zig/issues/1544
19 // this special case is needed because you can't u32 >> 32.
20 if (ShardKey == u0) return 0;
21
22 // this can be u1 >> u0
23 const shard_key = key >> shift_amount;
24
25 // TODO: https://github.com/ziglang/zig/issues/1544
26 // This cast could be implicit if we teach the compiler that
27 // u32 >> 30 -> u2
28 return @intCast(ShardKey, shard_key);
29 }
30
31 pub fn put(self: *Self, node: *Node) void {
32 const shard_key = Self.getShardKey(node.key);
33 node.next = self.shards[shard_key];
34 self.shards[shard_key] = node;
35 }
36
37 pub fn get(self: *Self, key: Key) ?*Node {
38 const shard_key = Self.getShardKey(key);
39 var maybe_node = self.shards[shard_key];
40 while (maybe_node) |node| : (maybe_node = node.next) {
41 if (node.key == key) return node;
42 }
43 return null;
44 }
45
46 pub const Node = struct {
47 key: Key,
48 value: V,
49 next: ?*Node,
50
51 pub fn init(self: *Node, key: Key, value: V) void {
52 self.key = key;
53 self.value = value;
54 self.next = null;
55 }
56 };
57 };
58}
59
60test "sharded table" {
61 // realistic 16-way sharding
62 testShardedTable(u32, 4, 8);
63
64 testShardedTable(u5, 0, 32); // ShardKey == u0
65 testShardedTable(u5, 2, 32);
66 testShardedTable(u5, 5, 32);
67
68 testShardedTable(u1, 0, 2);
69 testShardedTable(u1, 1, 2); // this does u1 >> u0
70
71 testShardedTable(u0, 0, 1);
72}
73fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime node_count: comptime_int) void {
74 const Table = ShardedTable(Key, mask_bit_count, void);
75
76 var table = Table.create();
77 var node_buffer: [node_count]Table.Node = undefined;
78 for (node_buffer) |*node, i| {
79 const key = @intCast(Key, i);
80 expect(table.get(key) == null);
81 node.init(key, {});
82 table.put(node);
83 }
84
85 for (node_buffer) |*node, i| {
86 expect(table.get(@intCast(Key, i)) == node);
87 }
88}
test/stage1/behavior/bitcast.zig created+36
...@@ -0,0 +1,36 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const maxInt = std.math.maxInt;
4
5test "@bitCast i32 -> u32" {
6 testBitCast_i32_u32();
7 comptime testBitCast_i32_u32();
8}
9
10fn testBitCast_i32_u32() void {
11 expect(conv(-1) == maxInt(u32));
12 expect(conv2(maxInt(u32)) == -1);
13}
14
15fn conv(x: i32) u32 {
16 return @bitCast(u32, x);
17}
18fn conv2(x: u32) i32 {
19 return @bitCast(i32, x);
20}
21
22test "@bitCast extern enum to its integer type" {
23 const SOCK = extern enum {
24 A,
25 B,
26
27 fn testBitCastExternEnum() void {
28 var SOCK_DGRAM = @This().B;
29 var sock_dgram = @bitCast(c_int, SOCK_DGRAM);
30 expect(sock_dgram == 1);
31 }
32 };
33
34 SOCK.testBitCastExternEnum();
35 comptime SOCK.testBitCastExternEnum();
36}
test/stage1/behavior/bitreverse.zig created+81
...@@ -0,0 +1,81 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const minInt = std.math.minInt;
4
5test "@bitreverse" {
6 comptime testBitReverse();
7 testBitReverse();
8}
9
10fn testBitReverse() void {
11 // using comptime_ints, unsigned
12 expect(@bitreverse(u0, 0) == 0);
13 expect(@bitreverse(u5, 0x12) == 0x9);
14 expect(@bitreverse(u8, 0x12) == 0x48);
15 expect(@bitreverse(u16, 0x1234) == 0x2c48);
16 expect(@bitreverse(u24, 0x123456) == 0x6a2c48);
17 expect(@bitreverse(u32, 0x12345678) == 0x1e6a2c48);
18 expect(@bitreverse(u40, 0x123456789a) == 0x591e6a2c48);
19 expect(@bitreverse(u48, 0x123456789abc) == 0x3d591e6a2c48);
20 expect(@bitreverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48);
21 expect(@bitreverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48);
22 expect(@bitreverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48);
23
24 // using runtime uints, unsigned
25 var num0: u0 = 0;
26 expect(@bitreverse(u0, num0) == 0);
27 var num5: u5 = 0x12;
28 expect(@bitreverse(u5, num5) == 0x9);
29 var num8: u8 = 0x12;
30 expect(@bitreverse(u8, num8) == 0x48);
31 var num16: u16 = 0x1234;
32 expect(@bitreverse(u16, num16) == 0x2c48);
33 var num24: u24 = 0x123456;
34 expect(@bitreverse(u24, num24) == 0x6a2c48);
35 var num32: u32 = 0x12345678;
36 expect(@bitreverse(u32, num32) == 0x1e6a2c48);
37 var num40: u40 = 0x123456789a;
38 expect(@bitreverse(u40, num40) == 0x591e6a2c48);
39 var num48: u48 = 0x123456789abc;
40 expect(@bitreverse(u48, num48) == 0x3d591e6a2c48);
41 var num56: u56 = 0x123456789abcde;
42 expect(@bitreverse(u56, num56) == 0x7b3d591e6a2c48);
43 var num64: u64 = 0x123456789abcdef1;
44 expect(@bitreverse(u64, num64) == 0x8f7b3d591e6a2c48);
45 var num128: u128 = 0x123456789abcdef11121314151617181;
46 expect(@bitreverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48);
47
48 // using comptime_ints, signed, positive
49 expect(@bitreverse(i0, 0) == 0);
50 expect(@bitreverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8(0x49)));
51 expect(@bitreverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x2c48)));
52 expect(@bitreverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x6a2c48)));
53 expect(@bitreverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x1e6a2c48)));
54 expect(@bitreverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x591e6a2c48)));
55 expect(@bitreverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0x3d591e6a2c48)));
56 expect(@bitreverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0x7b3d591e6a2c48)));
57 expect(@bitreverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0x8f7b3d591e6a2c48)));
58 expect(@bitreverse(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) == @bitCast(i128, u128(0x818e868a828c84888f7b3d591e6a2c48)));
59
60 // using comptime_ints, signed, negative. Compare to runtime ints returned from llvm.
61 var neg5: i5 = minInt(i5) + 1;
62 expect(@bitreverse(i5, minInt(i5) + 1) == @bitreverse(i5, neg5));
63 var neg8: i8 = -18;
64 expect(@bitreverse(i8, -18) == @bitreverse(i8, neg8));
65 var neg16: i16 = -32694;
66 expect(@bitreverse(i16, -32694) == @bitreverse(i16, neg16));
67 var neg24: i24 = -6773785;
68 expect(@bitreverse(i24, -6773785) == @bitreverse(i24, neg24));
69 var neg32: i32 = -16773785;
70 expect(@bitreverse(i32, -16773785) == @bitreverse(i32, neg32));
71 var neg40: i40 = minInt(i40) + 12345;
72 expect(@bitreverse(i40, minInt(i40) + 12345) == @bitreverse(i40, neg40));
73 var neg48: i48 = minInt(i48) + 12345;
74 expect(@bitreverse(i48, minInt(i48) + 12345) == @bitreverse(i48, neg48));
75 var neg56: i56 = minInt(i56) + 12345;
76 expect(@bitreverse(i56, minInt(i56) + 12345) == @bitreverse(i56, neg56));
77 var neg64: i64 = minInt(i64) + 12345;
78 expect(@bitreverse(i64, minInt(i64) + 12345) == @bitreverse(i64, neg64));
79 var neg128: i128 = minInt(i128) + 12345;
80 expect(@bitreverse(i128, minInt(i128) + 12345) == @bitreverse(i128, neg128));
81}
test/stage1/behavior/bool.zig created+35
...@@ -0,0 +1,35 @@
1const expect = @import("std").testing.expect;
2
3test "bool literals" {
4 expect(true);
5 expect(!false);
6}
7
8test "cast bool to int" {
9 const t = true;
10 const f = false;
11 expect(@boolToInt(t) == u32(1));
12 expect(@boolToInt(f) == u32(0));
13 nonConstCastBoolToInt(t, f);
14}
15
16fn nonConstCastBoolToInt(t: bool, f: bool) void {
17 expect(@boolToInt(t) == u32(1));
18 expect(@boolToInt(f) == u32(0));
19}
20
21test "bool cmp" {
22 expect(testBoolCmp(true, false) == false);
23}
24fn testBoolCmp(a: bool, b: bool) bool {
25 return a == b;
26}
27
28const global_f = false;
29const global_t = true;
30const not_global_f = !global_f;
31const not_global_t = !global_t;
32test "compile time bool not" {
33 expect(not_global_f);
34 expect(!not_global_t);
35}
test/stage1/behavior/bswap.zig created+32
...@@ -0,0 +1,32 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "@bswap" {
5 comptime testByteSwap();
6 testByteSwap();
7}
8
9fn testByteSwap() void {
10 expect(@bswap(u0, 0) == 0);
11 expect(@bswap(u8, 0x12) == 0x12);
12 expect(@bswap(u16, 0x1234) == 0x3412);
13 expect(@bswap(u24, 0x123456) == 0x563412);
14 expect(@bswap(u32, 0x12345678) == 0x78563412);
15 expect(@bswap(u40, 0x123456789a) == 0x9a78563412);
16 expect(@bswap(u48, 0x123456789abc) == 0xbc9a78563412);
17 expect(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412);
18 expect(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412);
19 expect(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412);
20
21 expect(@bswap(i0, 0) == 0);
22 expect(@bswap(i8, -50) == -50);
23 expect(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412)));
24 expect(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412)));
25 expect(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412)));
26 expect(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412)));
27 expect(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412)));
28 expect(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412)));
29 expect(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412)));
30 expect(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) ==
31 @bitCast(i128, u128(0x8171615141312111f1debc9a78563412)));
32}
test/stage1/behavior/bugs/1076.zig created+16
...@@ -0,0 +1,16 @@
1const std = @import("std");
2const mem = std.mem;
3const expect = std.testing.expect;
4
5test "comptime code should not modify constant data" {
6 testCastPtrOfArrayToSliceAndPtr();
7 comptime testCastPtrOfArrayToSliceAndPtr();
8}
9
10fn testCastPtrOfArrayToSliceAndPtr() void {
11 var array = "aoeu";
12 const x: [*]u8 = &array;
13 x[0] += 1;
14 expect(mem.eql(u8, array[0..], "boeu"));
15}
16
test/stage1/behavior/bugs/1111.zig created+12
...@@ -0,0 +1,12 @@
1const Foo = extern enum {
2 Bar = -1,
3};
4
5test "issue 1111 fixed" {
6 const v = Foo.Bar;
7
8 switch (v) {
9 Foo.Bar => return,
10 else => return,
11 }
12}
test/stage1/behavior/bugs/1277.zig created+15
...@@ -0,0 +1,15 @@
1const std = @import("std");
2
3const S = struct {
4 f: ?fn () i32,
5};
6
7const s = S{ .f = f };
8
9fn f() i32 {
10 return 1234;
11}
12
13test "don't emit an LLVM global for a const function when it's in an optional in a struct" {
14 std.testing.expect(s.f.?() == 1234);
15}
test/stage1/behavior/bugs/1322.zig created+19
...@@ -0,0 +1,19 @@
1const std = @import("std");
2
3const B = union(enum) {
4 c: C,
5 None,
6};
7
8const A = struct {
9 b: B,
10};
11
12const C = struct {};
13
14test "tagged union with all void fields but a meaningful tag" {
15 var a: A = A{ .b = B{ .c = C{} } };
16 std.testing.expect(@TagType(B)(a.b) == @TagType(B).c);
17 a = A{ .b = B.None };
18 std.testing.expect(@TagType(B)(a.b) == @TagType(B).None);
19}
test/stage1/behavior/bugs/1381.zig created+21
...@@ -0,0 +1,21 @@
1const std = @import("std");
2
3const B = union(enum) {
4 D: u8,
5 E: u16,
6};
7
8const A = union(enum) {
9 B: B,
10 C: u8,
11};
12
13test "union that needs padding bytes inside an array" {
14 var as = []A{
15 A{ .B = B{ .D = 1 } },
16 A{ .B = B{ .D = 1 } },
17 };
18
19 const a = as[0].B;
20 std.testing.expect(a.D == 1);
21}
test/stage1/behavior/bugs/1421.zig created+14
...@@ -0,0 +1,14 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4
5const S = struct {
6 fn method() builtin.TypeInfo {
7 return @typeInfo(S);
8 }
9};
10
11test "functions with return type required to be comptime are generic" {
12 const ti = S.method();
13 expect(builtin.TypeId(ti) == builtin.TypeId.Struct);
14}
test/stage1/behavior/bugs/1442.zig created+11
...@@ -0,0 +1,11 @@
1const std = @import("std");
2
3const Union = union(enum) {
4 Text: []const u8,
5 Color: u32,
6};
7
8test "const error union field alignment" {
9 var union_or_err: anyerror!Union = Union{ .Color = 1234 };
10 std.testing.expect((union_or_err catch unreachable).Color == 1234);
11}
test/stage1/behavior/bugs/1486.zig created+11
...@@ -0,0 +1,11 @@
1const expect = @import("std").testing.expect;
2
3const ptr = &global;
4var global: u64 = 123;
5
6test "constant pointer to global variable causes runtime load" {
7 global = 1234;
8 expect(&global == ptr);
9 expect(ptr.* == 1234);
10}
11
test/stage1/behavior/bugs/1851.zig created+27
...@@ -0,0 +1,27 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "allocation and looping over 3-byte integer" {
5 expect(@sizeOf(u24) == 4);
6 expect(@sizeOf([1]u24) == 4);
7 expect(@alignOf(u24) == 4);
8 expect(@alignOf([1]u24) == 4);
9 var buffer: [100]u8 = undefined;
10 const a = &std.heap.FixedBufferAllocator.init(&buffer).allocator;
11
12 var x = a.alloc(u24, 2) catch unreachable;
13 expect(x.len == 2);
14 x[0] = 0xFFFFFF;
15 x[1] = 0xFFFFFF;
16
17 const bytes = @sliceToBytes(x);
18 expect(@typeOf(bytes) == []align(4) u8);
19 expect(bytes.len == 8);
20
21 for (bytes) |*b| {
22 b.* = 0x00;
23 }
24
25 expect(x[0] == 0x00);
26 expect(x[1] == 0x00);
27}
test/stage1/behavior/bugs/394.zig created+18
...@@ -0,0 +1,18 @@
1const E = union(enum) {
2 A: [9]u8,
3 B: u64,
4};
5const S = struct {
6 x: u8,
7 y: E,
8};
9
10const expect = @import("std").testing.expect;
11
12test "bug 394 fixed" {
13 const x = S{
14 .x = 3,
15 .y = E{ .B = 1 },
16 };
17 expect(x.x == 3);
18}
test/stage1/behavior/bugs/655.zig created+12
...@@ -0,0 +1,12 @@
1const std = @import("std");
2const other_file = @import("655_other_file.zig");
3
4test "function with *const parameter with type dereferenced by namespace" {
5 const x: other_file.Integer = 1234;
6 comptime std.testing.expect(@typeOf(&x) == *const other_file.Integer);
7 foo(&x);
8}
9
10fn foo(x: *const other_file.Integer) void {
11 std.testing.expect(x.* == 1234);
12}
test/stage1/behavior/bugs/655_other_file.zig created+1
...@@ -0,0 +1 @@
1pub const Integer = u32;
test/stage1/behavior/bugs/656.zig created+31
...@@ -0,0 +1,31 @@
1const expect = @import("std").testing.expect;
2
3const PrefixOp = union(enum) {
4 Return,
5 AddrOf: Value,
6};
7
8const Value = struct {
9 align_expr: ?u32,
10};
11
12test "optional if after an if in a switch prong of a switch with 2 prongs in an else" {
13 foo(false, true);
14}
15
16fn foo(a: bool, b: bool) void {
17 var prefix_op = PrefixOp{
18 .AddrOf = Value{ .align_expr = 1234 },
19 };
20 if (a) {} else {
21 switch (prefix_op) {
22 PrefixOp.AddrOf => |addr_of_info| {
23 if (b) {}
24 if (addr_of_info.align_expr) |align_expr| {
25 expect(align_expr == 1234);
26 }
27 },
28 PrefixOp.Return => {},
29 }
30 }
31}
test/stage1/behavior/bugs/726.zig created+16
...@@ -0,0 +1,16 @@
1const expect = @import("std").testing.expect;
2
3test "@ptrCast from const to nullable" {
4 const c: u8 = 4;
5 var x: ?*const u8 = @ptrCast(?*const u8, &c);
6 expect(x.?.* == 4);
7}
8
9test "@ptrCast from var in empty struct to nullable" {
10 const container = struct {
11 var c: u8 = 4;
12 };
13 var x: ?*const u8 = @ptrCast(?*const u8, &container.c);
14 expect(x.?.* == 4);
15}
16
test/stage1/behavior/bugs/828.zig created+33
...@@ -0,0 +1,33 @@
1const CountBy = struct {
2 a: usize,
3
4 const One = CountBy{ .a = 1 };
5
6 pub fn counter(self: *const CountBy) Counter {
7 return Counter{ .i = 0 };
8 }
9};
10
11const Counter = struct {
12 i: usize,
13
14 pub fn count(self: *Counter) bool {
15 self.i += 1;
16 return self.i <= 10;
17 }
18};
19
20fn constCount(comptime cb: *const CountBy, comptime unused: u32) void {
21 comptime {
22 var cnt = cb.counter();
23 if (cnt.i != 0) @compileError("Counter instance reused!");
24 while (cnt.count()) {}
25 }
26}
27
28test "comptime struct return should not return the same instance" {
29 //the first parameter must be passed by reference to trigger the bug
30 //a second parameter is required to trigger the bug
31 const ValA = constCount(&CountBy.One, 12);
32 const ValB = constCount(&CountBy.One, 15);
33}
test/stage1/behavior/bugs/920.zig created+65
...@@ -0,0 +1,65 @@
1const std = @import("std");
2const math = std.math;
3const Random = std.rand.Random;
4
5const ZigTable = struct {
6 r: f64,
7 x: [257]f64,
8 f: [257]f64,
9
10 pdf: fn (f64) f64,
11 is_symmetric: bool,
12 zero_case: fn (*Random, f64) f64,
13};
14
15fn ZigTableGen(comptime is_symmetric: bool, comptime r: f64, comptime v: f64, comptime f: fn (f64) f64, comptime f_inv: fn (f64) f64, comptime zero_case: fn (*Random, f64) f64) ZigTable {
16 var tables: ZigTable = undefined;
17
18 tables.is_symmetric = is_symmetric;
19 tables.r = r;
20 tables.pdf = f;
21 tables.zero_case = zero_case;
22
23 tables.x[0] = v / f(r);
24 tables.x[1] = r;
25
26 for (tables.x[2..256]) |*entry, i| {
27 const last = tables.x[2 + i - 1];
28 entry.* = f_inv(v / last + f(last));
29 }
30 tables.x[256] = 0;
31
32 for (tables.f[0..]) |*entry, i| {
33 entry.* = f(tables.x[i]);
34 }
35
36 return tables;
37}
38
39const norm_r = 3.6541528853610088;
40const norm_v = 0.00492867323399;
41
42fn norm_f(x: f64) f64 {
43 return math.exp(-x * x / 2.0);
44}
45fn norm_f_inv(y: f64) f64 {
46 return math.sqrt(-2.0 * math.ln(y));
47}
48fn norm_zero_case(random: *Random, u: f64) f64 {
49 return 0.0;
50}
51
52const NormalDist = blk: {
53 @setEvalBranchQuota(30000);
54 break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case);
55};
56
57test "bug 920 fixed" {
58 const NormalDist1 = blk: {
59 break :blk ZigTableGen(true, norm_r, norm_v, norm_f, norm_f_inv, norm_zero_case);
60 };
61
62 for (NormalDist1.f) |_, i| {
63 std.testing.expect(NormalDist1.f[i] == NormalDist.f[i]);
64 }
65}
test/stage1/behavior/byval_arg_var.zig created+27
...@@ -0,0 +1,27 @@
1const std = @import("std");
2
3var result: []const u8 = "wrong";
4
5test "pass string literal byvalue to a generic var param" {
6 start();
7 blowUpStack(10);
8
9 std.testing.expect(std.mem.eql(u8, result, "string literal"));
10}
11
12fn start() void {
13 foo("string literal");
14}
15
16fn foo(x: var) void {
17 bar(x);
18}
19
20fn bar(x: var) void {
21 result = x;
22}
23
24fn blowUpStack(x: u32) void {
25 if (x == 0) return;
26 blowUpStack(x - 1);
27}
test/stage1/behavior/cancel.zig created+92
...@@ -0,0 +1,92 @@
1const std = @import("std");
2
3var defer_f1: bool = false;
4var defer_f2: bool = false;
5var defer_f3: bool = false;
6
7test "cancel forwards" {
8 var da = std.heap.DirectAllocator.init();
9 defer da.deinit();
10
11 const p = async<&da.allocator> f1() catch unreachable;
12 cancel p;
13 std.testing.expect(defer_f1);
14 std.testing.expect(defer_f2);
15 std.testing.expect(defer_f3);
16}
17
18async fn f1() void {
19 defer {
20 defer_f1 = true;
21 }
22 await (async f2() catch unreachable);
23}
24
25async fn f2() void {
26 defer {
27 defer_f2 = true;
28 }
29 await (async f3() catch unreachable);
30}
31
32async fn f3() void {
33 defer {
34 defer_f3 = true;
35 }
36 suspend;
37}
38
39var defer_b1: bool = false;
40var defer_b2: bool = false;
41var defer_b3: bool = false;
42var defer_b4: bool = false;
43
44test "cancel backwards" {
45 var da = std.heap.DirectAllocator.init();
46 defer da.deinit();
47
48 const p = async<&da.allocator> b1() catch unreachable;
49 cancel p;
50 std.testing.expect(defer_b1);
51 std.testing.expect(defer_b2);
52 std.testing.expect(defer_b3);
53 std.testing.expect(defer_b4);
54}
55
56async fn b1() void {
57 defer {
58 defer_b1 = true;
59 }
60 await (async b2() catch unreachable);
61}
62
63var b4_handle: promise = undefined;
64
65async fn b2() void {
66 const b3_handle = async b3() catch unreachable;
67 resume b4_handle;
68 cancel b4_handle;
69 defer {
70 defer_b2 = true;
71 }
72 const value = await b3_handle;
73 @panic("unreachable");
74}
75
76async fn b3() i32 {
77 defer {
78 defer_b3 = true;
79 }
80 await (async b4() catch unreachable);
81 return 1234;
82}
83
84async fn b4() void {
85 defer {
86 defer_b4 = true;
87 }
88 suspend {
89 b4_handle = @handle();
90 }
91 suspend;
92}
test/stage1/behavior/cast.zig created+484
...@@ -0,0 +1,484 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const mem = std.mem;
4const maxInt = std.math.maxInt;
5
6test "int to ptr cast" {
7 const x = usize(13);
8 const y = @intToPtr(*u8, x);
9 const z = @ptrToInt(y);
10 expect(z == 13);
11}
12
13test "integer literal to pointer cast" {
14 const vga_mem = @intToPtr(*u16, 0xB8000);
15 expect(@ptrToInt(vga_mem) == 0xB8000);
16}
17
18test "pointer reinterpret const float to int" {
19 const float: f64 = 5.99999999999994648725e-01;
20 const float_ptr = &float;
21 const int_ptr = @ptrCast(*const i32, float_ptr);
22 const int_val = int_ptr.*;
23 expect(int_val == 858993411);
24}
25
26test "implicitly cast indirect pointer to maybe-indirect pointer" {
27 const S = struct {
28 const Self = @This();
29 x: u8,
30 fn constConst(p: *const *const Self) u8 {
31 return p.*.x;
32 }
33 fn maybeConstConst(p: ?*const *const Self) u8 {
34 return p.?.*.x;
35 }
36 fn constConstConst(p: *const *const *const Self) u8 {
37 return p.*.*.x;
38 }
39 fn maybeConstConstConst(p: ?*const *const *const Self) u8 {
40 return p.?.*.*.x;
41 }
42 };
43 const s = S{ .x = 42 };
44 const p = &s;
45 const q = &p;
46 const r = &q;
47 expect(42 == S.constConst(q));
48 expect(42 == S.maybeConstConst(q));
49 expect(42 == S.constConstConst(r));
50 expect(42 == S.maybeConstConstConst(r));
51}
52
53test "explicit cast from integer to error type" {
54 testCastIntToErr(error.ItBroke);
55 comptime testCastIntToErr(error.ItBroke);
56}
57fn testCastIntToErr(err: anyerror) void {
58 const x = @errorToInt(err);
59 const y = @intToError(x);
60 expect(error.ItBroke == y);
61}
62
63test "peer resolve arrays of different size to const slice" {
64 expect(mem.eql(u8, boolToStr(true), "true"));
65 expect(mem.eql(u8, boolToStr(false), "false"));
66 comptime expect(mem.eql(u8, boolToStr(true), "true"));
67 comptime expect(mem.eql(u8, boolToStr(false), "false"));
68}
69fn boolToStr(b: bool) []const u8 {
70 return if (b) "true" else "false";
71}
72
73test "peer resolve array and const slice" {
74 testPeerResolveArrayConstSlice(true);
75 comptime testPeerResolveArrayConstSlice(true);
76}
77fn testPeerResolveArrayConstSlice(b: bool) void {
78 const value1 = if (b) "aoeu" else ([]const u8)("zz");
79 const value2 = if (b) ([]const u8)("zz") else "aoeu";
80 expect(mem.eql(u8, value1, "aoeu"));
81 expect(mem.eql(u8, value2, "zz"));
82}
83
84test "implicitly cast from T to anyerror!?T" {
85 castToOptionalTypeError(1);
86 comptime castToOptionalTypeError(1);
87}
88
89const A = struct {
90 a: i32,
91};
92fn castToOptionalTypeError(z: i32) void {
93 const x = i32(1);
94 const y: anyerror!?i32 = x;
95 expect((try y).? == 1);
96
97 const f = z;
98 const g: anyerror!?i32 = f;
99
100 const a = A{ .a = z };
101 const b: anyerror!?A = a;
102 expect((b catch unreachable).?.a == 1);
103}
104
105test "implicitly cast from int to anyerror!?T" {
106 implicitIntLitToOptional();
107 comptime implicitIntLitToOptional();
108}
109fn implicitIntLitToOptional() void {
110 const f: ?i32 = 1;
111 const g: anyerror!?i32 = 1;
112}
113
114test "return null from fn() anyerror!?&T" {
115 const a = returnNullFromOptionalTypeErrorRef();
116 const b = returnNullLitFromOptionalTypeErrorRef();
117 expect((try a) == null and (try b) == null);
118}
119fn returnNullFromOptionalTypeErrorRef() anyerror!?*A {
120 const a: ?*A = null;
121 return a;
122}
123fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
124 return null;
125}
126
127test "peer type resolution: ?T and T" {
128 expect(peerTypeTAndOptionalT(true, false).? == 0);
129 expect(peerTypeTAndOptionalT(false, false).? == 3);
130 comptime {
131 expect(peerTypeTAndOptionalT(true, false).? == 0);
132 expect(peerTypeTAndOptionalT(false, false).? == 3);
133 }
134}
135fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
136 if (c) {
137 return if (b) null else usize(0);
138 }
139
140 return usize(3);
141}
142
143test "peer type resolution: [0]u8 and []const u8" {
144 expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
145 expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
146 comptime {
147 expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
148 expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
149 }
150}
151fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
152 if (a) {
153 return []const u8{};
154 }
155
156 return slice[0..1];
157}
158
159test "implicitly cast from [N]T to ?[]const T" {
160 expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
161 comptime expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
162}
163
164fn castToOptionalSlice() ?[]const u8 {
165 return "hi";
166}
167
168test "implicitly cast from [0]T to anyerror![]T" {
169 testCastZeroArrayToErrSliceMut();
170 comptime testCastZeroArrayToErrSliceMut();
171}
172
173fn testCastZeroArrayToErrSliceMut() void {
174 expect((gimmeErrOrSlice() catch unreachable).len == 0);
175}
176
177fn gimmeErrOrSlice() anyerror![]u8 {
178 return []u8{};
179}
180
181test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
182 {
183 var data = "hi";
184 const slice = data[0..];
185 expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
186 expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
187 }
188 comptime {
189 var data = "hi";
190 const slice = data[0..];
191 expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
192 expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
193 }
194}
195fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
196 if (a) {
197 return []u8{};
198 }
199
200 return slice[0..1];
201}
202
203test "resolve undefined with integer" {
204 testResolveUndefWithInt(true, 1234);
205 comptime testResolveUndefWithInt(true, 1234);
206}
207fn testResolveUndefWithInt(b: bool, x: i32) void {
208 const value = if (b) x else undefined;
209 if (b) {
210 expect(value == x);
211 }
212}
213
214test "implicit cast from &const [N]T to []const T" {
215 testCastConstArrayRefToConstSlice();
216 comptime testCastConstArrayRefToConstSlice();
217}
218
219fn testCastConstArrayRefToConstSlice() void {
220 const blah = "aoeu";
221 const const_array_ref = &blah;
222 expect(@typeOf(const_array_ref) == *const [4]u8);
223 const slice: []const u8 = const_array_ref;
224 expect(mem.eql(u8, slice, "aoeu"));
225}
226
227test "peer type resolution: error and [N]T" {
228 // TODO: implicit error!T to error!U where T can implicitly cast to U
229 //expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
230 //comptime expect(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
231 expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
232 comptime expect(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
233}
234
235//fn testPeerErrorAndArray(x: u8) error![]const u8 {
236// return switch (x) {
237// 0x00 => "OK",
238// else => error.BadValue,
239// };
240//}
241fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
242 return switch (x) {
243 0x00 => "OK",
244 0x01 => "OKK",
245 else => error.BadValue,
246 };
247}
248
249test "@floatToInt" {
250 testFloatToInts();
251 comptime testFloatToInts();
252}
253
254fn testFloatToInts() void {
255 const x = i32(1e4);
256 expect(x == 10000);
257 const y = @floatToInt(i32, f32(1e4));
258 expect(y == 10000);
259 expectFloatToInt(f16, 255.1, u8, 255);
260 expectFloatToInt(f16, 127.2, i8, 127);
261 expectFloatToInt(f16, -128.2, i8, -128);
262 expectFloatToInt(f32, 255.1, u8, 255);
263 expectFloatToInt(f32, 127.2, i8, 127);
264 expectFloatToInt(f32, -128.2, i8, -128);
265 expectFloatToInt(comptime_int, 1234, i16, 1234);
266}
267
268fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) void {
269 expect(@floatToInt(I, f) == i);
270}
271
272test "cast u128 to f128 and back" {
273 comptime testCast128();
274 testCast128();
275}
276
277fn testCast128() void {
278 expect(cast128Int(cast128Float(0x7fff0000000000000000000000000000)) == 0x7fff0000000000000000000000000000);
279}
280
281fn cast128Int(x: f128) u128 {
282 return @bitCast(u128, x);
283}
284
285fn cast128Float(x: u128) f128 {
286 return @bitCast(f128, x);
287}
288
289test "const slice widen cast" {
290 const bytes align(4) = []u8{
291 0x12,
292 0x12,
293 0x12,
294 0x12,
295 };
296
297 const u32_value = @bytesToSlice(u32, bytes[0..])[0];
298 expect(u32_value == 0x12121212);
299
300 expect(@bitCast(u32, bytes) == 0x12121212);
301}
302
303test "single-item pointer of array to slice and to unknown length pointer" {
304 testCastPtrOfArrayToSliceAndPtr();
305 comptime testCastPtrOfArrayToSliceAndPtr();
306}
307
308fn testCastPtrOfArrayToSliceAndPtr() void {
309 var array = "aoeu";
310 const x: [*]u8 = &array;
311 x[0] += 1;
312 expect(mem.eql(u8, array[0..], "boeu"));
313 const y: []u8 = &array;
314 y[0] += 1;
315 expect(mem.eql(u8, array[0..], "coeu"));
316}
317
318test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
319 const window_name = [1][*]const u8{c"window name"};
320 const x: [*]const ?[*]const u8 = &window_name;
321 expect(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name"));
322}
323
324test "@intCast comptime_int" {
325 const result = @intCast(i32, 1234);
326 expect(@typeOf(result) == i32);
327 expect(result == 1234);
328}
329
330test "@floatCast comptime_int and comptime_float" {
331 {
332 const result = @floatCast(f16, 1234);
333 expect(@typeOf(result) == f16);
334 expect(result == 1234.0);
335 }
336 {
337 const result = @floatCast(f16, 1234.0);
338 expect(@typeOf(result) == f16);
339 expect(result == 1234.0);
340 }
341 {
342 const result = @floatCast(f32, 1234);
343 expect(@typeOf(result) == f32);
344 expect(result == 1234.0);
345 }
346 {
347 const result = @floatCast(f32, 1234.0);
348 expect(@typeOf(result) == f32);
349 expect(result == 1234.0);
350 }
351}
352
353test "comptime_int @intToFloat" {
354 {
355 const result = @intToFloat(f16, 1234);
356 expect(@typeOf(result) == f16);
357 expect(result == 1234.0);
358 }
359 {
360 const result = @intToFloat(f32, 1234);
361 expect(@typeOf(result) == f32);
362 expect(result == 1234.0);
363 }
364}
365
366test "@bytesToSlice keeps pointer alignment" {
367 var bytes = []u8{ 0x01, 0x02, 0x03, 0x04 };
368 const numbers = @bytesToSlice(u32, bytes[0..]);
369 comptime expect(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32);
370}
371
372test "@intCast i32 to u7" {
373 var x: u128 = maxInt(u128);
374 var y: i32 = 120;
375 var z = x >> @intCast(u7, y);
376 expect(z == 0xff);
377}
378
379test "implicit cast undefined to optional" {
380 expect(MakeType(void).getNull() == null);
381 expect(MakeType(void).getNonNull() != null);
382}
383
384fn MakeType(comptime T: type) type {
385 return struct {
386 fn getNull() ?T {
387 return null;
388 }
389
390 fn getNonNull() ?T {
391 return T(undefined);
392 }
393 };
394}
395
396test "implicit cast from *[N]T to ?[*]T" {
397 var x: ?[*]u16 = null;
398 var y: [4]u16 = [4]u16{ 0, 1, 2, 3 };
399
400 x = &y;
401 expect(std.mem.eql(u16, x.?[0..4], y[0..4]));
402 x.?[0] = 8;
403 y[3] = 6;
404 expect(std.mem.eql(u16, x.?[0..4], y[0..4]));
405}
406
407test "implicit cast from *T to ?*c_void" {
408 var a: u8 = 1;
409 incrementVoidPtrValue(&a);
410 std.testing.expect(a == 2);
411}
412
413fn incrementVoidPtrValue(value: ?*c_void) void {
414 @ptrCast(*u8, value.?).* += 1;
415}
416
417test "implicit cast from [*]T to ?*c_void" {
418 var a = []u8{ 3, 2, 1 };
419 incrementVoidPtrArray(a[0..].ptr, 3);
420 expect(std.mem.eql(u8, a, []u8{ 4, 3, 2 }));
421}
422
423fn incrementVoidPtrArray(array: ?*c_void, len: usize) void {
424 var n: usize = 0;
425 while (n < len) : (n += 1) {
426 @ptrCast([*]u8, array.?)[n] += 1;
427 }
428}
429
430test "*usize to *void" {
431 var i = usize(0);
432 var v = @ptrCast(*void, &i);
433 v.* = {};
434}
435
436test "compile time int to ptr of function" {
437 foobar(FUNCTION_CONSTANT);
438}
439
440pub const FUNCTION_CONSTANT = @intToPtr(PFN_void, maxInt(usize));
441pub const PFN_void = extern fn (*c_void) void;
442
443fn foobar(func: PFN_void) void {
444 std.testing.expect(@ptrToInt(func) == maxInt(usize));
445}
446
447test "implicit ptr to *c_void" {
448 var a: u32 = 1;
449 var ptr: *c_void = &a;
450 var b: *u32 = @ptrCast(*u32, ptr);
451 expect(b.* == 1);
452 var ptr2: ?*c_void = &a;
453 var c: *u32 = @ptrCast(*u32, ptr2.?);
454 expect(c.* == 1);
455}
456
457test "@intCast to comptime_int" {
458 expect(@intCast(comptime_int, 0) == 0);
459}
460
461test "implicit cast comptime numbers to any type when the value fits" {
462 const a: u64 = 255;
463 var b: u8 = a;
464 expect(b == 255);
465}
466
467test "@intToEnum passed a comptime_int to an enum with one item" {
468 const E = enum {
469 A,
470 };
471 const x = @intToEnum(E, 0);
472 expect(x == E.A);
473}
474
475test "@intCast to u0 and use the result" {
476 const S = struct {
477 fn doTheTest(zero: u1, one: u1, bigzero: i32) void {
478 expect((one << @intCast(u0, bigzero)) == 1);
479 expect((zero << @intCast(u0, bigzero)) == 0);
480 }
481 };
482 S.doTheTest(0, 1, 0);
483 comptime S.doTheTest(0, 1, 0);
484}
test/stage1/behavior/const_slice_child.zig created+46
...@@ -0,0 +1,46 @@
1const std = @import("std");
2const debug = std.debug;
3const expect = std.testing.expect;
4
5var argv: [*]const [*]const u8 = undefined;
6
7test "const slice child" {
8 const strs = ([][*]const u8){
9 c"one",
10 c"two",
11 c"three",
12 };
13 // TODO this should implicitly cast
14 argv = @ptrCast([*]const [*]const u8, &strs);
15 bar(strs.len);
16}
17
18fn foo(args: [][]const u8) void {
19 expect(args.len == 3);
20 expect(streql(args[0], "one"));
21 expect(streql(args[1], "two"));
22 expect(streql(args[2], "three"));
23}
24
25fn bar(argc: usize) void {
26 const args = debug.global_allocator.alloc([]const u8, argc) catch unreachable;
27 for (args) |_, i| {
28 const ptr = argv[i];
29 args[i] = ptr[0..strlen(ptr)];
30 }
31 foo(args);
32}
33
34fn strlen(ptr: [*]const u8) usize {
35 var count: usize = 0;
36 while (ptr[count] != 0) : (count += 1) {}
37 return count;
38}
39
40fn streql(a: []const u8, b: []const u8) bool {
41 if (a.len != b.len) return false;
42 for (a) |item, index| {
43 if (b[index] != item) return false;
44 }
45 return true;
46}
test/stage1/behavior/coroutine_await_struct.zig created+47
...@@ -0,0 +1,47 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4
5const Foo = struct {
6 x: i32,
7};
8
9var await_a_promise: promise = undefined;
10var await_final_result = Foo{ .x = 0 };
11
12test "coroutine await struct" {
13 var da = std.heap.DirectAllocator.init();
14 defer da.deinit();
15
16 await_seq('a');
17 const p = async<&da.allocator> await_amain() catch unreachable;
18 await_seq('f');
19 resume await_a_promise;
20 await_seq('i');
21 expect(await_final_result.x == 1234);
22 expect(std.mem.eql(u8, await_points, "abcdefghi"));
23}
24async fn await_amain() void {
25 await_seq('b');
26 const p = async await_another() catch unreachable;
27 await_seq('e');
28 await_final_result = await p;
29 await_seq('h');
30}
31async fn await_another() Foo {
32 await_seq('c');
33 suspend {
34 await_seq('d');
35 await_a_promise = @handle();
36 }
37 await_seq('g');
38 return Foo{ .x = 1234 };
39}
40
41var await_points = []u8{0} ** "abcdefghi".len;
42var await_seq_index: usize = 0;
43
44fn await_seq(c: u8) void {
45 await_points[await_seq_index] = c;
46 await_seq_index += 1;
47}
test/stage1/behavior/coroutines.zig created+258
...@@ -0,0 +1,258 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
4
5var x: i32 = 1;
6
7test "create a coroutine and cancel it" {
8 var da = std.heap.DirectAllocator.init();
9 defer da.deinit();
10
11 const p = try async<&da.allocator> simpleAsyncFn();
12 comptime expect(@typeOf(p) == promise->void);
13 cancel p;
14 expect(x == 2);
15}
16async fn simpleAsyncFn() void {
17 x += 1;
18 suspend;
19 x += 1;
20}
21
22test "coroutine suspend, resume, cancel" {
23 var da = std.heap.DirectAllocator.init();
24 defer da.deinit();
25
26 seq('a');
27 const p = try async<&da.allocator> testAsyncSeq();
28 seq('c');
29 resume p;
30 seq('f');
31 cancel p;
32 seq('g');
33
34 expect(std.mem.eql(u8, points, "abcdefg"));
35}
36async fn testAsyncSeq() void {
37 defer seq('e');
38
39 seq('b');
40 suspend;
41 seq('d');
42}
43var points = []u8{0} ** "abcdefg".len;
44var index: usize = 0;
45
46fn seq(c: u8) void {
47 points[index] = c;
48 index += 1;
49}
50
51test "coroutine suspend with block" {
52 var da = std.heap.DirectAllocator.init();
53 defer da.deinit();
54
55 const p = try async<&da.allocator> testSuspendBlock();
56 std.testing.expect(!result);
57 resume a_promise;
58 std.testing.expect(result);
59 cancel p;
60}
61
62var a_promise: promise = undefined;
63var result = false;
64async fn testSuspendBlock() void {
65 suspend {
66 comptime expect(@typeOf(@handle()) == promise->void);
67 a_promise = @handle();
68 }
69
70 //Test to make sure that @handle() works as advertised (issue #1296)
71 //var our_handle: promise = @handle();
72 expect(a_promise == @handle());
73
74 result = true;
75}
76
77var await_a_promise: promise = undefined;
78var await_final_result: i32 = 0;
79
80test "coroutine await" {
81 var da = std.heap.DirectAllocator.init();
82 defer da.deinit();
83
84 await_seq('a');
85 const p = async<&da.allocator> await_amain() catch unreachable;
86 await_seq('f');
87 resume await_a_promise;
88 await_seq('i');
89 expect(await_final_result == 1234);
90 expect(std.mem.eql(u8, await_points, "abcdefghi"));
91}
92async fn await_amain() void {
93 await_seq('b');
94 const p = async await_another() catch unreachable;
95 await_seq('e');
96 await_final_result = await p;
97 await_seq('h');
98}
99async fn await_another() i32 {
100 await_seq('c');
101 suspend {
102 await_seq('d');
103 await_a_promise = @handle();
104 }
105 await_seq('g');
106 return 1234;
107}
108
109var await_points = []u8{0} ** "abcdefghi".len;
110var await_seq_index: usize = 0;
111
112fn await_seq(c: u8) void {
113 await_points[await_seq_index] = c;
114 await_seq_index += 1;
115}
116
117var early_final_result: i32 = 0;
118
119test "coroutine await early return" {
120 var da = std.heap.DirectAllocator.init();
121 defer da.deinit();
122
123 early_seq('a');
124 const p = async<&da.allocator> early_amain() catch @panic("out of memory");
125 early_seq('f');
126 expect(early_final_result == 1234);
127 expect(std.mem.eql(u8, early_points, "abcdef"));
128}
129async fn early_amain() void {
130 early_seq('b');
131 const p = async early_another() catch @panic("out of memory");
132 early_seq('d');
133 early_final_result = await p;
134 early_seq('e');
135}
136async fn early_another() i32 {
137 early_seq('c');
138 return 1234;
139}
140
141var early_points = []u8{0} ** "abcdef".len;
142var early_seq_index: usize = 0;
143
144fn early_seq(c: u8) void {
145 early_points[early_seq_index] = c;
146 early_seq_index += 1;
147}
148
149test "coro allocation failure" {
150 var failing_allocator = std.debug.FailingAllocator.init(std.debug.global_allocator, 0);
151 if (async<&failing_allocator.allocator> asyncFuncThatNeverGetsRun()) {
152 @panic("expected allocation failure");
153 } else |err| switch (err) {
154 error.OutOfMemory => {},
155 }
156}
157async fn asyncFuncThatNeverGetsRun() void {
158 @panic("coro frame allocation should fail");
159}
160
161test "async function with dot syntax" {
162 const S = struct {
163 var y: i32 = 1;
164 async fn foo() void {
165 y += 1;
166 suspend;
167 }
168 };
169 var da = std.heap.DirectAllocator.init();
170 defer da.deinit();
171 const p = try async<&da.allocator> S.foo();
172 cancel p;
173 expect(S.y == 2);
174}
175
176test "async fn pointer in a struct field" {
177 var data: i32 = 1;
178 const Foo = struct {
179 bar: async<*std.mem.Allocator> fn (*i32) void,
180 };
181 var foo = Foo{ .bar = simpleAsyncFn2 };
182 var da = std.heap.DirectAllocator.init();
183 defer da.deinit();
184 const p = (async<&da.allocator> foo.bar(&data)) catch unreachable;
185 expect(data == 2);
186 cancel p;
187 expect(data == 4);
188}
189async<*std.mem.Allocator> fn simpleAsyncFn2(y: *i32) void {
190 defer y.* += 2;
191 y.* += 1;
192 suspend;
193}
194
195test "async fn with inferred error set" {
196 var da = std.heap.DirectAllocator.init();
197 defer da.deinit();
198 const p = (async<&da.allocator> failing()) catch unreachable;
199 resume p;
200 cancel p;
201}
202
203async fn failing() !void {
204 suspend;
205 return error.Fail;
206}
207
208test "error return trace across suspend points - early return" {
209 const p = nonFailing();
210 resume p;
211 var da = std.heap.DirectAllocator.init();
212 defer da.deinit();
213 const p2 = try async<&da.allocator> printTrace(p);
214 cancel p2;
215}
216
217test "error return trace across suspend points - async return" {
218 const p = nonFailing();
219 const p2 = try async<std.debug.global_allocator> printTrace(p);
220 resume p;
221 cancel p2;
222}
223
224fn nonFailing() (promise->anyerror!void) {
225 return async<std.debug.global_allocator> suspendThenFail() catch unreachable;
226}
227async fn suspendThenFail() anyerror!void {
228 suspend;
229 return error.Fail;
230}
231async fn printTrace(p: promise->(anyerror!void)) void {
232 (await p) catch |e| {
233 std.testing.expect(e == error.Fail);
234 if (@errorReturnTrace()) |trace| {
235 expect(trace.index == 1);
236 } else switch (builtin.mode) {
237 builtin.Mode.Debug, builtin.Mode.ReleaseSafe => @panic("expected return trace"),
238 builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {},
239 }
240 };
241}
242
243test "break from suspend" {
244 var buf: [500]u8 = undefined;
245 var a = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator;
246 var my_result: i32 = 1;
247 const p = try async<a> testBreakFromSuspend(&my_result);
248 cancel p;
249 std.testing.expect(my_result == 2);
250}
251async fn testBreakFromSuspend(my_result: *i32) void {
252 suspend {
253 resume @handle();
254 }
255 my_result.* += 1;
256 suspend;
257 my_result.* += 1;
258}
test/stage1/behavior/defer.zig created+78
...@@ -0,0 +1,78 @@
1const expect = @import("std").testing.expect;
2
3var result: [3]u8 = undefined;
4var index: usize = undefined;
5
6fn runSomeErrorDefers(x: bool) !bool {
7 index = 0;
8 defer {
9 result[index] = 'a';
10 index += 1;
11 }
12 errdefer {
13 result[index] = 'b';
14 index += 1;
15 }
16 defer {
17 result[index] = 'c';
18 index += 1;
19 }
20 return if (x) x else error.FalseNotAllowed;
21}
22
23test "mixing normal and error defers" {
24 expect(runSomeErrorDefers(true) catch unreachable);
25 expect(result[0] == 'c');
26 expect(result[1] == 'a');
27
28 const ok = runSomeErrorDefers(false) catch |err| x: {
29 expect(err == error.FalseNotAllowed);
30 break :x true;
31 };
32 expect(ok);
33 expect(result[0] == 'c');
34 expect(result[1] == 'b');
35 expect(result[2] == 'a');
36}
37
38test "break and continue inside loop inside defer expression" {
39 testBreakContInDefer(10);
40 comptime testBreakContInDefer(10);
41}
42
43fn testBreakContInDefer(x: usize) void {
44 defer {
45 var i: usize = 0;
46 while (i < x) : (i += 1) {
47 if (i < 5) continue;
48 if (i == 5) break;
49 }
50 expect(i == 5);
51 }
52}
53
54test "defer and labeled break" {
55 var i = usize(0);
56
57 blk: {
58 defer i += 1;
59 break :blk;
60 }
61
62 expect(i == 1);
63}
64
65test "errdefer does not apply to fn inside fn" {
66 if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| expect(e == error.Bad);
67}
68
69fn testNestedFnErrDefer() anyerror!void {
70 var a: i32 = 0;
71 errdefer a += 1;
72 const S = struct {
73 fn baz() anyerror {
74 return error.Bad;
75 }
76 };
77 return S.baz();
78}
test/stage1/behavior/enum.zig created+894
...@@ -0,0 +1,894 @@
1const expect = @import("std").testing.expect;
2const mem = @import("std").mem;
3
4test "enum type" {
5 const foo1 = Foo{ .One = 13 };
6 const foo2 = Foo{
7 .Two = Point{
8 .x = 1234,
9 .y = 5678,
10 },
11 };
12 const bar = Bar.B;
13
14 expect(bar == Bar.B);
15 expect(@memberCount(Foo) == 3);
16 expect(@memberCount(Bar) == 4);
17 expect(@sizeOf(Foo) == @sizeOf(FooNoVoid));
18 expect(@sizeOf(Bar) == 1);
19}
20
21test "enum as return value" {
22 switch (returnAnInt(13)) {
23 Foo.One => |value| expect(value == 13),
24 else => unreachable,
25 }
26}
27
28const Point = struct {
29 x: u64,
30 y: u64,
31};
32const Foo = union(enum) {
33 One: i32,
34 Two: Point,
35 Three: void,
36};
37const FooNoVoid = union(enum) {
38 One: i32,
39 Two: Point,
40};
41const Bar = enum {
42 A,
43 B,
44 C,
45 D,
46};
47
48fn returnAnInt(x: i32) Foo {
49 return Foo{ .One = x };
50}
51
52test "constant enum with payload" {
53 var empty = AnEnumWithPayload{ .Empty = {} };
54 var full = AnEnumWithPayload{ .Full = 13 };
55 shouldBeEmpty(empty);
56 shouldBeNotEmpty(full);
57}
58
59fn shouldBeEmpty(x: AnEnumWithPayload) void {
60 switch (x) {
61 AnEnumWithPayload.Empty => {},
62 else => unreachable,
63 }
64}
65
66fn shouldBeNotEmpty(x: AnEnumWithPayload) void {
67 switch (x) {
68 AnEnumWithPayload.Empty => unreachable,
69 else => {},
70 }
71}
72
73const AnEnumWithPayload = union(enum) {
74 Empty: void,
75 Full: i32,
76};
77
78const Number = enum {
79 Zero,
80 One,
81 Two,
82 Three,
83 Four,
84};
85
86test "enum to int" {
87 shouldEqual(Number.Zero, 0);
88 shouldEqual(Number.One, 1);
89 shouldEqual(Number.Two, 2);
90 shouldEqual(Number.Three, 3);
91 shouldEqual(Number.Four, 4);
92}
93
94fn shouldEqual(n: Number, expected: u3) void {
95 expect(@enumToInt(n) == expected);
96}
97
98test "int to enum" {
99 testIntToEnumEval(3);
100}
101fn testIntToEnumEval(x: i32) void {
102 expect(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three);
103}
104const IntToEnumNumber = enum {
105 Zero,
106 One,
107 Two,
108 Three,
109 Four,
110};
111
112test "@tagName" {
113 expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
114 comptime expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
115}
116
117fn testEnumTagNameBare(n: BareNumber) []const u8 {
118 return @tagName(n);
119}
120
121const BareNumber = enum {
122 One,
123 Two,
124 Three,
125};
126
127test "enum alignment" {
128 comptime {
129 expect(@alignOf(AlignTestEnum) >= @alignOf([9]u8));
130 expect(@alignOf(AlignTestEnum) >= @alignOf(u64));
131 }
132}
133
134const AlignTestEnum = union(enum) {
135 A: [9]u8,
136 B: u64,
137};
138
139const ValueCount1 = enum {
140 I0,
141};
142const ValueCount2 = enum {
143 I0,
144 I1,
145};
146const ValueCount256 = enum {
147 I0,
148 I1,
149 I2,
150 I3,
151 I4,
152 I5,
153 I6,
154 I7,
155 I8,
156 I9,
157 I10,
158 I11,
159 I12,
160 I13,
161 I14,
162 I15,
163 I16,
164 I17,
165 I18,
166 I19,
167 I20,
168 I21,
169 I22,
170 I23,
171 I24,
172 I25,
173 I26,
174 I27,
175 I28,
176 I29,
177 I30,
178 I31,
179 I32,
180 I33,
181 I34,
182 I35,
183 I36,
184 I37,
185 I38,
186 I39,
187 I40,
188 I41,
189 I42,
190 I43,
191 I44,
192 I45,
193 I46,
194 I47,
195 I48,
196 I49,
197 I50,
198 I51,
199 I52,
200 I53,
201 I54,
202 I55,
203 I56,
204 I57,
205 I58,
206 I59,
207 I60,
208 I61,
209 I62,
210 I63,
211 I64,
212 I65,
213 I66,
214 I67,
215 I68,
216 I69,
217 I70,
218 I71,
219 I72,
220 I73,
221 I74,
222 I75,
223 I76,
224 I77,
225 I78,
226 I79,
227 I80,
228 I81,
229 I82,
230 I83,
231 I84,
232 I85,
233 I86,
234 I87,
235 I88,
236 I89,
237 I90,
238 I91,
239 I92,
240 I93,
241 I94,
242 I95,
243 I96,
244 I97,
245 I98,
246 I99,
247 I100,
248 I101,
249 I102,
250 I103,
251 I104,
252 I105,
253 I106,
254 I107,
255 I108,
256 I109,
257 I110,
258 I111,
259 I112,
260 I113,
261 I114,
262 I115,
263 I116,
264 I117,
265 I118,
266 I119,
267 I120,
268 I121,
269 I122,
270 I123,
271 I124,
272 I125,
273 I126,
274 I127,
275 I128,
276 I129,
277 I130,
278 I131,
279 I132,
280 I133,
281 I134,
282 I135,
283 I136,
284 I137,
285 I138,
286 I139,
287 I140,
288 I141,
289 I142,
290 I143,
291 I144,
292 I145,
293 I146,
294 I147,
295 I148,
296 I149,
297 I150,
298 I151,
299 I152,
300 I153,
301 I154,
302 I155,
303 I156,
304 I157,
305 I158,
306 I159,
307 I160,
308 I161,
309 I162,
310 I163,
311 I164,
312 I165,
313 I166,
314 I167,
315 I168,
316 I169,
317 I170,
318 I171,
319 I172,
320 I173,
321 I174,
322 I175,
323 I176,
324 I177,
325 I178,
326 I179,
327 I180,
328 I181,
329 I182,
330 I183,
331 I184,
332 I185,
333 I186,
334 I187,
335 I188,
336 I189,
337 I190,
338 I191,
339 I192,
340 I193,
341 I194,
342 I195,
343 I196,
344 I197,
345 I198,
346 I199,
347 I200,
348 I201,
349 I202,
350 I203,
351 I204,
352 I205,
353 I206,
354 I207,
355 I208,
356 I209,
357 I210,
358 I211,
359 I212,
360 I213,
361 I214,
362 I215,
363 I216,
364 I217,
365 I218,
366 I219,
367 I220,
368 I221,
369 I222,
370 I223,
371 I224,
372 I225,
373 I226,
374 I227,
375 I228,
376 I229,
377 I230,
378 I231,
379 I232,
380 I233,
381 I234,
382 I235,
383 I236,
384 I237,
385 I238,
386 I239,
387 I240,
388 I241,
389 I242,
390 I243,
391 I244,
392 I245,
393 I246,
394 I247,
395 I248,
396 I249,
397 I250,
398 I251,
399 I252,
400 I253,
401 I254,
402 I255,
403};
404const ValueCount257 = enum {
405 I0,
406 I1,
407 I2,
408 I3,
409 I4,
410 I5,
411 I6,
412 I7,
413 I8,
414 I9,
415 I10,
416 I11,
417 I12,
418 I13,
419 I14,
420 I15,
421 I16,
422 I17,
423 I18,
424 I19,
425 I20,
426 I21,
427 I22,
428 I23,
429 I24,
430 I25,
431 I26,
432 I27,
433 I28,
434 I29,
435 I30,
436 I31,
437 I32,
438 I33,
439 I34,
440 I35,
441 I36,
442 I37,
443 I38,
444 I39,
445 I40,
446 I41,
447 I42,
448 I43,
449 I44,
450 I45,
451 I46,
452 I47,
453 I48,
454 I49,
455 I50,
456 I51,
457 I52,
458 I53,
459 I54,
460 I55,
461 I56,
462 I57,
463 I58,
464 I59,
465 I60,
466 I61,
467 I62,
468 I63,
469 I64,
470 I65,
471 I66,
472 I67,
473 I68,
474 I69,
475 I70,
476 I71,
477 I72,
478 I73,
479 I74,
480 I75,
481 I76,
482 I77,
483 I78,
484 I79,
485 I80,
486 I81,
487 I82,
488 I83,
489 I84,
490 I85,
491 I86,
492 I87,
493 I88,
494 I89,
495 I90,
496 I91,
497 I92,
498 I93,
499 I94,
500 I95,
501 I96,
502 I97,
503 I98,
504 I99,
505 I100,
506 I101,
507 I102,
508 I103,
509 I104,
510 I105,
511 I106,
512 I107,
513 I108,
514 I109,
515 I110,
516 I111,
517 I112,
518 I113,
519 I114,
520 I115,
521 I116,
522 I117,
523 I118,
524 I119,
525 I120,
526 I121,
527 I122,
528 I123,
529 I124,
530 I125,
531 I126,
532 I127,
533 I128,
534 I129,
535 I130,
536 I131,
537 I132,
538 I133,
539 I134,
540 I135,
541 I136,
542 I137,
543 I138,
544 I139,
545 I140,
546 I141,
547 I142,
548 I143,
549 I144,
550 I145,
551 I146,
552 I147,
553 I148,
554 I149,
555 I150,
556 I151,
557 I152,
558 I153,
559 I154,
560 I155,
561 I156,
562 I157,
563 I158,
564 I159,
565 I160,
566 I161,
567 I162,
568 I163,
569 I164,
570 I165,
571 I166,
572 I167,
573 I168,
574 I169,
575 I170,
576 I171,
577 I172,
578 I173,
579 I174,
580 I175,
581 I176,
582 I177,
583 I178,
584 I179,
585 I180,
586 I181,
587 I182,
588 I183,
589 I184,
590 I185,
591 I186,
592 I187,
593 I188,
594 I189,
595 I190,
596 I191,
597 I192,
598 I193,
599 I194,
600 I195,
601 I196,
602 I197,
603 I198,
604 I199,
605 I200,
606 I201,
607 I202,
608 I203,
609 I204,
610 I205,
611 I206,
612 I207,
613 I208,
614 I209,
615 I210,
616 I211,
617 I212,
618 I213,
619 I214,
620 I215,
621 I216,
622 I217,
623 I218,
624 I219,
625 I220,
626 I221,
627 I222,
628 I223,
629 I224,
630 I225,
631 I226,
632 I227,
633 I228,
634 I229,
635 I230,
636 I231,
637 I232,
638 I233,
639 I234,
640 I235,
641 I236,
642 I237,
643 I238,
644 I239,
645 I240,
646 I241,
647 I242,
648 I243,
649 I244,
650 I245,
651 I246,
652 I247,
653 I248,
654 I249,
655 I250,
656 I251,
657 I252,
658 I253,
659 I254,
660 I255,
661 I256,
662};
663
664test "enum sizes" {
665 comptime {
666 expect(@sizeOf(ValueCount1) == 0);
667 expect(@sizeOf(ValueCount2) == 1);
668 expect(@sizeOf(ValueCount256) == 1);
669 expect(@sizeOf(ValueCount257) == 2);
670 }
671}
672
673const Small2 = enum(u2) {
674 One,
675 Two,
676};
677const Small = enum(u2) {
678 One,
679 Two,
680 Three,
681 Four,
682};
683
684test "set enum tag type" {
685 {
686 var x = Small.One;
687 x = Small.Two;
688 comptime expect(@TagType(Small) == u2);
689 }
690 {
691 var x = Small2.One;
692 x = Small2.Two;
693 comptime expect(@TagType(Small2) == u2);
694 }
695}
696
697const A = enum(u3) {
698 One,
699 Two,
700 Three,
701 Four,
702 One2,
703 Two2,
704 Three2,
705 Four2,
706};
707
708const B = enum(u3) {
709 One3,
710 Two3,
711 Three3,
712 Four3,
713 One23,
714 Two23,
715 Three23,
716 Four23,
717};
718
719const C = enum(u2) {
720 One4,
721 Two4,
722 Three4,
723 Four4,
724};
725
726const BitFieldOfEnums = packed struct {
727 a: A,
728 b: B,
729 c: C,
730};
731
732const bit_field_1 = BitFieldOfEnums{
733 .a = A.Two,
734 .b = B.Three3,
735 .c = C.Four4,
736};
737
738test "bit field access with enum fields" {
739 var data = bit_field_1;
740 expect(getA(&data) == A.Two);
741 expect(getB(&data) == B.Three3);
742 expect(getC(&data) == C.Four4);
743 comptime expect(@sizeOf(BitFieldOfEnums) == 1);
744
745 data.b = B.Four3;
746 expect(data.b == B.Four3);
747
748 data.a = A.Three;
749 expect(data.a == A.Three);
750 expect(data.b == B.Four3);
751}
752
753fn getA(data: *const BitFieldOfEnums) A {
754 return data.a;
755}
756
757fn getB(data: *const BitFieldOfEnums) B {
758 return data.b;
759}
760
761fn getC(data: *const BitFieldOfEnums) C {
762 return data.c;
763}
764
765test "casting enum to its tag type" {
766 testCastEnumToTagType(Small2.Two);
767 comptime testCastEnumToTagType(Small2.Two);
768}
769
770fn testCastEnumToTagType(value: Small2) void {
771 expect(@enumToInt(value) == 1);
772}
773
774const MultipleChoice = enum(u32) {
775 A = 20,
776 B = 40,
777 C = 60,
778 D = 1000,
779};
780
781test "enum with specified tag values" {
782 testEnumWithSpecifiedTagValues(MultipleChoice.C);
783 comptime testEnumWithSpecifiedTagValues(MultipleChoice.C);
784}
785
786fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void {
787 expect(@enumToInt(x) == 60);
788 expect(1234 == switch (x) {
789 MultipleChoice.A => 1,
790 MultipleChoice.B => 2,
791 MultipleChoice.C => u32(1234),
792 MultipleChoice.D => 4,
793 });
794}
795
796const MultipleChoice2 = enum(u32) {
797 Unspecified1,
798 A = 20,
799 Unspecified2,
800 B = 40,
801 Unspecified3,
802 C = 60,
803 Unspecified4,
804 D = 1000,
805 Unspecified5,
806};
807
808test "enum with specified and unspecified tag values" {
809 testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
810 comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
811}
812
813fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
814 expect(@enumToInt(x) == 1000);
815 expect(1234 == switch (x) {
816 MultipleChoice2.A => 1,
817 MultipleChoice2.B => 2,
818 MultipleChoice2.C => 3,
819 MultipleChoice2.D => u32(1234),
820 MultipleChoice2.Unspecified1 => 5,
821 MultipleChoice2.Unspecified2 => 6,
822 MultipleChoice2.Unspecified3 => 7,
823 MultipleChoice2.Unspecified4 => 8,
824 MultipleChoice2.Unspecified5 => 9,
825 });
826}
827
828test "cast integer literal to enum" {
829 expect(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
830 expect(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);
831}
832
833const EnumWithOneMember = enum {
834 Eof,
835};
836
837fn doALoopThing(id: EnumWithOneMember) void {
838 while (true) {
839 if (id == EnumWithOneMember.Eof) {
840 break;
841 }
842 @compileError("above if condition should be comptime");
843 }
844}
845
846test "comparison operator on enum with one member is comptime known" {
847 doALoopThing(EnumWithOneMember.Eof);
848}
849
850const State = enum {
851 Start,
852};
853test "switch on enum with one member is comptime known" {
854 var state = State.Start;
855 switch (state) {
856 State.Start => return,
857 }
858 @compileError("analysis should not reach here");
859}
860
861const EnumWithTagValues = enum(u4) {
862 A = 1 << 0,
863 B = 1 << 1,
864 C = 1 << 2,
865 D = 1 << 3,
866};
867test "enum with tag values don't require parens" {
868 expect(@enumToInt(EnumWithTagValues.C) == 0b0100);
869}
870
871test "enum with 1 field but explicit tag type should still have the tag type" {
872 const Enum = enum(u8) {
873 B = 2,
874 };
875 comptime @import("std").testing.expect(@sizeOf(Enum) == @sizeOf(u8));
876}
877
878test "empty extern enum with members" {
879 const E = extern enum {
880 A,
881 B,
882 C,
883 };
884 expect(@sizeOf(E) == @sizeOf(c_int));
885}
886
887test "tag name with assigned enum values" {
888 const LocalFoo = enum {
889 A = 1,
890 B = 0,
891 };
892 var b = LocalFoo.B;
893 expect(mem.eql(u8, @tagName(b), "B"));
894}
test/stage1/behavior/enum_with_members.zig created+27
...@@ -0,0 +1,27 @@
1const expect = @import("std").testing.expect;
2const mem = @import("std").mem;
3const fmt = @import("std").fmt;
4
5const ET = union(enum) {
6 SINT: i32,
7 UINT: u32,
8
9 pub fn print(a: *const ET, buf: []u8) anyerror!usize {
10 return switch (a.*) {
11 ET.SINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
12 ET.UINT => |x| fmt.formatIntBuf(buf, x, 10, false, 0),
13 };
14 }
15};
16
17test "enum with members" {
18 const a = ET{ .SINT = -42 };
19 const b = ET{ .UINT = 42 };
20 var buf: [20]u8 = undefined;
21
22 expect((a.print(buf[0..]) catch unreachable) == 3);
23 expect(mem.eql(u8, buf[0..3], "-42"));
24
25 expect((b.print(buf[0..]) catch unreachable) == 2);
26 expect(mem.eql(u8, buf[0..2], "42"));
27}
test/stage1/behavior/error.zig created+337
...@@ -0,0 +1,337 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectError = std.testing.expectError;
4const mem = std.mem;
5const builtin = @import("builtin");
6
7pub fn foo() anyerror!i32 {
8 const x = try bar();
9 return x + 1;
10}
11
12pub fn bar() anyerror!i32 {
13 return 13;
14}
15
16pub fn baz() anyerror!i32 {
17 const y = foo() catch 1234;
18 return y + 1;
19}
20
21test "error wrapping" {
22 expect((baz() catch unreachable) == 15);
23}
24
25fn gimmeItBroke() []const u8 {
26 return @errorName(error.ItBroke);
27}
28
29test "@errorName" {
30 expect(mem.eql(u8, @errorName(error.AnError), "AnError"));
31 expect(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName"));
32}
33
34test "error values" {
35 const a = @errorToInt(error.err1);
36 const b = @errorToInt(error.err2);
37 expect(a != b);
38}
39
40test "redefinition of error values allowed" {
41 shouldBeNotEqual(error.AnError, error.SecondError);
42}
43fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
44 if (a == b) unreachable;
45}
46
47test "error binary operator" {
48 const a = errBinaryOperatorG(true) catch 3;
49 const b = errBinaryOperatorG(false) catch 3;
50 expect(a == 3);
51 expect(b == 10);
52}
53fn errBinaryOperatorG(x: bool) anyerror!isize {
54 return if (x) error.ItBroke else isize(10);
55}
56
57test "unwrap simple value from error" {
58 const i = unwrapSimpleValueFromErrorDo() catch unreachable;
59 expect(i == 13);
60}
61fn unwrapSimpleValueFromErrorDo() anyerror!isize {
62 return 13;
63}
64
65test "error return in assignment" {
66 doErrReturnInAssignment() catch unreachable;
67}
68
69fn doErrReturnInAssignment() anyerror!void {
70 var x: i32 = undefined;
71 x = try makeANonErr();
72}
73
74fn makeANonErr() anyerror!i32 {
75 return 1;
76}
77
78test "error union type " {
79 testErrorUnionType();
80 comptime testErrorUnionType();
81}
82
83fn testErrorUnionType() void {
84 const x: anyerror!i32 = 1234;
85 if (x) |value| expect(value == 1234) else |_| unreachable;
86 expect(@typeId(@typeOf(x)) == builtin.TypeId.ErrorUnion);
87 expect(@typeId(@typeOf(x).ErrorSet) == builtin.TypeId.ErrorSet);
88 expect(@typeOf(x).ErrorSet == anyerror);
89}
90
91test "error set type" {
92 testErrorSetType();
93 comptime testErrorSetType();
94}
95
96const MyErrSet = error{
97 OutOfMemory,
98 FileNotFound,
99};
100
101fn testErrorSetType() void {
102 expect(@memberCount(MyErrSet) == 2);
103
104 const a: MyErrSet!i32 = 5678;
105 const b: MyErrSet!i32 = MyErrSet.OutOfMemory;
106
107 if (a) |value| expect(value == 5678) else |err| switch (err) {
108 error.OutOfMemory => unreachable,
109 error.FileNotFound => unreachable,
110 }
111}
112
113test "explicit error set cast" {
114 testExplicitErrorSetCast(Set1.A);
115 comptime testExplicitErrorSetCast(Set1.A);
116}
117
118const Set1 = error{
119 A,
120 B,
121};
122const Set2 = error{
123 A,
124 C,
125};
126
127fn testExplicitErrorSetCast(set1: Set1) void {
128 var x = @errSetCast(Set2, set1);
129 var y = @errSetCast(Set1, x);
130 expect(y == error.A);
131}
132
133test "comptime test error for empty error set" {
134 testComptimeTestErrorEmptySet(1234);
135 comptime testComptimeTestErrorEmptySet(1234);
136}
137
138const EmptyErrorSet = error{};
139
140fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) void {
141 if (x) |v| expect(v == 1234) else |err| @compileError("bad");
142}
143
144test "syntax: optional operator in front of error union operator" {
145 comptime {
146 expect(?(anyerror!i32) == ?(anyerror!i32));
147 }
148}
149
150test "comptime err to int of error set with only 1 possible value" {
151 testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
152 comptime testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
153}
154fn testErrToIntWithOnePossibleValue(
155 x: error{A},
156 comptime value: u32,
157) void {
158 if (@errorToInt(x) != value) {
159 @compileError("bad");
160 }
161}
162
163test "error union peer type resolution" {
164 testErrorUnionPeerTypeResolution(1);
165}
166
167fn testErrorUnionPeerTypeResolution(x: i32) void {
168 const y = switch (x) {
169 1 => bar_1(),
170 2 => baz_1(),
171 else => quux_1(),
172 };
173 if (y) |_| {
174 @panic("expected error");
175 } else |e| {
176 expect(e == error.A);
177 }
178}
179
180fn bar_1() anyerror {
181 return error.A;
182}
183
184fn baz_1() !i32 {
185 return error.B;
186}
187
188fn quux_1() !i32 {
189 return error.C;
190}
191
192test "error: fn returning empty error set can be passed as fn returning any error" {
193 entry();
194 comptime entry();
195}
196
197fn entry() void {
198 foo2(bar2);
199}
200
201fn foo2(f: fn () anyerror!void) void {
202 const x = f();
203}
204
205fn bar2() (error{}!void) {}
206
207test "error: Zero sized error set returned with value payload crash" {
208 _ = foo3(0);
209 _ = comptime foo3(0);
210}
211
212const Error = error{};
213fn foo3(b: usize) Error!usize {
214 return b;
215}
216
217test "error: Infer error set from literals" {
218 _ = nullLiteral("n") catch |err| handleErrors(err);
219 _ = floatLiteral("n") catch |err| handleErrors(err);
220 _ = intLiteral("n") catch |err| handleErrors(err);
221 _ = comptime nullLiteral("n") catch |err| handleErrors(err);
222 _ = comptime floatLiteral("n") catch |err| handleErrors(err);
223 _ = comptime intLiteral("n") catch |err| handleErrors(err);
224}
225
226fn handleErrors(err: var) noreturn {
227 switch (err) {
228 error.T => {},
229 }
230
231 unreachable;
232}
233
234fn nullLiteral(str: []const u8) !?i64 {
235 if (str[0] == 'n') return null;
236
237 return error.T;
238}
239
240fn floatLiteral(str: []const u8) !?f64 {
241 if (str[0] == 'n') return 1.0;
242
243 return error.T;
244}
245
246fn intLiteral(str: []const u8) !?i64 {
247 if (str[0] == 'n') return 1;
248
249 return error.T;
250}
251
252test "nested error union function call in optional unwrap" {
253 const S = struct {
254 const Foo = struct {
255 a: i32,
256 };
257
258 fn errorable() !i32 {
259 var x: Foo = (try getFoo()) orelse return error.Other;
260 return x.a;
261 }
262
263 fn errorable2() !i32 {
264 var x: Foo = (try getFoo2()) orelse return error.Other;
265 return x.a;
266 }
267
268 fn errorable3() !i32 {
269 var x: Foo = (try getFoo3()) orelse return error.Other;
270 return x.a;
271 }
272
273 fn getFoo() anyerror!?Foo {
274 return Foo{ .a = 1234 };
275 }
276
277 fn getFoo2() anyerror!?Foo {
278 return error.Failure;
279 }
280
281 fn getFoo3() anyerror!?Foo {
282 return null;
283 }
284 };
285 expect((try S.errorable()) == 1234);
286 expectError(error.Failure, S.errorable2());
287 expectError(error.Other, S.errorable3());
288 comptime {
289 expect((try S.errorable()) == 1234);
290 expectError(error.Failure, S.errorable2());
291 expectError(error.Other, S.errorable3());
292 }
293}
294
295test "widen cast integer payload of error union function call" {
296 const S = struct {
297 fn errorable() !u64 {
298 var x = u64(try number());
299 return x;
300 }
301
302 fn number() anyerror!u32 {
303 return 1234;
304 }
305 };
306 expect((try S.errorable()) == 1234);
307}
308
309test "return function call to error set from error union function" {
310 const S = struct {
311 fn errorable() anyerror!i32 {
312 return fail();
313 }
314
315 fn fail() anyerror {
316 return error.Failure;
317 }
318 };
319 expectError(error.Failure, S.errorable());
320 comptime expectError(error.Failure, S.errorable());
321}
322
323test "optional error set is the same size as error set" {
324 comptime expect(@sizeOf(?anyerror) == @sizeOf(anyerror));
325 const S = struct {
326 fn returnsOptErrSet() ?anyerror {
327 return null;
328 }
329 };
330 expect(S.returnsOptErrSet() == null);
331 comptime expect(S.returnsOptErrSet() == null);
332}
333
334test "debug info for optional error set" {
335 const SomeError = error{Hello};
336 var a_local_variable: ?SomeError = null;
337}
test/stage1/behavior/eval.zig created+778
...@@ -0,0 +1,778 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const builtin = @import("builtin");
4
5test "compile time recursion" {
6 expect(some_data.len == 21);
7}
8var some_data: [@intCast(usize, fibonacci(7))]u8 = undefined;
9fn fibonacci(x: i32) i32 {
10 if (x <= 1) return 1;
11 return fibonacci(x - 1) + fibonacci(x - 2);
12}
13
14fn unwrapAndAddOne(blah: ?i32) i32 {
15 return blah.? + 1;
16}
17const should_be_1235 = unwrapAndAddOne(1234);
18test "static add one" {
19 expect(should_be_1235 == 1235);
20}
21
22test "inlined loop" {
23 comptime var i = 0;
24 comptime var sum = 0;
25 inline while (i <= 5) : (i += 1)
26 sum += i;
27 expect(sum == 15);
28}
29
30fn gimme1or2(comptime a: bool) i32 {
31 const x: i32 = 1;
32 const y: i32 = 2;
33 comptime var z: i32 = if (a) x else y;
34 return z;
35}
36test "inline variable gets result of const if" {
37 expect(gimme1or2(true) == 1);
38 expect(gimme1or2(false) == 2);
39}
40
41test "static function evaluation" {
42 expect(statically_added_number == 3);
43}
44const statically_added_number = staticAdd(1, 2);
45fn staticAdd(a: i32, b: i32) i32 {
46 return a + b;
47}
48
49test "const expr eval on single expr blocks" {
50 expect(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
51 comptime expect(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
52}
53
54fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) i32 {
55 const literal = 3;
56
57 const result = if (b) b: {
58 break :b literal;
59 } else b: {
60 break :b x;
61 };
62
63 return result;
64}
65
66test "statically initialized list" {
67 expect(static_point_list[0].x == 1);
68 expect(static_point_list[0].y == 2);
69 expect(static_point_list[1].x == 3);
70 expect(static_point_list[1].y == 4);
71}
72const Point = struct {
73 x: i32,
74 y: i32,
75};
76const static_point_list = []Point{
77 makePoint(1, 2),
78 makePoint(3, 4),
79};
80fn makePoint(x: i32, y: i32) Point {
81 return Point{
82 .x = x,
83 .y = y,
84 };
85}
86
87test "static eval list init" {
88 expect(static_vec3.data[2] == 1.0);
89 expect(vec3(0.0, 0.0, 3.0).data[2] == 3.0);
90}
91const static_vec3 = vec3(0.0, 0.0, 1.0);
92pub const Vec3 = struct {
93 data: [3]f32,
94};
95pub fn vec3(x: f32, y: f32, z: f32) Vec3 {
96 return Vec3{ .data = []f32{
97 x,
98 y,
99 z,
100 } };
101}
102
103test "constant expressions" {
104 var array: [array_size]u8 = undefined;
105 expect(@sizeOf(@typeOf(array)) == 20);
106}
107const array_size: u8 = 20;
108
109test "constant struct with negation" {
110 expect(vertices[0].x == -0.6);
111}
112const Vertex = struct {
113 x: f32,
114 y: f32,
115 r: f32,
116 g: f32,
117 b: f32,
118};
119const vertices = []Vertex{
120 Vertex{
121 .x = -0.6,
122 .y = -0.4,
123 .r = 1.0,
124 .g = 0.0,
125 .b = 0.0,
126 },
127 Vertex{
128 .x = 0.6,
129 .y = -0.4,
130 .r = 0.0,
131 .g = 1.0,
132 .b = 0.0,
133 },
134 Vertex{
135 .x = 0.0,
136 .y = 0.6,
137 .r = 0.0,
138 .g = 0.0,
139 .b = 1.0,
140 },
141};
142
143test "statically initialized struct" {
144 st_init_str_foo.x += 1;
145 expect(st_init_str_foo.x == 14);
146}
147const StInitStrFoo = struct {
148 x: i32,
149 y: bool,
150};
151var st_init_str_foo = StInitStrFoo{
152 .x = 13,
153 .y = true,
154};
155
156test "statically initalized array literal" {
157 const y: [4]u8 = st_init_arr_lit_x;
158 expect(y[3] == 4);
159}
160const st_init_arr_lit_x = []u8{
161 1,
162 2,
163 3,
164 4,
165};
166
167test "const slice" {
168 comptime {
169 const a = "1234567890";
170 expect(a.len == 10);
171 const b = a[1..2];
172 expect(b.len == 1);
173 expect(b[0] == '2');
174 }
175}
176
177test "try to trick eval with runtime if" {
178 expect(testTryToTrickEvalWithRuntimeIf(true) == 10);
179}
180
181fn testTryToTrickEvalWithRuntimeIf(b: bool) usize {
182 comptime var i: usize = 0;
183 inline while (i < 10) : (i += 1) {
184 const result = if (b) false else true;
185 }
186 comptime {
187 return i;
188 }
189}
190
191fn max(comptime T: type, a: T, b: T) T {
192 if (T == bool) {
193 return a or b;
194 } else if (a > b) {
195 return a;
196 } else {
197 return b;
198 }
199}
200fn letsTryToCompareBools(a: bool, b: bool) bool {
201 return max(bool, a, b);
202}
203test "inlined block and runtime block phi" {
204 expect(letsTryToCompareBools(true, true));
205 expect(letsTryToCompareBools(true, false));
206 expect(letsTryToCompareBools(false, true));
207 expect(!letsTryToCompareBools(false, false));
208
209 comptime {
210 expect(letsTryToCompareBools(true, true));
211 expect(letsTryToCompareBools(true, false));
212 expect(letsTryToCompareBools(false, true));
213 expect(!letsTryToCompareBools(false, false));
214 }
215}
216
217const CmdFn = struct {
218 name: []const u8,
219 func: fn (i32) i32,
220};
221
222const cmd_fns = []CmdFn{
223 CmdFn{
224 .name = "one",
225 .func = one,
226 },
227 CmdFn{
228 .name = "two",
229 .func = two,
230 },
231 CmdFn{
232 .name = "three",
233 .func = three,
234 },
235};
236fn one(value: i32) i32 {
237 return value + 1;
238}
239fn two(value: i32) i32 {
240 return value + 2;
241}
242fn three(value: i32) i32 {
243 return value + 3;
244}
245
246fn performFn(comptime prefix_char: u8, start_value: i32) i32 {
247 var result: i32 = start_value;
248 comptime var i = 0;
249 inline while (i < cmd_fns.len) : (i += 1) {
250 if (cmd_fns[i].name[0] == prefix_char) {
251 result = cmd_fns[i].func(result);
252 }
253 }
254 return result;
255}
256
257test "comptime iterate over fn ptr list" {
258 expect(performFn('t', 1) == 6);
259 expect(performFn('o', 0) == 1);
260 expect(performFn('w', 99) == 99);
261}
262
263test "eval @setRuntimeSafety at compile-time" {
264 const result = comptime fnWithSetRuntimeSafety();
265 expect(result == 1234);
266}
267
268fn fnWithSetRuntimeSafety() i32 {
269 @setRuntimeSafety(true);
270 return 1234;
271}
272
273test "eval @setFloatMode at compile-time" {
274 const result = comptime fnWithFloatMode();
275 expect(result == 1234.0);
276}
277
278fn fnWithFloatMode() f32 {
279 @setFloatMode(builtin.FloatMode.Strict);
280 return 1234.0;
281}
282
283const SimpleStruct = struct {
284 field: i32,
285
286 fn method(self: *const SimpleStruct) i32 {
287 return self.field + 3;
288 }
289};
290
291var simple_struct = SimpleStruct{ .field = 1234 };
292
293const bound_fn = simple_struct.method;
294
295test "call method on bound fn referring to var instance" {
296 expect(bound_fn() == 1237);
297}
298
299test "ptr to local array argument at comptime" {
300 comptime {
301 var bytes: [10]u8 = undefined;
302 modifySomeBytes(bytes[0..]);
303 expect(bytes[0] == 'a');
304 expect(bytes[9] == 'b');
305 }
306}
307
308fn modifySomeBytes(bytes: []u8) void {
309 bytes[0] = 'a';
310 bytes[9] = 'b';
311}
312
313test "comparisons 0 <= uint and 0 > uint should be comptime" {
314 testCompTimeUIntComparisons(1234);
315}
316fn testCompTimeUIntComparisons(x: u32) void {
317 if (!(0 <= x)) {
318 @compileError("this condition should be comptime known");
319 }
320 if (0 > x) {
321 @compileError("this condition should be comptime known");
322 }
323 if (!(x >= 0)) {
324 @compileError("this condition should be comptime known");
325 }
326 if (x < 0) {
327 @compileError("this condition should be comptime known");
328 }
329}
330
331test "const ptr to variable data changes at runtime" {
332 expect(foo_ref.name[0] == 'a');
333 foo_ref.name = "b";
334 expect(foo_ref.name[0] == 'b');
335}
336
337const Foo = struct {
338 name: []const u8,
339};
340
341var foo_contents = Foo{ .name = "a" };
342const foo_ref = &foo_contents;
343
344test "create global array with for loop" {
345 expect(global_array[5] == 5 * 5);
346 expect(global_array[9] == 9 * 9);
347}
348
349const global_array = x: {
350 var result: [10]usize = undefined;
351 for (result) |*item, index| {
352 item.* = index * index;
353 }
354 break :x result;
355};
356
357test "compile-time downcast when the bits fit" {
358 comptime {
359 const spartan_count: u16 = 255;
360 const byte = @intCast(u8, spartan_count);
361 expect(byte == 255);
362 }
363}
364
365const hi1 = "hi";
366const hi2 = hi1;
367test "const global shares pointer with other same one" {
368 assertEqualPtrs(&hi1[0], &hi2[0]);
369 comptime expect(&hi1[0] == &hi2[0]);
370}
371fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) void {
372 expect(ptr1 == ptr2);
373}
374
375test "@setEvalBranchQuota" {
376 comptime {
377 // 1001 for the loop and then 1 more for the expect fn call
378 @setEvalBranchQuota(1002);
379 var i = 0;
380 var sum = 0;
381 while (i < 1001) : (i += 1) {
382 sum += i;
383 }
384 expect(sum == 500500);
385 }
386}
387
388// TODO test "float literal at compile time not lossy" {
389// TODO expect(16777216.0 + 1.0 == 16777217.0);
390// TODO expect(9007199254740992.0 + 1.0 == 9007199254740993.0);
391// TODO }
392
393test "f32 at compile time is lossy" {
394 expect(f32(1 << 24) + 1 == 1 << 24);
395}
396
397test "f64 at compile time is lossy" {
398 expect(f64(1 << 53) + 1 == 1 << 53);
399}
400
401test "f128 at compile time is lossy" {
402 expect(f128(10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
403}
404
405comptime {
406 expect(f128(1 << 113) == 10384593717069655257060992658440192);
407}
408
409pub fn TypeWithCompTimeSlice(comptime field_name: []const u8) type {
410 return struct {
411 pub const Node = struct {};
412 };
413}
414
415test "string literal used as comptime slice is memoized" {
416 const a = "link";
417 const b = "link";
418 comptime expect(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
419 comptime expect(TypeWithCompTimeSlice("link").Node == TypeWithCompTimeSlice("link").Node);
420}
421
422test "comptime slice of undefined pointer of length 0" {
423 const slice1 = ([*]i32)(undefined)[0..0];
424 expect(slice1.len == 0);
425 const slice2 = ([*]i32)(undefined)[100..100];
426 expect(slice2.len == 0);
427}
428
429fn copyWithPartialInline(s: []u32, b: []u8) void {
430 comptime var i: usize = 0;
431 inline while (i < 4) : (i += 1) {
432 s[i] = 0;
433 s[i] |= u32(b[i * 4 + 0]) << 24;
434 s[i] |= u32(b[i * 4 + 1]) << 16;
435 s[i] |= u32(b[i * 4 + 2]) << 8;
436 s[i] |= u32(b[i * 4 + 3]) << 0;
437 }
438}
439
440test "binary math operator in partially inlined function" {
441 var s: [4]u32 = undefined;
442 var b: [16]u8 = undefined;
443
444 for (b) |*r, i|
445 r.* = @intCast(u8, i + 1);
446
447 copyWithPartialInline(s[0..], b[0..]);
448 expect(s[0] == 0x1020304);
449 expect(s[1] == 0x5060708);
450 expect(s[2] == 0x90a0b0c);
451 expect(s[3] == 0xd0e0f10);
452}
453
454test "comptime function with the same args is memoized" {
455 comptime {
456 expect(MakeType(i32) == MakeType(i32));
457 expect(MakeType(i32) != MakeType(f64));
458 }
459}
460
461fn MakeType(comptime T: type) type {
462 return struct {
463 field: T,
464 };
465}
466
467test "comptime function with mutable pointer is not memoized" {
468 comptime {
469 var x: i32 = 1;
470 const ptr = &x;
471 increment(ptr);
472 increment(ptr);
473 expect(x == 3);
474 }
475}
476
477fn increment(value: *i32) void {
478 value.* += 1;
479}
480
481fn generateTable(comptime T: type) [1010]T {
482 var res: [1010]T = undefined;
483 var i: usize = 0;
484 while (i < 1010) : (i += 1) {
485 res[i] = @intCast(T, i);
486 }
487 return res;
488}
489
490fn doesAlotT(comptime T: type, value: usize) T {
491 @setEvalBranchQuota(5000);
492 const table = comptime blk: {
493 break :blk generateTable(T);
494 };
495 return table[value];
496}
497
498test "@setEvalBranchQuota at same scope as generic function call" {
499 expect(doesAlotT(u32, 2) == 2);
500}
501
502test "comptime slice of slice preserves comptime var" {
503 comptime {
504 var buff: [10]u8 = undefined;
505 buff[0..][0..][0] = 1;
506 expect(buff[0..][0..][0] == 1);
507 }
508}
509
510test "comptime slice of pointer preserves comptime var" {
511 comptime {
512 var buff: [10]u8 = undefined;
513 var a = buff[0..].ptr;
514 a[0..1][0] = 1;
515 expect(buff[0..][0..][0] == 1);
516 }
517}
518
519const SingleFieldStruct = struct {
520 x: i32,
521
522 fn read_x(self: *const SingleFieldStruct) i32 {
523 return self.x;
524 }
525};
526test "const ptr to comptime mutable data is not memoized" {
527 comptime {
528 var foo = SingleFieldStruct{ .x = 1 };
529 expect(foo.read_x() == 1);
530 foo.x = 2;
531 expect(foo.read_x() == 2);
532 }
533}
534
535test "array concat of slices gives slice" {
536 comptime {
537 var a: []const u8 = "aoeu";
538 var b: []const u8 = "asdf";
539 const c = a ++ b;
540 expect(std.mem.eql(u8, c, "aoeuasdf"));
541 }
542}
543
544test "comptime shlWithOverflow" {
545 const ct_shifted: u64 = comptime amt: {
546 var amt = u64(0);
547 _ = @shlWithOverflow(u64, ~u64(0), 16, &amt);
548 break :amt amt;
549 };
550
551 const rt_shifted: u64 = amt: {
552 var amt = u64(0);
553 _ = @shlWithOverflow(u64, ~u64(0), 16, &amt);
554 break :amt amt;
555 };
556
557 expect(ct_shifted == rt_shifted);
558}
559
560test "runtime 128 bit integer division" {
561 var a: u128 = 152313999999999991610955792383;
562 var b: u128 = 10000000000000000000;
563 var c = a / b;
564 expect(c == 15231399999);
565}
566
567pub const Info = struct {
568 version: u8,
569};
570
571pub const diamond_info = Info{ .version = 0 };
572
573test "comptime modification of const struct field" {
574 comptime {
575 var res = diamond_info;
576 res.version = 1;
577 expect(diamond_info.version == 0);
578 expect(res.version == 1);
579 }
580}
581
582test "pointer to type" {
583 comptime {
584 var T: type = i32;
585 expect(T == i32);
586 var ptr = &T;
587 expect(@typeOf(ptr) == *type);
588 ptr.* = f32;
589 expect(T == f32);
590 expect(*T == *f32);
591 }
592}
593
594test "slice of type" {
595 comptime {
596 var types_array = []type{ i32, f64, type };
597 for (types_array) |T, i| {
598 switch (i) {
599 0 => expect(T == i32),
600 1 => expect(T == f64),
601 2 => expect(T == type),
602 else => unreachable,
603 }
604 }
605 for (types_array[0..]) |T, i| {
606 switch (i) {
607 0 => expect(T == i32),
608 1 => expect(T == f64),
609 2 => expect(T == type),
610 else => unreachable,
611 }
612 }
613 }
614}
615
616const Wrapper = struct {
617 T: type,
618};
619
620fn wrap(comptime T: type) Wrapper {
621 return Wrapper{ .T = T };
622}
623
624test "function which returns struct with type field causes implicit comptime" {
625 const ty = wrap(i32).T;
626 expect(ty == i32);
627}
628
629test "call method with comptime pass-by-non-copying-value self parameter" {
630 const S = struct {
631 a: u8,
632
633 fn b(comptime s: @This()) u8 {
634 return s.a;
635 }
636 };
637
638 const s = S{ .a = 2 };
639 var b = s.b();
640 expect(b == 2);
641}
642
643test "@tagName of @typeId" {
644 const str = @tagName(@typeId(u8));
645 expect(std.mem.eql(u8, str, "Int"));
646}
647
648test "setting backward branch quota just before a generic fn call" {
649 @setEvalBranchQuota(1001);
650 loopNTimes(1001);
651}
652
653fn loopNTimes(comptime n: usize) void {
654 comptime var i = 0;
655 inline while (i < n) : (i += 1) {}
656}
657
658test "variable inside inline loop that has different types on different iterations" {
659 testVarInsideInlineLoop(true, u32(42));
660}
661
662fn testVarInsideInlineLoop(args: ...) void {
663 comptime var i = 0;
664 inline while (i < args.len) : (i += 1) {
665 const x = args[i];
666 if (i == 0) expect(x);
667 if (i == 1) expect(x == 42);
668 }
669}
670
671test "inline for with same type but different values" {
672 var res: usize = 0;
673 inline for ([]type{ [2]u8, [1]u8, [2]u8 }) |T| {
674 var a: T = undefined;
675 res += a.len;
676 }
677 expect(res == 5);
678}
679
680test "refer to the type of a generic function" {
681 const Func = fn (type) void;
682 const f: Func = doNothingWithType;
683 f(i32);
684}
685
686fn doNothingWithType(comptime T: type) void {}
687
688test "zero extend from u0 to u1" {
689 var zero_u0: u0 = 0;
690 var zero_u1: u1 = zero_u0;
691 expect(zero_u1 == 0);
692}
693
694test "bit shift a u1" {
695 var x: u1 = 1;
696 var y = x << 0;
697 expect(y == 1);
698}
699
700test "@bytesToslice on a packed struct" {
701 const F = packed struct {
702 a: u8,
703 };
704
705 var b = [1]u8{9};
706 var f = @bytesToSlice(F, b);
707 expect(f[0].a == 9);
708}
709
710test "comptime pointer cast array and then slice" {
711 const array = []u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
712
713 const ptrA: [*]const u8 = @ptrCast([*]const u8, &array);
714 const sliceA: []const u8 = ptrA[0..2];
715
716 const ptrB: [*]const u8 = &array;
717 const sliceB: []const u8 = ptrB[0..2];
718
719 expect(sliceA[1] == 2);
720 expect(sliceB[1] == 2);
721}
722
723test "slice bounds in comptime concatenation" {
724 const bs = comptime blk: {
725 const b = c"........1........";
726 break :blk b[8..9];
727 };
728 const str = "" ++ bs;
729 expect(str.len == 1);
730 expect(std.mem.eql(u8, str, "1"));
731
732 const str2 = bs ++ "";
733 expect(str2.len == 1);
734 expect(std.mem.eql(u8, str2, "1"));
735}
736
737test "comptime bitwise operators" {
738 comptime {
739 expect(3 & 1 == 1);
740 expect(3 & -1 == 3);
741 expect(-3 & -1 == -3);
742 expect(3 | -1 == -1);
743 expect(-3 | -1 == -1);
744 expect(3 ^ -1 == -4);
745 expect(-3 ^ -1 == 2);
746 expect(~i8(-1) == 0);
747 expect(~i128(-1) == 0);
748 expect(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
749 expect(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
750 expect(~u128(0) == 0xffffffffffffffffffffffffffffffff);
751 }
752}
753
754test "*align(1) u16 is the same as *align(1:0:2) u16" {
755 comptime {
756 expect(*align(1:0:2) u16 == *align(1) u16);
757 // TODO add parsing support for this syntax
758 //expect(*align(:0:2) u16 == *u16);
759 }
760}
761
762test "array concatenation forces comptime" {
763 var a = oneItem(3) ++ oneItem(4);
764 expect(std.mem.eql(i32, a, []i32{ 3, 4 }));
765}
766
767test "array multiplication forces comptime" {
768 var a = oneItem(3) ** scalar(2);
769 expect(std.mem.eql(i32, a, []i32{ 3, 3 }));
770}
771
772fn oneItem(x: i32) [1]i32 {
773 return []i32{x};
774}
775
776fn scalar(x: u32) u32 {
777 return x;
778}
test/stage1/behavior/field_parent_ptr.zig created+41
...@@ -0,0 +1,41 @@
1const expect = @import("std").testing.expect;
2
3test "@fieldParentPtr non-first field" {
4 testParentFieldPtr(&foo.c);
5 comptime testParentFieldPtr(&foo.c);
6}
7
8test "@fieldParentPtr first field" {
9 testParentFieldPtrFirst(&foo.a);
10 comptime testParentFieldPtrFirst(&foo.a);
11}
12
13const Foo = struct {
14 a: bool,
15 b: f32,
16 c: i32,
17 d: i32,
18};
19
20const foo = Foo{
21 .a = true,
22 .b = 0.123,
23 .c = 1234,
24 .d = -10,
25};
26
27fn testParentFieldPtr(c: *const i32) void {
28 expect(c == &foo.c);
29
30 const base = @fieldParentPtr(Foo, "c", c);
31 expect(base == &foo);
32 expect(&base.c == c);
33}
34
35fn testParentFieldPtrFirst(a: *const bool) void {
36 expect(a == &foo.a);
37
38 const base = @fieldParentPtr(Foo, "a", a);
39 expect(base == &foo);
40 expect(&base.a == a);
41}
test/stage1/behavior/fn.zig created+208
...@@ -0,0 +1,208 @@
1const expect = @import("std").testing.expect;
2
3test "params" {
4 expect(testParamsAdd(22, 11) == 33);
5}
6fn testParamsAdd(a: i32, b: i32) i32 {
7 return a + b;
8}
9
10test "local variables" {
11 testLocVars(2);
12}
13fn testLocVars(b: i32) void {
14 const a: i32 = 1;
15 if (a + b != 3) unreachable;
16}
17
18test "void parameters" {
19 voidFun(1, void{}, 2, {});
20}
21fn voidFun(a: i32, b: void, c: i32, d: void) void {
22 const v = b;
23 const vv: void = if (a == 1) v else {};
24 expect(a + c == 3);
25 return vv;
26}
27
28test "mutable local variables" {
29 var zero: i32 = 0;
30 expect(zero == 0);
31
32 var i = i32(0);
33 while (i != 3) {
34 i += 1;
35 }
36 expect(i == 3);
37}
38
39test "separate block scopes" {
40 {
41 const no_conflict: i32 = 5;
42 expect(no_conflict == 5);
43 }
44
45 const c = x: {
46 const no_conflict = i32(10);
47 break :x no_conflict;
48 };
49 expect(c == 10);
50}
51
52test "call function with empty string" {
53 acceptsString("");
54}
55
56fn acceptsString(foo: []u8) void {}
57
58fn @"weird function name"() i32 {
59 return 1234;
60}
61test "weird function name" {
62 expect(@"weird function name"() == 1234);
63}
64
65test "implicit cast function unreachable return" {
66 wantsFnWithVoid(fnWithUnreachable);
67}
68
69fn wantsFnWithVoid(f: fn () void) void {}
70
71fn fnWithUnreachable() noreturn {
72 unreachable;
73}
74
75test "function pointers" {
76 const fns = []@typeOf(fn1){
77 fn1,
78 fn2,
79 fn3,
80 fn4,
81 };
82 for (fns) |f, i| {
83 expect(f() == @intCast(u32, i) + 5);
84 }
85}
86fn fn1() u32 {
87 return 5;
88}
89fn fn2() u32 {
90 return 6;
91}
92fn fn3() u32 {
93 return 7;
94}
95fn fn4() u32 {
96 return 8;
97}
98
99test "inline function call" {
100 expect(@inlineCall(add, 3, 9) == 12);
101}
102
103fn add(a: i32, b: i32) i32 {
104 return a + b;
105}
106
107test "number literal as an argument" {
108 numberLiteralArg(3);
109 comptime numberLiteralArg(3);
110}
111
112fn numberLiteralArg(a: var) void {
113 expect(a == 3);
114}
115
116test "assign inline fn to const variable" {
117 const a = inlineFn;
118 a();
119}
120
121inline fn inlineFn() void {}
122
123test "pass by non-copying value" {
124 expect(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
125}
126
127const Point = struct {
128 x: i32,
129 y: i32,
130};
131
132fn addPointCoords(pt: Point) i32 {
133 return pt.x + pt.y;
134}
135
136test "pass by non-copying value through var arg" {
137 expect(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3);
138}
139
140fn addPointCoordsVar(pt: var) i32 {
141 comptime expect(@typeOf(pt) == Point);
142 return pt.x + pt.y;
143}
144
145test "pass by non-copying value as method" {
146 var pt = Point2{ .x = 1, .y = 2 };
147 expect(pt.addPointCoords() == 3);
148}
149
150const Point2 = struct {
151 x: i32,
152 y: i32,
153
154 fn addPointCoords(self: Point2) i32 {
155 return self.x + self.y;
156 }
157};
158
159test "pass by non-copying value as method, which is generic" {
160 var pt = Point3{ .x = 1, .y = 2 };
161 expect(pt.addPointCoords(i32) == 3);
162}
163
164const Point3 = struct {
165 x: i32,
166 y: i32,
167
168 fn addPointCoords(self: Point3, comptime T: type) i32 {
169 return self.x + self.y;
170 }
171};
172
173test "pass by non-copying value as method, at comptime" {
174 comptime {
175 var pt = Point2{ .x = 1, .y = 2 };
176 expect(pt.addPointCoords() == 3);
177 }
178}
179
180fn outer(y: u32) fn (u32) u32 {
181 const Y = @typeOf(y);
182 const st = struct {
183 fn get(z: u32) u32 {
184 return z + @sizeOf(Y);
185 }
186 };
187 return st.get;
188}
189
190test "return inner function which references comptime variable of outer function" {
191 var func = outer(10);
192 expect(func(3) == 7);
193}
194
195test "extern struct with stdcallcc fn pointer" {
196 const S = extern struct {
197 ptr: stdcallcc fn () i32,
198
199 stdcallcc fn foo() i32 {
200 return 1234;
201 }
202 };
203
204 var s: S = undefined;
205 s.ptr = S.foo;
206 expect(s.ptr() == 1234);
207}
208
test/stage1/behavior/fn_in_struct_in_comptime.zig created+17
...@@ -0,0 +1,17 @@
1const expect = @import("std").testing.expect;
2
3fn get_foo() fn (*u8) usize {
4 comptime {
5 return struct {
6 fn func(ptr: *u8) usize {
7 var u = @ptrToInt(ptr);
8 return u;
9 }
10 }.func;
11 }
12}
13
14test "define a function in an anonymous struct in comptime" {
15 const foo = get_foo();
16 expect(foo(@intToPtr(*u8, 12345)) == 12345);
17}
test/stage1/behavior/for.zig created+106
...@@ -0,0 +1,106 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const mem = std.mem;
4
5test "continue in for loop" {
6 const array = []i32{
7 1,
8 2,
9 3,
10 4,
11 5,
12 };
13 var sum: i32 = 0;
14 for (array) |x| {
15 sum += x;
16 if (x < 3) {
17 continue;
18 }
19 break;
20 }
21 if (sum != 6) unreachable;
22}
23
24test "for loop with pointer elem var" {
25 const source = "abcdefg";
26 var target: [source.len]u8 = undefined;
27 mem.copy(u8, target[0..], source);
28 mangleString(target[0..]);
29 expect(mem.eql(u8, target, "bcdefgh"));
30}
31fn mangleString(s: []u8) void {
32 for (s) |*c| {
33 c.* += 1;
34 }
35}
36
37test "basic for loop" {
38 const expected_result = []u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3;
39
40 var buffer: [expected_result.len]u8 = undefined;
41 var buf_index: usize = 0;
42
43 const array = []u8{ 9, 8, 7, 6 };
44 for (array) |item| {
45 buffer[buf_index] = item;
46 buf_index += 1;
47 }
48 for (array) |item, index| {
49 buffer[buf_index] = @intCast(u8, index);
50 buf_index += 1;
51 }
52 const array_ptr = &array;
53 for (array_ptr) |item| {
54 buffer[buf_index] = item;
55 buf_index += 1;
56 }
57 for (array_ptr) |item, index| {
58 buffer[buf_index] = @intCast(u8, index);
59 buf_index += 1;
60 }
61 const unknown_size: []const u8 = array;
62 for (unknown_size) |item| {
63 buffer[buf_index] = item;
64 buf_index += 1;
65 }
66 for (unknown_size) |item, index| {
67 buffer[buf_index] = @intCast(u8, index);
68 buf_index += 1;
69 }
70
71 expect(mem.eql(u8, buffer[0..buf_index], expected_result));
72}
73
74test "break from outer for loop" {
75 testBreakOuter();
76 comptime testBreakOuter();
77}
78
79fn testBreakOuter() void {
80 var array = "aoeu";
81 var count: usize = 0;
82 outer: for (array) |_| {
83 for (array) |_| {
84 count += 1;
85 break :outer;
86 }
87 }
88 expect(count == 1);
89}
90
91test "continue outer for loop" {
92 testContinueOuter();
93 comptime testContinueOuter();
94}
95
96fn testContinueOuter() void {
97 var array = "aoeu";
98 var counter: usize = 0;
99 outer: for (array) |_| {
100 for (array) |_| {
101 counter += 1;
102 continue :outer;
103 }
104 }
105 expect(counter == array.len);
106}
test/stage1/behavior/generics.zig created+151
...@@ -0,0 +1,151 @@
1const expect = @import("std").testing.expect;
2
3test "simple generic fn" {
4 expect(max(i32, 3, -1) == 3);
5 expect(max(f32, 0.123, 0.456) == 0.456);
6 expect(add(2, 3) == 5);
7}
8
9fn max(comptime T: type, a: T, b: T) T {
10 return if (a > b) a else b;
11}
12
13fn add(comptime a: i32, b: i32) i32 {
14 return (comptime a) + b;
15}
16
17const the_max = max(u32, 1234, 5678);
18test "compile time generic eval" {
19 expect(the_max == 5678);
20}
21
22fn gimmeTheBigOne(a: u32, b: u32) u32 {
23 return max(u32, a, b);
24}
25
26fn shouldCallSameInstance(a: u32, b: u32) u32 {
27 return max(u32, a, b);
28}
29
30fn sameButWithFloats(a: f64, b: f64) f64 {
31 return max(f64, a, b);
32}
33
34test "fn with comptime args" {
35 expect(gimmeTheBigOne(1234, 5678) == 5678);
36 expect(shouldCallSameInstance(34, 12) == 34);
37 expect(sameButWithFloats(0.43, 0.49) == 0.49);
38}
39
40test "var params" {
41 expect(max_i32(12, 34) == 34);
42 expect(max_f64(1.2, 3.4) == 3.4);
43}
44
45comptime {
46 expect(max_i32(12, 34) == 34);
47 expect(max_f64(1.2, 3.4) == 3.4);
48}
49
50fn max_var(a: var, b: var) @typeOf(a + b) {
51 return if (a > b) a else b;
52}
53
54fn max_i32(a: i32, b: i32) i32 {
55 return max_var(a, b);
56}
57
58fn max_f64(a: f64, b: f64) f64 {
59 return max_var(a, b);
60}
61
62pub fn List(comptime T: type) type {
63 return SmallList(T, 8);
64}
65
66pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type {
67 return struct {
68 items: []T,
69 length: usize,
70 prealloc_items: [STATIC_SIZE]T,
71 };
72}
73
74test "function with return type type" {
75 var list: List(i32) = undefined;
76 var list2: List(i32) = undefined;
77 list.length = 10;
78 list2.length = 10;
79 expect(list.prealloc_items.len == 8);
80 expect(list2.prealloc_items.len == 8);
81}
82
83test "generic struct" {
84 var a1 = GenNode(i32){
85 .value = 13,
86 .next = null,
87 };
88 var b1 = GenNode(bool){
89 .value = true,
90 .next = null,
91 };
92 expect(a1.value == 13);
93 expect(a1.value == a1.getVal());
94 expect(b1.getVal());
95}
96fn GenNode(comptime T: type) type {
97 return struct {
98 value: T,
99 next: ?*GenNode(T),
100 fn getVal(n: *const GenNode(T)) T {
101 return n.value;
102 }
103 };
104}
105
106test "const decls in struct" {
107 expect(GenericDataThing(3).count_plus_one == 4);
108}
109fn GenericDataThing(comptime count: isize) type {
110 return struct {
111 const count_plus_one = count + 1;
112 };
113}
114
115test "use generic param in generic param" {
116 expect(aGenericFn(i32, 3, 4) == 7);
117}
118fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
119 return a + b;
120}
121
122test "generic fn with implicit cast" {
123 expect(getFirstByte(u8, []u8{13}) == 13);
124 expect(getFirstByte(u16, []u16{
125 0,
126 13,
127 }) == 0);
128}
129fn getByte(ptr: ?*const u8) u8 {
130 return ptr.?.*;
131}
132fn getFirstByte(comptime T: type, mem: []const T) u8 {
133 return getByte(@ptrCast(*const u8, &mem[0]));
134}
135
136const foos = []fn (var) bool{
137 foo1,
138 foo2,
139};
140
141fn foo1(arg: var) bool {
142 return arg;
143}
144fn foo2(arg: var) bool {
145 return !arg;
146}
147
148test "array of generic fns" {
149 expect(foos[0](true));
150 expect(!foos[1](true));
151}
test/stage1/behavior/if.zig created+37
...@@ -0,0 +1,37 @@
1const expect = @import("std").testing.expect;
2
3test "if statements" {
4 shouldBeEqual(1, 1);
5 firstEqlThird(2, 1, 2);
6}
7fn shouldBeEqual(a: i32, b: i32) void {
8 if (a != b) {
9 unreachable;
10 } else {
11 return;
12 }
13}
14fn firstEqlThird(a: i32, b: i32, c: i32) void {
15 if (a == b) {
16 unreachable;
17 } else if (b == c) {
18 unreachable;
19 } else if (a == c) {
20 return;
21 } else {
22 unreachable;
23 }
24}
25
26test "else if expression" {
27 expect(elseIfExpressionF(1) == 1);
28}
29fn elseIfExpressionF(c: u8) u8 {
30 if (c == 0) {
31 return 0;
32 } else if (c == 1) {
33 return 1;
34 } else {
35 return u8(2);
36 }
37}
test/stage1/behavior/import.zig created+10
...@@ -0,0 +1,10 @@
1const expect = @import("std").testing.expect;
2const a_namespace = @import("import/a_namespace.zig");
3
4test "call fn via namespace lookup" {
5 expect(a_namespace.foo() == 1234);
6}
7
8test "importing the same thing gives the same import" {
9 expect(@import("std") == @import("std"));
10}
test/stage1/behavior/import/a_namespace.zig created+3
...@@ -0,0 +1,3 @@
1pub fn foo() i32 {
2 return 1234;
3}
test/stage1/behavior/incomplete_struct_param_tld.zig created+30
...@@ -0,0 +1,30 @@
1const expect = @import("std").testing.expect;
2
3const A = struct {
4 b: B,
5};
6
7const B = struct {
8 c: C,
9};
10
11const C = struct {
12 x: i32,
13
14 fn d(c: *const C) i32 {
15 return c.x;
16 }
17};
18
19fn foo(a: A) i32 {
20 return a.b.c.d();
21}
22
23test "incomplete struct param top level declaration" {
24 const a = A{
25 .b = B{
26 .c = C{ .x = 13 },
27 },
28 };
29 expect(foo(a) == 13);
30}
test/stage1/behavior/inttoptr.zig created+26
...@@ -0,0 +1,26 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const expect = std.testing.expect;
4
5test "casting random address to function pointer" {
6 randomAddressToFunction();
7 comptime randomAddressToFunction();
8}
9
10fn randomAddressToFunction() void {
11 var addr: usize = 0xdeadbeef;
12 var ptr = @intToPtr(fn () void, addr);
13}
14
15test "mutate through ptr initialized with constant intToPtr value" {
16 forceCompilerAnalyzeBranchHardCodedPtrDereference(false);
17}
18
19fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void {
20 const hardCodedP = @intToPtr(*volatile u8, 0xdeadbeef);
21 if (x) {
22 hardCodedP.* = hardCodedP.* | 10;
23 } else {
24 return;
25 }
26}
test/stage1/behavior/ir_block_deps.zig created+21
...@@ -0,0 +1,21 @@
1const expect = @import("std").testing.expect;
2
3fn foo(id: u64) !i32 {
4 return switch (id) {
5 1 => getErrInt(),
6 2 => {
7 const size = try getErrInt();
8 return try getErrInt();
9 },
10 else => error.ItBroke,
11 };
12}
13
14fn getErrInt() anyerror!i32 {
15 return 0;
16}
17
18test "ir block deps" {
19 expect((foo(1) catch unreachable) == 0);
20 expect((foo(2) catch unreachable) == 0);
21}
test/stage1/behavior/math.zig created+517
...@@ -0,0 +1,517 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqual = std.testing.expectEqual;
4const expectEqualSlices = std.testing.expectEqualSlices;
5const maxInt = std.math.maxInt;
6const minInt = std.math.minInt;
7
8test "division" {
9 testDivision();
10 comptime testDivision();
11}
12fn testDivision() void {
13 expect(div(u32, 13, 3) == 4);
14 expect(div(f16, 1.0, 2.0) == 0.5);
15 expect(div(f32, 1.0, 2.0) == 0.5);
16
17 expect(divExact(u32, 55, 11) == 5);
18 expect(divExact(i32, -55, 11) == -5);
19 expect(divExact(f16, 55.0, 11.0) == 5.0);
20 expect(divExact(f16, -55.0, 11.0) == -5.0);
21 expect(divExact(f32, 55.0, 11.0) == 5.0);
22 expect(divExact(f32, -55.0, 11.0) == -5.0);
23
24 expect(divFloor(i32, 5, 3) == 1);
25 expect(divFloor(i32, -5, 3) == -2);
26 expect(divFloor(f16, 5.0, 3.0) == 1.0);
27 expect(divFloor(f16, -5.0, 3.0) == -2.0);
28 expect(divFloor(f32, 5.0, 3.0) == 1.0);
29 expect(divFloor(f32, -5.0, 3.0) == -2.0);
30 expect(divFloor(i32, -0x80000000, -2) == 0x40000000);
31 expect(divFloor(i32, 0, -0x80000000) == 0);
32 expect(divFloor(i32, -0x40000001, 0x40000000) == -2);
33 expect(divFloor(i32, -0x80000000, 1) == -0x80000000);
34
35 expect(divTrunc(i32, 5, 3) == 1);
36 expect(divTrunc(i32, -5, 3) == -1);
37 expect(divTrunc(f16, 5.0, 3.0) == 1.0);
38 expect(divTrunc(f16, -5.0, 3.0) == -1.0);
39 expect(divTrunc(f32, 5.0, 3.0) == 1.0);
40 expect(divTrunc(f32, -5.0, 3.0) == -1.0);
41 expect(divTrunc(f64, 5.0, 3.0) == 1.0);
42 expect(divTrunc(f64, -5.0, 3.0) == -1.0);
43
44 comptime {
45 expect(
46 1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600,
47 );
48 expect(
49 @rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600,
50 );
51 expect(
52 1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2,
53 );
54 expect(
55 @divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2,
56 );
57 expect(
58 @divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2,
59 );
60 expect(
61 @divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2,
62 );
63 expect(
64 4126227191251978491697987544882340798050766755606969681711 % 10 == 1,
65 );
66 }
67}
68fn div(comptime T: type, a: T, b: T) T {
69 return a / b;
70}
71fn divExact(comptime T: type, a: T, b: T) T {
72 return @divExact(a, b);
73}
74fn divFloor(comptime T: type, a: T, b: T) T {
75 return @divFloor(a, b);
76}
77fn divTrunc(comptime T: type, a: T, b: T) T {
78 return @divTrunc(a, b);
79}
80
81test "@addWithOverflow" {
82 var result: u8 = undefined;
83 expect(@addWithOverflow(u8, 250, 100, &result));
84 expect(!@addWithOverflow(u8, 100, 150, &result));
85 expect(result == 250);
86}
87
88// TODO test mulWithOverflow
89// TODO test subWithOverflow
90
91test "@shlWithOverflow" {
92 var result: u16 = undefined;
93 expect(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));
94 expect(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result));
95 expect(result == 0b1011111111111100);
96}
97
98test "@clz" {
99 testClz();
100 comptime testClz();
101}
102
103fn testClz() void {
104 expect(clz(u8(0b00001010)) == 4);
105 expect(clz(u8(0b10001010)) == 0);
106 expect(clz(u8(0b00000000)) == 8);
107 expect(clz(u128(0xffffffffffffffff)) == 64);
108 expect(clz(u128(0x10000000000000000)) == 63);
109}
110
111fn clz(x: var) usize {
112 return @clz(x);
113}
114
115test "@ctz" {
116 testCtz();
117 comptime testCtz();
118}
119
120fn testCtz() void {
121 expect(ctz(u8(0b10100000)) == 5);
122 expect(ctz(u8(0b10001010)) == 1);
123 expect(ctz(u8(0b00000000)) == 8);
124}
125
126fn ctz(x: var) usize {
127 return @ctz(x);
128}
129
130test "assignment operators" {
131 var i: u32 = 0;
132 i += 5;
133 expect(i == 5);
134 i -= 2;
135 expect(i == 3);
136 i *= 20;
137 expect(i == 60);
138 i /= 3;
139 expect(i == 20);
140 i %= 11;
141 expect(i == 9);
142 i <<= 1;
143 expect(i == 18);
144 i >>= 2;
145 expect(i == 4);
146 i = 6;
147 i &= 5;
148 expect(i == 4);
149 i ^= 6;
150 expect(i == 2);
151 i = 6;
152 i |= 3;
153 expect(i == 7);
154}
155
156test "three expr in a row" {
157 testThreeExprInARow(false, true);
158 comptime testThreeExprInARow(false, true);
159}
160fn testThreeExprInARow(f: bool, t: bool) void {
161 assertFalse(f or f or f);
162 assertFalse(t and t and f);
163 assertFalse(1 | 2 | 4 != 7);
164 assertFalse(3 ^ 6 ^ 8 != 13);
165 assertFalse(7 & 14 & 28 != 4);
166 assertFalse(9 << 1 << 2 != 9 << 3);
167 assertFalse(90 >> 1 >> 2 != 90 >> 3);
168 assertFalse(100 - 1 + 1000 != 1099);
169 assertFalse(5 * 4 / 2 % 3 != 1);
170 assertFalse(i32(i32(5)) != 5);
171 assertFalse(!!false);
172 assertFalse(i32(7) != --(i32(7)));
173}
174fn assertFalse(b: bool) void {
175 expect(!b);
176}
177
178test "const number literal" {
179 const one = 1;
180 const eleven = ten + one;
181
182 expect(eleven == 11);
183}
184const ten = 10;
185
186test "unsigned wrapping" {
187 testUnsignedWrappingEval(maxInt(u32));
188 comptime testUnsignedWrappingEval(maxInt(u32));
189}
190fn testUnsignedWrappingEval(x: u32) void {
191 const zero = x +% 1;
192 expect(zero == 0);
193 const orig = zero -% 1;
194 expect(orig == maxInt(u32));
195}
196
197test "signed wrapping" {
198 testSignedWrappingEval(maxInt(i32));
199 comptime testSignedWrappingEval(maxInt(i32));
200}
201fn testSignedWrappingEval(x: i32) void {
202 const min_val = x +% 1;
203 expect(min_val == minInt(i32));
204 const max_val = min_val -% 1;
205 expect(max_val == maxInt(i32));
206}
207
208test "negation wrapping" {
209 testNegationWrappingEval(minInt(i16));
210 comptime testNegationWrappingEval(minInt(i16));
211}
212fn testNegationWrappingEval(x: i16) void {
213 expect(x == -32768);
214 const neg = -%x;
215 expect(neg == -32768);
216}
217
218test "unsigned 64-bit division" {
219 test_u64_div();
220 comptime test_u64_div();
221}
222fn test_u64_div() void {
223 const result = divWithResult(1152921504606846976, 34359738365);
224 expect(result.quotient == 33554432);
225 expect(result.remainder == 100663296);
226}
227fn divWithResult(a: u64, b: u64) DivResult {
228 return DivResult{
229 .quotient = a / b,
230 .remainder = a % b,
231 };
232}
233const DivResult = struct {
234 quotient: u64,
235 remainder: u64,
236};
237
238test "binary not" {
239 expect(comptime x: {
240 break :x ~u16(0b1010101010101010) == 0b0101010101010101;
241 });
242 expect(comptime x: {
243 break :x ~u64(2147483647) == 18446744071562067968;
244 });
245 testBinaryNot(0b1010101010101010);
246}
247
248fn testBinaryNot(x: u16) void {
249 expect(~x == 0b0101010101010101);
250}
251
252test "small int addition" {
253 var x: @IntType(false, 2) = 0;
254 expect(x == 0);
255
256 x += 1;
257 expect(x == 1);
258
259 x += 1;
260 expect(x == 2);
261
262 x += 1;
263 expect(x == 3);
264
265 var result: @typeOf(x) = 3;
266 expect(@addWithOverflow(@typeOf(x), x, 1, &result));
267
268 expect(result == 0);
269}
270
271test "float equality" {
272 const x: f64 = 0.012;
273 const y: f64 = x + 1.0;
274
275 testFloatEqualityImpl(x, y);
276 comptime testFloatEqualityImpl(x, y);
277}
278
279fn testFloatEqualityImpl(x: f64, y: f64) void {
280 const y2 = x + 1.0;
281 expect(y == y2);
282}
283
284test "allow signed integer division/remainder when values are comptime known and positive or exact" {
285 expect(5 / 3 == 1);
286 expect(-5 / -3 == 1);
287 expect(-6 / 3 == -2);
288
289 expect(5 % 3 == 2);
290 expect(-6 % 3 == 0);
291}
292
293test "hex float literal parsing" {
294 comptime expect(0x1.0 == 1.0);
295}
296
297test "quad hex float literal parsing in range" {
298 const a = 0x1.af23456789bbaaab347645365cdep+5;
299 const b = 0x1.dedafcff354b6ae9758763545432p-9;
300 const c = 0x1.2f34dd5f437e849b4baab754cdefp+4534;
301 const d = 0x1.edcbff8ad76ab5bf46463233214fp-435;
302}
303
304test "quad hex float literal parsing accurate" {
305 const a: f128 = 0x1.1111222233334444555566667777p+0;
306
307 // implied 1 is dropped, with an exponent of 0 (0x3fff) after biasing.
308 const expected: u128 = 0x3fff1111222233334444555566667777;
309 expect(@bitCast(u128, a) == expected);
310}
311
312test "hex float literal within range" {
313 const a = 0x1.0p16383;
314 const b = 0x0.1p16387;
315 const c = 0x1.0p-16382;
316}
317
318test "truncating shift left" {
319 testShlTrunc(maxInt(u16));
320 comptime testShlTrunc(maxInt(u16));
321}
322fn testShlTrunc(x: u16) void {
323 const shifted = x << 1;
324 expect(shifted == 65534);
325}
326
327test "truncating shift right" {
328 testShrTrunc(maxInt(u16));
329 comptime testShrTrunc(maxInt(u16));
330}
331fn testShrTrunc(x: u16) void {
332 const shifted = x >> 1;
333 expect(shifted == 32767);
334}
335
336test "exact shift left" {
337 testShlExact(0b00110101);
338 comptime testShlExact(0b00110101);
339}
340fn testShlExact(x: u8) void {
341 const shifted = @shlExact(x, 2);
342 expect(shifted == 0b11010100);
343}
344
345test "exact shift right" {
346 testShrExact(0b10110100);
347 comptime testShrExact(0b10110100);
348}
349fn testShrExact(x: u8) void {
350 const shifted = @shrExact(x, 2);
351 expect(shifted == 0b00101101);
352}
353
354test "comptime_int addition" {
355 comptime {
356 expect(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
357 expect(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
358 }
359}
360
361test "comptime_int multiplication" {
362 comptime {
363 expect(
364 45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567,
365 );
366 expect(
367 594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016,
368 );
369 }
370}
371
372test "comptime_int shifting" {
373 comptime {
374 expect((u128(1) << 127) == 0x80000000000000000000000000000000);
375 }
376}
377
378test "comptime_int multi-limb shift and mask" {
379 comptime {
380 var a = 0xefffffffa0000001eeeeeeefaaaaaaab;
381
382 expect(u32(a & 0xffffffff) == 0xaaaaaaab);
383 a >>= 32;
384 expect(u32(a & 0xffffffff) == 0xeeeeeeef);
385 a >>= 32;
386 expect(u32(a & 0xffffffff) == 0xa0000001);
387 a >>= 32;
388 expect(u32(a & 0xffffffff) == 0xefffffff);
389 a >>= 32;
390
391 expect(a == 0);
392 }
393}
394
395test "comptime_int multi-limb partial shift right" {
396 comptime {
397 var a = 0x1ffffffffeeeeeeee;
398 a >>= 16;
399 expect(a == 0x1ffffffffeeee);
400 }
401}
402
403test "xor" {
404 test_xor();
405 comptime test_xor();
406}
407
408fn test_xor() void {
409 expect(0xFF ^ 0x00 == 0xFF);
410 expect(0xF0 ^ 0x0F == 0xFF);
411 expect(0xFF ^ 0xF0 == 0x0F);
412 expect(0xFF ^ 0x0F == 0xF0);
413 expect(0xFF ^ 0xFF == 0x00);
414}
415
416test "comptime_int xor" {
417 comptime {
418 expect(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
419 expect(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
420 expect(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF);
421 expect(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000);
422 expect(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000);
423 expect(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
424 expect(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF);
425 expect(0x00000000FFFFFFFF00000000FFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFF00000000FFFFFFFF00000000);
426 }
427}
428
429test "f128" {
430 test_f128();
431 comptime test_f128();
432}
433
434fn make_f128(x: f128) f128 {
435 return x;
436}
437
438fn test_f128() void {
439 expect(@sizeOf(f128) == 16);
440 expect(make_f128(1.0) == 1.0);
441 expect(make_f128(1.0) != 1.1);
442 expect(make_f128(1.0) > 0.9);
443 expect(make_f128(1.0) >= 0.9);
444 expect(make_f128(1.0) >= 1.0);
445 should_not_be_zero(1.0);
446}
447
448fn should_not_be_zero(x: f128) void {
449 expect(x != 0.0);
450}
451
452test "comptime float rem int" {
453 comptime {
454 var x = f32(1) % 2;
455 expect(x == 1.0);
456 }
457}
458
459test "remainder division" {
460 comptime remdiv(f16);
461 comptime remdiv(f32);
462 comptime remdiv(f64);
463 comptime remdiv(f128);
464 remdiv(f16);
465 remdiv(f64);
466 remdiv(f128);
467}
468
469fn remdiv(comptime T: type) void {
470 expect(T(1) == T(1) % T(2));
471 expect(T(1) == T(7) % T(3));
472}
473
474test "@sqrt" {
475 testSqrt(f64, 12.0);
476 comptime testSqrt(f64, 12.0);
477 testSqrt(f32, 13.0);
478 comptime testSqrt(f32, 13.0);
479 testSqrt(f16, 13.0);
480 comptime testSqrt(f16, 13.0);
481
482 const x = 14.0;
483 const y = x * x;
484 const z = @sqrt(@typeOf(y), y);
485 comptime expect(z == x);
486}
487
488fn testSqrt(comptime T: type, x: T) void {
489 expect(@sqrt(T, x * x) == x);
490}
491
492test "comptime_int param and return" {
493 const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702);
494 expect(a == 137114567242441932203689521744947848950);
495
496 const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768);
497 expect(b == 985095453608931032642182098849559179469148836107390954364380);
498}
499
500fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int {
501 return a + b;
502}
503
504test "vector integer addition" {
505 const S = struct {
506 fn doTheTest() void {
507 var a: @Vector(4, i32) = []i32{ 1, 2, 3, 4 };
508 var b: @Vector(4, i32) = []i32{ 5, 6, 7, 8 };
509 var result = a + b;
510 var result_array: [4]i32 = result;
511 const expected = []i32{ 6, 8, 10, 12 };
512 expectEqualSlices(i32, &expected, &result_array);
513 }
514 };
515 S.doTheTest();
516 comptime S.doTheTest();
517}
test/stage1/behavior/merge_error_sets.zig created+21
...@@ -0,0 +1,21 @@
1const A = error{
2 FileNotFound,
3 NotDir,
4};
5const B = error{OutOfMemory};
6
7const C = A || B;
8
9fn foo() C!void {
10 return error.NotDir;
11}
12
13test "merge error sets" {
14 if (foo()) {
15 @panic("unexpected");
16 } else |err| switch (err) {
17 error.OutOfMemory => @panic("unexpected"),
18 error.FileNotFound => @panic("unexpected"),
19 error.NotDir => {},
20 }
21}
test/stage1/behavior/misc.zig created+695
...@@ -0,0 +1,695 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const mem = std.mem;
4const cstr = std.cstr;
5const builtin = @import("builtin");
6const maxInt = std.math.maxInt;
7
8// normal comment
9
10/// this is a documentation comment
11/// doc comment line 2
12fn emptyFunctionWithComments() void {}
13
14test "empty function with comments" {
15 emptyFunctionWithComments();
16}
17
18comptime {
19 @export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal);
20}
21
22extern fn disabledExternFn() void {}
23
24test "call disabled extern fn" {
25 disabledExternFn();
26}
27
28test "@IntType builtin" {
29 expect(@IntType(true, 8) == i8);
30 expect(@IntType(true, 16) == i16);
31 expect(@IntType(true, 32) == i32);
32 expect(@IntType(true, 64) == i64);
33
34 expect(@IntType(false, 8) == u8);
35 expect(@IntType(false, 16) == u16);
36 expect(@IntType(false, 32) == u32);
37 expect(@IntType(false, 64) == u64);
38
39 expect(i8.bit_count == 8);
40 expect(i16.bit_count == 16);
41 expect(i32.bit_count == 32);
42 expect(i64.bit_count == 64);
43
44 expect(i8.is_signed);
45 expect(i16.is_signed);
46 expect(i32.is_signed);
47 expect(i64.is_signed);
48 expect(isize.is_signed);
49
50 expect(!u8.is_signed);
51 expect(!u16.is_signed);
52 expect(!u32.is_signed);
53 expect(!u64.is_signed);
54 expect(!usize.is_signed);
55}
56
57test "floating point primitive bit counts" {
58 expect(f16.bit_count == 16);
59 expect(f32.bit_count == 32);
60 expect(f64.bit_count == 64);
61}
62
63test "short circuit" {
64 testShortCircuit(false, true);
65 comptime testShortCircuit(false, true);
66}
67
68fn testShortCircuit(f: bool, t: bool) void {
69 var hit_1 = f;
70 var hit_2 = f;
71 var hit_3 = f;
72 var hit_4 = f;
73
74 if (t or x: {
75 expect(f);
76 break :x f;
77 }) {
78 hit_1 = t;
79 }
80 if (f or x: {
81 hit_2 = t;
82 break :x f;
83 }) {
84 expect(f);
85 }
86
87 if (t and x: {
88 hit_3 = t;
89 break :x f;
90 }) {
91 expect(f);
92 }
93 if (f and x: {
94 expect(f);
95 break :x f;
96 }) {
97 expect(f);
98 } else {
99 hit_4 = t;
100 }
101 expect(hit_1);
102 expect(hit_2);
103 expect(hit_3);
104 expect(hit_4);
105}
106
107test "truncate" {
108 expect(testTruncate(0x10fd) == 0xfd);
109}
110fn testTruncate(x: u32) u8 {
111 return @truncate(u8, x);
112}
113
114fn first4KeysOfHomeRow() []const u8 {
115 return "aoeu";
116}
117
118test "return string from function" {
119 expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
120}
121
122const g1: i32 = 1233 + 1;
123var g2: i32 = 0;
124
125test "global variables" {
126 expect(g2 == 0);
127 g2 = g1;
128 expect(g2 == 1234);
129}
130
131test "memcpy and memset intrinsics" {
132 var foo: [20]u8 = undefined;
133 var bar: [20]u8 = undefined;
134
135 @memset(foo[0..].ptr, 'A', foo.len);
136 @memcpy(bar[0..].ptr, foo[0..].ptr, bar.len);
137
138 if (bar[11] != 'A') unreachable;
139}
140
141test "builtin static eval" {
142 const x: i32 = comptime x: {
143 break :x 1 + 2 + 3;
144 };
145 expect(x == comptime 6);
146}
147
148test "slicing" {
149 var array: [20]i32 = undefined;
150
151 array[5] = 1234;
152
153 var slice = array[5..10];
154
155 if (slice.len != 5) unreachable;
156
157 const ptr = &slice[0];
158 if (ptr.* != 1234) unreachable;
159
160 var slice_rest = array[10..];
161 if (slice_rest.len != 10) unreachable;
162}
163
164test "constant equal function pointers" {
165 const alias = emptyFn;
166 expect(comptime x: {
167 break :x emptyFn == alias;
168 });
169}
170
171fn emptyFn() void {}
172
173test "hex escape" {
174 expect(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
175}
176
177test "string concatenation" {
178 expect(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
179}
180
181test "array mult operator" {
182 expect(mem.eql(u8, "ab" ** 5, "ababababab"));
183}
184
185test "string escapes" {
186 expect(mem.eql(u8, "\"", "\x22"));
187 expect(mem.eql(u8, "\'", "\x27"));
188 expect(mem.eql(u8, "\n", "\x0a"));
189 expect(mem.eql(u8, "\r", "\x0d"));
190 expect(mem.eql(u8, "\t", "\x09"));
191 expect(mem.eql(u8, "\\", "\x5c"));
192 expect(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69"));
193}
194
195test "multiline string" {
196 const s1 =
197 \\one
198 \\two)
199 \\three
200 ;
201 const s2 = "one\ntwo)\nthree";
202 expect(mem.eql(u8, s1, s2));
203}
204
205test "multiline C string" {
206 const s1 =
207 c\\one
208 c\\two)
209 c\\three
210 ;
211 const s2 = c"one\ntwo)\nthree";
212 expect(cstr.cmp(s1, s2) == 0);
213}
214
215test "type equality" {
216 expect(*const u8 != *u8);
217}
218
219const global_a: i32 = 1234;
220const global_b: *const i32 = &global_a;
221const global_c: *const f32 = @ptrCast(*const f32, global_b);
222test "compile time global reinterpret" {
223 const d = @ptrCast(*const i32, global_c);
224 expect(d.* == 1234);
225}
226
227test "explicit cast maybe pointers" {
228 const a: ?*i32 = undefined;
229 const b: ?*f32 = @ptrCast(?*f32, a);
230}
231
232test "generic malloc free" {
233 const a = memAlloc(u8, 10) catch unreachable;
234 memFree(u8, a);
235}
236var some_mem: [100]u8 = undefined;
237fn memAlloc(comptime T: type, n: usize) anyerror![]T {
238 return @ptrCast([*]T, &some_mem[0])[0..n];
239}
240fn memFree(comptime T: type, memory: []T) void {}
241
242test "cast undefined" {
243 const array: [100]u8 = undefined;
244 const slice = ([]const u8)(array);
245 testCastUndefined(slice);
246}
247fn testCastUndefined(x: []const u8) void {}
248
249test "cast small unsigned to larger signed" {
250 expect(castSmallUnsignedToLargerSigned1(200) == i16(200));
251 expect(castSmallUnsignedToLargerSigned2(9999) == i64(9999));
252}
253fn castSmallUnsignedToLargerSigned1(x: u8) i16 {
254 return x;
255}
256fn castSmallUnsignedToLargerSigned2(x: u16) i64 {
257 return x;
258}
259
260test "implicit cast after unreachable" {
261 expect(outer() == 1234);
262}
263fn inner() i32 {
264 return 1234;
265}
266fn outer() i64 {
267 return inner();
268}
269
270test "pointer dereferencing" {
271 var x = i32(3);
272 const y = &x;
273
274 y.* += 1;
275
276 expect(x == 4);
277 expect(y.* == 4);
278}
279
280test "call result of if else expression" {
281 expect(mem.eql(u8, f2(true), "a"));
282 expect(mem.eql(u8, f2(false), "b"));
283}
284fn f2(x: bool) []const u8 {
285 return (if (x) fA else fB)();
286}
287fn fA() []const u8 {
288 return "a";
289}
290fn fB() []const u8 {
291 return "b";
292}
293
294test "const expression eval handling of variables" {
295 var x = true;
296 while (x) {
297 x = false;
298 }
299}
300
301test "constant enum initialization with differing sizes" {
302 test3_1(test3_foo);
303 test3_2(test3_bar);
304}
305const Test3Foo = union(enum) {
306 One: void,
307 Two: f32,
308 Three: Test3Point,
309};
310const Test3Point = struct {
311 x: i32,
312 y: i32,
313};
314const test3_foo = Test3Foo{
315 .Three = Test3Point{
316 .x = 3,
317 .y = 4,
318 },
319};
320const test3_bar = Test3Foo{ .Two = 13 };
321fn test3_1(f: Test3Foo) void {
322 switch (f) {
323 Test3Foo.Three => |pt| {
324 expect(pt.x == 3);
325 expect(pt.y == 4);
326 },
327 else => unreachable,
328 }
329}
330fn test3_2(f: Test3Foo) void {
331 switch (f) {
332 Test3Foo.Two => |x| {
333 expect(x == 13);
334 },
335 else => unreachable,
336 }
337}
338
339test "character literals" {
340 expect('\'' == single_quote);
341}
342const single_quote = '\'';
343
344test "take address of parameter" {
345 testTakeAddressOfParameter(12.34);
346}
347fn testTakeAddressOfParameter(f: f32) void {
348 const f_ptr = &f;
349 expect(f_ptr.* == 12.34);
350}
351
352test "pointer comparison" {
353 const a = ([]const u8)("a");
354 const b = &a;
355 expect(ptrEql(b, b));
356}
357fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
358 return a == b;
359}
360
361test "C string concatenation" {
362 const a = c"OK" ++ c" IT " ++ c"WORKED";
363 const b = c"OK IT WORKED";
364
365 const len = cstr.len(b);
366 const len_with_null = len + 1;
367 {
368 var i: u32 = 0;
369 while (i < len_with_null) : (i += 1) {
370 expect(a[i] == b[i]);
371 }
372 }
373 expect(a[len] == 0);
374 expect(b[len] == 0);
375}
376
377test "cast slice to u8 slice" {
378 expect(@sizeOf(i32) == 4);
379 var big_thing_array = []i32{ 1, 2, 3, 4 };
380 const big_thing_slice: []i32 = big_thing_array[0..];
381 const bytes = @sliceToBytes(big_thing_slice);
382 expect(bytes.len == 4 * 4);
383 bytes[4] = 0;
384 bytes[5] = 0;
385 bytes[6] = 0;
386 bytes[7] = 0;
387 expect(big_thing_slice[1] == 0);
388 const big_thing_again = @bytesToSlice(i32, bytes);
389 expect(big_thing_again[2] == 3);
390 big_thing_again[2] = -1;
391 expect(bytes[8] == maxInt(u8));
392 expect(bytes[9] == maxInt(u8));
393 expect(bytes[10] == maxInt(u8));
394 expect(bytes[11] == maxInt(u8));
395}
396
397test "pointer to void return type" {
398 testPointerToVoidReturnType() catch unreachable;
399}
400fn testPointerToVoidReturnType() anyerror!void {
401 const a = testPointerToVoidReturnType2();
402 return a.*;
403}
404const test_pointer_to_void_return_type_x = void{};
405fn testPointerToVoidReturnType2() *const void {
406 return &test_pointer_to_void_return_type_x;
407}
408
409test "non const ptr to aliased type" {
410 const int = i32;
411 expect(?*int == ?*i32);
412}
413
414test "array 2D const double ptr" {
415 const rect_2d_vertexes = [][1]f32{
416 []f32{1.0},
417 []f32{2.0},
418 };
419 testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]);
420}
421
422fn testArray2DConstDoublePtr(ptr: *const f32) void {
423 const ptr2 = @ptrCast([*]const f32, ptr);
424 expect(ptr2[0] == 1.0);
425 expect(ptr2[1] == 2.0);
426}
427
428const Tid = builtin.TypeId;
429const AStruct = struct {
430 x: i32,
431};
432const AnEnum = enum {
433 One,
434 Two,
435};
436const AUnionEnum = union(enum) {
437 One: i32,
438 Two: void,
439};
440const AUnion = union {
441 One: void,
442 Two: void,
443};
444
445test "@typeId" {
446 comptime {
447 expect(@typeId(type) == Tid.Type);
448 expect(@typeId(void) == Tid.Void);
449 expect(@typeId(bool) == Tid.Bool);
450 expect(@typeId(noreturn) == Tid.NoReturn);
451 expect(@typeId(i8) == Tid.Int);
452 expect(@typeId(u8) == Tid.Int);
453 expect(@typeId(i64) == Tid.Int);
454 expect(@typeId(u64) == Tid.Int);
455 expect(@typeId(f32) == Tid.Float);
456 expect(@typeId(f64) == Tid.Float);
457 expect(@typeId(*f32) == Tid.Pointer);
458 expect(@typeId([2]u8) == Tid.Array);
459 expect(@typeId(AStruct) == Tid.Struct);
460 expect(@typeId(@typeOf(1)) == Tid.ComptimeInt);
461 expect(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat);
462 expect(@typeId(@typeOf(undefined)) == Tid.Undefined);
463 expect(@typeId(@typeOf(null)) == Tid.Null);
464 expect(@typeId(?i32) == Tid.Optional);
465 expect(@typeId(anyerror!i32) == Tid.ErrorUnion);
466 expect(@typeId(anyerror) == Tid.ErrorSet);
467 expect(@typeId(AnEnum) == Tid.Enum);
468 expect(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum);
469 expect(@typeId(AUnionEnum) == Tid.Union);
470 expect(@typeId(AUnion) == Tid.Union);
471 expect(@typeId(fn () void) == Tid.Fn);
472 expect(@typeId(@typeOf(builtin)) == Tid.Namespace);
473 // TODO bound fn
474 // TODO arg tuple
475 // TODO opaque
476 }
477}
478
479test "@typeName" {
480 const Struct = struct {};
481 const Union = union {
482 unused: u8,
483 };
484 const Enum = enum {
485 Unused,
486 };
487 comptime {
488 expect(mem.eql(u8, @typeName(i64), "i64"));
489 expect(mem.eql(u8, @typeName(*usize), "*usize"));
490 // https://github.com/ziglang/zig/issues/675
491 expect(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)"));
492 expect(mem.eql(u8, @typeName(Struct), "Struct"));
493 expect(mem.eql(u8, @typeName(Union), "Union"));
494 expect(mem.eql(u8, @typeName(Enum), "Enum"));
495 }
496}
497
498fn TypeFromFn(comptime T: type) type {
499 return struct {};
500}
501
502test "double implicit cast in same expression" {
503 var x = i32(u16(nine()));
504 expect(x == 9);
505}
506fn nine() u8 {
507 return 9;
508}
509
510test "global variable initialized to global variable array element" {
511 expect(global_ptr == &gdt[0]);
512}
513const GDTEntry = struct {
514 field: i32,
515};
516var gdt = []GDTEntry{
517 GDTEntry{ .field = 1 },
518 GDTEntry{ .field = 2 },
519};
520var global_ptr = &gdt[0];
521
522// can't really run this test but we can make sure it has no compile error
523// and generates code
524const vram = @intToPtr([*]volatile u8, 0x20000000)[0..0x8000];
525export fn writeToVRam() void {
526 vram[0] = 'X';
527}
528
529const OpaqueA = @OpaqueType();
530const OpaqueB = @OpaqueType();
531test "@OpaqueType" {
532 expect(*OpaqueA != *OpaqueB);
533 expect(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
534 expect(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
535}
536
537test "variable is allowed to be a pointer to an opaque type" {
538 var x: i32 = 1234;
539 _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x));
540}
541fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
542 var a = ptr;
543 return a;
544}
545
546test "comptime if inside runtime while which unconditionally breaks" {
547 testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
548 comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
549}
550fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void {
551 while (cond) {
552 if (false) {}
553 break;
554 }
555}
556
557test "implicit comptime while" {
558 while (false) {
559 @compileError("bad");
560 }
561}
562
563fn fnThatClosesOverLocalConst() type {
564 const c = 1;
565 return struct {
566 fn g() i32 {
567 return c;
568 }
569 };
570}
571
572test "function closes over local const" {
573 const x = fnThatClosesOverLocalConst().g();
574 expect(x == 1);
575}
576
577test "cold function" {
578 thisIsAColdFn();
579 comptime thisIsAColdFn();
580}
581
582fn thisIsAColdFn() void {
583 @setCold(true);
584}
585
586const PackedStruct = packed struct {
587 a: u8,
588 b: u8,
589};
590const PackedUnion = packed union {
591 a: u8,
592 b: u32,
593};
594const PackedEnum = packed enum {
595 A,
596 B,
597};
598
599test "packed struct, enum, union parameters in extern function" {
600 testPackedStuff(&(PackedStruct{
601 .a = 1,
602 .b = 2,
603 }), &(PackedUnion{ .a = 1 }), PackedEnum.A);
604}
605
606export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion, c: PackedEnum) void {}
607
608test "slicing zero length array" {
609 const s1 = ""[0..];
610 const s2 = ([]u32{})[0..];
611 expect(s1.len == 0);
612 expect(s2.len == 0);
613 expect(mem.eql(u8, s1, ""));
614 expect(mem.eql(u32, s2, []u32{}));
615}
616
617const addr1 = @ptrCast(*const u8, emptyFn);
618test "comptime cast fn to ptr" {
619 const addr2 = @ptrCast(*const u8, emptyFn);
620 comptime expect(addr1 == addr2);
621}
622
623test "equality compare fn ptrs" {
624 var a = emptyFn;
625 expect(a == a);
626}
627
628test "self reference through fn ptr field" {
629 const S = struct {
630 const A = struct {
631 f: fn (A) u8,
632 };
633
634 fn foo(a: A) u8 {
635 return 12;
636 }
637 };
638 var a: S.A = undefined;
639 a.f = S.foo;
640 expect(a.f(a) == 12);
641}
642
643test "volatile load and store" {
644 var number: i32 = 1234;
645 const ptr = (*volatile i32)(&number);
646 ptr.* += 1;
647 expect(ptr.* == 1235);
648}
649
650test "slice string literal has type []const u8" {
651 comptime {
652 expect(@typeOf("aoeu"[0..]) == []const u8);
653 const array = []i32{ 1, 2, 3, 4 };
654 expect(@typeOf(array[0..]) == []const i32);
655 }
656}
657
658test "pointer child field" {
659 expect((*u32).Child == u32);
660}
661
662test "struct inside function" {
663 testStructInFn();
664 comptime testStructInFn();
665}
666
667fn testStructInFn() void {
668 const BlockKind = u32;
669
670 const Block = struct {
671 kind: BlockKind,
672 };
673
674 var block = Block{ .kind = 1234 };
675
676 block.kind += 1;
677
678 expect(block.kind == 1235);
679}
680
681test "fn call returning scalar optional in equality expression" {
682 expect(getNull() == null);
683}
684
685fn getNull() ?*i32 {
686 return null;
687}
688
689test "thread local variable" {
690 const S = struct {
691 threadlocal var t: i32 = 1234;
692 };
693 S.t += 1;
694 expect(S.t == 1235);
695}
test/stage1/behavior/namespace_depends_on_compile_var/a.zig created+1
...@@ -0,0 +1 @@
1pub const a_bool = true;
test/stage1/behavior/namespace_depends_on_compile_var/b.zig created+1
...@@ -0,0 +1 @@
1pub const a_bool = false;
test/stage1/behavior/namespace_depends_on_compile_var/index.zig created+14
...@@ -0,0 +1,14 @@
1const builtin = @import("builtin");
2const expect = @import("std").testing.expect;
3
4test "namespace depends on compile var" {
5 if (some_namespace.a_bool) {
6 expect(some_namespace.a_bool);
7 } else {
8 expect(!some_namespace.a_bool);
9 }
10}
11const some_namespace = switch (builtin.os) {
12 builtin.Os.linux => @import("a.zig"),
13 else => @import("b.zig"),
14};
test/stage1/behavior/new_stack_call.zig created+26
...@@ -0,0 +1,26 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4var new_stack_bytes: [1024]u8 = undefined;
5
6test "calling a function with a new stack" {
7 const arg = 1234;
8
9 const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg);
10 const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg);
11 _ = targetFunction(arg);
12
13 expect(arg == 1234);
14 expect(a < b);
15}
16
17fn targetFunction(x: i32) usize {
18 expect(x == 1234);
19
20 var local_variable: i32 = 42;
21 const ptr = &local_variable;
22 ptr.* += 1;
23
24 expect(local_variable == 43);
25 return @ptrToInt(ptr);
26}
test/stage1/behavior/null.zig created+162
...@@ -0,0 +1,162 @@
1const expect = @import("std").testing.expect;
2
3test "optional type" {
4 const x: ?bool = true;
5
6 if (x) |y| {
7 if (y) {
8 // OK
9 } else {
10 unreachable;
11 }
12 } else {
13 unreachable;
14 }
15
16 const next_x: ?i32 = null;
17
18 const z = next_x orelse 1234;
19
20 expect(z == 1234);
21
22 const final_x: ?i32 = 13;
23
24 const num = final_x orelse unreachable;
25
26 expect(num == 13);
27}
28
29test "test maybe object and get a pointer to the inner value" {
30 var maybe_bool: ?bool = true;
31
32 if (maybe_bool) |*b| {
33 b.* = false;
34 }
35
36 expect(maybe_bool.? == false);
37}
38
39test "rhs maybe unwrap return" {
40 const x: ?bool = true;
41 const y = x orelse return;
42}
43
44test "maybe return" {
45 maybeReturnImpl();
46 comptime maybeReturnImpl();
47}
48
49fn maybeReturnImpl() void {
50 expect(foo(1235).?);
51 if (foo(null) != null) unreachable;
52 expect(!foo(1234).?);
53}
54
55fn foo(x: ?i32) ?bool {
56 const value = x orelse return null;
57 return value > 1234;
58}
59
60test "if var maybe pointer" {
61 expect(shouldBeAPlus1(Particle{
62 .a = 14,
63 .b = 1,
64 .c = 1,
65 .d = 1,
66 }) == 15);
67}
68fn shouldBeAPlus1(p: Particle) u64 {
69 var maybe_particle: ?Particle = p;
70 if (maybe_particle) |*particle| {
71 particle.a += 1;
72 }
73 if (maybe_particle) |particle| {
74 return particle.a;
75 }
76 return 0;
77}
78const Particle = struct {
79 a: u64,
80 b: u64,
81 c: u64,
82 d: u64,
83};
84
85test "null literal outside function" {
86 const is_null = here_is_a_null_literal.context == null;
87 expect(is_null);
88
89 const is_non_null = here_is_a_null_literal.context != null;
90 expect(!is_non_null);
91}
92const SillyStruct = struct {
93 context: ?i32,
94};
95const here_is_a_null_literal = SillyStruct{ .context = null };
96
97test "test null runtime" {
98 testTestNullRuntime(null);
99}
100fn testTestNullRuntime(x: ?i32) void {
101 expect(x == null);
102 expect(!(x != null));
103}
104
105test "optional void" {
106 optionalVoidImpl();
107 comptime optionalVoidImpl();
108}
109
110fn optionalVoidImpl() void {
111 expect(bar(null) == null);
112 expect(bar({}) != null);
113}
114
115fn bar(x: ?void) ?void {
116 if (x) |_| {
117 return {};
118 } else {
119 return null;
120 }
121}
122
123const StructWithOptional = struct {
124 field: ?i32,
125};
126
127var struct_with_optional: StructWithOptional = undefined;
128
129test "unwrap optional which is field of global var" {
130 struct_with_optional.field = null;
131 if (struct_with_optional.field) |payload| {
132 unreachable;
133 }
134 struct_with_optional.field = 1234;
135 if (struct_with_optional.field) |payload| {
136 expect(payload == 1234);
137 } else {
138 unreachable;
139 }
140}
141
142test "null with default unwrap" {
143 const x: i32 = null orelse 1;
144 expect(x == 1);
145}
146
147test "optional types" {
148 comptime {
149 const opt_type_struct = StructWithOptionalType{ .t = u8 };
150 expect(opt_type_struct.t != null and opt_type_struct.t.? == u8);
151 }
152}
153
154const StructWithOptionalType = struct {
155 t: ?type,
156};
157
158test "optional pointer to 0 bit type null value at runtime" {
159 const EmptyStruct = struct {};
160 var x: ?*EmptyStruct = null;
161 expect(x == null);
162}
test/stage1/behavior/optional.zig created+81
...@@ -0,0 +1,81 @@
1const expect = @import("std").testing.expect;
2
3pub const EmptyStruct = struct {};
4
5test "optional pointer to size zero struct" {
6 var e = EmptyStruct{};
7 var o: ?*EmptyStruct = &e;
8 expect(o != null);
9}
10
11test "equality compare nullable pointers" {
12 testNullPtrsEql();
13 comptime testNullPtrsEql();
14}
15
16fn testNullPtrsEql() void {
17 var number: i32 = 1234;
18
19 var x: ?*i32 = null;
20 var y: ?*i32 = null;
21 expect(x == y);
22 y = &number;
23 expect(x != y);
24 expect(x != &number);
25 expect(&number != x);
26 x = &number;
27 expect(x == y);
28 expect(x == &number);
29 expect(&number == x);
30}
31
32test "address of unwrap optional" {
33 const S = struct {
34 const Foo = struct {
35 a: i32,
36 };
37
38 var global: ?Foo = null;
39
40 pub fn getFoo() anyerror!*Foo {
41 return &global.?;
42 }
43 };
44 S.global = S.Foo{ .a = 1234 };
45 const foo = S.getFoo() catch unreachable;
46 expect(foo.a == 1234);
47}
48
49test "passing an optional integer as a parameter" {
50 const S = struct {
51 fn entry() bool {
52 var x: i32 = 1234;
53 return foo(x);
54 }
55
56 fn foo(x: ?i32) bool {
57 return x.? == 1234;
58 }
59 };
60 expect(S.entry());
61 comptime expect(S.entry());
62}
63
64test "unwrap function call with optional pointer return value" {
65 const S = struct {
66 fn entry() void {
67 expect(foo().?.* == 1234);
68 expect(bar() == null);
69 }
70 const global: i32 = 1234;
71 fn foo() ?*const i32 {
72 return &global;
73 }
74 fn bar() ?*i32 {
75 return null;
76 }
77 };
78 S.entry();
79 // TODO https://github.com/ziglang/zig/issues/1901
80 //comptime S.entry();
81}
test/stage1/behavior/pointers.zig created+126
...@@ -0,0 +1,126 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectError = std.testing.expectError;
4
5test "dereference pointer" {
6 comptime testDerefPtr();
7 testDerefPtr();
8}
9
10fn testDerefPtr() void {
11 var x: i32 = 1234;
12 var y = &x;
13 y.* += 1;
14 expect(x == 1235);
15}
16
17test "pointer arithmetic" {
18 var ptr = c"abcd";
19
20 expect(ptr[0] == 'a');
21 ptr += 1;
22 expect(ptr[0] == 'b');
23 ptr += 1;
24 expect(ptr[0] == 'c');
25 ptr += 1;
26 expect(ptr[0] == 'd');
27 ptr += 1;
28 expect(ptr[0] == 0);
29 ptr -= 1;
30 expect(ptr[0] == 'd');
31 ptr -= 1;
32 expect(ptr[0] == 'c');
33 ptr -= 1;
34 expect(ptr[0] == 'b');
35 ptr -= 1;
36 expect(ptr[0] == 'a');
37}
38
39test "double pointer parsing" {
40 comptime expect(PtrOf(PtrOf(i32)) == **i32);
41}
42
43fn PtrOf(comptime T: type) type {
44 return *T;
45}
46
47test "assigning integer to C pointer" {
48 var x: i32 = 0;
49 var ptr: [*c]u8 = 0;
50 var ptr2: [*c]u8 = x;
51}
52
53test "implicit cast single item pointer to C pointer and back" {
54 var y: u8 = 11;
55 var x: [*c]u8 = &y;
56 var z: *u8 = x;
57 z.* += 1;
58 expect(y == 12);
59}
60
61test "C pointer comparison and arithmetic" {
62 const S = struct {
63 fn doTheTest() void {
64 var one: usize = 1;
65 var ptr1: [*c]u32 = 0;
66 var ptr2 = ptr1 + 10;
67 expect(ptr1 == 0);
68 expect(ptr1 >= 0);
69 expect(ptr1 <= 0);
70 expect(ptr1 < 1);
71 expect(ptr1 < one);
72 expect(1 > ptr1);
73 expect(one > ptr1);
74 expect(ptr1 < ptr2);
75 expect(ptr2 > ptr1);
76 expect(ptr2 >= 40);
77 expect(ptr2 == 40);
78 expect(ptr2 <= 40);
79 ptr2 -= 10;
80 expect(ptr1 == ptr2);
81 }
82 };
83 S.doTheTest();
84 comptime S.doTheTest();
85}
86
87test "peer type resolution with C pointers" {
88 var ptr_one: *u8 = undefined;
89 var ptr_many: [*]u8 = undefined;
90 var ptr_c: [*c]u8 = undefined;
91 var t = true;
92 var x1 = if (t) ptr_one else ptr_c;
93 var x2 = if (t) ptr_many else ptr_c;
94 var x3 = if (t) ptr_c else ptr_one;
95 var x4 = if (t) ptr_c else ptr_many;
96 expect(@typeOf(x1) == [*c]u8);
97 expect(@typeOf(x2) == [*c]u8);
98 expect(@typeOf(x3) == [*c]u8);
99 expect(@typeOf(x4) == [*c]u8);
100}
101
102test "implicit casting between C pointer and optional non-C pointer" {
103 var slice: []const u8 = "aoeu";
104 const opt_many_ptr: ?[*]const u8 = slice.ptr;
105 var ptr_opt_many_ptr = &opt_many_ptr;
106 var c_ptr: [*c]const [*c]const u8 = ptr_opt_many_ptr;
107 expect(c_ptr.*.* == 'a');
108 ptr_opt_many_ptr = c_ptr;
109 expect(ptr_opt_many_ptr.*.?[1] == 'o');
110}
111
112test "implicit cast error unions with non-optional to optional pointer" {
113 const S = struct {
114 fn doTheTest() void {
115 expectError(error.Fail, foo());
116 }
117 fn foo() anyerror!?*u8 {
118 return bar() orelse error.Fail;
119 }
120 fn bar() ?*u8 {
121 return null;
122 }
123 };
124 S.doTheTest();
125 comptime S.doTheTest();
126}
test/stage1/behavior/popcount.zig created+25
...@@ -0,0 +1,25 @@
1const expect = @import("std").testing.expect;
2
3test "@popCount" {
4 comptime testPopCount();
5 testPopCount();
6}
7
8fn testPopCount() void {
9 {
10 var x: u32 = 0xaa;
11 expect(@popCount(x) == 4);
12 }
13 {
14 var x: u32 = 0xaaaaaaaa;
15 expect(@popCount(x) == 16);
16 }
17 {
18 var x: i16 = -1;
19 expect(@popCount(x) == 16);
20 }
21 comptime {
22 expect(@popCount(0b11111111000110001100010000100001000011000011100101010001) == 24);
23 }
24}
25
test/stage1/behavior/ptrcast.zig created+52
...@@ -0,0 +1,52 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const expect = std.testing.expect;
4
5test "reinterpret bytes as integer with nonzero offset" {
6 testReinterpretBytesAsInteger();
7 comptime testReinterpretBytesAsInteger();
8}
9
10fn testReinterpretBytesAsInteger() void {
11 const bytes = "\x12\x34\x56\x78\xab";
12 const expected = switch (builtin.endian) {
13 builtin.Endian.Little => 0xab785634,
14 builtin.Endian.Big => 0x345678ab,
15 };
16 expect(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected);
17}
18
19test "reinterpret bytes of an array into an extern struct" {
20 testReinterpretBytesAsExternStruct();
21 comptime testReinterpretBytesAsExternStruct();
22}
23
24fn testReinterpretBytesAsExternStruct() void {
25 var bytes align(2) = []u8{ 1, 2, 3, 4, 5, 6 };
26
27 const S = extern struct {
28 a: u8,
29 b: u16,
30 c: u8,
31 };
32
33 var ptr = @ptrCast(*const S, &bytes);
34 var val = ptr.c;
35 expect(val == 5);
36}
37
38test "reinterpret struct field at comptime" {
39 const numLittle = comptime Bytes.init(0x12345678);
40 expect(std.mem.eql(u8, []u8{ 0x78, 0x56, 0x34, 0x12 }, numLittle.bytes));
41}
42
43const Bytes = struct {
44 bytes: [4]u8,
45
46 pub fn init(v: u32) Bytes {
47 var res: Bytes = undefined;
48 @ptrCast(*align(1) u32, &res.bytes).* = v;
49
50 return res;
51 }
52};
test/stage1/behavior/pub_enum/index.zig created+13
...@@ -0,0 +1,13 @@
1const other = @import("other.zig");
2const expect = @import("std").testing.expect;
3
4test "pub enum" {
5 pubEnumTest(other.APubEnum.Two);
6}
7fn pubEnumTest(foo: other.APubEnum) void {
8 expect(foo == other.APubEnum.Two);
9}
10
11test "cast with imported symbol" {
12 expect(other.size_t(42) == 42);
13}
test/stage1/behavior/pub_enum/other.zig created+6
...@@ -0,0 +1,6 @@
1pub const APubEnum = enum {
2 One,
3 Two,
4 Three,
5};
6pub const size_t = u64;
test/stage1/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig created+37
...@@ -0,0 +1,37 @@
1const expect = @import("std").testing.expect;
2const mem = @import("std").mem;
3
4var ok: bool = false;
5test "reference a variable in an if after an if in the 2nd switch prong" {
6 foo(true, Num.Two, false, "aoeu");
7 expect(!ok);
8 foo(false, Num.One, false, "aoeu");
9 expect(!ok);
10 foo(true, Num.One, false, "aoeu");
11 expect(ok);
12}
13
14const Num = enum {
15 One,
16 Two,
17};
18
19fn foo(c: bool, k: Num, c2: bool, b: []const u8) void {
20 switch (k) {
21 Num.Two => {},
22 Num.One => {
23 if (c) {
24 const output_path = b;
25
26 if (c2) {}
27
28 a(output_path);
29 }
30 },
31 }
32}
33
34fn a(x: []const u8) void {
35 expect(mem.eql(u8, x, "aoeu"));
36 ok = true;
37}
test/stage1/behavior/reflection.zig created+96
...@@ -0,0 +1,96 @@
1const expect = @import("std").testing.expect;
2const mem = @import("std").mem;
3const reflection = @This();
4
5test "reflection: array, pointer, optional, error union type child" {
6 comptime {
7 expect(([10]u8).Child == u8);
8 expect((*u8).Child == u8);
9 expect((anyerror!u8).Payload == u8);
10 expect((?u8).Child == u8);
11 }
12}
13
14test "reflection: function return type, var args, and param types" {
15 comptime {
16 expect(@typeOf(dummy).ReturnType == i32);
17 expect(!@typeOf(dummy).is_var_args);
18 expect(@typeOf(dummy_varargs).is_var_args);
19 expect(@typeOf(dummy).arg_count == 3);
20 expect(@ArgType(@typeOf(dummy), 0) == bool);
21 expect(@ArgType(@typeOf(dummy), 1) == i32);
22 expect(@ArgType(@typeOf(dummy), 2) == f32);
23 }
24}
25
26fn dummy(a: bool, b: i32, c: f32) i32 {
27 return 1234;
28}
29fn dummy_varargs(args: ...) void {}
30
31test "reflection: struct member types and names" {
32 comptime {
33 expect(@memberCount(Foo) == 3);
34
35 expect(@memberType(Foo, 0) == i32);
36 expect(@memberType(Foo, 1) == bool);
37 expect(@memberType(Foo, 2) == void);
38
39 expect(mem.eql(u8, @memberName(Foo, 0), "one"));
40 expect(mem.eql(u8, @memberName(Foo, 1), "two"));
41 expect(mem.eql(u8, @memberName(Foo, 2), "three"));
42 }
43}
44
45test "reflection: enum member types and names" {
46 comptime {
47 expect(@memberCount(Bar) == 4);
48
49 expect(@memberType(Bar, 0) == void);
50 expect(@memberType(Bar, 1) == i32);
51 expect(@memberType(Bar, 2) == bool);
52 expect(@memberType(Bar, 3) == f64);
53
54 expect(mem.eql(u8, @memberName(Bar, 0), "One"));
55 expect(mem.eql(u8, @memberName(Bar, 1), "Two"));
56 expect(mem.eql(u8, @memberName(Bar, 2), "Three"));
57 expect(mem.eql(u8, @memberName(Bar, 3), "Four"));
58 }
59}
60
61test "reflection: @field" {
62 var f = Foo{
63 .one = 42,
64 .two = true,
65 .three = void{},
66 };
67
68 expect(f.one == f.one);
69 expect(@field(f, "o" ++ "ne") == f.one);
70 expect(@field(f, "t" ++ "wo") == f.two);
71 expect(@field(f, "th" ++ "ree") == f.three);
72 expect(@field(Foo, "const" ++ "ant") == Foo.constant);
73 expect(@field(Bar, "O" ++ "ne") == Bar.One);
74 expect(@field(Bar, "T" ++ "wo") == Bar.Two);
75 expect(@field(Bar, "Th" ++ "ree") == Bar.Three);
76 expect(@field(Bar, "F" ++ "our") == Bar.Four);
77 expect(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2));
78 @field(f, "o" ++ "ne") = 4;
79 expect(f.one == 4);
80}
81
82const Foo = struct {
83 const constant = 52;
84
85 one: i32,
86 two: bool,
87 three: void,
88};
89
90const Bar = union(enum) {
91 One: void,
92 Two: i32,
93 Three: bool,
94 Four: f64,
95};
96
test/stage1/behavior/sizeof_and_typeof.zig created+69
...@@ -0,0 +1,69 @@
1const builtin = @import("builtin");
2const expect = @import("std").testing.expect;
3
4test "@sizeOf and @typeOf" {
5 const y: @typeOf(x) = 120;
6 expect(@sizeOf(@typeOf(y)) == 2);
7}
8const x: u16 = 13;
9const z: @typeOf(x) = 19;
10
11const A = struct {
12 a: u8,
13 b: u32,
14 c: u8,
15 d: u3,
16 e: u5,
17 f: u16,
18 g: u16,
19};
20
21const P = packed struct {
22 a: u8,
23 b: u32,
24 c: u8,
25 d: u3,
26 e: u5,
27 f: u16,
28 g: u16,
29};
30
31test "@byteOffsetOf" {
32 // Packed structs have fixed memory layout
33 expect(@byteOffsetOf(P, "a") == 0);
34 expect(@byteOffsetOf(P, "b") == 1);
35 expect(@byteOffsetOf(P, "c") == 5);
36 expect(@byteOffsetOf(P, "d") == 6);
37 expect(@byteOffsetOf(P, "e") == 6);
38 expect(@byteOffsetOf(P, "f") == 7);
39 expect(@byteOffsetOf(P, "g") == 9);
40
41 // Normal struct fields can be moved/padded
42 var a: A = undefined;
43 expect(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a"));
44 expect(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b"));
45 expect(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c"));
46 expect(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d"));
47 expect(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e"));
48 expect(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f"));
49 expect(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g"));
50}
51
52test "@bitOffsetOf" {
53 // Packed structs have fixed memory layout
54 expect(@bitOffsetOf(P, "a") == 0);
55 expect(@bitOffsetOf(P, "b") == 8);
56 expect(@bitOffsetOf(P, "c") == 40);
57 expect(@bitOffsetOf(P, "d") == 48);
58 expect(@bitOffsetOf(P, "e") == 51);
59 expect(@bitOffsetOf(P, "f") == 56);
60 expect(@bitOffsetOf(P, "g") == 72);
61
62 expect(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a"));
63 expect(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b"));
64 expect(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c"));
65 expect(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d"));
66 expect(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e"));
67 expect(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
68 expect(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
69}
test/stage1/behavior/slice.zig created+40
...@@ -0,0 +1,40 @@
1const expect = @import("std").testing.expect;
2const mem = @import("std").mem;
3
4const x = @intToPtr([*]i32, 0x1000)[0..0x500];
5const y = x[0x100..];
6test "compile time slice of pointer to hard coded address" {
7 expect(@ptrToInt(x.ptr) == 0x1000);
8 expect(x.len == 0x500);
9
10 expect(@ptrToInt(y.ptr) == 0x1100);
11 expect(y.len == 0x400);
12}
13
14test "slice child property" {
15 var array: [5]i32 = undefined;
16 var slice = array[0..];
17 expect(@typeOf(slice).Child == i32);
18}
19
20test "runtime safety lets us slice from len..len" {
21 var an_array = []u8{
22 1,
23 2,
24 3,
25 };
26 expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
27}
28
29fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
30 return a_slice[start..end];
31}
32
33test "implicitly cast array of size 0 to slice" {
34 var msg = []u8{};
35 assertLenIsZero(msg);
36}
37
38fn assertLenIsZero(msg: []const u8) void {
39 expect(msg.len == 0);
40}
test/stage1/behavior/struct.zig created+470
...@@ -0,0 +1,470 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const builtin = @import("builtin");
4const maxInt = std.math.maxInt;
5
6const StructWithNoFields = struct {
7 fn add(a: i32, b: i32) i32 {
8 return a + b;
9 }
10};
11const empty_global_instance = StructWithNoFields{};
12
13test "call struct static method" {
14 const result = StructWithNoFields.add(3, 4);
15 expect(result == 7);
16}
17
18test "return empty struct instance" {
19 _ = returnEmptyStructInstance();
20}
21fn returnEmptyStructInstance() StructWithNoFields {
22 return empty_global_instance;
23}
24
25const should_be_11 = StructWithNoFields.add(5, 6);
26
27test "invoke static method in global scope" {
28 expect(should_be_11 == 11);
29}
30
31test "void struct fields" {
32 const foo = VoidStructFieldsFoo{
33 .a = void{},
34 .b = 1,
35 .c = void{},
36 };
37 expect(foo.b == 1);
38 expect(@sizeOf(VoidStructFieldsFoo) == 4);
39}
40const VoidStructFieldsFoo = struct {
41 a: void,
42 b: i32,
43 c: void,
44};
45
46test "structs" {
47 var foo: StructFoo = undefined;
48 @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo));
49 foo.a += 1;
50 foo.b = foo.a == 1;
51 testFoo(foo);
52 testMutation(&foo);
53 expect(foo.c == 100);
54}
55const StructFoo = struct {
56 a: i32,
57 b: bool,
58 c: f32,
59};
60fn testFoo(foo: StructFoo) void {
61 expect(foo.b);
62}
63fn testMutation(foo: *StructFoo) void {
64 foo.c = 100;
65}
66
67const Node = struct {
68 val: Val,
69 next: *Node,
70};
71
72const Val = struct {
73 x: i32,
74};
75
76test "struct point to self" {
77 var root: Node = undefined;
78 root.val.x = 1;
79
80 var node: Node = undefined;
81 node.next = &root;
82 node.val.x = 2;
83
84 root.next = &node;
85
86 expect(node.next.next.next.val.x == 1);
87}
88
89test "struct byval assign" {
90 var foo1: StructFoo = undefined;
91 var foo2: StructFoo = undefined;
92
93 foo1.a = 1234;
94 foo2.a = 0;
95 expect(foo2.a == 0);
96 foo2 = foo1;
97 expect(foo2.a == 1234);
98}
99
100fn structInitializer() void {
101 const val = Val{ .x = 42 };
102 expect(val.x == 42);
103}
104
105test "fn call of struct field" {
106 expect(callStructField(Foo{ .ptr = aFunc }) == 13);
107}
108
109const Foo = struct {
110 ptr: fn () i32,
111};
112
113fn aFunc() i32 {
114 return 13;
115}
116
117fn callStructField(foo: Foo) i32 {
118 return foo.ptr();
119}
120
121test "store member function in variable" {
122 const instance = MemberFnTestFoo{ .x = 1234 };
123 const memberFn = MemberFnTestFoo.member;
124 const result = memberFn(instance);
125 expect(result == 1234);
126}
127const MemberFnTestFoo = struct {
128 x: i32,
129 fn member(foo: MemberFnTestFoo) i32 {
130 return foo.x;
131 }
132};
133
134test "call member function directly" {
135 const instance = MemberFnTestFoo{ .x = 1234 };
136 const result = MemberFnTestFoo.member(instance);
137 expect(result == 1234);
138}
139
140test "member functions" {
141 const r = MemberFnRand{ .seed = 1234 };
142 expect(r.getSeed() == 1234);
143}
144const MemberFnRand = struct {
145 seed: u32,
146 pub fn getSeed(r: *const MemberFnRand) u32 {
147 return r.seed;
148 }
149};
150
151test "return struct byval from function" {
152 const bar = makeBar(1234, 5678);
153 expect(bar.y == 5678);
154}
155const Bar = struct {
156 x: i32,
157 y: i32,
158};
159fn makeBar(x: i32, y: i32) Bar {
160 return Bar{
161 .x = x,
162 .y = y,
163 };
164}
165
166test "empty struct method call" {
167 const es = EmptyStruct{};
168 expect(es.method() == 1234);
169}
170const EmptyStruct = struct {
171 fn method(es: *const EmptyStruct) i32 {
172 return 1234;
173 }
174};
175
176test "return empty struct from fn" {
177 _ = testReturnEmptyStructFromFn();
178}
179const EmptyStruct2 = struct {};
180fn testReturnEmptyStructFromFn() EmptyStruct2 {
181 return EmptyStruct2{};
182}
183
184test "pass slice of empty struct to fn" {
185 expect(testPassSliceOfEmptyStructToFn([]EmptyStruct2{EmptyStruct2{}}) == 1);
186}
187fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize {
188 return slice.len;
189}
190
191const APackedStruct = packed struct {
192 x: u8,
193 y: u8,
194};
195
196test "packed struct" {
197 var foo = APackedStruct{
198 .x = 1,
199 .y = 2,
200 };
201 foo.y += 1;
202 const four = foo.x + foo.y;
203 expect(four == 4);
204}
205
206const BitField1 = packed struct {
207 a: u3,
208 b: u3,
209 c: u2,
210};
211
212const bit_field_1 = BitField1{
213 .a = 1,
214 .b = 2,
215 .c = 3,
216};
217
218test "bit field access" {
219 var data = bit_field_1;
220 expect(getA(&data) == 1);
221 expect(getB(&data) == 2);
222 expect(getC(&data) == 3);
223 comptime expect(@sizeOf(BitField1) == 1);
224
225 data.b += 1;
226 expect(data.b == 3);
227
228 data.a += 1;
229 expect(data.a == 2);
230 expect(data.b == 3);
231}
232
233fn getA(data: *const BitField1) u3 {
234 return data.a;
235}
236
237fn getB(data: *const BitField1) u3 {
238 return data.b;
239}
240
241fn getC(data: *const BitField1) u2 {
242 return data.c;
243}
244
245const Foo24Bits = packed struct {
246 field: u24,
247};
248const Foo96Bits = packed struct {
249 a: u24,
250 b: u24,
251 c: u24,
252 d: u24,
253};
254
255test "packed struct 24bits" {
256 comptime {
257 expect(@sizeOf(Foo24Bits) == 3);
258 expect(@sizeOf(Foo96Bits) == 12);
259 }
260
261 var value = Foo96Bits{
262 .a = 0,
263 .b = 0,
264 .c = 0,
265 .d = 0,
266 };
267 value.a += 1;
268 expect(value.a == 1);
269 expect(value.b == 0);
270 expect(value.c == 0);
271 expect(value.d == 0);
272
273 value.b += 1;
274 expect(value.a == 1);
275 expect(value.b == 1);
276 expect(value.c == 0);
277 expect(value.d == 0);
278
279 value.c += 1;
280 expect(value.a == 1);
281 expect(value.b == 1);
282 expect(value.c == 1);
283 expect(value.d == 0);
284
285 value.d += 1;
286 expect(value.a == 1);
287 expect(value.b == 1);
288 expect(value.c == 1);
289 expect(value.d == 1);
290}
291
292const FooArray24Bits = packed struct {
293 a: u16,
294 b: [2]Foo24Bits,
295 c: u16,
296};
297
298test "packed array 24bits" {
299 comptime {
300 expect(@sizeOf([9]Foo24Bits) == 9 * 3);
301 expect(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2);
302 }
303
304 var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1);
305 bytes[bytes.len - 1] = 0xaa;
306 const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0];
307 expect(ptr.a == 0);
308 expect(ptr.b[0].field == 0);
309 expect(ptr.b[1].field == 0);
310 expect(ptr.c == 0);
311
312 ptr.a = maxInt(u16);
313 expect(ptr.a == maxInt(u16));
314 expect(ptr.b[0].field == 0);
315 expect(ptr.b[1].field == 0);
316 expect(ptr.c == 0);
317
318 ptr.b[0].field = maxInt(u24);
319 expect(ptr.a == maxInt(u16));
320 expect(ptr.b[0].field == maxInt(u24));
321 expect(ptr.b[1].field == 0);
322 expect(ptr.c == 0);
323
324 ptr.b[1].field = maxInt(u24);
325 expect(ptr.a == maxInt(u16));
326 expect(ptr.b[0].field == maxInt(u24));
327 expect(ptr.b[1].field == maxInt(u24));
328 expect(ptr.c == 0);
329
330 ptr.c = maxInt(u16);
331 expect(ptr.a == maxInt(u16));
332 expect(ptr.b[0].field == maxInt(u24));
333 expect(ptr.b[1].field == maxInt(u24));
334 expect(ptr.c == maxInt(u16));
335
336 expect(bytes[bytes.len - 1] == 0xaa);
337}
338
339const FooStructAligned = packed struct {
340 a: u8,
341 b: u8,
342};
343
344const FooArrayOfAligned = packed struct {
345 a: [2]FooStructAligned,
346};
347
348test "aligned array of packed struct" {
349 comptime {
350 expect(@sizeOf(FooStructAligned) == 2);
351 expect(@sizeOf(FooArrayOfAligned) == 2 * 2);
352 }
353
354 var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned);
355 const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0];
356
357 expect(ptr.a[0].a == 0xbb);
358 expect(ptr.a[0].b == 0xbb);
359 expect(ptr.a[1].a == 0xbb);
360 expect(ptr.a[1].b == 0xbb);
361}
362
363test "runtime struct initialization of bitfield" {
364 const s1 = Nibbles{
365 .x = x1,
366 .y = x1,
367 };
368 const s2 = Nibbles{
369 .x = @intCast(u4, x2),
370 .y = @intCast(u4, x2),
371 };
372
373 expect(s1.x == x1);
374 expect(s1.y == x1);
375 expect(s2.x == @intCast(u4, x2));
376 expect(s2.y == @intCast(u4, x2));
377}
378
379var x1 = u4(1);
380var x2 = u8(2);
381
382const Nibbles = packed struct {
383 x: u4,
384 y: u4,
385};
386
387const Bitfields = packed struct {
388 f1: u16,
389 f2: u16,
390 f3: u8,
391 f4: u8,
392 f5: u4,
393 f6: u4,
394 f7: u8,
395};
396
397test "native bit field understands endianness" {
398 var all: u64 = 0x7765443322221111;
399 var bytes: [8]u8 = undefined;
400 @memcpy(bytes[0..].ptr, @ptrCast([*]u8, &all), 8);
401 var bitfields = @ptrCast(*Bitfields, bytes[0..].ptr).*;
402
403 expect(bitfields.f1 == 0x1111);
404 expect(bitfields.f2 == 0x2222);
405 expect(bitfields.f3 == 0x33);
406 expect(bitfields.f4 == 0x44);
407 expect(bitfields.f5 == 0x5);
408 expect(bitfields.f6 == 0x6);
409 expect(bitfields.f7 == 0x77);
410}
411
412test "align 1 field before self referential align 8 field as slice return type" {
413 const result = alloc(Expr);
414 expect(result.len == 0);
415}
416
417const Expr = union(enum) {
418 Literal: u8,
419 Question: *Expr,
420};
421
422fn alloc(comptime T: type) []T {
423 return []T{};
424}
425
426test "call method with mutable reference to struct with no fields" {
427 const S = struct {
428 fn doC(s: *const @This()) bool {
429 return true;
430 }
431 fn do(s: *@This()) bool {
432 return true;
433 }
434 };
435
436 var s = S{};
437 expect(S.doC(&s));
438 expect(s.doC());
439 expect(S.do(&s));
440 expect(s.do());
441}
442
443test "implicit cast packed struct field to const ptr" {
444 const LevelUpMove = packed struct {
445 move_id: u9,
446 level: u7,
447
448 fn toInt(value: u7) u7 {
449 return value;
450 }
451 };
452
453 var lup: LevelUpMove = undefined;
454 lup.level = 12;
455 const res = LevelUpMove.toInt(lup.level);
456 expect(res == 12);
457}
458
459test "pointer to packed struct member in a stack variable" {
460 const S = packed struct {
461 a: u2,
462 b: u2,
463 };
464
465 var s = S{ .a = 2, .b = 0 };
466 var b_ptr = &s.b;
467 expect(s.b == 0);
468 b_ptr.* = 2;
469 expect(s.b == 2);
470}
test/stage1/behavior/struct_contains_null_ptr_itself.zig created+21
...@@ -0,0 +1,21 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "struct contains null pointer which contains original struct" {
5 var x: ?*NodeLineComment = null;
6 expect(x == null);
7}
8
9pub const Node = struct {
10 id: Id,
11 comment: ?*NodeLineComment,
12
13 pub const Id = enum {
14 Root,
15 LineComment,
16 };
17};
18
19pub const NodeLineComment = struct {
20 base: Node,
21};
test/stage1/behavior/struct_contains_slice_of_itself.zig created+85
...@@ -0,0 +1,85 @@
1const expect = @import("std").testing.expect;
2
3const Node = struct {
4 payload: i32,
5 children: []Node,
6};
7
8const NodeAligned = struct {
9 payload: i32,
10 children: []align(@alignOf(NodeAligned)) NodeAligned,
11};
12
13test "struct contains slice of itself" {
14 var other_nodes = []Node{
15 Node{
16 .payload = 31,
17 .children = []Node{},
18 },
19 Node{
20 .payload = 32,
21 .children = []Node{},
22 },
23 };
24 var nodes = []Node{
25 Node{
26 .payload = 1,
27 .children = []Node{},
28 },
29 Node{
30 .payload = 2,
31 .children = []Node{},
32 },
33 Node{
34 .payload = 3,
35 .children = other_nodes[0..],
36 },
37 };
38 const root = Node{
39 .payload = 1234,
40 .children = nodes[0..],
41 };
42 expect(root.payload == 1234);
43 expect(root.children[0].payload == 1);
44 expect(root.children[1].payload == 2);
45 expect(root.children[2].payload == 3);
46 expect(root.children[2].children[0].payload == 31);
47 expect(root.children[2].children[1].payload == 32);
48}
49
50test "struct contains aligned slice of itself" {
51 var other_nodes = []NodeAligned{
52 NodeAligned{
53 .payload = 31,
54 .children = []NodeAligned{},
55 },
56 NodeAligned{
57 .payload = 32,
58 .children = []NodeAligned{},
59 },
60 };
61 var nodes = []NodeAligned{
62 NodeAligned{
63 .payload = 1,
64 .children = []NodeAligned{},
65 },
66 NodeAligned{
67 .payload = 2,
68 .children = []NodeAligned{},
69 },
70 NodeAligned{
71 .payload = 3,
72 .children = other_nodes[0..],
73 },
74 };
75 const root = NodeAligned{
76 .payload = 1234,
77 .children = nodes[0..],
78 };
79 expect(root.payload == 1234);
80 expect(root.children[0].payload == 1);
81 expect(root.children[1].payload == 2);
82 expect(root.children[2].payload == 3);
83 expect(root.children[2].children[0].payload == 31);
84 expect(root.children[2].children[1].payload == 32);
85}
test/stage1/behavior/switch.zig created+271
...@@ -0,0 +1,271 @@
1const expect = @import("std").testing.expect;
2
3test "switch with numbers" {
4 testSwitchWithNumbers(13);
5}
6
7fn testSwitchWithNumbers(x: u32) void {
8 const result = switch (x) {
9 1, 2, 3, 4...8 => false,
10 13 => true,
11 else => false,
12 };
13 expect(result);
14}
15
16test "switch with all ranges" {
17 expect(testSwitchWithAllRanges(50, 3) == 1);
18 expect(testSwitchWithAllRanges(101, 0) == 2);
19 expect(testSwitchWithAllRanges(300, 5) == 3);
20 expect(testSwitchWithAllRanges(301, 6) == 6);
21}
22
23fn testSwitchWithAllRanges(x: u32, y: u32) u32 {
24 return switch (x) {
25 0...100 => 1,
26 101...200 => 2,
27 201...300 => 3,
28 else => y,
29 };
30}
31
32test "implicit comptime switch" {
33 const x = 3 + 4;
34 const result = switch (x) {
35 3 => 10,
36 4 => 11,
37 5, 6 => 12,
38 7, 8 => 13,
39 else => 14,
40 };
41
42 comptime {
43 expect(result + 1 == 14);
44 }
45}
46
47test "switch on enum" {
48 const fruit = Fruit.Orange;
49 nonConstSwitchOnEnum(fruit);
50}
51const Fruit = enum {
52 Apple,
53 Orange,
54 Banana,
55};
56fn nonConstSwitchOnEnum(fruit: Fruit) void {
57 switch (fruit) {
58 Fruit.Apple => unreachable,
59 Fruit.Orange => {},
60 Fruit.Banana => unreachable,
61 }
62}
63
64test "switch statement" {
65 nonConstSwitch(SwitchStatmentFoo.C);
66}
67fn nonConstSwitch(foo: SwitchStatmentFoo) void {
68 const val = switch (foo) {
69 SwitchStatmentFoo.A => i32(1),
70 SwitchStatmentFoo.B => 2,
71 SwitchStatmentFoo.C => 3,
72 SwitchStatmentFoo.D => 4,
73 };
74 expect(val == 3);
75}
76const SwitchStatmentFoo = enum {
77 A,
78 B,
79 C,
80 D,
81};
82
83test "switch prong with variable" {
84 switchProngWithVarFn(SwitchProngWithVarEnum{ .One = 13 });
85 switchProngWithVarFn(SwitchProngWithVarEnum{ .Two = 13.0 });
86 switchProngWithVarFn(SwitchProngWithVarEnum{ .Meh = {} });
87}
88const SwitchProngWithVarEnum = union(enum) {
89 One: i32,
90 Two: f32,
91 Meh: void,
92};
93fn switchProngWithVarFn(a: SwitchProngWithVarEnum) void {
94 switch (a) {
95 SwitchProngWithVarEnum.One => |x| {
96 expect(x == 13);
97 },
98 SwitchProngWithVarEnum.Two => |x| {
99 expect(x == 13.0);
100 },
101 SwitchProngWithVarEnum.Meh => |x| {
102 const v: void = x;
103 },
104 }
105}
106
107test "switch on enum using pointer capture" {
108 testSwitchEnumPtrCapture();
109 comptime testSwitchEnumPtrCapture();
110}
111
112fn testSwitchEnumPtrCapture() void {
113 var value = SwitchProngWithVarEnum{ .One = 1234 };
114 switch (value) {
115 SwitchProngWithVarEnum.One => |*x| x.* += 1,
116 else => unreachable,
117 }
118 switch (value) {
119 SwitchProngWithVarEnum.One => |x| expect(x == 1235),
120 else => unreachable,
121 }
122}
123
124test "switch with multiple expressions" {
125 const x = switch (returnsFive()) {
126 1, 2, 3 => 1,
127 4, 5, 6 => 2,
128 else => i32(3),
129 };
130 expect(x == 2);
131}
132fn returnsFive() i32 {
133 return 5;
134}
135
136const Number = union(enum) {
137 One: u64,
138 Two: u8,
139 Three: f32,
140};
141
142const number = Number{ .Three = 1.23 };
143
144fn returnsFalse() bool {
145 switch (number) {
146 Number.One => |x| return x > 1234,
147 Number.Two => |x| return x == 'a',
148 Number.Three => |x| return x > 12.34,
149 }
150}
151test "switch on const enum with var" {
152 expect(!returnsFalse());
153}
154
155test "switch on type" {
156 expect(trueIfBoolFalseOtherwise(bool));
157 expect(!trueIfBoolFalseOtherwise(i32));
158}
159
160fn trueIfBoolFalseOtherwise(comptime T: type) bool {
161 return switch (T) {
162 bool => true,
163 else => false,
164 };
165}
166
167test "switch handles all cases of number" {
168 testSwitchHandleAllCases();
169 comptime testSwitchHandleAllCases();
170}
171
172fn testSwitchHandleAllCases() void {
173 expect(testSwitchHandleAllCasesExhaustive(0) == 3);
174 expect(testSwitchHandleAllCasesExhaustive(1) == 2);
175 expect(testSwitchHandleAllCasesExhaustive(2) == 1);
176 expect(testSwitchHandleAllCasesExhaustive(3) == 0);
177
178 expect(testSwitchHandleAllCasesRange(100) == 0);
179 expect(testSwitchHandleAllCasesRange(200) == 1);
180 expect(testSwitchHandleAllCasesRange(201) == 2);
181 expect(testSwitchHandleAllCasesRange(202) == 4);
182 expect(testSwitchHandleAllCasesRange(230) == 3);
183}
184
185fn testSwitchHandleAllCasesExhaustive(x: u2) u2 {
186 return switch (x) {
187 0 => u2(3),
188 1 => 2,
189 2 => 1,
190 3 => 0,
191 };
192}
193
194fn testSwitchHandleAllCasesRange(x: u8) u8 {
195 return switch (x) {
196 0...100 => u8(0),
197 101...200 => 1,
198 201, 203 => 2,
199 202 => 4,
200 204...255 => 3,
201 };
202}
203
204test "switch all prongs unreachable" {
205 testAllProngsUnreachable();
206 comptime testAllProngsUnreachable();
207}
208
209fn testAllProngsUnreachable() void {
210 expect(switchWithUnreachable(1) == 2);
211 expect(switchWithUnreachable(2) == 10);
212}
213
214fn switchWithUnreachable(x: i32) i32 {
215 while (true) {
216 switch (x) {
217 1 => return 2,
218 2 => break,
219 else => continue,
220 }
221 }
222 return 10;
223}
224
225fn return_a_number() anyerror!i32 {
226 return 1;
227}
228
229test "capture value of switch with all unreachable prongs" {
230 const x = return_a_number() catch |err| switch (err) {
231 else => unreachable,
232 };
233 expect(x == 1);
234}
235
236test "switching on booleans" {
237 testSwitchOnBools();
238 comptime testSwitchOnBools();
239}
240
241fn testSwitchOnBools() void {
242 expect(testSwitchOnBoolsTrueAndFalse(true) == false);
243 expect(testSwitchOnBoolsTrueAndFalse(false) == true);
244
245 expect(testSwitchOnBoolsTrueWithElse(true) == false);
246 expect(testSwitchOnBoolsTrueWithElse(false) == true);
247
248 expect(testSwitchOnBoolsFalseWithElse(true) == false);
249 expect(testSwitchOnBoolsFalseWithElse(false) == true);
250}
251
252fn testSwitchOnBoolsTrueAndFalse(x: bool) bool {
253 return switch (x) {
254 true => false,
255 false => true,
256 };
257}
258
259fn testSwitchOnBoolsTrueWithElse(x: bool) bool {
260 return switch (x) {
261 true => false,
262 else => true,
263 };
264}
265
266fn testSwitchOnBoolsFalseWithElse(x: bool) bool {
267 return switch (x) {
268 false => true,
269 else => false,
270 };
271}
test/stage1/behavior/switch_prong_err_enum.zig created+30
...@@ -0,0 +1,30 @@
1const expect = @import("std").testing.expect;
2
3var read_count: u64 = 0;
4
5fn readOnce() anyerror!u64 {
6 read_count += 1;
7 return read_count;
8}
9
10const FormValue = union(enum) {
11 Address: u64,
12 Other: bool,
13};
14
15fn doThing(form_id: u64) anyerror!FormValue {
16 return switch (form_id) {
17 17 => FormValue{ .Address = try readOnce() },
18 else => error.InvalidDebugInfo,
19 };
20}
21
22test "switch prong returns error enum" {
23 switch (doThing(17) catch unreachable) {
24 FormValue.Address => |payload| {
25 expect(payload == 1);
26 },
27 else => unreachable,
28 }
29 expect(read_count == 1);
30}
test/stage1/behavior/switch_prong_implicit_cast.zig created+22
...@@ -0,0 +1,22 @@
1const expect = @import("std").testing.expect;
2
3const FormValue = union(enum) {
4 One: void,
5 Two: bool,
6};
7
8fn foo(id: u64) !FormValue {
9 return switch (id) {
10 2 => FormValue{ .Two = true },
11 1 => FormValue{ .One = {} },
12 else => return error.Whatever,
13 };
14}
15
16test "switch prong implicit cast" {
17 const result = switch (foo(2) catch unreachable) {
18 FormValue.One => false,
19 FormValue.Two => |x| x,
20 };
21 expect(result);
22}
test/stage1/behavior/syntax.zig created+60
...@@ -0,0 +1,60 @@
1// Test trailing comma syntax
2// zig fmt: off
3
4const struct_trailing_comma = struct { x: i32, y: i32, };
5const struct_no_comma = struct { x: i32, y: i32 };
6const struct_fn_no_comma = struct { fn m() void {} y: i32 };
7
8const enum_no_comma = enum { A, B };
9
10fn container_init() void {
11 const S = struct { x: i32, y: i32 };
12 _ = S { .x = 1, .y = 2 };
13 _ = S { .x = 1, .y = 2, };
14}
15
16fn type_expr_return1() if (true) A {}
17fn type_expr_return2() for (true) |_| A {}
18fn type_expr_return3() while (true) A {}
19fn type_expr_return4() comptime A {}
20
21fn switch_cases(x: i32) void {
22 switch (x) {
23 1,2,3 => {},
24 4,5, => {},
25 6...8, => {},
26 else => {},
27 }
28}
29
30fn switch_prongs(x: i32) void {
31 switch (x) {
32 0 => {},
33 else => {},
34 }
35 switch (x) {
36 0 => {},
37 else => {}
38 }
39}
40
41const fn_no_comma = fn(i32, i32)void;
42const fn_trailing_comma = fn(i32, i32,)void;
43
44fn fn_calls() void {
45 fn add(x: i32, y: i32,) i32 { x + y };
46 _ = add(1, 2);
47 _ = add(1, 2,);
48}
49
50fn asm_lists() void {
51 if (false) { // Build AST but don't analyze
52 asm ("not real assembly"
53 :[a] "x" (x),);
54 asm ("not real assembly"
55 :[a] "x" (->i32),:[a] "x" (1),);
56 asm ("still not real assembly"
57 :::"a","b",);
58 }
59}
60
test/stage1/behavior/this.zig created+35
...@@ -0,0 +1,35 @@
1const expect = @import("std").testing.expect;
2
3const module = @This();
4
5fn Point(comptime T: type) type {
6 return struct {
7 const Self = @This();
8 x: T,
9 y: T,
10
11 fn addOne(self: *Self) void {
12 self.x += 1;
13 self.y += 1;
14 }
15 };
16}
17
18fn add(x: i32, y: i32) i32 {
19 return x + y;
20}
21
22test "this refer to module call private fn" {
23 expect(module.add(1, 2) == 3);
24}
25
26test "this refer to container" {
27 var pt = Point(i32){
28 .x = 12,
29 .y = 34,
30 };
31 pt.addOne();
32 expect(pt.x == 13);
33 expect(pt.y == 35);
34}
35
test/stage1/behavior/truncate.zig created+36
...@@ -0,0 +1,36 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "truncate u0 to larger integer allowed and has comptime known result" {
5 var x: u0 = 0;
6 const y = @truncate(u8, x);
7 comptime expect(y == 0);
8}
9
10test "truncate.u0.literal" {
11 var z = @truncate(u0, 0);
12 expect(z == 0);
13}
14
15test "truncate.u0.const" {
16 const c0: usize = 0;
17 var z = @truncate(u0, c0);
18 expect(z == 0);
19}
20
21test "truncate.u0.var" {
22 var d: u8 = 2;
23 var z = @truncate(u0, d);
24 expect(z == 0);
25}
26
27test "truncate sign mismatch but comptime known so it works anyway" {
28 const x: u32 = 10;
29 var result = @truncate(i8, x);
30 expect(result == 10);
31}
32
33test "truncate on comptime integer" {
34 var x = @truncate(u16, 9999);
35 expect(x == 9999);
36}
test/stage1/behavior/try.zig created+43
...@@ -0,0 +1,43 @@
1const expect = @import("std").testing.expect;
2
3test "try on error union" {
4 tryOnErrorUnionImpl();
5 comptime tryOnErrorUnionImpl();
6}
7
8fn tryOnErrorUnionImpl() void {
9 const x = if (returnsTen()) |val| val + 1 else |err| switch (err) {
10 error.ItBroke, error.NoMem => 1,
11 error.CrappedOut => i32(2),
12 else => unreachable,
13 };
14 expect(x == 11);
15}
16
17fn returnsTen() anyerror!i32 {
18 return 10;
19}
20
21test "try without vars" {
22 const result1 = if (failIfTrue(true)) 1 else |_| i32(2);
23 expect(result1 == 2);
24
25 const result2 = if (failIfTrue(false)) 1 else |_| i32(2);
26 expect(result2 == 1);
27}
28
29fn failIfTrue(ok: bool) anyerror!void {
30 if (ok) {
31 return error.ItBroke;
32 } else {
33 return;
34 }
35}
36
37test "try then not executed with assignment" {
38 if (failIfTrue(true)) {
39 unreachable;
40 } else |err| {
41 expect(err == error.ItBroke);
42 }
43}
test/stage1/behavior/type_info.zig created+291
...@@ -0,0 +1,291 @@
1const expect = @import("std").testing.expect;
2const mem = @import("std").mem;
3const TypeInfo = @import("builtin").TypeInfo;
4const TypeId = @import("builtin").TypeId;
5
6test "type info: tag type, void info" {
7 testBasic();
8 comptime testBasic();
9}
10
11fn testBasic() void {
12 expect(@TagType(TypeInfo) == TypeId);
13 const void_info = @typeInfo(void);
14 expect(TypeId(void_info) == TypeId.Void);
15 expect(void_info.Void == {});
16}
17
18test "type info: integer, floating point type info" {
19 testIntFloat();
20 comptime testIntFloat();
21}
22
23fn testIntFloat() void {
24 const u8_info = @typeInfo(u8);
25 expect(TypeId(u8_info) == TypeId.Int);
26 expect(!u8_info.Int.is_signed);
27 expect(u8_info.Int.bits == 8);
28
29 const f64_info = @typeInfo(f64);
30 expect(TypeId(f64_info) == TypeId.Float);
31 expect(f64_info.Float.bits == 64);
32}
33
34test "type info: pointer type info" {
35 testPointer();
36 comptime testPointer();
37}
38
39fn testPointer() void {
40 const u32_ptr_info = @typeInfo(*u32);
41 expect(TypeId(u32_ptr_info) == TypeId.Pointer);
42 expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One);
43 expect(u32_ptr_info.Pointer.is_const == false);
44 expect(u32_ptr_info.Pointer.is_volatile == false);
45 expect(u32_ptr_info.Pointer.alignment == @alignOf(u32));
46 expect(u32_ptr_info.Pointer.child == u32);
47}
48
49test "type info: unknown length pointer type info" {
50 testUnknownLenPtr();
51 comptime testUnknownLenPtr();
52}
53
54fn testUnknownLenPtr() void {
55 const u32_ptr_info = @typeInfo([*]const volatile f64);
56 expect(TypeId(u32_ptr_info) == TypeId.Pointer);
57 expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
58 expect(u32_ptr_info.Pointer.is_const == true);
59 expect(u32_ptr_info.Pointer.is_volatile == true);
60 expect(u32_ptr_info.Pointer.alignment == @alignOf(f64));
61 expect(u32_ptr_info.Pointer.child == f64);
62}
63
64test "type info: C pointer type info" {
65 testCPtr();
66 comptime testCPtr();
67}
68
69fn testCPtr() void {
70 const ptr_info = @typeInfo([*c]align(4) const i8);
71 expect(TypeId(ptr_info) == TypeId.Pointer);
72 expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.C);
73 expect(ptr_info.Pointer.is_const);
74 expect(!ptr_info.Pointer.is_volatile);
75 expect(ptr_info.Pointer.alignment == 4);
76 expect(ptr_info.Pointer.child == i8);
77}
78
79test "type info: slice type info" {
80 testSlice();
81 comptime testSlice();
82}
83
84fn testSlice() void {
85 const u32_slice_info = @typeInfo([]u32);
86 expect(TypeId(u32_slice_info) == TypeId.Pointer);
87 expect(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice);
88 expect(u32_slice_info.Pointer.is_const == false);
89 expect(u32_slice_info.Pointer.is_volatile == false);
90 expect(u32_slice_info.Pointer.alignment == 4);
91 expect(u32_slice_info.Pointer.child == u32);
92}
93
94test "type info: array type info" {
95 testArray();
96 comptime testArray();
97}
98
99fn testArray() void {
100 const arr_info = @typeInfo([42]bool);
101 expect(TypeId(arr_info) == TypeId.Array);
102 expect(arr_info.Array.len == 42);
103 expect(arr_info.Array.child == bool);
104}
105
106test "type info: optional type info" {
107 testOptional();
108 comptime testOptional();
109}
110
111fn testOptional() void {
112 const null_info = @typeInfo(?void);
113 expect(TypeId(null_info) == TypeId.Optional);
114 expect(null_info.Optional.child == void);
115}
116
117test "type info: promise info" {
118 testPromise();
119 comptime testPromise();
120}
121
122fn testPromise() void {
123 const null_promise_info = @typeInfo(promise);
124 expect(TypeId(null_promise_info) == TypeId.Promise);
125 expect(null_promise_info.Promise.child == null);
126
127 const promise_info = @typeInfo(promise->usize);
128 expect(TypeId(promise_info) == TypeId.Promise);
129 expect(promise_info.Promise.child.? == usize);
130}
131
132test "type info: error set, error union info" {
133 testErrorSet();
134 comptime testErrorSet();
135}
136
137fn testErrorSet() void {
138 const TestErrorSet = error{
139 First,
140 Second,
141 Third,
142 };
143
144 const error_set_info = @typeInfo(TestErrorSet);
145 expect(TypeId(error_set_info) == TypeId.ErrorSet);
146 expect(error_set_info.ErrorSet.errors.len == 3);
147 expect(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
148 expect(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third));
149
150 const error_union_info = @typeInfo(TestErrorSet!usize);
151 expect(TypeId(error_union_info) == TypeId.ErrorUnion);
152 expect(error_union_info.ErrorUnion.error_set == TestErrorSet);
153 expect(error_union_info.ErrorUnion.payload == usize);
154}
155
156test "type info: enum info" {
157 testEnum();
158 comptime testEnum();
159}
160
161fn testEnum() void {
162 const Os = enum {
163 Windows,
164 Macos,
165 Linux,
166 FreeBSD,
167 };
168
169 const os_info = @typeInfo(Os);
170 expect(TypeId(os_info) == TypeId.Enum);
171 expect(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
172 expect(os_info.Enum.fields.len == 4);
173 expect(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
174 expect(os_info.Enum.fields[3].value == 3);
175 expect(os_info.Enum.tag_type == u2);
176 expect(os_info.Enum.defs.len == 0);
177}
178
179test "type info: union info" {
180 testUnion();
181 comptime testUnion();
182}
183
184fn testUnion() void {
185 const typeinfo_info = @typeInfo(TypeInfo);
186 expect(TypeId(typeinfo_info) == TypeId.Union);
187 expect(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
188 expect(typeinfo_info.Union.tag_type.? == TypeId);
189 expect(typeinfo_info.Union.fields.len == 25);
190 expect(typeinfo_info.Union.fields[4].enum_field != null);
191 expect(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
192 expect(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
193 expect(typeinfo_info.Union.defs.len == 21);
194
195 const TestNoTagUnion = union {
196 Foo: void,
197 Bar: u32,
198 };
199
200 const notag_union_info = @typeInfo(TestNoTagUnion);
201 expect(TypeId(notag_union_info) == TypeId.Union);
202 expect(notag_union_info.Union.tag_type == null);
203 expect(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
204 expect(notag_union_info.Union.fields.len == 2);
205 expect(notag_union_info.Union.fields[0].enum_field == null);
206 expect(notag_union_info.Union.fields[1].field_type == u32);
207
208 const TestExternUnion = extern union {
209 foo: *c_void,
210 };
211
212 const extern_union_info = @typeInfo(TestExternUnion);
213 expect(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
214 expect(extern_union_info.Union.tag_type == null);
215 expect(extern_union_info.Union.fields[0].enum_field == null);
216 expect(extern_union_info.Union.fields[0].field_type == *c_void);
217}
218
219test "type info: struct info" {
220 testStruct();
221 comptime testStruct();
222}
223
224fn testStruct() void {
225 const struct_info = @typeInfo(TestStruct);
226 expect(TypeId(struct_info) == TypeId.Struct);
227 expect(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
228 expect(struct_info.Struct.fields.len == 3);
229 expect(struct_info.Struct.fields[1].offset == null);
230 expect(struct_info.Struct.fields[2].field_type == *TestStruct);
231 expect(struct_info.Struct.defs.len == 2);
232 expect(struct_info.Struct.defs[0].is_pub);
233 expect(!struct_info.Struct.defs[0].data.Fn.is_extern);
234 expect(struct_info.Struct.defs[0].data.Fn.lib_name == null);
235 expect(struct_info.Struct.defs[0].data.Fn.return_type == void);
236 expect(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void);
237}
238
239const TestStruct = packed struct {
240 const Self = @This();
241
242 fieldA: usize,
243 fieldB: void,
244 fieldC: *Self,
245
246 pub fn foo(self: *const Self) void {}
247};
248
249test "type info: function type info" {
250 testFunction();
251 comptime testFunction();
252}
253
254fn testFunction() void {
255 const fn_info = @typeInfo(@typeOf(foo));
256 expect(TypeId(fn_info) == TypeId.Fn);
257 expect(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
258 expect(fn_info.Fn.is_generic);
259 expect(fn_info.Fn.args.len == 2);
260 expect(fn_info.Fn.is_var_args);
261 expect(fn_info.Fn.return_type == null);
262 expect(fn_info.Fn.async_allocator_type == null);
263
264 const test_instance: TestStruct = undefined;
265 const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
266 expect(TypeId(bound_fn_info) == TypeId.BoundFn);
267 expect(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
268}
269
270fn foo(comptime a: usize, b: bool, args: ...) usize {
271 return 0;
272}
273
274test "typeInfo with comptime parameter in struct fn def" {
275 const S = struct {
276 pub fn func(comptime x: f32) void {}
277 };
278 comptime var info = @typeInfo(S);
279}
280
281test "type info: vectors" {
282 testVector();
283 comptime testVector();
284}
285
286fn testVector() void {
287 const vec_info = @typeInfo(@Vector(4, i32));
288 expect(TypeId(vec_info) == TypeId.Vector);
289 expect(vec_info.Vector.len == 4);
290 expect(vec_info.Vector.child == i32);
291}
test/stage1/behavior/undefined.zig created+69
...@@ -0,0 +1,69 @@
1const expect = @import("std").testing.expect;
2const mem = @import("std").mem;
3
4fn initStaticArray() [10]i32 {
5 var array: [10]i32 = undefined;
6 array[0] = 1;
7 array[4] = 2;
8 array[7] = 3;
9 array[9] = 4;
10 return array;
11}
12const static_array = initStaticArray();
13test "init static array to undefined" {
14 expect(static_array[0] == 1);
15 expect(static_array[4] == 2);
16 expect(static_array[7] == 3);
17 expect(static_array[9] == 4);
18
19 comptime {
20 expect(static_array[0] == 1);
21 expect(static_array[4] == 2);
22 expect(static_array[7] == 3);
23 expect(static_array[9] == 4);
24 }
25}
26
27const Foo = struct {
28 x: i32,
29
30 fn setFooXMethod(foo: *Foo) void {
31 foo.x = 3;
32 }
33};
34
35fn setFooX(foo: *Foo) void {
36 foo.x = 2;
37}
38
39test "assign undefined to struct" {
40 comptime {
41 var foo: Foo = undefined;
42 setFooX(&foo);
43 expect(foo.x == 2);
44 }
45 {
46 var foo: Foo = undefined;
47 setFooX(&foo);
48 expect(foo.x == 2);
49 }
50}
51
52test "assign undefined to struct with method" {
53 comptime {
54 var foo: Foo = undefined;
55 foo.setFooXMethod();
56 expect(foo.x == 3);
57 }
58 {
59 var foo: Foo = undefined;
60 foo.setFooXMethod();
61 expect(foo.x == 3);
62 }
63}
64
65test "type name of undefined" {
66 const x = undefined;
67 expect(mem.eql(u8, @typeName(@typeOf(x)), "(undefined)"));
68}
69
test/stage1/behavior/underscore.zig created+28
...@@ -0,0 +1,28 @@
1const std = @import("std");
2const expect = std.testing.expect;
3
4test "ignore lval with underscore" {
5 _ = false;
6}
7
8test "ignore lval with underscore (for loop)" {
9 for ([]void{}) |_, i| {
10 for ([]void{}) |_, j| {
11 break;
12 }
13 break;
14 }
15}
16
17test "ignore lval with underscore (while loop)" {
18 while (optionalReturnError()) |_| {
19 while (optionalReturnError()) |_| {
20 break;
21 } else |_| {}
22 break;
23 } else |_| {}
24}
25
26fn optionalReturnError() !?u32 {
27 return error.optionalReturnError;
28}
test/stage1/behavior/union.zig created+352
...@@ -0,0 +1,352 @@
1const expect = @import("std").testing.expect;
2
3const Value = union(enum) {
4 Int: u64,
5 Array: [9]u8,
6};
7
8const Agg = struct {
9 val1: Value,
10 val2: Value,
11};
12
13const v1 = Value{ .Int = 1234 };
14const v2 = Value{ .Array = []u8{3} ** 9 };
15
16const err = (anyerror!Agg)(Agg{
17 .val1 = v1,
18 .val2 = v2,
19});
20
21const array = []Value{
22 v1,
23 v2,
24 v1,
25 v2,
26};
27
28test "unions embedded in aggregate types" {
29 switch (array[1]) {
30 Value.Array => |arr| expect(arr[4] == 3),
31 else => unreachable,
32 }
33 switch ((err catch unreachable).val1) {
34 Value.Int => |x| expect(x == 1234),
35 else => unreachable,
36 }
37}
38
39const Foo = union {
40 float: f64,
41 int: i32,
42};
43
44test "basic unions" {
45 var foo = Foo{ .int = 1 };
46 expect(foo.int == 1);
47 foo = Foo{ .float = 12.34 };
48 expect(foo.float == 12.34);
49}
50
51test "comptime union field access" {
52 comptime {
53 var foo = Foo{ .int = 0 };
54 expect(foo.int == 0);
55
56 foo = Foo{ .float = 42.42 };
57 expect(foo.float == 42.42);
58 }
59}
60
61test "init union with runtime value" {
62 var foo: Foo = undefined;
63
64 setFloat(&foo, 12.34);
65 expect(foo.float == 12.34);
66
67 setInt(&foo, 42);
68 expect(foo.int == 42);
69}
70
71fn setFloat(foo: *Foo, x: f64) void {
72 foo.* = Foo{ .float = x };
73}
74
75fn setInt(foo: *Foo, x: i32) void {
76 foo.* = Foo{ .int = x };
77}
78
79const FooExtern = extern union {
80 float: f64,
81 int: i32,
82};
83
84test "basic extern unions" {
85 var foo = FooExtern{ .int = 1 };
86 expect(foo.int == 1);
87 foo.float = 12.34;
88 expect(foo.float == 12.34);
89}
90
91const Letter = enum {
92 A,
93 B,
94 C,
95};
96const Payload = union(Letter) {
97 A: i32,
98 B: f64,
99 C: bool,
100};
101
102test "union with specified enum tag" {
103 doTest();
104 comptime doTest();
105}
106
107fn doTest() void {
108 expect(bar(Payload{ .A = 1234 }) == -10);
109}
110
111fn bar(value: Payload) i32 {
112 expect(Letter(value) == Letter.A);
113 return switch (value) {
114 Payload.A => |x| return x - 1244,
115 Payload.B => |x| if (x == 12.34) i32(20) else 21,
116 Payload.C => |x| if (x) i32(30) else 31,
117 };
118}
119
120const MultipleChoice = union(enum(u32)) {
121 A = 20,
122 B = 40,
123 C = 60,
124 D = 1000,
125};
126test "simple union(enum(u32))" {
127 var x = MultipleChoice.C;
128 expect(x == MultipleChoice.C);
129 expect(@enumToInt(@TagType(MultipleChoice)(x)) == 60);
130}
131
132const MultipleChoice2 = union(enum(u32)) {
133 Unspecified1: i32,
134 A: f32 = 20,
135 Unspecified2: void,
136 B: bool = 40,
137 Unspecified3: i32,
138 C: i8 = 60,
139 Unspecified4: void,
140 D: void = 1000,
141 Unspecified5: i32,
142};
143
144test "union(enum(u32)) with specified and unspecified tag values" {
145 comptime expect(@TagType(@TagType(MultipleChoice2)) == u32);
146 testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
147 comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
148}
149
150fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
151 expect(@enumToInt(@TagType(MultipleChoice2)(x)) == 60);
152 expect(1123 == switch (x) {
153 MultipleChoice2.A => 1,
154 MultipleChoice2.B => 2,
155 MultipleChoice2.C => |v| i32(1000) + v,
156 MultipleChoice2.D => 4,
157 MultipleChoice2.Unspecified1 => 5,
158 MultipleChoice2.Unspecified2 => 6,
159 MultipleChoice2.Unspecified3 => 7,
160 MultipleChoice2.Unspecified4 => 8,
161 MultipleChoice2.Unspecified5 => 9,
162 });
163}
164
165const ExternPtrOrInt = extern union {
166 ptr: *u8,
167 int: u64,
168};
169test "extern union size" {
170 comptime expect(@sizeOf(ExternPtrOrInt) == 8);
171}
172
173const PackedPtrOrInt = packed union {
174 ptr: *u8,
175 int: u64,
176};
177test "extern union size" {
178 comptime expect(@sizeOf(PackedPtrOrInt) == 8);
179}
180
181const ZeroBits = union {
182 OnlyField: void,
183};
184test "union with only 1 field which is void should be zero bits" {
185 comptime expect(@sizeOf(ZeroBits) == 0);
186}
187
188const TheTag = enum {
189 A,
190 B,
191 C,
192};
193const TheUnion = union(TheTag) {
194 A: i32,
195 B: i32,
196 C: i32,
197};
198test "union field access gives the enum values" {
199 expect(TheUnion.A == TheTag.A);
200 expect(TheUnion.B == TheTag.B);
201 expect(TheUnion.C == TheTag.C);
202}
203
204test "cast union to tag type of union" {
205 testCastUnionToTagType(TheUnion{ .B = 1234 });
206 comptime testCastUnionToTagType(TheUnion{ .B = 1234 });
207}
208
209fn testCastUnionToTagType(x: TheUnion) void {
210 expect(TheTag(x) == TheTag.B);
211}
212
213test "cast tag type of union to union" {
214 var x: Value2 = Letter2.B;
215 expect(Letter2(x) == Letter2.B);
216}
217const Letter2 = enum {
218 A,
219 B,
220 C,
221};
222const Value2 = union(Letter2) {
223 A: i32,
224 B,
225 C,
226};
227
228test "implicit cast union to its tag type" {
229 var x: Value2 = Letter2.B;
230 expect(x == Letter2.B);
231 giveMeLetterB(x);
232}
233fn giveMeLetterB(x: Letter2) void {
234 expect(x == Value2.B);
235}
236
237pub const PackThis = union(enum) {
238 Invalid: bool,
239 StringLiteral: u2,
240};
241
242test "constant packed union" {
243 testConstPackedUnion([]PackThis{PackThis{ .StringLiteral = 1 }});
244}
245
246fn testConstPackedUnion(expected_tokens: []const PackThis) void {
247 expect(expected_tokens[0].StringLiteral == 1);
248}
249
250test "switch on union with only 1 field" {
251 var r: PartialInst = undefined;
252 r = PartialInst.Compiled;
253 switch (r) {
254 PartialInst.Compiled => {
255 var z: PartialInstWithPayload = undefined;
256 z = PartialInstWithPayload{ .Compiled = 1234 };
257 switch (z) {
258 PartialInstWithPayload.Compiled => |x| {
259 expect(x == 1234);
260 return;
261 },
262 }
263 },
264 }
265 unreachable;
266}
267
268const PartialInst = union(enum) {
269 Compiled,
270};
271
272const PartialInstWithPayload = union(enum) {
273 Compiled: i32,
274};
275
276test "access a member of tagged union with conflicting enum tag name" {
277 const Bar = union(enum) {
278 A: A,
279 B: B,
280
281 const A = u8;
282 const B = void;
283 };
284
285 comptime expect(Bar.A == u8);
286}
287
288test "tagged union initialization with runtime void" {
289 expect(testTaggedUnionInit({}));
290}
291
292const TaggedUnionWithAVoid = union(enum) {
293 A,
294 B: i32,
295};
296
297fn testTaggedUnionInit(x: var) bool {
298 const y = TaggedUnionWithAVoid{ .A = x };
299 return @TagType(TaggedUnionWithAVoid)(y) == TaggedUnionWithAVoid.A;
300}
301
302pub const UnionEnumNoPayloads = union(enum) {
303 A,
304 B,
305};
306
307test "tagged union with no payloads" {
308 const a = UnionEnumNoPayloads{ .B = {} };
309 switch (a) {
310 @TagType(UnionEnumNoPayloads).A => @panic("wrong"),
311 @TagType(UnionEnumNoPayloads).B => {},
312 }
313}
314
315test "union with only 1 field casted to its enum type" {
316 const Literal = union(enum) {
317 Number: f64,
318 Bool: bool,
319 };
320
321 const Expr = union(enum) {
322 Literal: Literal,
323 };
324
325 var e = Expr{ .Literal = Literal{ .Bool = true } };
326 const Tag = @TagType(Expr);
327 comptime expect(@TagType(Tag) == comptime_int);
328 var t = Tag(e);
329 expect(t == Expr.Literal);
330}
331
332test "union with only 1 field casted to its enum type which has enum value specified" {
333 const Literal = union(enum) {
334 Number: f64,
335 Bool: bool,
336 };
337
338 const Tag = enum {
339 Literal = 33,
340 };
341
342 const Expr = union(Tag) {
343 Literal: Literal,
344 };
345
346 var e = Expr{ .Literal = Literal{ .Bool = true } };
347 comptime expect(@TagType(Tag) == comptime_int);
348 var t = Tag(e);
349 expect(t == Expr.Literal);
350 expect(@enumToInt(t) == 33);
351 comptime expect(@enumToInt(t) == 33);
352}
test/stage1/behavior/var_args.zig created+84
...@@ -0,0 +1,84 @@
1const expect = @import("std").testing.expect;
2
3fn add(args: ...) i32 {
4 var sum = i32(0);
5 {
6 comptime var i: usize = 0;
7 inline while (i < args.len) : (i += 1) {
8 sum += args[i];
9 }
10 }
11 return sum;
12}
13
14test "add arbitrary args" {
15 expect(add(i32(1), i32(2), i32(3), i32(4)) == 10);
16 expect(add(i32(1234)) == 1234);
17 expect(add() == 0);
18}
19
20fn readFirstVarArg(args: ...) void {
21 const value = args[0];
22}
23
24test "send void arg to var args" {
25 readFirstVarArg({});
26}
27
28test "pass args directly" {
29 expect(addSomeStuff(i32(1), i32(2), i32(3), i32(4)) == 10);
30 expect(addSomeStuff(i32(1234)) == 1234);
31 expect(addSomeStuff() == 0);
32}
33
34fn addSomeStuff(args: ...) i32 {
35 return add(args);
36}
37
38test "runtime parameter before var args" {
39 expect(extraFn(10) == 0);
40 expect(extraFn(10, false) == 1);
41 expect(extraFn(10, false, true) == 2);
42
43 // TODO issue #313
44 //comptime {
45 // expect(extraFn(10) == 0);
46 // expect(extraFn(10, false) == 1);
47 // expect(extraFn(10, false, true) == 2);
48 //}
49}
50
51fn extraFn(extra: u32, args: ...) usize {
52 if (args.len >= 1) {
53 expect(args[0] == false);
54 }
55 if (args.len >= 2) {
56 expect(args[1] == true);
57 }
58 return args.len;
59}
60
61const foos = []fn (...) bool{
62 foo1,
63 foo2,
64};
65
66fn foo1(args: ...) bool {
67 return true;
68}
69fn foo2(args: ...) bool {
70 return false;
71}
72
73test "array of var args functions" {
74 expect(foos[0]());
75 expect(!foos[1]());
76}
77
78test "pass zero length array to var args param" {
79 doNothingWithFirstArg("");
80}
81
82fn doNothingWithFirstArg(args: ...) void {
83 const a = args[0];
84}
test/stage1/behavior/vector.zig created+45
...@@ -0,0 +1,45 @@
1const std = @import("std");
2const mem = std.mem;
3const expect = std.testing.expect;
4
5test "vector wrap operators" {
6 const S = struct {
7 fn doTheTest() void {
8 const v: @Vector(4, i32) = [4]i32{ 10, 20, 30, 40 };
9 const x: @Vector(4, i32) = [4]i32{ 1, 2, 3, 4 };
10 expect(mem.eql(i32, ([4]i32)(v +% x), [4]i32{ 11, 22, 33, 44 }));
11 expect(mem.eql(i32, ([4]i32)(v -% x), [4]i32{ 9, 18, 27, 36 }));
12 expect(mem.eql(i32, ([4]i32)(v *% x), [4]i32{ 10, 40, 90, 160 }));
13 }
14 };
15 S.doTheTest();
16 comptime S.doTheTest();
17}
18
19test "vector float operators" {
20 const S = struct {
21 fn doTheTest() void {
22 const v: @Vector(4, f32) = [4]f32{ 10, 20, 30, 40 };
23 const x: @Vector(4, f32) = [4]f32{ 1, 2, 3, 4 };
24 expect(mem.eql(f32, ([4]f32)(v + x), [4]f32{ 11, 22, 33, 44 }));
25 expect(mem.eql(f32, ([4]f32)(v - x), [4]f32{ 9, 18, 27, 36 }));
26 expect(mem.eql(f32, ([4]f32)(v * x), [4]f32{ 10, 40, 90, 160 }));
27 }
28 };
29 S.doTheTest();
30 comptime S.doTheTest();
31}
32
33test "vector bit operators" {
34 const S = struct {
35 fn doTheTest() void {
36 const v: @Vector(4, u8) = [4]u8{ 0b10101010, 0b10101010, 0b10101010, 0b10101010 };
37 const x: @Vector(4, u8) = [4]u8{ 0b11110000, 0b00001111, 0b10101010, 0b01010101 };
38 expect(mem.eql(u8, ([4]u8)(v ^ x), [4]u8{ 0b01011010, 0b10100101, 0b00000000, 0b11111111 }));
39 expect(mem.eql(u8, ([4]u8)(v | x), [4]u8{ 0b11111010, 0b10101111, 0b10101010, 0b11111111 }));
40 expect(mem.eql(u8, ([4]u8)(v & x), [4]u8{ 0b10100000, 0b00001010, 0b10101010, 0b00000000 }));
41 }
42 };
43 S.doTheTest();
44 comptime S.doTheTest();
45}
test/stage1/behavior/void.zig created+35
...@@ -0,0 +1,35 @@
1const expect = @import("std").testing.expect;
2
3const Foo = struct {
4 a: void,
5 b: i32,
6 c: void,
7};
8
9test "compare void with void compile time known" {
10 comptime {
11 const foo = Foo{
12 .a = {},
13 .b = 1,
14 .c = {},
15 };
16 expect(foo.a == {});
17 }
18}
19
20test "iterate over a void slice" {
21 var j: usize = 0;
22 for (times(10)) |_, i| {
23 expect(i == j);
24 j += 1;
25 }
26}
27
28fn times(n: usize) []const void {
29 return ([*]void)(undefined)[0..n];
30}
31
32test "void optional" {
33 var x: ?void = {};
34 expect(x != null);
35}
test/stage1/behavior/while.zig created+228
...@@ -0,0 +1,228 @@
1const expect = @import("std").testing.expect;
2
3test "while loop" {
4 var i: i32 = 0;
5 while (i < 4) {
6 i += 1;
7 }
8 expect(i == 4);
9 expect(whileLoop1() == 1);
10}
11fn whileLoop1() i32 {
12 return whileLoop2();
13}
14fn whileLoop2() i32 {
15 while (true) {
16 return 1;
17 }
18}
19
20test "static eval while" {
21 expect(static_eval_while_number == 1);
22}
23const static_eval_while_number = staticWhileLoop1();
24fn staticWhileLoop1() i32 {
25 return whileLoop2();
26}
27fn staticWhileLoop2() i32 {
28 while (true) {
29 return 1;
30 }
31}
32
33test "continue and break" {
34 runContinueAndBreakTest();
35 expect(continue_and_break_counter == 8);
36}
37var continue_and_break_counter: i32 = 0;
38fn runContinueAndBreakTest() void {
39 var i: i32 = 0;
40 while (true) {
41 continue_and_break_counter += 2;
42 i += 1;
43 if (i < 4) {
44 continue;
45 }
46 break;
47 }
48 expect(i == 4);
49}
50
51test "return with implicit cast from while loop" {
52 returnWithImplicitCastFromWhileLoopTest() catch unreachable;
53}
54fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {
55 while (true) {
56 return;
57 }
58}
59
60test "while with continue expression" {
61 var sum: i32 = 0;
62 {
63 var i: i32 = 0;
64 while (i < 10) : (i += 1) {
65 if (i == 5) continue;
66 sum += i;
67 }
68 }
69 expect(sum == 40);
70}
71
72test "while with else" {
73 var sum: i32 = 0;
74 var i: i32 = 0;
75 var got_else: i32 = 0;
76 while (i < 10) : (i += 1) {
77 sum += 1;
78 } else {
79 got_else += 1;
80 }
81 expect(sum == 10);
82 expect(got_else == 1);
83}
84
85test "while with optional as condition" {
86 numbers_left = 10;
87 var sum: i32 = 0;
88 while (getNumberOrNull()) |value| {
89 sum += value;
90 }
91 expect(sum == 45);
92}
93
94test "while with optional as condition with else" {
95 numbers_left = 10;
96 var sum: i32 = 0;
97 var got_else: i32 = 0;
98 while (getNumberOrNull()) |value| {
99 sum += value;
100 expect(got_else == 0);
101 } else {
102 got_else += 1;
103 }
104 expect(sum == 45);
105 expect(got_else == 1);
106}
107
108test "while with error union condition" {
109 numbers_left = 10;
110 var sum: i32 = 0;
111 var got_else: i32 = 0;
112 while (getNumberOrErr()) |value| {
113 sum += value;
114 } else |err| {
115 expect(err == error.OutOfNumbers);
116 got_else += 1;
117 }
118 expect(sum == 45);
119 expect(got_else == 1);
120}
121
122var numbers_left: i32 = undefined;
123fn getNumberOrErr() anyerror!i32 {
124 return if (numbers_left == 0) error.OutOfNumbers else x: {
125 numbers_left -= 1;
126 break :x numbers_left;
127 };
128}
129fn getNumberOrNull() ?i32 {
130 return if (numbers_left == 0) null else x: {
131 numbers_left -= 1;
132 break :x numbers_left;
133 };
134}
135
136test "while on optional with else result follow else prong" {
137 const result = while (returnNull()) |value| {
138 break value;
139 } else
140 i32(2);
141 expect(result == 2);
142}
143
144test "while on optional with else result follow break prong" {
145 const result = while (returnOptional(10)) |value| {
146 break value;
147 } else
148 i32(2);
149 expect(result == 10);
150}
151
152test "while on error union with else result follow else prong" {
153 const result = while (returnError()) |value| {
154 break value;
155 } else |err|
156 i32(2);
157 expect(result == 2);
158}
159
160test "while on error union with else result follow break prong" {
161 const result = while (returnSuccess(10)) |value| {
162 break value;
163 } else |err|
164 i32(2);
165 expect(result == 10);
166}
167
168test "while on bool with else result follow else prong" {
169 const result = while (returnFalse()) {
170 break i32(10);
171 } else
172 i32(2);
173 expect(result == 2);
174}
175
176test "while on bool with else result follow break prong" {
177 const result = while (returnTrue()) {
178 break i32(10);
179 } else
180 i32(2);
181 expect(result == 10);
182}
183
184test "break from outer while loop" {
185 testBreakOuter();
186 comptime testBreakOuter();
187}
188
189fn testBreakOuter() void {
190 outer: while (true) {
191 while (true) {
192 break :outer;
193 }
194 }
195}
196
197test "continue outer while loop" {
198 testContinueOuter();
199 comptime testContinueOuter();
200}
201
202fn testContinueOuter() void {
203 var i: usize = 0;
204 outer: while (i < 10) : (i += 1) {
205 while (true) {
206 continue :outer;
207 }
208 }
209}
210
211fn returnNull() ?i32 {
212 return null;
213}
214fn returnOptional(x: i32) ?i32 {
215 return x;
216}
217fn returnError() anyerror!i32 {
218 return error.YouWantedAnError;
219}
220fn returnSuccess(x: i32) anyerror!i32 {
221 return x;
222}
223fn returnFalse() bool {
224 return false;
225}
226fn returnTrue() bool {
227 return true;
228}
test/stage1/behavior/widening.zig created+28
...@@ -0,0 +1,28 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const mem = std.mem;
4
5test "integer widening" {
6 var a: u8 = 250;
7 var b: u16 = a;
8 var c: u32 = b;
9 var d: u64 = c;
10 var e: u64 = d;
11 var f: u128 = e;
12 expect(f == a);
13}
14
15test "implicit unsigned integer to signed integer" {
16 var a: u8 = 250;
17 var b: i16 = a;
18 expect(b == 250);
19}
20
21test "float widening" {
22 var a: f16 = 12.34;
23 var b: f32 = a;
24 var c: f64 = b;
25 var d: f128 = c;
26 expect(d == a);
27}
28
test/stage1/c_abi/main.zig+41-41
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;2const expect = std.testing.expect;
33
4extern fn run_c_tests() void;4extern fn run_c_tests() void;
55
...@@ -33,28 +33,28 @@ test "C ABI integers" {...@@ -33,28 +33,28 @@ test "C ABI integers" {
33}33}
3434
35export fn zig_u8(x: u8) void {35export fn zig_u8(x: u8) void {
36 assertOrPanic(x == 0xff);36 expect(x == 0xff);
37}37}
38export fn zig_u16(x: u16) void {38export fn zig_u16(x: u16) void {
39 assertOrPanic(x == 0xfffe);39 expect(x == 0xfffe);
40}40}
41export fn zig_u32(x: u32) void {41export fn zig_u32(x: u32) void {
42 assertOrPanic(x == 0xfffffffd);42 expect(x == 0xfffffffd);
43}43}
44export fn zig_u64(x: u64) void {44export fn zig_u64(x: u64) void {
45 assertOrPanic(x == 0xfffffffffffffffc);45 expect(x == 0xfffffffffffffffc);
46}46}
47export fn zig_i8(x: i8) void {47export fn zig_i8(x: i8) void {
48 assertOrPanic(x == -1);48 expect(x == -1);
49}49}
50export fn zig_i16(x: i16) void {50export fn zig_i16(x: i16) void {
51 assertOrPanic(x == -2);51 expect(x == -2);
52}52}
53export fn zig_i32(x: i32) void {53export fn zig_i32(x: i32) void {
54 assertOrPanic(x == -3);54 expect(x == -3);
55}55}
56export fn zig_i64(x: i64) void {56export fn zig_i64(x: i64) void {
57 assertOrPanic(x == -4);57 expect(x == -4);
58}58}
5959
60extern fn c_f32(f32) void;60extern fn c_f32(f32) void;
...@@ -66,10 +66,10 @@ test "C ABI floats" {...@@ -66,10 +66,10 @@ test "C ABI floats" {
66}66}
6767
68export fn zig_f32(x: f32) void {68export fn zig_f32(x: f32) void {
69 assertOrPanic(x == 12.34);69 expect(x == 12.34);
70}70}
71export fn zig_f64(x: f64) void {71export fn zig_f64(x: f64) void {
72 assertOrPanic(x == 56.78);72 expect(x == 56.78);
73}73}
7474
75extern fn c_ptr(*c_void) void;75extern fn c_ptr(*c_void) void;
...@@ -79,7 +79,7 @@ test "C ABI pointer" {...@@ -79,7 +79,7 @@ test "C ABI pointer" {
79}79}
8080
81export fn zig_ptr(x: *c_void) void {81export fn zig_ptr(x: *c_void) void {
82 assertOrPanic(@ptrToInt(x) == 0xdeadbeef);82 expect(@ptrToInt(x) == 0xdeadbeef);
83}83}
8484
85extern fn c_bool(bool) void;85extern fn c_bool(bool) void;
...@@ -89,7 +89,7 @@ test "C ABI bool" {...@@ -89,7 +89,7 @@ test "C ABI bool" {
89}89}
9090
91export fn zig_bool(x: bool) void {91export fn zig_bool(x: bool) void {
92 assertOrPanic(x);92 expect(x);
93}93}
9494
95extern fn c_array([10]u8) void;95extern fn c_array([10]u8) void;
...@@ -100,7 +100,7 @@ test "C ABI array" {...@@ -100,7 +100,7 @@ test "C ABI array" {
100}100}
101101
102export fn zig_array(x: [10]u8) void {102export fn zig_array(x: [10]u8) void {
103 assertOrPanic(std.mem.eql(u8, x, "1234567890"));103 expect(std.mem.eql(u8, x, "1234567890"));
104}104}
105105
106const BigStruct = extern struct {106const BigStruct = extern struct {
...@@ -124,11 +124,11 @@ test "C ABI big struct" {...@@ -124,11 +124,11 @@ test "C ABI big struct" {
124}124}
125125
126export fn zig_big_struct(x: BigStruct) void {126export fn zig_big_struct(x: BigStruct) void {
127 assertOrPanic(x.a == 1);127 expect(x.a == 1);
128 assertOrPanic(x.b == 2);128 expect(x.b == 2);
129 assertOrPanic(x.c == 3);129 expect(x.c == 3);
130 assertOrPanic(x.d == 4);130 expect(x.d == 4);
131 assertOrPanic(x.e == 5);131 expect(x.e == 5);
132}132}
133133
134const BigUnion = extern union {134const BigUnion = extern union {
...@@ -150,11 +150,11 @@ test "C ABI big union" {...@@ -150,11 +150,11 @@ test "C ABI big union" {
150}150}
151151
152export fn zig_big_union(x: BigUnion) void {152export fn zig_big_union(x: BigUnion) void {
153 assertOrPanic(x.a.a == 1);153 expect(x.a.a == 1);
154 assertOrPanic(x.a.b == 2);154 expect(x.a.b == 2);
155 assertOrPanic(x.a.c == 3);155 expect(x.a.c == 3);
156 assertOrPanic(x.a.d == 4);156 expect(x.a.d == 4);
157 assertOrPanic(x.a.e == 5);157 expect(x.a.e == 5);
158}158}
159159
160const SmallStructInts = extern struct {160const SmallStructInts = extern struct {
...@@ -176,10 +176,10 @@ test "C ABI small struct of ints" {...@@ -176,10 +176,10 @@ test "C ABI small struct of ints" {
176}176}
177177
178export fn zig_small_struct_ints(x: SmallStructInts) void {178export fn zig_small_struct_ints(x: SmallStructInts) void {
179 assertOrPanic(x.a == 1);179 expect(x.a == 1);
180 assertOrPanic(x.b == 2);180 expect(x.b == 2);
181 assertOrPanic(x.c == 3);181 expect(x.c == 3);
182 assertOrPanic(x.d == 4);182 expect(x.d == 4);
183}183}
184184
185const SplitStructInt = extern struct {185const SplitStructInt = extern struct {
...@@ -199,9 +199,9 @@ test "C ABI split struct of ints" {...@@ -199,9 +199,9 @@ test "C ABI split struct of ints" {
199}199}
200200
201export fn zig_split_struct_ints(x: SplitStructInt) void {201export fn zig_split_struct_ints(x: SplitStructInt) void {
202 assertOrPanic(x.a == 1234);202 expect(x.a == 1234);
203 assertOrPanic(x.b == 100);203 expect(x.b == 100);
204 assertOrPanic(x.c == 1337);204 expect(x.c == 1337);
205}205}
206206
207extern fn c_big_struct_both(BigStruct) BigStruct;207extern fn c_big_struct_both(BigStruct) BigStruct;
...@@ -215,19 +215,19 @@ test "C ABI sret and byval together" {...@@ -215,19 +215,19 @@ test "C ABI sret and byval together" {
215 .e = 5,215 .e = 5,
216 };216 };
217 var y = c_big_struct_both(s);217 var y = c_big_struct_both(s);
218 assertOrPanic(y.a == 10);218 expect(y.a == 10);
219 assertOrPanic(y.b == 11);219 expect(y.b == 11);
220 assertOrPanic(y.c == 12);220 expect(y.c == 12);
221 assertOrPanic(y.d == 13);221 expect(y.d == 13);
222 assertOrPanic(y.e == 14);222 expect(y.e == 14);
223}223}
224224
225export fn zig_big_struct_both(x: BigStruct) BigStruct {225export fn zig_big_struct_both(x: BigStruct) BigStruct {
226 assertOrPanic(x.a == 30);226 expect(x.a == 30);
227 assertOrPanic(x.b == 31);227 expect(x.b == 31);
228 assertOrPanic(x.c == 32);228 expect(x.c == 32);
229 assertOrPanic(x.d == 33);229 expect(x.d == 33);
230 assertOrPanic(x.e == 34);230 expect(x.e == 34);
231 var s = BigStruct{231 var s = BigStruct{
232 .a = 20,232 .a = 20,
233 .b = 21,233 .b = 21,
test/standalone/brace_expansion/main.zig+3-6
...@@ -3,6 +3,7 @@ const io = std.io;...@@ -3,6 +3,7 @@ const io = std.io;
3const mem = std.mem;3const mem = std.mem;
4const debug = std.debug;4const debug = std.debug;
5const assert = debug.assert;5const assert = debug.assert;
6const testing = std.testing;
6const Buffer = std.Buffer;7const Buffer = std.Buffer;
7const ArrayList = std.ArrayList;8const ArrayList = std.ArrayList;
8const maxInt = std.math.maxInt;9const maxInt = std.math.maxInt;
...@@ -220,11 +221,7 @@ fn expectError(test_input: []const u8, expected_err: anyerror) void {...@@ -220,11 +221,7 @@ fn expectError(test_input: []const u8, expected_err: anyerror) void {
220 var output_buf = Buffer.initSize(global_allocator, 0) catch unreachable;221 var output_buf = Buffer.initSize(global_allocator, 0) catch unreachable;
221 defer output_buf.deinit();222 defer output_buf.deinit();
222223
223 if (expandString(test_input, &output_buf)) {224 testing.expectError(expected_err, expandString(test_input, &output_buf));
224 unreachable;
225 } else |err| {
226 assert(expected_err == err);
227 }
228}225}
229226
230test "valid inputs" {227test "valid inputs" {
...@@ -256,5 +253,5 @@ fn expectExpansion(test_input: []const u8, expected_result: []const u8) void {...@@ -256,5 +253,5 @@ fn expectExpansion(test_input: []const u8, expected_result: []const u8) void {
256253
257 expandString(test_input, &result) catch unreachable;254 expandString(test_input, &result) catch unreachable;
258255
259 assert(mem.eql(u8, result.toSlice(), expected_result));256 testing.expectEqualSlices(u8, expected_result, result.toSlice());
260}257}
test/standalone/issue_794/main.zig+2-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1const c = @cImport(@cInclude("foo.h"));1const c = @cImport(@cInclude("foo.h"));
2const std = @import("std");2const std = @import("std");
3const assert = std.debug.assert;3const testing = std.testing;
44
5test "c import" {5test "c import" {
6 comptime assert(c.NUMBER == 1234);6 comptime testing.expect(c.NUMBER == 1234);
7}7}
test/tests.zig+132-60
...@@ -48,13 +48,14 @@ const test_targets = []TestTarget{...@@ -48,13 +48,14 @@ const test_targets = []TestTarget{
48const max_stdout_size = 1 * 1024 * 1024; // 1 MB48const max_stdout_size = 1 * 1024 * 1024; // 1 MB
4949
50pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {50pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
51 const cases = b.allocator.create(CompareOutputContext{51 const cases = b.allocator.create(CompareOutputContext) catch unreachable;
52 cases.* = CompareOutputContext{
52 .b = b,53 .b = b,
53 .step = b.step("test-compare-output", "Run the compare output tests"),54 .step = b.step("test-compare-output", "Run the compare output tests"),
54 .test_index = 0,55 .test_index = 0,
55 .test_filter = test_filter,56 .test_filter = test_filter,
56 .modes = modes,57 .modes = modes,
57 }) catch unreachable;58 };
5859
59 compare_output.addCases(cases);60 compare_output.addCases(cases);
6061
...@@ -62,13 +63,14 @@ pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes:...@@ -62,13 +63,14 @@ pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes:
62}63}
6364
64pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {65pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
65 const cases = b.allocator.create(CompareOutputContext{66 const cases = b.allocator.create(CompareOutputContext) catch unreachable;
67 cases.* = CompareOutputContext{
66 .b = b,68 .b = b,
67 .step = b.step("test-runtime-safety", "Run the runtime safety tests"),69 .step = b.step("test-runtime-safety", "Run the runtime safety tests"),
68 .test_index = 0,70 .test_index = 0,
69 .test_filter = test_filter,71 .test_filter = test_filter,
70 .modes = modes,72 .modes = modes,
71 }) catch unreachable;73 };
7274
73 runtime_safety.addCases(cases);75 runtime_safety.addCases(cases);
7476
...@@ -76,13 +78,14 @@ pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes:...@@ -76,13 +78,14 @@ pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes:
76}78}
7779
78pub fn addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {80pub fn addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
79 const cases = b.allocator.create(CompileErrorContext{81 const cases = b.allocator.create(CompileErrorContext) catch unreachable;
82 cases.* = CompileErrorContext{
80 .b = b,83 .b = b,
81 .step = b.step("test-compile-errors", "Run the compile error tests"),84 .step = b.step("test-compile-errors", "Run the compile error tests"),
82 .test_index = 0,85 .test_index = 0,
83 .test_filter = test_filter,86 .test_filter = test_filter,
84 .modes = modes,87 .modes = modes,
85 }) catch unreachable;88 };
8689
87 compile_errors.addCases(cases);90 compile_errors.addCases(cases);
8891
...@@ -90,13 +93,14 @@ pub fn addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes:...@@ -90,13 +93,14 @@ pub fn addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes:
90}93}
9194
92pub fn addBuildExampleTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {95pub fn addBuildExampleTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
93 const cases = b.allocator.create(BuildExamplesContext{96 const cases = b.allocator.create(BuildExamplesContext) catch unreachable;
97 cases.* = BuildExamplesContext{
94 .b = b,98 .b = b,
95 .step = b.step("test-build-examples", "Build the examples"),99 .step = b.step("test-build-examples", "Build the examples"),
96 .test_index = 0,100 .test_index = 0,
97 .test_filter = test_filter,101 .test_filter = test_filter,
98 .modes = modes,102 .modes = modes,
99 }) catch unreachable;103 };
100104
101 build_examples.addCases(cases);105 build_examples.addCases(cases);
102106
...@@ -119,13 +123,14 @@ pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const M...@@ -119,13 +123,14 @@ pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const M
119}123}
120124
121pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {125pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
122 const cases = b.allocator.create(CompareOutputContext{126 const cases = b.allocator.create(CompareOutputContext) catch unreachable;
127 cases.* = CompareOutputContext{
123 .b = b,128 .b = b,
124 .step = b.step("test-asm-link", "Run the assemble and link tests"),129 .step = b.step("test-asm-link", "Run the assemble and link tests"),
125 .test_index = 0,130 .test_index = 0,
126 .test_filter = test_filter,131 .test_filter = test_filter,
127 .modes = modes,132 .modes = modes,
128 }) catch unreachable;133 };
129134
130 assemble_and_link.addCases(cases);135 assemble_and_link.addCases(cases);
131136
...@@ -133,12 +138,13 @@ pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, mode...@@ -133,12 +138,13 @@ pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, mode
133}138}
134139
135pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step {140pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step {
136 const cases = b.allocator.create(TranslateCContext{141 const cases = b.allocator.create(TranslateCContext) catch unreachable;
142 cases.* = TranslateCContext{
137 .b = b,143 .b = b,
138 .step = b.step("test-translate-c", "Run the C transation tests"),144 .step = b.step("test-translate-c", "Run the C transation tests"),
139 .test_index = 0,145 .test_index = 0,
140 .test_filter = test_filter,146 .test_filter = test_filter,
141 }) catch unreachable;147 };
142148
143 translate_c.addCases(cases);149 translate_c.addCases(cases);
144150
...@@ -146,12 +152,13 @@ pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.St...@@ -146,12 +152,13 @@ pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.St
146}152}
147153
148pub fn addGenHTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step {154pub fn addGenHTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step {
149 const cases = b.allocator.create(GenHContext{155 const cases = b.allocator.create(GenHContext) catch unreachable;
156 cases.* = GenHContext{
150 .b = b,157 .b = b,
151 .step = b.step("test-gen-h", "Run the C header file generation tests"),158 .step = b.step("test-gen-h", "Run the C header file generation tests"),
152 .test_index = 0,159 .test_index = 0,
153 .test_filter = test_filter,160 .test_filter = test_filter,
154 }) catch unreachable;161 };
155162
156 gen_h.addCases(cases);163 gen_h.addCases(cases);
157164
...@@ -163,25 +170,35 @@ pub fn addPkgTests(b: *build.Builder, test_filter: ?[]const u8, root_src: []cons...@@ -163,25 +170,35 @@ pub fn addPkgTests(b: *build.Builder, test_filter: ?[]const u8, root_src: []cons
163 for (test_targets) |test_target| {170 for (test_targets) |test_target| {
164 const is_native = (test_target.os == builtin.os and test_target.arch == builtin.arch);171 const is_native = (test_target.os == builtin.os and test_target.arch == builtin.arch);
165 for (modes) |mode| {172 for (modes) |mode| {
166 for ([]bool{173 for ([]bool{ false, true }) |link_libc| {
167 false,174 for ([]bool{ false, true }) |single_threaded| {
168 true,175 if (link_libc and !is_native) {
169 }) |link_libc| {176 // don't assume we have a cross-compiling libc set up
170 if (link_libc and !is_native) {177 continue;
171 // don't assume we have a cross-compiling libc set up178 }
172 continue;179 const these_tests = b.addTest(root_src);
173 }180 these_tests.setNamePrefix(b.fmt(
174 const these_tests = b.addTest(root_src);181 "{}-{}-{}-{}-{}-{} ",
175 these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os), @tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare"));182 name,
176 these_tests.setFilter(test_filter);183 @tagName(test_target.os),
177 these_tests.setBuildMode(mode);184 @tagName(test_target.arch),
178 if (!is_native) {185 @tagName(mode),
179 these_tests.setTarget(test_target.arch, test_target.os, test_target.environ);186 if (link_libc) "c" else "bare",
180 }187 if (single_threaded) "single" else "multi",
181 if (link_libc) {188 ));
182 these_tests.linkSystemLibrary("c");189 these_tests.setFilter(test_filter);
190 these_tests.setBuildMode(mode);
191 if (!is_native) {
192 these_tests.setTarget(test_target.arch, test_target.os, test_target.environ);
193 }
194 if (link_libc) {
195 these_tests.linkSystemLibrary("c");
196 }
197 if (mem.eql(u8, name, "std")) {
198 these_tests.overrideStdDir("std");
199 }
200 step.dependOn(&these_tests.step);
183 }201 }
184 step.dependOn(&these_tests.step);
185 }202 }
186 }203 }
187 }204 }
...@@ -237,7 +254,8 @@ pub const CompareOutputContext = struct {...@@ -237,7 +254,8 @@ pub const CompareOutputContext = struct {
237254
238 pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8, expected_output: []const u8, cli_args: []const []const u8) *RunCompareOutputStep {255 pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8, expected_output: []const u8, cli_args: []const []const u8) *RunCompareOutputStep {
239 const allocator = context.b.allocator;256 const allocator = context.b.allocator;
240 const ptr = allocator.create(RunCompareOutputStep{257 const ptr = allocator.create(RunCompareOutputStep) catch unreachable;
258 ptr.* = RunCompareOutputStep{
241 .context = context,259 .context = context,
242 .exe_path = exe_path,260 .exe_path = exe_path,
243 .name = name,261 .name = name,
...@@ -245,7 +263,7 @@ pub const CompareOutputContext = struct {...@@ -245,7 +263,7 @@ pub const CompareOutputContext = struct {
245 .test_index = context.test_index,263 .test_index = context.test_index,
246 .step = build.Step.init("RunCompareOutput", allocator, make),264 .step = build.Step.init("RunCompareOutput", allocator, make),
247 .cli_args = cli_args,265 .cli_args = cli_args,
248 }) catch unreachable;266 };
249 context.test_index += 1;267 context.test_index += 1;
250 return ptr;268 return ptr;
251 }269 }
...@@ -324,13 +342,14 @@ pub const CompareOutputContext = struct {...@@ -324,13 +342,14 @@ pub const CompareOutputContext = struct {
324342
325 pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8) *RuntimeSafetyRunStep {343 pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8) *RuntimeSafetyRunStep {
326 const allocator = context.b.allocator;344 const allocator = context.b.allocator;
327 const ptr = allocator.create(RuntimeSafetyRunStep{345 const ptr = allocator.create(RuntimeSafetyRunStep) catch unreachable;
346 ptr.* = RuntimeSafetyRunStep{
328 .context = context,347 .context = context,
329 .exe_path = exe_path,348 .exe_path = exe_path,
330 .name = name,349 .name = name,
331 .test_index = context.test_index,350 .test_index = context.test_index,
332 .step = build.Step.init("RuntimeSafetyRun", allocator, make),351 .step = build.Step.init("RuntimeSafetyRun", allocator, make),
333 }) catch unreachable;352 };
334353
335 context.test_index += 1;354 context.test_index += 1;
336 return ptr;355 return ptr;
...@@ -420,7 +439,10 @@ pub const CompareOutputContext = struct {...@@ -420,7 +439,10 @@ pub const CompareOutputContext = struct {
420 pub fn addCase(self: *CompareOutputContext, case: TestCase) void {439 pub fn addCase(self: *CompareOutputContext, case: TestCase) void {
421 const b = self.b;440 const b = self.b;
422441
423 const root_src = os.path.join(b.allocator, b.cache_root, case.sources.items[0].filename) catch unreachable;442 const root_src = os.path.join(
443 b.allocator,
444 [][]const u8{ b.cache_root, case.sources.items[0].filename },
445 ) catch unreachable;
424446
425 switch (case.special) {447 switch (case.special) {
426 Special.Asm => {448 Special.Asm => {
...@@ -433,7 +455,10 @@ pub const CompareOutputContext = struct {...@@ -433,7 +455,10 @@ pub const CompareOutputContext = struct {
433 exe.addAssemblyFile(root_src);455 exe.addAssemblyFile(root_src);
434456
435 for (case.sources.toSliceConst()) |src_file| {457 for (case.sources.toSliceConst()) |src_file| {
436 const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable;458 const expanded_src_path = os.path.join(
459 b.allocator,
460 [][]const u8{ b.cache_root, src_file.filename },
461 ) catch unreachable;
437 const write_src = b.addWriteFile(expanded_src_path, src_file.source);462 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
438 exe.step.dependOn(&write_src.step);463 exe.step.dependOn(&write_src.step);
439 }464 }
...@@ -457,7 +482,10 @@ pub const CompareOutputContext = struct {...@@ -457,7 +482,10 @@ pub const CompareOutputContext = struct {
457 }482 }
458483
459 for (case.sources.toSliceConst()) |src_file| {484 for (case.sources.toSliceConst()) |src_file| {
460 const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable;485 const expanded_src_path = os.path.join(
486 b.allocator,
487 [][]const u8{ b.cache_root, src_file.filename },
488 ) catch unreachable;
461 const write_src = b.addWriteFile(expanded_src_path, src_file.source);489 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
462 exe.step.dependOn(&write_src.step);490 exe.step.dependOn(&write_src.step);
463 }491 }
...@@ -480,7 +508,10 @@ pub const CompareOutputContext = struct {...@@ -480,7 +508,10 @@ pub const CompareOutputContext = struct {
480 }508 }
481509
482 for (case.sources.toSliceConst()) |src_file| {510 for (case.sources.toSliceConst()) |src_file| {
483 const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable;511 const expanded_src_path = os.path.join(
512 b.allocator,
513 [][]const u8{ b.cache_root, src_file.filename },
514 ) catch unreachable;
484 const write_src = b.addWriteFile(expanded_src_path, src_file.source);515 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
485 exe.step.dependOn(&write_src.step);516 exe.step.dependOn(&write_src.step);
486 }517 }
...@@ -507,6 +538,7 @@ pub const CompileErrorContext = struct {...@@ -507,6 +538,7 @@ pub const CompileErrorContext = struct {
507 expected_errors: ArrayList([]const u8),538 expected_errors: ArrayList([]const u8),
508 link_libc: bool,539 link_libc: bool,
509 is_exe: bool,540 is_exe: bool,
541 is_test: bool,
510542
511 const SourceFile = struct {543 const SourceFile = struct {
512 filename: []const u8,544 filename: []const u8,
...@@ -535,14 +567,15 @@ pub const CompileErrorContext = struct {...@@ -535,14 +567,15 @@ pub const CompileErrorContext = struct {
535567
536 pub fn create(context: *CompileErrorContext, name: []const u8, case: *const TestCase, build_mode: Mode) *CompileCmpOutputStep {568 pub fn create(context: *CompileErrorContext, name: []const u8, case: *const TestCase, build_mode: Mode) *CompileCmpOutputStep {
537 const allocator = context.b.allocator;569 const allocator = context.b.allocator;
538 const ptr = allocator.create(CompileCmpOutputStep{570 const ptr = allocator.create(CompileCmpOutputStep) catch unreachable;
571 ptr.* = CompileCmpOutputStep{
539 .step = build.Step.init("CompileCmpOutput", allocator, make),572 .step = build.Step.init("CompileCmpOutput", allocator, make),
540 .context = context,573 .context = context,
541 .name = name,574 .name = name,
542 .test_index = context.test_index,575 .test_index = context.test_index,
543 .case = case,576 .case = case,
544 .build_mode = build_mode,577 .build_mode = build_mode,
545 }) catch unreachable;578 };
546579
547 context.test_index += 1;580 context.test_index += 1;
548 return ptr;581 return ptr;
...@@ -552,13 +585,25 @@ pub const CompileErrorContext = struct {...@@ -552,13 +585,25 @@ pub const CompileErrorContext = struct {
552 const self = @fieldParentPtr(CompileCmpOutputStep, "step", step);585 const self = @fieldParentPtr(CompileCmpOutputStep, "step", step);
553 const b = self.context.b;586 const b = self.context.b;
554587
555 const root_src = os.path.join(b.allocator, b.cache_root, self.case.sources.items[0].filename) catch unreachable;588 const root_src = os.path.join(
556 const obj_path = os.path.join(b.allocator, b.cache_root, "test.o") catch unreachable;589 b.allocator,
590 [][]const u8{ b.cache_root, self.case.sources.items[0].filename },
591 ) catch unreachable;
592 const obj_path = os.path.join(
593 b.allocator,
594 [][]const u8{ b.cache_root, "test.o" },
595 ) catch unreachable;
557596
558 var zig_args = ArrayList([]const u8).init(b.allocator);597 var zig_args = ArrayList([]const u8).init(b.allocator);
559 zig_args.append(b.zig_exe) catch unreachable;598 zig_args.append(b.zig_exe) catch unreachable;
560599
561 zig_args.append(if (self.case.is_exe) "build-exe" else "build-obj") catch unreachable;600 if (self.case.is_exe) {
601 try zig_args.append("build-exe");
602 } else if (self.case.is_test) {
603 try zig_args.append("test");
604 } else {
605 try zig_args.append("build-obj");
606 }
562 zig_args.append(b.pathFromRoot(root_src)) catch unreachable;607 zig_args.append(b.pathFromRoot(root_src)) catch unreachable;
563608
564 zig_args.append("--name") catch unreachable;609 zig_args.append("--name") catch unreachable;
...@@ -654,13 +699,15 @@ pub const CompileErrorContext = struct {...@@ -654,13 +699,15 @@ pub const CompileErrorContext = struct {
654 }699 }
655700
656 pub fn create(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) *TestCase {701 pub fn create(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) *TestCase {
657 const tc = self.b.allocator.create(TestCase{702 const tc = self.b.allocator.create(TestCase) catch unreachable;
703 tc.* = TestCase{
658 .name = name,704 .name = name,
659 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),705 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
660 .expected_errors = ArrayList([]const u8).init(self.b.allocator),706 .expected_errors = ArrayList([]const u8).init(self.b.allocator),
661 .link_libc = false,707 .link_libc = false,
662 .is_exe = false,708 .is_exe = false,
663 }) catch unreachable;709 .is_test = false,
710 };
664711
665 tc.addSourceFile(".tmp_source.zig", source);712 tc.addSourceFile(".tmp_source.zig", source);
666 comptime var arg_i = 0;713 comptime var arg_i = 0;
...@@ -687,6 +734,12 @@ pub const CompileErrorContext = struct {...@@ -687,6 +734,12 @@ pub const CompileErrorContext = struct {
687 self.addCase(tc);734 self.addCase(tc);
688 }735 }
689736
737 pub fn addTest(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) void {
738 const tc = self.create(name, source, expected_lines);
739 tc.is_test = true;
740 self.addCase(tc);
741 }
742
690 pub fn addCase(self: *CompileErrorContext, case: *const TestCase) void {743 pub fn addCase(self: *CompileErrorContext, case: *const TestCase) void {
691 const b = self.b;744 const b = self.b;
692745
...@@ -700,7 +753,10 @@ pub const CompileErrorContext = struct {...@@ -700,7 +753,10 @@ pub const CompileErrorContext = struct {
700 self.step.dependOn(&compile_and_cmp_errors.step);753 self.step.dependOn(&compile_and_cmp_errors.step);
701754
702 for (case.sources.toSliceConst()) |src_file| {755 for (case.sources.toSliceConst()) |src_file| {
703 const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable;756 const expanded_src_path = os.path.join(
757 b.allocator,
758 [][]const u8{ b.cache_root, src_file.filename },
759 ) catch unreachable;
704 const write_src = b.addWriteFile(expanded_src_path, src_file.source);760 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
705 compile_and_cmp_errors.step.dependOn(&write_src.step);761 compile_and_cmp_errors.step.dependOn(&write_src.step);
706 }762 }
...@@ -814,13 +870,14 @@ pub const TranslateCContext = struct {...@@ -814,13 +870,14 @@ pub const TranslateCContext = struct {
814870
815 pub fn create(context: *TranslateCContext, name: []const u8, case: *const TestCase) *TranslateCCmpOutputStep {871 pub fn create(context: *TranslateCContext, name: []const u8, case: *const TestCase) *TranslateCCmpOutputStep {
816 const allocator = context.b.allocator;872 const allocator = context.b.allocator;
817 const ptr = allocator.create(TranslateCCmpOutputStep{873 const ptr = allocator.create(TranslateCCmpOutputStep) catch unreachable;
874 ptr.* = TranslateCCmpOutputStep{
818 .step = build.Step.init("ParseCCmpOutput", allocator, make),875 .step = build.Step.init("ParseCCmpOutput", allocator, make),
819 .context = context,876 .context = context,
820 .name = name,877 .name = name,
821 .test_index = context.test_index,878 .test_index = context.test_index,
822 .case = case,879 .case = case,
823 }) catch unreachable;880 };
824881
825 context.test_index += 1;882 context.test_index += 1;
826 return ptr;883 return ptr;
...@@ -830,7 +887,10 @@ pub const TranslateCContext = struct {...@@ -830,7 +887,10 @@ pub const TranslateCContext = struct {
830 const self = @fieldParentPtr(TranslateCCmpOutputStep, "step", step);887 const self = @fieldParentPtr(TranslateCCmpOutputStep, "step", step);
831 const b = self.context.b;888 const b = self.context.b;
832889
833 const root_src = os.path.join(b.allocator, b.cache_root, self.case.sources.items[0].filename) catch unreachable;890 const root_src = os.path.join(
891 b.allocator,
892 [][]const u8{ b.cache_root, self.case.sources.items[0].filename },
893 ) catch unreachable;
834894
835 var zig_args = ArrayList([]const u8).init(b.allocator);895 var zig_args = ArrayList([]const u8).init(b.allocator);
836 zig_args.append(b.zig_exe) catch unreachable;896 zig_args.append(b.zig_exe) catch unreachable;
...@@ -921,12 +981,13 @@ pub const TranslateCContext = struct {...@@ -921,12 +981,13 @@ pub const TranslateCContext = struct {
921 }981 }
922982
923 pub fn create(self: *TranslateCContext, allow_warnings: bool, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) *TestCase {983 pub fn create(self: *TranslateCContext, allow_warnings: bool, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) *TestCase {
924 const tc = self.b.allocator.create(TestCase{984 const tc = self.b.allocator.create(TestCase) catch unreachable;
985 tc.* = TestCase{
925 .name = name,986 .name = name,
926 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),987 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
927 .expected_lines = ArrayList([]const u8).init(self.b.allocator),988 .expected_lines = ArrayList([]const u8).init(self.b.allocator),
928 .allow_warnings = allow_warnings,989 .allow_warnings = allow_warnings,
929 }) catch unreachable;990 };
930991
931 tc.addSourceFile(filename, source);992 tc.addSourceFile(filename, source);
932 comptime var arg_i = 0;993 comptime var arg_i = 0;
...@@ -963,7 +1024,10 @@ pub const TranslateCContext = struct {...@@ -963,7 +1024,10 @@ pub const TranslateCContext = struct {
963 self.step.dependOn(&translate_c_and_cmp.step);1024 self.step.dependOn(&translate_c_and_cmp.step);
9641025
965 for (case.sources.toSliceConst()) |src_file| {1026 for (case.sources.toSliceConst()) |src_file| {
966 const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable;1027 const expanded_src_path = os.path.join(
1028 b.allocator,
1029 [][]const u8{ b.cache_root, src_file.filename },
1030 ) catch unreachable;
967 const write_src = b.addWriteFile(expanded_src_path, src_file.source);1031 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
968 translate_c_and_cmp.step.dependOn(&write_src.step);1032 translate_c_and_cmp.step.dependOn(&write_src.step);
969 }1033 }
...@@ -1008,14 +1072,15 @@ pub const GenHContext = struct {...@@ -1008,14 +1072,15 @@ pub const GenHContext = struct {
10081072
1009 pub fn create(context: *GenHContext, h_path: []const u8, name: []const u8, case: *const TestCase) *GenHCmpOutputStep {1073 pub fn create(context: *GenHContext, h_path: []const u8, name: []const u8, case: *const TestCase) *GenHCmpOutputStep {
1010 const allocator = context.b.allocator;1074 const allocator = context.b.allocator;
1011 const ptr = allocator.create(GenHCmpOutputStep{1075 const ptr = allocator.create(GenHCmpOutputStep) catch unreachable;
1076 ptr.* = GenHCmpOutputStep{
1012 .step = build.Step.init("ParseCCmpOutput", allocator, make),1077 .step = build.Step.init("ParseCCmpOutput", allocator, make),
1013 .context = context,1078 .context = context,
1014 .h_path = h_path,1079 .h_path = h_path,
1015 .name = name,1080 .name = name,
1016 .test_index = context.test_index,1081 .test_index = context.test_index,
1017 .case = case,1082 .case = case,
1018 }) catch unreachable;1083 };
10191084
1020 context.test_index += 1;1085 context.test_index += 1;
1021 return ptr;1086 return ptr;
...@@ -1055,11 +1120,12 @@ pub const GenHContext = struct {...@@ -1055,11 +1120,12 @@ pub const GenHContext = struct {
1055 }1120 }
10561121
1057 pub fn create(self: *GenHContext, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) *TestCase {1122 pub fn create(self: *GenHContext, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) *TestCase {
1058 const tc = self.b.allocator.create(TestCase{1123 const tc = self.b.allocator.create(TestCase) catch unreachable;
1124 tc.* = TestCase{
1059 .name = name,1125 .name = name,
1060 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),1126 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
1061 .expected_lines = ArrayList([]const u8).init(self.b.allocator),1127 .expected_lines = ArrayList([]const u8).init(self.b.allocator),
1062 }) catch unreachable;1128 };
10631129
1064 tc.addSourceFile(filename, source);1130 tc.addSourceFile(filename, source);
1065 comptime var arg_i = 0;1131 comptime var arg_i = 0;
...@@ -1076,7 +1142,10 @@ pub const GenHContext = struct {...@@ -1076,7 +1142,10 @@ pub const GenHContext = struct {
10761142
1077 pub fn addCase(self: *GenHContext, case: *const TestCase) void {1143 pub fn addCase(self: *GenHContext, case: *const TestCase) void {
1078 const b = self.b;1144 const b = self.b;
1079 const root_src = os.path.join(b.allocator, b.cache_root, case.sources.items[0].filename) catch unreachable;1145 const root_src = os.path.join(
1146 b.allocator,
1147 [][]const u8{ b.cache_root, case.sources.items[0].filename },
1148 ) catch unreachable;
10801149
1081 const mode = builtin.Mode.Debug;1150 const mode = builtin.Mode.Debug;
1082 const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", case.name, @tagName(mode)) catch unreachable;1151 const annotated_case_name = fmt.allocPrint(self.b.allocator, "gen-h {} ({})", case.name, @tagName(mode)) catch unreachable;
...@@ -1088,7 +1157,10 @@ pub const GenHContext = struct {...@@ -1088,7 +1157,10 @@ pub const GenHContext = struct {
1088 obj.setBuildMode(mode);1157 obj.setBuildMode(mode);
10891158
1090 for (case.sources.toSliceConst()) |src_file| {1159 for (case.sources.toSliceConst()) |src_file| {
1091 const expanded_src_path = os.path.join(b.allocator, b.cache_root, src_file.filename) catch unreachable;1160 const expanded_src_path = os.path.join(
1161 b.allocator,
1162 [][]const u8{ b.cache_root, src_file.filename },
1163 ) catch unreachable;
1092 const write_src = b.addWriteFile(expanded_src_path, src_file.source);1164 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
1093 obj.step.dependOn(&write_src.step);1165 obj.step.dependOn(&write_src.step);
1094 }1166 }
test/translate_c.zig+61-31
...@@ -117,11 +117,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -117,11 +117,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
117 \\};117 \\};
118 ,118 ,
119 \\pub const struct_Foo = extern struct {119 \\pub const struct_Foo = extern struct {
120 \\ a: ?[*]Foo,120 \\ a: [*c]Foo,
121 \\};121 \\};
122 \\pub const Foo = struct_Foo;122 \\pub const Foo = struct_Foo;
123 \\pub const struct_Bar = extern struct {123 \\pub const struct_Bar = extern struct {
124 \\ a: ?[*]Foo,124 \\ a: [*c]Foo,
125 \\};125 \\};
126 );126 );
127127
...@@ -213,7 +213,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -213,7 +213,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
213 ,213 ,
214 \\const struct_Foo = extern struct {214 \\const struct_Foo = extern struct {
215 \\ x: c_int,215 \\ x: c_int,
216 \\ y: ?[*]u8,216 \\ y: [*c]u8,
217 \\};217 \\};
218 ,218 ,
219 \\pub const Foo = struct_Foo;219 \\pub const Foo = struct_Foo;
...@@ -244,7 +244,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -244,7 +244,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
244 ,244 ,
245 \\pub const BarB = enum_Bar.B;245 \\pub const BarB = enum_Bar.B;
246 ,246 ,
247 \\pub extern fn func(a: ?[*]struct_Foo, b: ?[*](?[*]enum_Bar)) void;247 \\pub extern fn func(a: [*c]struct_Foo, b: [*c]([*c]enum_Bar)) void;
248 ,248 ,
249 \\pub const Foo = struct_Foo;249 \\pub const Foo = struct_Foo;
250 ,250 ,
...@@ -254,7 +254,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -254,7 +254,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
254 cases.add("constant size array",254 cases.add("constant size array",
255 \\void func(int array[20]);255 \\void func(int array[20]);
256 ,256 ,
257 \\pub extern fn func(array: ?[*]c_int) void;257 \\pub extern fn func(array: [*c]c_int) void;
258 );258 );
259259
260 cases.add("self referential struct with function pointer",260 cases.add("self referential struct with function pointer",
...@@ -263,7 +263,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -263,7 +263,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
263 \\};263 \\};
264 ,264 ,
265 \\pub const struct_Foo = extern struct {265 \\pub const struct_Foo = extern struct {
266 \\ derp: ?extern fn(?[*]struct_Foo) void,266 \\ derp: ?extern fn([*c]struct_Foo) void,
267 \\};267 \\};
268 ,268 ,
269 \\pub const Foo = struct_Foo;269 \\pub const Foo = struct_Foo;
...@@ -322,11 +322,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -322,11 +322,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
322 \\};322 \\};
323 ,323 ,
324 \\pub const struct_Bar = extern struct {324 \\pub const struct_Bar = extern struct {
325 \\ next: ?[*]struct_Foo,325 \\ next: [*c]struct_Foo,
326 \\};326 \\};
327 ,327 ,
328 \\pub const struct_Foo = extern struct {328 \\pub const struct_Foo = extern struct {
329 \\ next: ?[*]struct_Bar,329 \\ next: [*c]struct_Bar,
330 \\};330 \\};
331 );331 );
332332
...@@ -610,11 +610,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -610,11 +610,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
610 ,610 ,
611 \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {611 \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
612 \\ if ((a != 0) and (b != 0)) return 0;612 \\ if ((a != 0) and (b != 0)) return 0;
613 \\ if ((b != 0) and (c != null)) return 1;613 \\ if ((b != 0) and (c != 0)) return 1;
614 \\ if ((a != 0) and (c != null)) return 2;614 \\ if ((a != 0) and (c != 0)) return 2;
615 \\ if ((a != 0) or (b != 0)) return 3;615 \\ if ((a != 0) or (b != 0)) return 3;
616 \\ if ((b != 0) or (c != null)) return 4;616 \\ if ((b != 0) or (c != 0)) return 4;
617 \\ if ((a != 0) or (c != null)) return 5;617 \\ if ((a != 0) or (c != 0)) return 5;
618 \\ return 6;618 \\ return 6;
619 \\}619 \\}
620 );620 );
...@@ -710,7 +710,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -710,7 +710,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
710 \\pub const struct_Foo = extern struct {710 \\pub const struct_Foo = extern struct {
711 \\ field: c_int,711 \\ field: c_int,
712 \\};712 \\};
713 \\pub export fn read_field(foo: ?[*]struct_Foo) c_int {713 \\pub export fn read_field(foo: [*c]struct_Foo) c_int {
714 \\ return foo.?.field;714 \\ return foo.?.field;
715 \\}715 \\}
716 );716 );
...@@ -756,7 +756,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -756,7 +756,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
756 \\ return x;756 \\ return x;
757 \\}757 \\}
758 ,758 ,
759 \\pub export fn foo(x: ?[*]c_ushort) ?*c_void {759 \\pub export fn foo(x: [*c]c_ushort) ?*c_void {
760 \\ return @ptrCast(?*c_void, x);760 \\ return @ptrCast(?*c_void, x);
761 \\}761 \\}
762 );762 );
...@@ -777,8 +777,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -777,8 +777,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
777 \\ return 0;777 \\ return 0;
778 \\}778 \\}
779 ,779 ,
780 \\pub export fn foo() ?[*]c_int {780 \\pub export fn foo() [*c]c_int {
781 \\ return null;781 \\ return 0;
782 \\}782 \\}
783 );783 );
784784
...@@ -1086,7 +1086,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1086,7 +1086,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1086 \\ *x = 1;1086 \\ *x = 1;
1087 \\}1087 \\}
1088 ,1088 ,
1089 \\pub export fn foo(x: ?[*]c_int) void {1089 \\pub export fn foo(x: [*c]c_int) void {
1090 \\ x.?.* = 1;1090 \\ x.?.* = 1;
1091 \\}1091 \\}
1092 );1092 );
...@@ -1114,7 +1114,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1114,7 +1114,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1114 ,1114 ,
1115 \\pub fn foo() c_int {1115 \\pub fn foo() c_int {
1116 \\ var x: c_int = 1234;1116 \\ var x: c_int = 1234;
1117 \\ var ptr: ?[*]c_int = &x;1117 \\ var ptr: [*c]c_int = &x;
1118 \\ return ptr.?.*;1118 \\ return ptr.?.*;
1119 \\}1119 \\}
1120 );1120 );
...@@ -1124,7 +1124,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1124,7 +1124,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1124 \\ return "bar";1124 \\ return "bar";
1125 \\}1125 \\}
1126 ,1126 ,
1127 \\pub fn foo() ?[*]const u8 {1127 \\pub fn foo() [*c]const u8 {
1128 \\ return c"bar";1128 \\ return c"bar";
1129 \\}1129 \\}
1130 );1130 );
...@@ -1253,8 +1253,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1253,8 +1253,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1253 \\ return (float *)a;1253 \\ return (float *)a;
1254 \\}1254 \\}
1255 ,1255 ,
1256 \\fn ptrcast(a: ?[*]c_int) ?[*]f32 {1256 \\fn ptrcast(a: [*c]c_int) [*c]f32 {
1257 \\ return @ptrCast(?[*]f32, a);1257 \\ return @ptrCast([*c]f32, a);
1258 \\}1258 \\}
1259 );1259 );
12601260
...@@ -1280,7 +1280,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1280,7 +1280,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1280 \\ return !(a == 0);1280 \\ return !(a == 0);
1281 \\ return !(a != 0);1281 \\ return !(a != 0);
1282 \\ return !(b != 0);1282 \\ return !(b != 0);
1283 \\ return !(c != null);1283 \\ return !(c != 0);
1284 \\}1284 \\}
1285 );1285 );
12861286
...@@ -1297,7 +1297,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1297,7 +1297,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1297 cases.add("const ptr initializer",1297 cases.add("const ptr initializer",
1298 \\static const char *v0 = "0.0.0";1298 \\static const char *v0 = "0.0.0";
1299 ,1299 ,
1300 \\pub var v0: ?[*]const u8 = c"0.0.0";1300 \\pub var v0: [*c]const u8 = c"0.0.0";
1301 );1301 );
13021302
1303 cases.add("static incomplete array inside function",1303 cases.add("static incomplete array inside function",
...@@ -1306,17 +1306,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1306,17 +1306,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1306 \\}1306 \\}
1307 ,1307 ,
1308 \\pub fn foo() void {1308 \\pub fn foo() void {
1309 \\ const v2: [*]const u8 = c"2.2.2";1309 \\ const v2: [*c]const u8 = c"2.2.2";
1310 \\}1310 \\}
1311 );1311 );
13121312
1313 cases.add("macro pointer cast",1313 cases.add("macro pointer cast",
1314 \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)1314 \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
1315 ,1315 ,
1316 \\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast([*]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr([*]NRF_GPIO_Type, NRF_GPIO_BASE) else ([*]NRF_GPIO_Type)(NRF_GPIO_BASE);1316 \\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);
1317 );1317 );
13181318
1319 cases.add("if on none bool",1319 cases.add("if on non-bool",
1320 \\enum SomeEnum { A, B, C };1320 \\enum SomeEnum { A, B, C };
1321 \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) {1321 \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) {
1322 \\ if (a) return 0;1322 \\ if (a) return 0;
...@@ -1337,13 +1337,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1337,13 +1337,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1337 \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {1337 \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {
1338 \\ if (a != 0) return 0;1338 \\ if (a != 0) return 0;
1339 \\ if (b != 0) return 1;1339 \\ if (b != 0) return 1;
1340 \\ if (c != null) return 2;1340 \\ if (c != 0) return 2;
1341 \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3;1341 \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3;
1342 \\ return 4;1342 \\ return 4;
1343 \\}1343 \\}
1344 );1344 );
13451345
1346 cases.add("while on none bool",1346 cases.add("while on non-bool",
1347 \\int while_none_bool(int a, float b, void *c) {1347 \\int while_none_bool(int a, float b, void *c) {
1348 \\ while (a) return 0;1348 \\ while (a) return 0;
1349 \\ while (b) return 1;1349 \\ while (b) return 1;
...@@ -1354,12 +1354,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1354,12 +1354,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1354 \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {1354 \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
1355 \\ while (a != 0) return 0;1355 \\ while (a != 0) return 0;
1356 \\ while (b != 0) return 1;1356 \\ while (b != 0) return 1;
1357 \\ while (c != null) return 2;1357 \\ while (c != 0) return 2;
1358 \\ return 3;1358 \\ return 3;
1359 \\}1359 \\}
1360 );1360 );
13611361
1362 cases.add("for on none bool",1362 cases.add("for on non-bool",
1363 \\int for_none_bool(int a, float b, void *c) {1363 \\int for_none_bool(int a, float b, void *c) {
1364 \\ for (;a;) return 0;1364 \\ for (;a;) return 0;
1365 \\ for (;b;) return 1;1365 \\ for (;b;) return 1;
...@@ -1370,7 +1370,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1370,7 +1370,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1370 \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {1370 \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
1371 \\ while (a != 0) return 0;1371 \\ while (a != 0) return 0;
1372 \\ while (b != 0) return 1;1372 \\ while (b != 0) return 1;
1373 \\ while (c != null) return 2;1373 \\ while (c != 0) return 2;
1374 \\ return 3;1374 \\ return 3;
1375 \\}1375 \\}
1376 );1376 );
...@@ -1416,4 +1416,34 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1416,4 +1416,34 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1416 \\ }1416 \\ }
1417 \\}1417 \\}
1418 );1418 );
1419
1420 // cases.add("empty array with initializer",
1421 // "int a[4] = {};"
1422 // ,
1423 // "pub var a: [4]c_int = [1]c_int{0} ** 4;"
1424 // );
1425
1426 // cases.add("array with initialization",
1427 // "int a[4] = {1, 2, 3, 4};"
1428 // ,
1429 // "pub var a: [4]c_int = [4]c_int{1, 2, 3, 4};"
1430 // );
1431
1432 // cases.add("array with incomplete initialization",
1433 // "int a[4] = {3, 4};"
1434 // ,
1435 // "pub var a: [4]c_int = [2]c_int{3, 4} ++ ([1]c_int{0} ** 2);"
1436 // );
1437
1438 // cases.add("2D array with initialization",
1439 // "int a[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };"
1440 // ,
1441 // "pub var a: [3][3]c_int = [3][3]c_int{[3]c_int{1, 2, 3}, [3]c_int{4, 5, 6}, [3]c_int{7, 8, 9}};"
1442 // );
1443
1444 // cases.add("2D array with incomplete initialization",
1445 // "int a[3][3] = { {1, 2}, {4, 5, 6} };"
1446 // ,
1447 // "pub var a: [3][3]c_int = [2][3]c_int{[2]c_int{1, 2} ++ [1]c_int{0}, [3]c_int{4, 5, 6}} ++ [1][3]c_int{[1]c_int{0} ** 3};"
1448 // );
1419}1449}