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
429429)
430430set(ZIG_CPP_SOURCES
431431 "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"
432 "${CMAKE_SOURCE_DIR}/src/zig_clang.cpp"
432433 "${CMAKE_SOURCE_DIR}/src/windows_sdk.cpp"
433434)
434435
......@@ -454,10 +455,10 @@ set(ZIG_STD_FILES
454455 "crypto/hmac.zig"
455456 "crypto/index.zig"
456457 "crypto/md5.zig"
458 "crypto/poly1305.zig"
457459 "crypto/sha1.zig"
458460 "crypto/sha2.zig"
459461 "crypto/sha3.zig"
460 "crypto/poly1305.zig"
461462 "crypto/x25519.zig"
462463 "cstr.zig"
463464 "debug/failing_allocator.zig"
......@@ -482,6 +483,7 @@ set(ZIG_STD_FILES
482483 "fmt/errol/index.zig"
483484 "fmt/errol/lookup.zig"
484485 "fmt/index.zig"
486 "fmt/parse_float.zig"
485487 "hash/adler.zig"
486488 "hash/crc.zig"
487489 "hash/fnv.zig"
......@@ -566,9 +568,9 @@ set(ZIG_STD_FILES
566568 "math/tan.zig"
567569 "math/tanh.zig"
568570 "math/trunc.zig"
571 "mem.zig"
569572 "meta/index.zig"
570573 "meta/trait.zig"
571 "mem.zig"
572574 "mutex.zig"
573575 "net.zig"
574576 "os/child_process.zig"
......@@ -576,20 +578,19 @@ set(ZIG_STD_FILES
576578 "os/darwin/errno.zig"
577579 "os/epoch.zig"
578580 "os/file.zig"
581 "os/freebsd/errno.zig"
582 "os/freebsd/index.zig"
579583 "os/get_app_data_dir.zig"
580584 "os/get_user_id.zig"
581585 "os/index.zig"
586 "os/linux/arm64.zig"
582587 "os/linux/errno.zig"
583588 "os/linux/index.zig"
584589 "os/linux/vdso.zig"
585590 "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"
591591 "os/path.zig"
592592 "os/time.zig"
593 "os/uefi.zig"
593594 "os/windows/advapi32.zig"
594595 "os/windows/error.zig"
595596 "os/windows/index.zig"
......@@ -597,6 +598,7 @@ set(ZIG_STD_FILES
597598 "os/windows/ntdll.zig"
598599 "os/windows/ole32.zig"
599600 "os/windows/shell32.zig"
601 "os/windows/tls.zig"
600602 "os/windows/util.zig"
601603 "os/zen.zig"
602604 "pdb.zig"
......@@ -608,11 +610,22 @@ set(ZIG_STD_FILES
608610 "special/bootstrap_lib.zig"
609611 "special/build_runner.zig"
610612 "special/builtin.zig"
613 "special/compiler_rt/addXf3.zig"
611614 "special/compiler_rt/aulldiv.zig"
612615 "special/compiler_rt/aullrem.zig"
613616 "special/compiler_rt/comparetf2.zig"
614617 "special/compiler_rt/divti3.zig"
615618 "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"
616629 "special/compiler_rt/fixuint.zig"
617630 "special/compiler_rt/fixunsdfdi.zig"
618631 "special/compiler_rt/fixunsdfsi.zig"
......@@ -640,6 +653,7 @@ set(ZIG_STD_FILES
640653 "special/compiler_rt/udivmodti4.zig"
641654 "special/compiler_rt/udivti3.zig"
642655 "special/compiler_rt/umodti3.zig"
656 "special/fmt_runner.zig"
643657 "special/init-exe/build.zig"
644658 "special/init-exe/src/main.zig"
645659 "special/init-lib/build.zig"
......@@ -647,6 +661,8 @@ set(ZIG_STD_FILES
647661 "special/panic.zig"
648662 "special/test_runner.zig"
649663 "spinlock.zig"
664 "statically_initialized_mutex.zig"
665 "testing.zig"
650666 "unicode.zig"
651667 "zig/ast.zig"
652668 "zig/index.zig"
......@@ -891,3 +907,7 @@ foreach(file ${ZIG_STD_FILES})
891907 get_filename_component(file_dir "${ZIG_STD_DEST}/${file}" DIRECTORY)
892908 install(FILES "${CMAKE_SOURCE_DIR}/std/${file}" DESTINATION "${file_dir}")
893909endforeach()
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 @@
33A programming language designed for robustness, optimality, and
44clarity.
55
6[ziglang.org](https://ziglang.org)
6[Download & Documentation](https://ziglang.org/download/)
77
88## Feature Highlights
99
......@@ -84,29 +84,32 @@ clarity.
8484 * LLVM may have the target as an experimental target, which means that you
8585 need to use Zig-provided binaries for the target to be available, or
8686 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
8891#### Support Table
8992
90| | freestanding | linux | macosx | windows | freebsd | other |
91|--------|--------------|--------|--------|---------|---------|--------|
92|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 3 |
93|i386 | Tier 2 | Tier 2 | Tier 2 | Tier 2 | Tier 3 | Tier 3 |
94|arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
95|arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
96|bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
97|hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
98|mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
99|powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
100|r600 | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
101|amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
102|sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
103|s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
104|spir | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
105|lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
106|wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A |
107|wasm64 | Tier 4 | N/A | N/A | N/A | N/A | N/A |
108|riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 |
109|riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 |
93| | freestanding | linux | macosx | windows | freebsd | UEFI | other |
94|--------|--------------|--------|--------|---------|---------|--------|--------|
95|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 2 | Tier 3 |
96|i386 | Tier 2 | Tier 2 | Tier 4 | Tier 2 | Tier 3 | Tier 3 | Tier 3 |
97|arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
98|arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
99|bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
100|hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
101|mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
102|powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
103|r600 | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
104|amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
105|sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
106|s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
107|spir | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
108|lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
109|wasm32 | Tier 4 | N/A | 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 |
111|riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 |
112|riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 |
110113
111114## Community
112115
......@@ -171,7 +174,8 @@ See https://github.com/ziglang/zig/wiki/Building-Zig-on-Windows
171174*Note: Stage 2 compiler is not complete. Beta users of Zig should use the
172175Stage 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
176180```
177181bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install
......@@ -183,11 +187,13 @@ binary.
183187
184188### 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
188190*Note: Stage 2 compiler is not yet able to build Stage 3. Building Stage 3 is
189191not 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
191197#### Debug / Development Build
192198
193199```
build.zig+40-19
......@@ -16,7 +16,10 @@ pub fn build(b: *Builder) !void {
1616 var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
1717
1818 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;
2023 var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{
2124 docgen_exe.getOutputPath(),
2225 rel_zig_exe,
......@@ -104,7 +107,7 @@ pub fn build(b: *Builder) !void {
104107 }
105108 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
109112 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 {
125128 for (dep.libdirs.toSliceConst()) |lib_dir| {
126129 lib_exe_obj.addLibPath(lib_dir);
127130 }
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;
129135 for (dep.system_libs.toSliceConst()) |lib| {
130136 const static_bare_name = if (mem.eql(u8, lib, "curses"))
131137 ([]const u8)("libncurses.a")
132138 else
133139 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;
135144 const have_static = fileExists(static_lib_name) catch unreachable;
136145 if (have_static) {
137146 lib_exe_obj.addObjectFile(static_lib_name);
......@@ -159,7 +168,11 @@ fn fileExists(filename: []const u8) !bool {
159168
160169fn addCppLib(b: *Builder, lib_exe_obj: var, cmake_binary_dir: []const u8, lib_name: []const u8) void {
161170 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);
163176}
164177
165178const LibraryDep = struct {
......@@ -189,14 +202,14 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
189202 const prefix_output = try b.exec([][]const u8{ llvm_config_exe, "--prefix" });
190203
191204 var result = LibraryDep{
192 .prefix = mem.split(prefix_output, " \r\n").next().?,
205 .prefix = mem.tokenize(prefix_output, " \r\n").next().?,
193206 .libs = ArrayList([]const u8).init(b.allocator),
194207 .system_libs = ArrayList([]const u8).init(b.allocator),
195208 .includes = ArrayList([]const u8).init(b.allocator),
196209 .libdirs = ArrayList([]const u8).init(b.allocator),
197210 };
198211 {
199 var it = mem.split(libs_output, " \r\n");
212 var it = mem.tokenize(libs_output, " \r\n");
200213 while (it.next()) |lib_arg| {
201214 if (mem.startsWith(u8, lib_arg, "-l")) {
202215 try result.system_libs.append(lib_arg[2..]);
......@@ -210,7 +223,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
210223 }
211224 }
212225 {
213 var it = mem.split(includes_output, " \r\n");
226 var it = mem.tokenize(includes_output, " \r\n");
214227 while (it.next()) |include_arg| {
215228 if (mem.startsWith(u8, include_arg, "-I")) {
216229 try result.includes.append(include_arg[2..]);
......@@ -220,7 +233,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
220233 }
221234 }
222235 {
223 var it = mem.split(libdir_output, " \r\n");
236 var it = mem.tokenize(libdir_output, " \r\n");
224237 while (it.next()) |libdir| {
225238 if (mem.startsWith(u8, libdir, "-L")) {
226239 try result.libdirs.append(libdir[2..]);
......@@ -233,19 +246,25 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
233246}
234247
235248pub fn installStdLib(b: *Builder, stdlib_files: []const u8) void {
236 var it = mem.split(stdlib_files, ";");
249 var it = mem.tokenize(stdlib_files, ";");
237250 while (it.next()) |stdlib_file| {
238 const src_path = os.path.join(b.allocator, "std", stdlib_file) catch unreachable;
239 const dest_path = os.path.join(b.allocator, "lib", "zig", "std", stdlib_file) catch unreachable;
251 const src_path = os.path.join(b.allocator, [][]const u8{ "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;
240256 b.installFile(src_path, dest_path);
241257 }
242258}
243259
244260pub 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, ";");
246262 while (it.next()) |c_header_file| {
247 const src_path = os.path.join(b.allocator, "c_headers", c_header_file) catch unreachable;
248 const dest_path = os.path.join(b.allocator, "lib", "zig", "include", c_header_file) catch unreachable;
263 const src_path = os.path.join(b.allocator, [][]const u8{ "c_headers", 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;
249268 b.installFile(src_path, dest_path);
250269 }
251270}
......@@ -277,7 +296,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
277296 addCppLib(b, exe, ctx.cmake_binary_dir, "zig_cpp");
278297 if (ctx.lld_include_dir.len != 0) {
279298 exe.addIncludeDir(ctx.lld_include_dir);
280 var it = mem.split(ctx.lld_libraries, ";");
299 var it = mem.tokenize(ctx.lld_libraries, ";");
281300 while (it.next()) |lib| {
282301 exe.addObjectFile(lib);
283302 }
......@@ -293,11 +312,13 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
293312 try addCxxKnownPath(b, ctx, exe, "libstdc++.a",
294313 \\Unable to determine path to libstdc++.a
295314 \\On Fedora, install libstdc++-static and try again.
296 \\
297315 );
298316
299317 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()) {
301322 if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) {
302323 // Compiler is GCC.
303324 try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null);
......@@ -332,7 +353,7 @@ fn addCxxKnownPath(
332353 ctx.cxx_compiler,
333354 b.fmt("-print-file-name={}", objname),
334355 });
335 const path_unpadded = mem.split(path_padded, "\r\n").next().?;
356 const path_unpadded = mem.tokenize(path_padded, "\r\n").next().?;
336357 if (mem.eql(u8, path_unpadded, objname)) {
337358 if (errtxt) |msg| {
338359 warn("{}", msg);
ci/azure/windows_install+1
......@@ -3,6 +3,7 @@
33set -x
44set -e
55
6pacman -Su --needed --noconfirm
67pacman -S --needed --noconfirm wget p7zip python3-pip
78pip install s3cmd
89wget -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
1515 "c:/msys64/mingw64/bin"
1616 "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
1863if(NOT(CMAKE_BUILD_TYPE STREQUAL "Debug") OR ZIG_STATIC)
1964 execute_process(
2065 COMMAND ${LLVM_CONFIG_EXE} --libfiles --link-static
doc/docgen.zig+24-7
......@@ -4,7 +4,7 @@ const io = std.io;
44const os = std.os;
55const warn = std.debug.warn;
66const mem = std.mem;
7const assert = std.debug.assert;
7const testing = std.testing;
88
99const max_doc_file_size = 10 * 1024 * 1024;
1010
......@@ -620,7 +620,7 @@ const TermState = enum {
620620test "term color" {
621621 const input_bytes = "A\x1b[32;1mgreen\x1b[0mB";
622622 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);
624624}
625625
626626fn termColor(allocator: *mem.Allocator, input: []const u8) ![]u8 {
......@@ -770,6 +770,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
770770 std.zig.Token.Id.Keyword_suspend,
771771 std.zig.Token.Id.Keyword_switch,
772772 std.zig.Token.Id.Keyword_test,
773 std.zig.Token.Id.Keyword_threadlocal,
773774 std.zig.Token.Id.Keyword_try,
774775 std.zig.Token.Id.Keyword_union,
775776 std.zig.Token.Id.Keyword_unreachable,
......@@ -915,6 +916,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
915916 std.zig.Token.Id.AngleBracketAngleBracketRightEqual,
916917 std.zig.Token.Id.Tilde,
917918 std.zig.Token.Id.BracketStarBracket,
919 std.zig.Token.Id.BracketStarCBracket,
918920 => try writeEscaped(out, src[token.start..token.end]),
919921
920922 std.zig.Token.Id.Invalid => return parseError(
......@@ -990,13 +992,19 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
990992 try tokenizeAndPrint(tokenizer, out, code.source_token);
991993 try out.write("</pre>");
992994 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 );
994999 try io.writeFile(tmp_source_file_name, trimmed_raw_source);
9951000
9961001 switch (code.id) {
9971002 Code.Id.Exe => |expected_outcome| {
9981003 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 );
10001008 var build_args = std.ArrayList([]const u8).init(allocator);
10011009 defer build_args.deinit();
10021010 try build_args.appendSlice([][]const u8{
......@@ -1024,7 +1032,10 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
10241032 }
10251033 for (code.link_objects) |link_object| {
10261034 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 );
10281039 try build_args.append("--object");
10291040 try build_args.append(full_path_object);
10301041 try out.print(" --object {}", name_with_ext);
......@@ -1216,12 +1227,18 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
12161227 },
12171228 Code.Id.Obj => |maybe_error_match| {
12181229 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 );
12201234 var build_args = std.ArrayList([]const u8).init(allocator);
12211235 defer build_args.deinit();
12221236
12231237 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
12261243 try build_args.appendSlice([][]const u8{
12271244 zig_exe,
doc/langref.html.in+280-85
......@@ -165,7 +165,7 @@ const std = @import("std");
165165
166166pub fn main() !void {
167167 // 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();
169169 // If this program encounters pipe failure when printing to stdout, exit
170170 // with an error.
171171 try stdout_file.write("Hello, world!\n");
......@@ -1531,6 +1531,29 @@ test "array initialization with function calls" {
15311531 {#code_end#}
15321532 {#see_also|for|Slices#}
15331533 {#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
15341557 {#header_open|Pointers#}
15351558 <p>
15361559 Zig has two kinds of pointers:
......@@ -1671,7 +1694,7 @@ test "comptime @intToPtr" {
16711694 }
16721695}
16731696 {#code_end#}
1674 {#see_also|Optional Pointers#}
1697 {#see_also|Optional Pointers|@intToPtr|@ptrToInt#}
16751698 {#header_open|volatile#}
16761699 <p>Loads and stores are assumed to not have side effects. If a given load or store
16771700 should have side effects, such as Memory Mapped Input/Output (MMIO), use {#syntax#}volatile{#endsyntax#}.
......@@ -1800,7 +1823,9 @@ fn foo(bytes: []u8) u32 {
18001823}
18011824 {#code_end#}
18021825 {#header_close#}
1826 {#see_also|C Pointers#}
18031827 {#header_close#}
1828
18041829 {#header_open|Slices#}
18051830 {#code_begin|test_safety|index out of bounds#}
18061831const assert = @import("std").debug.assert;
......@@ -3169,7 +3194,16 @@ fn foo() void { }
31693194 {#code_end#}
31703195 {#header_open|Pass-by-value Parameters#}
31713196 <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.
31733207 </p>
31743208 {#code_begin|test#}
31753209const Point = struct {
......@@ -3178,20 +3212,20 @@ const Point = struct {
31783212};
31793213
31803214fn 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.
31813219 return point.x + point.y;
31823220}
31833221
31843222const assert = @import("std").debug.assert;
31853223
3186test "pass aggregate type by non-copy value to function" {
3224test "pass struct to function" {
31873225 assert(foo(Point{ .x = 1, .y = 2 }) == 3);
31883226}
31893227 {#code_end#}
31903228 <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>
31953229 For extern functions, Zig follows the C ABI for passing structs and unions by value.
31963230 </p>
31973231 {#header_close#}
......@@ -3949,7 +3983,7 @@ test "implicit cast - invoke a type as a function" {
39493983 {#code_end#}
39503984 <p>
39513985 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#}.
39533987 </p>
39543988 {#header_open|Implicit Cast: Stricter Qualification#}
39553989 <p>
......@@ -4327,7 +4361,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {
43274361 <p>
43284362 For example, if we were to introduce another function to the above snippet:
43294363 </p>
4330 {#code_begin|test_err|unable to evaluate constant expression#}
4364 {#code_begin|test_err|values of type 'type' must be comptime known#}
43314365fn max(comptime T: type, a: T, b: T) T {
43324366 return if (a > b) a else b;
43334367}
......@@ -4595,7 +4629,7 @@ test "fibonacci" {
45954629 <p>
45964630 What if we fix the base case, but put the wrong value in the {#syntax#}assert{#endsyntax#} line?
45974631 </p>
4598 {#code_begin|test_err|encountered @panic at compile-time#}
4632 {#code_begin|test_err|unable to evaluate constant expression#}
45994633const assert = @import("std").debug.assert;
46004634
46014635fn fibonacci(index: i32) i32 {
......@@ -5169,6 +5203,34 @@ fn seq(c: u8) void {
51695203 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
51705204 </p>
51715205 {#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#}
51725234 {#header_open|@ArgType#}
51735235 <pre>{#syntax#}@ArgType(comptime T: type, comptime n: usize) type{#endsyntax#}</pre>
51745236 <p>
......@@ -5241,6 +5303,7 @@ fn seq(c: u8) void {
52415303 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.
52425304 </p>
52435305 {#header_close#}
5306
52445307 {#header_open|@bitOffsetOf#}
52455308 <pre>{#syntax#}@bitOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre>
52465309 <p>
......@@ -5253,6 +5316,19 @@ fn seq(c: u8) void {
52535316 </p>
52545317 {#see_also|@byteOffsetOf#}
52555318 {#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
52565332 {#header_open|@breakpoint#}
52575333 <pre>{#syntax#}@breakpoint(){#endsyntax#}</pre>
52585334 <p>
......@@ -5264,52 +5340,34 @@ fn seq(c: u8) void {
52645340 </p>
52655341
52665342 {#header_close#}
5267 {#header_open|@byteOffsetOf#}
5268 <pre>{#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre>
5343
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>
52695347 <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.
52715350 </p>
5272 {#see_also|@bitOffsetOf#}
52735351 {#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#}
5285 {#header_open|@alignOf#}
5286 <pre>{#syntax#}@alignOf(comptime T: type) comptime_int{#endsyntax#}</pre>
5353 {#header_open|@bitreverse#}
5354 <pre>{#syntax#}@bitreverse(comptime T: type, value: T) T{#endsyntax#}</pre>
5355 <p>{#syntax#}T{#endsyntax#} accepts any integer type.</p>
52875356 <p>
5288 This function returns the number of bytes that this type should be aligned to
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.
5357 Reverses the bitpattern of an integer value, including the sign bit if applicable.
52915358 </p>
5292 <pre>{#syntax#}const assert = @import("std").debug.assert;
5293comptime {
5294 assert(*u32 == *align(@alignOf(u32)) u32);
5295}{#endsyntax#}</pre>
52965359 <p>
5297 The result is a target-specific compile time constant. It is guaranteed to be
5298 less than or equal to {#link|@sizeOf(T)|@sizeOf#}.
5360 For example 0b10110110 ({#syntax#}u8 = 182{#endsyntax#}, {#syntax#}i8 = -74{#endsyntax#})
5361 becomes 0b01101101 ({#syntax#}u8 = 109{#endsyntax#}, {#syntax#}i8 = 109{#endsyntax#}).
52995362 </p>
5300 {#see_also|Alignment#}
53015363 {#header_close#}
53025364
5303 {#header_open|@boolToInt#}
5304 <pre>{#syntax#}@boolToInt(value: bool) u1{#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>
5365 {#header_open|@byteOffsetOf#}
5366 <pre>{#syntax#}@byteOffsetOf(comptime T: type, comptime field_name: [] const u8) comptime_int{#endsyntax#}</pre>
53095367 <p>
5310 If the value is known at compile-time, the return type is {#syntax#}comptime_int{#endsyntax#}
5311 instead of {#syntax#}u1{#endsyntax#}.
5368 Returns the byte offset of a field relative to its containing struct.
53125369 </p>
5370 {#see_also|@bitOffsetOf#}
53135371 {#header_close#}
53145372
53155373 {#header_open|@bytesToSlice#}
......@@ -5378,17 +5436,7 @@ comptime {
53785436 </p>
53795437 {#see_also|Import from C Header File|@cImport|@cDefine|@cUndef#}
53805438 {#header_close#}
5381 {#header_open|@cUndef#}
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#}
5439
53925440 {#header_open|@clz#}
53935441 <pre>{#syntax#}@clz(x: T) U{#endsyntax#}</pre>
53945442 <p>
......@@ -5404,6 +5452,7 @@ comptime {
54045452 </p>
54055453 {#see_also|@ctz|@popCount#}
54065454 {#header_close#}
5455
54075456 {#header_open|@cmpxchgStrong#}
54085457 <pre>{#syntax#}@cmpxchgStrong(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T{#endsyntax#}</pre>
54095458 <p>
......@@ -5459,6 +5508,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
54595508 <p>{#syntax#}@typeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
54605509 {#see_also|Compile Variables|cmpxchgStrong#}
54615510 {#header_close#}
5511
54625512 {#header_open|@compileError#}
54635513 <pre>{#syntax#}@compileError(comptime msg: []u8){#endsyntax#}</pre>
54645514 <p>
......@@ -5471,6 +5521,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
54715521 and {#syntax#}comptime{#endsyntax#} functions.
54725522 </p>
54735523 {#header_close#}
5524
54745525 {#header_open|@compileLog#}
54755526 <pre>{#syntax#}@compileLog(args: ...){#endsyntax#}</pre>
54765527 <p>
......@@ -5525,6 +5576,7 @@ test "main" {
55255576}
55265577 {#code_end#}
55275578 {#header_close#}
5579
55285580 {#header_open|@ctz#}
55295581 <pre>{#syntax#}@ctz(x: T) U{#endsyntax#}</pre>
55305582 <p>
......@@ -5540,6 +5592,19 @@ test "main" {
55405592 </p>
55415593 {#see_also|@clz|@popCount#}
55425594 {#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
55435608 {#header_open|@divExact#}
55445609 <pre>{#syntax#}@divExact(numerator: T, denominator: T) T{#endsyntax#}</pre>
55455610 <p>
......@@ -5606,14 +5671,6 @@ test "main" {
56065671 {#see_also|@intToEnum#}
56075672 {#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
56175674 {#header_open|@errorName#}
56185675 <pre>{#syntax#}@errorName(err: anyerror) []const u8{#endsyntax#}</pre>
56195676 <p>
......@@ -5656,6 +5713,14 @@ test "main" {
56565713 {#see_also|@intToError#}
56575714 {#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
56595724 {#header_open|@export#}
56605725 <pre>{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8{#endsyntax#}</pre>
56615726 <p>
......@@ -5724,6 +5789,7 @@ test "main" {
57245789 This function is only valid within function scope.
57255790 </p>
57265791 {#header_close#}
5792
57275793 {#header_open|@handle#}
57285794 <pre>{#syntax#}@handle(){#endsyntax#}</pre>
57295795 <p>
......@@ -5734,6 +5800,7 @@ test "main" {
57345800 This function is only valid within an async function scope.
57355801 </p>
57365802 {#header_close#}
5803
57375804 {#header_open|@import#}
57385805 <pre>{#syntax#}@import(comptime path: []u8) (namespace){#endsyntax#}</pre>
57395806 <p>
......@@ -5754,6 +5821,7 @@ test "main" {
57545821 </ul>
57555822 {#see_also|Compile Variables|@embedFile#}
57565823 {#header_close#}
5824
57575825 {#header_open|@inlineCall#}
57585826 <pre>{#syntax#}@inlineCall(function: X, args: ...) Y{#endsyntax#}</pre>
57595827 <p>
......@@ -5833,6 +5901,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
58335901 bit count for an integer type is {#syntax#}65535{#endsyntax#}.
58345902 </p>
58355903 {#header_close#}
5904
58365905 {#header_open|@memberCount#}
58375906 <pre>{#syntax#}@memberCount(comptime T: type) comptime_int{#endsyntax#}</pre>
58385907 <p>
......@@ -5859,6 +5928,7 @@ fn add(a: i32, b: i32) i32 { return a + b; }
58595928 <pre>{#syntax#}@memberType(comptime T: type, comptime index: usize) type{#endsyntax#}</pre>
58605929 <p>Returns the field type of a struct or union.</p>
58615930 {#header_close#}
5931
58625932 {#header_open|@memcpy#}
58635933 <pre>{#syntax#}@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize){#endsyntax#}</pre>
58645934 <p>
......@@ -5869,14 +5939,15 @@ fn add(a: i32, b: i32) i32 { return a + b; }
58695939 This function is a low level intrinsic with no safety mechanisms. Most code
58705940 should not use this function, instead using something like this:
58715941 </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>
58735943 <p>
58745944 The optimizer is intelligent enough to turn the above snippet into a memcpy.
58755945 </p>
58765946 <p>There is also a standard library function for this:</p>
58775947 <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>
58795949 {#header_close#}
5950
58805951 {#header_open|@memset#}
58815952 <pre>{#syntax#}@memset(dest: [*]u8, c: u8, byte_count: usize){#endsyntax#}</pre>
58825953 <p>
......@@ -5886,7 +5957,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>
58865957 This function is a low level intrinsic with no safety mechanisms. Most
58875958 code should not use this function, instead using something like this:
58885959 </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>
58905961 <p>
58915962 The optimizer is intelligent enough to turn the above snippet into a memset.
58925963 </p>
......@@ -5894,6 +5965,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>
58945965 <pre>{#syntax#}const mem = @import("std").mem;
58955966mem.set(u8, dest, c);{#endsyntax#}</pre>
58965967 {#header_close#}
5968
58975969 {#header_open|@mod#}
58985970 <pre>{#syntax#}@mod(numerator: T, denominator: T) T{#endsyntax#}</pre>
58995971 <p>
......@@ -5907,6 +5979,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>
59075979 <p>For a function that returns an error code, see {#syntax#}@import("std").math.mod{#endsyntax#}.</p>
59085980 {#see_also|@rem#}
59095981 {#header_close#}
5982
59105983 {#header_open|@mulWithOverflow#}
59115984 <pre>{#syntax#}@mulWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre>
59125985 <p>
......@@ -5915,6 +5988,7 @@ mem.set(u8, dest, c);{#endsyntax#}</pre>
59155988 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
59165989 </p>
59175990 {#header_close#}
5991
59185992 {#header_open|@newStackCall#}
59195993 <pre>{#syntax#}@newStackCall(new_stack: []u8, function: var, args: ...) var{#endsyntax#}</pre>
59205994 <p>
......@@ -5951,6 +6025,7 @@ fn targetFunction(x: i32) usize {
59516025}
59526026 {#code_end#}
59536027 {#header_close#}
6028
59546029 {#header_open|@noInlineCall#}
59556030 <pre>{#syntax#}@noInlineCall(function: var, args: ...) var{#endsyntax#}</pre>
59566031 <p>
......@@ -5973,6 +6048,7 @@ fn add(a: i32, b: i32) i32 {
59736048 </p>
59746049 {#see_also|@inlineCall#}
59756050 {#header_close#}
6051
59766052 {#header_open|@OpaqueType#}
59776053 <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>
59786054 <p>
......@@ -5996,6 +6072,7 @@ test "call foo" {
59966072}
59976073 {#code_end#}
59986074 {#header_close#}
6075
59996076 {#header_open|@panic#}
60006077 <pre>{#syntax#}@panic(message: []const u8) noreturn{#endsyntax#}</pre>
60016078 <p>
......@@ -6012,6 +6089,7 @@ test "call foo" {
60126089 </ul>
60136090 {#see_also|Root Source File#}
60146091 {#header_close#}
6092
60156093 {#header_open|@popCount#}
60166094 <pre>{#syntax#}@popCount(integer: var) var{#endsyntax#}</pre>
60176095 <p>Counts the number of bits set in an integer.</p>
......@@ -6022,12 +6100,18 @@ test "call foo" {
60226100 </p>
60236101 {#see_also|@ctz|@clz#}
60246102 {#header_close#}
6103
60256104 {#header_open|@ptrCast#}
60266105 <pre>{#syntax#}@ptrCast(comptime DestType: type, value: var) DestType{#endsyntax#}</pre>
60276106 <p>
60286107 Converts a pointer of one type to a pointer of another type.
60296108 </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>
60306113 {#header_close#}
6114
60316115 {#header_open|@ptrToInt#}
60326116 <pre>{#syntax#}@ptrToInt(value: var) usize{#endsyntax#}</pre>
60336117 <p>
......@@ -6042,6 +6126,7 @@ test "call foo" {
60426126 <p>To convert the other way, use {#link|@intToPtr#}</p>
60436127
60446128 {#header_close#}
6129
60456130 {#header_open|@rem#}
60466131 <pre>{#syntax#}@rem(numerator: T, denominator: T) T{#endsyntax#}</pre>
60476132 <p>
......@@ -6055,6 +6140,7 @@ test "call foo" {
60556140 <p>For a function that returns an error code, see {#syntax#}@import("std").math.rem{#endsyntax#}.</p>
60566141 {#see_also|@mod#}
60576142 {#header_close#}
6143
60586144 {#header_open|@returnAddress#}
60596145 <pre>{#syntax#}@returnAddress(){#endsyntax#}</pre>
60606146 <p>
......@@ -6075,19 +6161,14 @@ test "call foo" {
60756161 Ensures that a function will have a stack alignment of at least {#syntax#}alignment{#endsyntax#} bytes.
60766162 </p>
60776163 {#header_close#}
6164
60786165 {#header_open|@setCold#}
60796166 <pre>{#syntax#}@setCold(is_cold: bool){#endsyntax#}</pre>
60806167 <p>
60816168 Tells the optimizer that a function is rarely called.
60826169 </p>
60836170 {#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#}
60916172 {#header_open|@setEvalBranchQuota#}
60926173 <pre>{#syntax#}@setEvalBranchQuota(new_quota: usize){#endsyntax#}</pre>
60936174 <p>
......@@ -6122,6 +6203,7 @@ test "foo" {
61226203
61236204 {#see_also|comptime#}
61246205 {#header_close#}
6206
61256207 {#header_open|@setFloatMode#}
61266208 <pre>{#syntax#}@setFloatMode(mode: @import("builtin").FloatMode){#endsyntax#}</pre>
61276209 <p>
......@@ -6156,6 +6238,7 @@ pub const FloatMode = enum {
61566238 </p>
61576239 {#see_also|Floating Point Operations#}
61586240 {#header_close#}
6241
61596242 {#header_open|@setGlobalLinkage#}
61606243 <pre>{#syntax#}@setGlobalLinkage(global_variable_name, comptime linkage: GlobalLinkage){#endsyntax#}</pre>
61616244 <p>
......@@ -6163,6 +6246,15 @@ pub const FloatMode = enum {
61636246 </p>
61646247 {#see_also|Compile Variables#}
61656248 {#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
61666258 {#header_open|@shlExact#}
61676259 <pre>{#syntax#}@shlExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre>
61686260 <p>
......@@ -6175,6 +6267,7 @@ pub const FloatMode = enum {
61756267 </p>
61766268 {#see_also|@shrExact|@shlWithOverflow#}
61776269 {#header_close#}
6270
61786271 {#header_open|@shlWithOverflow#}
61796272 <pre>{#syntax#}@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: *T) bool{#endsyntax#}</pre>
61806273 <p>
......@@ -6188,6 +6281,7 @@ pub const FloatMode = enum {
61886281 </p>
61896282 {#see_also|@shlExact|@shrExact#}
61906283 {#header_close#}
6284
61916285 {#header_open|@shrExact#}
61926286 <pre>{#syntax#}@shrExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre>
61936287 <p>
......@@ -6205,10 +6299,15 @@ pub const FloatMode = enum {
62056299 <pre>{#syntax#}@sizeOf(comptime T: type) comptime_int{#endsyntax#}</pre>
62066300 <p>
62076301 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.
62086303 </p>
62096304 <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#}.
62116309 </p>
6310 {#see_also|@typeInfo#}
62126311 {#header_close#}
62136312
62146313 {#header_open|@sliceToBytes#}
......@@ -6229,6 +6328,7 @@ pub const FloatMode = enum {
62296328 This is a low-level intrinsic. Most code can use {#syntax#}std.math.sqrt{#endsyntax#} instead.
62306329 </p>
62316330 {#header_close#}
6331
62326332 {#header_open|@subWithOverflow#}
62336333 <pre>{#syntax#}@subWithOverflow(comptime T: type, a: T, b: T, result: *T) bool{#endsyntax#}</pre>
62346334 <p>
......@@ -6237,12 +6337,14 @@ pub const FloatMode = enum {
62376337 If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
62386338 </p>
62396339 {#header_close#}
6340
62406341 {#header_open|@tagName#}
62416342 <pre>{#syntax#}@tagName(value: var) []const u8{#endsyntax#}</pre>
62426343 <p>
62436344 Converts an enum value or union value to a slice of bytes representing the name.
62446345 </p>
62456346 {#header_close#}
6347
62466348 {#header_open|@TagType#}
62476349 <pre>{#syntax#}@TagType(T: type) type{#endsyntax#}</pre>
62486350 <p>
......@@ -6252,6 +6354,7 @@ pub const FloatMode = enum {
62526354 For a union, returns the enum type that is used to store the tag value.
62536355 </p>
62546356 {#header_close#}
6357
62556358 {#header_open|@This#}
62566359 <pre>{#syntax#}@This() type{#endsyntax#}</pre>
62576360 <p>
......@@ -6287,15 +6390,16 @@ fn List(comptime T: type) type {
62876390 <a href="https://github.com/ziglang/zig/issues/1047">#1047</a> for details.
62886391 </p>
62896392 {#header_close#}
6393
62906394 {#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>
62926396 <p>
62936397 This function truncates bits from an integer type, resulting in a smaller
62946398 integer type.
62956399 </p>
62966400 <p>
6297 The following produces a crash in debug mode and undefined behavior in
6298 release mode:
6401 The following produces a crash in {#link|Debug#} mode and {#link|Undefined Behavior#} in
6402 {#link|ReleaseFast#} mode:
62996403 </p>
63006404 <pre>{#syntax#}const a: u16 = 0xabcd;
63016405const b: u8 = u8(a);{#endsyntax#}</pre>
......@@ -6309,8 +6413,12 @@ const b: u8 = @truncate(u8, a);
63096413 This function always truncates the significant bits of the integer, regardless
63106414 of endianness on the target platform.
63116415 </p>
6312
6416 <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>
63136420 {#header_close#}
6421
63146422 {#header_open|@typeId#}
63156423 <pre>{#syntax#}@typeId(comptime T: type) @import("builtin").TypeId{#endsyntax#}</pre>
63166424 <p>
......@@ -6345,6 +6453,7 @@ pub const TypeId = enum {
63456453};
63466454 {#code_end#}
63476455 {#header_close#}
6456
63486457 {#header_open|@typeInfo#}
63496458 <pre>{#syntax#}@typeInfo(comptime T: type) @import("builtin").TypeInfo{#endsyntax#}</pre>
63506459 <p>
......@@ -6527,13 +6636,16 @@ pub const TypeInfo = union(TypeId) {
65276636};
65286637 {#code_end#}
65296638 {#header_close#}
6639
65306640 {#header_open|@typeName#}
6531 <pre>{#syntax#}@typeName(T: type) []u8{#endsyntax#}</pre>
6641 <pre>{#syntax#}@typeName(T: type) [N]u8{#endsyntax#}</pre>
65326642 <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.
65346645 </p>
65356646
65366647 {#header_close#}
6648
65376649 {#header_open|@typeOf#}
65386650 <pre>{#syntax#}@typeOf(expression) type{#endsyntax#}</pre>
65396651 <p>
......@@ -6541,8 +6653,20 @@ pub const TypeInfo = union(TypeId) {
65416653 expression passed as an argument. The expression is evaluated.
65426654 </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>
65446667 {#header_close#}
65456668 {#header_close#}
6669
65466670 {#header_open|Build Mode#}
65476671 <p>
65486672 Zig has four build modes:
......@@ -6613,6 +6737,25 @@ pub fn build(b: *Builder) void {
66136737 {#header_close#}
66146738 {#see_also|Compile Variables|Zig Build System|Undefined Behavior#}
66156739 {#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
66166759 {#header_open|Undefined Behavior#}
66176760 <p>
66186761 Zig has many instances of undefined behavior. If undefined behavior is
......@@ -7213,10 +7356,27 @@ fn bar(f: *Foo) void {
72137356 {#code_end#}
72147357 {#header_close#}
72157358
7216 {#header_open|Out of Bounds Float To Integer Cast#}
7359 {#header_open|Out of Bounds Float to Integer Cast#}
72177360 <p>TODO</p>
72187361 {#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
72207380 {#header_close#}
72217381 {#header_open|Memory#}
72227382 <p>TODO: explain no default allocator in zig</p>
......@@ -7307,6 +7467,7 @@ pub fn main() void {
73077467 {#code_end#}
73087468 {#see_also|String Literals#}
73097469 {#header_close#}
7470
73107471 {#header_open|Import from C Header File#}
73117472 <p>
73127473 The {#syntax#}@cImport{#endsyntax#} builtin function can be used
......@@ -7345,6 +7506,36 @@ const c = @cImport({
73457506 {#code_end#}
73467507 {#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#}
73477508 {#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
73487539 {#header_open|Exporting a C Library#}
73497540 <p>
73507541 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
77417932
77427933TopLevelDecl
77437934 &lt;- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / KEYWORD_inline)? FnProto (SEMICOLON / Block)
7744 / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? VarDecl
7935 / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl
77457936 / KEYWORD_use Expr SEMICOLON
77467937
77477938FnProto &lt;- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr)
......@@ -8032,7 +8223,8 @@ ArrayTypeStart &lt;- LBRACKET Expr? RBRACKET
80328223PtrTypeStart
80338224 &lt;- ASTERISK
80348225 / ASTERISK2
8035 / LBRACKET ASTERISK RBRACKET
8226 / PTRUNKNOWN
8227 / PTRC
80368228
80378229# ContainerDecl specific
80388230ContainerDeclAuto &lt;- ContainerDeclType LBRACE ContainerMembers RBRACE
......@@ -8130,7 +8322,7 @@ LARROW2 &lt;- '&lt;&lt;' ![=] skip
81308322LARROW2EQUAL &lt;- '&lt;&lt;=' skip
81318323LARROWEQUAL &lt;- '&lt;=' skip
81328324LBRACE &lt;- '{' skip
8133LBRACKET &lt;- '[' skip
8325LBRACKET &lt;- '[' ![*] skip
81348326LPAREN &lt;- '(' skip
81358327MINUS &lt;- '-' ![%=&gt;] skip
81368328MINUSEQUAL &lt;- '-=' skip
......@@ -8147,6 +8339,8 @@ PLUS2 &lt;- '++' skip
81478339PLUSEQUAL &lt;- '+=' skip
81488340PLUSPERCENT &lt;- '+%' ![=] skip
81498341PLUSPERCENTEQUAL &lt;- '+%=' skip
8342PTRC &lt;- '[*c]' skip
8343PTRUNKNOWN &lt;- '[*]' skip
81508344QUESTIONMARK &lt;- '?' skip
81518345RARROW &lt;- '&gt;' ![&gt;=] skip
81528346RARROW2 &lt;- '&gt;&gt;' ![=] skip
......@@ -8201,6 +8395,7 @@ KEYWORD_struct &lt;- 'struct' end_of_word
82018395KEYWORD_suspend &lt;- 'suspend' end_of_word
82028396KEYWORD_switch &lt;- 'switch' end_of_word
82038397KEYWORD_test &lt;- 'test' end_of_word
8398KEYWORD_threadlocal &lt;- 'threadlocal' end_of_word
82048399KEYWORD_true &lt;- 'true' end_of_word
82058400KEYWORD_try &lt;- 'try' end_of_word
82068401KEYWORD_undefined &lt;- 'undefined' end_of_word
......@@ -8221,7 +8416,7 @@ keyword &lt;- KEYWORD_align / KEYWORD_and / KEYWORD_anyerror / KEYWORD_asm
82218416 / KEYWORD_orelse / KEYWORD_packed / KEYWORD_promise / KEYWORD_pub
82228417 / KEYWORD_resume / KEYWORD_return / KEYWORD_linksection
82238418 / KEYWORD_stdcallcc / KEYWORD_struct / KEYWORD_suspend
8224 / KEYWORD_switch / KEYWORD_test / KEYWORD_true / KEYWORD_try
8419 / KEYWORD_switch / KEYWORD_test / KEYWORD_threadlocal / KEYWORD_true / KEYWORD_try
82258420 / KEYWORD_undefined / KEYWORD_union / KEYWORD_unreachable
82268421 / KEYWORD_use / KEYWORD_var / KEYWORD_volatile / KEYWORD_while</code></pre>
82278422 {#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 {
1515 std.debug.warn("unable to seed random number generator: {}", err);
1616 return err;
1717 };
18 const seed = std.mem.readInt(seed_bytes, u64, builtin.Endian.Big);
18 const seed = std.mem.readIntNative(u64, &seed_bytes);
1919 var prng = std.rand.DefaultPrng.init(seed);
2020
2121 const answer = prng.random.range(u8, 0, 100) + 1;
example/hello_world/hello.zig+1-1
......@@ -2,7 +2,7 @@ const std = @import("std");
22
33pub fn main() !void {
44 // 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();
66 // If this program encounters pipe failure when printing to stdout, exit
77 // with an error.
88 try stdout_file.write("Hello, world!\n");
src-self-hosted/arg.zig+12-11
......@@ -1,5 +1,6 @@
11const std = @import("std");
22const debug = std.debug;
3const testing = std.testing;
34const mem = std.mem;
45
56const Allocator = mem.Allocator;
......@@ -272,21 +273,21 @@ test "parse arguments" {
272273
273274 var args = try Args.parse(std.debug.global_allocator, spec1, cliargs);
274275
275 debug.assert(args.present("help"));
276 debug.assert(!args.present("help2"));
277 debug.assert(!args.present("init"));
276 testing.expect(args.present("help"));
277 testing.expect(!args.present("help2"));
278 testing.expect(!args.present("init"));
278279
279 debug.assert(mem.eql(u8, args.single("build-file").?, "build.zig"));
280 debug.assert(mem.eql(u8, args.single("color").?, "on"));
280 testing.expect(mem.eql(u8, args.single("build-file").?, "build.zig"));
281 testing.expect(mem.eql(u8, args.single("color").?, "on"));
281282
282283 const objects = args.many("object").?;
283 debug.assert(mem.eql(u8, objects[0], "obj1"));
284 debug.assert(mem.eql(u8, objects[1], "obj2"));
284 testing.expect(mem.eql(u8, objects[0], "obj1"));
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
288289 const pos = args.positionals.toSliceConst();
289 debug.assert(mem.eql(u8, pos[0], "build"));
290 debug.assert(mem.eql(u8, pos[1], "pos1"));
291 debug.assert(mem.eql(u8, pos[2], "pos2"));
290 testing.expect(mem.eql(u8, pos[0], "build"));
291 testing.expect(mem.eql(u8, pos[1], "pos1"));
292 testing.expect(mem.eql(u8, pos[2], "pos2"));
292293}
src-self-hosted/codegen.zig+21-21
......@@ -137,10 +137,10 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
137137
138138pub const ObjectFile = struct {
139139 comp: *Compilation,
140 module: llvm.ModuleRef,
141 builder: llvm.BuilderRef,
140 module: *llvm.Module,
141 builder: *llvm.Builder,
142142 dibuilder: *llvm.DIBuilder,
143 context: llvm.ContextRef,
143 context: *llvm.Context,
144144 lock: event.Lock,
145145 arena: *std.mem.Allocator,
146146
......@@ -323,7 +323,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
323323
324324fn addLLVMAttr(
325325 ofile: *ObjectFile,
326 val: llvm.ValueRef,
326 val: *llvm.Value,
327327 attr_index: llvm.AttributeIndex,
328328 attr_name: []const u8,
329329) !void {
......@@ -335,7 +335,7 @@ fn addLLVMAttr(
335335
336336fn addLLVMAttrStr(
337337 ofile: *ObjectFile,
338 val: llvm.ValueRef,
338 val: *llvm.Value,
339339 attr_index: llvm.AttributeIndex,
340340 attr_name: []const u8,
341341 attr_val: []const u8,
......@@ -351,7 +351,7 @@ fn addLLVMAttrStr(
351351}
352352
353353fn addLLVMAttrInt(
354 val: llvm.ValueRef,
354 val: *llvm.Value,
355355 attr_index: llvm.AttributeIndex,
356356 attr_name: []const u8,
357357 attr_val: u64,
......@@ -362,25 +362,25 @@ fn addLLVMAttrInt(
362362 llvm.AddAttributeAtIndex(val, attr_index, llvm_attr);
363363}
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 {
366366 return addLLVMAttr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name);
367367}
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 {
370370 return addLLVMAttrStr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);
371371}
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 {
374374 return addLLVMAttrInt(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);
375375}
376376
377377fn renderLoadUntyped(
378378 ofile: *ObjectFile,
379 ptr: llvm.ValueRef,
379 ptr: *llvm.Value,
380380 alignment: Type.Pointer.Align,
381381 vol: Type.Pointer.Vol,
382382 name: [*]const u8,
383) !llvm.ValueRef {
383) !*llvm.Value {
384384 const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;
385385 switch (vol) {
386386 Type.Pointer.Vol.Non => {},
......@@ -390,11 +390,11 @@ fn renderLoadUntyped(
390390 return result;
391391}
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 {
394394 return renderLoadUntyped(ofile, ptr, ptr_type.key.alignment, ptr_type.key.vol, name);
395395}
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 {
398398 const child_type = ptr_type.key.child_type;
399399 if (!child_type.hasBits()) {
400400 return null;
......@@ -407,11 +407,11 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Po
407407
408408pub fn renderStoreUntyped(
409409 ofile: *ObjectFile,
410 value: llvm.ValueRef,
411 ptr: llvm.ValueRef,
410 value: *llvm.Value,
411 ptr: *llvm.Value,
412412 alignment: Type.Pointer.Align,
413413 vol: Type.Pointer.Vol,
414) !llvm.ValueRef {
414) !*llvm.Value {
415415 const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory;
416416 switch (vol) {
417417 Type.Pointer.Vol.Non => {},
......@@ -423,10 +423,10 @@ pub fn renderStoreUntyped(
423423
424424pub fn renderStore(
425425 ofile: *ObjectFile,
426 value: llvm.ValueRef,
427 ptr: llvm.ValueRef,
426 value: *llvm.Value,
427 ptr: *llvm.Value,
428428 ptr_type: *Type.Pointer,
429) !llvm.ValueRef {
429) !*llvm.Value {
430430 return renderStoreUntyped(ofile, value, ptr, ptr_type.key.alignment, ptr_type.key.vol);
431431}
432432
......@@ -435,7 +435,7 @@ pub fn renderAlloca(
435435 var_type: *Type,
436436 name: []const u8,
437437 alignment: Type.Pointer.Align,
438) !llvm.ValueRef {
438) !*llvm.Value {
439439 const llvm_var_type = try var_type.getLlvmType(ofile.arena, ofile.context);
440440 const name_with_null = try std.cstr.addNullByte(ofile.arena, name);
441441 const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, name_with_null.ptr) orelse return error.OutOfMemory;
......@@ -443,7 +443,7 @@ pub fn renderAlloca(
443443 return result;
444444}
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 {
447447 return switch (alignment) {
448448 Type.Pointer.Align.Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type),
449449 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
3737/// Data that is local to the event loop.
3838pub const ZigCompiler = struct {
3939 loop: *event.Loop,
40 llvm_handle_pool: std.atomic.Stack(llvm.ContextRef),
40 llvm_handle_pool: std.atomic.Stack(*llvm.Context),
4141 lld_lock: event.Lock,
4242
4343 /// TODO pool these so that it doesn't have to lock
......@@ -55,12 +55,12 @@ pub const ZigCompiler = struct {
5555
5656 var seed_bytes: [@sizeOf(u64)]u8 = undefined;
5757 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
6060 return ZigCompiler{
6161 .loop = loop,
6262 .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(),
6464 .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)),
6565 .native_libc = event.Future(LibCInstallation).init(loop),
6666 };
......@@ -70,7 +70,7 @@ pub const ZigCompiler = struct {
7070 fn deinit(self: *ZigCompiler) void {
7171 self.lld_lock.deinit();
7272 while (self.llvm_handle_pool.pop()) |node| {
73 c.LLVMContextDispose(node.data);
73 llvm.ContextDispose(node.data);
7474 self.loop.allocator.destroy(node);
7575 }
7676 }
......@@ -80,13 +80,14 @@ pub const ZigCompiler = struct {
8080 pub fn getAnyLlvmContext(self: *ZigCompiler) !LlvmHandle {
8181 if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node };
8282
83 const context_ref = c.LLVMContextCreate() orelse return error.OutOfMemory;
84 errdefer c.LLVMContextDispose(context_ref);
83 const context_ref = llvm.ContextCreate() orelse return error.OutOfMemory;
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{
8788 .next = undefined,
8889 .data = context_ref,
89 });
90 };
9091 errdefer self.loop.allocator.destroy(node);
9192
9293 return LlvmHandle{ .node = node };
......@@ -113,7 +114,7 @@ pub const ZigCompiler = struct {
113114};
114115
115116pub const LlvmHandle = struct {
116 node: *std.atomic.Stack(llvm.ContextRef).Node,
117 node: *std.atomic.Stack(*llvm.Context).Node,
117118
118119 pub fn release(self: LlvmHandle, zig_compiler: *ZigCompiler) void {
119120 zig_compiler.llvm_handle_pool.push(self.node);
......@@ -127,7 +128,7 @@ pub const Compilation = struct {
127128 llvm_triple: Buffer,
128129 root_src_path: ?[]const u8,
129130 target: Target,
130 llvm_target: llvm.TargetRef,
131 llvm_target: *llvm.Target,
131132 build_mode: builtin.Mode,
132133 zig_lib_dir: []const u8,
133134 zig_std_dir: []const u8,
......@@ -211,8 +212,8 @@ pub const Compilation = struct {
211212 false_value: *Value.Bool,
212213 noreturn_value: *Value.NoReturn,
213214
214 target_machine: llvm.TargetMachineRef,
215 target_data_ref: llvm.TargetDataRef,
215 target_machine: *llvm.TargetMachine,
216 target_data_ref: *llvm.TargetData,
216217 target_layout_str: [*]u8,
217218 target_ptr_bits: u32,
218219
......@@ -300,6 +301,7 @@ pub const Compilation = struct {
300301 UserResourceLimitReached,
301302 InvalidUtf8,
302303 BadPathName,
304 DeviceBusy,
303305 };
304306
305307 pub const Event = union(enum) {
......@@ -485,7 +487,7 @@ pub const Compilation = struct {
485487 comp.name = try Buffer.init(comp.arena(), name);
486488 comp.llvm_triple = try target.getTriple(comp.arena());
487489 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
490492 const opt_level = switch (build_mode) {
491493 builtin.Mode.Debug => llvm.CodeGenLevelNone,
......@@ -595,7 +597,8 @@ pub const Compilation = struct {
595597 }
596598
597599 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{
599602 .base = Type{
600603 .name = "type",
601604 .base = Value{
......@@ -607,12 +610,13 @@ pub const Compilation = struct {
607610 .abi_alignment = Type.AbiAlignment.init(comp.loop),
608611 },
609612 .value = undefined,
610 });
613 };
611614 comp.meta_type.value = &comp.meta_type.base;
612615 comp.meta_type.base.base.typ = &comp.meta_type.base;
613616 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{
616620 .base = Type{
617621 .name = "void",
618622 .base = Value{
......@@ -623,10 +627,11 @@ pub const Compilation = struct {
623627 .id = builtin.TypeId.Void,
624628 .abi_alignment = Type.AbiAlignment.init(comp.loop),
625629 },
626 });
630 };
627631 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{
630635 .base = Type{
631636 .name = "noreturn",
632637 .base = Value{
......@@ -637,10 +642,11 @@ pub const Compilation = struct {
637642 .id = builtin.TypeId.NoReturn,
638643 .abi_alignment = Type.AbiAlignment.init(comp.loop),
639644 },
640 });
645 };
641646 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{
644650 .base = Type{
645651 .name = "comptime_int",
646652 .base = Value{
......@@ -651,10 +657,11 @@ pub const Compilation = struct {
651657 .id = builtin.TypeId.ComptimeInt,
652658 .abi_alignment = Type.AbiAlignment.init(comp.loop),
653659 },
654 });
660 };
655661 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{
658665 .base = Type{
659666 .name = "bool",
660667 .base = Value{
......@@ -665,45 +672,50 @@ pub const Compilation = struct {
665672 .id = builtin.TypeId.Bool,
666673 .abi_alignment = Type.AbiAlignment.init(comp.loop),
667674 },
668 });
675 };
669676 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{
672680 .base = Value{
673681 .id = Value.Id.Void,
674682 .typ = &Type.Void.get(comp).base,
675683 .ref_count = std.atomic.Int(usize).init(1),
676684 },
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{
680689 .base = Value{
681690 .id = Value.Id.Bool,
682691 .typ = &Type.Bool.get(comp).base,
683692 .ref_count = std.atomic.Int(usize).init(1),
684693 },
685694 .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{
689699 .base = Value{
690700 .id = Value.Id.Bool,
691701 .typ = &Type.Bool.get(comp).base,
692702 .ref_count = std.atomic.Int(usize).init(1),
693703 },
694704 .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{
698709 .base = Value{
699710 .id = Value.Id.NoReturn,
700711 .typ = &Type.NoReturn.get(comp).base,
701712 .ref_count = std.atomic.Int(usize).init(1),
702713 },
703 });
714 };
704715
705716 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{
707719 .base = Type{
708720 .name = cint.zig_name,
709721 .base = Value{
......@@ -719,11 +731,12 @@ pub const Compilation = struct {
719731 .bit_count = comp.target.cIntTypeSizeInBits(cint.id),
720732 },
721733 .garbage_node = undefined,
722 });
734 };
723735 comp.c_int_types[i] = c_int_type;
724736 assert((try comp.primitive_type_table.put(cint.zig_name, &c_int_type.base)) == null);
725737 }
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{
727740 .base = Type{
728741 .name = "u8",
729742 .base = Value{
......@@ -739,7 +752,7 @@ pub const Compilation = struct {
739752 .bit_count = 8,
740753 },
741754 .garbage_node = undefined,
742 });
755 };
743756 assert((try comp.primitive_type_table.put(comp.u8_type.base.name, &comp.u8_type.base)) == null);
744757 }
745758
......@@ -828,7 +841,7 @@ pub const Compilation = struct {
828841 };
829842 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);
832845 tree.* = try std.zig.parse(self.gpa(), source_code);
833846 errdefer {
834847 tree.deinit();
......@@ -924,7 +937,8 @@ pub const Compilation = struct {
924937 }
925938 } else {
926939 // 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{
928942 .base = Decl{
929943 .id = Decl.Id.Fn,
930944 .name = name,
......@@ -935,7 +949,7 @@ pub const Compilation = struct {
935949 },
936950 .value = Decl.Fn.Val{ .Unresolved = {} },
937951 .fn_proto = fn_proto,
938 });
952 };
939953 tree_scope.base.ref();
940954 errdefer self.gpa().destroy(fn_decl);
941955
......@@ -1139,12 +1153,13 @@ pub const Compilation = struct {
11391153 }
11401154 }
11411155
1142 const link_lib = try self.gpa().create(LinkLib{
1156 const link_lib = try self.gpa().create(LinkLib);
1157 link_lib.* = LinkLib{
11431158 .name = name,
11441159 .path = null,
11451160 .provided_explicitly = provided_explicitly,
11461161 .symbols = ArrayList([]u8).init(self.gpa()),
1147 });
1162 };
11481163 try self.link_libs_list.append(link_lib);
11491164 if (is_libc) {
11501165 self.libc_link_lib = link_lib;
......@@ -1183,7 +1198,7 @@ pub const Compilation = struct {
11831198 const file_name = try std.fmt.allocPrint(self.gpa(), "{}{}", file_prefix[0..], suffix);
11841199 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..] });
11871202 errdefer self.gpa().free(full_path);
11881203
11891204 return Buffer.fromOwnedSlice(self.gpa(), full_path);
......@@ -1204,7 +1219,7 @@ pub const Compilation = struct {
12041219 const zig_dir_path = try getZigDir(self.gpa());
12051220 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..] });
12081223 try os.makePath(self.gpa(), tmp_dir);
12091224 return tmp_dir;
12101225 }
src-self-hosted/errmsg.zig+12-8
......@@ -118,7 +118,8 @@ pub const Msg = struct {
118118 const realpath = try mem.dupe(comp.gpa(), u8, tree_scope.root().realpath);
119119 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{
122123 .text = text,
123124 .realpath = realpath,
124125 .data = Data{
......@@ -128,7 +129,7 @@ pub const Msg = struct {
128129 .span = span,
129130 },
130131 },
131 });
132 };
132133 tree_scope.base.ref();
133134 return msg;
134135 }
......@@ -139,13 +140,14 @@ pub const Msg = struct {
139140 const realpath_copy = try mem.dupe(comp.gpa(), u8, realpath);
140141 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{
143145 .text = text,
144146 .realpath = realpath_copy,
145147 .data = Data{
146148 .Cli = Cli{ .allocator = comp.gpa() },
147149 },
148 });
150 };
149151 return msg;
150152 }
151153
......@@ -164,7 +166,8 @@ pub const Msg = struct {
164166 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
165167 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{
168171 .text = undefined,
169172 .realpath = realpath_copy,
170173 .data = Data{
......@@ -177,7 +180,7 @@ pub const Msg = struct {
177180 },
178181 },
179182 },
180 });
183 };
181184 tree_scope.base.ref();
182185 msg.text = text_buf.toOwnedSlice();
183186 return msg;
......@@ -203,7 +206,8 @@ pub const Msg = struct {
203206 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
204207 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{
207211 .text = undefined,
208212 .realpath = realpath_copy,
209213 .data = Data{
......@@ -216,7 +220,7 @@ pub const Msg = struct {
216220 },
217221 },
218222 },
219 });
223 };
220224 msg.text = text_buf.toOwnedSlice();
221225 errdefer allocator.destroy(msg);
222226
src-self-hosted/introspect.zig+2-2
......@@ -8,10 +8,10 @@ const warn = std.debug.warn;
88
99/// Caller must free result
1010pub 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" });
1212 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" });
1515 defer allocator.free(test_index_file);
1616
1717 var file = try os.File.openRead(test_index_file);
src-self-hosted/ir.zig+19-16
......@@ -67,7 +67,7 @@ pub const Inst = struct {
6767 parent: ?*Inst,
6868
6969 /// populated durign codegen
70 llvm_value: ?llvm.ValueRef,
70 llvm_value: ?*llvm.Value,
7171
7272 pub fn cast(base: *Inst, comptime T: type) ?*T {
7373 if (base.id == comptime typeToId(T)) {
......@@ -129,7 +129,7 @@ pub const Inst = struct {
129129 }
130130 }
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) {
133133 switch (base.id) {
134134 Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val),
135135 Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val),
......@@ -313,10 +313,10 @@ pub const Inst = struct {
313313 return new_inst;
314314 }
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 {
317317 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);
320320 for (self.params.args) |arg, i| {
321321 args[i] = arg.llvm_value.?;
322322 }
......@@ -360,7 +360,7 @@ pub const Inst = struct {
360360 return new_inst;
361361 }
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 {
364364 return self.base.val.KnownValue.getLlvmConst(ofile);
365365 }
366366 };
......@@ -392,7 +392,7 @@ pub const Inst = struct {
392392 return ira.irb.build(Return, self.base.scope, self.base.span, Params{ .return_value = casted_value });
393393 }
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 {
396396 const value = self.params.return_value.llvm_value;
397397 const return_type = self.params.return_value.getKnownType();
398398
......@@ -540,7 +540,7 @@ pub const Inst = struct {
540540 }
541541 }
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 {
544544 switch (self.params.var_scope.data) {
545545 Scope.Var.Data.Const => unreachable, // turned into Inst.Const in analyze pass
546546 Scope.Var.Data.Param => |param| return param.llvm_value,
......@@ -596,7 +596,7 @@ pub const Inst = struct {
596596 return new_inst;
597597 }
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 {
600600 const child_type = self.base.getKnownType();
601601 if (!child_type.hasBits()) {
602602 return null;
......@@ -935,8 +935,8 @@ pub const BasicBlock = struct {
935935 ref_instruction: ?*Inst,
936936
937937 /// for codegen
938 llvm_block: llvm.BasicBlockRef,
939 llvm_exit_block: llvm.BasicBlockRef,
938 llvm_block: *llvm.BasicBlock,
939 llvm_exit_block: *llvm.BasicBlock,
940940
941941 /// the basic block that is derived from this one in analysis
942942 child: ?*BasicBlock,
......@@ -1021,12 +1021,13 @@ pub const Builder = struct {
10211021 pub const Error = Analyze.Error;
10221022
10231023 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{
10251026 .basic_block_list = undefined,
10261027 .arena = std.heap.ArenaAllocator.init(comp.gpa()),
10271028 .return_type = null,
10281029 .tree_scope = tree_scope,
1029 });
1030 };
10301031 code.basic_block_list = std.ArrayList(*BasicBlock).init(&code.arena.allocator);
10311032 errdefer code.destroy(comp.gpa());
10321033
......@@ -1052,7 +1053,8 @@ pub const Builder = struct {
10521053
10531054 /// No need to clean up resources thanks to the arena allocator.
10541055 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{
10561058 .ref_count = 0,
10571059 .name_hint = name_hint,
10581060 .debug_id = self.next_debug_id,
......@@ -1063,7 +1065,7 @@ pub const Builder = struct {
10631065 .ref_instruction = null,
10641066 .llvm_block = undefined,
10651067 .llvm_exit_block = undefined,
1066 });
1068 };
10671069 self.next_debug_id += 1;
10681070 return basic_block;
10691071 }
......@@ -1774,7 +1776,8 @@ pub const Builder = struct {
17741776 params: I.Params,
17751777 is_generated: bool,
17761778 ) !*Inst {
1777 const inst = try self.arena().create(I{
1779 const inst = try self.arena().create(I);
1780 inst.* = I{
17781781 .base = Inst{
17791782 .id = Inst.typeToId(I),
17801783 .is_generated = is_generated,
......@@ -1793,7 +1796,7 @@ pub const Builder = struct {
17931796 .owner_bb = self.current_basic_block,
17941797 },
17951798 .params = params,
1796 });
1799 };
17971800
17981801 // Look at the params and ref() other instructions
17991802 comptime var i = 0;
src-self-hosted/libc_installation.zig+27-18
......@@ -57,10 +57,10 @@ pub const LibCInstallation = struct {
5757 const contents = try std.io.readFileAlloc(allocator, libc_file);
5858 defer allocator.free(contents);
5959
60 var it = std.mem.split(contents, "\n");
60 var it = std.mem.tokenize(contents, "\n");
6161 while (it.next()) |line| {
6262 if (line.len == 0 or line[0] == '#') continue;
63 var line_it = std.mem.split(line, "=");
63 var line_it = std.mem.separate(line, "=");
6464 const name = line_it.next() orelse {
6565 try stderr.print("missing equal sign after field name\n");
6666 return error.ParseError;
......@@ -154,8 +154,8 @@ pub const LibCInstallation = struct {
154154 c.ZigFindWindowsSdkError.None => {
155155 windows_sdk = sdk;
156156
157 if (sdk.msvc_lib_dir_ptr) |ptr| {
158 self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, ptr[0..sdk.msvc_lib_dir_len]);
157 if (sdk.msvc_lib_dir_ptr != 0) {
158 self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, sdk.msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]);
159159 }
160160 try group.call(findNativeKernel32LibDir, self, loop, sdk);
161161 try group.call(findNativeIncludeDirWindows, self, loop, sdk);
......@@ -213,7 +213,7 @@ pub const LibCInstallation = struct {
213213 },
214214 }
215215
216 var it = std.mem.split(exec_result.stderr, "\n\r");
216 var it = std.mem.tokenize(exec_result.stderr, "\n\r");
217217 var search_paths = std.ArrayList([]const u8).init(loop.allocator);
218218 defer search_paths.deinit();
219219 while (it.next()) |line| {
......@@ -230,7 +230,7 @@ pub const LibCInstallation = struct {
230230 while (path_i < search_paths.len) : (path_i += 1) {
231231 const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1);
232232 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" });
234234 defer loop.allocator.free(stdlib_path);
235235
236236 if (try fileExists(stdlib_path)) {
......@@ -254,7 +254,10 @@ pub const LibCInstallation = struct {
254254 const stream = &std.io.BufferOutStream.init(&result_buf).stream;
255255 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 );
258261 defer loop.allocator.free(stdlib_path);
259262
260263 if (try fileExists(stdlib_path)) {
......@@ -283,7 +286,10 @@ pub const LibCInstallation = struct {
283286 builtin.Arch.aarch64v8 => try stream.write("arm"),
284287 else => return error.UnsupportedArchitecture,
285288 }
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 );
287293 defer loop.allocator.free(ucrt_lib_path);
288294 if (try fileExists(ucrt_lib_path)) {
289295 self.lib_dir = result_buf.toOwnedSlice();
......@@ -358,7 +364,10 @@ pub const LibCInstallation = struct {
358364 builtin.Arch.aarch64v8 => try stream.write("arm\\"),
359365 else => return error.UnsupportedArchitecture,
360366 }
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 );
362371 defer loop.allocator.free(kernel32_path);
363372 if (try fileExists(kernel32_path)) {
364373 self.kernel32_lib_dir = result_buf.toOwnedSlice();
......@@ -410,7 +419,7 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo
410419 return error.CCompilerCrashed;
411420 },
412421 }
413 var it = std.mem.split(exec_result.stdout, "\n\r");
422 var it = std.mem.tokenize(exec_result.stdout, "\n\r");
414423 const line = it.next() orelse return error.LibCRuntimeNotFound;
415424 const dirname = std.os.path.dirname(line) orelse return error.LibCRuntimeNotFound;
416425
......@@ -428,20 +437,20 @@ const Search = struct {
428437
429438fn fillSearch(search_buf: *[2]Search, sdk: *c.ZigWindowsSDK) []Search {
430439 var search_end: usize = 0;
431 if (sdk.path10_ptr) |path10_ptr| {
432 if (sdk.version10_ptr) |ver10_ptr| {
440 if (sdk.path10_ptr != 0) {
441 if (sdk.version10_ptr != 0) {
433442 search_buf[search_end] = Search{
434 .path = path10_ptr[0..sdk.path10_len],
435 .version = ver10_ptr[0..sdk.version10_len],
443 .path = sdk.path10_ptr[0..sdk.path10_len],
444 .version = sdk.version10_ptr[0..sdk.version10_len],
436445 };
437446 search_end += 1;
438447 }
439448 }
440 if (sdk.path81_ptr) |path81_ptr| {
441 if (sdk.version81_ptr) |ver81_ptr| {
449 if (sdk.path81_ptr != 0) {
450 if (sdk.version81_ptr != 0) {
442451 search_buf[search_end] = Search{
443 .path = path81_ptr[0..sdk.path81_len],
444 .version = ver81_ptr[0..sdk.version81_len],
452 .path = sdk.path81_ptr[0..sdk.path81_len],
453 .version = sdk.version81_ptr[0..sdk.version81_len],
445454 };
446455 search_end += 1;
447456 }
src-self-hosted/link.zig+1-1
......@@ -315,7 +315,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
315315}
316316
317317fn 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 });
319319 const full_path_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, full_path);
320320 try ctx.args.append(full_path_with_null.ptr);
321321}
src-self-hosted/llvm.zig+129-52
......@@ -11,45 +11,31 @@ const assert = @import("std").debug.assert;
1111pub const AttributeIndex = c_uint;
1212pub const Bool = c_int;
1313
14pub const BuilderRef = removeNullability(c.LLVMBuilderRef);
15pub const ContextRef = removeNullability(c.LLVMContextRef);
16pub const ModuleRef = removeNullability(c.LLVMModuleRef);
17pub const ValueRef = removeNullability(c.LLVMValueRef);
18pub const TypeRef = removeNullability(c.LLVMTypeRef);
19pub const BasicBlockRef = removeNullability(c.LLVMBasicBlockRef);
20pub const AttributeRef = removeNullability(c.LLVMAttributeRef);
21pub const TargetRef = removeNullability(c.LLVMTargetRef);
22pub const TargetMachineRef = removeNullability(c.LLVMTargetMachineRef);
23pub const TargetDataRef = removeNullability(c.LLVMTargetDataRef);
14pub const Builder = c.LLVMBuilderRef.Child.Child;
15pub const Context = c.LLVMContextRef.Child.Child;
16pub const Module = c.LLVMModuleRef.Child.Child;
17pub const Value = c.LLVMValueRef.Child.Child;
18pub const Type = c.LLVMTypeRef.Child.Child;
19pub const BasicBlock = c.LLVMBasicBlockRef.Child.Child;
20pub const Attribute = c.LLVMAttributeRef.Child.Child;
21pub const Target = c.LLVMTargetRef.Child.Child;
22pub const TargetMachine = c.LLVMTargetMachineRef.Child.Child;
23pub const TargetData = c.LLVMTargetDataRef.Child.Child;
2424pub const DIBuilder = c.ZigLLVMDIBuilder;
25pub const DIFile = c.ZigLLVMDIFile;
26pub const DICompileUnit = c.ZigLLVMDICompileUnit;
2527
2628pub const ABIAlignmentOfType = c.LLVMABIAlignmentOfType;
2729pub const AddAttributeAtIndex = c.LLVMAddAttributeAtIndex;
28pub const AddFunction = c.LLVMAddFunction;
29pub const AddGlobal = c.LLVMAddGlobal;
3030pub const AddModuleCodeViewFlag = c.ZigLLVMAddModuleCodeViewFlag;
3131pub const AddModuleDebugInfoFlag = c.ZigLLVMAddModuleDebugInfoFlag;
32pub const ArrayType = c.LLVMArrayType;
33pub const BuildLoad = c.LLVMBuildLoad;
3432pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation;
3533pub const ConstAllOnes = c.LLVMConstAllOnes;
3634pub const ConstArray = c.LLVMConstArray;
3735pub const ConstBitCast = c.LLVMConstBitCast;
38pub const ConstInt = c.LLVMConstInt;
3936pub const ConstIntOfArbitraryPrecision = c.LLVMConstIntOfArbitraryPrecision;
4037pub const ConstNeg = c.LLVMConstNeg;
41pub const ConstNull = c.LLVMConstNull;
42pub const ConstStringInContext = c.LLVMConstStringInContext;
4338pub 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;
5339pub const DIBuilderFinalize = c.ZigLLVMDIBuilderFinalize;
5440pub const DisposeBuilder = c.LLVMDisposeBuilder;
5541pub const DisposeDIBuilder = c.ZigLLVMDisposeDIBuilder;
......@@ -62,9 +48,7 @@ pub const DumpModule = c.LLVMDumpModule;
6248pub const FP128TypeInContext = c.LLVMFP128TypeInContext;
6349pub const FloatTypeInContext = c.LLVMFloatTypeInContext;
6450pub const GetEnumAttributeKindForName = c.LLVMGetEnumAttributeKindForName;
65pub const GetHostCPUName = c.ZigLLVMGetHostCPUName;
6651pub const GetMDKindIDInContext = c.LLVMGetMDKindIDInContext;
67pub const GetNativeFeatures = c.ZigLLVMGetNativeFeatures;
6852pub const GetUndef = c.LLVMGetUndef;
6953pub const HalfTypeInContext = c.LLVMHalfTypeInContext;
7054pub const InitializeAllAsmParsers = c.LLVMInitializeAllAsmParsers;
......@@ -81,14 +65,11 @@ pub const Int64TypeInContext = c.LLVMInt64TypeInContext;
8165pub const Int8TypeInContext = c.LLVMInt8TypeInContext;
8266pub const IntPtrTypeForASInContext = c.LLVMIntPtrTypeForASInContext;
8367pub const IntPtrTypeInContext = c.LLVMIntPtrTypeInContext;
84pub const IntTypeInContext = c.LLVMIntTypeInContext;
8568pub const LabelTypeInContext = c.LLVMLabelTypeInContext;
8669pub const MDNodeInContext = c.LLVMMDNodeInContext;
8770pub const MDStringInContext = c.LLVMMDStringInContext;
8871pub const MetadataTypeInContext = c.LLVMMetadataTypeInContext;
89pub const ModuleCreateWithNameInContext = c.LLVMModuleCreateWithNameInContext;
9072pub const PPCFP128TypeInContext = c.LLVMPPCFP128TypeInContext;
91pub const PointerType = c.LLVMPointerType;
9273pub const SetAlignment = c.LLVMSetAlignment;
9374pub const SetDataLayout = c.LLVMSetDataLayout;
9475pub const SetGlobalConstant = c.LLVMSetGlobalConstant;
......@@ -99,50 +80,146 @@ pub const SetUnnamedAddr = c.LLVMSetUnnamedAddr;
9980pub const SetVolatile = c.LLVMSetVolatile;
10081pub const StructTypeInContext = c.LLVMStructTypeInContext;
10182pub const TokenTypeInContext = c.LLVMTokenTypeInContext;
102pub const VoidTypeInContext = c.LLVMVoidTypeInContext;
10383pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext;
10484pub 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
106183pub const GetElementType = LLVMGetElementType;
107extern fn LLVMGetElementType(Ty: TypeRef) TypeRef;
184extern fn LLVMGetElementType(Ty: *Type) *Type;
108185
109186pub const TypeOf = LLVMTypeOf;
110extern fn LLVMTypeOf(Val: ValueRef) TypeRef;
187extern fn LLVMTypeOf(Val: *Value) *Type;
111188
112189pub const BuildStore = LLVMBuildStore;
113extern fn LLVMBuildStore(arg0: BuilderRef, Val: ValueRef, Ptr: ValueRef) ?ValueRef;
190extern fn LLVMBuildStore(arg0: *Builder, Val: *Value, Ptr: *Value) ?*Value;
114191
115192pub 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
118195pub 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
121198pub 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
124201pub const VerifyModule = LLVMVerifyModule;
125extern fn LLVMVerifyModule(M: ModuleRef, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool;
202extern fn LLVMVerifyModule(M: *Module, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool;
126203
127204pub const GetInsertBlock = LLVMGetInsertBlock;
128extern fn LLVMGetInsertBlock(Builder: BuilderRef) BasicBlockRef;
205extern fn LLVMGetInsertBlock(Builder: *Builder) *BasicBlock;
129206
130207pub const FunctionType = LLVMFunctionType;
131208extern fn LLVMFunctionType(
132 ReturnType: TypeRef,
133 ParamTypes: [*]TypeRef,
209 ReturnType: *Type,
210 ParamTypes: [*]*Type,
134211 ParamCount: c_uint,
135212 IsVarArg: Bool,
136) ?TypeRef;
213) ?*Type;
137214
138215pub const GetParam = LLVMGetParam;
139extern fn LLVMGetParam(Fn: ValueRef, Index: c_uint) ValueRef;
216extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;
140217
141218pub 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
144221pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd;
145extern fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef) void;
222extern fn LLVMPositionBuilderAtEnd(Builder: *Builder, Block: *BasicBlock) void;
146223
147224pub const AbortProcessAction = VerifierFailureAction.LLVMAbortProcessAction;
148225pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction;
......@@ -190,17 +267,17 @@ pub const FnInline = extern enum {
190267};
191268
192269fn removeNullability(comptime T: type) type {
193 comptime assert(@typeId(T) == builtin.TypeId.Optional);
194 return T.Child;
270 comptime assert(@typeInfo(T).Pointer.size == @import("builtin").TypeInfo.Pointer.Size.C);
271 return *T.Child;
195272}
196273
197274pub const BuildRet = LLVMBuildRet;
198extern fn LLVMBuildRet(arg0: BuilderRef, V: ?ValueRef) ?ValueRef;
275extern fn LLVMBuildRet(arg0: *Builder, V: ?*Value) ?*Value;
199276
200277pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile;
201278extern fn ZigLLVMTargetMachineEmitToFile(
202 targ_machine_ref: TargetMachineRef,
203 module_ref: ModuleRef,
279 targ_machine_ref: *TargetMachine,
280 module_ref: *Module,
204281 filename: [*]const u8,
205282 output_type: EmitOutputType,
206283 error_message: *[*]u8,
......@@ -209,6 +286,6 @@ extern fn ZigLLVMTargetMachineEmitToFile(
209286) bool;
210287
211288pub 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
214291pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;
src-self-hosted/main.zig+8-7
......@@ -24,7 +24,7 @@ var stderr_file: os.File = undefined;
2424var stderr: *io.OutStream(os.File.WriteError) = undefined;
2525var stdout: *io.OutStream(os.File.WriteError) = undefined;
2626
27const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
27pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
2828
2929const usage =
3030 \\usage: zig [command] [options]
......@@ -351,7 +351,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
351351 const root_name = if (provided_name) |n| n else blk: {
352352 if (root_source_file) |file| {
353353 const basename = os.path.basename(file);
354 var it = mem.split(basename, ".");
354 var it = mem.separate(basename, ".");
355355 break :blk it.next() orelse basename;
356356 } else {
357357 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 {
510510 return buildOutputType(allocator, args, Compilation.Kind.Obj);
511511}
512512
513const usage_fmt =
513pub const usage_fmt =
514514 \\usage: zig fmt [file]...
515515 \\
516516 \\ Formats the input files and modifies them in-place.
......@@ -527,7 +527,7 @@ const usage_fmt =
527527 \\
528528;
529529
530const args_fmt_spec = []Flag{
530pub const args_fmt_spec = []Flag{
531531 Flag.Bool("--help"),
532532 Flag.Bool("--check"),
533533 Flag.Option("--color", []const []const u8{
......@@ -757,7 +757,7 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
757757 var group = event.Group(FmtError!void).init(fmt.loop);
758758 while (try dir.next()) |entry| {
759759 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 });
761761 try group.call(fmtPath, fmt, full_path, check_mode);
762762 }
763763 }
......@@ -944,12 +944,13 @@ const CliPkg = struct {
944944 parent: ?*CliPkg,
945945
946946 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{
948949 .name = name,
949950 .path = path,
950951 .children = ArrayList(*CliPkg).init(allocator),
951952 .parent = parent,
952 });
953 };
953954 return pkg;
954955 }
955956
src-self-hosted/package.zig+4-2
......@@ -15,11 +15,13 @@ pub const Package = struct {
1515 /// makes internal copies of root_src_dir and root_src_path
1616 /// allocator should be an arena allocator because Package never frees anything
1717 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{
1920 .root_src_dir = try Buffer.init(allocator, root_src_dir),
2021 .root_src_path = try Buffer.init(allocator, root_src_path),
2122 .table = Table.init(allocator),
22 });
23 };
24 return ptr;
2325 }
2426
2527 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 {
120120 /// Creates a Root scope with 1 reference
121121 /// Takes ownership of realpath
122122 pub fn create(comp: *Compilation, realpath: []u8) !*Root {
123 const self = try comp.gpa().createOne(Root);
123 const self = try comp.gpa().create(Root);
124124 self.* = Root{
125125 .base = Scope{
126126 .id = Id.Root,
......@@ -150,7 +150,7 @@ pub const Scope = struct {
150150 /// Creates a scope with 1 reference
151151 /// Takes ownership of tree, will deinit and destroy when done.
152152 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);
154154 self.* = AstTree{
155155 .base = undefined,
156156 .tree = tree,
......@@ -182,7 +182,7 @@ pub const Scope = struct {
182182
183183 /// Creates a Decls scope with 1 reference
184184 pub fn create(comp: *Compilation, parent: *Scope) !*Decls {
185 const self = try comp.gpa().createOne(Decls);
185 const self = try comp.gpa().create(Decls);
186186 self.* = Decls{
187187 .base = undefined,
188188 .table = event.RwLocked(Decl.Table).init(comp.loop, Decl.Table.init(comp.gpa())),
......@@ -235,7 +235,7 @@ pub const Scope = struct {
235235
236236 /// Creates a Block scope with 1 reference
237237 pub fn create(comp: *Compilation, parent: *Scope) !*Block {
238 const self = try comp.gpa().createOne(Block);
238 const self = try comp.gpa().create(Block);
239239 self.* = Block{
240240 .base = undefined,
241241 .incoming_values = undefined,
......@@ -262,7 +262,7 @@ pub const Scope = struct {
262262 /// Creates a FnDef scope with 1 reference
263263 /// Must set the fn_val later
264264 pub fn create(comp: *Compilation, parent: *Scope) !*FnDef {
265 const self = try comp.gpa().createOne(FnDef);
265 const self = try comp.gpa().create(FnDef);
266266 self.* = FnDef{
267267 .base = undefined,
268268 .fn_val = null,
......@@ -281,7 +281,7 @@ pub const Scope = struct {
281281
282282 /// Creates a CompTime scope with 1 reference
283283 pub fn create(comp: *Compilation, parent: *Scope) !*CompTime {
284 const self = try comp.gpa().createOne(CompTime);
284 const self = try comp.gpa().create(CompTime);
285285 self.* = CompTime{ .base = undefined };
286286 self.base.init(Id.CompTime, parent);
287287 return self;
......@@ -309,7 +309,7 @@ pub const Scope = struct {
309309 kind: Kind,
310310 defer_expr_scope: *DeferExpr,
311311 ) !*Defer {
312 const self = try comp.gpa().createOne(Defer);
312 const self = try comp.gpa().create(Defer);
313313 self.* = Defer{
314314 .base = undefined,
315315 .defer_expr_scope = defer_expr_scope,
......@@ -333,7 +333,7 @@ pub const Scope = struct {
333333
334334 /// Creates a DeferExpr scope with 1 reference
335335 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);
337337 self.* = DeferExpr{
338338 .base = undefined,
339339 .expr_node = expr_node,
......@@ -362,7 +362,7 @@ pub const Scope = struct {
362362 pub const Param = struct {
363363 index: usize,
364364 typ: *Type,
365 llvm_value: llvm.ValueRef,
365 llvm_value: *llvm.Value,
366366 };
367367
368368 pub fn createParam(
......@@ -398,7 +398,7 @@ pub const Scope = struct {
398398 }
399399
400400 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);
402402 self.* = Var{
403403 .base = undefined,
404404 .name = name,
src-self-hosted/target.zig+3-3
......@@ -457,8 +457,8 @@ pub const Target = union(enum) {
457457 }
458458 }
459459
460 pub fn llvmTargetFromTriple(triple: std.Buffer) !llvm.TargetRef {
461 var result: llvm.TargetRef = undefined;
460 pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target {
461 var result: *llvm.Target = undefined;
462462 var err_msg: [*]u8 = undefined;
463463 if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) {
464464 std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg);
......@@ -520,7 +520,7 @@ pub const Target = union(enum) {
520520 => return 64,
521521 },
522522
523 builtin.Os.windows => switch (id) {
523 builtin.Os.windows, builtin.Os.uefi => switch (id) {
524524 CInt.Id.Short,
525525 CInt.Id.UShort,
526526 => return 16,
src-self-hosted/test.zig+4-4
......@@ -4,7 +4,7 @@ const builtin = @import("builtin");
44const Target = @import("target.zig").Target;
55const Compilation = @import("compilation.zig").Compilation;
66const introspect = @import("introspect.zig");
7const assertOrPanic = std.debug.assertOrPanic;
7const testing = std.testing;
88const errmsg = @import("errmsg.zig");
99const ZigCompiler = @import("compilation.zig").ZigCompiler;
1010
......@@ -87,7 +87,7 @@ pub const TestContext = struct {
8787 ) !void {
8888 var file_index_buf: [20]u8 = undefined;
8989 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
9292 if (std.os.path.dirname(file1_path)) |dirname| {
9393 try std.os.makePath(allocator, dirname);
......@@ -120,7 +120,7 @@ pub const TestContext = struct {
120120 ) !void {
121121 var file_index_buf: [20]u8 = undefined;
122122 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
125125 const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", file1_path, Target(Target.Native).exeFileExt());
126126 if (std.os.path.dirname(file1_path)) |dirname| {
......@@ -210,7 +210,7 @@ pub const TestContext = struct {
210210 @panic("build incorrectly failed");
211211 },
212212 Compilation.Event.Fail => |msgs| {
213 assertOrPanic(msgs.len != 0);
213 testing.expect(msgs.len != 0);
214214 for (msgs) |msg| {
215215 if (mem.endsWith(u8, msg.realpath, path) and mem.eql(u8, msg.text, text)) {
216216 const span = msg.getSpan();
src-self-hosted/type.zig+48-27
......@@ -44,14 +44,15 @@ pub const Type = struct {
4444 Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),
4545 Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),
4646 Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(comp),
47 Id.Vector => @fieldParentPtr(Vector, "base", base).destroy(comp),
4748 }
4849 }
4950
5051 pub fn getLlvmType(
5152 base: *Type,
5253 allocator: *Allocator,
53 llvm_context: llvm.ContextRef,
54 ) (error{OutOfMemory}!llvm.TypeRef) {
54 llvm_context: *llvm.Context,
55 ) (error{OutOfMemory}!*llvm.Type) {
5556 switch (base.id) {
5657 Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),
5758 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),
......@@ -77,6 +78,7 @@ pub const Type = struct {
7778 Id.ArgTuple => unreachable,
7879 Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context),
7980 Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(allocator, llvm_context),
81 Id.Vector => return @fieldParentPtr(Vector, "base", base).getLlvmType(allocator, llvm_context),
8082 }
8183 }
8284
......@@ -103,6 +105,7 @@ pub const Type = struct {
103105 Id.Enum,
104106 Id.Fn,
105107 Id.Promise,
108 Id.Vector,
106109 => return false,
107110
108111 Id.Struct => @panic("TODO"),
......@@ -135,6 +138,7 @@ pub const Type = struct {
135138 Id.Float,
136139 Id.Fn,
137140 Id.Promise,
141 Id.Vector,
138142 => return true,
139143
140144 Id.Pointer => {
......@@ -192,7 +196,7 @@ pub const Type = struct {
192196 }
193197
194198 /// 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 {
196200 if (await (async base.abi_alignment.start() catch unreachable)) |ptr| return ptr.*;
197201
198202 base.abi_alignment.data = await (async base.resolveAbiAlignment(comp, llvm_context) catch unreachable);
......@@ -201,7 +205,7 @@ pub const Type = struct {
201205 }
202206
203207 /// 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 {
205209 const llvm_type = try base.getLlvmType(comp.gpa(), llvm_context);
206210 return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type));
207211 }
......@@ -214,7 +218,7 @@ pub const Type = struct {
214218 comp.gpa().destroy(self);
215219 }
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 {
218222 @panic("TODO");
219223 }
220224 };
......@@ -409,7 +413,7 @@ pub const Type = struct {
409413 key.ref();
410414 errdefer key.deref(comp);
411415
412 const self = try comp.gpa().createOne(Fn);
416 const self = try comp.gpa().create(Fn);
413417 self.* = Fn{
414418 .base = undefined,
415419 .key = key,
......@@ -492,13 +496,13 @@ pub const Type = struct {
492496 comp.gpa().destroy(self);
493497 }
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 {
496500 const normal = &self.key.data.Normal;
497501 const llvm_return_type = switch (normal.return_type.id) {
498502 Type.Id.Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory,
499503 else => try normal.return_type.getLlvmType(allocator, llvm_context),
500504 };
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);
502506 defer allocator.free(llvm_param_types);
503507 for (llvm_param_types) |*llvm_param_type, i| {
504508 llvm_param_type.* = try normal.params[i].typ.getLlvmType(allocator, llvm_context);
......@@ -555,7 +559,7 @@ pub const Type = struct {
555559 comp.gpa().destroy(self);
556560 }
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 {
559563 @panic("TODO");
560564 }
561565 };
......@@ -611,11 +615,12 @@ pub const Type = struct {
611615 }
612616 }
613617
614 const self = try comp.gpa().create(Int{
618 const self = try comp.gpa().create(Int);
619 self.* = Int{
615620 .base = undefined,
616621 .key = key,
617622 .garbage_node = undefined,
618 });
623 };
619624 errdefer comp.gpa().destroy(self);
620625
621626 const u_or_i = "ui"[@boolToInt(key.is_signed)];
......@@ -653,7 +658,7 @@ pub const Type = struct {
653658 comp.gpa().destroy(self);
654659 }
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 {
657662 return llvm.IntTypeInContext(llvm_context, self.key.bit_count) orelse return error.OutOfMemory;
658663 }
659664 };
......@@ -665,7 +670,7 @@ pub const Type = struct {
665670 comp.gpa().destroy(self);
666671 }
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 {
669674 @panic("TODO");
670675 }
671676 };
......@@ -777,17 +782,19 @@ pub const Type = struct {
777782 }
778783 }
779784
780 const self = try comp.gpa().create(Pointer{
785 const self = try comp.gpa().create(Pointer);
786 self.* = Pointer{
781787 .base = undefined,
782788 .key = normal_key,
783789 .garbage_node = undefined,
784 });
790 };
785791 errdefer comp.gpa().destroy(self);
786792
787793 const size_str = switch (self.key.size) {
788794 Size.One => "*",
789795 Size.Many => "[*]",
790796 Size.Slice => "[]",
797 Size.C => "[*c]",
791798 };
792799 const mut_str = switch (self.key.mut) {
793800 Mut.Const => "const ",
......@@ -829,7 +836,7 @@ pub const Type = struct {
829836 return self;
830837 }
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 {
833840 const elem_llvm_type = try self.key.child_type.getLlvmType(allocator, llvm_context);
834841 return llvm.PointerType(elem_llvm_type, 0) orelse return error.OutOfMemory;
835842 }
......@@ -875,11 +882,12 @@ pub const Type = struct {
875882 }
876883 }
877884
878 const self = try comp.gpa().create(Array{
885 const self = try comp.gpa().create(Array);
886 self.* = Array{
879887 .base = undefined,
880888 .key = key,
881889 .garbage_node = undefined,
882 });
890 };
883891 errdefer comp.gpa().destroy(self);
884892
885893 const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", key.len, key.elem_type.name);
......@@ -896,12 +904,24 @@ pub const Type = struct {
896904 return self;
897905 }
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 {
900908 const elem_llvm_type = try self.key.elem_type.getLlvmType(allocator, llvm_context);
901909 return llvm.ArrayType(elem_llvm_type, @intCast(c_uint, self.key.len)) orelse return error.OutOfMemory;
902910 }
903911 };
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
905925 pub const ComptimeFloat = struct {
906926 base: Type,
907927
......@@ -947,7 +967,7 @@ pub const Type = struct {
947967 comp.gpa().destroy(self);
948968 }
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 {
951971 @panic("TODO");
952972 }
953973 };
......@@ -959,7 +979,7 @@ pub const Type = struct {
959979 comp.gpa().destroy(self);
960980 }
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 {
963983 @panic("TODO");
964984 }
965985 };
......@@ -971,7 +991,7 @@ pub const Type = struct {
971991 comp.gpa().destroy(self);
972992 }
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 {
975995 @panic("TODO");
976996 }
977997 };
......@@ -983,7 +1003,7 @@ pub const Type = struct {
9831003 comp.gpa().destroy(self);
9841004 }
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 {
9871007 @panic("TODO");
9881008 }
9891009 };
......@@ -995,7 +1015,7 @@ pub const Type = struct {
9951015 comp.gpa().destroy(self);
9961016 }
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 {
9991019 @panic("TODO");
10001020 }
10011021 };
......@@ -1015,7 +1035,7 @@ pub const Type = struct {
10151035 comp.gpa().destroy(self);
10161036 }
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 {
10191039 @panic("TODO");
10201040 }
10211041 };
......@@ -1035,7 +1055,7 @@ pub const Type = struct {
10351055 comp.gpa().destroy(self);
10361056 }
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 {
10391059 @panic("TODO");
10401060 }
10411061 };
......@@ -1047,7 +1067,7 @@ pub const Type = struct {
10471067 comp.gpa().destroy(self);
10481068 }
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 {
10511071 @panic("TODO");
10521072 }
10531073 };
......@@ -1069,6 +1089,7 @@ fn hashAny(x: var, comptime seed: u64) u32 {
10691089 builtin.TypeInfo.Pointer.Size.One => return hashAny(@ptrToInt(x), seed),
10701090 builtin.TypeInfo.Pointer.Size.Many => @compileError("implement hash function"),
10711091 builtin.TypeInfo.Pointer.Size.Slice => @compileError("implement hash function"),
1092 builtin.TypeInfo.Pointer.Size.C => unreachable,
10721093 }
10731094 },
10741095 builtin.TypeId.Enum => return hashAny(@enumToInt(x), seed),
src-self-hosted/value.zig+30-23
......@@ -57,7 +57,7 @@ pub const Value = struct {
5757 std.debug.warn("{}", @tagName(base.id));
5858 }
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) {
6161 switch (base.id) {
6262 Id.Type => unreachable,
6363 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile),
......@@ -135,14 +135,15 @@ pub const Value = struct {
135135 symbol_name: Buffer,
136136
137137 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{
139140 .base = Value{
140141 .id = Value.Id.FnProto,
141142 .typ = &fn_type.base,
142143 .ref_count = std.atomic.Int(usize).init(1),
143144 },
144145 .symbol_name = symbol_name,
145 });
146 };
146147 fn_type.base.base.ref();
147148 return self;
148149 }
......@@ -152,7 +153,7 @@ pub const Value = struct {
152153 comp.gpa().destroy(self);
153154 }
154155
155 pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?llvm.ValueRef {
156 pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?*llvm.Value {
156157 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
157158 const llvm_fn = llvm.AddFunction(
158159 ofile.module,
......@@ -190,14 +191,16 @@ pub const Value = struct {
190191 /// Creates a Fn value with 1 ref
191192 /// Takes ownership of symbol_name
192193 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{
194196 .data = null,
195197 .next = undefined,
196198 .prev = undefined,
197 });
199 };
198200 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{
201204 .base = Value{
202205 .id = Value.Id.Fn,
203206 .typ = &fn_type.base,
......@@ -209,7 +212,7 @@ pub const Value = struct {
209212 .symbol_name = symbol_name,
210213 .containing_object = Buffer.initNull(comp.gpa()),
211214 .link_set_node = link_set_node,
212 });
215 };
213216 fn_type.base.base.ref();
214217 fndef_scope.fn_val = self;
215218 fndef_scope.base.ref();
......@@ -235,7 +238,7 @@ pub const Value = struct {
235238 /// We know that the function definition will end up in an .o file somewhere.
236239 /// Here, all we have to do is generate a global prototype.
237240 /// 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 {
239242 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
240243 const llvm_fn = llvm.AddFunction(
241244 ofile.module,
......@@ -280,8 +283,8 @@ pub const Value = struct {
280283 comp.gpa().destroy(self);
281284 }
282285
283 pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) ?llvm.ValueRef {
284 const llvm_type = llvm.Int1TypeInContext(ofile.context);
286 pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) !?*llvm.Value {
287 const llvm_type = llvm.Int1TypeInContext(ofile.context) orelse return error.OutOfMemory;
285288 if (self.x) {
286289 return llvm.ConstAllOnes(llvm_type);
287290 } else {
......@@ -353,7 +356,8 @@ pub const Value = struct {
353356 var ptr_type_consumed = false;
354357 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{
357361 .base = Value{
358362 .id = Value.Id.Ptr,
359363 .typ = &ptr_type.base,
......@@ -366,7 +370,7 @@ pub const Value = struct {
366370 },
367371 },
368372 .mut = Mut.CompTimeConst,
369 });
373 };
370374 ptr_type_consumed = true;
371375 errdefer comp.gpa().destroy(self);
372376
......@@ -377,7 +381,7 @@ pub const Value = struct {
377381 comp.gpa().destroy(self);
378382 }
379383
380 pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?llvm.ValueRef {
384 pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?*llvm.Value {
381385 const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context);
382386 // TODO carefully port the logic from codegen.cpp:gen_const_val_ptr
383387 switch (self.special) {
......@@ -387,7 +391,7 @@ pub const Value = struct {
387391 const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;
388392 const ptr_bit_count = ofile.comp.target_ptr_bits;
389393 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{
391395 llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory,
392396 llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory,
393397 };
......@@ -430,14 +434,15 @@ pub const Value = struct {
430434 }) catch unreachable);
431435 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{
434439 .base = Value{
435440 .id = Value.Id.Array,
436441 .typ = &array_type.base,
437442 .ref_count = std.atomic.Int(usize).init(1),
438443 },
439444 .special = Special{ .OwnedBuffer = buffer },
440 });
445 };
441446 errdefer comp.gpa().destroy(self);
442447
443448 return self;
......@@ -454,7 +459,7 @@ pub const Value = struct {
454459 comp.gpa().destroy(self);
455460 }
456461
457 pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?llvm.ValueRef {
462 pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?*llvm.Value {
458463 switch (self.special) {
459464 Special.Undefined => {
460465 const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
......@@ -509,14 +514,15 @@ pub const Value = struct {
509514 big_int: std.math.big.Int,
510515
511516 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{
513519 .base = Value{
514520 .id = Value.Id.Int,
515521 .typ = typ,
516522 .ref_count = std.atomic.Int(usize).init(1),
517523 },
518524 .big_int = undefined,
519 });
525 };
520526 typ.base.ref();
521527 errdefer comp.gpa().destroy(self);
522528
......@@ -528,7 +534,7 @@ pub const Value = struct {
528534 return self;
529535 }
530536
531 pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?llvm.ValueRef {
537 pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?*llvm.Value {
532538 switch (self.base.typ.id) {
533539 Type.Id.Int => {
534540 const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
......@@ -557,14 +563,15 @@ pub const Value = struct {
557563 old.base.typ.base.ref();
558564 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{
561568 .base = Value{
562569 .id = Value.Id.Int,
563570 .typ = old.base.typ,
564571 .ref_count = std.atomic.Int(usize).init(1),
565572 },
566573 .big_int = undefined,
567 });
574 };
568575 errdefer comp.gpa().destroy(new);
569576
570577 new.big_int = try old.big_int.clone();
src/all_types.hpp+212-61
......@@ -56,9 +56,6 @@ struct IrExecutable {
5656 size_t next_debug_id;
5757 size_t *backward_branch_count;
5858 size_t backward_branch_quota;
59 bool invalid;
60 bool is_inline;
61 bool is_generic_instantiation;
6259 ZigFn *fn_entry;
6360 Buf *c_import_buf;
6461 AstNode *source_node;
......@@ -78,6 +75,10 @@ struct IrExecutable {
7875 IrBasicBlock *coro_suspend_block;
7976 IrBasicBlock *coro_final_cleanup_block;
8077 ZigVar *coro_allocator_var;
78
79 bool invalid;
80 bool is_inline;
81 bool is_generic_instantiation;
8182};
8283
8384enum OutType {
......@@ -90,6 +91,9 @@ enum OutType {
9091enum ConstParentId {
9192 ConstParentIdNone,
9293 ConstParentIdStruct,
94 ConstParentIdErrUnionCode,
95 ConstParentIdErrUnionPayload,
96 ConstParentIdOptionalPayload,
9397 ConstParentIdArray,
9498 ConstParentIdUnion,
9599 ConstParentIdScalar,
......@@ -107,6 +111,15 @@ struct ConstParent {
107111 ConstExprValue *struct_val;
108112 size_t field_index;
109113 } 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;
110123 struct {
111124 ConstExprValue *union_val;
112125 } p_union;
......@@ -118,13 +131,11 @@ struct ConstParent {
118131
119132struct ConstStructValue {
120133 ConstExprValue *fields;
121 ConstParent parent;
122134};
123135
124136struct ConstUnionValue {
125137 BigInt tag;
126138 ConstExprValue *payload;
127 ConstParent parent;
128139};
129140
130141enum ConstArraySpecial {
......@@ -138,7 +149,6 @@ struct ConstArrayValue {
138149 union {
139150 struct {
140151 ConstExprValue *elements;
141 ConstParent parent;
142152 } s_none;
143153 Buf *s_buf;
144154 } data;
......@@ -153,19 +163,29 @@ enum ConstPtrSpecial {
153163 ConstPtrSpecialBaseArray,
154164 // The pointer points to a field in an underlying struct.
155165 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,
156172 // This means that we did a compile-time pointer reinterpret and we cannot
157173 // understand the value of pointee at compile time. However, we will still
158174 // emit a binary with a compile time known address.
159175 // 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
163176 ConstPtrSpecialHardCodedAddr,
164177 // This means that the pointer represents memory of assigning to _.
165178 // That is, storing discards the data, and loading is invalid.
166179 ConstPtrSpecialDiscard,
167180 // This is actually a function.
168181 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,
169189};
170190
171191enum ConstPtrMut {
......@@ -199,6 +219,15 @@ struct ConstPtrValue {
199219 ConstExprValue *struct_val;
200220 size_t field_index;
201221 } 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;
202231 struct {
203232 uint64_t addr;
204233 } hard_coded_addr;
......@@ -209,7 +238,7 @@ struct ConstPtrValue {
209238};
210239
211240struct ConstErrValue {
212 ErrorTableEntry *err;
241 ConstExprValue *error_set;
213242 ConstExprValue *payload;
214243};
215244
......@@ -265,6 +294,7 @@ struct ConstGlobalRefs {
265294struct ConstExprValue {
266295 ZigType *type;
267296 ConstValSpecial special;
297 ConstParent parent;
268298 ConstGlobalRefs *global_refs;
269299
270300 union {
......@@ -433,7 +463,7 @@ enum NodeType {
433463 NodeTypeArrayType,
434464 NodeTypeErrorType,
435465 NodeTypeIfErrorExpr,
436 NodeTypeTestExpr,
466 NodeTypeIfOptional,
437467 NodeTypeErrorSetDecl,
438468 NodeTypeCancel,
439469 NodeTypeResume,
......@@ -514,12 +544,7 @@ struct AstNodeDefer {
514544};
515545
516546struct AstNodeVariableDeclaration {
517 VisibMod visib_mod;
518547 Buf *symbol;
519 bool is_const;
520 bool is_comptime;
521 bool is_export;
522 bool is_extern;
523548 // one or both of type and expr will be non null
524549 AstNode *type;
525550 AstNode *expr;
......@@ -529,6 +554,13 @@ struct AstNodeVariableDeclaration {
529554 AstNode *align_expr;
530555 // populated if the "section(S)" is present
531556 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;
532564};
533565
534566struct AstNodeTestDecl {
......@@ -605,7 +637,6 @@ enum CastOp {
605637 CastOpFloatToInt,
606638 CastOpBoolToInt,
607639 CastOpResizeSlice,
608 CastOpBytesToSlice,
609640 CastOpNumLitToConcrete,
610641 CastOpErrSet,
611642 CastOpBitCast,
......@@ -660,15 +691,17 @@ struct AstNodePointerType {
660691 AstNode *align_expr;
661692 BigInt *bit_offset_start;
662693 BigInt *host_int_bytes;
694 AstNode *op_expr;
695 Token *allow_zero_token;
663696 bool is_const;
664697 bool is_volatile;
665 AstNode *op_expr;
666698};
667699
668700struct AstNodeArrayType {
669701 AstNode *size;
670702 AstNode *child_type;
671703 AstNode *align_expr;
704 Token *allow_zero_token;
672705 bool is_const;
673706 bool is_volatile;
674707};
......@@ -678,7 +711,7 @@ struct AstNodeUse {
678711 AstNode *expr;
679712
680713 TldResolution resolution;
681 IrInstruction *value;
714 ConstExprValue *value;
682715};
683716
684717struct AstNodeIfBoolExpr {
......@@ -1007,6 +1040,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
10071040enum PtrLen {
10081041 PtrLenUnknown,
10091042 PtrLenSingle,
1043 PtrLenC,
10101044};
10111045
10121046struct ZigTypePointer {
......@@ -1018,6 +1052,7 @@ struct ZigTypePointer {
10181052 uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned
10191053 bool is_const;
10201054 bool is_volatile;
1055 bool allow_zero;
10211056};
10221057
10231058struct ZigTypeInt {
......@@ -1167,6 +1202,7 @@ struct ZigTypeFn {
11671202 FnGenParamInfo *gen_param_info;
11681203
11691204 LLVMTypeRef raw_type_ref;
1205 ZigLLVMDIType *raw_di_type;
11701206
11711207 ZigType *bound_fn_parent;
11721208};
......@@ -1180,6 +1216,12 @@ struct ZigTypePromise {
11801216 ZigType *result_type;
11811217};
11821218
1219struct ZigTypeVector {
1220 // The type must be a pointer, integer, or float
1221 ZigType *elem_type;
1222 uint32_t len;
1223};
1224
11831225enum ZigTypeId {
11841226 ZigTypeIdInvalid,
11851227 ZigTypeIdMetaType,
......@@ -1206,6 +1248,7 @@ enum ZigTypeId {
12061248 ZigTypeIdArgTuple,
12071249 ZigTypeIdOpaque,
12081250 ZigTypeIdPromise,
1251 ZigTypeIdVector,
12091252};
12101253
12111254struct ZigType {
......@@ -1232,6 +1275,7 @@ struct ZigType {
12321275 ZigTypeFn fn;
12331276 ZigTypeBoundFn bound_fn;
12341277 ZigTypePromise promise;
1278 ZigTypeVector vector;
12351279 } data;
12361280
12371281 // use these fields to make sure we don't duplicate type table entries for the same type
......@@ -1385,6 +1429,7 @@ enum BuiltinFnId {
13851429 BuiltinFnIdEnumToInt,
13861430 BuiltinFnIdIntToEnum,
13871431 BuiltinFnIdIntType,
1432 BuiltinFnIdVectorType,
13881433 BuiltinFnIdSetCold,
13891434 BuiltinFnIdSetRuntimeSafety,
13901435 BuiltinFnIdSetFloatMode,
......@@ -1415,6 +1460,8 @@ enum BuiltinFnId {
14151460 BuiltinFnIdErrorReturnTrace,
14161461 BuiltinFnIdAtomicRmw,
14171462 BuiltinFnIdAtomicLoad,
1463 BuiltinFnIdBswap,
1464 BuiltinFnIdBitReverse,
14181465};
14191466
14201467struct BuiltinFnEntry {
......@@ -1441,6 +1488,7 @@ enum PanicMsgId {
14411488 PanicMsgIdBadUnionField,
14421489 PanicMsgIdBadEnumValue,
14431490 PanicMsgIdFloatToInt,
1491 PanicMsgIdPtrCastNull,
14441492
14451493 PanicMsgIdCount,
14461494};
......@@ -1455,11 +1503,12 @@ struct TypeId {
14551503 struct {
14561504 ZigType *child_type;
14571505 PtrLen ptr_len;
1458 bool is_const;
1459 bool is_volatile;
14601506 uint32_t alignment;
14611507 uint32_t bit_offset_in_host;
14621508 uint32_t host_int_bytes;
1509 bool is_const;
1510 bool is_volatile;
1511 bool allow_zero;
14631512 } pointer;
14641513 struct {
14651514 ZigType *child_type;
......@@ -1473,6 +1522,10 @@ struct TypeId {
14731522 ZigType *err_set_type;
14741523 ZigType *payload_type;
14751524 } error_union;
1525 struct {
1526 ZigType *elem_type;
1527 uint32_t len;
1528 } vector;
14761529 } data;
14771530};
14781531
......@@ -1487,8 +1540,12 @@ enum ZigLLVMFnId {
14871540 ZigLLVMFnIdFloor,
14881541 ZigLLVMFnIdCeil,
14891542 ZigLLVMFnIdSqrt,
1543 ZigLLVMFnIdBswap,
1544 ZigLLVMFnIdBitReverse,
14901545};
14911546
1547// There are a bunch of places in code that rely on these values being in
1548// exactly this order.
14921549enum AddSubMul {
14931550 AddSubMulAdd = 0,
14941551 AddSubMulSub = 1,
......@@ -1514,8 +1571,15 @@ struct ZigLLVMFnKey {
15141571 struct {
15151572 AddSubMul add_sub_mul;
15161573 uint32_t bit_count;
1574 uint32_t vector_len; // 0 means not a vector
15171575 bool is_signed;
15181576 } overflow_arithmetic;
1577 struct {
1578 uint32_t bit_count;
1579 } bswap;
1580 struct {
1581 uint32_t bit_count;
1582 } bit_reverse;
15191583 } data;
15201584};
15211585
......@@ -1600,7 +1664,7 @@ struct CodeGen {
16001664 HashMap<FnTypeId *, ZigType *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
16011665 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
16021666 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;
16041668 HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;
16051669 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names;
16061670 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
......@@ -1694,6 +1758,7 @@ struct CodeGen {
16941758 ZigFn *cur_fn;
16951759 ZigFn *main_fn;
16961760 ZigFn *panic_fn;
1761 TldFn *panic_tld_fn;
16971762 AstNode *root_export_decl;
16981763
16991764 CacheHash cache_hash;
......@@ -1746,12 +1811,12 @@ struct CodeGen {
17461811 BuildMode build_mode;
17471812 OutType out_type;
17481813 ZigTarget zig_target;
1814 TargetSubsystem subsystem;
17491815 bool is_static;
17501816 bool strip_debug_symbols;
17511817 bool is_test_build;
1818 bool is_single_threaded;
17521819 bool is_native_target;
1753 bool windows_subsystem_windows;
1754 bool windows_subsystem_console;
17551820 bool linker_rdynamic;
17561821 bool no_rosegment_workaround;
17571822 bool each_lib_rpath;
......@@ -1793,10 +1858,9 @@ enum VarLinkage {
17931858
17941859struct ZigVar {
17951860 Buf name;
1796 ConstExprValue *value;
1861 ConstExprValue *const_value;
1862 ZigType *var_type;
17971863 LLVMValueRef value_ref;
1798 bool src_is_const;
1799 bool gen_is_const;
18001864 IrInstruction *is_comptime;
18011865 // which node is the declaration of the variable
18021866 AstNode *decl_node;
......@@ -1806,17 +1870,22 @@ struct ZigVar {
18061870 Scope *parent_scope;
18071871 Scope *child_scope;
18081872 LLVMValueRef param_value_ref;
1809 bool shadowable;
18101873 size_t mem_slot_index;
18111874 IrExecutable *owner_exec;
18121875 size_t ref_count;
1813 VarLinkage linkage;
1814 uint32_t align_bytes;
18151876
18161877 // In an inline loop, multiple variables may be created,
18171878 // In this case, a reference to a variable should follow
18181879 // this pointer to the redefined variable.
18191880 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;
18201889};
18211890
18221891struct ErrorTableEntry {
......@@ -1882,10 +1951,11 @@ struct ScopeBlock {
18821951 ZigList<IrInstruction *> *incoming_values;
18831952 ZigList<IrBasicBlock *> *incoming_blocks;
18841953
1885 bool safety_off;
18861954 AstNode *safety_set_node;
1887 bool fast_math_on;
18881955 AstNode *fast_math_set_node;
1956
1957 bool safety_off;
1958 bool fast_math_on;
18891959};
18901960
18911961// This scope is created from every defer expression.
......@@ -2021,8 +2091,19 @@ struct IrBasicBlock {
20212091 IrInstruction *must_be_comptime_source_instr;
20222092};
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.
20242103enum IrInstructionId {
20252104 IrInstructionIdInvalid,
2105 IrInstructionIdDeclVarSrc,
2106 IrInstructionIdDeclVarGen,
20262107 IrInstructionIdBr,
20272108 IrInstructionIdCondBr,
20282109 IrInstructionIdSwitchBr,
......@@ -2031,7 +2112,6 @@ enum IrInstructionId {
20312112 IrInstructionIdPhi,
20322113 IrInstructionIdUnOp,
20332114 IrInstructionIdBinOp,
2034 IrInstructionIdDeclVar,
20352115 IrInstructionIdLoadPtr,
20362116 IrInstructionIdStorePtr,
20372117 IrInstructionIdFieldPtr,
......@@ -2060,7 +2140,7 @@ enum IrInstructionId {
20602140 IrInstructionIdAsm,
20612141 IrInstructionIdSizeOf,
20622142 IrInstructionIdTestNonNull,
2063 IrInstructionIdUnwrapOptional,
2143 IrInstructionIdOptionalUnwrapPtr,
20642144 IrInstructionIdOptionalWrap,
20652145 IrInstructionIdUnionTag,
20662146 IrInstructionIdClz,
......@@ -2076,7 +2156,8 @@ enum IrInstructionId {
20762156 IrInstructionIdCompileLog,
20772157 IrInstructionIdErrName,
20782158 IrInstructionIdEmbedFile,
2079 IrInstructionIdCmpxchg,
2159 IrInstructionIdCmpxchgSrc,
2160 IrInstructionIdCmpxchgGen,
20802161 IrInstructionIdFence,
20812162 IrInstructionIdTruncate,
20822163 IrInstructionIdIntCast,
......@@ -2085,6 +2166,7 @@ enum IrInstructionId {
20852166 IrInstructionIdFloatToInt,
20862167 IrInstructionIdBoolToInt,
20872168 IrInstructionIdIntType,
2169 IrInstructionIdVectorType,
20882170 IrInstructionIdBoolNot,
20892171 IrInstructionIdMemset,
20902172 IrInstructionIdMemcpy,
......@@ -2105,7 +2187,8 @@ enum IrInstructionId {
21052187 IrInstructionIdErrWrapPayload,
21062188 IrInstructionIdFnProto,
21072189 IrInstructionIdTestComptime,
2108 IrInstructionIdPtrCast,
2190 IrInstructionIdPtrCastSrc,
2191 IrInstructionIdPtrCastGen,
21092192 IrInstructionIdBitCast,
21102193 IrInstructionIdWidenOrShorten,
21112194 IrInstructionIdIntToPtr,
......@@ -2158,10 +2241,15 @@ enum IrInstructionId {
21582241 IrInstructionIdMergeErrRetTraces,
21592242 IrInstructionIdMarkErrRetTracePtr,
21602243 IrInstructionIdSqrt,
2244 IrInstructionIdBswap,
2245 IrInstructionIdBitReverse,
21612246 IrInstructionIdErrSetCast,
21622247 IrInstructionIdToBytes,
21632248 IrInstructionIdFromBytes,
21642249 IrInstructionIdCheckRuntimeScope,
2250 IrInstructionIdVectorToArray,
2251 IrInstructionIdArrayToVector,
2252 IrInstructionIdAssertZero,
21652253};
21662254
21672255struct IrInstruction {
......@@ -2183,6 +2271,22 @@ struct IrInstruction {
21832271 bool is_gen;
21842272};
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
21862290struct IrInstructionCondBr {
21872291 IrInstruction base;
21882292
......@@ -2291,20 +2395,11 @@ struct IrInstructionBinOp {
22912395 IrInstruction base;
22922396
22932397 IrInstruction *op1;
2294 IrBinOp op_id;
22952398 IrInstruction *op2;
2399 IrBinOp op_id;
22962400 bool safety_check_on;
22972401};
22982402
2299struct IrInstructionDeclVar {
2300 IrInstruction base;
2301
2302 ZigVar *var;
2303 IrInstruction *var_type;
2304 IrInstruction *align_value;
2305 IrInstruction *init_value;
2306};
2307
23082403struct IrInstructionLoadPtr {
23092404 IrInstruction base;
23102405
......@@ -2324,7 +2419,6 @@ struct IrInstructionFieldPtr {
23242419 IrInstruction *container_ptr;
23252420 Buf *field_name_buffer;
23262421 IrInstruction *field_name_expr;
2327 bool is_const;
23282422};
23292423
23302424struct IrInstructionStructFieldPtr {
......@@ -2367,13 +2461,13 @@ struct IrInstructionCall {
23672461 ZigFn *fn_entry;
23682462 size_t arg_count;
23692463 IrInstruction **args;
2370 bool is_comptime;
23712464 LLVMValueRef tmp_ptr;
2372 FnInline fn_inline;
2373 bool is_async;
23742465
23752466 IrInstruction *async_allocator;
23762467 IrInstruction *new_stack;
2468 FnInline fn_inline;
2469 bool is_async;
2470 bool is_comptime;
23772471};
23782472
23792473struct IrInstructionConst {
......@@ -2504,6 +2598,7 @@ struct IrInstructionPtrType {
25042598 PtrLen ptr_len;
25052599 bool is_const;
25062600 bool is_volatile;
2601 bool allow_zero;
25072602};
25082603
25092604struct IrInstructionPromiseType {
......@@ -2516,9 +2611,10 @@ struct IrInstructionSliceType {
25162611 IrInstruction base;
25172612
25182613 IrInstruction *align_value;
2614 IrInstruction *child_type;
25192615 bool is_const;
25202616 bool is_volatile;
2521 IrInstruction *child_type;
2617 bool allow_zero;
25222618};
25232619
25242620struct IrInstructionAsm {
......@@ -2546,10 +2642,12 @@ struct IrInstructionTestNonNull {
25462642 IrInstruction *value;
25472643};
25482644
2549struct IrInstructionUnwrapOptional {
2645// Takes a pointer to an optional value, returns a pointer
2646// to the payload.
2647struct IrInstructionOptionalUnwrapPtr {
25502648 IrInstruction base;
25512649
2552 IrInstruction *value;
2650 IrInstruction *base_ptr;
25532651 bool safety_check_on;
25542652};
25552653
......@@ -2640,7 +2738,7 @@ struct IrInstructionEmbedFile {
26402738 IrInstruction *name;
26412739};
26422740
2643struct IrInstructionCmpxchg {
2741struct IrInstructionCmpxchgSrc {
26442742 IrInstruction base;
26452743
26462744 IrInstruction *type_value;
......@@ -2650,14 +2748,19 @@ struct IrInstructionCmpxchg {
26502748 IrInstruction *success_order_value;
26512749 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
26582751 bool is_weak;
2752};
26592753
2754struct IrInstructionCmpxchgGen {
2755 IrInstruction base;
2756
2757 IrInstruction *ptr;
2758 IrInstruction *cmp_value;
2759 IrInstruction *new_value;
26602760 LLVMValueRef tmp_ptr;
2761 AtomicOrder success_order;
2762 AtomicOrder failure_order;
2763 bool is_weak;
26612764};
26622765
26632766struct IrInstructionFence {
......@@ -2737,6 +2840,13 @@ struct IrInstructionIntType {
27372840 IrInstruction *bit_count;
27382841};
27392842
2843struct IrInstructionVectorType {
2844 IrInstruction base;
2845
2846 IrInstruction *len;
2847 IrInstruction *elem_type;
2848};
2849
27402850struct IrInstructionBoolNot {
27412851 IrInstruction base;
27422852
......@@ -2840,7 +2950,7 @@ struct IrInstructionTestErr {
28402950struct IrInstructionUnwrapErrCode {
28412951 IrInstruction base;
28422952
2843 IrInstruction *value;
2953 IrInstruction *err_union;
28442954};
28452955
28462956struct IrInstructionUnwrapErrPayload {
......@@ -2888,11 +2998,19 @@ struct IrInstructionTestComptime {
28882998 IrInstruction *value;
28892999};
28903000
2891struct IrInstructionPtrCast {
3001struct IrInstructionPtrCastSrc {
28923002 IrInstruction base;
28933003
28943004 IrInstruction *dest_type;
28953005 IrInstruction *ptr;
3006 bool safety_check_on;
3007};
3008
3009struct IrInstructionPtrCastGen {
3010 IrInstruction base;
3011
3012 IrInstruction *ptr;
3013 bool safety_check_on;
28963014};
28973015
28983016struct IrInstructionBitCast {
......@@ -3251,6 +3369,39 @@ struct IrInstructionCheckRuntimeScope {
32513369 IrInstruction *is_comptime;
32523370};
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
32543405static const size_t slice_ptr_index = 0;
32553406static 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
2828static Error ATTRIBUTE_MUST_USE resolve_union_zero_bits(CodeGen *g, ZigType *union_type);
2929static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry);
3030
31ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
32 if (node->owner->c_import_node != nullptr) {
33 // if this happens, then translate_c generated code that
34 // failed semantic analysis, which isn't supposed to happen
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) {
31static ErrorMsg *add_error_note_token(CodeGen *g, ErrorMsg *parent_msg, ImportTableEntry *owner, Token *token,
32 Buf *msg)
33{
34 if (owner->c_import_node != nullptr) {
5335 // if this happens, then translate_c generated code that
5436 // 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
6446 return note;
6547 }
6648
67 ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column,
68 node->owner->source_code, node->owner->line_offsets, msg);
49 ErrorMsg *err = err_msg_create_with_line(owner->path, token->start_line, token->start_column,
50 owner->source_code, owner->line_offsets, msg);
6951
7052 err_msg_add_note(parent_msg, err);
7153 return err;
7254}
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
7489ZigType *new_type_table_entry(ZigTypeId id) {
7590 ZigType *entry = allocate<ZigType>(1);
7691 entry->id = id;
......@@ -250,6 +265,7 @@ AstNode *type_decl_node(ZigType *type_entry) {
250265 case ZigTypeIdBoundFn:
251266 case ZigTypeIdArgTuple:
252267 case ZigTypeIdPromise:
268 case ZigTypeIdVector:
253269 return nullptr;
254270 }
255271 zig_unreachable();
......@@ -311,6 +327,7 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
311327 case ZigTypeIdBoundFn:
312328 case ZigTypeIdArgTuple:
313329 case ZigTypeIdPromise:
330 case ZigTypeIdVector:
314331 return true;
315332 }
316333 zig_unreachable();
......@@ -339,6 +356,28 @@ uint64_t type_size(CodeGen *g, ZigType *type_entry) {
339356 }
340357 }
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
342381 return LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
343382}
344383
......@@ -400,9 +439,25 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {
400439 return entry;
401440}
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
403454ZigType *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)
405457{
458 // TODO when implementing https://github.com/ziglang/zig/issues/1953
459 // move this to a parameter
460 bool allow_zero = (ptr_len == PtrLenC);
406461 assert(!type_is_invalid(child_type));
407462 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
422477
423478 TypeId type_id = {};
424479 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) {
426481 type_id.id = ZigTypeIdPointer;
427482 type_id.data.pointer.child_type = child_type;
428483 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
431486 type_id.data.pointer.bit_offset_in_host = bit_offset_in_host;
432487 type_id.data.pointer.host_int_bytes = host_int_bytes;
433488 type_id.data.pointer.ptr_len = ptr_len;
489 type_id.data.pointer.allow_zero = allow_zero;
434490
435491 auto existing_entry = g->type_table.maybe_get(type_id);
436492 if (existing_entry)
......@@ -448,21 +504,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
448504
449505 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);
452508 const char *const_str = is_const ? "const " : "";
453509 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 }
454517 buf_resize(&entry->name, 0);
455518 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));
457521 } else if (host_int_bytes == 0) {
458 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment,
459 const_str, volatile_str, buf_ptr(&child_type->name));
522 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
523 const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
460524 } else if (byte_alignment == 0) {
461 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str,
462 bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));
525 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str,
526 bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
527 buf_ptr(&child_type->name));
463528 } else {
464 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment,
465 bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));
529 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
530 bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
531 buf_ptr(&child_type->name));
466532 }
467533
468534 assert(child_type->id != ZigTypeIdInvalid);
......@@ -470,7 +536,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
470536 entry->zero_bits = !type_has_bits(child_type);
471537
472538 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 {
474542 ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false,
475543 PtrLenSingle, 0, 0, host_int_bytes);
476544 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
504572 entry->data.pointer.explicit_alignment = byte_alignment;
505573 entry->data.pointer.bit_offset_in_host = bit_offset_in_host;
506574 entry->data.pointer.host_int_bytes = host_int_bytes;
575 entry->data.pointer.allow_zero = allow_zero;
507576
508577 if (parent_pointer) {
509578 *parent_pointer = entry;
......@@ -569,13 +638,16 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
569638 if (child_type->zero_bits) {
570639 entry->type_ref = LLVMInt1Type();
571640 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) {
573642 assert(child_type->di_type);
574643 // this is an optimization but also is necessary for calling C
575644 // functions where all pointers are maybe pointers
576645 // function types are technically pointers
577646 entry->type_ref = child_type->type_ref;
578647 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 }
579651 } else {
580652 assert(child_type->di_type);
581653 // 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) {
817889
818890 ZigType *child_type = ptr_type->data.pointer.child_type;
819891 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)
821893 {
822894 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
823895 PtrLenUnknown, 0, 0, 0);
......@@ -840,7 +912,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
840912 ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry;
841913 assert(child_ptr_type->id == ZigTypeIdPointer);
842914 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)
844916 {
845917 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
846918 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) {
10541126 }
10551127 if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
10561128 X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);
1057 if (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));
1129 return abi_class == X64CABIClass_MEMORY;
10621130 } else if (target_is_arm(&g->zig_target)) {
10631131 return type_size(g, fn_type_id->return_type) > 16;
10641132 }
......@@ -1219,7 +1287,10 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
12191287 fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref,
12201288 gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args);
12211289 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), "");
12231294 }
12241295
12251296 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
12741345 return entry;
12751346}
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{
12781351 size_t backward_branch_count = 0;
12791352 return ir_eval_const_value(g, scope, node, type_entry,
12801353 &backward_branch_count, default_backward_branch_quota,
1281 nullptr, nullptr, node, type_name, nullptr);
1354 nullptr, nullptr, node, type_name, nullptr, nullptr);
12821355}
12831356
12841357ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
1285 IrInstruction *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
1286 if (result->value.type->id == ZigTypeIdInvalid)
1358 ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
1359 if (type_is_invalid(result->type))
12871360 return g->builtin_types.entry_invalid;
12881361
1289 assert(result->value.special != ConstValSpecialRuntime);
1290 return result->value.data.x_type;
1362 assert(result->special != ConstValSpecialRuntime);
1363 return result->data.x_type;
12911364}
12921365
12931366ZigType *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
13381411}
13391412
13401413static 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);
1342 if (type_is_invalid(align_result->value.type))
1414 ConstExprValue *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);
1415 if (type_is_invalid(align_result->type))
13431416 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);
13461419 if (align_bytes == 0) {
13471420 add_node_error(g, node, buf_sprintf("alignment must be >= 1"));
13481421 return false;
......@@ -1360,12 +1433,12 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
13601433 ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
13611434 PtrLenUnknown, 0, 0, 0);
13621435 ZigType *str_type = get_slice_type(g, ptr_type);
1363 IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr);
1364 if (type_is_invalid(instr->value.type))
1436 ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr);
1437 if (type_is_invalid(result_val->type))
13651438 return false;
13661439
1367 ConstExprValue *ptr_field = &instr->value.data.x_struct.fields[slice_ptr_index];
1368 ConstExprValue *len_field = &instr->value.data.x_struct.fields[slice_len_index];
1440 ConstExprValue *ptr_field = &result_val->data.x_struct.fields[slice_ptr_index];
1441 ConstExprValue *len_field = &result_val->data.x_struct.fields[slice_len_index];
13691442
13701443 assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);
13711444 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) {
14181491 case ZigTypeIdPointer:
14191492 case ZigTypeIdArray:
14201493 case ZigTypeIdFn:
1494 case ZigTypeIdVector:
14211495 return true;
14221496 case ZigTypeIdStruct:
14231497 return type_entry->data.structure.layout == ContainerLayoutPacked;
......@@ -1434,7 +1508,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {
14341508 zig_unreachable();
14351509}
14361510
1437static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
1511bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
14381512 switch (type_entry->id) {
14391513 case ZigTypeIdInvalid:
14401514 zig_unreachable();
......@@ -1466,6 +1540,8 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
14661540 default:
14671541 return false;
14681542 }
1543 case ZigTypeIdVector:
1544 return type_allowed_in_extern(g, type_entry->data.vector.elem_type);
14691545 case ZigTypeIdFloat:
14701546 return true;
14711547 case ZigTypeIdArray:
......@@ -1619,6 +1695,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
16191695 case ZigTypeIdUnion:
16201696 case ZigTypeIdFn:
16211697 case ZigTypeIdPromise:
1698 case ZigTypeIdVector:
16221699 switch (type_requires_comptime(g, type_entry)) {
16231700 case ReqCompTimeNo:
16241701 break;
......@@ -1714,6 +1791,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
17141791 case ZigTypeIdUnion:
17151792 case ZigTypeIdFn:
17161793 case ZigTypeIdPromise:
1794 case ZigTypeIdVector:
17171795 switch (type_requires_comptime(g, fn_type_id.return_type)) {
17181796 case ReqCompTimeInvalid:
17191797 return g->builtin_types.entry_invalid;
......@@ -2500,20 +2578,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
25002578 // In this first pass we resolve explicit tag values.
25012579 // In a second pass we will fill in the unspecified ones.
25022580 if (tag_value != nullptr) {
2503 IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
2504 if (result_inst->value.type->id == ZigTypeIdInvalid) {
2581 ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
2582 if (type_is_invalid(result->type)) {
25052583 enum_type->data.enumeration.is_invalid = true;
25062584 continue;
25072585 }
2508 assert(result_inst->value.special != ConstValSpecialRuntime);
2509 assert(result_inst->value.type->id == ZigTypeIdInt ||
2510 result_inst->value.type->id == ZigTypeIdComptimeInt);
2511 auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);
2586 assert(result->special != ConstValSpecialRuntime);
2587 assert(result->type->id == ZigTypeIdInt ||
2588 result->type->id == ZigTypeIdComptimeInt);
2589 auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
25122590 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);
25142592 } else {
25152593 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
25182596 ErrorMsg *msg = add_node_error(g, tag_value,
25192597 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) {
26232701 buf_sprintf("enums, not structs, support field assignment"));
26242702 }
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
26262711 switch (type_requires_comptime(g, field_type)) {
26272712 case ReqCompTimeYes:
26282713 struct_type->data.structure.requires_comptime = true;
......@@ -2680,39 +2765,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
26802765 assert(decl_node->type == NodeTypeContainerDecl);
26812766 assert(struct_type->di_type);
26822767
2768 size_t field_count = struct_type->data.structure.src_field_count;
26832769 if (struct_type->data.structure.layout == ContainerLayoutPacked) {
26842770 struct_type->data.structure.abi_alignment = 1;
2685 }
2686
2687 size_t field_count = struct_type->data.structure.src_field_count;
2688 for (size_t i = 0; i < field_count; i += 1) {
2689 TypeStructField *field = &struct_type->data.structure.fields[i];
2690
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;
2771 for (size_t i = 0; i < field_count; i += 1) {
2772 TypeStructField *field = &struct_type->data.structure.fields[i];
2773 if (field->type_entry != nullptr && type_is_invalid(field->type_entry)) {
2774 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2775 break;
2776 }
26992777 }
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))
2702 continue;
2798 if (!type_has_bits(field->type_entry))
2799 continue;
27032800
2704 // alignment of structs is the alignment of the most-aligned field
2705 if (struct_type->data.structure.layout != ContainerLayoutPacked) {
27062801 if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) {
27072802 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
27082803 break;
27092804 }
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);
27122807 assert(this_field_align != 0);
2713 if (this_field_align > struct_type->data.structure.abi_alignment) {
2714 struct_type->data.structure.abi_alignment = this_field_align;
2715 }
2808 }
2809 // alignment of structs is the alignment of the most-aligned field
2810 if (this_field_align > struct_type->data.structure.abi_alignment) {
2811 struct_type->data.structure.abi_alignment = this_field_align;
27162812 }
27172813 }
27182814
......@@ -2790,7 +2886,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
27902886 union_type->data.unionation.have_explicit_tag_type = decl_node->data.container_decl.auto_enum ||
27912887 enum_type_node != nullptr;
27922888 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);
27942890 ZigType *tag_type;
27952891 bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety);
27962892 bool *covered_enum_fields;
......@@ -2896,6 +2992,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
28962992 }
28972993 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
28993002 switch (type_requires_comptime(g, field_type)) {
29003003 case ReqCompTimeInvalid:
29013004 union_type->data.unionation.is_invalid = true;
......@@ -2929,19 +3032,19 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
29293032 // In a second pass we will fill in the unspecified ones.
29303033 if (tag_value != nullptr) {
29313034 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);
2933 if (result_inst->value.type->id == ZigTypeIdInvalid) {
3035 ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
3036 if (type_is_invalid(result->type)) {
29343037 union_type->data.unionation.is_invalid = true;
29353038 continue;
29363039 }
2937 assert(result_inst->value.special != ConstValSpecialRuntime);
2938 assert(result_inst->value.type->id == ZigTypeIdInt);
2939 auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);
3040 assert(result->special != ConstValSpecialRuntime);
3041 assert(result->type->id == ZigTypeIdInt);
3042 auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
29403043 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);
29423045 } else {
29433046 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
29463049 ErrorMsg *msg = add_node_error(g, tag_value,
29473050 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
......@@ -3144,36 +3247,19 @@ static bool scope_is_root_decls(Scope *scope) {
31443247 zig_unreachable();
31453248}
31463249
3147static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, ZigType *fn_type) {
3148 add_node_error(g, proto_node,
3149 buf_sprintf("expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found '%s'",
3150 buf_ptr(&fn_type->name)));
3151}
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 }
3250void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn) {
3251 ConstExprValue *panic_fn_type_val = get_builtin_value(g, "PanicFn");
3252 assert(panic_fn_type_val != nullptr);
3253 assert(panic_fn_type_val->type->id == ZigTypeIdMetaType);
3254 ZigType *panic_fn_type = panic_fn_type_val->data.x_type;
31673255
3168 ZigType *optional_ptr_to_stack_trace_type = get_optional_type(g, get_ptr_to_stack_trace_type(g));
3169 if (fn_type_id->param_info[1].type != optional_ptr_to_stack_trace_type) {
3170 return wrong_panic_prototype(g, proto_node, fn_type);
3171 }
3256 AstNode *fake_decl = allocate<AstNode>(1);
3257 *fake_decl = *panic_fn->proto_node;
3258 fake_decl->type = NodeTypeSymbol;
3259 fake_decl->data.symbol_expr.symbol = &panic_fn->symbol_name;
31723260
3173 ZigType *actual_return_type = fn_type_id->return_type;
3174 if (actual_return_type != g->builtin_types.entry_unreachable) {
3175 return wrong_panic_prototype(g, proto_node, fn_type);
3176 }
3261 // call this for the side effects of casting to panic_fn_type
3262 analyze_const_value(g, tld_fn->base.parent_scope, fake_decl, panic_fn_type, nullptr);
31773263}
31783264
31793265ZigType *get_test_fn_type(CodeGen *g) {
......@@ -3191,14 +3277,12 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi
31913277 if (ccc) {
31923278 if (buf_eql_str(symbol_name, "main") && g->libc_link_lib != nullptr) {
31933279 g->have_c_main = true;
3194 g->windows_subsystem_windows = false;
3195 g->windows_subsystem_console = true;
3280 g->subsystem = TargetSubsystemConsole;
31963281 } else if (buf_eql_str(symbol_name, "WinMain") &&
31973282 g->zig_target.os == OsWindows)
31983283 {
31993284 g->have_winmain = true;
3200 g->windows_subsystem_windows = true;
3201 g->windows_subsystem_console = false;
3285 g->subsystem = TargetSubsystemWindows;
32023286 } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") &&
32033287 g->zig_target.os == OsWindows)
32043288 {
......@@ -3209,6 +3293,7 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi
32093293 g->have_dllmain_crt_startup = true;
32103294 }
32113295 }
3296
32123297 FnExport *fn_export = fn_table_entry->export_list.add_one();
32133298 memset(fn_export, 0, sizeof(FnExport));
32143299 buf_init_from_buf(&fn_export->name, symbol_name);
......@@ -3269,18 +3354,18 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
32693354 if (!fn_table_entry->type_entry->data.fn.is_generic) {
32703355 if (fn_def_node)
32713356 g->fn_defs.append(fn_table_entry);
3357 }
32723358
3273 if (scope_is_root_decls(tld_fn->base.parent_scope) &&
3274 (import == g->root_import || import->package == g->panic_package))
3359 if (scope_is_root_decls(tld_fn->base.parent_scope) &&
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"))
32753366 {
3276 if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) {
3277 g->main_fn = fn_table_entry;
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 }
3367 g->panic_fn = fn_table_entry;
3368 g->panic_tld_fn = tld_fn;
32843369 }
32853370 }
32863371 } else if (source_node->type == NodeTypeTestDecl) {
......@@ -3405,7 +3490,8 @@ void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) {
34053490 resolve_top_level_decl(g, tld, false, tld->source_node);
34063491 assert(tld->id == TldIdVar);
34073492 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;
34093495 tld_var->var->align_bytes = get_abi_alignment(g, value->type);
34103496}
34113497
......@@ -3499,7 +3585,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
34993585 case NodeTypeArrayType:
35003586 case NodeTypeErrorType:
35013587 case NodeTypeIfErrorExpr:
3502 case NodeTypeTestExpr:
3588 case NodeTypeIfOptional:
35033589 case NodeTypeErrorSetDecl:
35043590 case NodeTypeCancel:
35053591 case NodeTypeResume:
......@@ -3560,6 +3646,7 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
35603646 case ZigTypeIdFn:
35613647 case ZigTypeIdBoundFn:
35623648 case ZigTypeIdPromise:
3649 case ZigTypeIdVector:
35633650 return type_entry;
35643651 }
35653652 zig_unreachable();
......@@ -3568,13 +3655,15 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
35683655// Set name to nullptr to make the variable anonymous (not visible to programmer).
35693656// TODO merge with definition of add_local_var in ir.cpp
35703657ZigVar *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)
35723659{
35733660 Error err;
3574 assert(value);
3661 assert(const_value != nullptr);
3662 assert(var_type != nullptr);
35753663
35763664 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;
35783667 variable_entry->parent_scope = parent_scope;
35793668 variable_entry->shadowable = false;
35803669 variable_entry->mem_slot_index = SIZE_MAX;
......@@ -3583,23 +3672,23 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
35833672 assert(name);
35843673 buf_init_from_buf(&variable_entry->name, name);
35853674
3586 if ((err = type_resolve(g, value->type, ResolveStatusAlignmentKnown))) {
3587 variable_entry->value->type = g->builtin_types.entry_invalid;
3675 if ((err = type_resolve(g, var_type, ResolveStatusAlignmentKnown))) {
3676 variable_entry->var_type = g->builtin_types.entry_invalid;
35883677 } else {
3589 variable_entry->align_bytes = get_abi_alignment(g, value->type);
3678 variable_entry->align_bytes = get_abi_alignment(g, var_type);
35903679
35913680 ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr);
35923681 if (existing_var && !existing_var->shadowable) {
35933682 ErrorMsg *msg = add_node_error(g, source_node,
35943683 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
35953684 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;
35973686 } else {
35983687 ZigType *type;
35993688 if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) {
36003689 add_node_error(g, source_node,
36013690 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;
36033692 } else {
36043693 Scope *search_scope = nullptr;
36053694 if (src_tld == nullptr) {
......@@ -3613,7 +3702,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
36133702 ErrorMsg *msg = add_node_error(g, source_node,
36143703 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
36153704 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;
36173706 }
36183707 }
36193708 }
......@@ -3645,6 +3734,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
36453734 bool is_const = var_decl->is_const;
36463735 bool is_extern = var_decl->is_extern;
36473736 bool is_export = var_decl->is_export;
3737 bool is_thread_local = var_decl->threadlocal_tok != nullptr;
36483738
36493739 ZigType *explicit_type = nullptr;
36503740 if (var_decl->type) {
......@@ -3663,7 +3753,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
36633753 linkage = VarLinkageInternal;
36643754 }
36653755
3666 IrInstruction *init_value = nullptr;
3756 ConstExprValue *init_value = nullptr;
36673757
36683758 // TODO more validation for types that can't be used for export/extern variables
36693759 ZigType *implicit_type = nullptr;
......@@ -3672,7 +3762,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
36723762 } else if (var_decl->expr) {
36733763 init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol);
36743764 assert(init_value);
3675 implicit_type = init_value->value.type;
3765 implicit_type = init_value->type;
36763766
36773767 if (implicit_type->id == ZigTypeIdUnreachable) {
36783768 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) {
36903780 add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant"));
36913781 implicit_type = g->builtin_types.entry_invalid;
36923782 }
3693 assert(implicit_type->id == ZigTypeIdInvalid || init_value->value.special != ConstValSpecialRuntime);
3783 assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime);
36943784 } else if (linkage != VarLinkageExternal) {
36953785 add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
36963786 implicit_type = g->builtin_types.entry_invalid;
......@@ -3699,19 +3789,20 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
36993789 ZigType *type = explicit_type ? explicit_type : implicit_type;
37003790 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
37043794 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);
37063796 tld_var->var->linkage = linkage;
3797 tld_var->var->is_thread_local = is_thread_local;
37073798
37083799 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;
37103801 }
37113802
37123803 if (var_decl->align_expr != nullptr) {
37133804 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;
37153806 }
37163807 }
37173808
......@@ -3724,6 +3815,10 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
37243815 }
37253816 }
37263817
3818 if (is_thread_local && is_const) {
3819 add_node_error(g, source_node, buf_sprintf("threadlocal variable cannot be constant"));
3820 }
3821
37273822 g->global_vars.append(tld_var);
37283823}
37293824
......@@ -3924,6 +4019,7 @@ static bool is_container(ZigType *type_entry) {
39244019 case ZigTypeIdArgTuple:
39254020 case ZigTypeIdOpaque:
39264021 case ZigTypeIdPromise:
4022 case ZigTypeIdVector:
39274023 return false;
39284024 }
39294025 zig_unreachable();
......@@ -3983,6 +4079,7 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) {
39834079 case ZigTypeIdArgTuple:
39844080 case ZigTypeIdOpaque:
39854081 case ZigTypeIdPromise:
4082 case ZigTypeIdVector:
39864083 zig_unreachable();
39874084 }
39884085}
......@@ -3992,7 +4089,9 @@ ZigType *get_src_ptr_type(ZigType *type) {
39924089 if (type->id == ZigTypeIdFn) return type;
39934090 if (type->id == ZigTypeIdPromise) return type;
39944091 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 }
39964095 if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type;
39974096 if (type->data.maybe.child_type->id == ZigTypeIdPromise) return type->data.maybe.child_type;
39984097 }
......@@ -4006,6 +4105,10 @@ ZigType *get_codegen_ptr_type(ZigType *type) {
40064105 return ty;
40074106}
40084107
4108bool type_is_nonnull_ptr(ZigType *type) {
4109 return type_is_codegen_pointer(type) && !ptr_allows_addr_zero(type);
4110}
4111
40094112bool type_is_codegen_pointer(ZigType *type) {
40104113 return get_codegen_ptr_type(type) == type;
40114114}
......@@ -4076,7 +4179,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {
40764179 }
40774180
40784181 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);
40804183 var->src_arg_index = i;
40814184 fn_table_entry->child_scope = var->child_scope;
40824185 var->shadowable = var->shadowable || is_var_args;
......@@ -4214,18 +4317,17 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *
42144317 preview_use_decl(g, src_use_node);
42154318 }
42164319
4217 IrInstruction *use_target_value = src_use_node->data.use.value;
4218 if (use_target_value->value.type->id == ZigTypeIdInvalid) {
4320 ConstExprValue *use_target_value = src_use_node->data.use.value;
4321 if (type_is_invalid(use_target_value->type)) {
42194322 dst_use_node->owner->any_imports_failed = true;
42204323 return;
42214324 }
42224325
42234326 dst_use_node->data.use.resolution = TldResolutionOk;
42244327
4225 ConstExprValue *const_val = &use_target_value->value;
4226 assert(const_val->special != ConstValSpecialRuntime);
4328 assert(use_target_value->special != ConstValSpecialRuntime);
42274329
4228 ImportTableEntry *target_import = const_val->data.x_import;
4330 ImportTableEntry *target_import = use_target_value->data.x_import;
42294331 assert(target_import);
42304332
42314333 if (target_import->any_imports_failed) {
......@@ -4288,10 +4390,10 @@ void preview_use_decl(CodeGen *g, AstNode *node) {
42884390 }
42894391
42904392 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,
42924394 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))
42954397 node->owner->any_imports_failed = true;
42964398
42974399 node->data.use.value = result;
......@@ -4364,8 +4466,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *r
43644466 if (is_pub && ok_cc) {
43654467 if (buf_eql_str(proto_name, "main")) {
43664468 g->have_pub_main = true;
4367 g->windows_subsystem_windows = false;
4368 g->windows_subsystem_console = true;
4469 g->subsystem = TargetSubsystemConsole;
43694470 } else if (buf_eql_str(proto_name, "panic")) {
43704471 g->have_pub_panic = true;
43714472 }
......@@ -4434,6 +4535,43 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
44344535 return new_entry;
44354536}
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
44374575ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) {
44384576 return &g->builtin_types.entry_c_int[c_int_type];
44394577}
......@@ -4465,6 +4603,7 @@ bool handle_is_ptr(ZigType *type_entry) {
44654603 case ZigTypeIdFn:
44664604 case ZigTypeIdEnum:
44674605 case ZigTypeIdPromise:
4606 case ZigTypeIdVector:
44684607 return false;
44694608 case ZigTypeIdArray:
44704609 case ZigTypeIdStruct:
......@@ -4473,7 +4612,8 @@ bool handle_is_ptr(ZigType *type_entry) {
44734612 return type_has_bits(type_entry->data.error_union.payload_type);
44744613 case ZigTypeIdOptional:
44754614 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;
44774617 case ZigTypeIdUnion:
44784618 assert(type_entry->data.unionation.zero_bits_known);
44794619 if (type_entry->data.unionation.gen_field_count == 0)
......@@ -4580,8 +4720,7 @@ static Buf *get_posix_libc_include_path(void) {
45804720void find_libc_include_path(CodeGen *g) {
45814721 if (g->libc_include_dir == nullptr) {
45824722 if (!g->is_native_target) {
4583 fprintf(stderr, "Unable to determine libc include path. --libc-include-dir");
4584 exit(1);
4723 return;
45854724 }
45864725
45874726 if (g->zig_target.os == OsWindows) {
......@@ -4720,6 +4859,11 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {
47204859 return true;
47214860}
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
47234867static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
47244868 uint32_t hash_val = 0;
47254869 switch (const_val->data.x_ptr.mut) {
......@@ -4751,6 +4895,18 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
47514895 hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val);
47524896 hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index);
47534897 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;
47544910 case ConstPtrSpecialHardCodedAddr:
47554911 hash_val += (uint32_t)4048518294;
47564912 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) {
47624918 hash_val += (uint32_t)2590901619;
47634919 hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry);
47644920 return hash_val;
4921 case ConstPtrSpecialNull:
4922 hash_val += (uint32_t)1486246455;
4923 return hash_val;
47654924 }
47664925 zig_unreachable();
47674926}
......@@ -4860,7 +5019,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
48605019 return 2709806591;
48615020 case ZigTypeIdOptional:
48625021 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;
48645025 } else {
48655026 if (const_val->data.x_optional) {
48665027 return hash_const_val(const_val->data.x_optional) * 1992916303;
......@@ -4872,10 +5033,12 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
48725033 // TODO better hashing algorithm
48735034 return 3415065496;
48745035 case ZigTypeIdErrorSet:
4875 assert(const_val->data.x_err_set != nullptr);
4876 return const_val->data.x_err_set->value ^ 2630160122;
5036 return hash_const_val_error_set(const_val);
48775037 case ZigTypeIdNamespace:
48785038 return hash_ptr(const_val->data.x_import);
5039 case ZigTypeIdVector:
5040 // TODO better hashing algorithm
5041 return 3647867726;
48795042 case ZigTypeIdBoundFn:
48805043 case ZigTypeIdInvalid:
48815044 case ZigTypeIdUnreachable:
......@@ -4928,6 +5091,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
49285091 case ZigTypeIdBool:
49295092 case ZigTypeIdUnreachable:
49305093 case ZigTypeIdInt:
5094 case ZigTypeIdVector:
49315095 case ZigTypeIdFloat:
49325096 case ZigTypeIdComptimeFloat:
49335097 case ZigTypeIdComptimeInt:
......@@ -4975,7 +5139,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
49755139 return can_mutate_comptime_var_state(value->data.x_optional);
49765140
49775141 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)
49795143 return false;
49805144 assert(value->data.x_err_union.payload != nullptr);
49815145 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) {
50115175 case ZigTypeIdErrorSet:
50125176 case ZigTypeIdEnum:
50135177 case ZigTypeIdPointer:
5178 case ZigTypeIdVector:
50145179 return true;
50155180
50165181 case ZigTypeIdArray:
......@@ -5036,9 +5201,9 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) {
50365201 while (scope) {
50375202 if (scope->id == ScopeIdVarDecl) {
50385203 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))
50405205 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))
50425207 return false;
50435208 } else if (scope->id == ScopeIdFnDef) {
50445209 return true;
......@@ -5056,7 +5221,7 @@ uint32_t fn_eval_hash(Scope* scope) {
50565221 while (scope) {
50575222 if (scope->id == ScopeIdVarDecl) {
50585223 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
5059 result += hash_const_val(var_scope->var->value);
5224 result += hash_const_val(var_scope->var->const_value);
50605225 } else if (scope->id == ScopeIdFnDef) {
50615226 ScopeFnDef *fn_scope = (ScopeFnDef *)scope;
50625227 result += hash_ptr(fn_scope->fn_entry);
......@@ -5080,10 +5245,16 @@ bool fn_eval_eql(Scope *a, Scope *b) {
50805245 if (a->id == ScopeIdVarDecl) {
50815246 ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a;
50825247 ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b;
5083 if (a_var_scope->var->value->type != b_var_scope->var->value->type)
5084 return false;
5085 if (!const_values_equal(a->codegen, a_var_scope->var->value, b_var_scope->var->value))
5248 if (a_var_scope->var->var_type != b_var_scope->var->var_type)
50865249 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 }
50875258 } else if (a->id == ScopeIdFnDef) {
50885259 ScopeFnDef *a_fn_scope = (ScopeFnDef *)a;
50895260 ScopeFnDef *b_fn_scope = (ScopeFnDef *)b;
......@@ -5101,6 +5272,7 @@ bool fn_eval_eql(Scope *a, Scope *b) {
51015272 return false;
51025273}
51035274
5275// Whether the type has bits at runtime.
51045276bool type_has_bits(ZigType *type_entry) {
51055277 assert(type_entry);
51065278 assert(!type_is_invalid(type_entry));
......@@ -5108,6 +5280,66 @@ bool type_has_bits(ZigType *type_entry) {
51085280 return !type_entry->zero_bits;
51095281}
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
51115343ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
51125344 Error err;
51135345 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
......@@ -5147,6 +5379,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
51475379 case ZigTypeIdErrorSet:
51485380 case ZigTypeIdBool:
51495381 case ZigTypeIdInt:
5382 case ZigTypeIdVector:
51505383 case ZigTypeIdFloat:
51515384 case ZigTypeIdVoid:
51525385 case ZigTypeIdUnreachable:
......@@ -5562,6 +5795,33 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
55625795 if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index)
55635796 return false;
55645797 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;
55655825 case ConstPtrSpecialHardCodedAddr:
55665826 if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr)
55675827 return false;
......@@ -5570,10 +5830,34 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
55705830 return true;
55715831 case ConstPtrSpecialFunction:
55725832 return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry;
5833 case ConstPtrSpecialNull:
5834 return true;
55735835 }
55745836 zig_unreachable();
55755837}
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
55775861bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
55785862 assert(a->type->id == b->type->id);
55795863 assert(a->special == ConstValSpecialStatic);
......@@ -5628,28 +5912,12 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
56285912 case ZigTypeIdPointer:
56295913 case ZigTypeIdFn:
56305914 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);
56315918 case ZigTypeIdArray: {
56325919 assert(a->type->data.array.len == b->type->data.array.len);
5633 assert(a->data.x_array.special != ConstArraySpecialUndef);
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;
5920 return const_values_equal_array(g, a, b, a->type->data.array.len);
56535921 }
56545922 case ZigTypeIdStruct:
56555923 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
57386006 }
57396007}
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
57426017 switch (const_val->data.x_ptr.special) {
57436018 case ConstPtrSpecialInvalid:
57446019 zig_unreachable();
57456020 case ConstPtrSpecialRef:
57466021 case ConstPtrSpecialBaseStruct:
6022 case ConstPtrSpecialBaseErrorUnionCode:
6023 case ConstPtrSpecialBaseErrorUnionPayload:
6024 case ConstPtrSpecialBaseOptionalPayload:
57476025 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));
57496028 return;
57506029 case ConstPtrSpecialBaseArray:
57516030 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
57536032 return;
57546033 } else {
57556034 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));
57576037 return;
57586038 }
57596039 case ConstPtrSpecialHardCodedAddr:
......@@ -5769,6 +6049,56 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy
57696049 buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name));
57706050 return;
57716051 }
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 }
57726102 }
57736103 zig_unreachable();
57746104}
......@@ -5853,39 +6183,16 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
58536183 }
58546184 case ZigTypeIdPointer:
58556185 return render_const_val_ptr(g, buf, const_val, type_entry);
5856 case ZigTypeIdArray:
5857 switch (const_val->data.x_array.special) {
5858 case ConstArraySpecialUndef:
5859 buf_append_str(buf, "undefined");
5860 return;
5861 case ConstArraySpecialBuf: {
5862 Buf *array_buf = const_val->data.x_array.data.s_buf;
5863 buf_append_char(buf, '"');
5864 for (size_t i = 0; i < buf_len(array_buf); i += 1) {
5865 uint8_t c = buf_ptr(array_buf)[i];
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();
6186 case ZigTypeIdArray: {
6187 uint64_t len = type_entry->data.array.len;
6188 render_const_val_array(g, buf, &type_entry->name, const_val, 0, len);
6189 return;
6190 }
6191 case ZigTypeIdVector: {
6192 uint32_t len = type_entry->data.vector.len;
6193 render_const_val_array(g, buf, &type_entry->name, const_val, 0, len);
6194 return;
6195 }
58896196 case ZigTypeIdNull:
58906197 {
58916198 buf_appendf(buf, "null");
......@@ -5900,6 +6207,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
59006207 {
59016208 if (get_codegen_ptr_type(const_val->type) != nullptr)
59026209 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);
59036212 if (const_val->data.x_optional) {
59046213 render_const_value(g, buf, const_val->data.x_optional);
59056214 } else {
......@@ -5925,7 +6234,24 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
59256234 }
59266235 case ZigTypeIdStruct:
59276236 {
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 }
59296255 return;
59306256 }
59316257 case ZigTypeIdEnum:
......@@ -5937,11 +6263,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
59376263 case ZigTypeIdErrorUnion:
59386264 {
59396265 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) {
59416268 render_const_value(g, buf, const_val->data.x_err_union.payload);
59426269 } else {
59436270 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));
59456272 }
59466273 buf_appendf(buf, ")");
59476274 return;
......@@ -5956,10 +6283,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
59566283 return;
59576284 }
59586285 case ZigTypeIdErrorSet:
5959 {
5960 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name));
5961 return;
5962 }
6286 return render_const_val_err_set(g, buf, const_val, type_entry);
59636287 case ZigTypeIdArgTuple:
59646288 {
59656289 buf_appendf(buf, "(args value)");
......@@ -6035,6 +6359,7 @@ uint32_t type_id_hash(TypeId x) {
60356359 ((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) +
60366360 (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +
60376361 (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) +
6362 (x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) +
60386363 (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +
60396364 (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +
60406365 (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);
......@@ -6044,6 +6369,8 @@ uint32_t type_id_hash(TypeId x) {
60446369 case ZigTypeIdInt:
60456370 return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) +
60466371 (((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);
60476374 }
60486375 zig_unreachable();
60496376}
......@@ -6083,6 +6410,7 @@ bool type_id_eql(TypeId a, TypeId b) {
60836410 a.data.pointer.ptr_len == b.data.pointer.ptr_len &&
60846411 a.data.pointer.is_const == b.data.pointer.is_const &&
60856412 a.data.pointer.is_volatile == b.data.pointer.is_volatile &&
6413 a.data.pointer.allow_zero == b.data.pointer.allow_zero &&
60866414 a.data.pointer.alignment == b.data.pointer.alignment &&
60876415 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&
60886416 a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes;
......@@ -6092,6 +6420,9 @@ bool type_id_eql(TypeId a, TypeId b) {
60926420 case ZigTypeIdInt:
60936421 return a.data.integer.is_signed == b.data.integer.is_signed &&
60946422 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;
60956426 }
60966427 zig_unreachable();
60976428}
......@@ -6110,10 +6441,15 @@ uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey x) {
61106441 return (uint32_t)(x.data.floating.bit_count) * (uint32_t)1953839089;
61116442 case ZigLLVMFnIdSqrt:
61126443 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;
61136448 case ZigLLVMFnIdOverflowArithmetic:
61146449 return ((uint32_t)(x.data.overflow_arithmetic.bit_count) * 87135777) +
61156450 ((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;
61176453 }
61186454 zig_unreachable();
61196455}
......@@ -6128,6 +6464,10 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
61286464 return a.data.clz.bit_count == b.data.clz.bit_count;
61296465 case ZigLLVMFnIdPopCount:
61306466 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;
61316471 case ZigLLVMFnIdFloor:
61326472 case ZigLLVMFnIdCeil:
61336473 case ZigLLVMFnIdSqrt:
......@@ -6135,31 +6475,42 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
61356475 case ZigLLVMFnIdOverflowArithmetic:
61366476 return (a.data.overflow_arithmetic.bit_count == b.data.overflow_arithmetic.bit_count) &&
61376477 (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);
61396480 }
61406481 zig_unreachable();
61416482}
61426483
61436484// Canonicalize the array value as ConstArraySpecialNone
61446485void 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 }
61466501 switch (const_val->data.x_array.special) {
61476502 case ConstArraySpecialNone:
61486503 return;
61496504 case ConstArraySpecialUndef: {
61506505 const_val->data.x_array.special = ConstArraySpecialNone;
6151 size_t elem_count = const_val->type->data.array.len;
61526506 const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count);
61536507 for (size_t i = 0; i < elem_count; i += 1) {
61546508 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;
61566510 init_const_undefined(g, element_val);
6157 ConstParent *parent = get_const_val_parent(g, element_val);
6158 if (parent != nullptr) {
6159 parent->id = ConstParentIdArray;
6160 parent->data.p_array.array_val = const_val;
6161 parent->data.p_array.elem_index = i;
6162 }
6511 element_val->parent.id = ConstParentIdArray;
6512 element_val->parent.data.p_array.array_val = const_val;
6513 element_val->parent.data.p_array.elem_index = i;
61636514 }
61646515 return;
61656516 }
......@@ -6170,7 +6521,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
61706521 g->string_literals_table.maybe_remove(buf);
61716522
61726523 const_val->data.x_array.special = ConstArraySpecialNone;
6173 size_t elem_count = const_val->type->data.array.len;
61746524 assert(elem_count == buf_len(buf));
61756525 const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count);
61766526 for (size_t i = 0; i < elem_count; i += 1) {
......@@ -6178,6 +6528,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
61786528 this_char->special = ConstValSpecialStatic;
61796529 this_char->type = g->builtin_types.entry_u8;
61806530 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;
61816534 }
61826535 return;
61836536 }
......@@ -6185,18 +6538,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
61856538 zig_unreachable();
61866539}
61876540
6541// Deprecated. Reference the parent field directly.
61886542ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {
6189 assert(value->type);
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;
6543 return &value->parent;
62006544}
62016545
62026546static const ZigTypeId all_type_ids[] = {
......@@ -6224,6 +6568,7 @@ static const ZigTypeId all_type_ids[] = {
62246568 ZigTypeIdArgTuple,
62256569 ZigTypeIdOpaque,
62266570 ZigTypeIdPromise,
6571 ZigTypeIdVector,
62276572};
62286573
62296574ZigTypeId type_id_at_index(size_t index) {
......@@ -6289,6 +6634,8 @@ size_t type_id_index(ZigType *entry) {
62896634 return 22;
62906635 case ZigTypeIdPromise:
62916636 return 23;
6637 case ZigTypeIdVector:
6638 return 24;
62926639 }
62936640 zig_unreachable();
62946641}
......@@ -6345,6 +6692,8 @@ const char *type_id_name(ZigTypeId id) {
63456692 return "Opaque";
63466693 case ZigTypeIdPromise:
63476694 return "Promise";
6695 case ZigTypeIdVector:
6696 return "Vector";
63486697 }
63496698 zig_unreachable();
63506699}
......@@ -6361,7 +6710,7 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {
63616710 if (is_libc && g->libc_link_lib != nullptr)
63626711 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) {
63656714 fprintf(stderr, "TODO linking against libc is currently incompatible with `--cache on`.\n"
63666715 "Zig is not yet capable of determining whether the libc installation has changed on subsequent builds.\n");
63676716 exit(1);
......@@ -6424,7 +6773,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
64246773 resolve_top_level_decl(codegen, tld, false, nullptr);
64256774 assert(tld->id == TldIdVar);
64266775 TldVar *tld_var = (TldVar *)tld;
6427 ConstExprValue *var_value = tld_var->var->value;
6776 ConstExprValue *var_value = tld_var->var->const_value;
64286777 assert(var_value != nullptr);
64296778 return var_value;
64306779}
......@@ -6500,6 +6849,7 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {
65006849 case ZigTypeIdBool:
65016850 return X64CABIClass_INTEGER;
65026851 case ZigTypeIdFloat:
6852 case ZigTypeIdVector:
65036853 return X64CABIClass_SSE;
65046854 case ZigTypeIdStruct: {
65056855 // "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
65796929 LLVMTypeRef field_type = LLVMStructGetTypeAtIndex(struct_type->type_ref, field->gen_index);
65806930 return LLVMStoreSizeOfType(g->target_data_ref, field_type);
65816931}
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 @@
1212
1313void semantic_analyze(CodeGen *g);
1414ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);
15ErrorMsg *add_token_error(CodeGen *g, ImportTableEntry *owner, Token *token, Buf *msg);
1516ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg);
1617ZigType *new_type_table_entry(ZigTypeId id);
1718ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const);
1819ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
1920 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count);
2021uint64_t type_size(CodeGen *g, ZigType *type_entry);
22uint64_t type_size_store(CodeGen *g, ZigType *type_entry);
2123uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);
2224ZigType *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);
2326ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
2427ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type);
2528ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
......@@ -42,7 +45,9 @@ void find_libc_include_path(CodeGen *g);
4245void find_libc_lib_path(CodeGen *g);
4346
4447bool type_has_bits(ZigType *type_entry);
45
48bool 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
4752ImportTableEntry *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);
7378bool is_ref(ZigType *type_entry);
7479bool is_array_ref(ZigType *type_entry);
7580bool is_container_ref(ZigType *type_entry);
81bool is_valid_vector_elem_type(ZigType *elem_type);
7682void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
7783void scan_import(CodeGen *g, ImportTableEntry *import);
7884void preview_use_decl(CodeGen *g, AstNode *node);
......@@ -81,7 +87,7 @@ ZigFn *scope_fn_entry(Scope *scope);
8187ImportTableEntry *get_scope_import(Scope *scope);
8288void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope);
8389ZigVar *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);
8591ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);
8692ZigFn *create_fn(CodeGen *g, AstNode *proto_node);
8793ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);
......@@ -212,6 +218,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);
212218X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);
213219bool type_is_c_abi_int(CodeGen *g, ZigType *ty);
214220bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);
221const char *container_string(ContainerKind kind);
215222
216223uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field);
217224
......@@ -222,4 +229,15 @@ enum ReqCompTime {
222229};
223230ReqCompTime 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);
225243#endif
src/ast_render.cpp+24-18
......@@ -132,13 +132,23 @@ static const char *const_or_var_string(bool is_const) {
132132 return is_const ? "const" : "var";
133133}
134134
135const char *container_string(ContainerKind kind) {
136 switch (kind) {
137 case ContainerKindEnum: return "enum";
138 case ContainerKindStruct: return "struct";
139 case ContainerKindUnion: return "union";
135static const char *thread_local_string(Token *tok) {
136 return (tok == nullptr) ? "" : "threadlocal ";
137}
138
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();
140151 }
141 zig_unreachable();
142152}
143153
144154static const char *node_type_str(NodeType node_type) {
......@@ -233,8 +243,8 @@ static const char *node_type_str(NodeType node_type) {
233243 return "ErrorType";
234244 case NodeTypeIfErrorExpr:
235245 return "IfErrorExpr";
236 case NodeTypeTestExpr:
237 return "TestExpr";
246 case NodeTypeIfOptional:
247 return "IfOptional";
238248 case NodeTypeErrorSetDecl:
239249 return "ErrorSetDecl";
240250 case NodeTypeCancel:
......@@ -387,7 +397,7 @@ static bool statement_terminates_without_semicolon(AstNode *node) {
387397 if (node->data.if_err_expr.else_node)
388398 return statement_terminates_without_semicolon(node->data.if_err_expr.else_node);
389399 return node->data.if_err_expr.then_node->type == NodeTypeBlock;
390 case NodeTypeTestExpr:
400 case NodeTypeIfOptional:
391401 if (node->data.test_expr.else_node)
392402 return statement_terminates_without_semicolon(node->data.test_expr.else_node);
393403 return node->data.test_expr.then_node->type == NodeTypeBlock;
......@@ -554,8 +564,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
554564 {
555565 const char *pub_str = visib_mod_string(node->data.variable_declaration.visib_mod);
556566 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);
557568 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);
559570 print_symbol(ar, node->data.variable_declaration.symbol);
560571
561572 if (node->data.variable_declaration.type) {
......@@ -639,13 +650,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
639650 case NodeTypePointerType:
640651 {
641652 if (!grouped) fprintf(ar->f, "(");
642 const char *star = "[*]";
643 if (node->data.pointer_type.star_token != nullptr &&
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);
653 const char *ptr_len_str = token_to_ptr_len_str(node->data.pointer_type.star_token);
654 fprintf(ar->f, "%s", ptr_len_str);
649655 if (node->data.pointer_type.align_expr != nullptr) {
650656 fprintf(ar->f, "align(");
651657 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) {
974980 }
975981 break;
976982 }
977 case NodeTypeTestExpr:
983 case NodeTypeIfOptional:
978984 {
979985 fprintf(ar->f, "if (");
980986 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);
1717
1818void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size);
1919
20const char *container_string(ContainerKind kind);
21
2220#endif
23
src/bigint.cpp+1
......@@ -1722,3 +1722,4 @@ void bigint_incr(BigInt *x) {
17221722
17231723 bigint_add(x, &copy, &one);
17241724}
1725
src/cache_hash.cpp+3-13
......@@ -222,14 +222,9 @@ static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf, Buf *contents
222222 assert(chf->path != nullptr);
223223
224224 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)))
226226 return err;
227227
228 if ((err = os_file_mtime(this_file, &chf->mtime))) {
229 os_file_close(this_file);
230 return err;
231 }
232
233228 if ((err = hash_file(chf->bin_digest, this_file, contents))) {
234229 os_file_close(this_file);
235230 return err;
......@@ -351,17 +346,12 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
351346
352347 // if the mtime matches we can trust the digest
353348 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))) {
355351 fprintf(stderr, "Unable to open %s\n: %s", buf_ptr(chf->path), err_str(err));
356352 os_file_close(ch->manifest_file);
357353 return ErrorCacheUnavailable;
358354 }
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 }
365355 if (chf->mtime.sec == actual_mtime.sec && chf->mtime.nsec == actual_mtime.nsec) {
366356 os_file_close(this_file);
367357 } else {
src/codegen.cpp+686-296
......@@ -88,7 +88,7 @@ static const char *symbols_that_llvm_depends_on[] = {
8888};
8989
9090CodeGen *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)
9292{
9393 CodeGen *g = allocate<CodeGen>(1);
9494
......@@ -96,8 +96,12 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
9696
9797 g->zig_lib_dir = zig_lib_dir;
9898
99 g->zig_std_dir = buf_alloc();
100 os_path_join(zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir);
99 if (override_std_dir == nullptr) {
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
102106 g->zig_c_headers_dir = buf_alloc();
103107 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
118122 g->string_literals_table.init(16);
119123 g->type_info_cache.init(32);
120124 g->is_test_build = false;
125 g->is_single_threaded = false;
121126 buf_resize(&g->global_asm, 0);
122127
123128 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
178183
179184 // On Darwin/MacOS/iOS, we always link libSystem which contains libc.
180185 if (g->zig_target.os == OsMacOSX ||
181 g->zig_target.os == OsIOS)
186 g->zig_target.os == OsIOS ||
187 g->zig_target.os == OsFreeBSD)
182188 {
183189 g->libc_link_lib = create_link_lib(buf_create_from_str("c"));
184190 g->link_libs_list.append(g->libc_link_lib);
......@@ -291,11 +297,6 @@ void codegen_add_framework(CodeGen *g, const char *framework) {
291297 g->darwin_frameworks.append(buf_create_from_str(framework));
292298}
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
299300void codegen_set_mmacosx_version_min(CodeGen *g, Buf *mmacosx_version_min) {
300301 g->mmacosx_version_min = mmacosx_version_min;
301302}
......@@ -317,6 +318,8 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val, const char *
317318static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name);
318319static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name);
319320static 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
321324static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) {
322325 unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));
......@@ -465,6 +468,21 @@ static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkag
465468 }
466469}
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
468486static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
469487 if (fn_table_entry->llvm_value)
470488 return fn_table_entry->llvm_value;
......@@ -599,12 +617,13 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
599617 unsigned init_gen_i = 0;
600618 if (!type_has_bits(return_type)) {
601619 // nothing to do
602 } else if (type_is_codegen_pointer(return_type)) {
620 } else if (type_is_nonnull_ptr(return_type)) {
603621 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
604622 } 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
606624 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)) {
608627 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias");
609628 }
610629 init_gen_i = 1;
......@@ -619,6 +638,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
619638
620639 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
621640 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.
622643 addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull");
623644 }
624645
......@@ -653,7 +674,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
653674 ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder,
654675 fn_di_scope, buf_ptr(&fn_table_entry->symbol_name), "",
655676 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,
657678 is_definition, scope_line, flags, is_optimized, nullptr);
658679
659680 scope->di_scope = ZigLLVMSubprogramToScope(subprogram);
......@@ -697,38 +718,59 @@ static void clear_debug_source_node(CodeGen *g) {
697718 ZigLLVMClearCurrentDebugLocation(g->builder);
698719}
699720
700static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, ZigType *type_entry,
721static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, ZigType *operand_type,
701722 const char *signed_name, const char *unsigned_name)
702723{
724 ZigType *int_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
703725 char fn_name[64];
704726
705 assert(type_entry->id == ZigTypeIdInt);
706 const char *signed_str = type_entry->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);
727 assert(int_type->id == ZigTypeIdInt);
728 const char *signed_str = int_type->data.integral.is_signed ? signed_name : unsigned_name;
708729
709 LLVMTypeRef return_elem_types[] = {
710 type_entry->type_ref,
711 LLVMInt1Type(),
712 };
713730 LLVMTypeRef param_types[] = {
714 type_entry->type_ref,
715 type_entry->type_ref,
731 operand_type->type_ref,
732 operand_type->type_ref,
716733 };
717 LLVMTypeRef return_struct_type = LLVMStructType(return_elem_types, 2, false);
718 LLVMTypeRef fn_type = LLVMFunctionType(return_struct_type, param_types, 2, false);
719 LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type);
720 assert(LLVMGetIntrinsicID(fn_val));
721 return fn_val;
734
735 if (operand_type->id == ZigTypeIdVector) {
736 sprintf(fn_name, "llvm.%s.with.overflow.v%" PRIu32 "i%" PRIu32, signed_str,
737 operand_type->data.vector.len, int_type->data.integral.bit_count);
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 }
722761}
723762
724static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *type_entry, AddSubMul add_sub_mul) {
725 assert(type_entry->id == ZigTypeIdInt);
763static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *operand_type, AddSubMul add_sub_mul) {
764 ZigType *int_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
765 assert(int_type->id == ZigTypeIdInt);
726766
727767 ZigLLVMFnKey key = {};
728768 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;
730770 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
733775 auto existing_entry = g->llvm_fn_table.maybe_get(key);
734776 if (existing_entry)
......@@ -737,13 +779,13 @@ static LLVMValueRef get_int_overflow_fn(CodeGen *g, ZigType *type_entry, AddSubM
737779 LLVMValueRef fn_val;
738780 switch (add_sub_mul) {
739781 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");
741783 break;
742784 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");
744786 break;
745787 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");
747789 break;
748790 }
749791
......@@ -911,6 +953,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
911953 return buf_create_from_str("invalid enum value");
912954 case PanicMsgIdFloatToInt:
913955 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");
914958 }
915959 zig_unreachable();
916960}
......@@ -1205,6 +1249,8 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {
12051249 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
12061250 addLLVMFnAttr(fn_val, "nounwind");
12071251 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.
12081254 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
12091255 if (g->build_mode == BuildModeDebug) {
12101256 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");
......@@ -1279,9 +1325,13 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
12791325 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
12801326 addLLVMFnAttr(fn_val, "nounwind");
12811327 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.
12821330 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
12831331 addLLVMArgAttr(fn_val, (unsigned)0, "noalias");
12841332 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.
12851335 addLLVMArgAttr(fn_val, (unsigned)1, "nonnull");
12861336 addLLVMArgAttr(fn_val, (unsigned)1, "noalias");
12871337 addLLVMArgAttr(fn_val, (unsigned)1, "readonly");
......@@ -1409,6 +1459,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
14091459 LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
14101460 addLLVMFnAttr(fn_val, "nounwind");
14111461 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.
14121464 addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
14131465 if (g->build_mode == BuildModeDebug) {
14141466 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");
......@@ -1633,10 +1685,25 @@ static void add_bounds_check(CodeGen *g, LLVMValueRef target_val,
16331685 LLVMPositionBuilderAtEnd(g->builder, ok_block);
16341686}
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
16361702static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, ZigType *actual_type,
16371703 ZigType *wanted_type, LLVMValueRef expr_val)
16381704{
16391705 assert(actual_type->id == wanted_type->id);
1706 assert(expr_val != nullptr);
16401707
16411708 uint64_t actual_bits;
16421709 uint64_t wanted_bits;
......@@ -1689,17 +1756,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
16891756 if (!want_runtime_safety)
16901757 return nullptr;
16911758
1692 LLVMValueRef zero = LLVMConstNull(actual_type->type_ref);
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;
1759 return gen_assert_zero(g, expr_val, actual_type);
17031760 }
17041761 LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
17051762 if (!want_runtime_safety) {
......@@ -1729,17 +1786,49 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
17291786 }
17301787}
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,
17331799 LLVMValueRef val1, LLVMValueRef val2)
17341800{
1735 LLVMValueRef fn_val = get_int_overflow_fn(g, type_entry, op);
1736 LLVMValueRef params[] = {
1737 val1,
1738 val2,
1739 };
1740 LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, "");
1741 LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, "");
1742 LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, "");
1801 LLVMValueRef overflow_bit;
1802 LLVMValueRef result;
1803
1804 if (operand_type->id == ZigTypeIdVector) {
1805 ZigType *int_type = operand_type->data.vector.elem_type;
1806 assert(int_type->id == ZigTypeIdInt);
1807 LLVMTypeRef one_more_bit_int = LLVMIntType(int_type->data.integral.bit_count + 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
17431832 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowFail");
17441833 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowOk");
17451834 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) {
19071996}
19081997
19091998static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) {
1910 assert(alignment > 0);
19111999 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);
19132001 return result;
19142002}
19152003
......@@ -1967,14 +2055,14 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
19672055 break;
19682056 }
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 ||
19712059 ty->id == ZigTypeIdInt // TODO investigate if we need to change this
19722060 ) {
19732061 switch (fn_walk->id) {
19742062 case FnWalkIdAttrs: {
19752063 ZigType *ptr_type = get_codegen_ptr_type(ty);
19762064 if (ptr_type != nullptr) {
1977 if (ty->id != ZigTypeIdOptional) {
2065 if (type_is_nonnull_ptr(ty)) {
19782066 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
19792067 }
19802068 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_
20182106 assert(handle_is_ptr(ty));
20192107 switch (fn_walk->id) {
20202108 case FnWalkIdAttrs:
2109 // arrays passed to C ABI functions may not be at address 0
20212110 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
20222111 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
20232112 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_
20572146 case FnWalkIdAttrs:
20582147 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "byval");
20592148 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
2149 // Byvalue parameters must not have address 0
20602150 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
20612151 fn_walk->data.attrs.gen_i += 1;
20622152 break;
......@@ -2189,7 +2279,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
21892279 if ((param_type->id == ZigTypeIdPointer && param_type->data.pointer.is_const) || is_byval) {
21902280 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "readonly");
21912281 }
2192 if (param_type->id == ZigTypeIdPointer) {
2282 if (type_is_nonnull_ptr(param_type)) {
21932283 addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "nonnull");
21942284 }
21952285 break;
......@@ -2204,10 +2294,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
22042294 assert(variable);
22052295 assert(variable->value_ref);
22062296
2207 if (!handle_is_ptr(variable->value->type)) {
2297 if (!handle_is_ptr(variable->var_type)) {
22082298 clear_debug_source_node(g);
2209 gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index), variable->value_ref,
2210 variable->align_bytes, false);
2299 gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index),
2300 variable->value_ref, variable->align_bytes, false);
22112301 }
22122302
22132303 if (variable->decl_node) {
......@@ -2582,9 +2672,10 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
25822672 (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) ||
25832673 (op1->value.type->id == ZigTypeIdPointer &&
25842674 (op_id == IrBinOpAdd || op_id == IrBinOpSub) &&
2585 op1->value.type->data.pointer.ptr_len == PtrLenUnknown)
2675 op1->value.type->data.pointer.ptr_len != PtrLenSingle)
25862676 );
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
25892680 bool want_runtime_safety = bin_op_instruction->safety_check_on &&
25902681 ir_want_runtime_safety(g, &bin_op_instruction->base);
......@@ -2610,46 +2701,71 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
26102701 case IrBinOpCmpGreaterThan:
26112702 case IrBinOpCmpLessOrEq:
26122703 case IrBinOpCmpGreaterOrEq:
2613 if (type_entry->id == ZigTypeIdFloat) {
2704 if (scalar_type->id == ZigTypeIdFloat) {
26142705 ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
26152706 LLVMRealPredicate pred = cmp_op_to_real_predicate(op_id);
26162707 return LLVMBuildFCmp(g->builder, pred, op1_value, op2_value, "");
2617 } else if (type_entry->id == ZigTypeIdInt) {
2618 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, type_entry->data.integral.is_signed);
2708 } else if (scalar_type->id == ZigTypeIdInt) {
2709 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, scalar_type->data.integral.is_signed);
26192710 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
2620 } else if (type_entry->id == ZigTypeIdEnum ||
2621 type_entry->id == ZigTypeIdErrorSet ||
2622 type_entry->id == ZigTypeIdBool ||
2623 get_codegen_ptr_type(type_entry) != nullptr)
2711 } else if (scalar_type->id == ZigTypeIdEnum ||
2712 scalar_type->id == ZigTypeIdErrorSet ||
2713 scalar_type->id == ZigTypeIdBool ||
2714 get_codegen_ptr_type(scalar_type) != nullptr)
26242715 {
26252716 LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false);
26262717 return LLVMBuildICmp(g->builder, pred, op1_value, op2_value, "");
26272718 } else {
26282719 zig_unreachable();
26292720 }
2721 case IrBinOpMult:
2722 case IrBinOpMultWrap:
26302723 case IrBinOpAdd:
26312724 case IrBinOpAddWrap:
2632 if (type_entry->id == ZigTypeIdPointer) {
2633 assert(type_entry->data.pointer.ptr_len == PtrLenUnknown);
2725 case IrBinOpSub:
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
26342750 // TODO runtime safety
2635 return LLVMBuildInBoundsGEP(g->builder, op1_value, &op2_value, 1, "");
2636 } else if (type_entry->id == ZigTypeIdFloat) {
2751 return LLVMBuildInBoundsGEP(g->builder, op1_value, &subscript_value, 1, "");
2752 } else if (scalar_type->id == ZigTypeIdFloat) {
26372753 ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
2638 return LLVMBuildFAdd(g->builder, op1_value, op2_value, "");
2639 } else if (type_entry->id == ZigTypeIdInt) {
2640 bool is_wrapping = (op_id == IrBinOpAddWrap);
2754 return float_op[add_sub_mul](g->builder, op1_value, op2_value, "");
2755 } else if (scalar_type->id == ZigTypeIdInt) {
26412756 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, "");
26432758 } else if (want_runtime_safety) {
2644 return gen_overflow_op(g, type_entry, AddSubMulAdd, op1_value, op2_value);
2645 } else if (type_entry->data.integral.is_signed) {
2646 return LLVMBuildNSWAdd(g->builder, op1_value, op2_value, "");
2759 return gen_overflow_op(g, operand_type, add_sub_mul, op1_value, op2_value);
2760 } else if (scalar_type->data.integral.is_signed) {
2761 return signed_op[add_sub_mul](g->builder, op1_value, op2_value, "");
26472762 } else {
2648 return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, "");
2763 return unsigned_op[add_sub_mul](g->builder, op1_value, op2_value, "");
26492764 }
26502765 } else {
26512766 zig_unreachable();
26522767 }
2768 }
26532769 case IrBinOpBinOr:
26542770 return LLVMBuildOr(g->builder, op1_value, op2_value, "");
26552771 case IrBinOpBinXor:
......@@ -2659,15 +2775,14 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
26592775 case IrBinOpBitShiftLeftLossy:
26602776 case IrBinOpBitShiftLeftExact:
26612777 {
2662 assert(type_entry->id == ZigTypeIdInt);
2663 LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type,
2664 type_entry, op2_value);
2778 assert(scalar_type->id == ZigTypeIdInt);
2779 LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type, scalar_type, op2_value);
26652780 bool is_sloppy = (op_id == IrBinOpBitShiftLeftLossy);
26662781 if (is_sloppy) {
26672782 return LLVMBuildShl(g->builder, op1_value, op2_casted, "");
26682783 } else if (want_runtime_safety) {
2669 return gen_overflow_shl_op(g, type_entry, op1_value, op2_casted);
2670 } else if (type_entry->data.integral.is_signed) {
2784 return gen_overflow_shl_op(g, scalar_type, op1_value, op2_casted);
2785 } else if (scalar_type->data.integral.is_signed) {
26712786 return ZigLLVMBuildNSWShl(g->builder, op1_value, op2_casted, "");
26722787 } else {
26732788 return ZigLLVMBuildNUWShl(g->builder, op1_value, op2_casted, "");
......@@ -2676,85 +2791,41 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
26762791 case IrBinOpBitShiftRightLossy:
26772792 case IrBinOpBitShiftRightExact:
26782793 {
2679 assert(type_entry->id == ZigTypeIdInt);
2680 LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type,
2681 type_entry, op2_value);
2794 assert(scalar_type->id == ZigTypeIdInt);
2795 LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type, scalar_type, op2_value);
26822796 bool is_sloppy = (op_id == IrBinOpBitShiftRightLossy);
26832797 if (is_sloppy) {
2684 if (type_entry->data.integral.is_signed) {
2798 if (scalar_type->data.integral.is_signed) {
26852799 return LLVMBuildAShr(g->builder, op1_value, op2_casted, "");
26862800 } else {
26872801 return LLVMBuildLShr(g->builder, op1_value, op2_casted, "");
26882802 }
26892803 } else if (want_runtime_safety) {
2690 return gen_overflow_shr_op(g, type_entry, op1_value, op2_casted);
2691 } else if (type_entry->data.integral.is_signed) {
2804 return gen_overflow_shr_op(g, scalar_type, op1_value, op2_casted);
2805 } else if (scalar_type->data.integral.is_signed) {
26922806 return ZigLLVMBuildAShrExact(g->builder, op1_value, op2_casted, "");
26932807 } else {
26942808 return ZigLLVMBuildLShrExact(g->builder, op1_value, op2_casted, "");
26952809 }
26962810 }
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 }
27402811 case IrBinOpDivUnspecified:
27412812 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);
27432814 case IrBinOpDivExact:
27442815 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);
27462817 case IrBinOpDivTrunc:
27472818 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);
27492820 case IrBinOpDivFloor:
27502821 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);
27522823 case IrBinOpRemRem:
27532824 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);
27552826 case IrBinOpRemMod:
27562827 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);
27582829 }
27592830 zig_unreachable();
27602831}
......@@ -2882,32 +2953,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
28822953 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
29112956 return cast_instruction->tmp_ptr;
29122957 }
29132958 case CastOpIntToFloat:
......@@ -2991,14 +3036,29 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
29913036}
29923037
29933038static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
2994 IrInstructionPtrCast *instruction)
3039 IrInstructionPtrCastGen *instruction)
29953040{
29963041 ZigType *wanted_type = instruction->base.value.type;
29973042 if (!type_has_bits(wanted_type)) {
29983043 return nullptr;
29993044 }
30003045 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;
30023062}
30033063
30043064static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,
......@@ -3179,11 +3239,11 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI
31793239}
31803240
31813241static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
3182 IrInstructionDeclVar *decl_var_instruction)
3242 IrInstructionDeclVarGen *decl_var_instruction)
31833243{
31843244 ZigVar *var = decl_var_instruction->var;
31853245
3186 if (!type_has_bits(var->value->type))
3246 if (!type_has_bits(var->var_type))
31873247 return nullptr;
31883248
31893249 if (var->ref_count == 0 && g->build_mode != BuildModeDebug)
......@@ -3191,34 +3251,16 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
31913251
31923252 IrInstruction *init_value = decl_var_instruction->init_value;
31933253
3194 bool have_init_expr = false;
3195
3196 ConstExprValue *const_val = &init_value->value;
3197 if (const_val->special == ConstValSpecialRuntime || const_val->special == ConstValSpecialStatic)
3198 have_init_expr = true;
3254 bool have_init_expr = !value_is_all_undef(&init_value->value);
31993255
32003256 if (have_init_expr) {
3201 assert(var->value->type == init_value->value.type);
3202 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,
3257 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->var_type, false, false,
32033258 PtrLenSingle, var->align_bytes, 0, 0);
32043259 LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);
32053260 gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);
3206 } else {
3207 bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);
3208 if (want_safe) {
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 }
3261 } else if (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;
3263 gen_undef_init(g, align_bytes, var->var_type, var->value_ref);
32223264 }
32233265
32243266 gen_var_debug_decl(g, var);
......@@ -3255,21 +3297,81 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
32553297 return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, "");
32563298}
32573299
3258static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {
3259 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
3260 LLVMValueRef value = ir_llvm_value(g, instruction->value);
3300static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) {
3301 switch (const_val->data.x_array.special) {
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);
3263 ZigType *ptr_type = instruction->ptr->value.type;
3316static bool value_is_all_undef(ConstExprValue *const_val) {
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 }
32673369 return nullptr;
32683370}
32693371
32703372static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {
32713373 ZigVar *var = instruction->var;
3272 if (type_has_bits(var->value->type)) {
3374 if (type_has_bits(var->var_type)) {
32733375 assert(var->value_ref);
32743376 return var->value_ref;
32753377 } else {
......@@ -3583,7 +3685,8 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
35833685 LLVMPositionBuilderAtEnd(g->builder, ok_block);
35843686 }
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, "");
35873690 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, "");
35883691 return bitcasted_union_field_ptr;
35893692}
......@@ -3745,8 +3848,8 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR
37453848 if (child_type->zero_bits) {
37463849 return maybe_handle;
37473850 } else {
3748 bool maybe_is_ptr = type_is_codegen_pointer(child_type);
3749 if (maybe_is_ptr) {
3851 bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet;
3852 if (is_scalar) {
37503853 return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), "");
37513854 } else {
37523855 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
37613864 return gen_non_null_bit(g, instruction->value->value.type, ir_llvm_value(g, instruction->value));
37623865}
37633866
3764static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
3765 IrInstructionUnwrapOptional *instruction)
3867static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *executable,
3868 IrInstructionOptionalUnwrapPtr *instruction)
37663869{
3767 ZigType *ptr_type = instruction->value->value.type;
3870 ZigType *ptr_type = instruction->base_ptr->value.type;
37683871 assert(ptr_type->id == ZigTypeIdPointer);
37693872 ZigType *maybe_type = ptr_type->data.pointer.child_type;
37703873 assert(maybe_type->id == ZigTypeIdOptional);
37713874 ZigType *child_type = maybe_type->data.maybe.child_type;
3772 LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value);
3773 LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
3875 LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->base_ptr);
37743876 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);
37753878 LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);
37763879 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");
37773880 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");
......@@ -3785,8 +3888,8 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
37853888 if (child_type->zero_bits) {
37863889 return nullptr;
37873890 } else {
3788 bool maybe_is_ptr = type_is_codegen_pointer(child_type);
3789 if (maybe_is_ptr) {
3891 bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet;
3892 if (is_scalar) {
37903893 return maybe_ptr;
37913894 } else {
37923895 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
38143917 n_args = 1;
38153918 key.id = ZigLLVMFnIdPopCount;
38163919 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;
38173930 } else {
38183931 zig_unreachable();
38193932 }
......@@ -4194,7 +4307,7 @@ static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed)
41944307 zig_unreachable();
41954308}
41964309
4197static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchg *instruction) {
4310static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchgGen *instruction) {
41984311 LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr);
41994312 LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value);
42004313 LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value);
......@@ -4209,18 +4322,18 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
42094322 assert(maybe_type->id == ZigTypeIdOptional);
42104323 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)) {
42134326 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
42144327 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
42154328 return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(child_type->type_ref), payload_val, "");
42164329 }
42174330
42184331 assert(instruction->tmp_ptr != nullptr);
4219 assert(type_has_bits(instruction->type));
4332 assert(type_has_bits(child_type));
42204333
42214334 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
42224335 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
42254338 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
42264339 LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, "");
......@@ -4371,6 +4484,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
43714484 assert(array_type->data.structure.is_slice);
43724485 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
43734486 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
4487 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind);
43744488
43754489 size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index;
43764490 assert(ptr_index != SIZE_MAX);
......@@ -4560,12 +4674,14 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI
45604674 return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, "");
45614675}
45624676
4563static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) {
4564 ZigType *ptr_type = instruction->value->value.type;
4677static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable,
4678 IrInstructionUnwrapErrCode *instruction)
4679{
4680 ZigType *ptr_type = instruction->err_union->value.type;
45654681 assert(ptr_type->id == ZigTypeIdPointer);
45664682 ZigType *err_union_type = ptr_type->data.pointer.child_type;
45674683 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);
45694685 LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
45704686
45714687 if (type_has_bits(payload_type)) {
......@@ -4576,7 +4692,13 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab
45764692 }
45774693}
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;
45804702 ZigType *ptr_type = instruction->value->value.type;
45814703 assert(ptr_type->id == ZigTypeIdPointer);
45824704 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
45884710 return err_union_handle;
45894711 }
45904712
4591 if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->errors_by_index.length > 1) {
4713 if (want_safety) {
45924714 LLVMValueRef err_val;
45934715 if (type_has_bits(payload_type)) {
45944716 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
46274749 }
46284750
46294751 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) {
46314753 return payload_val;
46324754 }
46334755
......@@ -5098,6 +5220,74 @@ static LLVMValueRef ir_render_sqrt(CodeGen *g, IrExecutable *executable, IrInstr
50985220 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
50995221}
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
51015291static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
51025292 AstNode *source_node = instruction->source_node;
51035293 Scope *scope = instruction->scope;
......@@ -5137,6 +5327,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
51375327 case IrInstructionIdCUndef:
51385328 case IrInstructionIdEmbedFile:
51395329 case IrInstructionIdIntType:
5330 case IrInstructionIdVectorType:
51405331 case IrInstructionIdMemberCount:
51415332 case IrInstructionIdMemberType:
51425333 case IrInstructionIdMemberName:
......@@ -5173,12 +5364,15 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
51735364 case IrInstructionIdToBytes:
51745365 case IrInstructionIdEnumToInt:
51755366 case IrInstructionIdCheckRuntimeScope:
5367 case IrInstructionIdDeclVarSrc:
5368 case IrInstructionIdPtrCastSrc:
5369 case IrInstructionIdCmpxchgSrc:
51765370 zig_unreachable();
51775371
5372 case IrInstructionIdDeclVarGen:
5373 return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction);
51785374 case IrInstructionIdReturn:
51795375 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
5180 case IrInstructionIdDeclVar:
5181 return ir_render_decl_var(g, executable, (IrInstructionDeclVar *)instruction);
51825376 case IrInstructionIdBinOp:
51835377 return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);
51845378 case IrInstructionIdCast:
......@@ -5209,8 +5403,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
52095403 return ir_render_asm(g, executable, (IrInstructionAsm *)instruction);
52105404 case IrInstructionIdTestNonNull:
52115405 return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction);
5212 case IrInstructionIdUnwrapOptional:
5213 return ir_render_unwrap_maybe(g, executable, (IrInstructionUnwrapOptional *)instruction);
5406 case IrInstructionIdOptionalUnwrapPtr:
5407 return ir_render_optional_unwrap_ptr(g, executable, (IrInstructionOptionalUnwrapPtr *)instruction);
52145408 case IrInstructionIdClz:
52155409 return ir_render_clz(g, executable, (IrInstructionClz *)instruction);
52165410 case IrInstructionIdCtz:
......@@ -5225,8 +5419,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
52255419 return ir_render_ref(g, executable, (IrInstructionRef *)instruction);
52265420 case IrInstructionIdErrName:
52275421 return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction);
5228 case IrInstructionIdCmpxchg:
5229 return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchg *)instruction);
5422 case IrInstructionIdCmpxchgGen:
5423 return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchgGen *)instruction);
52305424 case IrInstructionIdFence:
52315425 return ir_render_fence(g, executable, (IrInstructionFence *)instruction);
52325426 case IrInstructionIdTruncate:
......@@ -5267,8 +5461,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
52675461 return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
52685462 case IrInstructionIdUnionInit:
52695463 return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
5270 case IrInstructionIdPtrCast:
5271 return ir_render_ptr_cast(g, executable, (IrInstructionPtrCast *)instruction);
5464 case IrInstructionIdPtrCastGen:
5465 return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction);
52725466 case IrInstructionIdBitCast:
52735467 return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction);
52745468 case IrInstructionIdWidenOrShorten:
......@@ -5335,6 +5529,16 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
53355529 return ir_render_mark_err_ret_trace_ptr(g, executable, (IrInstructionMarkErrRetTracePtr *)instruction);
53365530 case IrInstructionIdSqrt:
53375531 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);
53385542 }
53395543 zig_unreachable();
53405544}
......@@ -5362,6 +5566,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
53625566static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);
53635567static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);
53645568static 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
53665573static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {
53675574 switch (parent->id) {
......@@ -5372,6 +5579,12 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
53725579 case ConstParentIdStruct:
53735580 return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val,
53745581 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);
53755588 case ConstParentIdArray:
53765589 return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val,
53775590 parent->data.p_array.elem_index);
......@@ -5387,7 +5600,7 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
53875600
53885601static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) {
53895602 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;
53915604 LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);
53925605
53935606 LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr)));
......@@ -5412,7 +5625,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
54125625}
54135626
54145627static 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;
54165629 LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent);
54175630
54185631 ZigType *u32 = g->builtin_types.entry_u32;
......@@ -5423,8 +5636,44 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s
54235636 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
54245637}
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
54265675static 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;
54285677 LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent);
54295678
54305679 ZigType *u32 = g->builtin_types.entry_u32;
......@@ -5494,6 +5743,8 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
54945743 }
54955744 case ZigTypeIdArray:
54965745 zig_panic("TODO bit pack an array");
5746 case ZigTypeIdVector:
5747 zig_panic("TODO bit pack a vector");
54975748 case ZigTypeIdUnion:
54985749 zig_panic("TODO bit pack a union");
54995750 case ZigTypeIdStruct:
......@@ -5541,76 +5792,127 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
55415792 zig_unreachable();
55425793 case ConstPtrSpecialRef:
55435794 {
5544 render_const_val_global(g, const_val, name);
5795 assert(const_val->global_refs != nullptr);
55455796 ConstExprValue *pointee = const_val->data.x_ptr.data.ref.pointee;
55465797 render_const_val(g, pointee, "");
55475798 render_const_val_global(g, pointee, "");
5548 ConstExprValue *other_val = pointee;
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, "");
5799 const_val->global_refs->llvm_value = LLVMConstBitCast(pointee->global_refs->llvm_global, const_val->type->type_ref);
55515800 return const_val->global_refs->llvm_value;
55525801 }
55535802 case ConstPtrSpecialBaseArray:
55545803 {
5555 render_const_val_global(g, const_val, name);
5804 assert(const_val->global_refs != nullptr);
55565805 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;
55585806 assert(array_const_val->type->id == ZigTypeIdArray);
5559 if (array_const_val->type->zero_bits) {
5807 if (!type_has_bits(array_const_val->type)) {
55605808 // make this a null pointer
55615809 ZigType *usize = g->builtin_types.entry_usize;
55625810 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
55635811 const_val->type->type_ref);
5564 render_const_val_global(g, const_val, "");
55655812 return const_val->global_refs->llvm_value;
55665813 }
5567 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val,
5568 elem_index);
5814 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
5815 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, elem_index);
55695816 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
55705817 const_val->global_refs->llvm_value = ptr_val;
5571 render_const_val_global(g, const_val, "");
55725818 return ptr_val;
55735819 }
55745820 case ConstPtrSpecialBaseStruct:
55755821 {
5576 render_const_val_global(g, const_val, name);
5822 assert(const_val->global_refs != nullptr);
55775823 ConstExprValue *struct_const_val = const_val->data.x_ptr.data.base_struct.struct_val;
55785824 assert(struct_const_val->type->id == ZigTypeIdStruct);
5579 if (struct_const_val->type->zero_bits) {
5825 if (!type_has_bits(struct_const_val->type)) {
55805826 // make this a null pointer
55815827 ZigType *usize = g->builtin_types.entry_usize;
55825828 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
55835829 const_val->type->type_ref);
5584 render_const_val_global(g, const_val, "");
55855830 return const_val->global_refs->llvm_value;
55865831 }
55875832 size_t src_field_index = const_val->data.x_ptr.data.base_struct.field_index;
5588 size_t gen_field_index =
5589 struct_const_val->type->data.structure.fields[src_field_index].gen_index;
5833 size_t gen_field_index = struct_const_val->type->data.structure.fields[src_field_index].gen_index;
55905834 LLVMValueRef uncasted_ptr_val = gen_const_ptr_struct_recursive(g, struct_const_val,
55915835 gen_field_index);
55925836 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
55935837 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;
55955889 return ptr_val;
55965890 }
55975891 case ConstPtrSpecialHardCodedAddr:
55985892 {
5599 render_const_val_global(g, const_val, name);
5893 assert(const_val->global_refs != nullptr);
56005894 uint64_t addr_value = const_val->data.x_ptr.data.hard_coded_addr.addr;
56015895 ZigType *usize = g->builtin_types.entry_usize;
5602 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstInt(usize->type_ref, addr_value, false),
5603 const_val->type->type_ref);
5604 render_const_val_global(g, const_val, "");
5896 const_val->global_refs->llvm_value = LLVMConstIntToPtr(
5897 LLVMConstInt(usize->type_ref, addr_value, false), const_val->type->type_ref);
56055898 return const_val->global_refs->llvm_value;
56065899 }
56075900 case ConstPtrSpecialFunction:
56085901 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);
56095904 }
56105905 zig_unreachable();
56115906}
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
56135913static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) {
5914 Error err;
5915
56145916 ZigType *type_entry = const_val->type;
56155917 assert(!type_entry->zero_bits);
56165918
......@@ -5627,9 +5929,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
56275929 case ZigTypeIdInt:
56285930 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);
56295931 case ZigTypeIdErrorSet:
5630 assert(const_val->data.x_err_set != nullptr);
5631 return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref,
5632 const_val->data.x_err_set->value, false);
5932 return gen_const_val_err_set(g, const_val, name);
56335933 case ZigTypeIdFloat:
56345934 switch (type_entry->data.floating.bit_count) {
56355935 case 16:
......@@ -5663,6 +5963,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
56635963 return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false);
56645964 } else if (type_is_codegen_pointer(child_type)) {
56655965 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);
56665968 } else {
56675969 LLVMValueRef child_val;
56685970 LLVMValueRef maybe_val;
......@@ -5754,6 +6056,12 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
57546056 }
57556057 ConstExprValue *field_val = &const_val->data.x_struct.fields[i];
57566058 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
57576065 LLVMValueRef val = gen_const_val(g, field_val, "");
57586066 fields[type_struct_field->gen_index] = val;
57596067 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
57936101 return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf), true);
57946102 }
57956103 }
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 }
57966128 }
6129 zig_unreachable();
6130 }
57976131 case ZigTypeIdUnion:
57986132 {
57996133 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
58916225 ZigType *err_set_type = type_entry->data.error_union.err_set_type;
58926226 if (!type_has_bits(payload_type)) {
58936227 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;
58956230 return LLVMConstInt(g->err_tag_type->type_ref, value, false);
58966231 } else if (!type_has_bits(err_set_type)) {
58976232 assert(type_has_bits(payload_type));
......@@ -5900,8 +6235,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
59006235 LLVMValueRef err_tag_value;
59016236 LLVMValueRef err_payload_value;
59026237 bool make_unnamed_struct;
5903 if (const_val->data.x_err_union.err) {
5904 err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false);
6238 ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
6239 if (err_set != nullptr) {
6240 err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, err_set->value, false);
59056241 err_payload_value = LLVMConstNull(payload_type->type_ref);
59066242 make_unnamed_struct = false;
59076243 } else {
......@@ -6075,6 +6411,12 @@ static void validate_inline_fns(CodeGen *g) {
60756411 report_errors_and_maybe_exit(g);
60766412}
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
60786420static void do_code_gen(CodeGen *g) {
60796421 assert(!g->errors.length);
60806422
......@@ -6107,10 +6449,13 @@ static void do_code_gen(CodeGen *g) {
61076449 TldVar *tld_var = g->global_vars.at(i);
61086450 ZigVar *var = tld_var->var;
61096451
6110 if (var->value->type->id == ZigTypeIdComptimeFloat) {
6452 if (var->var_type->id == ZigTypeIdComptimeFloat) {
61116453 // Generate debug info for it but that's it.
6112 ConstExprValue *const_val = var->value;
6454 ConstExprValue *const_val = var->const_value;
61136455 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 }
61146459 ZigType *var_type = g->builtin_types.entry_f128;
61156460 ConstExprValue coerced_value;
61166461 coerced_value.special = ConstValSpecialStatic;
......@@ -6121,10 +6466,13 @@ static void do_code_gen(CodeGen *g) {
61216466 continue;
61226467 }
61236468
6124 if (var->value->type->id == ZigTypeIdComptimeInt) {
6469 if (var->var_type->id == ZigTypeIdComptimeInt) {
61256470 // Generate debug info for it but that's it.
6126 ConstExprValue *const_val = var->value;
6471 ConstExprValue *const_val = var->const_value;
61276472 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 }
61286476 size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint);
61296477 if (bits_needed < 8) {
61306478 bits_needed = 8;
......@@ -6135,7 +6483,7 @@ static void do_code_gen(CodeGen *g) {
61356483 continue;
61366484 }
61376485
6138 if (!type_has_bits(var->value->type))
6486 if (!type_has_bits(var->var_type))
61396487 continue;
61406488
61416489 assert(var->decl_node);
......@@ -6144,22 +6492,23 @@ static void do_code_gen(CodeGen *g) {
61446492 if (var->linkage == VarLinkageExternal) {
61456493 LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name));
61466494 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));
61486496 } 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));
61506498 // TODO debug info for the extern variable
61516499
61526500 LLVMSetLinkage(global_value, LLVMExternalLinkage);
61536501 maybe_import_dll(g, global_value, GlobalLinkageIdStrong);
61546502 LLVMSetAlignment(global_value, var->align_bytes);
61556503 LLVMSetGlobalConstant(global_value, var->gen_is_const);
6504 set_global_tls(g, var, global_value);
61566505 }
61576506 } else {
61586507 bool exported = (var->linkage == VarLinkageExport);
61596508 const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));
6160 render_const_val(g, var->value, mangled_name);
6161 render_const_val_global(g, var->value, mangled_name);
6162 global_value = var->value->global_refs->llvm_global;
6509 render_const_val(g, var->const_value, mangled_name);
6510 render_const_val_global(g, var->const_value, mangled_name);
6511 global_value = var->const_value->global_refs->llvm_global;
61636512
61646513 if (exported) {
61656514 LLVMSetLinkage(global_value, LLVMExternalLinkage);
......@@ -6171,11 +6520,14 @@ static void do_code_gen(CodeGen *g) {
61716520 LLVMSetAlignment(global_value, var->align_bytes);
61726521
61736522 // TODO debug info for function pointers
6174 if (var->gen_is_const && var->value->type->id != ZigTypeIdFn) {
6175 gen_global_var(g, var, var->value->global_refs->llvm_value, var->value->type);
6523 // Here we use const_value->type because that's the type of the llvm global,
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);
61766527 }
61776528
61786529 LLVMSetGlobalConstant(global_value, var->gen_is_const);
6530 set_global_tls(g, var, global_value);
61796531 }
61806532
61816533 var->value_ref = global_value;
......@@ -6226,6 +6578,7 @@ static void do_code_gen(CodeGen *g) {
62266578 IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i);
62276579 LLVMValueRef *slot;
62286580 ZigType *slot_type = instruction->value.type;
6581 uint32_t alignment_bytes = 0;
62296582 if (instruction->id == IrInstructionIdCast) {
62306583 IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction;
62316584 slot = &cast_instruction->tmp_ptr;
......@@ -6258,13 +6611,17 @@ static void do_code_gen(CodeGen *g) {
62586611 } else if (instruction->id == IrInstructionIdErrWrapCode) {
62596612 IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
62606613 slot = &err_wrap_code_instruction->tmp_ptr;
6261 } else if (instruction->id == IrInstructionIdCmpxchg) {
6262 IrInstructionCmpxchg *cmpxchg_instruction = (IrInstructionCmpxchg *)instruction;
6614 } else if (instruction->id == IrInstructionIdCmpxchgGen) {
6615 IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;
62636616 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;
62646621 } else {
62656622 zig_unreachable();
62666623 }
6267 *slot = build_alloca(g, slot_type, "", get_abi_alignment(g, slot_type));
6624 *slot = build_alloca(g, slot_type, "", alignment_bytes);
62686625 }
62696626
62706627 ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base);
......@@ -6281,12 +6638,12 @@ static void do_code_gen(CodeGen *g) {
62816638 for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {
62826639 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)) {
62856642 continue;
62866643 }
62876644 if (ir_get_var_is_comptime(var))
62886645 continue;
6289 switch (type_requires_comptime(g, var->value->type)) {
6646 switch (type_requires_comptime(g, var->var_type)) {
62906647 case ReqCompTimeInvalid:
62916648 zig_unreachable();
62926649 case ReqCompTimeYes:
......@@ -6296,11 +6653,11 @@ static void do_code_gen(CodeGen *g) {
62966653 }
62976654
62986655 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
63016658 var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
63026659 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
63056662 } else if (is_c_abi) {
63066663 fn_walk_var.data.vars.var = var;
......@@ -6310,16 +6667,16 @@ static void do_code_gen(CodeGen *g) {
63106667 ZigType *gen_type;
63116668 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)) {
63146671 if (gen_info->is_byval) {
6315 gen_type = var->value->type;
6672 gen_type = var->var_type;
63166673 } else {
63176674 gen_type = gen_info->type;
63186675 }
63196676 var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index);
63206677 } else {
6321 gen_type = var->value->type;
6322 var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);
6678 gen_type = var->var_type;
6679 var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
63236680 }
63246681 if (var->decl_node) {
63256682 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) {
67197076 create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
67207077 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
67217078 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
7079 create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);
67227080 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);
67237081 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);
67247082 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);
......@@ -6757,6 +7115,8 @@ static void define_builtin_fns(CodeGen *g) {
67577115 create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);
67587116 create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
67597117 create_builtin_fn(g, BuiltinFnIdThis, "This", 0);
7118 create_builtin_fn(g, BuiltinFnIdBswap, "bswap", 2);
7119 create_builtin_fn(g, BuiltinFnIdBitReverse, "bitreverse", 2);
67607120}
67617121
67627122static const char *bool_to_str(bool b) {
......@@ -6784,6 +7144,8 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
67847144 " instruction_addresses: []usize,\n"
67857145 "};\n\n");
67867146
7147 buf_append_str(contents, "pub const PanicFn = fn([]const u8, ?*StackTrace) noreturn;\n\n");
7148
67877149 const char *cur_os = nullptr;
67887150 {
67897151 buf_appendf(contents, "pub const Os = enum {\n");
......@@ -6942,6 +7304,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
69427304 " ArgTuple: void,\n"
69437305 " Opaque: void,\n"
69447306 " Promise: Promise,\n"
7307 " Vector: Vector,\n"
69457308 "\n\n"
69467309 " pub const Int = struct {\n"
69477310 " is_signed: bool,\n"
......@@ -6963,6 +7326,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
69637326 " One,\n"
69647327 " Many,\n"
69657328 " Slice,\n"
7329 " C,\n"
69667330 " };\n"
69677331 " };\n"
69687332 "\n"
......@@ -7060,6 +7424,11 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
70607424 " child: ?type,\n"
70617425 " };\n"
70627426 "\n"
7427 " pub const Vector = struct {\n"
7428 " len: u32,\n"
7429 " child: type,\n"
7430 " };\n"
7431 "\n"
70637432 " pub const Definition = struct {\n"
70647433 " name: []const u8,\n"
70657434 " is_pub: bool,\n"
......@@ -7128,6 +7497,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
71287497 buf_appendf(contents, "pub const endian = %s;\n", endian_str);
71297498 }
71307499 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));
71317501 buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);
71327502 buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);
71337503 buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ);
......@@ -7162,6 +7532,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
71627532 cache_buf(&cache_hash, compiler_id);
71637533 cache_int(&cache_hash, g->build_mode);
71647534 cache_bool(&cache_hash, g->is_test_build);
7535 cache_bool(&cache_hash, g->is_single_threaded);
71657536 cache_int(&cache_hash, g->zig_target.arch.arch);
71667537 cache_int(&cache_hash, g->zig_target.arch.sub_arch);
71677538 cache_int(&cache_hash, g->zig_target.vendor);
......@@ -7210,6 +7581,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
72107581 g->compile_var_package = new_package(buf_ptr(this_dir), builtin_zig_basename);
72117582 g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package);
72127583 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);
72137585 g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents);
72147586 scan_import(g, g->compile_var_import);
72157587
......@@ -7231,8 +7603,7 @@ static void init(CodeGen *g) {
72317603 }
72327604
72337605 if (g->is_test_build) {
7234 g->windows_subsystem_windows = false;
7235 g->windows_subsystem_console = true;
7606 g->subsystem = TargetSubsystemConsole;
72367607 }
72377608
72387609 assert(g->root_out_name);
......@@ -7251,7 +7622,13 @@ static void init(CodeGen *g) {
72517622 LLVMTargetRef target_ref;
72527623 char *err_msg = nullptr;
72537624 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);
72557632 }
72567633
72577634 bool is_optimized = g->build_mode != BuildModeDebug;
......@@ -7268,7 +7645,7 @@ static void init(CodeGen *g) {
72687645 // LLVM creates invalid binaries on Windows sometimes.
72697646 // See https://github.com/ziglang/zig/issues/508
72707647 // 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) {
72727649 target_specific_cpu_args = "";
72737650 target_specific_features = "";
72747651 } else {
......@@ -7434,9 +7811,9 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
74347811 ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i];
74357812 this_val->special = ConstValSpecialStatic;
74367813 this_val->type = struct_type;
7437 this_val->data.x_struct.parent.id = ConstParentIdArray;
7438 this_val->data.x_struct.parent.data.p_array.array_val = test_fn_array;
7439 this_val->data.x_struct.parent.data.p_array.elem_index = i;
7814 this_val->parent.id = ConstParentIdArray;
7815 this_val->parent.data.p_array.array_val = test_fn_array;
7816 this_val->parent.data.p_array.elem_index = i;
74407817 this_val->data.x_struct.fields = create_const_vals(2);
74417818
74427819 ConstExprValue *name_field = &this_val->data.x_struct.fields[0];
......@@ -7514,6 +7891,7 @@ static void gen_root_source(CodeGen *g) {
75147891 report_errors_and_maybe_exit(g);
75157892
75167893 if (!g->is_test_build && g->zig_target.os != OsFreestanding &&
7894 g->zig_target.os != OsUefi &&
75177895 !g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup &&
75187896 ((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe))
75197897 {
......@@ -7537,6 +7915,8 @@ static void gen_root_source(CodeGen *g) {
75377915 }
75387916 }
75397917
7918 typecheck_panic_fn(g, g->panic_tld_fn, g->panic_fn);
7919
75407920 report_errors_and_maybe_exit(g);
75417921
75427922}
......@@ -7631,6 +8011,9 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e
76318011 case ZigTypeIdArray:
76328012 prepend_c_type_to_decl_list(g, gen_h, type_entry->data.array.child_type);
76338013 return;
8014 case ZigTypeIdVector:
8015 prepend_c_type_to_decl_list(g, gen_h, type_entry->data.vector.elem_type);
8016 return;
76348017 case ZigTypeIdOptional:
76358018 prepend_c_type_to_decl_list(g, gen_h, type_entry->data.maybe.child_type);
76368019 return;
......@@ -7762,6 +8145,8 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu
77628145 buf_appendf(out_buf, "%s", buf_ptr(child_buf));
77638146 return;
77648147 }
8148 case ZigTypeIdVector:
8149 zig_panic("TODO implement get_c_type for vector types");
77658150 case ZigTypeIdErrorUnion:
77668151 case ZigTypeIdErrorSet:
77678152 case ZigTypeIdFn:
......@@ -7927,6 +8312,7 @@ static void gen_h_file(CodeGen *g) {
79278312 case ZigTypeIdOptional:
79288313 case ZigTypeIdFn:
79298314 case ZigTypeIdPromise:
8315 case ZigTypeIdVector:
79308316 zig_unreachable();
79318317 case ZigTypeIdEnum:
79328318 if (type_entry->data.enumeration.layout == ContainerLayoutExtern) {
......@@ -8033,8 +8419,12 @@ static void add_cache_pkg(CodeGen *g, CacheHash *ch, PackageTableEntry *pkg) {
80338419 if (!entry)
80348420 break;
80358421
8036 cache_buf(ch, entry->key);
8037 add_cache_pkg(g, ch, entry->value);
8422 // TODO: I think we need a more sophisticated detection of
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 }
80388428 }
80398429}
80408430
......@@ -8070,12 +8460,12 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
80708460 cache_int(ch, g->zig_target.os);
80718461 cache_int(ch, g->zig_target.env_type);
80728462 cache_int(ch, g->zig_target.oformat);
8463 cache_int(ch, g->subsystem);
80738464 cache_bool(ch, g->is_static);
80748465 cache_bool(ch, g->strip_debug_symbols);
80758466 cache_bool(ch, g->is_test_build);
8467 cache_bool(ch, g->is_single_threaded);
80768468 cache_bool(ch, g->is_native_target);
8077 cache_bool(ch, g->windows_subsystem_windows);
8078 cache_bool(ch, g->windows_subsystem_console);
80798469 cache_bool(ch, g->linker_rdynamic);
80808470 cache_bool(ch, g->no_rosegment_workaround);
80818471 cache_bool(ch, g->each_lib_rpath);
src/codegen.hpp+1-2
......@@ -15,7 +15,7 @@
1515#include <stdio.h>
1616
1717CodeGen *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
2020void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
2121void 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);
3333void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir);
3434void codegen_set_kernel32_lib_dir(CodeGen *codegen, Buf *kernel32_lib_dir);
3535void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker);
36void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole);
3736void codegen_add_lib_dir(CodeGen *codegen, const char *dir);
3837void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib);
3938LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib);
src/ir.cpp+2127-1051
......@@ -61,7 +61,7 @@ enum ConstCastResultId {
6161 ConstCastResultIdType,
6262 ConstCastResultIdUnresolvedInferredErrSet,
6363 ConstCastResultIdAsyncAllocatorType,
64 ConstCastResultIdNullWrapPtr
64 ConstCastResultIdBadAllowsZero,
6565};
6666
6767struct ConstCastOnly;
......@@ -83,6 +83,7 @@ struct ConstCastErrUnionErrSetMismatch;
8383struct ConstCastErrUnionPayloadMismatch;
8484struct ConstCastErrSetMismatch;
8585struct ConstCastTypeMismatch;
86struct ConstCastBadAllowsZero;
8687
8788struct ConstCastOnly {
8889 ConstCastResultId id;
......@@ -99,6 +100,7 @@ struct ConstCastOnly {
99100 ConstCastOnly *null_wrap_ptr_child;
100101 ConstCastArg fn_arg;
101102 ConstCastArgNoAlias arg_no_alias;
103 ConstCastBadAllowsZero *bad_allows_zero;
102104 } data;
103105};
104106
......@@ -141,6 +143,12 @@ struct ConstCastErrSetMismatch {
141143 ZigList<ErrorTableEntry *> missing_errors;
142144};
143145
146struct ConstCastBadAllowsZero {
147 ZigType *wanted_type;
148 ZigType *actual_type;
149};
150
151
144152enum UndefAllowed {
145153 UndefOk,
146154 UndefBad,
......@@ -159,13 +167,20 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op
159167static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval);
160168static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align);
161169static 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);
163171static 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,
165173 ConstExprValue *out_val, ConstExprValue *ptr_val);
166174static 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);
168176static 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
170185static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
171186 assert(get_src_ptr_type(const_val->type) != nullptr);
......@@ -177,15 +192,28 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
177192 case ConstPtrSpecialRef:
178193 result = const_val->data.x_ptr.data.ref.pointee;
179194 break;
180 case ConstPtrSpecialBaseArray:
181 expand_undef_array(g, 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[
183 const_val->data.x_ptr.data.base_array.elem_index];
195 case ConstPtrSpecialBaseArray: {
196 ConstExprValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
197 expand_undef_array(g, array_val);
198 result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];
184199 break;
200 }
185201 case ConstPtrSpecialBaseStruct:
186202 result = &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[
187203 const_val->data.x_ptr.data.base_struct.field_index];
188204 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;
189217 case ConstPtrSpecialHardCodedAddr:
190218 zig_unreachable();
191219 case ConstPtrSpecialDiscard:
......@@ -197,6 +225,11 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
197225 return result;
198226}
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
200233static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
201234 if (a == b)
202235 return true;
......@@ -207,15 +240,10 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
207240 if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr)
208241 return true;
209242
210 return false;
211}
243 if (is_opt_err_set(a) && is_opt_err_set(b))
244 return true;
212245
213ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {
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;
246 return false;
219247}
220248
221249static bool ir_should_inline(IrExecutable *exec, Scope *scope) {
......@@ -304,6 +332,14 @@ static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) {
304332 return new_bb;
305333}
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
307343static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) {
308344 return IrInstructionIdCondBr;
309345}
......@@ -336,10 +372,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) {
336372 return IrInstructionIdBinOp;
337373}
338374
339static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVar *) {
340 return IrInstructionIdDeclVar;
341}
342
343375static constexpr IrInstructionId ir_instruction_id(IrInstructionExport *) {
344376 return IrInstructionIdExport;
345377}
......@@ -448,8 +480,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestNonNull *) {
448480 return IrInstructionIdTestNonNull;
449481}
450482
451static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapOptional *) {
452 return IrInstructionIdUnwrapOptional;
483static constexpr IrInstructionId ir_instruction_id(IrInstructionOptionalUnwrapPtr *) {
484 return IrInstructionIdOptionalUnwrapPtr;
453485}
454486
455487static constexpr IrInstructionId ir_instruction_id(IrInstructionClz *) {
......@@ -516,8 +548,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) {
516548 return IrInstructionIdEmbedFile;
517549}
518550
519static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchg *) {
520 return IrInstructionIdCmpxchg;
551static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgSrc *) {
552 return IrInstructionIdCmpxchgSrc;
553}
554
555static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgGen *) {
556 return IrInstructionIdCmpxchgGen;
521557}
522558
523559static constexpr IrInstructionId ir_instruction_id(IrInstructionFence *) {
......@@ -564,6 +600,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionIntType *) {
564600 return IrInstructionIdIntType;
565601}
566602
603static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorType *) {
604 return IrInstructionIdVectorType;
605}
606
567607static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) {
568608 return IrInstructionIdBoolNot;
569609}
......@@ -648,8 +688,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *)
648688 return IrInstructionIdTestComptime;
649689}
650690
651static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) {
652 return IrInstructionIdPtrCast;
691static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastSrc *) {
692 return IrInstructionIdPtrCastSrc;
693}
694
695static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastGen *) {
696 return IrInstructionIdPtrCastGen;
653697}
654698
655699static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {
......@@ -856,10 +900,30 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSqrt *) {
856900 return IrInstructionIdSqrt;
857901}
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
859911static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScope *) {
860912 return IrInstructionIdCheckRuntimeScope;
861913}
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
863927template<typename T>
864928static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
865929 T *special_instruction = allocate<T>(1);
......@@ -906,7 +970,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so
906970 ir_ref_instruction(condition, irb->current_basic_block);
907971 ir_ref_bb(then_block);
908972 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
911975 return &cond_br_instruction->base;
912976}
......@@ -922,16 +986,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou
922986 return &return_instruction->base;
923987}
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
935989static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) {
936990 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
937991 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
11791233 call_instruction->async_allocator = async_allocator;
11801234 call_instruction->new_stack = new_stack;
11811235
1182 if (fn_ref)
1183 ir_ref_instruction(fn_ref, irb->current_basic_block);
1236 if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block);
11841237 for (size_t i = 0; i < arg_count; i += 1)
11851238 ir_ref_instruction(args[i], irb->current_basic_block);
1186 if (async_allocator)
1187 ir_ref_instruction(async_allocator, irb->current_basic_block);
1188 if (new_stack != nullptr)
1189 ir_ref_instruction(new_stack, irb->current_basic_block);
1239 if (async_allocator != nullptr) ir_ref_instruction(async_allocator, irb->current_basic_block);
1240 if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block);
11901241
11911242 return &call_instruction->base;
11921243}
......@@ -1271,7 +1322,7 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope,
12711322 container_init_list_instruction->item_count = item_count;
12721323 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);
12751326 for (size_t i = 0; i < item_count; i += 1) {
12761327 ir_ref_instruction(items[i], irb->current_basic_block);
12771328 }
......@@ -1346,10 +1397,10 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *
13461397 return &instruction->base;
13471398}
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,
13501401 ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value)
13511402{
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);
13531404 decl_var_instruction->base.value.special = ConstValSpecialStatic;
13541405 decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void;
13551406 decl_var_instruction->var = var;
......@@ -1357,13 +1408,28 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *s
13571408 decl_var_instruction->align_value = align_value;
13581409 decl_var_instruction->init_value = init_value;
13591410
1360 if (var_type) ir_ref_instruction(var_type, irb->current_basic_block);
1361 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);
1411 if (var_type != nullptr) ir_ref_instruction(var_type, irb->current_basic_block);
1412 if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block);
13621413 ir_ref_instruction(init_value, irb->current_basic_block);
13631414
13641415 return &decl_var_instruction->base;
13651416}
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
13671433static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node,
13681434 IrInstruction *name, IrInstruction *target, IrInstruction *linkage)
13691435{
......@@ -1533,14 +1599,14 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod
15331599 return &instruction->base;
15341600}
15351601
1536static IrInstruction *ir_build_unwrap_maybe(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value,
1537 bool safety_check_on)
1602static IrInstruction *ir_build_optional_unwrap_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
1603 IrInstruction *base_ptr, bool safety_check_on)
15381604{
1539 IrInstructionUnwrapOptional *instruction = ir_build_instruction<IrInstructionUnwrapOptional>(irb, scope, source_node);
1540 instruction->value = value;
1605 IrInstructionOptionalUnwrapPtr *instruction = ir_build_instruction<IrInstructionOptionalUnwrapPtr>(irb, scope, source_node);
1606 instruction->base_ptr = base_ptr;
15411607 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
15451611 return &instruction->base;
15461612}
......@@ -1756,13 +1822,12 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode
17561822 return &instruction->base;
17571823}
17581824
1759static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value,
1760 IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
1825static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
1826 IrInstruction *type_value, IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
17611827 IrInstruction *success_order_value, IrInstruction *failure_order_value,
1762 bool is_weak,
1763 ZigType *type, AtomicOrder success_order, AtomicOrder failure_order)
1828 bool is_weak)
17641829{
1765 IrInstructionCmpxchg *instruction = ir_build_instruction<IrInstructionCmpxchg>(irb, scope, source_node);
1830 IrInstructionCmpxchgSrc *instruction = ir_build_instruction<IrInstructionCmpxchgSrc>(irb, scope, source_node);
17661831 instruction->type_value = type_value;
17671832 instruction->ptr = ptr;
17681833 instruction->cmp_value = cmp_value;
......@@ -1770,16 +1835,33 @@ static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *so
17701835 instruction->success_order_value = success_order_value;
17711836 instruction->failure_order_value = failure_order_value;
17721837 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);
17781840 ir_ref_instruction(ptr, irb->current_basic_block);
17791841 ir_ref_instruction(cmp_value, irb->current_basic_block);
17801842 ir_ref_instruction(new_value, irb->current_basic_block);
1781 if (type_value != nullptr) 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);
1843 ir_ref_instruction(success_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
17841866 return &instruction->base;
17851867}
......@@ -1900,6 +1982,19 @@ static IrInstruction *ir_build_int_type(IrBuilder *irb, Scope *scope, AstNode *s
19001982 return &instruction->base;
19011983}
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
19031998static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
19041999 IrInstructionBoolNot *instruction = ir_build_instruction<IrInstructionBoolNot>(irb, scope, source_node);
19052000 instruction->value = value;
......@@ -2051,12 +2146,12 @@ static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *s
20512146}
20522147
20532148static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node,
2054 IrInstruction *value)
2149 IrInstruction *err_union)
20552150{
20562151 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
20612156 return &instruction->base;
20622157}
......@@ -2106,20 +2201,35 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo
21062201 return &instruction->base;
21072202}
21082203
2109static IrInstruction *ir_build_ptr_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
2110 IrInstruction *dest_type, IrInstruction *ptr)
2204static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
2205 IrInstruction *dest_type, IrInstruction *ptr, bool safety_check_on)
21112206{
2112 IrInstructionPtrCast *instruction = ir_build_instruction<IrInstructionPtrCast>(
2207 IrInstructionPtrCastSrc *instruction = ir_build_instruction<IrInstructionPtrCastSrc>(
21132208 irb, scope, source_node);
21142209 instruction->dest_type = dest_type;
21152210 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);
21182214 ir_ref_instruction(ptr, irb->current_basic_block);
21192215
21202216 return &instruction->base;
21212217}
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
21232233static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
21242234 IrInstruction *dest_type, IrInstruction *value)
21252235{
......@@ -2362,7 +2472,7 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *
23622472
23632473 ir_ref_instruction(type_value, irb->current_basic_block);
23642474
2365 return &instruction->base;
2475 return &instruction->base;
23662476}
23672477
23682478static 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
27052815 return &instruction->base;
27062816}
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
27082840static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *scope_is_comptime, IrInstruction *is_comptime) {
27092841 IrInstructionCheckRuntimeScope *instruction = ir_build_instruction<IrInstructionCheckRuntimeScope>(irb, scope, source_node);
27102842 instruction->scope_is_comptime = scope_is_comptime;
......@@ -2716,6 +2848,47 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope,
27162848 return &instruction->base;
27172849}
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
27192892static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
27202893 results[ReturnKindUnconditional] = 0;
27212894 results[ReturnKindError] = 0;
......@@ -2776,10 +2949,13 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o
27762949 Scope *defer_expr_scope = defer_node->data.defer.expr_scope;
27772950 IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);
27782951 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 {
27802955 is_noreturn = true;
27812956 } 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));
27832959 }
27842960 }
27852961 }
......@@ -3034,7 +3210,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
30343210 variable_entry->mem_slot_index = SIZE_MAX;
30353211 variable_entry->is_comptime = is_comptime;
30363212 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
30393215 if (is_comptime != nullptr) {
30403216 is_comptime->ref_count += 1;
......@@ -3049,20 +3225,20 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
30493225 ErrorMsg *msg = add_node_error(codegen, node,
30503226 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
30513227 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;
30533229 } else {
30543230 ZigType *type;
30553231 if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) {
30563232 add_node_error(codegen, node,
30573233 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;
30593235 } else {
30603236 Tld *tld = find_decl(codegen, parent_scope, name);
30613237 if (tld != nullptr) {
30623238 ErrorMsg *msg = add_node_error(codegen, node,
30633239 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
30643240 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;
30663242 }
30673243 }
30683244 }
......@@ -3125,7 +3301,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
31253301 scope_block->incoming_blocks = &incoming_blocks;
31263302 scope_block->incoming_values = &incoming_values;
31273303 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));
31293306 }
31303307
31313308 bool is_continuation_unreachable = false;
......@@ -3143,9 +3320,9 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
31433320 // defer starts a new scope
31443321 child_scope = statement_node->data.defer.child_scope;
31453322 assert(child_scope);
3146 } else if (statement_value->id == IrInstructionIdDeclVar) {
3323 } else if (statement_value->id == IrInstructionIdDeclVarSrc) {
31473324 // variable declarations start a new scope
3148 IrInstructionDeclVar *decl_var_instruction = (IrInstructionDeclVar *)statement_value;
3325 IrInstructionDeclVarSrc *decl_var_instruction = (IrInstructionDeclVarSrc *)statement_value;
31493326 child_scope = decl_var_instruction->var->child_scope;
31503327 } else if (statement_value != irb->codegen->invalid_instruction && !is_continuation_unreachable) {
31513328 // this statement's value must be void
......@@ -3300,7 +3477,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod
33003477 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
33013478}
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) {
33043481 assert(node->type == NodeTypeBinOpExpr);
33053482
33063483 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
33343511 ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));
33353512
33363513 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);
33383515 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
33393516 IrBasicBlock *after_ok_block = irb->current_basic_block;
33403517 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)
34523629 case BinOpTypeMergeErrorSets:
34533630 return ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets);
34543631 case BinOpTypeUnwrapOptional:
3455 return ir_gen_maybe_ok_or(irb, scope, node);
3632 return ir_gen_orelse(irb, scope, node);
34563633 case BinOpTypeErrorUnion:
34573634 return ir_gen_error_union(irb, scope, node);
34583635 }
......@@ -3511,6 +3688,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
35113688 buf_ptr(variable_name)));
35123689 return irb->codegen->invalid_instruction;
35133690 }
3691 assert(err == ErrorPrimitiveTypeNotFound);
35143692 } else {
35153693 IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_type);
35163694 if (lval == LValPtr) {
......@@ -3630,7 +3808,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
36303808 Buf *name = fn_ref_expr->data.symbol_expr.symbol;
36313809 auto entry = irb->codegen->builtin_fn_table.maybe_get(name);
36323810
3633 if (!entry) {
3811 if (!entry) { // new built in not found
36343812 add_node_error(irb->codegen, node,
36353813 buf_sprintf("invalid builtin function: '%s'", buf_ptr(name)));
36363814 return irb->codegen->invalid_instruction;
......@@ -3873,9 +4051,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
38734051 if (arg5_value == irb->codegen->invalid_instruction)
38744052 return arg5_value;
38754053
3876 IrInstruction *cmpxchg = ir_build_cmpxchg(irb, scope, node, arg0_value, arg1_value,
3877 arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak),
3878 nullptr, AtomicOrderUnordered, AtomicOrderUnordered);
4054 IrInstruction *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value,
4055 arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak));
38794056 return ir_lval_wrap(irb, scope, cmpxchg, lval);
38804057 }
38814058 case BuiltinFnIdFence:
......@@ -4138,6 +4315,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
41384315 IrInstruction *int_type = ir_build_int_type(irb, scope, node, arg0_value, arg1_value);
41394316 return ir_lval_wrap(irb, scope, int_type, lval);
41404317 }
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 }
41414333 case BuiltinFnIdMemcpy:
41424334 {
41434335 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
43154507 if (arg1_value == irb->codegen->invalid_instruction)
43164508 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);
43194511 return ir_lval_wrap(irb, scope, ptr_cast, lval);
43204512 }
43214513 case BuiltinFnIdBitCast:
......@@ -4689,6 +4881,36 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
46894881 IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value);
46904882 return ir_lval_wrap(irb, scope, result, lval);
46914883 }
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 }
46924914 }
46934915 zig_unreachable();
46944916}
......@@ -4723,7 +4945,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
47234945 }
47244946 }
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);
47274950 return ir_lval_wrap(irb, scope, fn_call, lval);
47284951}
47294952
......@@ -4732,7 +4955,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
47324955
47334956 IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope);
47344957 if (condition == irb->codegen->invalid_instruction)
4735 return condition;
4958 return irb->codegen->invalid_instruction;
47364959
47374960 IrInstruction *is_comptime;
47384961 if (ir_should_inline(irb->exec, scope)) {
......@@ -4755,7 +4978,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
47554978 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
47564979 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, subexpr_scope);
47574980 if (then_expr_result == irb->codegen->invalid_instruction)
4758 return then_expr_result;
4981 return irb->codegen->invalid_instruction;
47594982 IrBasicBlock *after_then_block = irb->current_basic_block;
47604983 if (!instr_is_unreachable(then_expr_result))
47614984 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
47654988 if (else_node) {
47664989 else_expr_result = ir_gen_node(irb, else_node, subexpr_scope);
47674990 if (else_expr_result == irb->codegen->invalid_instruction)
4768 return else_expr_result;
4991 return irb->codegen->invalid_instruction;
47694992 } else {
47704993 else_expr_result = ir_build_const_void(irb, scope, node);
47714994 }
......@@ -4810,10 +5033,23 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *
48105033 return ir_build_ref(irb, scope, value->source_node, value, false, false);
48115034}
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
48135050static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {
48145051 assert(node->type == NodeTypePointerType);
4815 PtrLen ptr_len = (node->data.pointer_type.star_token->id == TokenIdStar ||
4816 node->data.pointer_type.star_token->id == TokenIdStarStar) ? PtrLenSingle : PtrLenUnknown;
5052 PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id);
48175053 bool is_const = node->data.pointer_type.is_const;
48185054 bool is_volatile = node->data.pointer_type.is_volatile;
48195055 AstNode *expr_node = node->data.pointer_type.op_expr;
......@@ -4866,7 +5102,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
48665102 ptr_len, align_value, bit_offset_start, host_int_bytes);
48675103}
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,
48705106 LVal lval)
48715107{
48725108 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
49925228 ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime);
49935229 ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol,
49945230 is_const, is_const, is_shadowable, is_comptime);
4995 // we detect IrInstructionIdDeclVar in gen_block to make sure the next node
5231 // we detect IrInstructionIdDeclVarSrc in gen_block to make sure the next node
49965232 // is inside var->child_scope
49975233
49985234 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;
50005236 add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized"));
50015237 return irb->codegen->invalid_instruction;
50025238 }
......@@ -5012,6 +5248,10 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
50125248 add_node_error(irb->codegen, variable_declaration->section_expr,
50135249 buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol)));
50145250 }
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
50165256 // Temporarily set the name of the IrExecutable to the VariableDeclaration
50175257 // 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
50235263 if (init_value == irb->codegen->invalid_instruction)
50245264 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);
50275267}
50285268
50295269static 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
50795319 err_val_ptr, false);
50805320 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
50815321 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);
50835323 }
50845324
50855325 ZigList<IrInstruction *> incoming_values = {0};
......@@ -5119,7 +5359,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
51195359 true, false, false, is_comptime);
51205360 Scope *err_scope = err_var->child_scope;
51215361 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
51245364 IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope);
51255365 if (else_result == irb->codegen->invalid_instruction)
......@@ -5159,10 +5399,10 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
51595399 }
51605400
51615401 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);
51635403 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
51645404 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
51675407 ZigList<IrInstruction *> incoming_values = {0};
51685408 ZigList<IrBasicBlock *> incoming_blocks = {0};
......@@ -5319,7 +5559,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
53195559 Scope *child_scope = elem_var->child_scope;
53205560
53215561 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);
53235563 IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var);
53245564
53255565 AstNode *index_var_source_node;
......@@ -5337,7 +5577,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
53375577 IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize);
53385578 IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0);
53395579 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);
53415581 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
55615801 return ir_build_asm(irb, scope, node, input_list, output_types, output_vars, return_count, is_volatile);
55625802}
55635803
5564static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
5565 assert(node->type == NodeTypeTestExpr);
5804static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
5805 assert(node->type == NodeTypeIfOptional);
55665806
55675807 Buf *var_symbol = node->data.test_expr.var_symbol;
55685808 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
56005840 ZigVar *var = ir_create_var(irb, node, subexpr_scope,
56015841 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);
56045844 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);
56065846 var_scope = var->child_scope;
56075847 } else {
56085848 var_scope = subexpr_scope;
......@@ -5677,7 +5917,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
56775917
56785918 IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false);
56795919 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);
56815921 var_scope = var->child_scope;
56825922 } else {
56835923 var_scope = subexpr_scope;
......@@ -5702,7 +5942,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
57025942 err_symbol, is_const, is_const, is_shadowable, is_comptime);
57035943
57045944 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);
57065946 err_var_scope = var->child_scope;
57075947 } else {
57085948 err_var_scope = subexpr_scope;
......@@ -5757,7 +5997,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
57575997 var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr);
57585998 }
57595999 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);
57616001 } else {
57626002 child_scope = scope;
57636003 }
......@@ -6167,7 +6407,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)
61676407 return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true);
61686408}
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) {
61716411 assert(node->type == NodeTypeUnwrapErrorExpr);
61726412
61736413 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
61816421 add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));
61826422 return irb->codegen->invalid_instruction;
61836423 }
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);
61856425 }
61866426
61876427
......@@ -6215,7 +6455,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
62156455 is_const, is_const, is_shadowable, is_comptime);
62166456 err_scope = var->child_scope;
62176457 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);
62196459 } else {
62206460 err_scope = parent_scope;
62216461 }
......@@ -6251,7 +6491,8 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o
62516491 ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope;
62526492 if (need_comma)
62536493 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);
62556496 return true;
62566497}
62576498
......@@ -6501,14 +6742,15 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
65016742 IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010
65026743
65036744 // 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);
65056747 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
65066748 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
65076749 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
65086750 atomic_state_field_name);
65096751
65106752 // 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,
65126754 usize_type_val, atomic_state_ptr, nullptr, is_canceled_mask, nullptr,
65136755 AtomicRmwOp_or, AtomicOrderSeqCst);
65146756
......@@ -6579,14 +6821,15 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode
65796821 get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));
65806822
65816823 // 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);
65836826 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
65846827 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
65856828 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
65866829 atomic_state_field_name);
65876830
65886831 // 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,
65906833 usize_type_val, atomic_state_ptr, nullptr, and_mask, nullptr,
65916834 AtomicRmwOp_and, AtomicOrderSeqCst);
65926835
......@@ -6695,14 +6938,14 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
66956938 IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst);
66966939 IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type);
66976940 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);
66996942 IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var);
67006943 ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr);
67016944 IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle);
67026945
67036946 IrInstruction *coro_handle_addr = ir_build_ptr_to_int(irb, scope, node, irb->exec->coro_handle);
67046947 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,
67066949 usize_type_val, atomic_state_ptr, nullptr, mask_bits, nullptr,
67076950 AtomicRmwOp_or, AtomicOrderSeqCst);
67086951
......@@ -6745,7 +6988,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
67456988
67466989
67476990 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,
67496992 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, is_suspended_mask, nullptr,
67506993 AtomicRmwOp_or, AtomicOrderSeqCst);
67516994 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
67777020
67787021 ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
67797022 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,
67817024 usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, my_mask_bits, nullptr,
67827025 AtomicRmwOp_or, AtomicOrderSeqCst);
67837026 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
69897232 if (maybe_ptr == irb->codegen->invalid_instruction)
69907233 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);
69937236 if (lval == LValPtr)
69947237 return unwrapped_ptr;
69957238
......@@ -7013,8 +7256,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
70137256 return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);
70147257 case NodeTypeIfErrorExpr:
70157258 return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval);
7016 case NodeTypeTestExpr:
7017 return ir_lval_wrap(irb, scope, ir_gen_test_expr(irb, scope, node), lval);
7259 case NodeTypeIfOptional:
7260 return ir_lval_wrap(irb, scope, ir_gen_if_optional_expr(irb, scope, node), lval);
70187261 case NodeTypeSwitchExpr:
70197262 return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);
70207263 case NodeTypeCompTime:
......@@ -7032,7 +7275,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
70327275 case NodeTypeSliceExpr:
70337276 return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval);
70347277 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);
70367279 case NodeTypeContainerDecl:
70377280 return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval);
70387281 case NodeTypeFnProto:
......@@ -7091,6 +7334,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
70917334 ir_ref_bb(irb->current_basic_block);
70927335
70937336 ZigFn *fn_entry = exec_fn_entry(irb->exec);
7337
70947338 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
70957339 IrInstruction *coro_id;
70967340 IrInstruction *u8_ptr_type;
......@@ -7111,27 +7355,28 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
71117355 ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);
71127356 IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);
71137357 // 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);
71157359 coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var);
71167360
71177361 ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
71187362 IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);
71197363 IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,
71207364 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);
71227366 irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var);
71237367
71247368 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
71257369 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);
71277372 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);
71287373 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
71297374 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);
71317376 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node,
71327377 ImplicitAllocatorIdArg);
71337378 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);
71357380 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
71367381 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, alloc_field_name);
71377382 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
71477392 ir_build_return(irb, coro_scope, node, undef);
71487393
71497394 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);
71517397 irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);
71527398
71537399 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
72257471 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
72267472 false, false, PtrLenUnknown, 0, 0, 0));
72277473 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);
7229 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len,
7230 irb->exec->coro_result_field_ptr);
7474 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
7475 result_ptr, false);
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);
72317478 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,
72327479 fn_entry->type_entry->data.fn.fn_type_id.return_type);
72337480 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
72427489 // Before we destroy the coroutine frame, we need to load the target promise into
72437490 // a register or local variable which does not get spilled into the frame,
72447491 // 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,
72467493 irb->exec->await_handle_var_ptr, false);
72477494 IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);
72487495 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
72777524 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
72787525 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
72797526 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);
72817529 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
72827530 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
72837531 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
73307578 return exec_add_error_node(ira->codegen, ira->new_irb.exec, source_node, msg);
73317579}
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
73337588static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction, Buf *msg) {
73347589 return ir_add_error_node(ira, source_instruction->source_node, msg);
73357590}
73367591
7337static ConstExprValue *ir_const_ptr_pointee(IrAnalyze *ira, ConstExprValue *const_val, AstNode *source_node) {
7338 ConstExprValue *val = const_ptr_pointee_unchecked(ira->codegen, const_val);
7592// This function takes a comptime ptr and makes the child const value conform to the type
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);
73397614 assert(val != nullptr);
73407615 assert(const_val->type->id == ZigTypeIdPointer);
73417616 ZigType *expected_type = const_val->type->data.pointer.child_type;
73427617 if (!types_have_same_zig_comptime_repr(val->type, expected_type)) {
7343 ir_add_error_node(ira, source_node,
7344 buf_sprintf("TODO handle comptime reinterpreted pointer. See https://github.com/ziglang/zig/issues/955"));
7345 return nullptr;
7618 if ((err = eval_comptime_ptr_reinterpret(ira, codegen, source_node, const_val)))
7619 return nullptr;
7620 return const_ptr_pointee_unchecked(codegen, const_val);
73467621 }
73477622 return val;
73487623}
73497624
7350static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) {
7625static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) {
73517626 IrBasicBlock *bb = exec->basic_block_list.at(0);
73527627 for (size_t i = 0; i < bb->instruction_list.length; i += 1) {
73537628 IrInstruction *instruction = bb->instruction_list.at(i);
......@@ -7357,16 +7632,16 @@ static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec)
73577632 if (value->value.special == ConstValSpecialRuntime) {
73587633 exec_add_error_node(codegen, exec, value->source_node,
73597634 buf_sprintf("unable to evaluate constant expression"));
7360 return codegen->invalid_instruction;
7635 return &codegen->invalid_instruction->value;
73617636 }
7362 return value;
7637 return &value->value;
73637638 } else if (ir_has_side_effects(instruction)) {
73647639 exec_add_error_node(codegen, exec, instruction->source_node,
73657640 buf_sprintf("unable to evaluate constant expression"));
7366 return codegen->invalid_instruction;
7641 return &codegen->invalid_instruction->value;
73677642 }
73687643 }
7369 return codegen->invalid_instruction;
7644 return &codegen->invalid_instruction->value;
73707645}
73717646
73727647static 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
80868361
80878362 bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt);
80888363 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
80908366 if (other_type->id == ZigTypeIdFloat) {
80918367 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
83768652 return err_set_type;
83778653}
83788654
8379
83808655static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type,
83818656 ZigType *actual_type, AstNode *source_node, bool wanted_is_mutable)
83828657{
......@@ -8389,53 +8664,63 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
83898664 if (wanted_type == actual_type)
83908665 return result;
83918666
8392 // *T and [*]T may const-cast-only to ?*U and ?[*]U, respectively
8393 // but not if we want a mutable pointer
8394 // and not if the actual pointer has zero bits
8395 if (!wanted_is_mutable && wanted_type->id == ZigTypeIdOptional &&
8396 wanted_type->data.maybe.child_type->id == ZigTypeIdPointer &&
8397 actual_type->id == ZigTypeIdPointer && type_has_bits(actual_type))
8398 {
8399 ConstCastOnly child = types_match_const_cast_only(ira,
8400 wanted_type->data.maybe.child_type, actual_type, source_node, wanted_is_mutable);
8401 if (child.id == ConstCastResultIdInvalid)
8402 return child;
8403 if (child.id != ConstCastResultIdOk) {
8404 result.id = ConstCastResultIdNullWrapPtr;
8405 result.data.null_wrap_ptr_child = allocate_nonzero<ConstCastOnly>(1);
8406 *result.data.null_wrap_ptr_child = child;
8407 }
8408 return result;
8409 }
8410
8411 // pointer const
8412 if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) {
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);
8667 // If pointers have the same representation in memory, they can be "const-casted".
8668 // `const` attribute can be gained
8669 // `volatile` attribute can be gained
8670 // `allowzero` attribute can be gained (whether from explicit attribute, C pointer, or optional pointer)
8671 // but only if !wanted_is_mutable
8672 // alignment can be decreased
8673 // bit offset attributes must match exactly
8674 // PtrLenSingle/PtrLenUnknown must match exactly, but PtrLenC matches either one
8675 ZigType *wanted_ptr_type = get_src_ptr_type(wanted_type);
8676 ZigType *actual_ptr_type = get_src_ptr_type(actual_type);
8677 bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);
8678 bool actual_allows_zero = ptr_allows_addr_zero(actual_type);
8679 bool wanted_is_c_ptr = wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC;
8680 bool actual_is_c_ptr = actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenC;
8681 bool wanted_opt_or_ptr = wanted_ptr_type != nullptr &&
8682 (wanted_type->id == ZigTypeIdPointer || wanted_type->id == ZigTypeIdOptional);
8683 bool actual_opt_or_ptr = actual_ptr_type != nullptr &&
8684 (actual_type->id == ZigTypeIdPointer || actual_type->id == ZigTypeIdOptional);
8685 if (wanted_opt_or_ptr && actual_opt_or_ptr) {
8686 ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,
8687 actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);
84158688 if (child.id == ConstCastResultIdInvalid)
84168689 return child;
84178690 if (child.id != ConstCastResultIdOk) {
84188691 result.id = ConstCastResultIdPointerChild;
84198692 result.data.pointer_mismatch = allocate_nonzero<ConstCastPointerMismatch>(1);
84208693 result.data.pointer_mismatch->child = child;
8421 result.data.pointer_mismatch->wanted_child = wanted_type->data.pointer.child_type;
8422 result.data.pointer_mismatch->actual_child = actual_type->data.pointer.child_type;
8694 result.data.pointer_mismatch->wanted_child = wanted_ptr_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;
84238706 return result;
84248707 }
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))) {
84268709 result.id = ConstCastResultIdInvalid;
84278710 return result;
84288711 }
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))) {
84308713 result.id = ConstCastResultIdInvalid;
84318714 return result;
84328715 }
8433 if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) &&
8434 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
8435 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) &&
8436 actual_type->data.pointer.bit_offset_in_host == wanted_type->data.pointer.bit_offset_in_host &&
8437 actual_type->data.pointer.host_int_bytes == wanted_type->data.pointer.host_int_bytes &&
8438 get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type))
8716 bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
8717 if ((ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr) &&
8718 type_has_bits(wanted_type) == type_has_bits(actual_type) &&
8719 (!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&
8720 (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) &&
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))
84398724 {
84408725 return result;
84418726 }
......@@ -8669,7 +8954,9 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t *
86698954 *errors = reallocate(*errors, old_errors_count, *errors_count);
86708955}
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{
86738960 Error err;
86748961 assert(instruction_count >= 1);
86758962 IrInstruction *prev_inst = instructions[0];
......@@ -8680,13 +8967,13 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
86808967 size_t errors_count = 0;
86818968 ZigType *err_set_type = nullptr;
86828969 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 }
86838973 if (type_is_global_error_set(prev_inst->value.type)) {
86848974 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
86858975 } else {
86868976 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 }
86908977 update_errors_helper(ira->codegen, &errors, &errors_count);
86918978
86928979 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
88459132 if (prev_type->id == ZigTypeIdArray) {
88469133 convert_to_const_slice = true;
88479134 }
9135 if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
9136 return ira->codegen->builtin_types.entry_invalid;
9137 }
88489138 if (type_is_global_error_set(cur_type)) {
88499139 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
88509140 continue;
......@@ -8852,9 +9142,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
88529142 if (err_set_type != nullptr && type_is_global_error_set(err_set_type)) {
88539143 continue;
88549144 }
8855 if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
8856 return ira->codegen->builtin_types.entry_invalid;
8857 }
88589145
88599146 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
89869273 continue;
89879274 }
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
89899307 if (types_match_const_cast_only(ira, prev_type, cur_type, source_node, false).id == ConstCastResultIdOk) {
89909308 continue;
89919309 }
......@@ -9292,7 +9610,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
92929610 const_val->type = new_type;
92939611 break;
92949612 case CastOpResizeSlice:
9295 case CastOpBytesToSlice:
92969613 // can't do it
92979614 zig_unreachable();
92989615 case CastOpIntToFloat:
......@@ -9345,14 +9662,23 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
93459662 }
93469663 return true;
93479664}
9348static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
9349 ZigType *wanted_type, CastOp cast_op, bool need_alloca)
9350{
9665
9666static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) {
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{
93519678 if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) &&
9352 cast_op != CastOpResizeSlice && cast_op != CastOpBytesToSlice)
9679 cast_op != CastOpResizeSlice)
93539680 {
9354 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
9355 source_instr->source_node, wanted_type);
9681 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
93569682 if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type,
93579683 &result->value, wanted_type))
93589684 {
......@@ -9385,13 +9711,11 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
93859711 wanted_type = adjust_ptr_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type));
93869712
93879713 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);
93899715 if (pointee == nullptr)
93909716 return ira->codegen->invalid_instruction;
93919717 if (pointee->special != ConstValSpecialRuntime) {
9392 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
9393 source_instr->source_node, wanted_type);
9394 result->value.type = wanted_type;
9718 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
93959719 result->value.data.x_ptr.special = ConstPtrSpecialBaseArray;
93969720 result->value.data.x_ptr.mut = value->value.data.x_ptr.mut;
93979721 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
94219745 wanted_type = adjust_slice_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type));
94229746
94239747 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);
94259749 if (pointee == nullptr)
94269750 return ira->codegen->invalid_instruction;
94279751 if (pointee->special != ConstValSpecialRuntime) {
......@@ -9430,8 +9754,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
94309754 assert(is_slice(wanted_type));
94319755 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,
9434 source_instr->source_node, wanted_type);
9757 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
94359758 init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const);
94369759 result->value.data.x_struct.fields[slice_ptr_index].data.x_ptr.mut =
94379760 value->value.data.x_ptr.mut;
......@@ -9566,15 +9889,6 @@ static IrInstruction *ir_finish_anal(IrAnalyze *ira, IrInstruction *instruction)
95669889 return instruction;
95679890}
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
95789892static IrInstruction *ir_const_type(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) {
95799893 IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_type);
95809894 result->value.data.x_type = ty;
......@@ -9625,20 +9939,20 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
96259939 if (undef_allowed == UndefOk) {
96269940 return &value->value;
96279941 } 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"));
96299943 return nullptr;
96309944 }
96319945 }
96329946 zig_unreachable();
96339947}
96349948
9635IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
9949ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
96369950 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
96379951 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)
96399953{
96409954 if (expected_type != nullptr && type_is_invalid(expected_type))
9641 return codegen->invalid_instruction;
9955 return &codegen->invalid_instruction->value;
96429956
96439957 IrExecutable *ir_executable = allocate<IrExecutable>(1);
96449958 ir_executable->source_node = source_node;
......@@ -9651,13 +9965,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node
96519965 ir_gen(codegen, node, scope, ir_executable);
96529966
96539967 if (ir_executable->invalid)
9654 return codegen->invalid_instruction;
9968 return &codegen->invalid_instruction->value;
96559969
96569970 if (codegen->verbose_ir) {
96579971 fprintf(stderr, "\nSource: ");
96589972 ast_render(codegen, stderr, node, 4);
96599973 fprintf(stderr, "\n{ // (IR)\n");
9660 ir_print(codegen, stderr, ir_executable, 4);
9974 ir_print(codegen, stderr, ir_executable, 2);
96619975 fprintf(stderr, "}\n");
96629976 }
96639977 IrExecutable *analyzed_executable = allocate<IrExecutable>(1);
......@@ -9671,13 +9985,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node
96719985 analyzed_executable->backward_branch_count = backward_branch_count;
96729986 analyzed_executable->backward_branch_quota = backward_branch_quota;
96739987 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);
96759989 if (type_is_invalid(result_type))
9676 return codegen->invalid_instruction;
9990 return &codegen->invalid_instruction->value;
96779991
96789992 if (codegen->verbose_ir) {
96799993 fprintf(stderr, "{ // (analyzed)\n");
9680 ir_print(codegen, stderr, analyzed_executable, 4);
9994 ir_print(codegen, stderr, analyzed_executable, 2);
96819995 fprintf(stderr, "}\n");
96829996 }
96839997
......@@ -9702,6 +10016,34 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {
970210016 return const_val->data.x_type;
970310017}
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
970510047static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
970610048 if (fn_value == ira->codegen->invalid_instruction)
970710049 return nullptr;
......@@ -9723,7 +10065,9 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
972310065 return const_val->data.x_ptr.data.fn.fn_entry;
972410066}
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{
972710071 assert(wanted_type->id == ZigTypeIdOptional);
972810072
972910073 if (instr_is_comptime(value)) {
......@@ -9739,7 +10083,7 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc
973910083 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
974010084 source_instr->scope, source_instr->source_node);
974110085 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)) {
974310087 copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst);
974410088 } else {
974510089 const_instruction->base.value.data.x_optional = val;
......@@ -9770,11 +10114,16 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
977010114 if (!val)
977110115 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
977310122 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
977410123 source_instr->scope, source_instr->source_node);
977510124 const_instruction->base.value.type = wanted_type;
977610125 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;
977810127 const_instruction->base.value.data.x_err_union.payload = val;
977910128 return &const_instruction->base;
978010129 }
......@@ -9839,11 +10188,16 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so
983910188 if (!val)
984010189 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
984210196 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
984310197 source_instr->scope, source_instr->source_node);
984410198 const_instruction->base.value.type = wanted_type;
984510199 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;
984710201 const_instruction->base.value.data.x_err_union.payload = nullptr;
984810202 return &const_instruction->base;
984910203 }
......@@ -9865,8 +10219,9 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so
986510219 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, source_instr->scope, source_instr->source_node);
986610220 const_instruction->base.value.special = ConstValSpecialStatic;
986710221 if (get_codegen_ptr_type(wanted_type) != nullptr) {
9868 const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
9869 const_instruction->base.value.data.x_ptr.data.hard_coded_addr.addr = 0;
10222 const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialNull;
10223 } else if (is_opt_err_set(wanted_type)) {
10224 const_instruction->base.value.data.x_err_set = nullptr;
987010225 } else {
987110226 const_instruction->base.value.data.x_optional = nullptr;
987210227 }
......@@ -9899,7 +10254,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
989910254 source_instruction->source_node, value, is_const, is_volatile);
990010255 new_instruction->value.type = ptr_type;
990110256 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)) {
990310258 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
990410259 assert(fn_entry);
990510260 fn_entry->alloca_list.append(new_instruction);
......@@ -9925,20 +10280,17 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
992510280 ZigType *array_type = array->value.type;
992610281 assert(array_type->id == ZigTypeIdArray);
992710282
9928 if (instr_is_comptime(array)) {
9929 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
9930 source_instr->source_node, wanted_type);
10283 if (instr_is_comptime(array) || array_type->data.array.len == 0) {
10284 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
993110285 init_const_slice(ira->codegen, &result->value, &array->value, 0, array_type->data.array.len, true);
993210286 result->value.type = wanted_type;
993310287 return result;
993410288 }
993510289
9936 IrInstruction *start = ir_create_const(&ira->new_irb, source_instr->scope,
9937 source_instr->source_node, ira->codegen->builtin_types.entry_usize);
10290 IrInstruction *start = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize);
993810291 init_const_usize(ira->codegen, &start->value, 0);
993910292
9940 IrInstruction *end = ir_create_const(&ira->new_irb, source_instr->scope,
9941 source_instr->source_node, ira->codegen->builtin_types.entry_usize);
10293 IrInstruction *end = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize);
994210294 init_const_usize(ira->codegen, &end->value, array_type->data.array.len);
994310295
994410296 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
997710329 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
997810330 if (!val)
997910331 return ira->codegen->invalid_instruction;
9980 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
9981 source_instr->source_node, wanted_type);
10332 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
998210333 init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag);
998310334 return result;
998410335 }
......@@ -9988,8 +10339,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
998810339 actual_type->data.enumeration.src_field_count == 1)
998910340 {
999010341 assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int);
9991 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
9992 source_instr->source_node, wanted_type);
10342 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
999310343 init_const_bigint(&result->value, wanted_type,
999410344 &actual_type->data.enumeration.fields[0].value);
999510345 return result;
......@@ -10012,8 +10362,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
1001210362 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
1001310363 if (!val)
1001410364 return ira->codegen->invalid_instruction;
10015 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10016 source_instr->source_node, wanted_type);
10365 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1001710366 result->value.special = ConstValSpecialStatic;
1001810367 result->value.type = wanted_type;
1001910368 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
1002410373 if (wanted_type->data.enumeration.layout == ContainerLayoutAuto &&
1002510374 wanted_type->data.enumeration.src_field_count == 1)
1002610375 {
10027 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10028 source_instr->source_node, wanted_type);
10376 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1002910377 result->value.special = ConstValSpecialStatic;
1003010378 result->value.type = wanted_type;
1003110379 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
1004210390static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr,
1004310391 IrInstruction *target, ZigType *wanted_type)
1004410392{
10045 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10046 source_instr->source_node, wanted_type);
10393 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1004710394 init_const_undefined(ira->codegen, &result->value);
1004810395 return result;
1004910396}
......@@ -10075,8 +10422,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so
1007510422 buf_sprintf("field '%s' declared here", buf_ptr(union_field->name)));
1007610423 return ira->codegen->invalid_instruction;
1007710424 }
10078 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10079 source_instr->source_node, wanted_type);
10425 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1008010426 result->value.special = ConstValSpecialStatic;
1008110427 result->value.type = wanted_type;
1008210428 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
1013110477 return ira->codegen->invalid_instruction;
1013210478 }
1013310479 }
10134 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10135 source_instr->source_node, wanted_type);
10480 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1013610481 result->value.type = wanted_type;
1013710482 if (wanted_type->id == ZigTypeIdInt) {
1013810483 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
1014210487 return result;
1014310488 }
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
1014510502 IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope,
1014610503 source_instr->source_node, target);
1014710504 result->value.type = wanted_type;
......@@ -10186,8 +10543,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
1018610543 return ira->codegen->invalid_instruction;
1018710544 }
1018810545
10189 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10190 source_instr->source_node, wanted_type);
10546 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1019110547 bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_bigint);
1019210548 return result;
1019310549 }
......@@ -10205,8 +10561,7 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction
1020510561 if (!val)
1020610562 return ira->codegen->invalid_instruction;
1020710563
10208 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10209 source_instr->source_node, wanted_type);
10564 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1021010565 if (wanted_type->id == ZigTypeIdComptimeFloat) {
1021110566 float_init_float(&result->value, val);
1021210567 } else if (wanted_type->id == ZigTypeIdComptimeInt) {
......@@ -10229,8 +10584,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc
1022910584 if (!val)
1023010585 return ira->codegen->invalid_instruction;
1023110586
10232 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10233 source_instr->source_node, wanted_type);
10587 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1023410588
1023510589 if (!resolve_inferred_error_set(ira->codegen, wanted_type, source_instr->source_node)) {
1023610590 return ira->codegen->invalid_instruction;
......@@ -10294,12 +10648,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
1029410648 if (!val)
1029510649 return ira->codegen->invalid_instruction;
1029610650
10297 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10298 source_instr->source_node, wanted_type);
10651 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1029910652
1030010653 ErrorTableEntry *err;
1030110654 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;
1030310656 } else if (err_type->id == ZigTypeIdErrorSet) {
1030410657 err = val->data.x_err_set;
1030510658 } else {
......@@ -10334,15 +10687,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
1033410687 return ira->codegen->invalid_instruction;
1033510688 }
1033610689 if (err_set_type->data.error_set.err_count == 0) {
10337 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10338 source_instr->source_node, wanted_type);
10339 result->value.type = wanted_type;
10690 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1034010691 bigint_init_unsigned(&result->value.data.x_bigint, 0);
1034110692 return result;
1034210693 } else if (err_set_type->data.error_set.err_count == 1) {
10343 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10344 source_instr->source_node, wanted_type);
10345 result->value.type = wanted_type;
10694 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1034610695 ErrorTableEntry *err = err_set_type->data.error_set.errors[0];
1034710696 bigint_init_unsigned(&result->value.data.x_bigint, err->value);
1034810697 return result;
......@@ -10380,7 +10729,7 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou
1038010729 return ira->codegen->invalid_instruction;
1038110730
1038210731 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);
1038410733 if (pointee == nullptr)
1038510734 return ira->codegen->invalid_instruction;
1038610735 if (pointee->special != ConstValSpecialRuntime) {
......@@ -10389,8 +10738,8 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou
1038910738 array_val->type = array_type;
1039010739 array_val->data.x_array.special = ConstArraySpecialNone;
1039110740 array_val->data.x_array.data.s_none.elements = pointee;
10392 array_val->data.x_array.data.s_none.parent.id = ConstParentIdScalar;
10393 array_val->data.x_array.data.s_none.parent.data.p_scalar.scalar_val = pointee;
10741 array_val->parent.id = ConstParentIdScalar;
10742 array_val->parent.data.p_scalar.scalar_val = pointee;
1039410743
1039510744 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
1039610745 source_instr->scope, source_instr->source_node);
......@@ -10496,21 +10845,100 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
1049610845 report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg);
1049710846 break;
1049810847 }
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;
1049910870 case ConstCastResultIdFnAlign: // TODO
1050010871 case ConstCastResultIdFnCC: // TODO
1050110872 case ConstCastResultIdFnVarArgs: // TODO
10502 case ConstCastResultIdFnIsGeneric: // TODO
1050310873 case ConstCastResultIdFnReturnType: // TODO
1050410874 case ConstCastResultIdFnArgCount: // TODO
1050510875 case ConstCastResultIdFnGenericArgCount: // TODO
1050610876 case ConstCastResultIdFnArgNoAlias: // TODO
1050710877 case ConstCastResultIdUnresolvedInferredErrSet: // TODO
1050810878 case ConstCastResultIdAsyncAllocatorType: // TODO
10509 case ConstCastResultIdNullWrapPtr: // TODO
1051010879 break;
1051110880 }
1051210881}
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
1051410942static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
1051510943 ZigType *wanted_type, IrInstruction *value)
1051610944{
......@@ -10538,12 +10966,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1053810966 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,
1053910967 false).id == ConstCastResultIdOk)
1054010968 {
10541 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
10969 return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type);
1054210970 } else if (actual_type->id == ZigTypeIdComptimeInt ||
1054310971 actual_type->id == ZigTypeIdComptimeFloat)
1054410972 {
1054510973 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);
1054710975 } else {
1054810976 return ira->codegen->invalid_instruction;
1054910977 }
......@@ -10567,7 +10995,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1056710995 wanted_child_type);
1056810996 if (type_is_invalid(cast1->value.type))
1056910997 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);
1057110999 }
1057211000 }
1057311001 }
......@@ -10620,6 +11048,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1062011048 (wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt ||
1062111049 wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat))
1062211050 {
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 }
1062311056 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {
1062411057 if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) {
1062511058 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
......@@ -10673,6 +11106,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1067311106
1067411107
1067511108 // cast from [N]T to []const T
11109 // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
1067611110 if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) {
1067711111 ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
1067811112 assert(ptr_type->id == ZigTypeIdPointer);
......@@ -10685,6 +11119,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1068511119 }
1068611120
1068711121 // cast from [N]T to ?[]const T
11122 // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
1068811123 if (wanted_type->id == ZigTypeIdOptional &&
1068911124 is_slice(wanted_type->data.maybe.child_type) &&
1069011125 actual_type->id == ZigTypeIdArray)
......@@ -10779,7 +11214,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1077911214 }
1078011215 }
1078111216
10782 // cast from error set to error union type
11217 // cast from E to E!T
1078311218 if (wanted_type->id == ZigTypeIdErrorUnion &&
1078411219 actual_type->id == ZigTypeIdErrorSet)
1078511220 {
......@@ -10875,7 +11310,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1087511310 actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes &&
1087611311 get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type))
1087711312 {
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);
1087911314 }
1088011315 }
1088111316
......@@ -10892,6 +11327,40 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1089211327 }
1089311328 }
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
1089611365 // cast from undefined to anything
1089711366 if (actual_type->id == ZigTypeIdUndefined) {
......@@ -10931,8 +11400,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
1093111400 ZigType *child_type = type_entry->data.pointer.child_type;
1093211401 // dereferencing a *u0 is comptime known to be 0
1093311402 if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) {
10934 IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,
10935 source_instruction->source_node, child_type);
11403 IrInstruction *result = ir_const(ira, source_instruction, child_type);
1093611404 init_const_unsigned_negative(&result->value, child_type, 0, false);
1093711405 return result;
1093811406 }
......@@ -10946,10 +11414,9 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
1094611414 {
1094711415 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
1094811416 if (pointee->special != ConstValSpecialRuntime) {
10949 IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,
10950 source_instruction->source_node, child_type);
11417 IrInstruction *result = ir_const(ira, source_instruction, 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,
1095311420 &ptr->value)))
1095411421 {
1095511422 return ira->codegen->invalid_instruction;
......@@ -10959,7 +11426,11 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
1095911426 }
1096011427 }
1096111428 }
10962 // TODO if the instruction is a const ref instruction we can skip it
11429 // 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 }
1096311434 IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,
1096411435 source_instruction->source_node, ptr);
1096511436 load_ptr_instruction->value.type = child_type;
......@@ -11184,10 +11655,13 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio
1118411655 return ir_unreach_error(ira);
1118511656
1118611657 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) {
11188 ErrorMsg *msg = ira->codegen->errors.last();
11189 add_error_note(ira->codegen, msg, ira->explicit_return_type_source_node,
11190 buf_sprintf("return type declared here"));
11658 if (type_is_invalid(casted_value->value.type)) {
11659 AstNode *source_node = ira->explicit_return_type_source_node;
11660 if (source_node != nullptr) {
11661 ErrorMsg *msg = ira->codegen->errors.last();
11662 add_error_note(ira->codegen, msg, source_node,
11663 buf_sprintf("return type declared here"));
11664 }
1119111665 return ir_unreach_error(ira);
1119211666 }
1119311667
......@@ -11206,8 +11680,7 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio
1120611680
1120711681static IrInstruction *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *instruction) {
1120811682 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
11209 // TODO determine if we need to use copy_const_val here
11210 result->value = instruction->base.value;
11683 copy_const_val(&result->value, &instruction->base.value, true);
1121111684 return result;
1121211685}
1121311686
......@@ -11260,28 +11733,36 @@ static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
1126011733}
1126111734
1126211735static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {
11263 if (op_id == IrBinOpCmpEq) {
11264 return cmp == CmpEQ;
11265 } else if (op_id == IrBinOpCmpNotEq) {
11266 return cmp != CmpEQ;
11267 } else if (op_id == IrBinOpCmpLessThan) {
11268 return cmp == CmpLT;
11269 } else if (op_id == IrBinOpCmpGreaterThan) {
11270 return cmp == CmpGT;
11271 } else if (op_id == IrBinOpCmpLessOrEq) {
11272 return cmp != CmpGT;
11273 } else if (op_id == IrBinOpCmpGreaterOrEq) {
11274 return cmp != CmpLT;
11275 } else {
11276 zig_unreachable();
11736 switch (op_id) {
11737 case IrBinOpCmpEq:
11738 return cmp == CmpEQ;
11739 case IrBinOpCmpNotEq:
11740 return cmp != CmpEQ;
11741 case IrBinOpCmpLessThan:
11742 return cmp == CmpLT;
11743 case IrBinOpCmpGreaterThan:
11744 return cmp == CmpGT;
11745 case IrBinOpCmpLessOrEq:
11746 return cmp != CmpGT;
11747 case IrBinOpCmpGreaterOrEq:
11748 return cmp != CmpLT;
11749 default:
11750 zig_unreachable();
1127711751 }
1127811752}
1127911753
1128011754static bool optional_value_is_null(ConstExprValue *val) {
1128111755 assert(val->special == ConstValSpecialStatic);
1128211756 if (get_codegen_ptr_type(val->type) != nullptr) {
11283 return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
11284 val->data.x_ptr.data.hard_coded_addr.addr == 0;
11757 if (val->data.x_ptr.special == ConstPtrSpecialNull) {
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;
1128511766 } else {
1128611767 return val->data.x_optional == nullptr;
1128711768 }
......@@ -11436,13 +11917,13 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1143611917 case ZigTypeIdComptimeInt:
1143711918 case ZigTypeIdInt:
1143811919 case ZigTypeIdFloat:
11920 case ZigTypeIdVector:
1143911921 operator_allowed = true;
1144011922 break;
1144111923
1144211924 case ZigTypeIdBool:
1144311925 case ZigTypeIdMetaType:
1144411926 case ZigTypeIdVoid:
11445 case ZigTypeIdPointer:
1144611927 case ZigTypeIdErrorSet:
1144711928 case ZigTypeIdFn:
1144811929 case ZigTypeIdOpaque:
......@@ -11454,6 +11935,10 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1145411935 operator_allowed = is_equality_cmp;
1145511936 break;
1145611937
11938 case ZigTypeIdPointer:
11939 operator_allowed = is_equality_cmp || (resolved_type->data.pointer.ptr_len == PtrLenC);
11940 break;
11941
1145711942 case ZigTypeIdUnreachable:
1145811943 case ZigTypeIdArray:
1145911944 case ZigTypeIdStruct:
......@@ -11481,19 +11966,18 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1148111966 if (casted_op2 == ira->codegen->invalid_instruction)
1148211967 return ira->codegen->invalid_instruction;
1148311968
11484 bool requires_comptime;
11485 switch (type_requires_comptime(ira->codegen, resolved_type)) {
11486 case ReqCompTimeYes:
11487 requires_comptime = true;
11969 bool one_possible_value;
11970 switch (type_has_one_possible_value(ira->codegen, resolved_type)) {
11971 case OnePossibleValueInvalid:
11972 return ira->codegen->invalid_instruction;
11973 case OnePossibleValueYes:
11974 one_possible_value = true;
1148811975 break;
11489 case ReqCompTimeNo:
11490 requires_comptime = false;
11976 case OnePossibleValueNo:
11977 one_possible_value = false;
1149111978 break;
11492 case ReqCompTimeInvalid:
11493 return ira->codegen->invalid_instruction;
1149411979 }
1149511980
11496 bool one_possible_value = !requires_comptime && !type_has_bits(resolved_type);
1149711981 if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {
1149811982 ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad);
1149911983 if (op1_val == nullptr)
......@@ -11502,15 +11986,38 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1150211986 if (op2_val == nullptr)
1150311987 return ira->codegen->invalid_instruction;
1150411988
11505 bool answer;
1150611989 if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) {
1150711990 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);
1150911993 } else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) {
1151011994 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 }
1151212018 } else {
1151312019 bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val);
12020 bool answer;
1151412021 if (op_id == IrBinOpCmpEq) {
1151512022 answer = are_equal;
1151612023 } else if (op_id == IrBinOpCmpNotEq) {
......@@ -11518,9 +12025,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1151812025 } else {
1151912026 zig_unreachable();
1152012027 }
12028 return ir_const_bool(ira, &bin_op_instruction->base, answer);
1152112029 }
11522
11523 return ir_const_bool(ira, &bin_op_instruction->base, answer);
1152412030 }
1152512031
1152612032 // some comparisons with unsigned numbers can be evaluated
......@@ -11567,8 +12073,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1156712073 return result;
1156812074}
1156912075
11570static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
11571 IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val)
12076static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, IrInstruction *source_instr, ZigType *type_entry,
12077 ConstExprValue *op1_val, IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val)
1157212078{
1157312079 bool is_int;
1157412080 bool is_float;
......@@ -11590,10 +12096,10 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
1159012096 if ((op_id == IrBinOpDivUnspecified || op_id == IrBinOpRemRem || op_id == IrBinOpRemMod ||
1159112097 op_id == IrBinOpDivTrunc || op_id == IrBinOpDivFloor) && op2_zcmp == CmpEQ)
1159212098 {
11593 return ErrorDivByZero;
12099 return ir_add_error(ira, source_instr, buf_sprintf("division by zero"));
1159412100 }
1159512101 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"));
1159712103 }
1159812104
1159912105 switch (op_id) {
......@@ -11639,7 +12145,7 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
1163912145 BigInt orig_bigint;
1164012146 bigint_shl(&orig_bigint, &out_val->data.x_bigint, &op2_val->data.x_bigint);
1164112147 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"));
1164312149 }
1164412150 break;
1164512151 }
......@@ -11707,14 +12213,14 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
1170712213 BigInt remainder;
1170812214 bigint_rem(&remainder, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
1170912215 if (bigint_cmp_zero(&remainder) != CmpEQ) {
11710 return ErrorExactDivRemainder;
12216 return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder"));
1171112217 }
1171212218 } else {
1171312219 float_div_trunc(out_val, op1_val, op2_val);
1171412220 ConstExprValue remainder;
1171512221 float_rem(&remainder, op1_val, op2_val);
1171612222 if (float_cmp_zero(&remainder) != CmpEQ) {
11717 return ErrorExactDivRemainder;
12223 return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder"));
1171812224 }
1171912225 }
1172012226 break;
......@@ -11738,13 +12244,51 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
1173812244 if (!bigint_fits_in_bits(&out_val->data.x_bigint, type_entry->data.integral.bit_count,
1173912245 type_entry->data.integral.is_signed))
1174012246 {
11741 return ErrorOverflow;
12247 return ir_add_error(ira, source_instr, buf_sprintf("operation caused overflow"));
1174212248 }
1174312249 }
1174412250
1174512251 out_val->type = type_entry;
1174612252 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);
1174812292}
1174912293
1175012294static 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
1181612360 if (op2_val == nullptr)
1181712361 return ira->codegen->invalid_instruction;
1181812362
11819 IrInstruction *result_instruction = ir_const(ira, &bin_op_instruction->base, op1->value.type);
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;
12363 return ir_analyze_math_op(ira, &bin_op_instruction->base, op1->value.type, op1_val, op_id, op2_val);
1183712364 } else if (op1->value.type->id == ZigTypeIdComptimeInt) {
1183812365 ir_add_error(ira, &bin_op_instruction->base,
1183912366 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
1185212379 return result;
1185312380}
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
1185512444static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {
12445 Error err;
12446
1185612447 IrInstruction *op1 = instruction->op1->child;
1185712448 if (type_is_invalid(op1->value.type))
1185812449 return ira->codegen->invalid_instruction;
......@@ -11864,13 +12455,44 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
1186412455 IrBinOp op_id = instruction->op_id;
1186512456
1186612457 // look for pointer math
11867 if (op1->value.type->id == ZigTypeIdPointer && op1->value.type->data.pointer.ptr_len == PtrLenUnknown &&
11868 (op_id == IrBinOpAdd || op_id == IrBinOpSub))
11869 {
12458 if (is_pointer_arithmetic_allowed(op1->value.type, op_id)) {
1187012459 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))
1187212461 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
1187412496 IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
1187512497 instruction->base.source_node, op_id, op1, casted_op2, true);
1187612498 result->value.type = op1->value.type;
......@@ -11989,21 +12611,20 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
1198912611 op_id = IrBinOpRemRem;
1199012612 }
1199112613
12614 bool ok = false;
1199212615 if (is_int) {
11993 // int
11994 } else if (is_float &&
11995 (op_id == IrBinOpAdd ||
11996 op_id == IrBinOpSub ||
11997 op_id == IrBinOpMult ||
11998 op_id == IrBinOpDivUnspecified ||
11999 op_id == IrBinOpDivTrunc ||
12000 op_id == IrBinOpDivFloor ||
12001 op_id == IrBinOpDivExact ||
12002 op_id == IrBinOpRemRem ||
12003 op_id == IrBinOpRemMod))
12004 {
12005 // float
12006 } else {
12616 ok = true;
12617 } else if (is_float && ok_float_op(op_id)) {
12618 ok = true;
12619 } else if (resolved_type->id == ZigTypeIdVector) {
12620 ZigType *elem_type = resolved_type->data.vector.elem_type;
12621 if (elem_type->id == ZigTypeIdInt || elem_type->id == ZigTypeIdComptimeInt) {
12622 ok = true;
12623 } else if ((elem_type->id == ZigTypeIdFloat || elem_type->id == ZigTypeIdComptimeFloat) && ok_float_op(op_id)) {
12624 ok = true;
12625 }
12626 }
12627 if (!ok) {
1200712628 AstNode *source_node = instruction->base.source_node;
1200812629 ir_add_error_node(ira, source_node,
1200912630 buf_sprintf("invalid operands to binary expression: '%s' and '%s'",
......@@ -12038,30 +12659,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
1203812659 if (op2_val == nullptr)
1203912660 return ira->codegen->invalid_instruction;
1204012661
12041 IrInstruction *result_instruction = ir_const(ira, &instruction->base, resolved_type);
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;
12662 return ir_analyze_math_op(ira, &instruction->base, resolved_type, op1_val, op_id, op2_val);
1206512663 }
1206612664
1206712665 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
1211512713 op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
1211612714 op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
1211712715 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);
1211912717 } else {
1212012718 ir_add_error(ira, op1,
1212112719 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
1212512723 ConstExprValue *op2_array_val;
1212612724 size_t op2_array_index;
1212712725 size_t op2_array_end;
12726 bool op2_type_valid;
1212812727 if (op2_type->id == ZigTypeIdArray) {
12129 if (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 }
12728 op2_type_valid = op2_type->data.array.child_type == child_type;
1213512729 op2_array_val = op2_val;
1213612730 op2_array_index = 0;
1213712731 op2_array_end = op2_array_val->type->data.array.len;
......@@ -12140,35 +12734,30 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
1214012734 op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray &&
1214112735 op2_val->data.x_ptr.data.base_array.is_cstr)
1214212736 {
12143 if (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 }
12737 op2_type_valid = child_type == ira->codegen->builtin_types.entry_u8;
1214912738 op2_array_val = op2_val->data.x_ptr.data.base_array.array_val;
1215012739 op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index;
1215112740 op2_array_end = op2_array_val->type->data.array.len - 1;
1215212741 } else if (is_slice(op2_type)) {
1215312742 ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index].type_entry;
12154 if (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 }
12743 op2_type_valid = ptr_type->data.pointer.child_type == child_type;
1216012744 ConstExprValue *ptr_val = &op2_val->data.x_struct.fields[slice_ptr_index];
1216112745 assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
1216212746 op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
1216312747 op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
12164 op2_array_end = op2_array_val->type->data.array.len;
1216512748 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);
1216712750 } else {
1216812751 ir_add_error(ira, op2,
1216912752 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));
1217012753 return ira->codegen->invalid_instruction;
1217112754 }
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
1217312762 // The type of result is populated in the following if blocks
1217412763 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
......@@ -12301,26 +12890,14 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
1230112890}
1230212891
1230312892static 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);
1230512894 if (type_is_invalid(op1_type))
1230612895 return ira->codegen->invalid_instruction;
1230712896
12308 if (op1_type->id != ZigTypeIdErrorSet) {
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);
12897 ZigType *op2_type = ir_resolve_error_set_type(ira, &instruction->base, instruction->op2->child);
1231512898 if (type_is_invalid(op2_type))
1231612899 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
1232412901 if (type_is_global_error_set(op1_type) ||
1232512902 type_is_global_error_set(op2_type))
1232612903 {
......@@ -12394,13 +12971,15 @@ static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructio
1239412971 zig_unreachable();
1239512972}
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{
1239812977 Error err;
1239912978 ZigVar *var = decl_var_instruction->var;
1240012979
1240112980 IrInstruction *init_value = decl_var_instruction->init_value->child;
1240212981 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;
1240412983 return ira->codegen->invalid_instruction;
1240512984 }
1240612985
......@@ -12411,7 +12990,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1241112990 ZigType *proposed_type = ir_resolve_type(ira, var_type);
1241212991 explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type);
1241312992 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;
1241512994 return ira->codegen->invalid_instruction;
1241612995 }
1241712996 }
......@@ -12436,7 +13015,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1243613015 case ReqCompTimeInvalid:
1243713016 result_type = ira->codegen->builtin_types.entry_invalid;
1243813017 break;
12439 case ReqCompTimeYes: {
13018 case ReqCompTimeYes:
1244013019 var_class_requires_const = true;
1244113020 if (!var->gen_is_const && !is_comptime_var) {
1244213021 ir_add_error_node(ira, source_node,
......@@ -12445,10 +13024,10 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1244513024 result_type = ira->codegen->builtin_types.entry_invalid;
1244613025 }
1244713026 break;
12448 }
1244913027 case ReqCompTimeNo:
1245013028 if (casted_init_value->value.special == ConstValSpecialStatic &&
1245113029 casted_init_value->value.type->id == ZigTypeIdFn &&
13030 casted_init_value->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
1245213031 casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways)
1245313032 {
1245413033 var_class_requires_const = true;
......@@ -12463,7 +13042,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1246313042 break;
1246413043 }
1246513044
12466 if (var->value->type != nullptr && !is_comptime_var) {
13045 if (var->var_type != nullptr && !is_comptime_var) {
1246713046 // This is at least the second time we've seen this variable declaration during analysis.
1246813047 // This means that this is actually a different variable due to, e.g. an inline while loop.
1246913048 // 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
1248513064 // This must be done after possibly creating a new variable above
1248613065 var->ref_count = 0;
1248713066
12488 var->value->type = result_type;
12489 assert(var->value->type);
13067 var->var_type = result_type;
13068 assert(var->var_type);
1249013069
1249113070 if (type_is_invalid(result_type)) {
1249213071 return ir_const_void(ira, &decl_var_instruction->base);
......@@ -12494,13 +13073,13 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1249413073
1249513074 if (decl_var_instruction->align_value == nullptr) {
1249613075 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;
1249813077 return ir_const_void(ira, &decl_var_instruction->base);
1249913078 }
1250013079 var->align_bytes = get_abi_alignment(ira->codegen, result_type);
1250113080 } else {
1250213081 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;
1250413083 }
1250513084 }
1250613085
......@@ -12517,7 +13096,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1251713096 } else if (is_comptime_var) {
1251813097 ir_add_error(ira, &decl_var_instruction->base,
1251913098 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;
1252113100 return ira->codegen->invalid_instruction;
1252213101 }
1252313102
......@@ -12525,11 +13104,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1252513104 if (fn_entry)
1252613105 fn_entry->variable_list.append(var);
1252713106
12528 IrInstruction *result = ir_build_var_decl(&ira->new_irb,
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;
13107 return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value);
1253313108}
1253413109
1253513110static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {
......@@ -12651,6 +13226,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
1265113226 case ZigTypeIdPointer:
1265213227 case ZigTypeIdArray:
1265313228 case ZigTypeIdBool:
13229 case ZigTypeIdVector:
1265413230 break;
1265513231 case ZigTypeIdMetaType:
1265613232 case ZigTypeIdVoid:
......@@ -12685,6 +13261,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
1268513261 case ZigTypeIdOptional:
1268613262 case ZigTypeIdErrorUnion:
1268713263 case ZigTypeIdErrorSet:
13264 case ZigTypeIdVector:
1268813265 zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name));
1268913266 case ZigTypeIdNamespace:
1269013267 case ZigTypeIdBoundFn:
......@@ -12859,7 +13436,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node
1285913436
1286013437 Buf *param_name = param_decl_node->data.param_decl.name;
1286113438 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);
1286313440 *exec_scope = var->child_scope;
1286413441 *next_proto_i += 1;
1286513442
......@@ -12917,7 +13494,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
1291713494 if (!param_name) return false;
1291813495 if (!is_var_args) {
1291913496 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);
1292113498 *child_scope = var->child_scope;
1292213499 var->shadowable = !comptime_arg;
1292313500
......@@ -12971,9 +13548,7 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) {
1297113548 return fn_entry->variable_list.at(next_var_i);
1297213549}
1297313550
12974static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
12975 ZigVar *var)
12976{
13551static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var) {
1297713552 while (var->next_var != nullptr) {
1297813553 var = var->next_var;
1297913554 }
......@@ -12982,14 +13557,14 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
1298213557 assert(ira->codegen->errors.length != 0);
1298313558 return ira->codegen->invalid_instruction;
1298413559 }
12985 if (var->value->type == nullptr || type_is_invalid(var->value->type))
13560 if (var->var_type == nullptr || type_is_invalid(var->var_type))
1298613561 return ira->codegen->invalid_instruction;
1298713562
1298813563 bool comptime_var_mem = ir_get_var_is_comptime(var);
1298913564
1299013565 ConstExprValue *mem_slot = nullptr;
12991 if (var->value->special == ConstValSpecialStatic) {
12992 mem_slot = var->value;
13566 if (var->const_value->special == ConstValSpecialStatic) {
13567 mem_slot = var->const_value;
1299313568 } else {
1299413569 if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) {
1299513570 // find the relevant exec_context
......@@ -13018,7 +13593,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
1301813593 assert(!comptime_var_mem);
1301913594 ptr_mut = ConstPtrMutRuntimeVar;
1302013595 }
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,
1302213597 ptr_mut, is_const, is_volatile, var->align_bytes);
1302313598 }
1302413599 }
......@@ -13029,7 +13604,7 @@ no_mem_slot:
1302913604
1303013605 IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb,
1303113606 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,
1303313608 var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0);
1303413609
1303513610 bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);
......@@ -13038,6 +13613,96 @@ no_mem_slot:
1303813613 return var_ptr_instruction;
1303913614}
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
1304113706static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction,
1304213707 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
1304313708 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
1318213847 }
1318313848
1318413849 bool cacheable = fn_eval_cacheable(exec_scope, return_type);
13185 IrInstruction *result = nullptr;
13850 ConstExprValue *result = nullptr;
1318613851 if (cacheable) {
1318713852 auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope);
1318813853 if (entry)
......@@ -13194,22 +13859,23 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1319413859 AstNode *body_node = fn_entry->body_node;
1319513860 result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,
1319613861 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
1319913864 if (inferred_err_set_type != nullptr) {
1320013865 inferred_err_set_type->data.error_set.infer_fn = nullptr;
13201 if (result->value.type->id == ZigTypeIdErrorUnion) {
13202 if (result->value.data.x_err_union.err != nullptr) {
13866 if (result->type->id == ZigTypeIdErrorUnion) {
13867 ErrorTableEntry *err = result->data.x_err_union.error_set->data.x_err_set;
13868 if (err != nullptr) {
1320313869 inferred_err_set_type->data.error_set.err_count = 1;
1320413870 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;
1320613872 }
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;
1320813874 inferred_err_set_type->data.error_set.err_count = fn_inferred_err_set_type->data.error_set.err_count;
1320913875 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) {
13211 inferred_err_set_type->data.error_set.err_count = result->value.type->data.error_set.err_count;
13212 inferred_err_set_type->data.error_set.errors = result->value.type->data.error_set.errors;
13876 } else if (result->type->id == ZigTypeIdErrorSet) {
13877 inferred_err_set_type->data.error_set.err_count = result->type->data.error_set.err_count;
13878 inferred_err_set_type->data.error_set.errors = result->type->data.error_set.errors;
1321313879 }
1321413880 }
1321513881
......@@ -13217,13 +13883,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1321713883 ira->codegen->memoized_fn_eval_table.put(exec_scope, result);
1321813884 }
1321913885
13220 if (type_is_invalid(result->value.type))
13886 if (type_is_invalid(result->type))
1322113887 return ira->codegen->invalid_instruction;
1322213888 }
1322313889
13224 IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->value.type);
13225 // TODO should we use copy_const_val?
13226 new_instruction->value = result->value;
13890 IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->type);
13891 copy_const_val(&new_instruction->value, result, true);
1322713892 new_instruction->value.type = return_type;
1322813893 return ir_finish_anal(ira, new_instruction);
1322913894 }
......@@ -13382,18 +14047,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1338214047 ConstExprValue *var_args_val = create_const_arg_tuple(ira->codegen,
1338314048 first_var_arg, inst_fn_type_id.param_count);
1338414049 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);
1338614051 impl_fn->child_scope = var->child_scope;
1338714052 }
1338814053
1338914054 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,
1339114056 fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),
1339214057 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
1339514063 uint32_t align_bytes = 0;
13396 ir_resolve_align(ira, align_result, &align_bytes);
14064 ir_resolve_align(ira, &const_instruction->base, &align_bytes);
1339714065 impl_fn->align_bytes = align_bytes;
1339814066 inst_fn_type_id.alignment = align_bytes;
1339914067 }
......@@ -13471,12 +14139,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1347114139 ira->codegen->fn_defs.append(impl_fn);
1347214140 }
1347314141
13474 ZigType *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type;
13475 if (fn_type_can_fail(&impl_fn->type_entry->data.fn.fn_type_id)) {
14142 FnTypeId *impl_fn_type_id = &impl_fn->type_entry->data.fn.fn_type_id;
14143 if (fn_type_can_fail(impl_fn_type_id)) {
1347614144 parent_fn_entry->calls_or_awaits_errorable_fn = true;
1347714145 }
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;
1348014148 if (call_instruction->is_async) {
1348114149 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,
1348214150 fn_ref, casted_args, impl_param_count, async_allocator_inst);
......@@ -13489,9 +14157,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1348914157 call_instruction->base.scope, call_instruction->base.source_node,
1349014158 impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline,
1349114159 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
1349614164 return ir_finish_anal(ira, new_call_instruction);
1349714165 }
......@@ -13653,39 +14321,87 @@ static IrInstruction *ir_analyze_instruction_call(IrAnalyze *ira, IrInstructionC
1365314321
1365414322// out_val->type must be the type to read the pointer as
1365514323// 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,
1365714325 ConstExprValue *out_val, ConstExprValue *ptr_val)
1365814326{
1365914327 Error err;
1366014328 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)))
1366514333 return ErrorSemanticAnalyzeFail;
13666 if ((err = type_resolve(ira->codegen, out_val->type, ResolveStatusSizeKnown)))
14334 if ((err = type_resolve(codegen, out_val->type, ResolveStatusSizeKnown)))
1366714335 return ErrorSemanticAnalyzeFail;
1366814336
13669 size_t src_size = type_size(ira->codegen, pointee->type);
13670 size_t dst_size = type_size(ira->codegen, out_val->type);
14337 // We don't need to read the padding bytes, so we look at type_size_store bytes
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)) {
13673 copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut == ConstPtrMutComptimeConst);
14341 if (dst_size <= src_size) {
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;
1367414351 return ErrorNone;
1367514352 }
1367614353
13677 if (dst_size > src_size) {
13678 ir_add_error_node(ira, source_node,
13679 buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",
13680 dst_size, buf_ptr(&pointee->type->name), src_size));
13681 return ErrorSemanticAnalyzeFail;
14354 switch (ptr_val->data.x_ptr.special) {
14355 case ConstPtrSpecialInvalid:
14356 zig_unreachable();
14357 case ConstPtrSpecialNull:
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");
1368214403 }
13683
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;
14404 zig_unreachable();
1368914405}
1369014406
1369114407static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
......@@ -13704,6 +14420,7 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_
1370414420 case ZigTypeIdVoid:
1370514421 case ZigTypeIdBool:
1370614422 case ZigTypeIdInt:
14423 case ZigTypeIdVector:
1370714424 case ZigTypeIdFloat:
1370814425 case ZigTypeIdPointer:
1370914426 case ZigTypeIdArray:
......@@ -13875,9 +14592,14 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi
1387514592 if (!ir_resolve_comptime(ira, cond_br_instruction->is_comptime->child, &is_comptime))
1387614593 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)) {
1387914601 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))
1388114603 return ir_unreach_error(ira);
1388214604
1388314605 IrBasicBlock *old_dest_block = cond_is_true ?
......@@ -13896,11 +14618,6 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi
1389614618 return ir_finish_anal(ira, result);
1389714619 }
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
1390414621 assert(cond_br_instruction->then_block != cond_br_instruction->else_block);
1390514622 IrBasicBlock *new_then_block = ir_get_new_bb_runtime(ira, cond_br_instruction->then_block, &cond_br_instruction->base);
1390614623 if (new_then_block == nullptr)
......@@ -13939,8 +14656,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
1393914656
1394014657 if (value->value.special != ConstValSpecialRuntime) {
1394114658 IrInstruction *result = ir_const(ira, &phi_instruction->base, nullptr);
13942 // TODO use copy_const_val?
13943 result->value = value->value;
14659 copy_const_val(&result->value, &value->value, true);
1394414660 return result;
1394514661 } else {
1394614662 return value;
......@@ -13989,14 +14705,24 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
1398914705 if (type_is_invalid(resolved_type))
1399014706 return ira->codegen->invalid_instruction;
1399114707
13992 if (resolved_type->id == ZigTypeIdComptimeFloat ||
13993 resolved_type->id == ZigTypeIdComptimeInt ||
13994 resolved_type->id == ZigTypeIdNull ||
13995 resolved_type->id == ZigTypeIdUndefined)
13996 {
14708 switch (type_has_one_possible_value(ira->codegen, resolved_type)) {
14709 case OnePossibleValueInvalid:
14710 return ira->codegen->invalid_instruction;
14711 case OnePossibleValueYes:
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:
1399714721 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)));
1399914723 return ira->codegen->invalid_instruction;
14724 case ReqCompTimeNo:
14725 break;
1400014726 }
1400114727
1400214728 bool all_stack_ptrs = (resolved_type->id == ZigTypeIdPointer);
......@@ -14112,7 +14838,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1411214838 array_type = array_type->data.pointer.child_type;
1411314839 ptr_type = ptr_type->data.pointer.child_type;
1411414840 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,
1411614842 elem_ptr_instruction->base.source_node);
1411714843 if (orig_array_ptr_val == nullptr)
1411814844 return ira->codegen->invalid_instruction;
......@@ -14156,7 +14882,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1415614882 ConstExprValue *ptr_val = ir_resolve_const(ira, array_ptr, UndefBad);
1415714883 if (!ptr_val)
1415814884 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);
1416014886 if (args_val == nullptr)
1416114887 return ira->codegen->invalid_instruction;
1416214888 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
1423814964 (orig_array_ptr_val->data.x_ptr.mut != ConstPtrMutRuntimeVar ||
1423914965 array_type->id == ZigTypeIdArray))
1424014966 {
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,
1424214968 elem_ptr_instruction->base.source_node);
1424314969 if (array_ptr_val == nullptr)
1424414970 return ira->codegen->invalid_instruction;
......@@ -14286,10 +15012,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1428615012 }
1428715013 case ConstPtrSpecialBaseStruct:
1428815014 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");
1428915021 case ConstPtrSpecialHardCodedAddr:
1429015022 zig_unreachable();
1429115023 case ConstPtrSpecialFunction:
1429215024 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");
1429315027 }
1429415028 if (new_index >= mem_size) {
1429515029 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
1433915073 }
1434015074 case ConstPtrSpecialBaseStruct:
1434115075 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");
1434215082 case ConstPtrSpecialHardCodedAddr:
1434315083 zig_unreachable();
1434415084 case ConstPtrSpecialFunction:
1434515085 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");
1434615088 }
1434715089 return result;
1434815090 } else if (array_type->id == ZigTypeIdArray) {
......@@ -14457,13 +15199,12 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
1445715199 return ira->codegen->invalid_instruction;
1445815200
1445915201 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);
1446115203 if (struct_val == nullptr)
1446215204 return ira->codegen->invalid_instruction;
1446315205 if (type_is_invalid(struct_val->type))
1446415206 return ira->codegen->invalid_instruction;
14465 ConstExprValue *field_val = &struct_val->data.x_struct.fields[field->src_index];
14466 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_val->type,
15207 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,
1446715208 is_const, is_volatile, PtrLenSingle, align_bytes,
1446815209 (uint32_t)(ptr_bit_offset + field->bit_offset_in_host),
1446915210 (uint32_t)host_int_bytes_for_result_type);
......@@ -14500,7 +15241,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
1450015241 return ira->codegen->invalid_instruction;
1450115242
1450215243 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);
1450415245 if (union_val == nullptr)
1450515246 return ira->codegen->invalid_instruction;
1450615247 if (type_is_invalid(union_val->type))
......@@ -14697,7 +15438,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
1469715438 return ira->codegen->invalid_instruction;
1469815439
1469915440 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);
1470115442 if (child_val == nullptr)
1470215443 return ira->codegen->invalid_instruction;
1470315444
......@@ -14723,7 +15464,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
1472315464 return ira->codegen->invalid_instruction;
1472415465
1472515466 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);
1472715468 if (child_val == nullptr)
1472815469 return ira->codegen->invalid_instruction;
1472915470 ZigType *child_type = child_val->data.x_type;
......@@ -14998,7 +15739,7 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
1499815739 if (!container_ptr_val)
1499915740 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,
1500215743 field_ptr_instruction->base.source_node);
1500315744 if (namespace_val == nullptr)
1500415745 return ira->codegen->invalid_instruction;
......@@ -15030,74 +15771,23 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
1503015771 }
1503115772}
1503215773
15033static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) {
15034 IrInstruction *ptr = load_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;
15774static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *instruction) {
15775 IrInstruction *ptr = instruction->ptr->child;
1504215776 if (type_is_invalid(ptr->value.type))
1504315777 return ira->codegen->invalid_instruction;
1504415778
15045 IrInstruction *value = store_ptr_instruction->value->child;
15779 IrInstruction *value = instruction->value->child;
1504615780 if (type_is_invalid(value->value.type))
1504715781 return ira->codegen->invalid_instruction;
1504815782
15049 if (ptr->value.type->id != ZigTypeIdPointer) {
15050 ir_add_error(ira, ptr,
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 }
15783 return ir_analyze_store_ptr(ira, &instruction->base, ptr, value);
15784}
1506315785
15064 ZigType *child_type = ptr->value.type->data.pointer.child_type;
15065 IrInstruction *casted_value = ir_implicit_cast(ira, value, child_type);
15066 if (casted_value == ira->codegen->invalid_instruction)
15786static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *instruction) {
15787 IrInstruction *ptr = instruction->ptr->child;
15788 if (type_is_invalid(ptr->value.type))
1506715789 return ira->codegen->invalid_instruction;
15068
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;
15790 return ir_get_deref(ira, &instruction->base, ptr);
1510115791}
1510215792
1510315793static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) {
......@@ -15105,42 +15795,14 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio
1510515795 ZigType *type_entry = expr_value->value.type;
1510615796 if (type_is_invalid(type_entry))
1510715797 return ira->codegen->invalid_instruction;
15108 switch (type_entry->id) {
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();
15798 return ir_const_type(ira, &typeof_instruction->base, type_entry);
1513915799}
1514015800
1514115801static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
1514215802 IrInstructionToPtrType *to_ptr_type_instruction)
1514315803{
15804 Error err;
15805
1514415806 IrInstruction *value = to_ptr_type_instruction->value->child;
1514515807 ZigType *type_entry = value->value.type;
1514615808 if (type_is_invalid(type_entry))
......@@ -15156,7 +15818,17 @@ static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
1515615818 ptr_type = get_pointer_to_type(ira->codegen,
1515715819 type_entry->data.pointer.child_type->data.array.child_type, type_entry->data.pointer.is_const);
1515815820 } 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 }
1516015832 } else if (type_entry->id == ZigTypeIdArgTuple) {
1516115833 ConstExprValue *arg_tuple_val = ir_resolve_const(ira, value, UndefBad);
1516215834 if (!arg_tuple_val)
......@@ -15374,6 +16046,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
1537416046 case ZigTypeIdNamespace:
1537516047 case ZigTypeIdBoundFn:
1537616048 case ZigTypeIdPromise:
16049 case ZigTypeIdVector:
1537716050 {
1537816051 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
1537916052 return ira->codegen->invalid_instruction;
......@@ -15494,6 +16167,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
1549416167 case ZigTypeIdNamespace:
1549516168 case ZigTypeIdBoundFn:
1549616169 case ZigTypeIdPromise:
16170 case ZigTypeIdVector:
1549716171 {
1549816172 if ((err = ensure_complete_type(ira->codegen, child_type)))
1549916173 return ira->codegen->invalid_instruction;
......@@ -15560,6 +16234,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
1556016234 case ZigTypeIdUnion:
1556116235 case ZigTypeIdFn:
1556216236 case ZigTypeIdPromise:
16237 case ZigTypeIdVector:
1556316238 {
1556416239 uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
1556516240 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,
1556816243 zig_unreachable();
1556916244}
1557016245
15571static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) {
15572 IrInstruction *value = instruction->value->child;
15573 if (type_is_invalid(value->value.type))
15574 return ira->codegen->invalid_instruction;
15575
16246static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value) {
1557616247 ZigType *type_entry = value->value.type;
1557716248
1557816249 if (type_entry->id == ZigTypeIdOptional) {
......@@ -15581,60 +16252,66 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns
1558116252 if (!maybe_val)
1558216253 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));
1558516256 }
1558616257
1558716258 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);
1558916260 result->value.type = ira->codegen->builtin_types.entry_bool;
1559016261 return result;
1559116262 } else if (type_entry->id == ZigTypeIdNull) {
15592 return ir_const_bool(ira, &instruction->base, false);
16263 return ir_const_bool(ira, source_inst, false);
1559316264 } else {
15594 return ir_const_bool(ira, &instruction->base, true);
16265 return ir_const_bool(ira, source_inst, true);
1559516266 }
1559616267}
1559716268
15598static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
15599 IrInstructionUnwrapOptional *unwrap_maybe_instruction)
15600{
15601 IrInstruction *value = unwrap_maybe_instruction->value->child;
16269static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) {
16270 IrInstruction *value = instruction->value->child;
1560216271 if (type_is_invalid(value->value.type))
1560316272 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;
1560616281 assert(ptr_type->id == ZigTypeIdPointer);
1560716282
1560816283 ZigType *type_entry = ptr_type->data.pointer.child_type;
15609 if (type_is_invalid(type_entry)) {
16284 if (type_is_invalid(type_entry))
1561016285 return ira->codegen->invalid_instruction;
15611 } else if (type_entry->id != ZigTypeIdOptional) {
15612 ir_add_error_node(ira, unwrap_maybe_instruction->value->source_node,
16286
16287 if (type_entry->id != ZigTypeIdOptional) {
16288 ir_add_error_node(ira, base_ptr->source_node,
1561316289 buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name)));
1561416290 return ira->codegen->invalid_instruction;
1561516291 }
16292
1561616293 ZigType *child_type = type_entry->data.maybe.child_type;
1561716294 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
1561816295 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0);
1561916296
15620 if (instr_is_comptime(value)) {
15621 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
16297 if (instr_is_comptime(base_ptr)) {
16298 ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad);
1562216299 if (!val)
1562316300 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);
1562516302 if (maybe_val == nullptr)
1562616303 return ira->codegen->invalid_instruction;
1562716304
1562816305 if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
1562916306 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"));
1563116308 return ira->codegen->invalid_instruction;
1563216309 }
15633 IrInstruction *result = ir_const(ira, &unwrap_maybe_instruction->base, result_type);
16310 IrInstruction *result = ir_const(ira, source_instr, result_type);
1563416311 ConstExprValue *out_val = &result->value;
1563516312 out_val->data.x_ptr.special = ConstPtrSpecialRef;
1563616313 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)) {
1563816315 out_val->data.x_ptr.data.ref.pointee = maybe_val;
1563916316 } else {
1564016317 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,
1564316320 }
1564416321 }
1564516322
15646 IrInstruction *result = ir_build_unwrap_maybe(&ira->new_irb,
15647 unwrap_maybe_instruction->base.scope, unwrap_maybe_instruction->base.source_node,
15648 value, unwrap_maybe_instruction->safety_check_on);
16323 IrInstruction *result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope,
16324 source_instr->source_node, base_ptr, safety_check_on);
1564916325 result->value.type = result_type;
1565016326 return result;
1565116327}
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
1565316339static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) {
1565416340 IrInstruction *value = ctz_instruction->value->child;
1565516341 if (type_is_invalid(value->value.type)) {
......@@ -15918,10 +16604,10 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1591816604 ZigType *target_type = target_value_ptr->value.type->data.pointer.child_type;
1591916605 ConstExprValue *pointee_val = nullptr;
1592016606 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);
1592216608 if (pointee_val == nullptr)
1592316609 return ira->codegen->invalid_instruction;
15924
16610
1592516611 if (pointee_val->special == ConstValSpecialRuntime)
1592616612 pointee_val = nullptr;
1592716613 }
......@@ -15950,9 +16636,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1595016636 return result;
1595116637 }
1595216638
15953 IrInstruction *result = ir_build_load_ptr(&ira->new_irb,
15954 switch_target_instruction->base.scope, switch_target_instruction->base.source_node,
15955 target_value_ptr);
16639 IrInstruction *result = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
1595616640 result->value.type = target_type;
1595716641 return result;
1595816642 }
......@@ -15982,8 +16666,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1598216666 return result;
1598316667 }
1598416668
15985 IrInstruction *union_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,
15986 switch_target_instruction->base.source_node, target_value_ptr);
16669 IrInstruction *union_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
1598716670 union_value->value.type = target_type;
1598816671
1598916672 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,
1600716690 return result;
1600816691 }
1600916692
16010 IrInstruction *enum_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,
16011 switch_target_instruction->base.source_node, target_value_ptr);
16693 IrInstruction *enum_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
1601216694 enum_value->value.type = target_type;
1601316695 return enum_value;
1601416696 }
......@@ -16022,6 +16704,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1602216704 case ZigTypeIdBoundFn:
1602316705 case ZigTypeIdArgTuple:
1602416706 case ZigTypeIdOpaque:
16707 case ZigTypeIdVector:
1602516708 ir_add_error(ira, &switch_target_instruction->base,
1602616709 buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name)));
1602716710 return ira->codegen->invalid_instruction;
......@@ -16053,7 +16736,7 @@ static IrInstruction *ir_analyze_instruction_switch_var(IrAnalyze *ira, IrInstru
1605316736 if (!target_value_ptr)
1605416737 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);
1605716740 if (pointee_val == nullptr)
1605816741 return ira->codegen->invalid_instruction;
1605916742
......@@ -16165,7 +16848,7 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
1616516848 Error err;
1616616849 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)))
1616916852 return ira->codegen->invalid_instruction;
1617016853
1617116854 if (instr_field_count != 1) {
......@@ -16197,7 +16880,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
1619716880 if ((err = type_resolve(ira->codegen, casted_field_value->value.type, ResolveStatusZeroBitsKnown)))
1619816881 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;
1620116885 if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime ||
1620216886 !type_has_bits(casted_field_value->value.type))
1620316887 {
......@@ -16209,12 +16893,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
1620916893 ConstExprValue *out_val = &result->value;
1621016894 out_val->data.x_union.payload = field_val;
1621116895 out_val->data.x_union.tag = type_field->enum_field->value;
16212
16213 ConstParent *parent = get_const_val_parent(ira->codegen, field_val);
16214 if (parent != nullptr) {
16215 parent->id = ConstParentIdUnion;
16216 parent->data.p_union.union_val = out_val;
16217 }
16896 out_val->parent.id = ConstParentIdUnion;
16897 out_val->parent.data.p_union.union_val = out_val;
1621816898
1621916899 return result;
1622016900 }
......@@ -16241,7 +16921,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1624116921 return ira->codegen->invalid_instruction;
1624216922 }
1624316923
16244 if ((err = ensure_complete_type(ira->codegen, container_type)))
16924 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
1624516925 return ira->codegen->invalid_instruction;
1624616926
1624716927 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
1625216932
1625316933 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
1625716938 ConstExprValue const_val = {};
1625816939 const_val.special = ConstValSpecialStatic;
......@@ -16320,9 +17001,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1632017001 if (const_val.special == ConstValSpecialStatic) {
1632117002 IrInstruction *result = ir_const(ira, instruction, nullptr);
1632217003 ConstExprValue *out_val = &result->value;
16323 // TODO copy_const_val?
16324 *out_val = const_val;
16325 result->value.type = container_type;
17004 copy_const_val(out_val, &const_val, true);
17005 out_val->type = container_type;
1632617006
1632717007 for (size_t i = 0; i < instr_field_count; i += 1) {
1632817008 ConstExprValue *field_val = &out_val->data.x_struct.fields[i];
......@@ -16354,127 +17034,119 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1635417034static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
1635517035 IrInstructionContainerInitList *instruction)
1635617036{
16357 IrInstruction *container_type_value = instruction->container_type->child;
16358 if (type_is_invalid(container_type_value->value.type))
17037 ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
17038 if (type_is_invalid(container_type))
1635917039 return ira->codegen->invalid_instruction;
1636017040
1636117041 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) {
16368 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
16369 0, nullptr);
16370 } 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 wrong
16372 ZigType *child_type;
16373 if (container_type->id == ZigTypeIdArray) {
16374 child_type = container_type->data.array.child_type;
16375 if (container_type->data.array.len != elem_count) {
16376 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
17043 if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {
17044 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
17045 0, nullptr);
17046 } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) {
17047 // array is same as slice init but we make a compile error if the length is wrong
17048 ZigType *child_type;
17049 if (container_type->id == ZigTypeIdArray) {
17050 child_type = container_type->data.array.child_type;
17051 if (container_type->data.array.len != elem_count) {
17052 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
1637717053
16378 ir_add_error(ira, &instruction->base,
16379 buf_sprintf("expected %s literal, found %s literal",
16380 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
16381 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;
17054 ir_add_error(ira, &instruction->base,
17055 buf_sprintf("expected %s literal, found %s literal",
17056 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
17057 return ira->codegen->invalid_instruction;
1638717058 }
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 = {};
16392 const_val.special = ConstValSpecialStatic;
16393 const_val.type = fixed_size_array_type;
16394 const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);
17067 ConstExprValue const_val = {};
17068 const_val.special = ConstValSpecialStatic;
17069 const_val.type = fixed_size_array_type;
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) {
16403 IrInstruction *arg_value = instruction->items[i]->child;
16404 if (type_is_invalid(arg_value->value.type))
16405 return ira->codegen->invalid_instruction;
17078 for (size_t i = 0; i < elem_count; i += 1) {
17079 IrInstruction *arg_value = instruction->items[i]->child;
17080 if (type_is_invalid(arg_value->value.type))
17081 return ira->codegen->invalid_instruction;
1640617082
16407 IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);
16408 if (casted_arg == ira->codegen->invalid_instruction)
16409 return ira->codegen->invalid_instruction;
17083 IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);
17084 if (casted_arg == 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) {
16414 if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {
16415 ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);
16416 if (!elem_val)
16417 return ira->codegen->invalid_instruction;
17089 if (const_val.special == ConstValSpecialStatic) {
17090 if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {
17091 ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);
17092 if (!elem_val)
17093 return ira->codegen->invalid_instruction;
1641817094
16419 copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);
16420 } else {
16421 first_non_const_instruction = casted_arg;
16422 const_val.special = ConstValSpecialRuntime;
16423 }
17095 copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);
17096 } else {
17097 first_non_const_instruction = casted_arg;
17098 const_val.special = ConstValSpecialRuntime;
1642417099 }
1642517100 }
17101 }
1642617102
16427 if (const_val.special == ConstValSpecialStatic) {
16428 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
16429 ConstExprValue *out_val = &result->value;
16430 // TODO copy_const_val?
16431 *out_val = const_val;
16432 result->value.type = fixed_size_array_type;
16433 for (size_t i = 0; i < elem_count; i += 1) {
16434 ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];
16435 ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);
16436 if (parent != nullptr) {
16437 parent->id = ConstParentIdArray;
16438 parent->data.p_array.array_val = out_val;
16439 parent->data.p_array.elem_index = i;
16440 }
17103 if (const_val.special == ConstValSpecialStatic) {
17104 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
17105 ConstExprValue *out_val = &result->value;
17106 copy_const_val(out_val, &const_val, true);
17107 result->value.type = fixed_size_array_type;
17108 for (size_t i = 0; i < elem_count; i += 1) {
17109 ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];
17110 ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);
17111 if (parent != nullptr) {
17112 parent->id = ConstParentIdArray;
17113 parent->data.p_array.array_val = out_val;
17114 parent->data.p_array.elem_index = i;
1644117115 }
16442 return result;
1644317116 }
17117 return result;
17118 }
1644417119
16445 if (is_comptime) {
16446 ir_add_error_node(ira, first_non_const_instruction->source_node,
16447 buf_sprintf("unable to evaluate constant expression"));
16448 return ira->codegen->invalid_instruction;
16449 }
17120 if (is_comptime) {
17121 ir_add_error_node(ira, first_non_const_instruction->source_node,
17122 buf_sprintf("unable to evaluate constant expression"));
17123 return ira->codegen->invalid_instruction;
17124 }
1645017125
16451 IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,
16452 instruction->base.scope, instruction->base.source_node,
16453 container_type_value, elem_count, new_items);
16454 new_instruction->value.type = fixed_size_array_type;
16455 ir_add_alloca(ira, new_instruction, fixed_size_array_type);
16456 return new_instruction;
16457 } else if (container_type->id == ZigTypeIdVoid) {
16458 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 {
17126 IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,
17127 instruction->base.scope, instruction->base.source_node,
17128 nullptr, elem_count, new_items);
17129 new_instruction->value.type = fixed_size_array_type;
17130 ir_add_alloca(ira, new_instruction, fixed_size_array_type);
17131 return new_instruction;
17132 } else if (container_type->id == ZigTypeIdVoid) {
17133 if (elem_count != 0) {
1646517134 ir_add_error_node(ira, instruction->base.source_node,
16466 buf_sprintf("type '%s' does not support array initialization",
16467 buf_ptr(&container_type->name)));
17135 buf_sprintf("void expression expects no arguments"));
1646817136 return ira->codegen->invalid_instruction;
1646917137 }
17138 return ir_const_void(ira, &instruction->base);
1647017139 } else {
16471 ir_add_error(ira, container_type_value,
16472 buf_sprintf("expected type, found '%s' value", buf_ptr(&container_type_value->value.type->name)));
17140 ir_add_error_node(ira, instruction->base.source_node,
17141 buf_sprintf("type '%s' does not support array initialization",
17142 buf_ptr(&container_type->name)));
1647317143 return ira->codegen->invalid_instruction;
1647417144 }
1647517145}
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{
1647817150 IrInstruction *container_type_value = instruction->container_type->child;
1647917151 ZigType *container_type = ir_resolve_type(ira, container_type_value);
1648017152 if (type_is_invalid(container_type))
......@@ -16534,7 +17206,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct
1653417206 if (type_is_invalid(value->value.type))
1653517207 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);
1653817210 if (type_is_invalid(casted_value->value.type))
1653917211 return ira->codegen->invalid_instruction;
1654017212
......@@ -16685,7 +17357,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
1668517357static TypeStructField *validate_byte_offset(IrAnalyze *ira,
1668617358 IrInstruction *type_value,
1668717359 IrInstruction *field_name_value,
16688 size_t *byte_offset)
17360 size_t *byte_offset)
1668917361{
1669017362 ZigType *container_type = ir_resolve_type(ira, type_value);
1669117363 if (type_is_invalid(container_type))
......@@ -16768,16 +17440,12 @@ static void ensure_field_index(ZigType *type, const char *field_name, size_t ind
1676817440
1676917441static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, ZigType *root) {
1677017442 Error err;
16771 static ConstExprValue *type_info_var = nullptr; // TODO oops this global variable made it past code review
16772 static ZigType *type_info_type = nullptr; // TODO oops this global variable made it past code review
16773 if (type_info_var == nullptr) {
16774 type_info_var = get_builtin_value(ira->codegen, "TypeInfo");
16775 assert(type_info_var->type->id == ZigTypeIdMetaType);
17443 ConstExprValue *type_info_var = get_builtin_value(ira->codegen, "TypeInfo");
17444 assert(type_info_var->type->id == ZigTypeIdMetaType);
17445 assertNoError(ensure_complete_type(ira->codegen, type_info_var->data.x_type));
1677617446
16777 assertNoError(ensure_complete_type(ira->codegen, type_info_var->data.x_type));
16778 type_info_type = type_info_var->data.x_type;
16779 assert(type_info_type->id == ZigTypeIdUnion);
16780 }
17447 ZigType *type_info_type = type_info_var->data.x_type;
17448 assert(type_info_type->id == ZigTypeIdUnion);
1678117449
1678217450 if (type_name == nullptr && root == nullptr)
1678317451 return type_info_type;
......@@ -16799,10 +17467,11 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig
1679917467
1680017468 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)))
1680317471 return ira->codegen->builtin_types.entry_invalid;
16804 assert(var->value->type->id == ZigTypeIdMetaType);
16805 return var->value->data.x_type;
17472
17473 assert(var->const_value->type->id == ZigTypeIdMetaType);
17474 return var->const_value->data.x_type;
1680617475}
1680717476
1680817477static 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
1685717526 definition_array->special = ConstValSpecialStatic;
1685817527 definition_array->type = get_array_type(ira->codegen, type_info_definition_type, definition_count);
1685917528 definition_array->data.x_array.special = ConstArraySpecialNone;
16860 definition_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1686117529 definition_array->data.x_array.data.s_none.elements = create_const_vals(definition_count);
1686217530 init_const_slice(ira->codegen, out_val, definition_array, 0, definition_count, false);
1686317531
1686417532 // Loop through the definitions and generate info.
1686517533 decl_it = decls_scope->decl_table.entry_iterator();
16866 curr_entry = nullptr;
17534 curr_entry = nullptr;
1686717535 int definition_index = 0;
1686817536 while ((curr_entry = decl_it.next()) != nullptr) {
1686917537 // Skip comptime blocks and test functions.
......@@ -16888,33 +17556,30 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
1688817556 inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub;
1688917557 inner_fields[2].special = ConstValSpecialStatic;
1689017558 inner_fields[2].type = type_info_definition_data_type;
16891 inner_fields[2].data.x_union.parent.id = ConstParentIdStruct;
16892 inner_fields[2].data.x_union.parent.data.p_struct.struct_val = definition_val;
16893 inner_fields[2].data.x_union.parent.data.p_struct.field_index = 1;
17559 inner_fields[2].parent.id = ConstParentIdStruct;
17560 inner_fields[2].parent.data.p_struct.struct_val = definition_val;
17561 inner_fields[2].parent.data.p_struct.field_index = 1;
1689417562
1689517563 switch (curr_entry->value->id) {
1689617564 case TldIdVar:
1689717565 {
1689817566 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)))
1690017568 return ErrorSemanticAnalyzeFail;
1690117569
16902 if (var->value->type->id == ZigTypeIdMetaType)
16903 {
17570 if (var->const_value->type->id == ZigTypeIdMetaType) {
1690417571 // We have a variable of type 'type', so it's actually a type definition.
1690517572 // 0: Data.Type: type
1690617573 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0);
16907 inner_fields[2].data.x_union.payload = var->value;
16908 }
16909 else
16910 {
17574 inner_fields[2].data.x_union.payload = var->const_value;
17575 } else {
1691117576 // We have a variable of another type, so we store the type of the variable.
1691217577 // 1: Data.Var: type
1691317578 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 1);
1691417579
1691517580 ConstExprValue *payload = create_const_vals(1);
1691617581 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
1691917584 inner_fields[2].data.x_union.payload = payload;
1692017585 }
......@@ -16934,8 +17599,8 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
1693417599 ConstExprValue *fn_def_val = create_const_vals(1);
1693517600 fn_def_val->special = ConstValSpecialStatic;
1693617601 fn_def_val->type = type_info_fn_def_type;
16937 fn_def_val->data.x_struct.parent.id = ConstParentIdUnion;
16938 fn_def_val->data.x_struct.parent.data.p_union.union_val = &inner_fields[2];
17602 fn_def_val->parent.id = ConstParentIdUnion;
17603 fn_def_val->parent.data.p_union.union_val = &inner_fields[2];
1693917604
1694017605 ConstExprValue *fn_def_fields = create_const_vals(9);
1694117606 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
1699017655 ensure_field_index(fn_def_val->type, "return_type", 7);
1699117656 fn_def_fields[7].special = ConstValSpecialStatic;
1699217657 fn_def_fields[7].type = ira->codegen->builtin_types.entry_type;
16993 if (fn_entry->src_implicit_return_type != nullptr)
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;
17658 fn_def_fields[7].data.x_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
1699917659 // arg_names: [][] const u8
1700017660 ensure_field_index(fn_def_val->type, "arg_names", 8);
1700117661 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
1700417664 fn_arg_name_array->type = get_array_type(ira->codegen,
1700517665 get_slice_type(ira->codegen, u8_ptr), fn_arg_count);
1700617666 fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;
17007 fn_arg_name_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1700817667 fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
1700917668
1701017669 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++)
17013 {
17671 for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) {
1701417672 ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index);
1701517673 ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index];
1701617674 ConstExprValue *arg_name = create_const_str_lit(ira->codegen, &arg_var->name);
1701717675 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;
17019 fn_arg_name_val->data.x_struct.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;
17676 fn_arg_name_val->parent.id = ConstParentIdArray;
17677 fn_arg_name_val->parent.data.p_array.array_val = fn_arg_name_array;
17678 fn_arg_name_val->parent.data.p_array.elem_index = fn_arg_index;
1702117679 }
1702217680
1702317681 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
1705217710 return ErrorNone;
1705317711}
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
1705517725static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) {
1705617726 Error err;
1705717727 ZigType *attrs_type;
......@@ -17061,7 +17731,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
1706117731 size_enum_index = 2;
1706217732 } else if (ptr_type_entry->id == ZigTypeIdPointer) {
1706317733 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);
1706517735 } else {
1706617736 zig_unreachable();
1706717737 }
......@@ -17129,21 +17799,16 @@ static void make_enum_field_val(IrAnalyze *ira, ConstExprValue *enum_field_val,
1712917799 enum_field_val->data.x_struct.fields = inner_fields;
1713017800}
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) {
1713317803 Error err;
1713417804 assert(type_entry != nullptr);
1713517805 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)))
1713817808 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
1714417810 ConstExprValue *result = nullptr;
17145 switch (type_entry->id)
17146 {
17811 switch (type_entry->id) {
1714717812 case ZigTypeIdInvalid:
1714817813 zig_unreachable();
1714917814 case ZigTypeIdMetaType:
......@@ -17238,6 +17903,27 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1723817903
1723917904 break;
1724017905 }
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 }
1724117927 case ZigTypeIdOptional:
1724217928 {
1724317929 result = create_const_vals(1);
......@@ -17310,7 +17996,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1731017996 enum_field_array->special = ConstValSpecialStatic;
1731117997 enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count);
1731217998 enum_field_array->data.x_array.special = ConstArraySpecialNone;
17313 enum_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1731417999 enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count);
1731518000
1731618001 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
1732018005 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index];
1732118006 ConstExprValue *enum_field_val = &enum_field_array->data.x_array.data.s_none.elements[enum_field_index];
1732218007 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;
17324 enum_field_val->data.x_struct.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;
18008 enum_field_val->parent.id = ConstParentIdArray;
18009 enum_field_val->parent.data.p_array.array_val = enum_field_array;
18010 enum_field_val->parent.data.p_array.elem_index = enum_field_index;
1732618011 }
1732718012 // defs: []TypeInfo.Definition
1732818013 ensure_field_index(result->type, "defs", 3);
......@@ -17344,12 +18029,20 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1734418029 ensure_field_index(result->type, "errors", 0);
1734518030
1734618031 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
1734718041 uint32_t error_count = type_entry->data.error_set.err_count;
1734818042 ConstExprValue *error_array = create_const_vals(1);
1734918043 error_array->special = ConstValSpecialStatic;
1735018044 error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count);
1735118045 error_array->data.x_array.special = ConstArraySpecialNone;
17352 error_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1735318046 error_array->data.x_array.data.s_none.elements = create_const_vals(error_count);
1735418047
1735518048 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
1737318066 bigint_init_unsigned(&inner_fields[1].data.x_bigint, error->value);
1737418067
1737518068 error_val->data.x_struct.fields = inner_fields;
17376 error_val->data.x_struct.parent.id = ConstParentIdArray;
17377 error_val->data.x_struct.parent.data.p_array.array_val = error_array;
17378 error_val->data.x_struct.parent.data.p_array.elem_index = error_index;
18069 error_val->parent.id = ConstParentIdArray;
18070 error_val->parent.data.p_array.array_val = error_array;
18071 error_val->parent.data.p_array.elem_index = error_index;
1737918072 }
1738018073
1738118074 break;
......@@ -17444,7 +18137,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1744418137 union_field_array->special = ConstValSpecialStatic;
1744518138 union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count);
1744618139 union_field_array->data.x_array.special = ConstArraySpecialNone;
17447 union_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1744818140 union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count);
1744918141
1745018142 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
1747718169 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true);
1747818170
1747918171 union_field_val->data.x_struct.fields = inner_fields;
17480 union_field_val->data.x_struct.parent.id = ConstParentIdArray;
17481 union_field_val->data.x_struct.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;
18172 union_field_val->parent.id = ConstParentIdArray;
18173 union_field_val->parent.data.p_array.array_val = union_field_array;
18174 union_field_val->parent.data.p_array.elem_index = union_field_index;
1748318175 }
1748418176 // defs: []TypeInfo.Definition
1748518177 ensure_field_index(result->type, "defs", 3);
......@@ -17519,7 +18211,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1751918211 struct_field_array->special = ConstValSpecialStatic;
1752018212 struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count);
1752118213 struct_field_array->data.x_array.special = ConstArraySpecialNone;
17522 struct_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1752318214 struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count);
1752418215
1752518216 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
1755318244 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(struct_field->name), true);
1755418245
1755518246 struct_field_val->data.x_struct.fields = inner_fields;
17556 struct_field_val->data.x_struct.parent.id = ConstParentIdArray;
17557 struct_field_val->data.x_struct.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;
18247 struct_field_val->parent.id = ConstParentIdArray;
18248 struct_field_val->parent.data.p_array.array_val = struct_field_array;
18249 struct_field_val->parent.data.p_array.elem_index = struct_field_index;
1755918250 }
1756018251 // defs: []TypeInfo.Definition
1756118252 ensure_field_index(result->type, "defs", 2);
......@@ -17625,7 +18316,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1762518316 fn_arg_array->special = ConstValSpecialStatic;
1762618317 fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count);
1762718318 fn_arg_array->data.x_array.special = ConstArraySpecialNone;
17628 fn_arg_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1762918319 fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
1763018320
1763118321 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
1766218352 }
1766318353
1766418354 fn_arg_val->data.x_struct.fields = inner_fields;
17665 fn_arg_val->data.x_struct.parent.id = ConstParentIdArray;
17666 fn_arg_val->data.x_struct.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;
18355 fn_arg_val->parent.id = ConstParentIdArray;
18356 fn_arg_val->parent.data.p_array.array_val = fn_arg_array;
18357 fn_arg_val->parent.data.p_array.elem_index = fn_arg_index;
1766818358 }
1766918359
1767018360 break;
......@@ -17673,7 +18363,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1767318363 {
1767418364 ZigType *fn_type = type_entry->data.bound_fn.fn_type;
1767518365 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)))
1767718367 return err;
1767818368
1767918369 break;
......@@ -17698,7 +18388,7 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira,
1769818388 ZigType *result_type = ir_type_info_get_type(ira, nullptr, nullptr);
1769918389
1770018390 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)))
1770218392 return ira->codegen->invalid_instruction;
1770318393
1770418394 IrInstruction *result = ir_const(ira, &instruction->base, result_type);
......@@ -17708,8 +18398,8 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira,
1770818398
1770918399 if (payload != nullptr) {
1771018400 assert(payload->type->id == ZigTypeIdStruct);
17711 payload->data.x_struct.parent.id = ConstParentIdUnion;
17712 payload->data.x_struct.parent.data.p_union.union_val = out_val;
18401 payload->parent.id = ConstParentIdUnion;
18402 payload->parent.data.p_union.union_val = out_val;
1771318403 }
1771418404
1771518405 return result;
......@@ -17735,12 +18425,6 @@ static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira,
1773518425static IrInstruction *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira,
1773618426 IrInstructionSetEvalBranchQuota *instruction)
1773718427{
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
1774418428 uint64_t new_quota;
1774518429 if (!ir_resolve_usize(ira, instruction->new_quota->child, &new_quota))
1774618430 return ira->codegen->invalid_instruction;
......@@ -17781,10 +18465,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
1778118465
1778218466 // Execute the C import block like an inline function
1778318467 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,
1778518469 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,
17786 &cimport_scope->buf, block_node, nullptr, nullptr);
17787 if (type_is_invalid(cimport_result->value.type))
18470 &cimport_scope->buf, block_node, nullptr, nullptr, nullptr);
18471 if (type_is_invalid(cimport_result->type))
1778818472 return ira->codegen->invalid_instruction;
1778918473
1779018474 find_libc_include_path(ira->codegen);
......@@ -17934,7 +18618,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru
1793418618 return result;
1793518619}
1793618620
17937static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchg *instruction) {
18621static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchgSrc *instruction) {
1793818622 ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child);
1793918623 if (type_is_invalid(operand_type))
1794018624 return ira->codegen->invalid_instruction;
......@@ -18006,9 +18690,9 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi
1800618690 zig_panic("TODO compile-time execution of cmpxchg");
1800718691 }
1800818692
18009 IrInstruction *result = ir_build_cmpxchg(&ira->new_irb, instruction->base.scope, instruction->base.source_node,
18010 nullptr, casted_ptr, casted_cmp_value, casted_new_value, nullptr, nullptr, instruction->is_weak,
18011 operand_type, success_order, failure_order);
18693 IrInstruction *result = ir_build_cmpxchg_gen(ira, &instruction->base,
18694 casted_ptr, casted_cmp_value, casted_new_value,
18695 success_order, failure_order, instruction->is_weak);
1801218696 result->value.type = get_optional_type(ira->codegen, operand_type);
1801318697 ir_add_alloca(ira, result, result->value.type);
1801418698 return result;
......@@ -18054,6 +18738,27 @@ static IrInstruction *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruct
1805418738 return ira->codegen->invalid_instruction;
1805518739 }
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
1805718762 if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) {
1805818763 const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned";
1805918764 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
1806418769 return ira->codegen->invalid_instruction;
1806518770 }
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
1807418772 IrInstruction *new_instruction = ir_build_truncate(&ira->new_irb, instruction->base.scope,
1807518773 instruction->base.source_node, dest_type_value, target);
1807618774 new_instruction->value.type = dest_type;
......@@ -18174,18 +18872,6 @@ static IrInstruction *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInst
1817418872 return ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type);
1817518873}
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
1818918875static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {
1819018876 Error err;
1819118877
......@@ -18304,6 +18990,20 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct
1830418990 return ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);
1830518991}
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
1830719007static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) {
1830819008 ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
1830919009 if (type_is_invalid(dest_type))
......@@ -18410,6 +19110,27 @@ static IrInstruction *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstruct
1841019110 return ir_const_type(ira, &instruction->base, get_int_type(ira->codegen, is_signed, (uint32_t)bit_count));
1841119111}
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
1841319134static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {
1841419135 IrInstruction *value = instruction->value->child;
1841519136 if (type_is_invalid(value->value.type))
......@@ -18508,10 +19229,18 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio
1850819229 }
1850919230 case ConstPtrSpecialBaseStruct:
1851019231 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");
1851119238 case ConstPtrSpecialHardCodedAddr:
1851219239 zig_unreachable();
1851319240 case ConstPtrSpecialFunction:
1851419241 zig_panic("TODO memset on ptr cast from function");
19242 case ConstPtrSpecialNull:
19243 zig_panic("TODO memset on null ptr");
1851519244 }
1851619245
1851719246 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
1862319352 }
1862419353 case ConstPtrSpecialBaseStruct:
1862519354 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");
1862619361 case ConstPtrSpecialHardCodedAddr:
1862719362 zig_unreachable();
1862819363 case ConstPtrSpecialFunction:
1862919364 zig_panic("TODO memcpy on ptr cast from function");
19365 case ConstPtrSpecialNull:
19366 zig_panic("TODO memcpy on null ptr");
1863019367 }
1863119368
1863219369 if (dest_start + count > dest_end) {
......@@ -18659,10 +19396,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
1865919396 }
1866019397 case ConstPtrSpecialBaseStruct:
1866119398 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");
1866219405 case ConstPtrSpecialHardCodedAddr:
1866319406 zig_unreachable();
1866419407 case ConstPtrSpecialFunction:
1866519408 zig_panic("TODO memcpy on ptr cast from function");
19409 case ConstPtrSpecialNull:
19410 zig_panic("TODO memcpy on null ptr");
1866619411 }
1866719412
1866819413 if (src_start + count > src_end) {
......@@ -18690,9 +19435,9 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1869019435 if (type_is_invalid(ptr_ptr->value.type))
1869119436 return ira->codegen->invalid_instruction;
1869219437
18693 ZigType *ptr_type = ptr_ptr->value.type;
18694 assert(ptr_type->id == ZigTypeIdPointer);
18695 ZigType *array_type = ptr_type->data.pointer.child_type;
19438 ZigType *ptr_ptr_type = ptr_ptr->value.type;
19439 assert(ptr_ptr_type->id == ZigTypeIdPointer);
19440 ZigType *array_type = ptr_ptr_type->data.pointer.child_type;
1869619441
1869719442 IrInstruction *start = instruction->start->child;
1869819443 if (type_is_invalid(start->value.type))
......@@ -18721,10 +19466,10 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1872119466 bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic &&
1872219467 ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst;
1872319468 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,
18725 ptr_type->data.pointer.is_volatile,
19469 ptr_ptr_type->data.pointer.is_const || is_comptime_const,
19470 ptr_ptr_type->data.pointer.is_volatile,
1872619471 PtrLenUnknown,
18727 ptr_type->data.pointer.explicit_alignment, 0, 0);
19472 ptr_ptr_type->data.pointer.explicit_alignment, 0, 0);
1872819473 return_type = get_slice_type(ira->codegen, slice_ptr_type);
1872919474 } else if (array_type->id == ZigTypeIdPointer) {
1873019475 if (array_type->data.pointer.ptr_len == PtrLenSingle) {
......@@ -18771,18 +19516,18 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1877119516 if (array_type->id == ZigTypeIdPointer) {
1877219517 ZigType *child_array_type = array_type->data.pointer.child_type;
1877319518 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);
1877519520 if (parent_ptr == nullptr)
1877619521 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);
1877919524 if (array_val == nullptr)
1878019525 return ira->codegen->invalid_instruction;
1878119526
1878219527 rel_end = child_array_type->data.array.len;
1878319528 abs_offset = 0;
1878419529 } 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);
1878619531 if (array_val == nullptr)
1878719532 return ira->codegen->invalid_instruction;
1878819533 rel_end = array_type->data.array.len;
......@@ -18791,7 +19536,7 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1879119536 }
1879219537 } else if (array_type->id == ZigTypeIdPointer) {
1879319538 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);
1879519540 if (parent_ptr == nullptr)
1879619541 return ira->codegen->invalid_instruction;
1879719542
......@@ -18822,6 +19567,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1882219567 break;
1882319568 case ConstPtrSpecialBaseStruct:
1882419569 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");
1882519576 case ConstPtrSpecialHardCodedAddr:
1882619577 array_val = nullptr;
1882719578 abs_offset = 0;
......@@ -18829,9 +19580,11 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1882919580 break;
1883019581 case ConstPtrSpecialFunction:
1883119582 zig_panic("TODO slice of ptr cast from function");
19583 case ConstPtrSpecialNull:
19584 zig_panic("TODO slice of null ptr");
1883219585 }
1883319586 } 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);
1883519588 if (slice_ptr == nullptr)
1883619589 return ira->codegen->invalid_instruction;
1883719590
......@@ -18859,6 +19612,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1885919612 break;
1886019613 case ConstPtrSpecialBaseStruct:
1886119614 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");
1886219621 case ConstPtrSpecialHardCodedAddr:
1886319622 array_val = nullptr;
1886419623 abs_offset = 0;
......@@ -18866,6 +19625,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1886619625 break;
1886719626 case ConstPtrSpecialFunction:
1886819627 zig_panic("TODO slice of slice cast from function");
19628 case ConstPtrSpecialNull:
19629 zig_panic("TODO slice of null");
1886919630 }
1887019631 } else {
1887119632 zig_unreachable();
......@@ -18931,6 +19692,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1893119692 zig_unreachable();
1893219693 case ConstPtrSpecialBaseStruct:
1893319694 zig_panic("TODO");
19695 case ConstPtrSpecialBaseErrorUnionCode:
19696 zig_panic("TODO");
19697 case ConstPtrSpecialBaseErrorUnionPayload:
19698 zig_panic("TODO");
19699 case ConstPtrSpecialBaseOptionalPayload:
19700 zig_panic("TODO");
1893419701 case ConstPtrSpecialHardCodedAddr:
1893519702 init_const_ptr_hard_coded_addr(ira->codegen, ptr_val,
1893619703 parent_ptr->type->data.pointer.child_type,
......@@ -18939,6 +19706,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1893919706 break;
1894019707 case ConstPtrSpecialFunction:
1894119708 zig_panic("TODO");
19709 case ConstPtrSpecialNull:
19710 zig_panic("TODO");
1894219711 }
1894319712
1894419713 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
1916519934 case ZigTypeIdEnum:
1916619935 case ZigTypeIdUnion:
1916719936 case ZigTypeIdFn:
19937 case ZigTypeIdVector:
1916819938 {
1916919939 uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry);
1917019940 return ir_const_unsigned(ira, &instruction->base, align_in_bytes);
......@@ -19240,7 +20010,7 @@ static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstr
1924020010 {
1924120011 BigInt *op1_bigint = &casted_op1->value.data.x_bigint;
1924220012 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);
1924420014 if (pointee_val == nullptr)
1924520015 return ira->codegen->invalid_instruction;
1924620016 BigInt *dest_bigint = &pointee_val->data.x_bigint;
......@@ -19294,7 +20064,8 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
1929420064 return ira->codegen->invalid_instruction;
1929520065
1929620066 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));
1929820069 }
1929920070 }
1930020071
......@@ -19320,48 +20091,47 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
1932020091 }
1932120092}
1932220093
19323static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,
19324 IrInstructionUnwrapErrCode *instruction)
19325{
19326 IrInstruction *value = instruction->value->child;
19327 if (type_is_invalid(value->value.type))
20094static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrInstructionUnwrapErrCode *instruction) {
20095 IrInstruction *base_ptr = instruction->err_union->child;
20096 if (type_is_invalid(base_ptr->value.type))
1932820097 return ira->codegen->invalid_instruction;
19329 ZigType *ptr_type = value->value.type;
20098 ZigType *ptr_type = base_ptr->value.type;
1933020099
1933120100 // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
1933220101 assert(ptr_type->id == ZigTypeIdPointer);
1933320102
1933420103 ZigType *type_entry = ptr_type->data.pointer.child_type;
19335 if (type_is_invalid(type_entry)) {
20104 if (type_is_invalid(type_entry))
1933620105 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,
19350 type_entry->data.error_union.err_set_type);
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,
20107 if (type_entry->id != ZigTypeIdErrorUnion) {
20108 ir_add_error(ira, base_ptr,
1936220109 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
1936320110 return ira->codegen->invalid_instruction;
1936420111 }
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;
1936520135}
1936620136
1936720137static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
......@@ -19377,48 +20147,48 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
1937720147 assert(ptr_type->id == ZigTypeIdPointer);
1937820148
1937920149 ZigType *type_entry = ptr_type->data.pointer.child_type;
19380 if (type_is_invalid(type_entry)) {
20150 if (type_is_invalid(type_entry))
1938120151 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);
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 {
20153 if (type_entry->id != ZigTypeIdErrorUnion) {
1941720154 ir_add_error(ira, value,
1941820155 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
1941920156 return ira->codegen->invalid_instruction;
1942020157 }
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;
1942220192}
1942320193
1942420194static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {
......@@ -19696,6 +20466,39 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
1969620466 return ira->codegen->invalid_instruction;
1969720467 }
1969820468 }
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 }
1969920502 } else if (!instruction->have_else_prong) {
1970020503 ir_add_error(ira, &instruction->base,
1970120504 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
1980220605 return ira->codegen->invalid_instruction;
1980320606 }
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);
1980620609 copy_const_val(&result->value, val, false);
1980720610 result->value.type = result_type;
1980820611 return result;
......@@ -19819,7 +20622,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
1981920622}
1982020623
1982120624static 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)
1982320626{
1982420627 Error err;
1982520628
......@@ -19829,12 +20632,14 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
1982920632 // We have a check for zero bits later so we use get_src_ptr_type to
1983020633 // 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) {
1983320637 ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));
1983420638 return ira->codegen->invalid_instruction;
1983520639 }
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) {
1983820643 ir_add_error(ira, dest_type_src,
1983920644 buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
1984020645 return ira->codegen->invalid_instruction;
......@@ -19846,12 +20651,24 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
1984620651 }
1984720652
1984820653 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);
1985020657 if (!val)
1985120658 return ira->codegen->invalid_instruction;
1985220659
19853 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, source_instr->source_node,
19854 dest_type);
20660 if (val->special == ConstValSpecialStatic) {
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);
1985520672 copy_const_val(&result->value, val, false);
1985620673 result->value.type = dest_type;
1985720674 return result;
......@@ -19874,9 +20691,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
1987420691 return ira->codegen->invalid_instruction;
1987520692 }
1987620693
19877 IrInstruction *casted_ptr = ir_build_ptr_cast(&ira->new_irb, source_instr->scope,
19878 source_instr->source_node, nullptr, ptr);
19879 casted_ptr->value.type = dest_type;
20694 IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on);
1988020695
1988120696 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
1988220697 ErrorMsg *msg = ir_add_error(ira, source_instr,
......@@ -19902,7 +20717,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
1990220717 return result;
1990320718}
1990420719
19905static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCast *instruction) {
20720static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCastSrc *instruction) {
1990620721 IrInstruction *dest_type_value = instruction->dest_type->child;
1990720722 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
1990820723 if (type_is_invalid(dest_type))
......@@ -19913,10 +20728,24 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct
1991320728 if (type_is_invalid(src_type))
1991420729 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 }
1991720744}
1991820745
1991920746static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {
20747 if (val->special == ConstValSpecialUndef)
20748 val->special = ConstValSpecialStatic;
1992020749 assert(val->special == ConstValSpecialStatic);
1992120750 switch (val->type->id) {
1992220751 case ZigTypeIdInvalid:
......@@ -19959,17 +20788,9 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
1995920788 zig_unreachable();
1996020789 }
1996120790 case ZigTypeIdArray:
19962 {
19963 size_t buf_i = 0;
19964 // TODO optimize the buf case
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;
20791 return buf_write_value_bytes_array(codegen, buf, val, val->type->data.array.len);
20792 case ZigTypeIdVector:
20793 return buf_write_value_bytes_array(codegen, buf, val, val->type->data.vector.len);
1997320794 case ZigTypeIdStruct:
1997420795 zig_panic("TODO buf_write_value_bytes struct type");
1997520796 case ZigTypeIdOptional:
......@@ -19986,7 +20807,33 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
1998620807 zig_unreachable();
1998720808}
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;
1999020837 assert(val->special == ConstValSpecialStatic);
1999120838 switch (val->type->id) {
1999220839 case ZigTypeIdInvalid:
......@@ -20003,17 +20850,17 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
2000320850 case ZigTypeIdPromise:
2000420851 zig_unreachable();
2000520852 case ZigTypeIdVoid:
20006 return;
20853 return ErrorNone;
2000720854 case ZigTypeIdBool:
2000820855 val->data.x_bool = (buf[0] != 0);
20009 return;
20856 return ErrorNone;
2001020857 case ZigTypeIdInt:
2001120858 bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,
2001220859 codegen->is_big_endian, val->type->data.integral.is_signed);
20013 return;
20860 return ErrorNone;
2001420861 case ZigTypeIdFloat:
2001520862 float_read_ieee597(val, buf, codegen->is_big_endian);
20016 return;
20863 return ErrorNone;
2001720864 case ZigTypeIdPointer:
2001820865 {
2001920866 val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
......@@ -20021,20 +20868,67 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
2002120868 bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count,
2002220869 codegen->is_big_endian, false);
2002320870 val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);
20024 return;
20871 return ErrorNone;
2002520872 }
2002620873 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();
2002820894 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();
2003020926 case ZigTypeIdOptional:
2003120927 zig_panic("TODO buf_read_value_bytes maybe type");
2003220928 case ZigTypeIdErrorUnion:
2003320929 zig_panic("TODO buf_read_value_bytes error union");
2003420930 case ZigTypeIdErrorSet:
2003520931 zig_panic("TODO buf_read_value_bytes pure error type");
20036 case ZigTypeIdEnum:
20037 zig_panic("TODO buf_read_value_bytes enum type");
2003820932 case ZigTypeIdFn:
2003920933 zig_panic("TODO buf_read_value_bytes fn type");
2004020934 case ZigTypeIdUnion:
......@@ -20043,32 +20937,10 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
2004320937 zig_unreachable();
2004420938}
2004520939
20046static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
20047 Error err;
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) {
20940static bool type_can_bit_cast(ZigType *t) {
20941 switch (t->id) {
2007120942 case ZigTypeIdInvalid:
20943 zig_unreachable();
2007220944 case ZigTypeIdMetaType:
2007320945 case ZigTypeIdOpaque:
2007420946 case ZigTypeIdBoundFn:
......@@ -20079,90 +20951,114 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
2007920951 case ZigTypeIdComptimeInt:
2008020952 case ZigTypeIdUndefined:
2008120953 case ZigTypeIdNull:
20082 ir_add_error(ira, dest_type_value,
20083 buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
20084 return ira->codegen->invalid_instruction;
20954 case ZigTypeIdPointer:
20955 return false;
2008520956 default:
20086 break;
20957 // TODO list these types out explicitly, there are probably some other invalid ones here
20958 return true;
2008720959 }
20960}
2008820961
20089 if (get_codegen_ptr_type(dest_type) != nullptr) {
20090 ir_add_error(ira, dest_type_value,
20091 buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
20962static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
20963 ZigType *dest_type)
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)))
2009220977 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
2011420980 uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);
2011520981 uint64_t src_size_bytes = type_size(ira->codegen, src_type);
2011620982 if (dest_size_bytes != src_size_bytes) {
20117 ir_add_error(ira, &instruction->base,
20983 ir_add_error(ira, source_instr,
2011820984 buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,
2011920985 buf_ptr(&dest_type->name), dest_size_bytes,
2012020986 buf_ptr(&src_type->name), src_size_bytes));
2012120987 return ira->codegen->invalid_instruction;
2012220988 }
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
2012421000 if (instr_is_comptime(value)) {
2012521001 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
2012621002 if (!val)
2012721003 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);
2013021006 uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes);
2013121007 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;
2013321010 return result;
2013421011 }
2013521012
20136 IrInstruction *result = ir_build_bit_cast(&ira->new_irb, instruction->base.scope,
20137 instruction->base.source_node, nullptr, value);
21013 IrInstruction *result = ir_build_bit_cast(&ira->new_irb, source_instr->scope,
21014 source_instr->source_node, nullptr, value);
2013821015 result->value.type = dest_type;
2013921016 return result;
2014021017}
2014121018
20142static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstructionIntToPtr *instruction) {
20143 Error err;
21019static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
2014421020 IrInstruction *dest_type_value = instruction->dest_type->child;
2014521021 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
2014621022 if (type_is_invalid(dest_type))
2014721023 return ira->codegen->invalid_instruction;
2014821024
20149 // We explicitly check for the size, so we can use get_src_ptr_type
20150 if (get_src_ptr_type(dest_type) == nullptr) {
20151 ir_add_error(ira, dest_type_value, buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
21025 IrInstruction *value = instruction->value->child;
21026 ZigType *src_type = value->value.type;
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)));
2015221033 return ira->codegen->invalid_instruction;
2015321034 }
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)));
2015621039 return ira->codegen->invalid_instruction;
20157 if (!type_has_bits(dest_type)) {
21040 }
21041
21042 if (get_codegen_ptr_type(dest_type) != nullptr) {
2015821043 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)));
2016021045 return ira->codegen->invalid_instruction;
2016121046 }
2016221047
20163 IrInstruction *target = instruction->target->child;
20164 if (type_is_invalid(target->value.type))
21048 if (!type_can_bit_cast(dest_type)) {
21049 ir_add_error(ira, dest_type_value,
21050 buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
2016521051 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
2016721063 IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);
2016821064 if (type_is_invalid(casted_int->value.type))
......@@ -20173,18 +21069,48 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru
2017321069 if (!val)
2017421070 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);
2017721073 result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
21074 result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
2017821075 result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);
2017921076 return result;
2018021077 }
2018121078
20182 IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, instruction->base.scope,
20183 instruction->base.source_node, nullptr, casted_int);
20184 result->value.type = dest_type;
21079 IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, source_instr->scope,
21080 source_instr->source_node, nullptr, casted_int);
21081 result->value.type = ptr_type;
2018521082 return result;
2018621083}
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
2018821114static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
2018921115 IrInstructionDeclRef *instruction)
2019021116{
......@@ -20199,8 +21125,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
2019921125 case TldIdContainer:
2020021126 case TldIdCompTime:
2020121127 zig_unreachable();
20202 case TldIdVar:
20203 {
21128 case TldIdVar: {
2020421129 TldVar *tld_var = (TldVar *)tld;
2020521130 ZigVar *var = tld_var->var;
2020621131
......@@ -20218,8 +21143,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
2021821143 return ir_get_deref(ira, &instruction->base, var_ptr);
2021921144 }
2022021145 }
20221 case TldIdFn:
20222 {
21146 case TldIdFn: {
2022321147 TldFn *tld_fn = (TldFn *)tld;
2022421148 ZigFn *fn_entry = tld_fn->fn_entry;
2022521149 assert(fn_entry->type_entry);
......@@ -20265,8 +21189,7 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru
2026521189 if (!val)
2026621190 return ira->codegen->invalid_instruction;
2026721191 if (val->type->id == ZigTypeIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
20268 IrInstruction *result = ir_create_const(&ira->new_irb, instruction->base.scope,
20269 instruction->base.source_node, usize);
21192 IrInstruction *result = ir_const(ira, &instruction->base, usize);
2027021193 bigint_init_unsigned(&result->value.data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr);
2027121194 result->value.type = usize;
2027221195 return result;
......@@ -20291,6 +21214,15 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
2029121214 } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) {
2029221215 ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque"));
2029321216 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 }
2029421226 }
2029521227
2029621228 uint32_t align_bytes;
......@@ -20299,6 +21231,9 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
2029921231 return ira->codegen->invalid_instruction;
2030021232 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown)))
2030121233 return ira->codegen->invalid_instruction;
21234 if (!type_has_bits(child_type)) {
21235 align_bytes = 0;
21236 }
2030221237 } else {
2030321238 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
2030421239 return ira->codegen->invalid_instruction;
......@@ -20898,6 +21833,126 @@ static IrInstruction *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstructionS
2089821833 return result;
2089921834}
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
2090121956static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {
2090221957 Error err;
2090321958 IrInstruction *target = instruction->target->child;
......@@ -20981,6 +22036,12 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2098122036 case IrInstructionIdErrWrapCode:
2098222037 case IrInstructionIdErrWrapPayload:
2098322038 case IrInstructionIdCast:
22039 case IrInstructionIdDeclVarGen:
22040 case IrInstructionIdPtrCastGen:
22041 case IrInstructionIdCmpxchgGen:
22042 case IrInstructionIdArrayToVector:
22043 case IrInstructionIdVectorToArray:
22044 case IrInstructionIdAssertZero:
2098422045 zig_unreachable();
2098522046
2098622047 case IrInstructionIdReturn:
......@@ -20991,8 +22052,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2099122052 return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction);
2099222053 case IrInstructionIdBinOp:
2099322054 return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction);
20994 case IrInstructionIdDeclVar:
20995 return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVar *)instruction);
22055 case IrInstructionIdDeclVarSrc:
22056 return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVarSrc *)instruction);
2099622057 case IrInstructionIdLoadPtr:
2099722058 return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction);
2099822059 case IrInstructionIdStorePtr:
......@@ -21037,8 +22098,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2103722098 return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction);
2103822099 case IrInstructionIdTestNonNull:
2103922100 return ir_analyze_instruction_test_non_null(ira, (IrInstructionTestNonNull *)instruction);
21040 case IrInstructionIdUnwrapOptional:
21041 return ir_analyze_instruction_unwrap_maybe(ira, (IrInstructionUnwrapOptional *)instruction);
22101 case IrInstructionIdOptionalUnwrapPtr:
22102 return ir_analyze_instruction_optional_unwrap_ptr(ira, (IrInstructionOptionalUnwrapPtr *)instruction);
2104222103 case IrInstructionIdClz:
2104322104 return ir_analyze_instruction_clz(ira, (IrInstructionClz *)instruction);
2104422105 case IrInstructionIdCtz:
......@@ -21079,8 +22140,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2107922140 return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction);
2108022141 case IrInstructionIdEmbedFile:
2108122142 return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction);
21082 case IrInstructionIdCmpxchg:
21083 return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchg *)instruction);
22143 case IrInstructionIdCmpxchgSrc:
22144 return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchgSrc *)instruction);
2108422145 case IrInstructionIdFence:
2108522146 return ir_analyze_instruction_fence(ira, (IrInstructionFence *)instruction);
2108622147 case IrInstructionIdTruncate:
......@@ -21103,6 +22164,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2110322164 return ir_analyze_instruction_bool_to_int(ira, (IrInstructionBoolToInt *)instruction);
2110422165 case IrInstructionIdIntType:
2110522166 return ir_analyze_instruction_int_type(ira, (IrInstructionIntType *)instruction);
22167 case IrInstructionIdVectorType:
22168 return ir_analyze_instruction_vector_type(ira, (IrInstructionVectorType *)instruction);
2110622169 case IrInstructionIdBoolNot:
2110722170 return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction);
2110822171 case IrInstructionIdMemset:
......@@ -21147,8 +22210,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2114722210 return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction);
2114822211 case IrInstructionIdPanic:
2114922212 return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);
21150 case IrInstructionIdPtrCast:
21151 return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCast *)instruction);
22213 case IrInstructionIdPtrCastSrc:
22214 return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCastSrc *)instruction);
2115222215 case IrInstructionIdBitCast:
2115322216 return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction);
2115422217 case IrInstructionIdIntToPtr:
......@@ -21233,6 +22296,10 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2123322296 return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);
2123422297 case IrInstructionIdSqrt:
2123522298 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);
2123622303 case IrInstructionIdIntToErr:
2123722304 return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);
2123822305 case IrInstructionIdErrToInt:
......@@ -21328,7 +22395,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2132822395 case IrInstructionIdBr:
2132922396 case IrInstructionIdCondBr:
2133022397 case IrInstructionIdSwitchBr:
21331 case IrInstructionIdDeclVar:
22398 case IrInstructionIdDeclVarSrc:
22399 case IrInstructionIdDeclVarGen:
2133222400 case IrInstructionIdStorePtr:
2133322401 case IrInstructionIdCall:
2133422402 case IrInstructionIdReturn:
......@@ -21343,7 +22411,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2134322411 case IrInstructionIdCInclude:
2134422412 case IrInstructionIdCDefine:
2134522413 case IrInstructionIdCUndef:
21346 case IrInstructionIdCmpxchg:
2134722414 case IrInstructionIdFence:
2134822415 case IrInstructionIdMemset:
2134922416 case IrInstructionIdMemcpy:
......@@ -21371,6 +22438,9 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2137122438 case IrInstructionIdMergeErrRetTraces:
2137222439 case IrInstructionIdMarkErrRetTracePtr:
2137322440 case IrInstructionIdAtomicRmw:
22441 case IrInstructionIdCmpxchgGen:
22442 case IrInstructionIdCmpxchgSrc:
22443 case IrInstructionIdAssertZero:
2137422444 return true;
2137522445
2137622446 case IrInstructionIdPhi:
......@@ -21396,7 +22466,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2139622466 case IrInstructionIdSliceType:
2139722467 case IrInstructionIdSizeOf:
2139822468 case IrInstructionIdTestNonNull:
21399 case IrInstructionIdUnwrapOptional:
22469 case IrInstructionIdOptionalUnwrapPtr:
2140022470 case IrInstructionIdClz:
2140122471 case IrInstructionIdCtz:
2140222472 case IrInstructionIdPopCount:
......@@ -21407,6 +22477,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2140722477 case IrInstructionIdEmbedFile:
2140822478 case IrInstructionIdTruncate:
2140922479 case IrInstructionIdIntType:
22480 case IrInstructionIdVectorType:
2141022481 case IrInstructionIdBoolNot:
2141122482 case IrInstructionIdSlice:
2141222483 case IrInstructionIdMemberCount:
......@@ -21423,7 +22494,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2142322494 case IrInstructionIdErrWrapPayload:
2142422495 case IrInstructionIdFnProto:
2142522496 case IrInstructionIdTestComptime:
21426 case IrInstructionIdPtrCast:
22497 case IrInstructionIdPtrCastSrc:
22498 case IrInstructionIdPtrCastGen:
2142722499 case IrInstructionIdBitCast:
2142822500 case IrInstructionIdWidenOrShorten:
2142922501 case IrInstructionIdPtrToInt:
......@@ -21454,6 +22526,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2145422526 case IrInstructionIdCoroPromise:
2145522527 case IrInstructionIdPromiseResultType:
2145622528 case IrInstructionIdSqrt:
22529 case IrInstructionIdBswap:
22530 case IrInstructionIdBitReverse:
2145722531 case IrInstructionIdAtomicLoad:
2145822532 case IrInstructionIdIntCast:
2145922533 case IrInstructionIdFloatCast:
......@@ -21464,6 +22538,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2146422538 case IrInstructionIdFromBytes:
2146522539 case IrInstructionIdToBytes:
2146622540 case IrInstructionIdEnumToInt:
22541 case IrInstructionIdVectorToArray:
22542 case IrInstructionIdArrayToVector:
2146722543 return false;
2146822544
2146922545 case IrInstructionIdAsm:
src/ir.hpp+6-3
......@@ -13,15 +13,18 @@
1313bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable);
1414bool 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,
1717 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
1818 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
2121ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
2222 ZigType *expected_type, AstNode *expected_type_source_node);
2323
2424bool 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
2730#endif
src/ir_print.cpp+129-22
......@@ -172,7 +172,7 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction
172172 }
173173}
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) {
176176 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
177177 const char *name = buf_ptr(&decl_var_instruction->var->name);
178178 if (decl_var_instruction->var_type) {
......@@ -332,8 +332,8 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {
332332}
333333
334334static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
335 fprintf(irp->f, "*");
336335 ir_print_other_instruction(irp, instruction->ptr);
336 fprintf(irp->f, ".*");
337337}
338338
339339static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {
......@@ -479,15 +479,15 @@ static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) {
479479 fprintf(irp->f, ")");
480480}
481481
482static void ir_print_test_null(IrPrint *irp, IrInstructionTestNonNull *instruction) {
483 fprintf(irp->f, "*");
482static void ir_print_test_non_null(IrPrint *irp, IrInstructionTestNonNull *instruction) {
484483 ir_print_other_instruction(irp, instruction->value);
485484 fprintf(irp->f, " != null");
486485}
487486
488static void ir_print_unwrap_maybe(IrPrint *irp, IrInstructionUnwrapOptional *instruction) {
489 fprintf(irp->f, "&??*");
490 ir_print_other_instruction(irp, instruction->value);
487static void ir_print_optional_unwrap_ptr(IrPrint *irp, IrInstructionOptionalUnwrapPtr *instruction) {
488 fprintf(irp->f, "&");
489 ir_print_other_instruction(irp, instruction->base_ptr);
490 fprintf(irp->f, ".*.?");
491491 if (!instruction->safety_check_on) {
492492 fprintf(irp->f, " // no safety");
493493 }
......@@ -613,7 +613,7 @@ static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instructio
613613 fprintf(irp->f, ")");
614614}
615615
616static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {
616static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruction) {
617617 fprintf(irp->f, "@cmpxchg(");
618618 ir_print_other_instruction(irp, instruction->ptr);
619619 fprintf(irp->f, ", ");
......@@ -627,6 +627,16 @@ static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {
627627 fprintf(irp->f, ")");
628628}
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
630640static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) {
631641 fprintf(irp->f, "@fence(");
632642 ir_print_other_instruction(irp, instruction->order_value);
......@@ -709,6 +719,14 @@ static void ir_print_int_type(IrPrint *irp, IrInstructionIntType *instruction) {
709719 fprintf(irp->f, ")");
710720}
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
712730static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) {
713731 fprintf(irp->f, "! ");
714732 ir_print_other_instruction(irp, instruction->value);
......@@ -820,13 +838,13 @@ static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) {
820838}
821839
822840static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) {
823 fprintf(irp->f, "@unwrapErrorCode(");
824 ir_print_other_instruction(irp, instruction->value);
841 fprintf(irp->f, "UnwrapErrorCode(");
842 ir_print_other_instruction(irp, instruction->err_union);
825843 fprintf(irp->f, ")");
826844}
827845
828846static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) {
829 fprintf(irp->f, "@unwrapErrorPayload(");
847 fprintf(irp->f, "ErrorUnionFieldPayload(");
830848 ir_print_other_instruction(irp, instruction->value);
831849 fprintf(irp->f, ")");
832850 if (!instruction->safety_check_on) {
......@@ -879,7 +897,7 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst
879897 fprintf(irp->f, ")");
880898}
881899
882static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {
900static void ir_print_ptr_cast_src(IrPrint *irp, IrInstructionPtrCastSrc *instruction) {
883901 fprintf(irp->f, "@ptrCast(");
884902 if (instruction->dest_type) {
885903 ir_print_other_instruction(irp, instruction->dest_type);
......@@ -889,6 +907,12 @@ static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {
889907 fprintf(irp->f, ")");
890908}
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
892916static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
893917 fprintf(irp->f, "@bitCast(");
894918 if (instruction->dest_type) {
......@@ -900,7 +924,7 @@ static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
900924}
901925
902926static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) {
903 fprintf(irp->f, "@widenOrShorten(");
927 fprintf(irp->f, "WidenOrShorten(");
904928 ir_print_other_instruction(irp, instruction->target);
905929 fprintf(irp->f, ")");
906930}
......@@ -948,6 +972,24 @@ static void ir_print_check_runtime_scope(IrPrint *irp, IrInstructionCheckRuntime
948972 fprintf(irp->f, ")");
949973}
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
951993static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {
952994 fprintf(irp->f, "inttoerr ");
953995 ir_print_other_instruction(irp, instruction->target);
......@@ -1323,6 +1365,44 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) {
13231365 fprintf(irp->f, ")");
13241366}
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
13261406static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
13271407 ir_print_prefix(irp, instruction);
13281408 switch (instruction->id) {
......@@ -1337,8 +1417,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
13371417 case IrInstructionIdBinOp:
13381418 ir_print_bin_op(irp, (IrInstructionBinOp *)instruction);
13391419 break;
1340 case IrInstructionIdDeclVar:
1341 ir_print_decl_var(irp, (IrInstructionDeclVar *)instruction);
1420 case IrInstructionIdDeclVarSrc:
1421 ir_print_decl_var_src(irp, (IrInstructionDeclVarSrc *)instruction);
13421422 break;
13431423 case IrInstructionIdCast:
13441424 ir_print_cast(irp, (IrInstructionCast *)instruction);
......@@ -1428,10 +1508,10 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
14281508 ir_print_size_of(irp, (IrInstructionSizeOf *)instruction);
14291509 break;
14301510 case IrInstructionIdTestNonNull:
1431 ir_print_test_null(irp, (IrInstructionTestNonNull *)instruction);
1511 ir_print_test_non_null(irp, (IrInstructionTestNonNull *)instruction);
14321512 break;
1433 case IrInstructionIdUnwrapOptional:
1434 ir_print_unwrap_maybe(irp, (IrInstructionUnwrapOptional *)instruction);
1513 case IrInstructionIdOptionalUnwrapPtr:
1514 ir_print_optional_unwrap_ptr(irp, (IrInstructionOptionalUnwrapPtr *)instruction);
14351515 break;
14361516 case IrInstructionIdCtz:
14371517 ir_print_ctz(irp, (IrInstructionCtz *)instruction);
......@@ -1484,8 +1564,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
14841564 case IrInstructionIdEmbedFile:
14851565 ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction);
14861566 break;
1487 case IrInstructionIdCmpxchg:
1488 ir_print_cmpxchg(irp, (IrInstructionCmpxchg *)instruction);
1567 case IrInstructionIdCmpxchgSrc:
1568 ir_print_cmpxchg_src(irp, (IrInstructionCmpxchgSrc *)instruction);
1569 break;
1570 case IrInstructionIdCmpxchgGen:
1571 ir_print_cmpxchg_gen(irp, (IrInstructionCmpxchgGen *)instruction);
14891572 break;
14901573 case IrInstructionIdFence:
14911574 ir_print_fence(irp, (IrInstructionFence *)instruction);
......@@ -1520,6 +1603,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
15201603 case IrInstructionIdIntType:
15211604 ir_print_int_type(irp, (IrInstructionIntType *)instruction);
15221605 break;
1606 case IrInstructionIdVectorType:
1607 ir_print_vector_type(irp, (IrInstructionVectorType *)instruction);
1608 break;
15231609 case IrInstructionIdBoolNot:
15241610 ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction);
15251611 break;
......@@ -1583,8 +1669,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
15831669 case IrInstructionIdTestComptime:
15841670 ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction);
15851671 break;
1586 case IrInstructionIdPtrCast:
1587 ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction);
1672 case IrInstructionIdPtrCastSrc:
1673 ir_print_ptr_cast_src(irp, (IrInstructionPtrCastSrc *)instruction);
1674 break;
1675 case IrInstructionIdPtrCastGen:
1676 ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction);
15881677 break;
15891678 case IrInstructionIdBitCast:
15901679 ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);
......@@ -1736,6 +1825,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
17361825 case IrInstructionIdSqrt:
17371826 ir_print_sqrt(irp, (IrInstructionSqrt *)instruction);
17381827 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;
17391834 case IrInstructionIdAtomicLoad:
17401835 ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);
17411836 break;
......@@ -1745,6 +1840,18 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
17451840 case IrInstructionIdCheckRuntimeScope:
17461841 ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction);
17471842 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;
17481855 }
17491856 fprintf(irp->f, "\n");
17501857}
src/link.cpp+178-128
......@@ -42,7 +42,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path)
4242 }
4343
4444 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
4747 child_gen->out_h_path = nullptr;
4848 child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
......@@ -444,72 +444,19 @@ static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, si
444444 return ZigLLDLink(oformat, args, arg_count, link_diag_callback, diag);
445445}
446446
447static void construct_linker_job_coff(LinkJob *lj) {
448 CodeGen *g = lj->codegen;
449
450 lj->args.append("/ERRORLIMIT:0");
451
452 if (g->libc_link_lib != nullptr) {
453 find_libc_lib_path(g);
454 }
455
456 lj->args.append("-NOLOGO");
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))));
447static void add_uefi_link_args(LinkJob *lj) {
448 lj->args.append("/BASE:0");
449 lj->args.append("/ENTRY:EfiMain");
450 lj->args.append("/OPT:REF");
451 lj->args.append("/SAFESEH:NO");
452 lj->args.append("/MERGE:.rdata=.data");
453 lj->args.append("/ALIGN:32");
454 lj->args.append("/NODEFAULTLIB");
455 lj->args.append("/SECTION:.xdata,D");
456}
507457
508 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir))));
509 if (g->libc_static_lib_dir != nullptr) {
510 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_lib_dir))));
511 }
512 }
458static void add_nt_link_args(LinkJob *lj, bool is_library) {
459 CodeGen *g = lj->codegen;
513460
514461 if (lj->link_in_crt) {
515462 const char *lib_str = g->is_static ? "lib" : "";
......@@ -533,29 +480,180 @@ static void construct_linker_job_coff(LinkJob *lj) {
533480 //https://msdn.microsoft.com/en-us/library/bb531344.aspx
534481 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
547483 // msvcrt depends on kernel32
548484 lj->args.append("kernel32.lib");
549485 } else {
550 lj->args.append("-NODEFAULTLIB");
486 lj->args.append("/NODEFAULTLIB");
551487 if (!is_library) {
552488 if (g->have_winmain) {
553 lj->args.append("-ENTRY:WinMain");
489 lj->args.append("/ENTRY:WinMain");
554490 } else {
555 lj->args.append("-ENTRY:WinMainCRTStartup");
491 lj->args.append("/ENTRY:WinMainCRTStartup");
556492 }
557493 }
558494 }
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
560658 if (is_library && !g->is_static) {
561659 lj->args.append("-DLL");
......@@ -627,54 +725,6 @@ static void construct_linker_job_coff(LinkJob *lj) {
627725 }
628726 }
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 //}
678728}
679729
680730
src/main.cpp+82-16
......@@ -21,8 +21,8 @@ static int print_error_usage(const char *arg0) {
2121 return EXIT_FAILURE;
2222}
2323
24static int print_full_usage(const char *arg0) {
25 fprintf(stdout,
24static int print_full_usage(const char *arg0, FILE *file, int return_code) {
25 fprintf(file,
2626 "Usage: %s [command] [options]\n"
2727 "\n"
2828 "Commands:\n"
......@@ -31,6 +31,7 @@ static int print_full_usage(const char *arg0) {
3131 " build-lib [source] create library from source or object files\n"
3232 " build-obj [source] create object from source or assembly\n"
3333 " builtin show the source code of that @import(\"builtin\")\n"
34 " fmt parse files and render in canonical zig format\n"
3435 " help show this usage information\n"
3536 " id print the base64-encoded compiler id\n"
3637 " init-exe initialize a `zig build` application in the cwd\n"
......@@ -59,6 +60,7 @@ static int print_full_usage(const char *arg0) {
5960 " --release-fast build with optimizations on and safety off\n"
6061 " --release-safe build with optimizations on and safety on\n"
6162 " --release-small build with size optimizations on and safety off\n"
63 " --single-threaded source may assume it is only used single-threaded\n"
6264 " --static output will be statically linked\n"
6365 " --strip exclude debug symbols\n"
6466 " --target-arch [name] specify target architecture\n"
......@@ -73,6 +75,7 @@ static int print_full_usage(const char *arg0) {
7375 " -dirafter [dir] same as -isystem but do it last\n"
7476 " -isystem [dir] add additional search path for other .h files\n"
7577 " -mllvm [arg] forward an arg to LLVM's option processing\n"
78 " --override-std-dir [arg] use an alternate Zig standard library\n"
7679 "\n"
7780 "Link Options:\n"
7881 " --dynamic-linker [path] set the path to ld.so\n"
......@@ -90,8 +93,7 @@ static int print_full_usage(const char *arg0) {
9093 " -rdynamic add all symbols to the dynamic symbol table\n"
9194 " -rpath [path] add directory to the runtime library search path\n"
9295 " --no-rosegment compromise security to workaround valgrind bug\n"
93 " -mconsole (windows) --subsystem console to the linker\n"
94 " -mwindows (windows) --subsystem windows to the linker\n"
96 " --subsystem [subsystem] (windows) /SUBSYSTEM:<subsystem> to the linker\n"
9597 " -framework [name] (darwin) link against framework\n"
9698 " -mios-version-min [ver] (darwin) set iOS deployment target\n"
9799 " -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target\n"
......@@ -105,7 +107,7 @@ static int print_full_usage(const char *arg0) {
105107 " --test-cmd [arg] specify test execution command one arg at a time\n"
106108 " --test-cmd-bin appends test binary path to test cmd args\n"
107109 , arg0);
108 return EXIT_SUCCESS;
110 return return_code;
109111}
110112
111113static const char *ZIG_ZEN = "\n"
......@@ -371,8 +373,6 @@ int main(int argc, char **argv) {
371373 const char *target_arch = nullptr;
372374 const char *target_os = nullptr;
373375 const char *target_environ = nullptr;
374 bool mwindows = false;
375 bool mconsole = false;
376376 bool rdynamic = false;
377377 const char *mmacosx_version_min = nullptr;
378378 const char *mios_version_min = nullptr;
......@@ -395,6 +395,9 @@ int main(int argc, char **argv) {
395395 int runtime_args_start = -1;
396396 bool no_rosegment_workaround = false;
397397 bool system_linker_hack = false;
398 TargetSubsystem subsystem = TargetSubsystemAuto;
399 bool is_single_threaded = false;
400 Buf *override_std_dir = nullptr;
398401
399402 if (argc >= 2 && strcmp(argv[1], "build") == 0) {
400403 Buf zig_exe_path_buf = BUF_INIT;
......@@ -430,7 +433,8 @@ int main(int argc, char **argv) {
430433 Buf *build_runner_path = buf_alloc();
431434 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);
434438 g->enable_time_report = timing_info;
435439 buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
436440 codegen_set_out_name(g, buf_create_from_str("build"));
......@@ -512,6 +516,31 @@ int main(int argc, char **argv) {
512516 fprintf(stderr, "\n");
513517 }
514518 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;
515544 }
516545
517546 for (int i = 1; i < argc; i += 1) {
......@@ -524,6 +553,8 @@ int main(int argc, char **argv) {
524553 build_mode = BuildModeSafeRelease;
525554 } else if (strcmp(arg, "--release-small") == 0) {
526555 build_mode = BuildModeSmallRelease;
556 } else if (strcmp(arg, "--help") == 0) {
557 return print_full_usage(arg0, stderr, EXIT_FAILURE);
527558 } else if (strcmp(arg, "--strip") == 0) {
528559 strip = true;
529560 } else if (strcmp(arg, "--static") == 0) {
......@@ -540,10 +571,6 @@ int main(int argc, char **argv) {
540571 verbose_llvm_ir = true;
541572 } else if (strcmp(arg, "--verbose-cimport") == 0) {
542573 verbose_cimport = true;
543 } else if (strcmp(arg, "-mwindows") == 0) {
544 mwindows = true;
545 } else if (strcmp(arg, "-mconsole") == 0) {
546 mconsole = true;
547574 } else if (strcmp(arg, "-rdynamic") == 0) {
548575 rdynamic = true;
549576 } else if (strcmp(arg, "--no-rosegment") == 0) {
......@@ -556,6 +583,8 @@ int main(int argc, char **argv) {
556583 disable_pic = true;
557584 } else if (strcmp(arg, "--system-linker-hack") == 0) {
558585 system_linker_hack = true;
586 } else if (strcmp(arg, "--single-threaded") == 0) {
587 is_single_threaded = true;
559588 } else if (strcmp(arg, "--test-cmd-bin") == 0) {
560589 test_exec_args.append(nullptr);
561590 } else if (arg[1] == 'L' && arg[2] != 0) {
......@@ -647,6 +676,8 @@ int main(int argc, char **argv) {
647676 clang_argv.append(argv[i]);
648677
649678 llvm_argv.append(argv[i]);
679 } else if (strcmp(arg, "--override-std-dir") == 0) {
680 override_std_dir = buf_create_from_str(argv[i]);
650681 } else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) {
651682 lib_dirs.append(argv[i]);
652683 } else if (strcmp(arg, "--library") == 0) {
......@@ -687,6 +718,37 @@ int main(int argc, char **argv) {
687718 ver_patch = atoi(argv[i]);
688719 } else if (strcmp(arg, "--test-cmd") == 0) {
689720 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 }
690752 } else {
691753 fprintf(stderr, "Invalid argument: %s\n", arg);
692754 return print_error_usage(arg0);
......@@ -790,7 +852,8 @@ int main(int argc, char **argv) {
790852
791853 switch (cmd) {
792854 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;
794857 Buf *builtin_source = codegen_generate_builtin_source(g);
795858 if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {
796859 fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));
......@@ -848,7 +911,10 @@ int main(int argc, char **argv) {
848911 if (cmd == CmdRun && buf_out_name == nullptr) {
849912 buf_out_name = buf_create_from_str("run");
850913 }
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
852918 if (disable_pic) {
853919 if (out_type != OutTypeLib || !is_static) {
854920 fprintf(stderr, "--disable-pic only applies to static libraries");
......@@ -862,6 +928,7 @@ int main(int argc, char **argv) {
862928 codegen_set_out_name(g, buf_out_name);
863929 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
864930 codegen_set_is_test(g, cmd == CmdTest);
931 g->is_single_threaded = is_single_threaded;
865932 codegen_set_linker_script(g, linker_script);
866933 if (each_lib_rpath)
867934 codegen_set_each_lib_rpath(g, each_lib_rpath);
......@@ -909,7 +976,6 @@ int main(int argc, char **argv) {
909976 codegen_add_rpath(g, rpath_list.at(i));
910977 }
911978
912 codegen_set_windows_subsystem(g, mwindows, mconsole);
913979 codegen_set_rdynamic(g, rdynamic);
914980 g->no_rosegment_workaround = no_rosegment_workaround;
915981 if (mmacosx_version_min && mios_version_min) {
......@@ -1042,7 +1108,7 @@ int main(int argc, char **argv) {
10421108 }
10431109 }
10441110 case CmdHelp:
1045 return print_full_usage(arg0);
1111 return print_full_usage(arg0, stdout, EXIT_SUCCESS);
10461112 case CmdVersion:
10471113 printf("%s\n", ZIG_VERSION_STRING);
10481114 return EXIT_SUCCESS;
src/os.cpp+32-32
......@@ -1456,7 +1456,7 @@ Error os_self_exe_path(Buf *out_path) {
14561456 if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) {
14571457 return ErrorUnexpected;
14581458 }
1459 buf_resize(out_path, cb);
1459 buf_resize(out_path, cb - 1);
14601460 return ErrorNone;
14611461#endif
14621462 return ErrorFileNotFound;
......@@ -1808,7 +1808,7 @@ Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {
18081808#endif
18091809}
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) {
18121812#if defined(ZIG_OS_WINDOWS)
18131813 // TODO use CreateFileW
18141814 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) {
18341834 return ErrorUnexpected;
18351835 }
18361836 }
1837
18381837 *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
18391849 return ErrorNone;
18401850#else
18411851 for (;;) {
......@@ -1858,7 +1868,26 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) {
18581868 return ErrorFileSystem;
18591869 }
18601870 }
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 }
18611880 *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 }
18621891 return ErrorNone;
18631892 }
18641893#endif
......@@ -1948,35 +1977,6 @@ Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {
19481977#endif
19491978}
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
19801980Error os_file_read(OsFile file, void *ptr, size_t *len) {
19811981#if defined(ZIG_OS_WINDOWS)
19821982 DWORD amt_read;
src/os.hpp+1-2
......@@ -101,9 +101,8 @@ bool os_path_is_absolute(Buf *path);
101101Error ATTRIBUTE_MUST_USE os_make_path(Buf *path);
102102Error 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);
105105Error 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);
107106Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len);
108107Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents);
109108Error 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
381381 else_body = ast_expect(pc, body_parser);
382382 }
383383
384 assert(res->type == NodeTypeTestExpr);
384 assert(res->type == NodeTypeIfOptional);
385385 if (err_payload != nullptr) {
386386 AstNodeTestExpr old = res->data.test_expr;
387387 res->type = NodeTypeIfErrorExpr;
......@@ -844,12 +844,17 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {
844844
845845// VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON
846846static AstNode *ast_parse_var_decl(ParseContext *pc) {
847 Token *first = eat_token_if(pc, TokenIdKeywordConst);
848 if (first == nullptr)
849 first = eat_token_if(pc, TokenIdKeywordVar);
850 if (first == nullptr)
851 return nullptr;
852
847 Token *thread_local_kw = eat_token_if(pc, TokenIdKeywordThreadLocal);
848 Token *mut_kw = eat_token_if(pc, TokenIdKeywordConst);
849 if (mut_kw == nullptr)
850 mut_kw = eat_token_if(pc, TokenIdKeywordVar);
851 if (mut_kw == nullptr) {
852 if (thread_local_kw == nullptr) {
853 return nullptr;
854 } else {
855 ast_invalid_token_error(pc, peek_token(pc));
856 }
857 }
853858 Token *identifier = expect_token(pc, TokenIdSymbol);
854859 AstNode *type_expr = nullptr;
855860 if (eat_token_if(pc, TokenIdColon) != nullptr)
......@@ -863,8 +868,9 @@ static AstNode *ast_parse_var_decl(ParseContext *pc) {
863868
864869 expect_token(pc, TokenIdSemicolon);
865870
866 AstNode *res = ast_create_node(pc, NodeTypeVariableDeclaration, first);
867 res->data.variable_declaration.is_const = first->id == TokenIdKeywordConst;
871 AstNode *res = ast_create_node(pc, NodeTypeVariableDeclaration, mut_kw);
872 res->data.variable_declaration.threadlocal_tok = thread_local_kw;
873 res->data.variable_declaration.is_const = mut_kw->id == TokenIdKeywordConst;
868874 res->data.variable_declaration.symbol = token_buf(identifier);
869875 res->data.variable_declaration.type = type_expr;
870876 res->data.variable_declaration.align_expr = align_expr;
......@@ -990,7 +996,7 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) {
990996 if (requires_semi && else_body == nullptr)
991997 expect_token(pc, TokenIdSemicolon);
992998
993 assert(res->type == NodeTypeTestExpr);
999 assert(res->type == NodeTypeIfOptional);
9941000 if (err_payload != nullptr) {
9951001 AstNodeTestExpr old = res->data.test_expr;
9961002 res->type = NodeTypeIfErrorExpr;
......@@ -2204,7 +2210,7 @@ static AstNode *ast_parse_if_prefix(ParseContext *pc) {
22042210 Optional<PtrPayload> opt_payload = ast_parse_ptr_payload(pc);
22052211
22062212 PtrPayload payload;
2207 AstNode *res = ast_create_node(pc, NodeTypeTestExpr, first);
2213 AstNode *res = ast_create_node(pc, NodeTypeIfOptional, first);
22082214 res->data.test_expr.target_node = condition;
22092215 if (opt_payload.unwrap(&payload)) {
22102216 res->data.test_expr.var_symbol = token_buf(payload.payload);
......@@ -2772,7 +2778,8 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {
27722778// PtrTypeStart
27732779// <- ASTERISK
27742780// / ASTERISK2
2775// / LBRACKET ASTERISK RBRACKET
2781// / PTRUNKNOWN
2782// / PTRC
27762783static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
27772784 Token *asterisk = eat_token_if(pc, TokenIdStar);
27782785 if (asterisk != nullptr) {
......@@ -2798,6 +2805,13 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
27982805 return res;
27992806 }
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
28012815 return nullptr;
28022816}
28032817
......@@ -2999,7 +3013,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
29993013 visit_field(&node->data.if_err_expr.then_node, visit, context);
30003014 visit_field(&node->data.if_err_expr.else_node, visit, context);
30013015 break;
3002 case NodeTypeTestExpr:
3016 case NodeTypeIfOptional:
30033017 visit_field(&node->data.test_expr.target_node, visit, context);
30043018 visit_field(&node->data.test_expr.then_node, visit, context);
30053019 visit_field(&node->data.test_expr.else_node, visit, context);
src/target.cpp+13-2
......@@ -174,6 +174,7 @@ static const Os os_list[] = {
174174 OsContiki,
175175 OsAMDPAL,
176176 OsZen,
177 OsUefi,
177178};
178179
179180// Coordinate with zig_llvm.h
......@@ -282,6 +283,7 @@ ZigLLVM_OSType get_llvm_os_type(Os os_type) {
282283 case OsSolaris:
283284 return ZigLLVM_Solaris;
284285 case OsWindows:
286 case OsUefi:
285287 return ZigLLVM_Win32;
286288 case OsHaiku:
287289 return ZigLLVM_Haiku;
......@@ -394,6 +396,8 @@ const char *get_target_os_name(Os os_type) {
394396 return "freestanding";
395397 case OsZen:
396398 return "zen";
399 case OsUefi:
400 return "uefi";
397401 case OsAnanas:
398402 case OsCloudABI:
399403 case OsDragonFly:
......@@ -756,6 +760,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
756760 case CIntTypeCount:
757761 zig_unreachable();
758762 }
763 case OsUefi:
759764 case OsWindows:
760765 switch (id) {
761766 case CIntTypeShort:
......@@ -802,8 +807,12 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
802807 zig_unreachable();
803808}
804809
810bool target_allows_addr_zero(const ZigTarget *target) {
811 return target->os == OsFreestanding;
812}
813
805814const 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) {
807816 return ".obj";
808817 } else {
809818 return ".o";
......@@ -821,13 +830,15 @@ const char *target_llvm_ir_file_ext(ZigTarget *target) {
821830const char *target_exe_file_ext(ZigTarget *target) {
822831 if (target->os == OsWindows) {
823832 return ".exe";
833 } else if (target->os == OsUefi) {
834 return ".efi";
824835 } else {
825836 return "";
826837 }
827838}
828839
829840const 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) {
831842 if (is_static) {
832843 return ".lib";
833844 } else {
src/target.hpp+14
......@@ -51,6 +51,19 @@ enum Os {
5151 OsContiki,
5252 OsAMDPAL,
5353 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,
5467};
5568
5669struct ZigTarget {
......@@ -122,5 +135,6 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target
122135ZigLLVM_OSType get_llvm_os_type(Os os_type);
123136
124137bool target_is_arm(const ZigTarget *target);
138bool target_allows_addr_zero(const ZigTarget *target);
125139
126140#endif
src/tokenizer.cpp+25-8
......@@ -146,6 +146,7 @@ static const struct ZigKeyword zig_keywords[] = {
146146 {"suspend", TokenIdKeywordSuspend},
147147 {"switch", TokenIdKeywordSwitch},
148148 {"test", TokenIdKeywordTest},
149 {"threadlocal", TokenIdKeywordThreadLocal},
149150 {"true", TokenIdKeywordTrue},
150151 {"try", TokenIdKeywordTry},
151152 {"undefined", TokenIdKeywordUndefined},
......@@ -220,6 +221,7 @@ enum TokenizeState {
220221 TokenizeStateError,
221222 TokenizeStateLBracket,
222223 TokenizeStateLBracketStar,
224 TokenizeStateLBracketStarC,
223225};
224226
225227
......@@ -248,13 +250,8 @@ ATTRIBUTE_PRINTF(2, 3)
248250static void tokenize_error(Tokenize *t, const char *format, ...) {
249251 t->state = TokenizeStateError;
250252
251 if (t->cur_tok) {
252 t->out->err_line = t->cur_tok->start_line;
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 }
253 t->out->err_line = t->line;
254 t->out->err_column = t->column;
258255
259256 va_list ap;
260257 va_start(ap, format);
......@@ -850,7 +847,6 @@ void tokenize(Buf *buf, Tokenization *out) {
850847 switch (c) {
851848 case '*':
852849 t.state = TokenizeStateLBracketStar;
853 set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket);
854850 break;
855851 default:
856852 // reinterpret as just an lbracket
......@@ -861,6 +857,21 @@ void tokenize(Buf *buf, Tokenization *out) {
861857 }
862858 break;
863859 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:
864875 switch (c) {
865876 case ']':
866877 end_token(&t);
......@@ -886,6 +897,9 @@ void tokenize(Buf *buf, Tokenization *out) {
886897 break;
887898 case TokenizeStateSawAmpersand:
888899 switch (c) {
900 case '&':
901 tokenize_error(&t, "`&&` is invalid. Note that `and` is boolean AND.");
902 break;
889903 case '=':
890904 set_token_id(&t, t.cur_tok, TokenIdBitAndEq);
891905 end_token(&t);
......@@ -1492,6 +1506,7 @@ void tokenize(Buf *buf, Tokenization *out) {
14921506 case TokenizeStateLineStringContinue:
14931507 case TokenizeStateLineStringContinueC:
14941508 case TokenizeStateLBracketStar:
1509 case TokenizeStateLBracketStarC:
14951510 tokenize_error(&t, "unexpected EOF");
14961511 break;
14971512 case TokenizeStateLineComment:
......@@ -1529,6 +1544,7 @@ const char * token_name(TokenId id) {
15291544 case TokenIdBitShiftRightEq: return ">>=";
15301545 case TokenIdBitXorEq: return "^=";
15311546 case TokenIdBracketStarBracket: return "[*]";
1547 case TokenIdBracketStarCBracket: return "[*c]";
15321548 case TokenIdCharLiteral: return "CharLiteral";
15331549 case TokenIdCmpEq: return "==";
15341550 case TokenIdCmpGreaterOrEq: return ">=";
......@@ -1588,6 +1604,7 @@ const char * token_name(TokenId id) {
15881604 case TokenIdKeywordStruct: return "struct";
15891605 case TokenIdKeywordSwitch: return "switch";
15901606 case TokenIdKeywordTest: return "test";
1607 case TokenIdKeywordThreadLocal: return "threadlocal";
15911608 case TokenIdKeywordTrue: return "true";
15921609 case TokenIdKeywordTry: return "try";
15931610 case TokenIdKeywordUndefined: return "undefined";
src/tokenizer.hpp+2
......@@ -29,6 +29,7 @@ enum TokenId {
2929 TokenIdBitShiftRightEq,
3030 TokenIdBitXorEq,
3131 TokenIdBracketStarBracket,
32 TokenIdBracketStarCBracket,
3233 TokenIdCharLiteral,
3334 TokenIdCmpEq,
3435 TokenIdCmpGreaterOrEq,
......@@ -88,6 +89,7 @@ enum TokenId {
8889 TokenIdKeywordSuspend,
8990 TokenIdKeywordSwitch,
9091 TokenIdKeywordTest,
92 TokenIdKeywordThreadLocal,
9193 TokenIdKeywordTrue,
9294 TokenIdKeywordTry,
9395 TokenIdKeywordUndefined,
src/translate_c.cpp+1226-1173
......@@ -4,7 +4,6 @@
44 * This file is part of zig, which is MIT licensed.
55 * See http://opensource.org/licenses/MIT
66 */
7
87#include "all_types.hpp"
98#include "analyze.hpp"
109#include "c_tokenizer.hpp"
......@@ -13,7 +12,7 @@
1312#include "os.hpp"
1413#include "translate_c.hpp"
1514#include "parser.hpp"
16
15#include "zig_clang.h"
1716
1817#if __GNUC__ >= 8
1918#pragma GCC diagnostic push
......@@ -30,8 +29,6 @@
3029
3130#include <string.h>
3231
33using namespace clang;
34
3532struct Alias {
3633 Buf *new_name;
3734 Buf *canon_name;
......@@ -87,13 +84,13 @@ struct Context {
8784 HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;
8885 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
8986 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;
90 SourceManager *source_manager;
87 ZigClangSourceManager *source_manager;
9188 ZigList<Alias> aliases;
9289 AstNode *source_node;
9390 bool warnings_on;
9491
9592 CodeGen *codegen;
96 ASTContext *ctx;
93 ZigClangASTContext *ctx;
9794
9895 TransScopeRoot *global_scope;
9996 HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params;
......@@ -117,21 +114,37 @@ static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *paren
117114
118115static TransScopeBlock *trans_scope_block_find(TransScope *scope);
119116
120static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl);
121static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl);
122static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl);
117static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl);
118static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_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,
125122 ResultUsed result_used, TransLRValue lrval,
126123 AstNode **out_node, TransScope **out_child_scope,
127124 TransScope **out_node_scope);
128static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node);
129static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);
130static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);
131static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);
125static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node);
126static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval);
127static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc);
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
133146ATTRIBUTE_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, ...) {
135148 if (!c->warnings_on) {
136149 return;
137150 }
......@@ -141,16 +154,17 @@ static void emit_warning(Context *c, const SourceLocation &sl, const char *forma
141154 Buf *msg = buf_vprintf(format, ap);
142155 va_end(ap);
143156
144 StringRef filename = c->source_manager->getFilename(c->source_manager->getSpellingLoc(sl));
145 const char *filename_bytes = (const char *)filename.bytes_begin();
157 ZigClangSourceLocation sl = bitcast(clang_sl);
158 const char *filename_bytes = ZigClangSourceManager_getFilename(c->source_manager,
159 ZigClangSourceManager_getSpellingLoc(c->source_manager, sl));
146160 Buf *path;
147161 if (filename_bytes) {
148162 path = buf_create_from_str(filename_bytes);
149163 } else {
150164 path = buf_sprintf("(no file)");
151165 }
152 unsigned line = c->source_manager->getSpellingLineNumber(sl);
153 unsigned column = c->source_manager->getSpellingColumnNumber(sl);
166 unsigned line = ZigClangSourceManager_getSpellingLineNumber(c->source_manager, sl);
167 unsigned column = ZigClangSourceManager_getSpellingColumnNumber(c->source_manager, sl);
154168 fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg));
155169}
156170
......@@ -291,11 +305,22 @@ static AstNode *maybe_suppress_result(Context *c, ResultUsed result_used, AstNod
291305 node);
292306}
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
294320static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_volatile, AstNode *child_node, PtrLen ptr_len) {
295321 AstNode *node = trans_create_node(c, NodeTypePointerType);
296322 node->data.pointer_type.star_token = allocate<ZigToken>(1);
297 node->data.pointer_type.star_token->id = (ptr_len == PtrLenSingle) ? TokenIdStar: TokenIdBracketStarBracket;
298 node->data.pointer_type.is_const = is_const;
323 node->data.pointer_type.star_token->id = ptr_len_to_token_id(ptr_len);
299324 node->data.pointer_type.is_const = is_const;
300325 node->data.pointer_type.is_volatile = is_volatile;
301326 node->data.pointer_type.op_expr = child_node;
......@@ -460,15 +485,15 @@ static Buf *string_ref_to_buf(StringRef string_ref) {
460485 return buf_create_from_mem((const char *)string_ref.bytes_begin(), string_ref.size());
461486}
462487
463static const char *decl_name(const Decl *decl) {
464 const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl);
488static const char *decl_name(const clang::Decl *decl) {
489 const clang::NamedDecl *named_decl = static_cast<const clang::NamedDecl *>(decl);
465490 return (const char *)named_decl->getName().bytes_begin();
466491}
467492
468493static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) {
469494 AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
470495 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();
472497 if (!is_negative) {
473498 bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), false);
474499 return node;
......@@ -479,41 +504,41 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int)
479504
480505}
481506
482static const Type *qual_type_canon(QualType qt) {
507static const clang::Type *qual_type_canon(clang::QualType qt) {
483508 return qt.getCanonicalType().getTypePtr();
484509}
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) {
487512 // String literals in C are `char *` but they should really be `const char *`.
488 if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) {
489 const ImplicitCastExpr *cast_expr = static_cast<const ImplicitCastExpr *>(expr);
490 if (cast_expr->getCastKind() == CK_ArrayToPointerDecay) {
491 const Expr *sub_expr = cast_expr->getSubExpr();
492 if (sub_expr->getStmtClass() == Stmt::StringLiteralClass) {
493 QualType array_qt = sub_expr->getType();
494 const ArrayType *array_type = static_cast<const ArrayType *>(array_qt.getTypePtr());
495 QualType pointee_qt = array_type->getElementType();
513 if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
514 const clang::ImplicitCastExpr *cast_expr = static_cast<const clang::ImplicitCastExpr *>(expr);
515 if (cast_expr->getCastKind() == clang::CK_ArrayToPointerDecay) {
516 const clang::Expr *sub_expr = cast_expr->getSubExpr();
517 if (sub_expr->getStmtClass() == clang::Stmt::StringLiteralClass) {
518 clang::QualType array_qt = sub_expr->getType();
519 const clang::ArrayType *array_type = static_cast<const clang::ArrayType *>(array_qt.getTypePtr());
520 clang::QualType pointee_qt = array_type->getElementType();
496521 pointee_qt.addConst();
497 return c->ctx->getPointerType(pointee_qt);
522 return bitcast(ZigClangASTContext_getPointerType(c->ctx, bitcast(pointee_qt)));
498523 }
499524 }
500525 }
501526 return expr->getType();
502527}
503528
504static QualType get_expr_qual_type_before_implicit_cast(Context *c, const Expr *expr) {
505 if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) {
506 const ImplicitCastExpr *cast_expr = static_cast<const ImplicitCastExpr *>(expr);
529static clang::QualType get_expr_qual_type_before_implicit_cast(Context *c, const clang::Expr *expr) {
530 if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
531 const clang::ImplicitCastExpr *cast_expr = static_cast<const clang::ImplicitCastExpr *>(expr);
507532 return get_expr_qual_type(c, cast_expr->getSubExpr());
508533 }
509534 return expr->getType();
510535}
511536
512static AstNode *get_expr_type(Context *c, const Expr *expr) {
537static AstNode *get_expr_type(Context *c, const clang::Expr *expr) {
513538 return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getLocStart());
514539}
515540
516static bool qual_types_equal(QualType t1, QualType t2) {
541static bool qual_types_equal(clang::QualType t1, clang::QualType t2) {
517542 if (t1.isConstQualified() != t2.isConstQualified()) {
518543 return false;
519544 }
......@@ -530,37 +555,37 @@ static bool is_c_void_type(AstNode *node) {
530555 return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));
531556}
532557
533static bool expr_types_equal(Context *c, const Expr *expr1, const Expr *expr2) {
534 QualType t1 = get_expr_qual_type(c, expr1);
535 QualType t2 = get_expr_qual_type(c, expr2);
558static bool expr_types_equal(Context *c, const clang::Expr *expr1, const clang::Expr *expr2) {
559 clang::QualType t1 = get_expr_qual_type(c, expr1);
560 clang::QualType t2 = get_expr_qual_type(c, expr2);
536561
537562 return qual_types_equal(t1, t2);
538563}
539564
540static bool qual_type_is_ptr(QualType qt) {
541 const Type *ty = qual_type_canon(qt);
542 return ty->getTypeClass() == Type::Pointer;
565static bool qual_type_is_ptr(clang::QualType qt) {
566 const clang::Type *ty = qual_type_canon(qt);
567 return ty->getTypeClass() == clang::Type::Pointer;
543568}
544569
545static const FunctionProtoType *qual_type_get_fn_proto(QualType qt, bool *is_ptr) {
546 const Type *ty = qual_type_canon(qt);
570static const clang::FunctionProtoType *qual_type_get_fn_proto(clang::QualType qt, bool *is_ptr) {
571 const clang::Type *ty = qual_type_canon(qt);
547572 *is_ptr = false;
548573
549 if (ty->getTypeClass() == Type::Pointer) {
574 if (ty->getTypeClass() == clang::Type::Pointer) {
550575 *is_ptr = true;
551 const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
552 QualType child_qt = pointer_ty->getPointeeType();
576 const clang::PointerType *pointer_ty = static_cast<const clang::PointerType*>(ty);
577 clang::QualType child_qt = pointer_ty->getPointeeType();
553578 ty = child_qt.getTypePtr();
554579 }
555580
556 if (ty->getTypeClass() == Type::FunctionProto) {
557 return static_cast<const FunctionProtoType*>(ty);
581 if (ty->getTypeClass() == clang::Type::FunctionProto) {
582 return static_cast<const clang::FunctionProtoType*>(ty);
558583 }
559584
560585 return nullptr;
561586}
562587
563static bool qual_type_is_fn_ptr(QualType qt) {
588static bool qual_type_is_fn_ptr(clang::QualType qt) {
564589 bool is_ptr;
565590 if (qual_type_get_fn_proto(qt, &is_ptr)) {
566591 return is_ptr;
......@@ -569,30 +594,30 @@ static bool qual_type_is_fn_ptr(QualType qt) {
569594 return false;
570595}
571596
572static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) {
573 const Type *ty = qt.getTypePtr();
597static uint32_t qual_type_int_bit_width(Context *c, const clang::QualType &qt, const clang::SourceLocation &source_loc) {
598 const clang::Type *ty = qt.getTypePtr();
574599 switch (ty->getTypeClass()) {
575 case Type::Builtin:
600 case clang::Type::Builtin:
576601 {
577 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
602 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);
578603 switch (builtin_ty->getKind()) {
579 case BuiltinType::Char_U:
580 case BuiltinType::UChar:
581 case BuiltinType::Char_S:
582 case BuiltinType::SChar:
604 case clang::BuiltinType::Char_U:
605 case clang::BuiltinType::UChar:
606 case clang::BuiltinType::Char_S:
607 case clang::BuiltinType::SChar:
583608 return 8;
584 case BuiltinType::UInt128:
585 case BuiltinType::Int128:
609 case clang::BuiltinType::UInt128:
610 case clang::BuiltinType::Int128:
586611 return 128;
587612 default:
588613 return 0;
589614 }
590615 zig_unreachable();
591616 }
592 case Type::Typedef:
617 case clang::Type::Typedef:
593618 {
594 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
595 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
619 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
620 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
596621 const char *type_name = decl_name(typedef_decl);
597622 if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) {
598623 return 8;
......@@ -613,8 +638,8 @@ static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const So
613638}
614639
615640
616static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
617 const SourceLocation &source_loc)
641static AstNode *qual_type_to_log2_int_ref(Context *c, const clang::QualType &qt,
642 const clang::SourceLocation &source_loc)
618643{
619644 uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc);
620645 if (int_bit_width != 0) {
......@@ -632,7 +657,7 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
632657// FieldAccess
633658// FnCall (.builtin = true)
634659// Symbol "import"
635// StringLiteral "std"
660// clang::StringLiteral "std"
636661// Symbol "math"
637662// Symbol "Log2Int"
638663// zig_type_node
......@@ -646,21 +671,21 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
646671 return log2int_fn_call;
647672}
648673
649static bool qual_type_child_is_fn_proto(const QualType &qt) {
650 if (qt.getTypePtr()->getTypeClass() == Type::Paren) {
651 const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr());
652 if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) {
674static bool qual_type_child_is_fn_proto(const clang::QualType &qt) {
675 if (qt.getTypePtr()->getTypeClass() == clang::Type::Paren) {
676 const clang::ParenType *paren_type = static_cast<const clang::ParenType *>(qt.getTypePtr());
677 if (paren_type->getInnerType()->getTypeClass() == clang::Type::FunctionProto) {
653678 return true;
654679 }
655 } else if (qt.getTypePtr()->getTypeClass() == Type::Attributed) {
656 const AttributedType *attr_type = static_cast<const AttributedType *>(qt.getTypePtr());
680 } else if (qt.getTypePtr()->getTypeClass() == clang::Type::Attributed) {
681 const clang::AttributedType *attr_type = static_cast<const clang::AttributedType *>(qt.getTypePtr());
657682 return qual_type_child_is_fn_proto(attr_type->getEquivalentType());
658683 }
659684 return false;
660685}
661686
662static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, QualType dest_type,
663 QualType src_type, AstNode *expr)
687static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_location, clang::QualType dest_type,
688 clang::QualType src_type, AstNode *expr)
664689{
665690 if (qual_types_equal(dest_type, src_type)) {
666691 return expr;
......@@ -677,72 +702,72 @@ static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location,
677702 return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr);
678703}
679704
680static bool c_is_signed_integer(Context *c, QualType qt) {
681 const Type *c_type = qual_type_canon(qt);
682 if (c_type->getTypeClass() != Type::Builtin)
705static bool c_is_signed_integer(Context *c, clang::QualType qt) {
706 const clang::Type *c_type = qual_type_canon(qt);
707 if (c_type->getTypeClass() != clang::Type::Builtin)
683708 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);
685710 switch (builtin_ty->getKind()) {
686 case BuiltinType::SChar:
687 case BuiltinType::Short:
688 case BuiltinType::Int:
689 case BuiltinType::Long:
690 case BuiltinType::LongLong:
691 case BuiltinType::Int128:
692 case BuiltinType::WChar_S:
711 case clang::BuiltinType::SChar:
712 case clang::BuiltinType::Short:
713 case clang::BuiltinType::Int:
714 case clang::BuiltinType::Long:
715 case clang::BuiltinType::LongLong:
716 case clang::BuiltinType::Int128:
717 case clang::BuiltinType::WChar_S:
693718 return true;
694719 default:
695720 return false;
696721 }
697722}
698723
699static bool c_is_unsigned_integer(Context *c, QualType qt) {
700 const Type *c_type = qual_type_canon(qt);
701 if (c_type->getTypeClass() != Type::Builtin)
724static bool c_is_unsigned_integer(Context *c, clang::QualType qt) {
725 const clang::Type *c_type = qual_type_canon(qt);
726 if (c_type->getTypeClass() != clang::Type::Builtin)
702727 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);
704729 switch (builtin_ty->getKind()) {
705 case BuiltinType::Char_U:
706 case BuiltinType::UChar:
707 case BuiltinType::Char_S:
708 case BuiltinType::UShort:
709 case BuiltinType::UInt:
710 case BuiltinType::ULong:
711 case BuiltinType::ULongLong:
712 case BuiltinType::UInt128:
713 case BuiltinType::WChar_U:
730 case clang::BuiltinType::Char_U:
731 case clang::BuiltinType::UChar:
732 case clang::BuiltinType::Char_S:
733 case clang::BuiltinType::UShort:
734 case clang::BuiltinType::UInt:
735 case clang::BuiltinType::ULong:
736 case clang::BuiltinType::ULongLong:
737 case clang::BuiltinType::UInt128:
738 case clang::BuiltinType::WChar_U:
714739 return true;
715740 default:
716741 return false;
717742 }
718743}
719744
720static bool c_is_builtin_type(Context *c, QualType qt, BuiltinType::Kind kind) {
721 const Type *c_type = qual_type_canon(qt);
722 if (c_type->getTypeClass() != Type::Builtin)
745static bool c_is_builtin_type(Context *c, clang::QualType qt, clang::BuiltinType::Kind kind) {
746 const clang::Type *c_type = qual_type_canon(qt);
747 if (c_type->getTypeClass() != clang::Type::Builtin)
723748 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);
725750 return builtin_ty->getKind() == kind;
726751}
727752
728static bool c_is_float(Context *c, QualType qt) {
729 const Type *c_type = qt.getTypePtr();
730 if (c_type->getTypeClass() != Type::Builtin)
753static bool c_is_float(Context *c, clang::QualType qt) {
754 const clang::Type *c_type = qt.getTypePtr();
755 if (c_type->getTypeClass() != clang::Type::Builtin)
731756 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);
733758 switch (builtin_ty->getKind()) {
734 case BuiltinType::Half:
735 case BuiltinType::Float:
736 case BuiltinType::Double:
737 case BuiltinType::Float128:
738 case BuiltinType::LongDouble:
759 case clang::BuiltinType::Half:
760 case clang::BuiltinType::Float:
761 case clang::BuiltinType::Double:
762 case clang::BuiltinType::Float128:
763 case clang::BuiltinType::LongDouble:
739764 return true;
740765 default:
741766 return false;
742767 }
743768}
744769
745static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
770static bool qual_type_has_wrapping_overflow(Context *c, clang::QualType qt) {
746771 if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) {
747772 // float and signed integer overflow is undefined behavior.
748773 return false;
......@@ -752,23 +777,23 @@ static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
752777 }
753778}
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) {
756781 switch (ty->getTypeClass()) {
757 case Type::Builtin: {
758 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
759 return builtin_ty->getKind() == BuiltinType::Void;
782 case clang::Type::Builtin: {
783 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);
784 return builtin_ty->getKind() == clang::BuiltinType::Void;
760785 }
761 case Type::Record: {
762 const RecordType *record_ty = static_cast<const RecordType*>(ty);
786 case clang::Type::Record: {
787 const clang::RecordType *record_ty = static_cast<const clang::RecordType*>(ty);
763788 return record_ty->getDecl()->getDefinition() == nullptr;
764789 }
765 case Type::Elaborated: {
766 const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);
790 case clang::Type::Elaborated: {
791 const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty);
767792 return type_is_opaque(c, elaborated_ty->getNamedType().getTypePtr(), source_loc);
768793 }
769 case Type::Typedef: {
770 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
771 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
794 case clang::Type::Typedef: {
795 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
796 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
772797 return type_is_opaque(c, typedef_decl->getUnderlyingType().getTypePtr(), source_loc);
773798 }
774799 default:
......@@ -776,145 +801,145 @@ static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &sou
776801 }
777802}
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) {
780805 switch (ty->getTypeClass()) {
781 case Type::Builtin:
806 case clang::Type::Builtin:
782807 {
783 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
808 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);
784809 switch (builtin_ty->getKind()) {
785 case BuiltinType::Void:
810 case clang::BuiltinType::Void:
786811 return trans_create_node_symbol_str(c, "c_void");
787 case BuiltinType::Bool:
812 case clang::BuiltinType::Bool:
788813 return trans_create_node_symbol_str(c, "bool");
789 case BuiltinType::Char_U:
790 case BuiltinType::UChar:
791 case BuiltinType::Char_S:
792 case BuiltinType::Char8:
814 case clang::BuiltinType::Char_U:
815 case clang::BuiltinType::UChar:
816 case clang::BuiltinType::Char_S:
817 case clang::BuiltinType::Char8:
793818 return trans_create_node_symbol_str(c, "u8");
794 case BuiltinType::SChar:
819 case clang::BuiltinType::SChar:
795820 return trans_create_node_symbol_str(c, "i8");
796 case BuiltinType::UShort:
821 case clang::BuiltinType::UShort:
797822 return trans_create_node_symbol_str(c, "c_ushort");
798 case BuiltinType::UInt:
823 case clang::BuiltinType::UInt:
799824 return trans_create_node_symbol_str(c, "c_uint");
800 case BuiltinType::ULong:
825 case clang::BuiltinType::ULong:
801826 return trans_create_node_symbol_str(c, "c_ulong");
802 case BuiltinType::ULongLong:
827 case clang::BuiltinType::ULongLong:
803828 return trans_create_node_symbol_str(c, "c_ulonglong");
804 case BuiltinType::Short:
829 case clang::BuiltinType::Short:
805830 return trans_create_node_symbol_str(c, "c_short");
806 case BuiltinType::Int:
831 case clang::BuiltinType::Int:
807832 return trans_create_node_symbol_str(c, "c_int");
808 case BuiltinType::Long:
833 case clang::BuiltinType::Long:
809834 return trans_create_node_symbol_str(c, "c_long");
810 case BuiltinType::LongLong:
835 case clang::BuiltinType::LongLong:
811836 return trans_create_node_symbol_str(c, "c_longlong");
812 case BuiltinType::UInt128:
837 case clang::BuiltinType::UInt128:
813838 return trans_create_node_symbol_str(c, "u128");
814 case BuiltinType::Int128:
839 case clang::BuiltinType::Int128:
815840 return trans_create_node_symbol_str(c, "i128");
816 case BuiltinType::Float:
841 case clang::BuiltinType::Float:
817842 return trans_create_node_symbol_str(c, "f32");
818 case BuiltinType::Double:
843 case clang::BuiltinType::Double:
819844 return trans_create_node_symbol_str(c, "f64");
820 case BuiltinType::Float128:
845 case clang::BuiltinType::Float128:
821846 return trans_create_node_symbol_str(c, "f128");
822 case BuiltinType::Float16:
847 case clang::BuiltinType::Float16:
823848 return trans_create_node_symbol_str(c, "f16");
824 case BuiltinType::LongDouble:
849 case clang::BuiltinType::LongDouble:
825850 return trans_create_node_symbol_str(c, "c_longdouble");
826 case BuiltinType::WChar_U:
827 case BuiltinType::Char16:
828 case BuiltinType::Char32:
829 case BuiltinType::WChar_S:
830 case BuiltinType::Half:
831 case BuiltinType::NullPtr:
832 case BuiltinType::ObjCId:
833 case BuiltinType::ObjCClass:
834 case BuiltinType::ObjCSel:
835 case BuiltinType::OMPArraySection:
836 case BuiltinType::Dependent:
837 case BuiltinType::Overload:
838 case BuiltinType::BoundMember:
839 case BuiltinType::PseudoObject:
840 case BuiltinType::UnknownAny:
841 case BuiltinType::BuiltinFn:
842 case BuiltinType::ARCUnbridgedCast:
843 case BuiltinType::ShortAccum:
844 case BuiltinType::Accum:
845 case BuiltinType::LongAccum:
846 case BuiltinType::UShortAccum:
847 case BuiltinType::UAccum:
848 case BuiltinType::ULongAccum:
849
850 case BuiltinType::OCLImage1dRO:
851 case BuiltinType::OCLImage1dArrayRO:
852 case BuiltinType::OCLImage1dBufferRO:
853 case BuiltinType::OCLImage2dRO:
854 case BuiltinType::OCLImage2dArrayRO:
855 case BuiltinType::OCLImage2dDepthRO:
856 case BuiltinType::OCLImage2dArrayDepthRO:
857 case BuiltinType::OCLImage2dMSAARO:
858 case BuiltinType::OCLImage2dArrayMSAARO:
859 case BuiltinType::OCLImage2dMSAADepthRO:
860 case BuiltinType::OCLImage2dArrayMSAADepthRO:
861 case BuiltinType::OCLImage3dRO:
862 case BuiltinType::OCLImage1dWO:
863 case BuiltinType::OCLImage1dArrayWO:
864 case BuiltinType::OCLImage1dBufferWO:
865 case BuiltinType::OCLImage2dWO:
866 case BuiltinType::OCLImage2dArrayWO:
867 case BuiltinType::OCLImage2dDepthWO:
868 case BuiltinType::OCLImage2dArrayDepthWO:
869 case BuiltinType::OCLImage2dMSAAWO:
870 case BuiltinType::OCLImage2dArrayMSAAWO:
871 case BuiltinType::OCLImage2dMSAADepthWO:
872 case BuiltinType::OCLImage2dArrayMSAADepthWO:
873 case BuiltinType::OCLImage3dWO:
874 case BuiltinType::OCLImage1dRW:
875 case BuiltinType::OCLImage1dArrayRW:
876 case BuiltinType::OCLImage1dBufferRW:
877 case BuiltinType::OCLImage2dRW:
878 case BuiltinType::OCLImage2dArrayRW:
879 case BuiltinType::OCLImage2dDepthRW:
880 case BuiltinType::OCLImage2dArrayDepthRW:
881 case BuiltinType::OCLImage2dMSAARW:
882 case BuiltinType::OCLImage2dArrayMSAARW:
883 case BuiltinType::OCLImage2dMSAADepthRW:
884 case BuiltinType::OCLImage2dArrayMSAADepthRW:
885 case BuiltinType::OCLImage3dRW:
886 case BuiltinType::OCLSampler:
887 case BuiltinType::OCLEvent:
888 case BuiltinType::OCLClkEvent:
889 case BuiltinType::OCLQueue:
890 case BuiltinType::OCLReserveID:
891 case BuiltinType::ShortFract:
892 case BuiltinType::Fract:
893 case BuiltinType::LongFract:
894 case BuiltinType::UShortFract:
895 case BuiltinType::UFract:
896 case BuiltinType::ULongFract:
897 case BuiltinType::SatShortAccum:
898 case BuiltinType::SatAccum:
899 case BuiltinType::SatLongAccum:
900 case BuiltinType::SatUShortAccum:
901 case BuiltinType::SatUAccum:
902 case BuiltinType::SatULongAccum:
903 case BuiltinType::SatShortFract:
904 case BuiltinType::SatFract:
905 case BuiltinType::SatLongFract:
906 case BuiltinType::SatUShortFract:
907 case BuiltinType::SatUFract:
908 case BuiltinType::SatULongFract:
851 case clang::BuiltinType::WChar_U:
852 case clang::BuiltinType::Char16:
853 case clang::BuiltinType::Char32:
854 case clang::BuiltinType::WChar_S:
855 case clang::BuiltinType::Half:
856 case clang::BuiltinType::NullPtr:
857 case clang::BuiltinType::ObjCId:
858 case clang::BuiltinType::ObjCClass:
859 case clang::BuiltinType::ObjCSel:
860 case clang::BuiltinType::OMPArraySection:
861 case clang::BuiltinType::Dependent:
862 case clang::BuiltinType::Overload:
863 case clang::BuiltinType::BoundMember:
864 case clang::BuiltinType::PseudoObject:
865 case clang::BuiltinType::UnknownAny:
866 case clang::BuiltinType::BuiltinFn:
867 case clang::BuiltinType::ARCUnbridgedCast:
868 case clang::BuiltinType::ShortAccum:
869 case clang::BuiltinType::Accum:
870 case clang::BuiltinType::LongAccum:
871 case clang::BuiltinType::UShortAccum:
872 case clang::BuiltinType::UAccum:
873 case clang::BuiltinType::ULongAccum:
874
875 case clang::BuiltinType::OCLImage1dRO:
876 case clang::BuiltinType::OCLImage1dArrayRO:
877 case clang::BuiltinType::OCLImage1dBufferRO:
878 case clang::BuiltinType::OCLImage2dRO:
879 case clang::BuiltinType::OCLImage2dArrayRO:
880 case clang::BuiltinType::OCLImage2dDepthRO:
881 case clang::BuiltinType::OCLImage2dArrayDepthRO:
882 case clang::BuiltinType::OCLImage2dMSAARO:
883 case clang::BuiltinType::OCLImage2dArrayMSAARO:
884 case clang::BuiltinType::OCLImage2dMSAADepthRO:
885 case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:
886 case clang::BuiltinType::OCLImage3dRO:
887 case clang::BuiltinType::OCLImage1dWO:
888 case clang::BuiltinType::OCLImage1dArrayWO:
889 case clang::BuiltinType::OCLImage1dBufferWO:
890 case clang::BuiltinType::OCLImage2dWO:
891 case clang::BuiltinType::OCLImage2dArrayWO:
892 case clang::BuiltinType::OCLImage2dDepthWO:
893 case clang::BuiltinType::OCLImage2dArrayDepthWO:
894 case clang::BuiltinType::OCLImage2dMSAAWO:
895 case clang::BuiltinType::OCLImage2dArrayMSAAWO:
896 case clang::BuiltinType::OCLImage2dMSAADepthWO:
897 case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:
898 case clang::BuiltinType::OCLImage3dWO:
899 case clang::BuiltinType::OCLImage1dRW:
900 case clang::BuiltinType::OCLImage1dArrayRW:
901 case clang::BuiltinType::OCLImage1dBufferRW:
902 case clang::BuiltinType::OCLImage2dRW:
903 case clang::BuiltinType::OCLImage2dArrayRW:
904 case clang::BuiltinType::OCLImage2dDepthRW:
905 case clang::BuiltinType::OCLImage2dArrayDepthRW:
906 case clang::BuiltinType::OCLImage2dMSAARW:
907 case clang::BuiltinType::OCLImage2dArrayMSAARW:
908 case clang::BuiltinType::OCLImage2dMSAADepthRW:
909 case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:
910 case clang::BuiltinType::OCLImage3dRW:
911 case clang::BuiltinType::OCLSampler:
912 case clang::BuiltinType::OCLEvent:
913 case clang::BuiltinType::OCLClkEvent:
914 case clang::BuiltinType::OCLQueue:
915 case clang::BuiltinType::OCLReserveID:
916 case clang::BuiltinType::ShortFract:
917 case clang::BuiltinType::Fract:
918 case clang::BuiltinType::LongFract:
919 case clang::BuiltinType::UShortFract:
920 case clang::BuiltinType::UFract:
921 case clang::BuiltinType::ULongFract:
922 case clang::BuiltinType::SatShortAccum:
923 case clang::BuiltinType::SatAccum:
924 case clang::BuiltinType::SatLongAccum:
925 case clang::BuiltinType::SatUShortAccum:
926 case clang::BuiltinType::SatUAccum:
927 case clang::BuiltinType::SatULongAccum:
928 case clang::BuiltinType::SatShortFract:
929 case clang::BuiltinType::SatFract:
930 case clang::BuiltinType::SatLongFract:
931 case clang::BuiltinType::SatUShortFract:
932 case clang::BuiltinType::SatUFract:
933 case clang::BuiltinType::SatULongFract:
909934 emit_warning(c, source_loc, "unsupported builtin type");
910935 return nullptr;
911936 }
912937 break;
913938 }
914 case Type::Pointer:
939 case clang::Type::Pointer:
915940 {
916 const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
917 QualType child_qt = pointer_ty->getPointeeType();
941 const clang::PointerType *pointer_ty = static_cast<const clang::PointerType*>(ty);
942 clang::QualType child_qt = pointer_ty->getPointeeType();
918943 AstNode *child_node = trans_qual_type(c, child_qt, source_loc);
919944 if (child_node == nullptr) {
920945 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
925950 return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
926951 }
927952
928 PtrLen ptr_len = type_is_opaque(c, child_qt.getTypePtr(), source_loc) ? PtrLenSingle : PtrLenUnknown;
929
930 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
931 child_qt.isVolatileQualified(), child_node, ptr_len);
932 return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);
953 if (type_is_opaque(c, child_qt.getTypePtr(), source_loc)) {
954 AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
955 child_qt.isVolatileQualified(), child_node, PtrLenSingle);
956 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 }
933961 }
934 case Type::Typedef:
962 case clang::Type::Typedef:
935963 {
936 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
937 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
964 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
965 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
938966 return resolve_typedef_decl(c, typedef_decl);
939967 }
940 case Type::Elaborated:
968 case clang::Type::Elaborated:
941969 {
942 const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);
970 const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty);
943971 switch (elaborated_ty->getKeyword()) {
944 case ETK_Struct:
945 case ETK_Enum:
946 case ETK_Union:
972 case clang::ETK_Struct:
973 case clang::ETK_Enum:
974 case clang::ETK_Union:
947975 return trans_qual_type(c, elaborated_ty->getNamedType(), source_loc);
948 case ETK_Interface:
949 case ETK_Class:
950 case ETK_Typename:
951 case ETK_None:
976 case clang::ETK_Interface:
977 case clang::ETK_Class:
978 case clang::ETK_Typename:
979 case clang::ETK_None:
952980 emit_warning(c, source_loc, "unsupported elaborated type");
953981 return nullptr;
954982 }
955983 }
956 case Type::FunctionProto:
984 case clang::Type::FunctionProto:
957985 {
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
960988 AstNode *proto_node = trans_create_node(c, NodeTypeFnProto);
961989 switch (fn_proto_ty->getCallConv()) {
962 case CC_C: // __attribute__((cdecl))
990 case clang::CC_C: // __attribute__((cdecl))
963991 proto_node->data.fn_proto.cc = CallingConventionC;
964992 proto_node->data.fn_proto.is_extern = true;
965993 break;
966 case CC_X86StdCall: // __attribute__((stdcall))
994 case clang::CC_X86StdCall: // __attribute__((stdcall))
967995 proto_node->data.fn_proto.cc = CallingConventionStdcall;
968996 break;
969 case CC_X86FastCall: // __attribute__((fastcall))
997 case clang::CC_X86FastCall: // __attribute__((fastcall))
970998 emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall");
971999 return nullptr;
972 case CC_X86ThisCall: // __attribute__((thiscall))
1000 case clang::CC_X86ThisCall: // __attribute__((thiscall))
9731001 emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall");
9741002 return nullptr;
975 case CC_X86VectorCall: // __attribute__((vectorcall))
1003 case clang::CC_X86VectorCall: // __attribute__((vectorcall))
9761004 emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall");
9771005 return nullptr;
978 case CC_X86Pascal: // __attribute__((pascal))
1006 case clang::CC_X86Pascal: // __attribute__((pascal))
9791007 emit_warning(c, source_loc, "unsupported calling convention: x86 pascal");
9801008 return nullptr;
981 case CC_Win64: // __attribute__((ms_abi))
1009 case clang::CC_Win64: // __attribute__((ms_abi))
9821010 emit_warning(c, source_loc, "unsupported calling convention: win64");
9831011 return nullptr;
984 case CC_X86_64SysV: // __attribute__((sysv_abi))
1012 case clang::CC_X86_64SysV: // __attribute__((sysv_abi))
9851013 emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv");
9861014 return nullptr;
987 case CC_X86RegCall:
1015 case clang::CC_X86RegCall:
9881016 emit_warning(c, source_loc, "unsupported calling convention: x86 reg");
9891017 return nullptr;
990 case CC_AAPCS: // __attribute__((pcs("aapcs")))
1018 case clang::CC_AAPCS: // __attribute__((pcs("aapcs")))
9911019 emit_warning(c, source_loc, "unsupported calling convention: aapcs");
9921020 return nullptr;
993 case CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
1021 case clang::CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
9941022 emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp");
9951023 return nullptr;
996 case CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))
1024 case clang::CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))
9971025 emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc");
9981026 return nullptr;
999 case CC_SpirFunction: // default for OpenCL functions on SPIR target
1027 case clang::CC_SpirFunction: // default for OpenCL functions on SPIR target
10001028 emit_warning(c, source_loc, "unsupported calling convention: SPIR function");
10011029 return nullptr;
1002 case CC_OpenCLKernel:
1030 case clang::CC_OpenCLKernel:
10031031 emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel");
10041032 return nullptr;
1005 case CC_Swift:
1033 case clang::CC_Swift:
10061034 emit_warning(c, source_loc, "unsupported calling convention: Swift");
10071035 return nullptr;
1008 case CC_PreserveMost:
1036 case clang::CC_PreserveMost:
10091037 emit_warning(c, source_loc, "unsupported calling convention: PreserveMost");
10101038 return nullptr;
1011 case CC_PreserveAll:
1039 case clang::CC_PreserveAll:
10121040 emit_warning(c, source_loc, "unsupported calling convention: PreserveAll");
10131041 return nullptr;
10141042 }
......@@ -1026,7 +1054,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
10261054 return nullptr;
10271055 }
10281056 // convert c_void to actual void (only for return type)
1029 // we do want to look at the AstNode instead of QualType, because
1057 // we do want to look at the AstNode instead of clang::QualType, because
10301058 // if they do something like:
10311059 // typedef Foo void;
10321060 // void foo(void) -> Foo;
......@@ -1043,7 +1071,7 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
10431071 }
10441072
10451073 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);
10471075 AstNode *param_type_node = trans_qual_type(c, qt, source_loc);
10481076
10491077 if (param_type_node == nullptr) {
......@@ -1066,19 +1094,19 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
10661094
10671095 return proto_node;
10681096 }
1069 case Type::Record:
1097 case clang::Type::Record:
10701098 {
1071 const RecordType *record_ty = static_cast<const RecordType*>(ty);
1099 const clang::RecordType *record_ty = static_cast<const clang::RecordType*>(ty);
10721100 return resolve_record_decl(c, record_ty->getDecl());
10731101 }
1074 case Type::Enum:
1102 case clang::Type::Enum:
10751103 {
1076 const EnumType *enum_ty = static_cast<const EnumType*>(ty);
1104 const clang::EnumType *enum_ty = static_cast<const clang::EnumType*>(ty);
10771105 return resolve_enum_decl(c, enum_ty->getDecl());
10781106 }
1079 case Type::ConstantArray:
1107 case clang::Type::ConstantArray:
10801108 {
1081 const ConstantArrayType *const_arr_ty = static_cast<const ConstantArrayType *>(ty);
1109 const clang::ConstantArrayType *const_arr_ty = static_cast<const clang::ConstantArrayType *>(ty);
10821110 AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc);
10831111 if (child_type_node == nullptr) {
10841112 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
10881116 AstNode *size_node = trans_create_node_unsigned(c, size);
10891117 return trans_create_node_array_type(c, size_node, child_type_node);
10901118 }
1091 case Type::Paren:
1119 case clang::Type::Paren:
10921120 {
1093 const ParenType *paren_ty = static_cast<const ParenType *>(ty);
1121 const clang::ParenType *paren_ty = static_cast<const clang::ParenType *>(ty);
10941122 return trans_qual_type(c, paren_ty->getInnerType(), source_loc);
10951123 }
1096 case Type::Decayed:
1124 case clang::Type::Decayed:
10971125 {
1098 const DecayedType *decayed_ty = static_cast<const DecayedType *>(ty);
1126 const clang::DecayedType *decayed_ty = static_cast<const clang::DecayedType *>(ty);
10991127 return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc);
11001128 }
1101 case Type::Attributed:
1129 case clang::Type::Attributed:
11021130 {
1103 const AttributedType *attributed_ty = static_cast<const AttributedType *>(ty);
1131 const clang::AttributedType *attributed_ty = static_cast<const clang::AttributedType *>(ty);
11041132 return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc);
11051133 }
1106 case Type::IncompleteArray:
1134 case clang::Type::IncompleteArray:
11071135 {
1108 const IncompleteArrayType *incomplete_array_ty = static_cast<const IncompleteArrayType *>(ty);
1109 QualType child_qt = incomplete_array_ty->getElementType();
1136 const clang::IncompleteArrayType *incomplete_array_ty = static_cast<const clang::IncompleteArrayType *>(ty);
1137 clang::QualType child_qt = incomplete_array_ty->getElementType();
11101138 AstNode *child_type_node = trans_qual_type(c, child_qt, source_loc);
11111139 if (child_type_node == nullptr) {
11121140 emit_warning(c, source_loc, "unresolved array element type");
11131141 return nullptr;
11141142 }
11151143 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);
11171145 return pointer_node;
11181146 }
1119 case Type::BlockPointer:
1120 case Type::LValueReference:
1121 case Type::RValueReference:
1122 case Type::MemberPointer:
1123 case Type::VariableArray:
1124 case Type::DependentSizedArray:
1125 case Type::DependentSizedExtVector:
1126 case Type::Vector:
1127 case Type::ExtVector:
1128 case Type::FunctionNoProto:
1129 case Type::UnresolvedUsing:
1130 case Type::Adjusted:
1131 case Type::TypeOfExpr:
1132 case Type::TypeOf:
1133 case Type::Decltype:
1134 case Type::UnaryTransform:
1135 case Type::TemplateTypeParm:
1136 case Type::SubstTemplateTypeParm:
1137 case Type::SubstTemplateTypeParmPack:
1138 case Type::TemplateSpecialization:
1139 case Type::Auto:
1140 case Type::InjectedClassName:
1141 case Type::DependentName:
1142 case Type::DependentTemplateSpecialization:
1143 case Type::PackExpansion:
1144 case Type::ObjCObject:
1145 case Type::ObjCInterface:
1146 case Type::Complex:
1147 case Type::ObjCObjectPointer:
1148 case Type::Atomic:
1149 case Type::Pipe:
1150 case Type::ObjCTypeParam:
1151 case Type::DeducedTemplateSpecialization:
1152 case Type::DependentAddressSpace:
1153 case Type::DependentVector:
1147 case clang::Type::BlockPointer:
1148 case clang::Type::LValueReference:
1149 case clang::Type::RValueReference:
1150 case clang::Type::MemberPointer:
1151 case clang::Type::VariableArray:
1152 case clang::Type::DependentSizedArray:
1153 case clang::Type::DependentSizedExtVector:
1154 case clang::Type::Vector:
1155 case clang::Type::ExtVector:
1156 case clang::Type::FunctionNoProto:
1157 case clang::Type::UnresolvedUsing:
1158 case clang::Type::Adjusted:
1159 case clang::Type::TypeOfExpr:
1160 case clang::Type::TypeOf:
1161 case clang::Type::Decltype:
1162 case clang::Type::UnaryTransform:
1163 case clang::Type::TemplateTypeParm:
1164 case clang::Type::SubstTemplateTypeParm:
1165 case clang::Type::SubstTemplateTypeParmPack:
1166 case clang::Type::TemplateSpecialization:
1167 case clang::Type::Auto:
1168 case clang::Type::InjectedClassName:
1169 case clang::Type::DependentName:
1170 case clang::Type::DependentTemplateSpecialization:
1171 case clang::Type::PackExpansion:
1172 case clang::Type::ObjCObject:
1173 case clang::Type::ObjCInterface:
1174 case clang::Type::Complex:
1175 case clang::Type::ObjCObjectPointer:
1176 case clang::Type::Atomic:
1177 case clang::Type::Pipe:
1178 case clang::Type::ObjCTypeParam:
1179 case clang::Type::DeducedTemplateSpecialization:
1180 case clang::Type::DependentAddressSpace:
1181 case clang::Type::DependentVector:
11541182 emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName());
11551183 return nullptr;
11561184 }
11571185 zig_unreachable();
11581186}
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) {
11611189 return trans_type(c, qt.getTypePtr(), source_loc);
11621190}
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,
11651193 AstNode *block_node, TransScope **out_node_scope)
11661194{
11671195 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) {
11691197 AstNode *child_node;
11701198 scope = trans_stmt(c, scope, *it, &child_node);
11711199 if (scope == nullptr)
......@@ -1179,7 +1207,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const Compo
11791207 return ErrorNone;
11801208}
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,
11831211 TransScope **out_node_scope)
11841212{
11851213 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
11881216 return child_scope_block->node;
11891217}
11901218
1191static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStmt *stmt) {
1192 const Expr *value_expr = stmt->getRetValue();
1219static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::ReturnStmt *stmt) {
1220 const clang::Expr *value_expr = stmt->getRetValue();
11931221 if (value_expr == nullptr) {
11941222 return trans_create_node(c, NodeTypeReturnExpr);
11951223 } else {
......@@ -1201,9 +1229,9 @@ static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStm
12011229 }
12021230}
12031231
1204static AstNode *trans_integer_literal(Context *c, const IntegerLiteral *stmt) {
1232static AstNode *trans_integer_literal(Context *c, const clang::IntegerLiteral *stmt) {
12051233 llvm::APSInt result;
1206 if (!stmt->EvaluateAsInt(result, *c->ctx)) {
1234 if (!stmt->EvaluateAsInt(result, *reinterpret_cast<clang::ASTContext *>(c->ctx))) {
12071235 emit_warning(c, stmt->getLocStart(), "invalid integer literal");
12081236 return nullptr;
12091237 }
......@@ -1211,13 +1239,13 @@ static AstNode *trans_integer_literal(Context *c, const IntegerLiteral *stmt) {
12111239}
12121240
12131241static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, TransScope *scope,
1214 const ConditionalOperator *stmt)
1242 const clang::ConditionalOperator *stmt)
12151243{
12161244 AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr);
12171245
1218 Expr *cond_expr = stmt->getCond();
1219 Expr *true_expr = stmt->getTrueExpr();
1220 Expr *false_expr = stmt->getFalseExpr();
1246 clang::Expr *cond_expr = stmt->getCond();
1247 clang::Expr *true_expr = stmt->getTrueExpr();
1248 clang::Expr *false_expr = stmt->getFalseExpr();
12211249
12221250 node->data.if_bool_expr.condition = trans_expr(c, ResultUsedYes, scope, cond_expr, TransRValue);
12231251 if (node->data.if_bool_expr.condition == nullptr)
......@@ -1234,7 +1262,7 @@ static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, T
12341262 return maybe_suppress_result(c, result_used, node);
12351263}
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) {
12381266 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
12391267 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
12491277 return node;
12501278}
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) {
12531281 assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr);
12541282 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
12551283 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
12651293 return node;
12661294}
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) {
12691297 if (result_used == ResultUsedNo) {
12701298 // common case
12711299 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
......@@ -1316,10 +1344,10 @@ static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransSco
13161344 }
13171345}
13181346
1319static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType result_type,
1320 Expr *lhs_expr, BinOpType bin_op, Expr *rhs_expr)
1347static AstNode *trans_create_shift_op(Context *c, TransScope *scope, clang::QualType result_type,
1348 clang::Expr *lhs_expr, BinOpType bin_op, clang::Expr *rhs_expr)
13211349{
1322 const SourceLocation &rhs_location = rhs_expr->getLocStart();
1350 const clang::SourceLocation &rhs_location = rhs_expr->getLocStart();
13231351 AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location);
13241352 // lhs >> u5(rh)
13251353
......@@ -1333,22 +1361,22 @@ static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType re
13331361 return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs);
13341362}
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) {
13371365 switch (stmt->getOpcode()) {
1338 case BO_PtrMemD:
1339 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemD");
1366 case clang::BO_PtrMemD:
1367 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: clang::BO_PtrMemD");
13401368 return nullptr;
1341 case BO_PtrMemI:
1342 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemI");
1369 case clang::BO_PtrMemI:
1370 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: clang::BO_PtrMemI");
13431371 return nullptr;
1344 case BO_Cmp:
1345 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Cmp");
1372 case clang::BO_Cmp:
1373 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: clang::BO_Cmp");
13461374 return nullptr;
1347 case BO_Mul:
1375 case clang::BO_Mul:
13481376 return trans_create_bin_op(c, scope, stmt->getLHS(),
13491377 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult,
13501378 stmt->getRHS());
1351 case BO_Div:
1379 case clang::BO_Div:
13521380 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
13531381 // unsigned/float division uses the operator
13541382 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
13631391 fn_call->data.fn_call_expr.params.append(rhs);
13641392 return fn_call;
13651393 }
1366 case BO_Rem:
1394 case clang::BO_Rem:
13671395 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
13681396 // unsigned/float division uses the operator
13691397 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
13781406 fn_call->data.fn_call_expr.params.append(rhs);
13791407 return fn_call;
13801408 }
1381 case BO_Add:
1409 case clang::BO_Add:
13821410 return trans_create_bin_op(c, scope, stmt->getLHS(),
13831411 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd,
13841412 stmt->getRHS());
1385 case BO_Sub:
1413 case clang::BO_Sub:
13861414 return trans_create_bin_op(c, scope, stmt->getLHS(),
13871415 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub,
13881416 stmt->getRHS());
1389 case BO_Shl:
1417 case clang::BO_Shl:
13901418 return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS());
1391 case BO_Shr:
1419 case clang::BO_Shr:
13921420 return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS());
1393 case BO_LT:
1421 case clang::BO_LT:
13941422 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS());
1395 case BO_GT:
1423 case clang::BO_GT:
13961424 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS());
1397 case BO_LE:
1425 case clang::BO_LE:
13981426 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS());
1399 case BO_GE:
1427 case clang::BO_GE:
14001428 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS());
1401 case BO_EQ:
1429 case clang::BO_EQ:
14021430 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS());
1403 case BO_NE:
1431 case clang::BO_NE:
14041432 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS());
1405 case BO_And:
1433 case clang::BO_And:
14061434 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS());
1407 case BO_Xor:
1435 case clang::BO_Xor:
14081436 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS());
1409 case BO_Or:
1437 case clang::BO_Or:
14101438 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());
1411 case BO_LAnd:
1439 case clang::BO_LAnd:
14121440 return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());
1413 case BO_LOr:
1441 case clang::BO_LOr:
14141442 return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());
1415 case BO_Assign:
1443 case clang::BO_Assign:
14161444 return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS());
1417 case BO_Comma:
1445 case clang::BO_Comma:
14181446 {
14191447 TransScopeBlock *scope_block = trans_scope_block_create(c, scope);
14201448 Buf *label_name = buf_create_from_str("x");
......@@ -1431,16 +1459,16 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
14311459 scope_block->node->data.block.statements.append(trans_create_node_break(c, label_name, maybe_suppress_result(c, result_used, rhs)));
14321460 return scope_block->node;
14331461 }
1434 case BO_MulAssign:
1435 case BO_DivAssign:
1436 case BO_RemAssign:
1437 case BO_AddAssign:
1438 case BO_SubAssign:
1439 case BO_ShlAssign:
1440 case BO_ShrAssign:
1441 case BO_AndAssign:
1442 case BO_XorAssign:
1443 case BO_OrAssign:
1462 case clang::BO_MulAssign:
1463 case clang::BO_DivAssign:
1464 case clang::BO_RemAssign:
1465 case clang::BO_AddAssign:
1466 case clang::BO_SubAssign:
1467 case clang::BO_ShlAssign:
1468 case clang::BO_ShrAssign:
1469 case clang::BO_AndAssign:
1470 case clang::BO_XorAssign:
1471 case clang::BO_OrAssign:
14441472 zig_unreachable();
14451473 }
14461474
......@@ -1448,9 +1476,9 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
14481476}
14491477
14501478static 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)
14521480{
1453 const SourceLocation &rhs_location = stmt->getRHS()->getLocStart();
1481 const clang::SourceLocation &rhs_location = stmt->getRHS()->getLocStart();
14541482 AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location);
14551483
14561484 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
15301558}
15311559
15321560static 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)
15341562{
15351563 if (result_used == ResultUsedNo) {
15361564 // 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,
15901618
15911619
15921620static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_used, TransScope *scope,
1593 const CompoundAssignOperator *stmt)
1621 const clang::CompoundAssignOperator *stmt)
15941622{
15951623 switch (stmt->getOpcode()) {
1596 case BO_MulAssign:
1624 case clang::BO_MulAssign:
15971625 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
15981626 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap);
15991627 else
16001628 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult);
1601 case BO_DivAssign:
1602 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_DivAssign");
1629 case clang::BO_DivAssign:
1630 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: clang::BO_DivAssign");
16031631 return nullptr;
1604 case BO_RemAssign:
1605 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_RemAssign");
1632 case clang::BO_RemAssign:
1633 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: clang::BO_RemAssign");
16061634 return nullptr;
1607 case BO_Cmp:
1608 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_Cmp");
1635 case clang::BO_Cmp:
1636 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: clang::BO_Cmp");
16091637 return nullptr;
1610 case BO_AddAssign:
1638 case clang::BO_AddAssign:
16111639 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
16121640 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap);
16131641 else
16141642 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlus, BinOpTypeAdd);
1615 case BO_SubAssign:
1643 case clang::BO_SubAssign:
16161644 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
16171645 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap);
16181646 else
16191647 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinus, BinOpTypeSub);
1620 case BO_ShlAssign:
1648 case clang::BO_ShlAssign:
16211649 return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft);
1622 case BO_ShrAssign:
1650 case clang::BO_ShrAssign:
16231651 return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight);
1624 case BO_AndAssign:
1652 case clang::BO_AndAssign:
16251653 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd);
1626 case BO_XorAssign:
1654 case clang::BO_XorAssign:
16271655 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor);
1628 case BO_OrAssign:
1656 case clang::BO_OrAssign:
16291657 return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr);
1630 case BO_PtrMemD:
1631 case BO_PtrMemI:
1632 case BO_Assign:
1633 case BO_Mul:
1634 case BO_Div:
1635 case BO_Rem:
1636 case BO_Add:
1637 case BO_Sub:
1638 case BO_Shl:
1639 case BO_Shr:
1640 case BO_LT:
1641 case BO_GT:
1642 case BO_LE:
1643 case BO_GE:
1644 case BO_EQ:
1645 case BO_NE:
1646 case BO_And:
1647 case BO_Xor:
1648 case BO_Or:
1649 case BO_LAnd:
1650 case BO_LOr:
1651 case BO_Comma:
1658 case clang::BO_PtrMemD:
1659 case clang::BO_PtrMemI:
1660 case clang::BO_Assign:
1661 case clang::BO_Mul:
1662 case clang::BO_Div:
1663 case clang::BO_Rem:
1664 case clang::BO_Add:
1665 case clang::BO_Sub:
1666 case clang::BO_Shl:
1667 case clang::BO_Shr:
1668 case clang::BO_LT:
1669 case clang::BO_GT:
1670 case clang::BO_LE:
1671 case clang::BO_GE:
1672 case clang::BO_EQ:
1673 case clang::BO_NE:
1674 case clang::BO_And:
1675 case clang::BO_Xor:
1676 case clang::BO_Or:
1677 case clang::BO_LAnd:
1678 case clang::BO_LOr:
1679 case clang::BO_Comma:
16521680 zig_unreachable();
16531681 }
16541682
16551683 zig_unreachable();
16561684}
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) {
16591687 switch (stmt->getCastKind()) {
1660 case CK_LValueToRValue:
1688 case clang::CK_LValueToRValue:
16611689 return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
1662 case CK_IntegralCast:
1690 case clang::CK_IntegralCast:
16631691 {
16641692 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
16651693 if (target_node == nullptr)
......@@ -1667,15 +1695,15 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im
16671695 return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(),
16681696 stmt->getSubExpr()->getType(), target_node);
16691697 }
1670 case CK_FunctionToPointerDecay:
1671 case CK_ArrayToPointerDecay:
1698 case clang::CK_FunctionToPointerDecay:
1699 case clang::CK_ArrayToPointerDecay:
16721700 {
16731701 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
16741702 if (target_node == nullptr)
16751703 return nullptr;
16761704 return target_node;
16771705 }
1678 case CK_BitCast:
1706 case clang::CK_BitCast:
16791707 {
16801708 AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
16811709 if (target_node == nullptr)
......@@ -1692,170 +1720,170 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im
16921720 node->data.fn_call_expr.params.append(target_node);
16931721 return node;
16941722 }
1695 case CK_NullToPointer:
1696 return trans_create_node(c, NodeTypeNullLiteral);
1697 case CK_Dependent:
1698 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent");
1723 case clang::CK_NullToPointer:
1724 return trans_create_node_unsigned(c, 0);
1725 case clang::CK_Dependent:
1726 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_Dependent");
16991727 return nullptr;
1700 case CK_LValueBitCast:
1701 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_LValueBitCast");
1728 case clang::CK_LValueBitCast:
1729 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_LValueBitCast");
17021730 return nullptr;
1703 case CK_NoOp:
1704 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NoOp");
1731 case clang::CK_NoOp:
1732 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_NoOp");
17051733 return nullptr;
1706 case CK_BaseToDerived:
1707 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BaseToDerived");
1734 case clang::CK_BaseToDerived:
1735 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BaseToDerived");
17081736 return nullptr;
1709 case CK_DerivedToBase:
1710 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_DerivedToBase");
1737 case clang::CK_DerivedToBase:
1738 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_DerivedToBase");
17111739 return nullptr;
1712 case CK_UncheckedDerivedToBase:
1713 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_UncheckedDerivedToBase");
1740 case clang::CK_UncheckedDerivedToBase:
1741 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_UncheckedDerivedToBase");
17141742 return nullptr;
1715 case CK_Dynamic:
1716 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dynamic");
1743 case clang::CK_Dynamic:
1744 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_Dynamic");
17171745 return nullptr;
1718 case CK_ToUnion:
1719 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ToUnion");
1746 case clang::CK_ToUnion:
1747 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ToUnion");
17201748 return nullptr;
1721 case CK_NullToMemberPointer:
1722 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NullToMemberPointer");
1749 case clang::CK_NullToMemberPointer:
1750 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_NullToMemberPointer");
17231751 return nullptr;
1724 case CK_BaseToDerivedMemberPointer:
1725 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BaseToDerivedMemberPointer");
1752 case clang::CK_BaseToDerivedMemberPointer:
1753 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BaseToDerivedMemberPointer");
17261754 return nullptr;
1727 case CK_DerivedToBaseMemberPointer:
1728 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_DerivedToBaseMemberPointer");
1755 case clang::CK_DerivedToBaseMemberPointer:
1756 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_DerivedToBaseMemberPointer");
17291757 return nullptr;
1730 case CK_MemberPointerToBoolean:
1731 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_MemberPointerToBoolean");
1758 case clang::CK_MemberPointerToBoolean:
1759 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_MemberPointerToBoolean");
17321760 return nullptr;
1733 case CK_ReinterpretMemberPointer:
1734 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ReinterpretMemberPointer");
1761 case clang::CK_ReinterpretMemberPointer:
1762 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ReinterpretMemberPointer");
17351763 return nullptr;
1736 case CK_UserDefinedConversion:
1737 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_UserDefinedConversion");
1764 case clang::CK_UserDefinedConversion:
1765 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_UserDefinedConversion");
17381766 return nullptr;
1739 case CK_ConstructorConversion:
1740 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ConstructorConversion");
1767 case clang::CK_ConstructorConversion:
1768 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ConstructorConversion");
17411769 return nullptr;
1742 case CK_IntegralToPointer:
1743 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralToPointer");
1770 case clang::CK_IntegralToPointer:
1771 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralToPointer");
17441772 return nullptr;
1745 case CK_PointerToIntegral:
1746 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_PointerToIntegral");
1773 case clang::CK_PointerToIntegral:
1774 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_PointerToIntegral");
17471775 return nullptr;
1748 case CK_PointerToBoolean:
1749 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_PointerToBoolean");
1776 case clang::CK_PointerToBoolean:
1777 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_PointerToBoolean");
17501778 return nullptr;
1751 case CK_ToVoid:
1752 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ToVoid");
1779 case clang::CK_ToVoid:
1780 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ToVoid");
17531781 return nullptr;
1754 case CK_VectorSplat:
1755 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_VectorSplat");
1782 case clang::CK_VectorSplat:
1783 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_VectorSplat");
17561784 return nullptr;
1757 case CK_IntegralToBoolean:
1758 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralToBoolean");
1785 case clang::CK_IntegralToBoolean:
1786 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralToBoolean");
17591787 return nullptr;
1760 case CK_IntegralToFloating:
1761 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralToFloating");
1788 case clang::CK_IntegralToFloating:
1789 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralToFloating");
17621790 return nullptr;
1763 case CK_FloatingToIntegral:
1764 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingToIntegral");
1791 case clang::CK_FloatingToIntegral:
1792 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingToIntegral");
17651793 return nullptr;
1766 case CK_FloatingToBoolean:
1767 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingToBoolean");
1794 case clang::CK_FloatingToBoolean:
1795 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingToBoolean");
17681796 return nullptr;
1769 case CK_BooleanToSignedIntegral:
1770 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BooleanToSignedIntegral");
1797 case clang::CK_BooleanToSignedIntegral:
1798 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BooleanToSignedIntegral");
17711799 return nullptr;
1772 case CK_FloatingCast:
1773 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingCast");
1800 case clang::CK_FloatingCast:
1801 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingCast");
17741802 return nullptr;
1775 case CK_CPointerToObjCPointerCast:
1776 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_CPointerToObjCPointerCast");
1803 case clang::CK_CPointerToObjCPointerCast:
1804 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_CPointerToObjCPointerCast");
17771805 return nullptr;
1778 case CK_BlockPointerToObjCPointerCast:
1779 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BlockPointerToObjCPointerCast");
1806 case clang::CK_BlockPointerToObjCPointerCast:
1807 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BlockPointerToObjCPointerCast");
17801808 return nullptr;
1781 case CK_AnyPointerToBlockPointerCast:
1782 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_AnyPointerToBlockPointerCast");
1809 case clang::CK_AnyPointerToBlockPointerCast:
1810 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_AnyPointerToBlockPointerCast");
17831811 return nullptr;
1784 case CK_ObjCObjectLValueCast:
1785 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ObjCObjectLValueCast");
1812 case clang::CK_ObjCObjectLValueCast:
1813 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ObjCObjectLValueCast");
17861814 return nullptr;
1787 case CK_FloatingRealToComplex:
1788 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingRealToComplex");
1815 case clang::CK_FloatingRealToComplex:
1816 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingRealToComplex");
17891817 return nullptr;
1790 case CK_FloatingComplexToReal:
1791 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexToReal");
1818 case clang::CK_FloatingComplexToReal:
1819 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingComplexToReal");
17921820 return nullptr;
1793 case CK_FloatingComplexToBoolean:
1794 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexToBoolean");
1821 case clang::CK_FloatingComplexToBoolean:
1822 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingComplexToBoolean");
17951823 return nullptr;
1796 case CK_FloatingComplexCast:
1797 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexCast");
1824 case clang::CK_FloatingComplexCast:
1825 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingComplexCast");
17981826 return nullptr;
1799 case CK_FloatingComplexToIntegralComplex:
1800 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexToIntegralComplex");
1827 case clang::CK_FloatingComplexToIntegralComplex:
1828 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_FloatingComplexToIntegralComplex");
18011829 return nullptr;
1802 case CK_IntegralRealToComplex:
1803 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralRealToComplex");
1830 case clang::CK_IntegralRealToComplex:
1831 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralRealToComplex");
18041832 return nullptr;
1805 case CK_IntegralComplexToReal:
1806 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexToReal");
1833 case clang::CK_IntegralComplexToReal:
1834 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralComplexToReal");
18071835 return nullptr;
1808 case CK_IntegralComplexToBoolean:
1809 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexToBoolean");
1836 case clang::CK_IntegralComplexToBoolean:
1837 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralComplexToBoolean");
18101838 return nullptr;
1811 case CK_IntegralComplexCast:
1812 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexCast");
1839 case clang::CK_IntegralComplexCast:
1840 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralComplexCast");
18131841 return nullptr;
1814 case CK_IntegralComplexToFloatingComplex:
1815 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexToFloatingComplex");
1842 case clang::CK_IntegralComplexToFloatingComplex:
1843 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntegralComplexToFloatingComplex");
18161844 return nullptr;
1817 case CK_ARCProduceObject:
1818 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCProduceObject");
1845 case clang::CK_ARCProduceObject:
1846 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ARCProduceObject");
18191847 return nullptr;
1820 case CK_ARCConsumeObject:
1821 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCConsumeObject");
1848 case clang::CK_ARCConsumeObject:
1849 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ARCConsumeObject");
18221850 return nullptr;
1823 case CK_ARCReclaimReturnedObject:
1824 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCReclaimReturnedObject");
1851 case clang::CK_ARCReclaimReturnedObject:
1852 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ARCReclaimReturnedObject");
18251853 return nullptr;
1826 case CK_ARCExtendBlockObject:
1827 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCExtendBlockObject");
1854 case clang::CK_ARCExtendBlockObject:
1855 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ARCExtendBlockObject");
18281856 return nullptr;
1829 case CK_AtomicToNonAtomic:
1830 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_AtomicToNonAtomic");
1857 case clang::CK_AtomicToNonAtomic:
1858 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_AtomicToNonAtomic");
18311859 return nullptr;
1832 case CK_NonAtomicToAtomic:
1833 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NonAtomicToAtomic");
1860 case clang::CK_NonAtomicToAtomic:
1861 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_NonAtomicToAtomic");
18341862 return nullptr;
1835 case CK_CopyAndAutoreleaseBlockObject:
1836 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_CopyAndAutoreleaseBlockObject");
1863 case clang::CK_CopyAndAutoreleaseBlockObject:
1864 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_CopyAndAutoreleaseBlockObject");
18371865 return nullptr;
1838 case CK_BuiltinFnToFnPtr:
1839 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BuiltinFnToFnPtr");
1866 case clang::CK_BuiltinFnToFnPtr:
1867 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_BuiltinFnToFnPtr");
18401868 return nullptr;
1841 case CK_ZeroToOCLEvent:
1842 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ZeroToOCLEvent");
1869 case clang::CK_ZeroToOCLEvent:
1870 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ZeroToOCLEvent");
18431871 return nullptr;
1844 case CK_ZeroToOCLQueue:
1845 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ZeroToOCLQueue");
1872 case clang::CK_ZeroToOCLQueue:
1873 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_ZeroToOCLQueue");
18461874 return nullptr;
1847 case CK_AddressSpaceConversion:
1848 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_AddressSpaceConversion");
1875 case clang::CK_AddressSpaceConversion:
1876 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_AddressSpaceConversion");
18491877 return nullptr;
1850 case CK_IntToOCLSampler:
1851 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntToOCLSampler");
1878 case clang::CK_IntToOCLSampler:
1879 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast clang::CK_IntToOCLSampler");
18521880 return nullptr;
18531881 }
18541882 zig_unreachable();
18551883}
18561884
1857static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRefExpr *stmt, TransLRValue lrval) {
1858 const ValueDecl *value_decl = stmt->getDecl();
1885static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const clang::DeclRefExpr *stmt, TransLRValue lrval) {
1886 const clang::ValueDecl *value_decl = stmt->getDecl();
18591887 Buf *c_symbol_name = buf_create_from_str(decl_name(value_decl));
18601888 Buf *zig_symbol_name = trans_lookup_zig_symbol(c, scope, c_symbol_name);
18611889 if (lrval == TransLValue) {
......@@ -1865,9 +1893,9 @@ static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRef
18651893}
18661894
18671895static 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)
18691897{
1870 Expr *op_expr = stmt->getSubExpr();
1898 clang::Expr *op_expr = stmt->getSubExpr();
18711899
18721900 if (result_used == ResultUsedNo) {
18731901 // common case
......@@ -1921,9 +1949,9 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr
19211949}
19221950
19231951static 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)
19251953{
1926 Expr *op_expr = stmt->getSubExpr();
1954 clang::Expr *op_expr = stmt->getSubExpr();
19271955
19281956 if (result_used == ResultUsedNo) {
19291957 // common case
......@@ -1970,36 +1998,36 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra
19701998 return child_scope->node;
19711999}
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) {
19742002 switch (stmt->getOpcode()) {
1975 case UO_PostInc:
2003 case clang::UO_PostInc:
19762004 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
19772005 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);
19782006 else
19792007 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);
1980 case UO_PostDec:
2008 case clang::UO_PostDec:
19812009 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
19822010 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);
19832011 else
19842012 return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);
1985 case UO_PreInc:
2013 case clang::UO_PreInc:
19862014 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
19872015 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);
19882016 else
19892017 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);
1990 case UO_PreDec:
2018 case clang::UO_PreDec:
19912019 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
19922020 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);
19932021 else
19942022 return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);
1995 case UO_AddrOf:
2023 case clang::UO_AddrOf:
19962024 {
19972025 AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue);
19982026 if (value_node == nullptr)
19992027 return value_node;
20002028 return trans_create_node_addr_of(c, value_node);
20012029 }
2002 case UO_Deref:
2030 case clang::UO_Deref:
20032031 {
20042032 AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue);
20052033 if (value_node == nullptr)
......@@ -2010,12 +2038,12 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
20102038 AstNode *unwrapped = trans_create_node_unwrap_null(c, value_node);
20112039 return trans_create_node_ptr_deref(c, unwrapped);
20122040 }
2013 case UO_Plus:
2014 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Plus");
2041 case clang::UO_Plus:
2042 emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Plus");
20152043 return nullptr;
2016 case UO_Minus:
2044 case clang::UO_Minus:
20172045 {
2018 Expr *op_expr = stmt->getSubExpr();
2046 clang::Expr *op_expr = stmt->getSubExpr();
20192047 if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) {
20202048 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
20212049 node->data.prefix_op_expr.prefix_op = PrefixOpNegation;
......@@ -2041,41 +2069,41 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
20412069 return nullptr;
20422070 }
20432071 }
2044 case UO_Not:
2072 case clang::UO_Not:
20452073 {
2046 Expr *op_expr = stmt->getSubExpr();
2074 clang::Expr *op_expr = stmt->getSubExpr();
20472075 AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
20482076 if (sub_node == nullptr)
20492077 return nullptr;
20502078
20512079 return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node);
20522080 }
2053 case UO_LNot:
2081 case clang::UO_LNot:
20542082 {
2055 Expr *op_expr = stmt->getSubExpr();
2083 clang::Expr *op_expr = stmt->getSubExpr();
20562084 AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
20572085 if (sub_node == nullptr)
20582086 return nullptr;
20592087
20602088 return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node);
20612089 }
2062 case UO_Real:
2063 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Real");
2090 case clang::UO_Real:
2091 emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Real");
20642092 return nullptr;
2065 case UO_Imag:
2066 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Imag");
2093 case clang::UO_Imag:
2094 emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Imag");
20672095 return nullptr;
2068 case UO_Extension:
2069 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Extension");
2096 case clang::UO_Extension:
2097 emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Extension");
20702098 return nullptr;
2071 case UO_Coawait:
2072 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Coawait");
2099 case clang::UO_Coawait:
2100 emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Coawait");
20732101 return nullptr;
20742102 }
20752103 zig_unreachable();
20762104}
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,
20792107 AstNode **out_node, TransScope **out_scope)
20802108{
20812109 // declarations are added via the scope
......@@ -2085,11 +2113,11 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt
20852113 assert(scope_block != nullptr);
20862114
20872115 for (auto iter = stmt->decl_begin(); iter != stmt->decl_end(); iter++) {
2088 Decl *decl = *iter;
2116 clang::Decl *decl = *iter;
20892117 switch (decl->getKind()) {
2090 case Decl::Var: {
2091 VarDecl *var_decl = (VarDecl *)decl;
2092 QualType qual_type = var_decl->getTypeSourceInfo()->getType();
2118 case clang::Decl::Var: {
2119 clang::VarDecl *var_decl = (clang::VarDecl *)decl;
2120 clang::QualType qual_type = var_decl->getTypeSourceInfo()->getType();
20932121 AstNode *init_node = nullptr;
20942122 if (var_decl->hasInit()) {
20952123 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
21142142 scope_block->node->data.block.statements.append(node);
21152143 continue;
21162144 }
2117 case Decl::AccessSpec:
2145 case clang::Decl::AccessSpec:
21182146 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind AccessSpec");
21192147 return ErrorUnexpected;
2120 case Decl::Block:
2148 case clang::Decl::Block:
21212149 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Block");
21222150 return ErrorUnexpected;
2123 case Decl::Captured:
2151 case clang::Decl::Captured:
21242152 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Captured");
21252153 return ErrorUnexpected;
2126 case Decl::ClassScopeFunctionSpecialization:
2154 case clang::Decl::ClassScopeFunctionSpecialization:
21272155 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassScopeFunctionSpecialization");
21282156 return ErrorUnexpected;
2129 case Decl::Empty:
2157 case clang::Decl::Empty:
21302158 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Empty");
21312159 return ErrorUnexpected;
2132 case Decl::Export:
2160 case clang::Decl::Export:
21332161 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Export");
21342162 return ErrorUnexpected;
2135 case Decl::ExternCContext:
2163 case clang::Decl::ExternCContext:
21362164 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ExternCContext");
21372165 return ErrorUnexpected;
2138 case Decl::FileScopeAsm:
2166 case clang::Decl::FileScopeAsm:
21392167 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FileScopeAsm");
21402168 return ErrorUnexpected;
2141 case Decl::Friend:
2169 case clang::Decl::Friend:
21422170 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Friend");
21432171 return ErrorUnexpected;
2144 case Decl::FriendTemplate:
2172 case clang::Decl::FriendTemplate:
21452173 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FriendTemplate");
21462174 return ErrorUnexpected;
2147 case Decl::Import:
2175 case clang::Decl::Import:
21482176 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Import");
21492177 return ErrorUnexpected;
2150 case Decl::LinkageSpec:
2178 case clang::Decl::LinkageSpec:
21512179 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind LinkageSpec");
21522180 return ErrorUnexpected;
2153 case Decl::Label:
2181 case clang::Decl::Label:
21542182 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Label");
21552183 return ErrorUnexpected;
2156 case Decl::Namespace:
2184 case clang::Decl::Namespace:
21572185 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Namespace");
21582186 return ErrorUnexpected;
2159 case Decl::NamespaceAlias:
2187 case clang::Decl::NamespaceAlias:
21602188 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind NamespaceAlias");
21612189 return ErrorUnexpected;
2162 case Decl::ObjCCompatibleAlias:
2190 case clang::Decl::ObjCCompatibleAlias:
21632191 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCompatibleAlias");
21642192 return ErrorUnexpected;
2165 case Decl::ObjCCategory:
2193 case clang::Decl::ObjCCategory:
21662194 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCategory");
21672195 return ErrorUnexpected;
2168 case Decl::ObjCCategoryImpl:
2196 case clang::Decl::ObjCCategoryImpl:
21692197 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCategoryImpl");
21702198 return ErrorUnexpected;
2171 case Decl::ObjCImplementation:
2199 case clang::Decl::ObjCImplementation:
21722200 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCImplementation");
21732201 return ErrorUnexpected;
2174 case Decl::ObjCInterface:
2202 case clang::Decl::ObjCInterface:
21752203 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCInterface");
21762204 return ErrorUnexpected;
2177 case Decl::ObjCProtocol:
2205 case clang::Decl::ObjCProtocol:
21782206 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCProtocol");
21792207 return ErrorUnexpected;
2180 case Decl::ObjCMethod:
2208 case clang::Decl::ObjCMethod:
21812209 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCMethod");
21822210 return ErrorUnexpected;
2183 case Decl::ObjCProperty:
2211 case clang::Decl::ObjCProperty:
21842212 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCProperty");
21852213 return ErrorUnexpected;
2186 case Decl::BuiltinTemplate:
2214 case clang::Decl::BuiltinTemplate:
21872215 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind BuiltinTemplate");
21882216 return ErrorUnexpected;
2189 case Decl::ClassTemplate:
2217 case clang::Decl::ClassTemplate:
21902218 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplate");
21912219 return ErrorUnexpected;
2192 case Decl::FunctionTemplate:
2220 case clang::Decl::FunctionTemplate:
21932221 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FunctionTemplate");
21942222 return ErrorUnexpected;
2195 case Decl::TypeAliasTemplate:
2223 case clang::Decl::TypeAliasTemplate:
21962224 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TypeAliasTemplate");
21972225 return ErrorUnexpected;
2198 case Decl::VarTemplate:
2226 case clang::Decl::VarTemplate:
21992227 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplate");
22002228 return ErrorUnexpected;
2201 case Decl::TemplateTemplateParm:
2229 case clang::Decl::TemplateTemplateParm:
22022230 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TemplateTemplateParm");
22032231 return ErrorUnexpected;
2204 case Decl::Enum:
2232 case clang::Decl::Enum:
22052233 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Enum");
22062234 return ErrorUnexpected;
2207 case Decl::Record:
2235 case clang::Decl::Record:
22082236 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Record");
22092237 return ErrorUnexpected;
2210 case Decl::CXXRecord:
2238 case clang::Decl::CXXRecord:
22112239 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXRecord");
22122240 return ErrorUnexpected;
2213 case Decl::ClassTemplateSpecialization:
2241 case clang::Decl::ClassTemplateSpecialization:
22142242 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplateSpecialization");
22152243 return ErrorUnexpected;
2216 case Decl::ClassTemplatePartialSpecialization:
2244 case clang::Decl::ClassTemplatePartialSpecialization:
22172245 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplatePartialSpecialization");
22182246 return ErrorUnexpected;
2219 case Decl::TemplateTypeParm:
2247 case clang::Decl::TemplateTypeParm:
22202248 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TemplateTypeParm");
22212249 return ErrorUnexpected;
2222 case Decl::ObjCTypeParam:
2250 case clang::Decl::ObjCTypeParam:
22232251 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCTypeParam");
22242252 return ErrorUnexpected;
2225 case Decl::TypeAlias:
2253 case clang::Decl::TypeAlias:
22262254 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TypeAlias");
22272255 return ErrorUnexpected;
2228 case Decl::Typedef:
2256 case clang::Decl::Typedef:
22292257 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Typedef");
22302258 return ErrorUnexpected;
2231 case Decl::UnresolvedUsingTypename:
2259 case clang::Decl::UnresolvedUsingTypename:
22322260 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UnresolvedUsingTypename");
22332261 return ErrorUnexpected;
2234 case Decl::Using:
2262 case clang::Decl::Using:
22352263 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Using");
22362264 return ErrorUnexpected;
2237 case Decl::UsingDirective:
2265 case clang::Decl::UsingDirective:
22382266 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingDirective");
22392267 return ErrorUnexpected;
2240 case Decl::UsingPack:
2268 case clang::Decl::UsingPack:
22412269 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingPack");
22422270 return ErrorUnexpected;
2243 case Decl::UsingShadow:
2271 case clang::Decl::UsingShadow:
22442272 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingShadow");
22452273 return ErrorUnexpected;
2246 case Decl::ConstructorUsingShadow:
2274 case clang::Decl::ConstructorUsingShadow:
22472275 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ConstructorUsingShadow");
22482276 return ErrorUnexpected;
2249 case Decl::Binding:
2277 case clang::Decl::Binding:
22502278 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Binding");
22512279 return ErrorUnexpected;
2252 case Decl::Field:
2280 case clang::Decl::Field:
22532281 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Field");
22542282 return ErrorUnexpected;
2255 case Decl::ObjCAtDefsField:
2283 case clang::Decl::ObjCAtDefsField:
22562284 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCAtDefsField");
22572285 return ErrorUnexpected;
2258 case Decl::ObjCIvar:
2286 case clang::Decl::ObjCIvar:
22592287 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCIvar");
22602288 return ErrorUnexpected;
2261 case Decl::Function:
2289 case clang::Decl::Function:
22622290 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Function");
22632291 return ErrorUnexpected;
2264 case Decl::CXXDeductionGuide:
2292 case clang::Decl::CXXDeductionGuide:
22652293 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXDeductionGuide");
22662294 return ErrorUnexpected;
2267 case Decl::CXXMethod:
2295 case clang::Decl::CXXMethod:
22682296 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXMethod");
22692297 return ErrorUnexpected;
2270 case Decl::CXXConstructor:
2298 case clang::Decl::CXXConstructor:
22712299 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXConstructor");
22722300 return ErrorUnexpected;
2273 case Decl::CXXConversion:
2301 case clang::Decl::CXXConversion:
22742302 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXConversion");
22752303 return ErrorUnexpected;
2276 case Decl::CXXDestructor:
2304 case clang::Decl::CXXDestructor:
22772305 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXDestructor");
22782306 return ErrorUnexpected;
2279 case Decl::MSProperty:
2307 case clang::Decl::MSProperty:
22802308 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind MSProperty");
22812309 return ErrorUnexpected;
2282 case Decl::NonTypeTemplateParm:
2310 case clang::Decl::NonTypeTemplateParm:
22832311 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind NonTypeTemplateParm");
22842312 return ErrorUnexpected;
2285 case Decl::Decomposition:
2313 case clang::Decl::Decomposition:
22862314 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Decomposition");
22872315 return ErrorUnexpected;
2288 case Decl::ImplicitParam:
2316 case clang::Decl::ImplicitParam:
22892317 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ImplicitParam");
22902318 return ErrorUnexpected;
2291 case Decl::OMPCapturedExpr:
2319 case clang::Decl::OMPCapturedExpr:
22922320 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPCapturedExpr");
22932321 return ErrorUnexpected;
2294 case Decl::ParmVar:
2322 case clang::Decl::ParmVar:
22952323 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ParmVar");
22962324 return ErrorUnexpected;
2297 case Decl::VarTemplateSpecialization:
2325 case clang::Decl::VarTemplateSpecialization:
22982326 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplateSpecialization");
22992327 return ErrorUnexpected;
2300 case Decl::VarTemplatePartialSpecialization:
2328 case clang::Decl::VarTemplatePartialSpecialization:
23012329 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplatePartialSpecialization");
23022330 return ErrorUnexpected;
2303 case Decl::EnumConstant:
2331 case clang::Decl::EnumConstant:
23042332 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind EnumConstant");
23052333 return ErrorUnexpected;
2306 case Decl::IndirectField:
2334 case clang::Decl::IndirectField:
23072335 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind IndirectField");
23082336 return ErrorUnexpected;
2309 case Decl::OMPDeclareReduction:
2337 case clang::Decl::OMPDeclareReduction:
23102338 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPDeclareReduction");
23112339 return ErrorUnexpected;
2312 case Decl::UnresolvedUsingValue:
2340 case clang::Decl::UnresolvedUsingValue:
23132341 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UnresolvedUsingValue");
23142342 return ErrorUnexpected;
2315 case Decl::OMPThreadPrivate:
2343 case clang::Decl::OMPThreadPrivate:
23162344 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPThreadPrivate");
23172345 return ErrorUnexpected;
2318 case Decl::ObjCPropertyImpl:
2346 case clang::Decl::ObjCPropertyImpl:
23192347 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCPropertyImpl");
23202348 return ErrorUnexpected;
2321 case Decl::PragmaComment:
2349 case clang::Decl::PragmaComment:
23222350 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind PragmaComment");
23232351 return ErrorUnexpected;
2324 case Decl::PragmaDetectMismatch:
2352 case clang::Decl::PragmaDetectMismatch:
23252353 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind PragmaDetectMismatch");
23262354 return ErrorUnexpected;
2327 case Decl::StaticAssert:
2355 case clang::Decl::StaticAssert:
23282356 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind StaticAssert");
23292357 return ErrorUnexpected;
2330 case Decl::TranslationUnit:
2358 case clang::Decl::TranslationUnit:
23312359 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TranslationUnit");
23322360 return ErrorUnexpected;
23332361 }
......@@ -2354,7 +2382,7 @@ static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type)
23542382 return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast);
23552383}
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) {
23582386 AstNode *res = trans_expr(c, result_used, scope, expr, lrval);
23592387 if (res == nullptr)
23602388 return nullptr;
......@@ -2391,131 +2419,133 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
23912419 }
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();
23952423 auto classs = ty->getTypeClass();
23962424 switch (classs) {
2397 case Type::Builtin:
2425 case clang::Type::Builtin:
23982426 {
2399 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
2427 const clang::BuiltinType *builtin_ty = static_cast<const clang::BuiltinType*>(ty);
24002428 switch (builtin_ty->getKind()) {
2401 case BuiltinType::Bool:
2402 case BuiltinType::Char_U:
2403 case BuiltinType::UChar:
2404 case BuiltinType::Char_S:
2405 case BuiltinType::SChar:
2406 case BuiltinType::UShort:
2407 case BuiltinType::UInt:
2408 case BuiltinType::ULong:
2409 case BuiltinType::ULongLong:
2410 case BuiltinType::Short:
2411 case BuiltinType::Int:
2412 case BuiltinType::Long:
2413 case BuiltinType::LongLong:
2414 case BuiltinType::UInt128:
2415 case BuiltinType::Int128:
2416 case BuiltinType::Float:
2417 case BuiltinType::Double:
2418 case BuiltinType::Float128:
2419 case BuiltinType::LongDouble:
2420 case BuiltinType::WChar_U:
2421 case BuiltinType::Char8:
2422 case BuiltinType::Char16:
2423 case BuiltinType::Char32:
2424 case BuiltinType::WChar_S:
2425 case BuiltinType::Float16:
2429 case clang::BuiltinType::Bool:
2430 case clang::BuiltinType::Char_U:
2431 case clang::BuiltinType::UChar:
2432 case clang::BuiltinType::Char_S:
2433 case clang::BuiltinType::SChar:
2434 case clang::BuiltinType::UShort:
2435 case clang::BuiltinType::UInt:
2436 case clang::BuiltinType::ULong:
2437 case clang::BuiltinType::ULongLong:
2438 case clang::BuiltinType::Short:
2439 case clang::BuiltinType::Int:
2440 case clang::BuiltinType::Long:
2441 case clang::BuiltinType::LongLong:
2442 case clang::BuiltinType::UInt128:
2443 case clang::BuiltinType::Int128:
2444 case clang::BuiltinType::Float:
2445 case clang::BuiltinType::Double:
2446 case clang::BuiltinType::Float128:
2447 case clang::BuiltinType::LongDouble:
2448 case clang::BuiltinType::WChar_U:
2449 case clang::BuiltinType::Char8:
2450 case clang::BuiltinType::Char16:
2451 case clang::BuiltinType::Char32:
2452 case clang::BuiltinType::WChar_S:
2453 case clang::BuiltinType::Float16:
24262454 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
2427 case BuiltinType::NullPtr:
2428 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));
2429
2430 case BuiltinType::Void:
2431 case BuiltinType::Half:
2432 case BuiltinType::ObjCId:
2433 case BuiltinType::ObjCClass:
2434 case BuiltinType::ObjCSel:
2435 case BuiltinType::OMPArraySection:
2436 case BuiltinType::Dependent:
2437 case BuiltinType::Overload:
2438 case BuiltinType::BoundMember:
2439 case BuiltinType::PseudoObject:
2440 case BuiltinType::UnknownAny:
2441 case BuiltinType::BuiltinFn:
2442 case BuiltinType::ARCUnbridgedCast:
2443 case BuiltinType::OCLImage1dRO:
2444 case BuiltinType::OCLImage1dArrayRO:
2445 case BuiltinType::OCLImage1dBufferRO:
2446 case BuiltinType::OCLImage2dRO:
2447 case BuiltinType::OCLImage2dArrayRO:
2448 case BuiltinType::OCLImage2dDepthRO:
2449 case BuiltinType::OCLImage2dArrayDepthRO:
2450 case BuiltinType::OCLImage2dMSAARO:
2451 case BuiltinType::OCLImage2dArrayMSAARO:
2452 case BuiltinType::OCLImage2dMSAADepthRO:
2453 case BuiltinType::OCLImage2dArrayMSAADepthRO:
2454 case BuiltinType::OCLImage3dRO:
2455 case BuiltinType::OCLImage1dWO:
2456 case BuiltinType::OCLImage1dArrayWO:
2457 case BuiltinType::OCLImage1dBufferWO:
2458 case BuiltinType::OCLImage2dWO:
2459 case BuiltinType::OCLImage2dArrayWO:
2460 case BuiltinType::OCLImage2dDepthWO:
2461 case BuiltinType::OCLImage2dArrayDepthWO:
2462 case BuiltinType::OCLImage2dMSAAWO:
2463 case BuiltinType::OCLImage2dArrayMSAAWO:
2464 case BuiltinType::OCLImage2dMSAADepthWO:
2465 case BuiltinType::OCLImage2dArrayMSAADepthWO:
2466 case BuiltinType::OCLImage3dWO:
2467 case BuiltinType::OCLImage1dRW:
2468 case BuiltinType::OCLImage1dArrayRW:
2469 case BuiltinType::OCLImage1dBufferRW:
2470 case BuiltinType::OCLImage2dRW:
2471 case BuiltinType::OCLImage2dArrayRW:
2472 case BuiltinType::OCLImage2dDepthRW:
2473 case BuiltinType::OCLImage2dArrayDepthRW:
2474 case BuiltinType::OCLImage2dMSAARW:
2475 case BuiltinType::OCLImage2dArrayMSAARW:
2476 case BuiltinType::OCLImage2dMSAADepthRW:
2477 case BuiltinType::OCLImage2dArrayMSAADepthRW:
2478 case BuiltinType::OCLImage3dRW:
2479 case BuiltinType::OCLSampler:
2480 case BuiltinType::OCLEvent:
2481 case BuiltinType::OCLClkEvent:
2482 case BuiltinType::OCLQueue:
2483 case BuiltinType::OCLReserveID:
2484 case BuiltinType::ShortAccum:
2485 case BuiltinType::Accum:
2486 case BuiltinType::LongAccum:
2487 case BuiltinType::UShortAccum:
2488 case BuiltinType::UAccum:
2489 case BuiltinType::ULongAccum:
2490 case BuiltinType::ShortFract:
2491 case BuiltinType::Fract:
2492 case BuiltinType::LongFract:
2493 case BuiltinType::UShortFract:
2494 case BuiltinType::UFract:
2495 case BuiltinType::ULongFract:
2496 case BuiltinType::SatShortAccum:
2497 case BuiltinType::SatAccum:
2498 case BuiltinType::SatLongAccum:
2499 case BuiltinType::SatUShortAccum:
2500 case BuiltinType::SatUAccum:
2501 case BuiltinType::SatULongAccum:
2502 case BuiltinType::SatShortFract:
2503 case BuiltinType::SatFract:
2504 case BuiltinType::SatLongFract:
2505 case BuiltinType::SatUShortFract:
2506 case BuiltinType::SatUFract:
2507 case BuiltinType::SatULongFract:
2455 case clang::BuiltinType::NullPtr:
2456 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,
2457 trans_create_node_unsigned(c, 0));
2458
2459 case clang::BuiltinType::Void:
2460 case clang::BuiltinType::Half:
2461 case clang::BuiltinType::ObjCId:
2462 case clang::BuiltinType::ObjCClass:
2463 case clang::BuiltinType::ObjCSel:
2464 case clang::BuiltinType::OMPArraySection:
2465 case clang::BuiltinType::Dependent:
2466 case clang::BuiltinType::Overload:
2467 case clang::BuiltinType::BoundMember:
2468 case clang::BuiltinType::PseudoObject:
2469 case clang::BuiltinType::UnknownAny:
2470 case clang::BuiltinType::BuiltinFn:
2471 case clang::BuiltinType::ARCUnbridgedCast:
2472 case clang::BuiltinType::OCLImage1dRO:
2473 case clang::BuiltinType::OCLImage1dArrayRO:
2474 case clang::BuiltinType::OCLImage1dBufferRO:
2475 case clang::BuiltinType::OCLImage2dRO:
2476 case clang::BuiltinType::OCLImage2dArrayRO:
2477 case clang::BuiltinType::OCLImage2dDepthRO:
2478 case clang::BuiltinType::OCLImage2dArrayDepthRO:
2479 case clang::BuiltinType::OCLImage2dMSAARO:
2480 case clang::BuiltinType::OCLImage2dArrayMSAARO:
2481 case clang::BuiltinType::OCLImage2dMSAADepthRO:
2482 case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:
2483 case clang::BuiltinType::OCLImage3dRO:
2484 case clang::BuiltinType::OCLImage1dWO:
2485 case clang::BuiltinType::OCLImage1dArrayWO:
2486 case clang::BuiltinType::OCLImage1dBufferWO:
2487 case clang::BuiltinType::OCLImage2dWO:
2488 case clang::BuiltinType::OCLImage2dArrayWO:
2489 case clang::BuiltinType::OCLImage2dDepthWO:
2490 case clang::BuiltinType::OCLImage2dArrayDepthWO:
2491 case clang::BuiltinType::OCLImage2dMSAAWO:
2492 case clang::BuiltinType::OCLImage2dArrayMSAAWO:
2493 case clang::BuiltinType::OCLImage2dMSAADepthWO:
2494 case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:
2495 case clang::BuiltinType::OCLImage3dWO:
2496 case clang::BuiltinType::OCLImage1dRW:
2497 case clang::BuiltinType::OCLImage1dArrayRW:
2498 case clang::BuiltinType::OCLImage1dBufferRW:
2499 case clang::BuiltinType::OCLImage2dRW:
2500 case clang::BuiltinType::OCLImage2dArrayRW:
2501 case clang::BuiltinType::OCLImage2dDepthRW:
2502 case clang::BuiltinType::OCLImage2dArrayDepthRW:
2503 case clang::BuiltinType::OCLImage2dMSAARW:
2504 case clang::BuiltinType::OCLImage2dArrayMSAARW:
2505 case clang::BuiltinType::OCLImage2dMSAADepthRW:
2506 case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:
2507 case clang::BuiltinType::OCLImage3dRW:
2508 case clang::BuiltinType::OCLSampler:
2509 case clang::BuiltinType::OCLEvent:
2510 case clang::BuiltinType::OCLClkEvent:
2511 case clang::BuiltinType::OCLQueue:
2512 case clang::BuiltinType::OCLReserveID:
2513 case clang::BuiltinType::ShortAccum:
2514 case clang::BuiltinType::Accum:
2515 case clang::BuiltinType::LongAccum:
2516 case clang::BuiltinType::UShortAccum:
2517 case clang::BuiltinType::UAccum:
2518 case clang::BuiltinType::ULongAccum:
2519 case clang::BuiltinType::ShortFract:
2520 case clang::BuiltinType::Fract:
2521 case clang::BuiltinType::LongFract:
2522 case clang::BuiltinType::UShortFract:
2523 case clang::BuiltinType::UFract:
2524 case clang::BuiltinType::ULongFract:
2525 case clang::BuiltinType::SatShortAccum:
2526 case clang::BuiltinType::SatAccum:
2527 case clang::BuiltinType::SatLongAccum:
2528 case clang::BuiltinType::SatUShortAccum:
2529 case clang::BuiltinType::SatUAccum:
2530 case clang::BuiltinType::SatULongAccum:
2531 case clang::BuiltinType::SatShortFract:
2532 case clang::BuiltinType::SatFract:
2533 case clang::BuiltinType::SatLongFract:
2534 case clang::BuiltinType::SatUShortFract:
2535 case clang::BuiltinType::SatUFract:
2536 case clang::BuiltinType::SatULongFract:
25082537 return res;
25092538 }
25102539 break;
25112540 }
2512 case Type::Pointer:
2513 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));
2541 case clang::Type::Pointer:
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:
25162546 {
2517 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
2518 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
2547 const clang::TypedefType *typedef_ty = static_cast<const clang::TypedefType*>(ty);
2548 const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
25192549 auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());
25202550 if (existing_entry) {
25212551 return existing_entry->value;
......@@ -2524,79 +2554,79 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
25242554 return res;
25252555 }
25262556
2527 case Type::Enum:
2557 case clang::Type::Enum:
25282558 {
2529 const EnumType *enum_ty = static_cast<const EnumType*>(ty);
2559 const clang::EnumType *enum_ty = static_cast<const clang::EnumType*>(ty);
25302560 AstNode *enum_type = resolve_enum_decl(c, enum_ty->getDecl());
25312561 return to_enum_zero_cmp(c, res, enum_type);
25322562 }
25332563
2534 case Type::Elaborated:
2564 case clang::Type::Elaborated:
25352565 {
2536 const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);
2566 const clang::ElaboratedType *elaborated_ty = static_cast<const clang::ElaboratedType*>(ty);
25372567 switch (elaborated_ty->getKeyword()) {
2538 case ETK_Enum: {
2568 case clang::ETK_Enum: {
25392569 AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getLocStart());
25402570 return to_enum_zero_cmp(c, res, enum_type);
25412571 }
2542 case ETK_Struct:
2543 case ETK_Union:
2544 case ETK_Interface:
2545 case ETK_Class:
2546 case ETK_Typename:
2547 case ETK_None:
2572 case clang::ETK_Struct:
2573 case clang::ETK_Union:
2574 case clang::ETK_Interface:
2575 case clang::ETK_Class:
2576 case clang::ETK_Typename:
2577 case clang::ETK_None:
25482578 return res;
25492579 }
25502580 }
25512581
2552 case Type::FunctionProto:
2553 case Type::Record:
2554 case Type::ConstantArray:
2555 case Type::Paren:
2556 case Type::Decayed:
2557 case Type::Attributed:
2558 case Type::IncompleteArray:
2559 case Type::BlockPointer:
2560 case Type::LValueReference:
2561 case Type::RValueReference:
2562 case Type::MemberPointer:
2563 case Type::VariableArray:
2564 case Type::DependentSizedArray:
2565 case Type::DependentSizedExtVector:
2566 case Type::Vector:
2567 case Type::ExtVector:
2568 case Type::FunctionNoProto:
2569 case Type::UnresolvedUsing:
2570 case Type::Adjusted:
2571 case Type::TypeOfExpr:
2572 case Type::TypeOf:
2573 case Type::Decltype:
2574 case Type::UnaryTransform:
2575 case Type::TemplateTypeParm:
2576 case Type::SubstTemplateTypeParm:
2577 case Type::SubstTemplateTypeParmPack:
2578 case Type::TemplateSpecialization:
2579 case Type::Auto:
2580 case Type::InjectedClassName:
2581 case Type::DependentName:
2582 case Type::DependentTemplateSpecialization:
2583 case Type::PackExpansion:
2584 case Type::ObjCObject:
2585 case Type::ObjCInterface:
2586 case Type::Complex:
2587 case Type::ObjCObjectPointer:
2588 case Type::Atomic:
2589 case Type::Pipe:
2590 case Type::ObjCTypeParam:
2591 case Type::DeducedTemplateSpecialization:
2592 case Type::DependentAddressSpace:
2593 case Type::DependentVector:
2582 case clang::Type::FunctionProto:
2583 case clang::Type::Record:
2584 case clang::Type::ConstantArray:
2585 case clang::Type::Paren:
2586 case clang::Type::Decayed:
2587 case clang::Type::Attributed:
2588 case clang::Type::IncompleteArray:
2589 case clang::Type::BlockPointer:
2590 case clang::Type::LValueReference:
2591 case clang::Type::RValueReference:
2592 case clang::Type::MemberPointer:
2593 case clang::Type::VariableArray:
2594 case clang::Type::DependentSizedArray:
2595 case clang::Type::DependentSizedExtVector:
2596 case clang::Type::Vector:
2597 case clang::Type::ExtVector:
2598 case clang::Type::FunctionNoProto:
2599 case clang::Type::UnresolvedUsing:
2600 case clang::Type::Adjusted:
2601 case clang::Type::TypeOfExpr:
2602 case clang::Type::TypeOf:
2603 case clang::Type::Decltype:
2604 case clang::Type::UnaryTransform:
2605 case clang::Type::TemplateTypeParm:
2606 case clang::Type::SubstTemplateTypeParm:
2607 case clang::Type::SubstTemplateTypeParmPack:
2608 case clang::Type::TemplateSpecialization:
2609 case clang::Type::Auto:
2610 case clang::Type::InjectedClassName:
2611 case clang::Type::DependentName:
2612 case clang::Type::DependentTemplateSpecialization:
2613 case clang::Type::PackExpansion:
2614 case clang::Type::ObjCObject:
2615 case clang::Type::ObjCInterface:
2616 case clang::Type::Complex:
2617 case clang::Type::ObjCObjectPointer:
2618 case clang::Type::Atomic:
2619 case clang::Type::Pipe:
2620 case clang::Type::ObjCTypeParam:
2621 case clang::Type::DeducedTemplateSpecialization:
2622 case clang::Type::DependentAddressSpace:
2623 case clang::Type::DependentVector:
25942624 return res;
25952625 }
25962626 zig_unreachable();
25972627}
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) {
26002630 TransScopeWhile *while_scope = trans_scope_while_create(c, scope);
26012631
26022632 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
26112641 return while_scope->node;
26122642}
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) {
26152645 // if (c) t
26162646 // if (c) t else e
26172647 AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);
......@@ -2633,7 +2663,7 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
26332663 return if_node;
26342664}
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) {
26372667 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
26382668
26392669 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 *
26412671 return nullptr;
26422672
26432673 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);
26452675 AstNode *callee_node = nullptr;
26462676 if (is_ptr && fn_ty) {
2647 if (stmt->getCallee()->getStmtClass() == Stmt::ImplicitCastExprClass) {
2648 const ImplicitCastExpr *implicit_cast = static_cast<const ImplicitCastExpr *>(stmt->getCallee());
2649 if (implicit_cast->getCastKind() == CK_FunctionToPointerDecay) {
2650 if (implicit_cast->getSubExpr()->getStmtClass() == Stmt::DeclRefExprClass) {
2651 const DeclRefExpr *decl_ref = static_cast<const DeclRefExpr *>(implicit_cast->getSubExpr());
2652 const Decl *decl = decl_ref->getFoundDecl();
2653 if (decl->getKind() == Decl::Function) {
2677 if (stmt->getCallee()->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
2678 const clang::ImplicitCastExpr *implicit_cast = static_cast<const clang::ImplicitCastExpr *>(stmt->getCallee());
2679 if (implicit_cast->getCastKind() == clang::CK_FunctionToPointerDecay) {
2680 if (implicit_cast->getSubExpr()->getStmtClass() == clang::Stmt::DeclRefExprClass) {
2681 const clang::DeclRefExpr *decl_ref = static_cast<const clang::DeclRefExpr *>(implicit_cast->getSubExpr());
2682 const clang::Decl *decl = decl_ref->getFoundDecl();
2683 if (decl->getKind() == clang::Decl::Function) {
26542684 callee_node = callee_raw_node;
26552685 }
26562686 }
......@@ -2666,7 +2696,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
26662696 node->data.fn_call_expr.fn_ref_expr = callee_node;
26672697
26682698 unsigned num_args = stmt->getNumArgs();
2669 const Expr * const* args = stmt->getArgs();
2699 const clang::Expr * const* args = stmt->getArgs();
26702700 for (unsigned i = 0; i < num_args; i += 1) {
26712701 AstNode *arg_node = trans_expr(c, ResultUsedYes, scope, args[i], TransRValue);
26722702 if (arg_node == nullptr)
......@@ -2682,7 +2712,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
26822712 return node;
26832713}
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) {
26862716 AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);
26872717 if (container_node == nullptr)
26882718 return nullptr;
......@@ -2697,7 +2727,7 @@ static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExp
26972727 return node;
26982728}
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) {
27012731 AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);
27022732 if (container_node == nullptr)
27032733 return nullptr;
......@@ -2714,7 +2744,7 @@ static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const
27142744}
27152745
27162746static 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)
27182748{
27192749 AstNode *sub_expr_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), lrvalue);
27202750 if (sub_expr_node == nullptr)
......@@ -2724,7 +2754,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran
27242754}
27252755
27262756static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope,
2727 const UnaryExprOrTypeTraitExpr *stmt)
2757 const clang::UnaryExprOrTypeTraitExpr *stmt)
27282758{
27292759 AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getLocStart());
27302760 if (type_node == nullptr)
......@@ -2735,14 +2765,14 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scop
27352765 return node;
27362766}
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) {
27392769 TransScopeWhile *while_scope = trans_scope_while_create(c, parent_scope);
27402770
27412771 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
27422772
27432773 AstNode *body_node;
27442774 TransScope *child_scope;
2745 if (stmt->getBody()->getStmtClass() == Stmt::CompoundStmtClass) {
2775 if (stmt->getBody()->getStmtClass() == clang::Stmt::CompoundStmtClass) {
27462776 // there's already a block in C, so we'll append our condition to it.
27472777 // c: do {
27482778 // c: a;
......@@ -2795,11 +2825,11 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt
27952825 return while_scope->node;
27962826}
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) {
27992829 AstNode *loop_block_node;
28002830 TransScopeWhile *while_scope;
28012831 TransScope *cond_scope;
2802 const Stmt *init_stmt = stmt->getInit();
2832 const clang::Stmt *init_stmt = stmt->getInit();
28032833 if (init_stmt == nullptr) {
28042834 while_scope = trans_scope_while_create(c, parent_scope);
28052835 loop_block_node = while_scope->node;
......@@ -2820,12 +2850,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
28202850 child_scope->node->data.block.statements.append(while_scope->node);
28212851 }
28222852
2823 const Stmt *cond_stmt = stmt->getCond();
2853 const clang::Stmt *cond_stmt = stmt->getCond();
28242854 if (cond_stmt == nullptr) {
28252855 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
28262856 } else {
2827 if (Expr::classof(cond_stmt)) {
2828 const Expr *cond_expr = static_cast<const Expr*>(cond_stmt);
2857 if (clang::Expr::classof(cond_stmt)) {
2858 const clang::Expr *cond_expr = static_cast<const clang::Expr*>(cond_stmt);
28292859 while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, cond_expr, TransRValue);
28302860
28312861 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
28382868 }
28392869 }
28402870
2841 const Stmt *inc_stmt = stmt->getInc();
2871 const clang::Stmt *inc_stmt = stmt->getInc();
28422872 if (inc_stmt != nullptr) {
28432873 AstNode *inc_node;
28442874 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
28612891 return loop_block_node;
28622892}
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) {
28652895 TransScopeBlock *block_scope = trans_scope_block_create(c, parent_scope);
28662896
28672897 TransScopeSwitch *switch_scope;
28682898
2869 const DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt();
2899 const clang::DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt();
28702900 if (var_decl_stmt == nullptr) {
28712901 switch_scope = trans_scope_switch_create(c, &block_scope->base);
28722902 } else {
......@@ -2885,7 +2915,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw
28852915 switch_scope->end_label_name = end_label_name;
28862916 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();
28892919 assert(cond_expr != nullptr);
28902920
28912921 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
28942924 switch_scope->switch_node->data.switch_expr.expr = expr_node;
28952925
28962926 AstNode *body_node;
2897 const Stmt *body_stmt = stmt->getBody();
2898 if (body_stmt->getStmtClass() == Stmt::CompoundStmtClass) {
2899 if (trans_compound_stmt_inline(c, &switch_scope->base, (const CompoundStmt *)body_stmt,
2927 const clang::Stmt *body_stmt = stmt->getBody();
2928 if (body_stmt->getStmtClass() == clang::Stmt::CompoundStmtClass) {
2929 if (trans_compound_stmt_inline(c, &switch_scope->base, (const clang::CompoundStmt *)body_stmt,
29002930 block_scope->node, nullptr))
29012931 {
29022932 return nullptr;
......@@ -2928,7 +2958,7 @@ static TransScopeSwitch *trans_scope_switch_find(TransScope *scope) {
29282958 return nullptr;
29292959}
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,
29322962 TransScope **out_scope) {
29332963 *out_node = nullptr;
29342964
......@@ -2973,7 +3003,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStm
29733003 return ErrorNone;
29743004}
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,
29773007 TransScope **out_scope)
29783008{
29793009 *out_node = nullptr;
......@@ -3010,25 +3040,25 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const Defa
30103040 return ErrorNone;
30113041}
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) {
30143044 switch (stmt->getKind()) {
3015 case StringLiteral::Ascii:
3016 case StringLiteral::UTF8:
3045 case clang::StringLiteral::Ascii:
3046 case clang::StringLiteral::UTF8:
30173047 return trans_create_node_str_lit_c(c, string_ref_to_buf(stmt->getString()));
3018 case StringLiteral::UTF16:
3048 case clang::StringLiteral::UTF16:
30193049 emit_warning(c, stmt->getLocStart(), "TODO support UTF16 string literals");
30203050 return nullptr;
3021 case StringLiteral::UTF32:
3051 case clang::StringLiteral::UTF32:
30223052 emit_warning(c, stmt->getLocStart(), "TODO support UTF32 string literals");
30233053 return nullptr;
3024 case StringLiteral::Wide:
3054 case clang::StringLiteral::Wide:
30253055 emit_warning(c, stmt->getLocStart(), "TODO support wide string literals");
30263056 return nullptr;
30273057 }
30283058 zig_unreachable();
30293059}
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) {
30323062 TransScope *cur_scope = scope;
30333063 while (cur_scope != nullptr) {
30343064 if (cur_scope->id == TransScopeIdWhile) {
......@@ -3042,7 +3072,7 @@ static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt
30423072 zig_unreachable();
30433073}
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) {
30463076 return trans_create_node(c, NodeTypeContinue);
30473077}
30483078
......@@ -3055,47 +3085,47 @@ static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_
30553085 return ErrorNone;
30563086}
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,
30593089 ResultUsed result_used, TransLRValue lrvalue,
30603090 AstNode **out_node, TransScope **out_child_scope,
30613091 TransScope **out_node_scope)
30623092{
3063 Stmt::StmtClass sc = stmt->getStmtClass();
3093 clang::Stmt::StmtClass sc = stmt->getStmtClass();
30643094 switch (sc) {
3065 case Stmt::ReturnStmtClass:
3095 case clang::Stmt::ReturnStmtClass:
30663096 return wrap_stmt(out_node, out_child_scope, scope,
3067 trans_return_stmt(c, scope, (const ReturnStmt *)stmt));
3068 case Stmt::CompoundStmtClass:
3097 trans_return_stmt(c, scope, (const clang::ReturnStmt *)stmt));
3098 case clang::Stmt::CompoundStmtClass:
30693099 return wrap_stmt(out_node, out_child_scope, scope,
3070 trans_compound_stmt(c, scope, (const CompoundStmt *)stmt, out_node_scope));
3071 case Stmt::IntegerLiteralClass:
3100 trans_compound_stmt(c, scope, (const clang::CompoundStmt *)stmt, out_node_scope));
3101 case clang::Stmt::IntegerLiteralClass:
30723102 return wrap_stmt(out_node, out_child_scope, scope,
3073 trans_integer_literal(c, (const IntegerLiteral *)stmt));
3074 case Stmt::ConditionalOperatorClass:
3103 trans_integer_literal(c, (const clang::IntegerLiteral *)stmt));
3104 case clang::Stmt::ConditionalOperatorClass:
30753105 return wrap_stmt(out_node, out_child_scope, scope,
3076 trans_conditional_operator(c, result_used, scope, (const ConditionalOperator *)stmt));
3077 case Stmt::BinaryOperatorClass:
3106 trans_conditional_operator(c, result_used, scope, (const clang::ConditionalOperator *)stmt));
3107 case clang::Stmt::BinaryOperatorClass:
30783108 return wrap_stmt(out_node, out_child_scope, scope,
3079 trans_binary_operator(c, result_used, scope, (const BinaryOperator *)stmt));
3080 case Stmt::CompoundAssignOperatorClass:
3109 trans_binary_operator(c, result_used, scope, (const clang::BinaryOperator *)stmt));
3110 case clang::Stmt::CompoundAssignOperatorClass:
30813111 return wrap_stmt(out_node, out_child_scope, scope,
3082 trans_compound_assign_operator(c, result_used, scope, (const CompoundAssignOperator *)stmt));
3083 case Stmt::ImplicitCastExprClass:
3112 trans_compound_assign_operator(c, result_used, scope, (const clang::CompoundAssignOperator *)stmt));
3113 case clang::Stmt::ImplicitCastExprClass:
30843114 return wrap_stmt(out_node, out_child_scope, scope,
3085 trans_implicit_cast_expr(c, scope, (const ImplicitCastExpr *)stmt));
3086 case Stmt::DeclRefExprClass:
3115 trans_implicit_cast_expr(c, scope, (const clang::ImplicitCastExpr *)stmt));
3116 case clang::Stmt::DeclRefExprClass:
30873117 return wrap_stmt(out_node, out_child_scope, scope,
3088 trans_decl_ref_expr(c, scope, (const DeclRefExpr *)stmt, lrvalue));
3089 case Stmt::UnaryOperatorClass:
3118 trans_decl_ref_expr(c, scope, (const clang::DeclRefExpr *)stmt, lrvalue));
3119 case clang::Stmt::UnaryOperatorClass:
30903120 return wrap_stmt(out_node, out_child_scope, scope,
3091 trans_unary_operator(c, result_used, scope, (const UnaryOperator *)stmt));
3092 case Stmt::DeclStmtClass:
3093 return trans_local_declaration(c, scope, (const DeclStmt *)stmt, out_node, out_child_scope);
3094 case Stmt::DoStmtClass:
3095 case Stmt::WhileStmtClass: {
3096 AstNode *while_node = sc == Stmt::DoStmtClass
3097 ? trans_do_loop(c, scope, (const DoStmt *)stmt)
3098 : trans_while_loop(c, scope, (const WhileStmt *)stmt);
3121 trans_unary_operator(c, result_used, scope, (const clang::UnaryOperator *)stmt));
3122 case clang::Stmt::DeclStmtClass:
3123 return trans_local_declaration(c, scope, (const clang::DeclStmt *)stmt, out_node, out_child_scope);
3124 case clang::Stmt::DoStmtClass:
3125 case clang::Stmt::WhileStmtClass: {
3126 AstNode *while_node = sc == clang::Stmt::DoStmtClass
3127 ? trans_do_loop(c, scope, (const clang::DoStmt *)stmt)
3128 : trans_while_loop(c, scope, (const clang::WhileStmt *)stmt);
30993129
31003130 if (while_node == nullptr)
31013131 return ErrorUnexpected;
......@@ -3106,556 +3136,556 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,
31063136
31073137 return wrap_stmt(out_node, out_child_scope, scope, while_node);
31083138 }
3109 case Stmt::IfStmtClass:
3139 case clang::Stmt::IfStmtClass:
31103140 return wrap_stmt(out_node, out_child_scope, scope,
3111 trans_if_statement(c, scope, (const IfStmt *)stmt));
3112 case Stmt::CallExprClass:
3141 trans_if_statement(c, scope, (const clang::IfStmt *)stmt));
3142 case clang::Stmt::CallExprClass:
31133143 return wrap_stmt(out_node, out_child_scope, scope,
3114 trans_call_expr(c, result_used, scope, (const CallExpr *)stmt));
3115 case Stmt::NullStmtClass:
3144 trans_call_expr(c, result_used, scope, (const clang::CallExpr *)stmt));
3145 case clang::Stmt::NullStmtClass:
31163146 *out_node = nullptr;
31173147 *out_child_scope = scope;
31183148 return ErrorNone;
3119 case Stmt::MemberExprClass:
3149 case clang::Stmt::MemberExprClass:
31203150 return wrap_stmt(out_node, out_child_scope, scope,
3121 trans_member_expr(c, scope, (const MemberExpr *)stmt));
3122 case Stmt::ArraySubscriptExprClass:
3151 trans_member_expr(c, scope, (const clang::MemberExpr *)stmt));
3152 case clang::Stmt::ArraySubscriptExprClass:
31233153 return wrap_stmt(out_node, out_child_scope, scope,
3124 trans_array_subscript_expr(c, scope, (const ArraySubscriptExpr *)stmt));
3125 case Stmt::CStyleCastExprClass:
3154 trans_array_subscript_expr(c, scope, (const clang::ArraySubscriptExpr *)stmt));
3155 case clang::Stmt::CStyleCastExprClass:
31263156 return wrap_stmt(out_node, out_child_scope, scope,
3127 trans_c_style_cast_expr(c, result_used, scope, (const CStyleCastExpr *)stmt, lrvalue));
3128 case Stmt::UnaryExprOrTypeTraitExprClass:
3157 trans_c_style_cast_expr(c, result_used, scope, (const clang::CStyleCastExpr *)stmt, lrvalue));
3158 case clang::Stmt::UnaryExprOrTypeTraitExprClass:
31293159 return wrap_stmt(out_node, out_child_scope, scope,
3130 trans_unary_expr_or_type_trait_expr(c, scope, (const UnaryExprOrTypeTraitExpr *)stmt));
3131 case Stmt::ForStmtClass: {
3132 AstNode *node = trans_for_loop(c, scope, (const ForStmt *)stmt);
3160 trans_unary_expr_or_type_trait_expr(c, scope, (const clang::UnaryExprOrTypeTraitExpr *)stmt));
3161 case clang::Stmt::ForStmtClass: {
3162 AstNode *node = trans_for_loop(c, scope, (const clang::ForStmt *)stmt);
31333163 return wrap_stmt(out_node, out_child_scope, scope, node);
31343164 }
3135 case Stmt::StringLiteralClass:
3165 case clang::Stmt::StringLiteralClass:
31363166 return wrap_stmt(out_node, out_child_scope, scope,
3137 trans_string_literal(c, scope, (const StringLiteral *)stmt));
3138 case Stmt::BreakStmtClass:
3167 trans_string_literal(c, scope, (const clang::StringLiteral *)stmt));
3168 case clang::Stmt::BreakStmtClass:
31393169 return wrap_stmt(out_node, out_child_scope, scope,
3140 trans_break_stmt(c, scope, (const BreakStmt *)stmt));
3141 case Stmt::ContinueStmtClass:
3170 trans_break_stmt(c, scope, (const clang::BreakStmt *)stmt));
3171 case clang::Stmt::ContinueStmtClass:
31423172 return wrap_stmt(out_node, out_child_scope, scope,
3143 trans_continue_stmt(c, scope, (const ContinueStmt *)stmt));
3144 case Stmt::ParenExprClass:
3173 trans_continue_stmt(c, scope, (const clang::ContinueStmt *)stmt));
3174 case clang::Stmt::ParenExprClass:
31453175 return wrap_stmt(out_node, out_child_scope, scope,
3146 trans_expr(c, result_used, scope, ((const ParenExpr*)stmt)->getSubExpr(), lrvalue));
3147 case Stmt::SwitchStmtClass:
3176 trans_expr(c, result_used, scope, ((const clang::ParenExpr*)stmt)->getSubExpr(), lrvalue));
3177 case clang::Stmt::SwitchStmtClass:
31483178 return wrap_stmt(out_node, out_child_scope, scope,
3149 trans_switch_stmt(c, scope, (const SwitchStmt *)stmt));
3150 case Stmt::CaseStmtClass:
3151 return trans_switch_case(c, scope, (const CaseStmt *)stmt, out_node, out_child_scope);
3152 case Stmt::DefaultStmtClass:
3153 return trans_switch_default(c, scope, (const DefaultStmt *)stmt, out_node, out_child_scope);
3154 case Stmt::NoStmtClass:
3179 trans_switch_stmt(c, scope, (const clang::SwitchStmt *)stmt));
3180 case clang::Stmt::CaseStmtClass:
3181 return trans_switch_case(c, scope, (const clang::CaseStmt *)stmt, out_node, out_child_scope);
3182 case clang::Stmt::DefaultStmtClass:
3183 return trans_switch_default(c, scope, (const clang::DefaultStmt *)stmt, out_node, out_child_scope);
3184 case clang::Stmt::NoStmtClass:
31553185 emit_warning(c, stmt->getLocStart(), "TODO handle C NoStmtClass");
31563186 return ErrorUnexpected;
3157 case Stmt::GCCAsmStmtClass:
3187 case clang::Stmt::GCCAsmStmtClass:
31583188 emit_warning(c, stmt->getLocStart(), "TODO handle C GCCAsmStmtClass");
31593189 return ErrorUnexpected;
3160 case Stmt::MSAsmStmtClass:
3190 case clang::Stmt::MSAsmStmtClass:
31613191 emit_warning(c, stmt->getLocStart(), "TODO handle C MSAsmStmtClass");
31623192 return ErrorUnexpected;
3163 case Stmt::AttributedStmtClass:
3193 case clang::Stmt::AttributedStmtClass:
31643194 emit_warning(c, stmt->getLocStart(), "TODO handle C AttributedStmtClass");
31653195 return ErrorUnexpected;
3166 case Stmt::CXXCatchStmtClass:
3196 case clang::Stmt::CXXCatchStmtClass:
31673197 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXCatchStmtClass");
31683198 return ErrorUnexpected;
3169 case Stmt::CXXForRangeStmtClass:
3199 case clang::Stmt::CXXForRangeStmtClass:
31703200 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXForRangeStmtClass");
31713201 return ErrorUnexpected;
3172 case Stmt::CXXTryStmtClass:
3202 case clang::Stmt::CXXTryStmtClass:
31733203 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTryStmtClass");
31743204 return ErrorUnexpected;
3175 case Stmt::CapturedStmtClass:
3205 case clang::Stmt::CapturedStmtClass:
31763206 emit_warning(c, stmt->getLocStart(), "TODO handle C CapturedStmtClass");
31773207 return ErrorUnexpected;
3178 case Stmt::CoreturnStmtClass:
3208 case clang::Stmt::CoreturnStmtClass:
31793209 emit_warning(c, stmt->getLocStart(), "TODO handle C CoreturnStmtClass");
31803210 return ErrorUnexpected;
3181 case Stmt::CoroutineBodyStmtClass:
3211 case clang::Stmt::CoroutineBodyStmtClass:
31823212 emit_warning(c, stmt->getLocStart(), "TODO handle C CoroutineBodyStmtClass");
31833213 return ErrorUnexpected;
3184 case Stmt::BinaryConditionalOperatorClass:
3214 case clang::Stmt::BinaryConditionalOperatorClass:
31853215 emit_warning(c, stmt->getLocStart(), "TODO handle C BinaryConditionalOperatorClass");
31863216 return ErrorUnexpected;
3187 case Stmt::AddrLabelExprClass:
3217 case clang::Stmt::AddrLabelExprClass:
31883218 emit_warning(c, stmt->getLocStart(), "TODO handle C AddrLabelExprClass");
31893219 return ErrorUnexpected;
3190 case Stmt::ArrayInitIndexExprClass:
3220 case clang::Stmt::ArrayInitIndexExprClass:
31913221 emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitIndexExprClass");
31923222 return ErrorUnexpected;
3193 case Stmt::ArrayInitLoopExprClass:
3223 case clang::Stmt::ArrayInitLoopExprClass:
31943224 emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitLoopExprClass");
31953225 return ErrorUnexpected;
3196 case Stmt::ArrayTypeTraitExprClass:
3226 case clang::Stmt::ArrayTypeTraitExprClass:
31973227 emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayTypeTraitExprClass");
31983228 return ErrorUnexpected;
3199 case Stmt::AsTypeExprClass:
3229 case clang::Stmt::AsTypeExprClass:
32003230 emit_warning(c, stmt->getLocStart(), "TODO handle C AsTypeExprClass");
32013231 return ErrorUnexpected;
3202 case Stmt::AtomicExprClass:
3232 case clang::Stmt::AtomicExprClass:
32033233 emit_warning(c, stmt->getLocStart(), "TODO handle C AtomicExprClass");
32043234 return ErrorUnexpected;
3205 case Stmt::BlockExprClass:
3235 case clang::Stmt::BlockExprClass:
32063236 emit_warning(c, stmt->getLocStart(), "TODO handle C BlockExprClass");
32073237 return ErrorUnexpected;
3208 case Stmt::CXXBindTemporaryExprClass:
3238 case clang::Stmt::CXXBindTemporaryExprClass:
32093239 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXBindTemporaryExprClass");
32103240 return ErrorUnexpected;
3211 case Stmt::CXXBoolLiteralExprClass:
3241 case clang::Stmt::CXXBoolLiteralExprClass:
32123242 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXBoolLiteralExprClass");
32133243 return ErrorUnexpected;
3214 case Stmt::CXXConstructExprClass:
3244 case clang::Stmt::CXXConstructExprClass:
32153245 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXConstructExprClass");
32163246 return ErrorUnexpected;
3217 case Stmt::CXXTemporaryObjectExprClass:
3247 case clang::Stmt::CXXTemporaryObjectExprClass:
32183248 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTemporaryObjectExprClass");
32193249 return ErrorUnexpected;
3220 case Stmt::CXXDefaultArgExprClass:
3250 case clang::Stmt::CXXDefaultArgExprClass:
32213251 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDefaultArgExprClass");
32223252 return ErrorUnexpected;
3223 case Stmt::CXXDefaultInitExprClass:
3253 case clang::Stmt::CXXDefaultInitExprClass:
32243254 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDefaultInitExprClass");
32253255 return ErrorUnexpected;
3226 case Stmt::CXXDeleteExprClass:
3256 case clang::Stmt::CXXDeleteExprClass:
32273257 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDeleteExprClass");
32283258 return ErrorUnexpected;
3229 case Stmt::CXXDependentScopeMemberExprClass:
3259 case clang::Stmt::CXXDependentScopeMemberExprClass:
32303260 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDependentScopeMemberExprClass");
32313261 return ErrorUnexpected;
3232 case Stmt::CXXFoldExprClass:
3262 case clang::Stmt::CXXFoldExprClass:
32333263 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFoldExprClass");
32343264 return ErrorUnexpected;
3235 case Stmt::CXXInheritedCtorInitExprClass:
3265 case clang::Stmt::CXXInheritedCtorInitExprClass:
32363266 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXInheritedCtorInitExprClass");
32373267 return ErrorUnexpected;
3238 case Stmt::CXXNewExprClass:
3268 case clang::Stmt::CXXNewExprClass:
32393269 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNewExprClass");
32403270 return ErrorUnexpected;
3241 case Stmt::CXXNoexceptExprClass:
3271 case clang::Stmt::CXXNoexceptExprClass:
32423272 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNoexceptExprClass");
32433273 return ErrorUnexpected;
3244 case Stmt::CXXNullPtrLiteralExprClass:
3274 case clang::Stmt::CXXNullPtrLiteralExprClass:
32453275 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNullPtrLiteralExprClass");
32463276 return ErrorUnexpected;
3247 case Stmt::CXXPseudoDestructorExprClass:
3277 case clang::Stmt::CXXPseudoDestructorExprClass:
32483278 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXPseudoDestructorExprClass");
32493279 return ErrorUnexpected;
3250 case Stmt::CXXScalarValueInitExprClass:
3280 case clang::Stmt::CXXScalarValueInitExprClass:
32513281 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXScalarValueInitExprClass");
32523282 return ErrorUnexpected;
3253 case Stmt::CXXStdInitializerListExprClass:
3283 case clang::Stmt::CXXStdInitializerListExprClass:
32543284 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXStdInitializerListExprClass");
32553285 return ErrorUnexpected;
3256 case Stmt::CXXThisExprClass:
3286 case clang::Stmt::CXXThisExprClass:
32573287 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXThisExprClass");
32583288 return ErrorUnexpected;
3259 case Stmt::CXXThrowExprClass:
3289 case clang::Stmt::CXXThrowExprClass:
32603290 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXThrowExprClass");
32613291 return ErrorUnexpected;
3262 case Stmt::CXXTypeidExprClass:
3292 case clang::Stmt::CXXTypeidExprClass:
32633293 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTypeidExprClass");
32643294 return ErrorUnexpected;
3265 case Stmt::CXXUnresolvedConstructExprClass:
3295 case clang::Stmt::CXXUnresolvedConstructExprClass:
32663296 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUnresolvedConstructExprClass");
32673297 return ErrorUnexpected;
3268 case Stmt::CXXUuidofExprClass:
3298 case clang::Stmt::CXXUuidofExprClass:
32693299 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUuidofExprClass");
32703300 return ErrorUnexpected;
3271 case Stmt::CUDAKernelCallExprClass:
3301 case clang::Stmt::CUDAKernelCallExprClass:
32723302 emit_warning(c, stmt->getLocStart(), "TODO handle C CUDAKernelCallExprClass");
32733303 return ErrorUnexpected;
3274 case Stmt::CXXMemberCallExprClass:
3304 case clang::Stmt::CXXMemberCallExprClass:
32753305 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXMemberCallExprClass");
32763306 return ErrorUnexpected;
3277 case Stmt::CXXOperatorCallExprClass:
3307 case clang::Stmt::CXXOperatorCallExprClass:
32783308 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXOperatorCallExprClass");
32793309 return ErrorUnexpected;
3280 case Stmt::UserDefinedLiteralClass:
3310 case clang::Stmt::UserDefinedLiteralClass:
32813311 emit_warning(c, stmt->getLocStart(), "TODO handle C UserDefinedLiteralClass");
32823312 return ErrorUnexpected;
3283 case Stmt::CXXFunctionalCastExprClass:
3313 case clang::Stmt::CXXFunctionalCastExprClass:
32843314 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFunctionalCastExprClass");
32853315 return ErrorUnexpected;
3286 case Stmt::CXXConstCastExprClass:
3316 case clang::Stmt::CXXConstCastExprClass:
32873317 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXConstCastExprClass");
32883318 return ErrorUnexpected;
3289 case Stmt::CXXDynamicCastExprClass:
3319 case clang::Stmt::CXXDynamicCastExprClass:
32903320 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDynamicCastExprClass");
32913321 return ErrorUnexpected;
3292 case Stmt::CXXReinterpretCastExprClass:
3322 case clang::Stmt::CXXReinterpretCastExprClass:
32933323 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXReinterpretCastExprClass");
32943324 return ErrorUnexpected;
3295 case Stmt::CXXStaticCastExprClass:
3325 case clang::Stmt::CXXStaticCastExprClass:
32963326 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXStaticCastExprClass");
32973327 return ErrorUnexpected;
3298 case Stmt::ObjCBridgedCastExprClass:
3328 case clang::Stmt::ObjCBridgedCastExprClass:
32993329 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBridgedCastExprClass");
33003330 return ErrorUnexpected;
3301 case Stmt::CharacterLiteralClass:
3331 case clang::Stmt::CharacterLiteralClass:
33023332 emit_warning(c, stmt->getLocStart(), "TODO handle C CharacterLiteralClass");
33033333 return ErrorUnexpected;
3304 case Stmt::ChooseExprClass:
3334 case clang::Stmt::ChooseExprClass:
33053335 emit_warning(c, stmt->getLocStart(), "TODO handle C ChooseExprClass");
33063336 return ErrorUnexpected;
3307 case Stmt::CompoundLiteralExprClass:
3337 case clang::Stmt::CompoundLiteralExprClass:
33083338 emit_warning(c, stmt->getLocStart(), "TODO handle C CompoundLiteralExprClass");
33093339 return ErrorUnexpected;
3310 case Stmt::ConvertVectorExprClass:
3340 case clang::Stmt::ConvertVectorExprClass:
33113341 emit_warning(c, stmt->getLocStart(), "TODO handle C ConvertVectorExprClass");
33123342 return ErrorUnexpected;
3313 case Stmt::CoawaitExprClass:
3343 case clang::Stmt::CoawaitExprClass:
33143344 emit_warning(c, stmt->getLocStart(), "TODO handle C CoawaitExprClass");
33153345 return ErrorUnexpected;
3316 case Stmt::CoyieldExprClass:
3346 case clang::Stmt::CoyieldExprClass:
33173347 emit_warning(c, stmt->getLocStart(), "TODO handle C CoyieldExprClass");
33183348 return ErrorUnexpected;
3319 case Stmt::DependentCoawaitExprClass:
3349 case clang::Stmt::DependentCoawaitExprClass:
33203350 emit_warning(c, stmt->getLocStart(), "TODO handle C DependentCoawaitExprClass");
33213351 return ErrorUnexpected;
3322 case Stmt::DependentScopeDeclRefExprClass:
3352 case clang::Stmt::DependentScopeDeclRefExprClass:
33233353 emit_warning(c, stmt->getLocStart(), "TODO handle C DependentScopeDeclRefExprClass");
33243354 return ErrorUnexpected;
3325 case Stmt::DesignatedInitExprClass:
3355 case clang::Stmt::DesignatedInitExprClass:
33263356 emit_warning(c, stmt->getLocStart(), "TODO handle C DesignatedInitExprClass");
33273357 return ErrorUnexpected;
3328 case Stmt::DesignatedInitUpdateExprClass:
3358 case clang::Stmt::DesignatedInitUpdateExprClass:
33293359 emit_warning(c, stmt->getLocStart(), "TODO handle C DesignatedInitUpdateExprClass");
33303360 return ErrorUnexpected;
3331 case Stmt::ExprWithCleanupsClass:
3361 case clang::Stmt::ExprWithCleanupsClass:
33323362 emit_warning(c, stmt->getLocStart(), "TODO handle C ExprWithCleanupsClass");
33333363 return ErrorUnexpected;
3334 case Stmt::ExpressionTraitExprClass:
3364 case clang::Stmt::ExpressionTraitExprClass:
33353365 emit_warning(c, stmt->getLocStart(), "TODO handle C ExpressionTraitExprClass");
33363366 return ErrorUnexpected;
3337 case Stmt::ExtVectorElementExprClass:
3367 case clang::Stmt::ExtVectorElementExprClass:
33383368 emit_warning(c, stmt->getLocStart(), "TODO handle C ExtVectorElementExprClass");
33393369 return ErrorUnexpected;
3340 case Stmt::FloatingLiteralClass:
3370 case clang::Stmt::FloatingLiteralClass:
33413371 emit_warning(c, stmt->getLocStart(), "TODO handle C FloatingLiteralClass");
33423372 return ErrorUnexpected;
3343 case Stmt::FunctionParmPackExprClass:
3373 case clang::Stmt::FunctionParmPackExprClass:
33443374 emit_warning(c, stmt->getLocStart(), "TODO handle C FunctionParmPackExprClass");
33453375 return ErrorUnexpected;
3346 case Stmt::GNUNullExprClass:
3376 case clang::Stmt::GNUNullExprClass:
33473377 emit_warning(c, stmt->getLocStart(), "TODO handle C GNUNullExprClass");
33483378 return ErrorUnexpected;
3349 case Stmt::GenericSelectionExprClass:
3379 case clang::Stmt::GenericSelectionExprClass:
33503380 emit_warning(c, stmt->getLocStart(), "TODO handle C GenericSelectionExprClass");
33513381 return ErrorUnexpected;
3352 case Stmt::ImaginaryLiteralClass:
3382 case clang::Stmt::ImaginaryLiteralClass:
33533383 emit_warning(c, stmt->getLocStart(), "TODO handle C ImaginaryLiteralClass");
33543384 return ErrorUnexpected;
3355 case Stmt::ImplicitValueInitExprClass:
3385 case clang::Stmt::ImplicitValueInitExprClass:
33563386 emit_warning(c, stmt->getLocStart(), "TODO handle C ImplicitValueInitExprClass");
33573387 return ErrorUnexpected;
3358 case Stmt::InitListExprClass:
3388 case clang::Stmt::InitListExprClass:
33593389 emit_warning(c, stmt->getLocStart(), "TODO handle C InitListExprClass");
33603390 return ErrorUnexpected;
3361 case Stmt::LambdaExprClass:
3391 case clang::Stmt::LambdaExprClass:
33623392 emit_warning(c, stmt->getLocStart(), "TODO handle C LambdaExprClass");
33633393 return ErrorUnexpected;
3364 case Stmt::MSPropertyRefExprClass:
3394 case clang::Stmt::MSPropertyRefExprClass:
33653395 emit_warning(c, stmt->getLocStart(), "TODO handle C MSPropertyRefExprClass");
33663396 return ErrorUnexpected;
3367 case Stmt::MSPropertySubscriptExprClass:
3397 case clang::Stmt::MSPropertySubscriptExprClass:
33683398 emit_warning(c, stmt->getLocStart(), "TODO handle C MSPropertySubscriptExprClass");
33693399 return ErrorUnexpected;
3370 case Stmt::MaterializeTemporaryExprClass:
3400 case clang::Stmt::MaterializeTemporaryExprClass:
33713401 emit_warning(c, stmt->getLocStart(), "TODO handle C MaterializeTemporaryExprClass");
33723402 return ErrorUnexpected;
3373 case Stmt::NoInitExprClass:
3403 case clang::Stmt::NoInitExprClass:
33743404 emit_warning(c, stmt->getLocStart(), "TODO handle C NoInitExprClass");
33753405 return ErrorUnexpected;
3376 case Stmt::OMPArraySectionExprClass:
3406 case clang::Stmt::OMPArraySectionExprClass:
33773407 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPArraySectionExprClass");
33783408 return ErrorUnexpected;
3379 case Stmt::ObjCArrayLiteralClass:
3409 case clang::Stmt::ObjCArrayLiteralClass:
33803410 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCArrayLiteralClass");
33813411 return ErrorUnexpected;
3382 case Stmt::ObjCAvailabilityCheckExprClass:
3412 case clang::Stmt::ObjCAvailabilityCheckExprClass:
33833413 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAvailabilityCheckExprClass");
33843414 return ErrorUnexpected;
3385 case Stmt::ObjCBoolLiteralExprClass:
3415 case clang::Stmt::ObjCBoolLiteralExprClass:
33863416 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBoolLiteralExprClass");
33873417 return ErrorUnexpected;
3388 case Stmt::ObjCBoxedExprClass:
3418 case clang::Stmt::ObjCBoxedExprClass:
33893419 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBoxedExprClass");
33903420 return ErrorUnexpected;
3391 case Stmt::ObjCDictionaryLiteralClass:
3421 case clang::Stmt::ObjCDictionaryLiteralClass:
33923422 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCDictionaryLiteralClass");
33933423 return ErrorUnexpected;
3394 case Stmt::ObjCEncodeExprClass:
3424 case clang::Stmt::ObjCEncodeExprClass:
33953425 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCEncodeExprClass");
33963426 return ErrorUnexpected;
3397 case Stmt::ObjCIndirectCopyRestoreExprClass:
3427 case clang::Stmt::ObjCIndirectCopyRestoreExprClass:
33983428 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIndirectCopyRestoreExprClass");
33993429 return ErrorUnexpected;
3400 case Stmt::ObjCIsaExprClass:
3430 case clang::Stmt::ObjCIsaExprClass:
34013431 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIsaExprClass");
34023432 return ErrorUnexpected;
3403 case Stmt::ObjCIvarRefExprClass:
3433 case clang::Stmt::ObjCIvarRefExprClass:
34043434 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIvarRefExprClass");
34053435 return ErrorUnexpected;
3406 case Stmt::ObjCMessageExprClass:
3436 case clang::Stmt::ObjCMessageExprClass:
34073437 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCMessageExprClass");
34083438 return ErrorUnexpected;
3409 case Stmt::ObjCPropertyRefExprClass:
3439 case clang::Stmt::ObjCPropertyRefExprClass:
34103440 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCPropertyRefExprClass");
34113441 return ErrorUnexpected;
3412 case Stmt::ObjCProtocolExprClass:
3442 case clang::Stmt::ObjCProtocolExprClass:
34133443 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCProtocolExprClass");
34143444 return ErrorUnexpected;
3415 case Stmt::ObjCSelectorExprClass:
3445 case clang::Stmt::ObjCSelectorExprClass:
34163446 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCSelectorExprClass");
34173447 return ErrorUnexpected;
3418 case Stmt::ObjCStringLiteralClass:
3448 case clang::Stmt::ObjCStringLiteralClass:
34193449 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCStringLiteralClass");
34203450 return ErrorUnexpected;
3421 case Stmt::ObjCSubscriptRefExprClass:
3451 case clang::Stmt::ObjCSubscriptRefExprClass:
34223452 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCSubscriptRefExprClass");
34233453 return ErrorUnexpected;
3424 case Stmt::OffsetOfExprClass:
3454 case clang::Stmt::OffsetOfExprClass:
34253455 emit_warning(c, stmt->getLocStart(), "TODO handle C OffsetOfExprClass");
34263456 return ErrorUnexpected;
3427 case Stmt::OpaqueValueExprClass:
3457 case clang::Stmt::OpaqueValueExprClass:
34283458 emit_warning(c, stmt->getLocStart(), "TODO handle C OpaqueValueExprClass");
34293459 return ErrorUnexpected;
3430 case Stmt::UnresolvedLookupExprClass:
3460 case clang::Stmt::UnresolvedLookupExprClass:
34313461 emit_warning(c, stmt->getLocStart(), "TODO handle C UnresolvedLookupExprClass");
34323462 return ErrorUnexpected;
3433 case Stmt::UnresolvedMemberExprClass:
3463 case clang::Stmt::UnresolvedMemberExprClass:
34343464 emit_warning(c, stmt->getLocStart(), "TODO handle C UnresolvedMemberExprClass");
34353465 return ErrorUnexpected;
3436 case Stmt::PackExpansionExprClass:
3466 case clang::Stmt::PackExpansionExprClass:
34373467 emit_warning(c, stmt->getLocStart(), "TODO handle C PackExpansionExprClass");
34383468 return ErrorUnexpected;
3439 case Stmt::ParenListExprClass:
3469 case clang::Stmt::ParenListExprClass:
34403470 emit_warning(c, stmt->getLocStart(), "TODO handle C ParenListExprClass");
34413471 return ErrorUnexpected;
3442 case Stmt::PredefinedExprClass:
3472 case clang::Stmt::PredefinedExprClass:
34433473 emit_warning(c, stmt->getLocStart(), "TODO handle C PredefinedExprClass");
34443474 return ErrorUnexpected;
3445 case Stmt::PseudoObjectExprClass:
3475 case clang::Stmt::PseudoObjectExprClass:
34463476 emit_warning(c, stmt->getLocStart(), "TODO handle C PseudoObjectExprClass");
34473477 return ErrorUnexpected;
3448 case Stmt::ShuffleVectorExprClass:
3478 case clang::Stmt::ShuffleVectorExprClass:
34493479 emit_warning(c, stmt->getLocStart(), "TODO handle C ShuffleVectorExprClass");
34503480 return ErrorUnexpected;
3451 case Stmt::SizeOfPackExprClass:
3481 case clang::Stmt::SizeOfPackExprClass:
34523482 emit_warning(c, stmt->getLocStart(), "TODO handle C SizeOfPackExprClass");
34533483 return ErrorUnexpected;
3454 case Stmt::StmtExprClass:
3484 case clang::Stmt::StmtExprClass:
34553485 emit_warning(c, stmt->getLocStart(), "TODO handle C StmtExprClass");
34563486 return ErrorUnexpected;
3457 case Stmt::SubstNonTypeTemplateParmExprClass:
3487 case clang::Stmt::SubstNonTypeTemplateParmExprClass:
34583488 emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmExprClass");
34593489 return ErrorUnexpected;
3460 case Stmt::SubstNonTypeTemplateParmPackExprClass:
3490 case clang::Stmt::SubstNonTypeTemplateParmPackExprClass:
34613491 emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmPackExprClass");
34623492 return ErrorUnexpected;
3463 case Stmt::TypeTraitExprClass:
3493 case clang::Stmt::TypeTraitExprClass:
34643494 emit_warning(c, stmt->getLocStart(), "TODO handle C TypeTraitExprClass");
34653495 return ErrorUnexpected;
3466 case Stmt::TypoExprClass:
3496 case clang::Stmt::TypoExprClass:
34673497 emit_warning(c, stmt->getLocStart(), "TODO handle C TypoExprClass");
34683498 return ErrorUnexpected;
3469 case Stmt::VAArgExprClass:
3499 case clang::Stmt::VAArgExprClass:
34703500 emit_warning(c, stmt->getLocStart(), "TODO handle C VAArgExprClass");
34713501 return ErrorUnexpected;
3472 case Stmt::GotoStmtClass:
3502 case clang::Stmt::GotoStmtClass:
34733503 emit_warning(c, stmt->getLocStart(), "TODO handle C GotoStmtClass");
34743504 return ErrorUnexpected;
3475 case Stmt::IndirectGotoStmtClass:
3505 case clang::Stmt::IndirectGotoStmtClass:
34763506 emit_warning(c, stmt->getLocStart(), "TODO handle C IndirectGotoStmtClass");
34773507 return ErrorUnexpected;
3478 case Stmt::LabelStmtClass:
3508 case clang::Stmt::LabelStmtClass:
34793509 emit_warning(c, stmt->getLocStart(), "TODO handle C LabelStmtClass");
34803510 return ErrorUnexpected;
3481 case Stmt::MSDependentExistsStmtClass:
3511 case clang::Stmt::MSDependentExistsStmtClass:
34823512 emit_warning(c, stmt->getLocStart(), "TODO handle C MSDependentExistsStmtClass");
34833513 return ErrorUnexpected;
3484 case Stmt::OMPAtomicDirectiveClass:
3514 case clang::Stmt::OMPAtomicDirectiveClass:
34853515 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPAtomicDirectiveClass");
34863516 return ErrorUnexpected;
3487 case Stmt::OMPBarrierDirectiveClass:
3517 case clang::Stmt::OMPBarrierDirectiveClass:
34883518 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPBarrierDirectiveClass");
34893519 return ErrorUnexpected;
3490 case Stmt::OMPCancelDirectiveClass:
3520 case clang::Stmt::OMPCancelDirectiveClass:
34913521 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCancelDirectiveClass");
34923522 return ErrorUnexpected;
3493 case Stmt::OMPCancellationPointDirectiveClass:
3523 case clang::Stmt::OMPCancellationPointDirectiveClass:
34943524 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCancellationPointDirectiveClass");
34953525 return ErrorUnexpected;
3496 case Stmt::OMPCriticalDirectiveClass:
3526 case clang::Stmt::OMPCriticalDirectiveClass:
34973527 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCriticalDirectiveClass");
34983528 return ErrorUnexpected;
3499 case Stmt::OMPFlushDirectiveClass:
3529 case clang::Stmt::OMPFlushDirectiveClass:
35003530 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPFlushDirectiveClass");
35013531 return ErrorUnexpected;
3502 case Stmt::OMPDistributeDirectiveClass:
3532 case clang::Stmt::OMPDistributeDirectiveClass:
35033533 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeDirectiveClass");
35043534 return ErrorUnexpected;
3505 case Stmt::OMPDistributeParallelForDirectiveClass:
3535 case clang::Stmt::OMPDistributeParallelForDirectiveClass:
35063536 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeParallelForDirectiveClass");
35073537 return ErrorUnexpected;
3508 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
3538 case clang::Stmt::OMPDistributeParallelForSimdDirectiveClass:
35093539 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeParallelForSimdDirectiveClass");
35103540 return ErrorUnexpected;
3511 case Stmt::OMPDistributeSimdDirectiveClass:
3541 case clang::Stmt::OMPDistributeSimdDirectiveClass:
35123542 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeSimdDirectiveClass");
35133543 return ErrorUnexpected;
3514 case Stmt::OMPForDirectiveClass:
3544 case clang::Stmt::OMPForDirectiveClass:
35153545 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPForDirectiveClass");
35163546 return ErrorUnexpected;
3517 case Stmt::OMPForSimdDirectiveClass:
3547 case clang::Stmt::OMPForSimdDirectiveClass:
35183548 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPForSimdDirectiveClass");
35193549 return ErrorUnexpected;
3520 case Stmt::OMPParallelForDirectiveClass:
3550 case clang::Stmt::OMPParallelForDirectiveClass:
35213551 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelForDirectiveClass");
35223552 return ErrorUnexpected;
3523 case Stmt::OMPParallelForSimdDirectiveClass:
3553 case clang::Stmt::OMPParallelForSimdDirectiveClass:
35243554 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelForSimdDirectiveClass");
35253555 return ErrorUnexpected;
3526 case Stmt::OMPSimdDirectiveClass:
3556 case clang::Stmt::OMPSimdDirectiveClass:
35273557 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSimdDirectiveClass");
35283558 return ErrorUnexpected;
3529 case Stmt::OMPTargetParallelForSimdDirectiveClass:
3559 case clang::Stmt::OMPTargetParallelForSimdDirectiveClass:
35303560 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelForSimdDirectiveClass");
35313561 return ErrorUnexpected;
3532 case Stmt::OMPTargetSimdDirectiveClass:
3562 case clang::Stmt::OMPTargetSimdDirectiveClass:
35333563 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetSimdDirectiveClass");
35343564 return ErrorUnexpected;
3535 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
3565 case clang::Stmt::OMPTargetTeamsDistributeDirectiveClass:
35363566 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeDirectiveClass");
35373567 return ErrorUnexpected;
3538 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
3568 case clang::Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
35393569 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass");
35403570 return ErrorUnexpected;
3541 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
3571 case clang::Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
35423572 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass");
35433573 return ErrorUnexpected;
3544 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
3574 case clang::Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
35453575 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass");
35463576 return ErrorUnexpected;
3547 case Stmt::OMPTaskLoopDirectiveClass:
3577 case clang::Stmt::OMPTaskLoopDirectiveClass:
35483578 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskLoopDirectiveClass");
35493579 return ErrorUnexpected;
3550 case Stmt::OMPTaskLoopSimdDirectiveClass:
3580 case clang::Stmt::OMPTaskLoopSimdDirectiveClass:
35513581 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskLoopSimdDirectiveClass");
35523582 return ErrorUnexpected;
3553 case Stmt::OMPTeamsDistributeDirectiveClass:
3583 case clang::Stmt::OMPTeamsDistributeDirectiveClass:
35543584 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeDirectiveClass");
35553585 return ErrorUnexpected;
3556 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
3586 case clang::Stmt::OMPTeamsDistributeParallelForDirectiveClass:
35573587 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass");
35583588 return ErrorUnexpected;
3559 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
3589 case clang::Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
35603590 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass");
35613591 return ErrorUnexpected;
3562 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
3592 case clang::Stmt::OMPTeamsDistributeSimdDirectiveClass:
35633593 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeSimdDirectiveClass");
35643594 return ErrorUnexpected;
3565 case Stmt::OMPMasterDirectiveClass:
3595 case clang::Stmt::OMPMasterDirectiveClass:
35663596 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPMasterDirectiveClass");
35673597 return ErrorUnexpected;
3568 case Stmt::OMPOrderedDirectiveClass:
3598 case clang::Stmt::OMPOrderedDirectiveClass:
35693599 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPOrderedDirectiveClass");
35703600 return ErrorUnexpected;
3571 case Stmt::OMPParallelDirectiveClass:
3601 case clang::Stmt::OMPParallelDirectiveClass:
35723602 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelDirectiveClass");
35733603 return ErrorUnexpected;
3574 case Stmt::OMPParallelSectionsDirectiveClass:
3604 case clang::Stmt::OMPParallelSectionsDirectiveClass:
35753605 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelSectionsDirectiveClass");
35763606 return ErrorUnexpected;
3577 case Stmt::OMPSectionDirectiveClass:
3607 case clang::Stmt::OMPSectionDirectiveClass:
35783608 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSectionDirectiveClass");
35793609 return ErrorUnexpected;
3580 case Stmt::OMPSectionsDirectiveClass:
3610 case clang::Stmt::OMPSectionsDirectiveClass:
35813611 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSectionsDirectiveClass");
35823612 return ErrorUnexpected;
3583 case Stmt::OMPSingleDirectiveClass:
3613 case clang::Stmt::OMPSingleDirectiveClass:
35843614 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSingleDirectiveClass");
35853615 return ErrorUnexpected;
3586 case Stmt::OMPTargetDataDirectiveClass:
3616 case clang::Stmt::OMPTargetDataDirectiveClass:
35873617 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetDataDirectiveClass");
35883618 return ErrorUnexpected;
3589 case Stmt::OMPTargetDirectiveClass:
3619 case clang::Stmt::OMPTargetDirectiveClass:
35903620 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetDirectiveClass");
35913621 return ErrorUnexpected;
3592 case Stmt::OMPTargetEnterDataDirectiveClass:
3622 case clang::Stmt::OMPTargetEnterDataDirectiveClass:
35933623 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetEnterDataDirectiveClass");
35943624 return ErrorUnexpected;
3595 case Stmt::OMPTargetExitDataDirectiveClass:
3625 case clang::Stmt::OMPTargetExitDataDirectiveClass:
35963626 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetExitDataDirectiveClass");
35973627 return ErrorUnexpected;
3598 case Stmt::OMPTargetParallelDirectiveClass:
3628 case clang::Stmt::OMPTargetParallelDirectiveClass:
35993629 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelDirectiveClass");
36003630 return ErrorUnexpected;
3601 case Stmt::OMPTargetParallelForDirectiveClass:
3631 case clang::Stmt::OMPTargetParallelForDirectiveClass:
36023632 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelForDirectiveClass");
36033633 return ErrorUnexpected;
3604 case Stmt::OMPTargetTeamsDirectiveClass:
3634 case clang::Stmt::OMPTargetTeamsDirectiveClass:
36053635 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDirectiveClass");
36063636 return ErrorUnexpected;
3607 case Stmt::OMPTargetUpdateDirectiveClass:
3637 case clang::Stmt::OMPTargetUpdateDirectiveClass:
36083638 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetUpdateDirectiveClass");
36093639 return ErrorUnexpected;
3610 case Stmt::OMPTaskDirectiveClass:
3640 case clang::Stmt::OMPTaskDirectiveClass:
36113641 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskDirectiveClass");
36123642 return ErrorUnexpected;
3613 case Stmt::OMPTaskgroupDirectiveClass:
3643 case clang::Stmt::OMPTaskgroupDirectiveClass:
36143644 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskgroupDirectiveClass");
36153645 return ErrorUnexpected;
3616 case Stmt::OMPTaskwaitDirectiveClass:
3646 case clang::Stmt::OMPTaskwaitDirectiveClass:
36173647 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskwaitDirectiveClass");
36183648 return ErrorUnexpected;
3619 case Stmt::OMPTaskyieldDirectiveClass:
3649 case clang::Stmt::OMPTaskyieldDirectiveClass:
36203650 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskyieldDirectiveClass");
36213651 return ErrorUnexpected;
3622 case Stmt::OMPTeamsDirectiveClass:
3652 case clang::Stmt::OMPTeamsDirectiveClass:
36233653 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDirectiveClass");
36243654 return ErrorUnexpected;
3625 case Stmt::ObjCAtCatchStmtClass:
3655 case clang::Stmt::ObjCAtCatchStmtClass:
36263656 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtCatchStmtClass");
36273657 return ErrorUnexpected;
3628 case Stmt::ObjCAtFinallyStmtClass:
3658 case clang::Stmt::ObjCAtFinallyStmtClass:
36293659 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtFinallyStmtClass");
36303660 return ErrorUnexpected;
3631 case Stmt::ObjCAtSynchronizedStmtClass:
3661 case clang::Stmt::ObjCAtSynchronizedStmtClass:
36323662 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtSynchronizedStmtClass");
36333663 return ErrorUnexpected;
3634 case Stmt::ObjCAtThrowStmtClass:
3664 case clang::Stmt::ObjCAtThrowStmtClass:
36353665 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtThrowStmtClass");
36363666 return ErrorUnexpected;
3637 case Stmt::ObjCAtTryStmtClass:
3667 case clang::Stmt::ObjCAtTryStmtClass:
36383668 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtTryStmtClass");
36393669 return ErrorUnexpected;
3640 case Stmt::ObjCAutoreleasePoolStmtClass:
3670 case clang::Stmt::ObjCAutoreleasePoolStmtClass:
36413671 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAutoreleasePoolStmtClass");
36423672 return ErrorUnexpected;
3643 case Stmt::ObjCForCollectionStmtClass:
3673 case clang::Stmt::ObjCForCollectionStmtClass:
36443674 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCForCollectionStmtClass");
36453675 return ErrorUnexpected;
3646 case Stmt::SEHExceptStmtClass:
3676 case clang::Stmt::SEHExceptStmtClass:
36473677 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHExceptStmtClass");
36483678 return ErrorUnexpected;
3649 case Stmt::SEHFinallyStmtClass:
3679 case clang::Stmt::SEHFinallyStmtClass:
36503680 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHFinallyStmtClass");
36513681 return ErrorUnexpected;
3652 case Stmt::SEHLeaveStmtClass:
3682 case clang::Stmt::SEHLeaveStmtClass:
36533683 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHLeaveStmtClass");
36543684 return ErrorUnexpected;
3655 case Stmt::SEHTryStmtClass:
3685 case clang::Stmt::SEHTryStmtClass:
36563686 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHTryStmtClass");
36573687 return ErrorUnexpected;
3658 case Stmt::FixedPointLiteralClass:
3688 case clang::Stmt::FixedPointLiteralClass:
36593689 emit_warning(c, stmt->getLocStart(), "TODO handle C FixedPointLiteralClass");
36603690 return ErrorUnexpected;
36613691 }
......@@ -3663,7 +3693,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,
36633693}
36643694
36653695// 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,
36673697 TransLRValue lrval)
36683698{
36693699 AstNode *result_node;
......@@ -3676,7 +3706,7 @@ static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope
36763706
36773707// Statements have no result and no concept of L or R value.
36783708// 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) {
36803710 TransScope *child_scope;
36813711 if (trans_stmt_extra(c, scope, stmt, ResultUsedNo, TransRValue, out_node, &child_scope, nullptr)) {
36823712 return nullptr;
......@@ -3684,7 +3714,7 @@ static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, A
36843714 return child_scope;
36853715}
36863716
3687static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
3717static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {
36883718 Buf *fn_name = buf_create_from_str(decl_name(fn_decl));
36893719
36903720 if (get_global(c, fn_name)) {
......@@ -3701,13 +3731,13 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
37013731 proto_node->data.fn_proto.name = fn_name;
37023732 proto_node->data.fn_proto.is_extern = !fn_decl->hasBody();
37033733
3704 StorageClass sc = fn_decl->getStorageClass();
3705 if (sc == SC_None) {
3734 clang::StorageClass sc = fn_decl->getStorageClass();
3735 if (sc == clang::SC_None) {
37063736 proto_node->data.fn_proto.visib_mod = c->visib_mod;
37073737 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) {
37093739 proto_node->data.fn_proto.visib_mod = c->visib_mod;
3710 } else if (sc == SC_PrivateExtern) {
3740 } else if (sc == clang::SC_PrivateExtern) {
37113741 emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern");
37123742 return;
37133743 } else {
......@@ -3719,7 +3749,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
37193749
37203750 for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
37213751 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);
37233753 const char *name = decl_name(param);
37243754
37253755 Buf *proto_param_name;
......@@ -3746,7 +3776,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
37463776
37473777 // actual function definition with body
37483778 c->ptr_params.clear();
3749 Stmt *body = fn_decl->getBody();
3779 clang::Stmt *body = fn_decl->getBody();
37503780 AstNode *actual_body_node;
37513781 TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node);
37523782 if (result_scope == nullptr) {
......@@ -3788,19 +3818,19 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
37883818 add_top_level_decl(c, fn_def_node->data.fn_def.fn_proto->data.fn_proto.name, fn_def_node);
37893819}
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) {
37923822 AstNode *node = trans_create_node_symbol_str(c, primitive_name);
37933823 c->decl_table.put(typedef_decl, node);
37943824 return node;
37953825}
37963826
3797static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) {
3827static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl) {
37983828 auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());
37993829 if (existing_entry) {
38003830 return existing_entry->value;
38013831 }
38023832
3803 QualType child_qt = typedef_decl->getUnderlyingType();
3833 clang::QualType child_qt = typedef_decl->getUnderlyingType();
38043834 Buf *type_name = buf_create_from_str(decl_name(typedef_decl));
38053835
38063836 if (buf_eql_str(type_name, "uint8_t")) {
......@@ -3849,7 +3879,7 @@ static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_
38493879 return symbol_node;
38503880}
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,
38533883 Buf *full_type_name, Buf *bare_name)
38543884{
38553885 AstNode *opaque_node = trans_create_node_opaque(c);
......@@ -3864,7 +3894,7 @@ struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl,
38643894 return symbol_node;
38653895}
38663896
3867static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
3897static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl) {
38683898 auto existing_entry = c->decl_table.maybe_get((void*)enum_decl->getCanonicalDecl());
38693899 if (existing_entry) {
38703900 return existing_entry->value;
......@@ -3875,7 +3905,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
38753905 Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
38763906 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();
38793909 if (!enum_def) {
38803910 return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name);
38813911 }
......@@ -3887,7 +3917,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
38873917 it_end = enum_def->enumerator_end();
38883918 it != it_end; ++it, field_count += 1)
38893919 {
3890 const EnumConstantDecl *enum_const = *it;
3920 const clang::EnumConstantDecl *enum_const = *it;
38913921 if (enum_const->getInitExpr()) {
38923922 pure_enum = false;
38933923 }
......@@ -3901,8 +3931,8 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
39013931 // TODO only emit this tag type if the enum tag type is not the default.
39023932 // I don't know what the default is, need to figure out how clang is deciding.
39033933 // it appears to at least be different across gcc/msvc
3904 if (!c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::UInt) &&
3905 !c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::Int))
3934 if (!c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::UInt) &&
3935 !c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::Int))
39063936 {
39073937 enum_node->data.container_decl.init_arg_expr = tag_int_type;
39083938 }
......@@ -3912,7 +3942,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
39123942 it_end = enum_def->enumerator_end();
39133943 it != it_end; ++it, i += 1)
39143944 {
3915 const EnumConstantDecl *enum_const = *it;
3945 const clang::EnumConstantDecl *enum_const = *it;
39163946
39173947 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
39183948 Buf *field_name;
......@@ -3953,7 +3983,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
39533983 }
39543984}
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,
39573987 Buf *full_type_name, Buf *bare_name)
39583988{
39593989 AstNode *opaque_node = trans_create_node_opaque(c);
......@@ -3968,7 +3998,7 @@ static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_dec
39683998 return symbol_node;
39693999}
39704000
3971static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
4001static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl) {
39724002 auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl());
39734003 if (existing_entry) {
39744004 return existing_entry->value;
......@@ -3994,7 +4024,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
39944024 Buf *full_type_name = (bare_name == nullptr) ?
39954025 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();
39984028 if (record_def == nullptr) {
39994029 return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
40004030 }
......@@ -4005,7 +4035,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
40054035 it_end = record_def->field_end();
40064036 it != it_end; ++it, field_count += 1)
40074037 {
4008 const FieldDecl *field_decl = *it;
4038 const clang::FieldDecl *field_decl = *it;
40094039
40104040 if (field_decl->isBitField()) {
40114041 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) {
40354065 it_end = record_def->field_end();
40364066 it != it_end; ++it, i += 1)
40374067 {
4038 const FieldDecl *field_decl = *it;
4068 const clang::FieldDecl *field_decl = *it;
40394069
40404070 AstNode *field_node = trans_create_node(c, NodeTypeStructField);
40414071 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) {
40624092 }
40634093}
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) {
40664096 switch (ap_value->getKind()) {
4067 case APValue::Int:
4097 case clang::APValue::Int:
40684098 return trans_create_node_apint(c, ap_value->getInt());
4069 case APValue::Uninitialized:
4099 case clang::APValue::Uninitialized:
40704100 return trans_create_node(c, NodeTypeUndefinedLiteral);
4071 case APValue::Array: {
4101 case clang::APValue::Array: {
40724102 emit_warning(c, source_loc, "TODO add a test case for this code");
40734103
40744104 unsigned init_count = ap_value->getArrayInitializedElts();
......@@ -4076,13 +4106,16 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const
40764106 unsigned leftover_count = all_count - init_count;
40774107 AstNode *init_node = trans_create_node(c, NodeTypeContainerInitExpr);
40784108 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 }
40794112 init_node->data.container_init_expr.type = arr_type_node;
40804113 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
40844117 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);
40864119 AstNode *elem_node = trans_ap_value(c, &elem_ap_val, child_qt, source_loc);
40874120 if (elem_node == nullptr)
40884121 return nullptr;
......@@ -4092,15 +4125,19 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const
40924125 return init_node;
40934126 }
40944127
4095 APValue &filler_ap_val = ap_value->getArrayFiller();
4128 clang::APValue &filler_ap_val = ap_value->getArrayFiller();
40964129 AstNode *filler_node = trans_ap_value(c, &filler_ap_val, child_qt, source_loc);
40974130 if (filler_node == nullptr)
40984131 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
41004137 AstNode *filler_arr_1 = trans_create_node(c, NodeTypeContainerInitExpr);
4101 init_node->data.container_init_expr.type = arr_type_node;
4102 init_node->data.container_init_expr.kind = ContainerInitKindArray;
4103 init_node->data.container_init_expr.entries.append(filler_node);
4138 filler_arr_1->data.container_init_expr.type = filler_arr_type;
4139 filler_arr_1->data.container_init_expr.kind = ContainerInitKindArray;
4140 filler_arr_1->data.container_init_expr.entries.append(filler_node);
41044141
41054142 AstNode *rhs_node;
41064143 if (leftover_count == 1) {
......@@ -4110,62 +4147,66 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const
41104147 rhs_node = trans_create_node_bin_op(c, filler_arr_1, BinOpTypeArrayMult, amt_node);
41114148 }
41124149
4150 if (init_count == 0) {
4151 return rhs_node;
4152 }
4153
41134154 return trans_create_node_bin_op(c, init_node, BinOpTypeArrayCat, rhs_node);
41144155 }
4115 case APValue::LValue: {
4116 const APValue::LValueBase lval_base = ap_value->getLValueBase();
4117 if (const Expr *expr = lval_base.dyn_cast<const Expr *>()) {
4156 case clang::APValue::LValue: {
4157 const clang::APValue::LValueBase lval_base = ap_value->getLValueBase();
4158 if (const clang::Expr *expr = lval_base.dyn_cast<const clang::Expr *>()) {
41184159 return trans_expr(c, ResultUsedYes, &c->global_scope->base, expr, TransRValue);
41194160 }
4120 //const ValueDecl *value_decl = lval_base.get<const ValueDecl *>();
4121 emit_warning(c, source_loc, "TODO handle initializer LValue ValueDecl");
4161 //const clang::ValueDecl *value_decl = lval_base.get<const clang::ValueDecl *>();
4162 emit_warning(c, source_loc, "TODO handle initializer LValue clang::ValueDecl");
41224163 return nullptr;
41234164 }
4124 case APValue::Float:
4165 case clang::APValue::Float:
41254166 emit_warning(c, source_loc, "unsupported initializer value kind: Float");
41264167 return nullptr;
4127 case APValue::ComplexInt:
4168 case clang::APValue::ComplexInt:
41284169 emit_warning(c, source_loc, "unsupported initializer value kind: ComplexInt");
41294170 return nullptr;
4130 case APValue::ComplexFloat:
4171 case clang::APValue::ComplexFloat:
41314172 emit_warning(c, source_loc, "unsupported initializer value kind: ComplexFloat");
41324173 return nullptr;
4133 case APValue::Vector:
4174 case clang::APValue::Vector:
41344175 emit_warning(c, source_loc, "unsupported initializer value kind: Vector");
41354176 return nullptr;
4136 case APValue::Struct:
4177 case clang::APValue::Struct:
41374178 emit_warning(c, source_loc, "unsupported initializer value kind: Struct");
41384179 return nullptr;
4139 case APValue::Union:
4180 case clang::APValue::Union:
41404181 emit_warning(c, source_loc, "unsupported initializer value kind: Union");
41414182 return nullptr;
4142 case APValue::MemberPointer:
4183 case clang::APValue::MemberPointer:
41434184 emit_warning(c, source_loc, "unsupported initializer value kind: MemberPointer");
41444185 return nullptr;
4145 case APValue::AddrLabelDiff:
4186 case clang::APValue::AddrLabelDiff:
41464187 emit_warning(c, source_loc, "unsupported initializer value kind: AddrLabelDiff");
41474188 return nullptr;
41484189 }
41494190 zig_unreachable();
41504191}
41514192
4152static void visit_var_decl(Context *c, const VarDecl *var_decl) {
4193static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) {
41534194 Buf *name = buf_create_from_str(decl_name(var_decl));
41544195
41554196 switch (var_decl->getTLSKind()) {
4156 case VarDecl::TLS_None:
4197 case clang::VarDecl::TLS_None:
41574198 break;
4158 case VarDecl::TLS_Static:
4199 case clang::VarDecl::TLS_Static:
41594200 emit_warning(c, var_decl->getLocation(),
41604201 "ignoring variable '%s' - static thread local storage", buf_ptr(name));
41614202 return;
4162 case VarDecl::TLS_Dynamic:
4203 case clang::VarDecl::TLS_Dynamic:
41634204 emit_warning(c, var_decl->getLocation(),
41644205 "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name));
41654206 return;
41664207 }
41674208
4168 QualType qt = var_decl->getType();
4209 clang::QualType qt = var_decl->getType();
41694210 AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation());
41704211 if (var_type == nullptr) {
41714212 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) {
41794220 if (is_static && !is_extern) {
41804221 AstNode *init_node;
41814222 if (var_decl->hasInit()) {
4182 APValue *ap_value = var_decl->evaluateValue();
4223 clang::APValue *ap_value = var_decl->evaluateValue();
41834224 if (ap_value == nullptr) {
41844225 emit_warning(c, var_decl->getLocation(),
41854226 "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) {
42094250 return;
42104251}
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);
42134255 Context *c = (Context*)context;
42144256
42154257 switch (decl->getKind()) {
4216 case Decl::Function:
4217 visit_fn_decl(c, static_cast<const FunctionDecl*>(decl));
4258 case clang::Decl::Function:
4259 visit_fn_decl(c, static_cast<const clang::FunctionDecl*>(decl));
42184260 break;
4219 case Decl::Typedef:
4220 resolve_typedef_decl(c, static_cast<const TypedefNameDecl *>(decl));
4261 case clang::Decl::Typedef:
4262 resolve_typedef_decl(c, static_cast<const clang::TypedefNameDecl *>(decl));
42214263 break;
4222 case Decl::Enum:
4223 resolve_enum_decl(c, static_cast<const EnumDecl *>(decl));
4264 case clang::Decl::Enum:
4265 resolve_enum_decl(c, static_cast<const clang::EnumDecl *>(decl));
42244266 break;
4225 case Decl::Record:
4226 resolve_record_decl(c, static_cast<const RecordDecl *>(decl));
4267 case clang::Decl::Record:
4268 resolve_record_decl(c, static_cast<const clang::RecordDecl *>(decl));
42274269 break;
4228 case Decl::Var:
4229 visit_var_decl(c, static_cast<const VarDecl *>(decl));
4270 case clang::Decl::Var:
4271 visit_var_decl(c, static_cast<const clang::VarDecl *>(decl));
42304272 break;
42314273 default:
42324274 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
45684610 } else if (first_tok->id == CTokIdAsterisk) {
45694611 *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);
45724614 } else {
45734615 return node;
45744616 }
......@@ -4647,24 +4689,25 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch
46474689 c->macro_table.put(name, result_node);
46484690}
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);
46514694 CTokenize ctok = {{0}};
46524695
46534696 // TODO if we see #undef, delete it from the table
46544697
4655 for (PreprocessedEntity *entity : unit.getLocalPreprocessingEntities()) {
4698 for (clang::PreprocessedEntity *entity : unit->getLocalPreprocessingEntities()) {
46564699 switch (entity->getKind()) {
4657 case PreprocessedEntity::InvalidKind:
4658 case PreprocessedEntity::InclusionDirectiveKind:
4659 case PreprocessedEntity::MacroExpansionKind:
4700 case clang::PreprocessedEntity::InvalidKind:
4701 case clang::PreprocessedEntity::InclusionDirectiveKind:
4702 case clang::PreprocessedEntity::MacroExpansionKind:
46604703 continue;
4661 case PreprocessedEntity::MacroDefinitionKind:
4704 case clang::PreprocessedEntity::MacroDefinitionKind:
46624705 {
4663 MacroDefinitionRecord *macro = static_cast<MacroDefinitionRecord *>(entity);
4706 clang::MacroDefinitionRecord *macro = static_cast<clang::MacroDefinitionRecord *>(entity);
46644707 const char *raw_name = macro->getName()->getNameStart();
4665 SourceRange range = macro->getSourceRange();
4666 SourceLocation begin_loc = range.getBegin();
4667 SourceLocation end_loc = range.getEnd();
4708 clang::SourceRange range = macro->getSourceRange();
4709 clang::SourceLocation begin_loc = range.getBegin();
4710 clang::SourceLocation end_loc = range.getEnd();
46684711
46694712 if (begin_loc == end_loc) {
46704713 // this means it is a macro without a value
......@@ -4676,7 +4719,7 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) {
46764719 continue;
46774720 }
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));
46804723 process_macro(c, &ctok, name, begin_c);
46814724 }
46824725 }
......@@ -4749,8 +4792,10 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
47494792 clang_argv.append("-isystem");
47504793 clang_argv.append(buf_ptr(codegen->zig_c_headers_dir));
47514794
4752 clang_argv.append("-isystem");
4753 clang_argv.append(buf_ptr(codegen->libc_include_dir));
4795 if (codegen->libc_include_dir != nullptr) {
4796 clang_argv.append("-isystem");
4797 clang_argv.append(buf_ptr(codegen->libc_include_dir));
4798 }
47544799
47554800 // windows c runtime requires -D_DEBUG if using debug libraries
47564801 if (codegen->build_mode == BuildModeDebug) {
......@@ -4776,12 +4821,20 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
47764821
47774822 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
47794832 // to make the [start...end] argument work
47804833 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
47864839 bool only_local_decls = true;
47874840 bool capture_diagnostics = true;
......@@ -4790,13 +4843,13 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
47904843 bool single_file_parse = false;
47914844 bool for_serialization = false;
47924845 const char *resources_path = buf_ptr(codegen->zig_c_headers_dir);
4793 std::unique_ptr<ASTUnit> err_unit;
4794 std::unique_ptr<ASTUnit> ast_unit(ASTUnit::LoadFromCommandLine(
4846 std::unique_ptr<clang::ASTUnit> err_unit;
4847 ZigClangASTUnit *ast_unit = reinterpret_cast<ZigClangASTUnit *>(clang::ASTUnit::LoadFromCommandLine(
47954848 &clang_argv.at(0), &clang_argv.last(),
47964849 pch_container_ops, diags, resources_path,
4797 only_local_decls, capture_diagnostics, None, true, 0, TU_Complete,
4798 false, false, allow_pch_with_compiler_errors, SkipFunctionBodiesScope::None,
4799 single_file_parse, user_files_are_volatile, for_serialization, None, &err_unit,
4850 only_local_decls, capture_diagnostics, clang::None, true, 0, clang::TU_Complete,
4851 false, false, allow_pch_with_compiler_errors, clang::SkipFunctionBodiesScope::None,
4852 single_file_parse, user_files_are_volatile, for_serialization, clang::None, &err_unit,
48004853 nullptr));
48014854
48024855 // Early failures in LoadFromCommandLine may return with ErrUnit unset.
......@@ -4806,29 +4859,29 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
48064859
48074860 if (diags->getClient()->getNumErrors() > 0) {
48084861 if (ast_unit) {
4809 err_unit = std::move(ast_unit);
4862 err_unit = std::unique_ptr<clang::ASTUnit>(reinterpret_cast<clang::ASTUnit *>(ast_unit));
48104863 }
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(),
48134866 it_end = err_unit->stored_diag_end();
48144867 it != it_end; ++it)
48154868 {
48164869 switch (it->getLevel()) {
4817 case DiagnosticsEngine::Ignored:
4818 case DiagnosticsEngine::Note:
4819 case DiagnosticsEngine::Remark:
4820 case DiagnosticsEngine::Warning:
4870 case clang::DiagnosticsEngine::Ignored:
4871 case clang::DiagnosticsEngine::Note:
4872 case clang::DiagnosticsEngine::Remark:
4873 case clang::DiagnosticsEngine::Warning:
48214874 continue;
4822 case DiagnosticsEngine::Error:
4823 case DiagnosticsEngine::Fatal:
4875 case clang::DiagnosticsEngine::Error:
4876 case clang::DiagnosticsEngine::Fatal:
48244877 break;
48254878 }
48264879 StringRef msg_str_ref = it->getMessage();
48274880 Buf *msg = string_ref_to_buf(msg_str_ref);
4828 FullSourceLoc fsl = it->getLocation();
4881 clang::FullSourceLoc fsl = it->getLocation();
48294882 if (fsl.hasManager()) {
4830 FileID file_id = fsl.getFileID();
4831 StringRef filename = fsl.getManager().getFilename(fsl);
4883 clang::FileID file_id = fsl.getFileID();
4884 clang::StringRef filename = fsl.getManager().getFilename(fsl);
48324885 unsigned line = fsl.getSpellingLineNumber() - 1;
48334886 unsigned column = fsl.getSpellingColumnNumber() - 1;
48344887 unsigned offset = fsl.getManager().getFileOffset(fsl);
......@@ -4853,14 +4906,14 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
48534906 return ErrorCCompileErrors;
48544907 }
48554908
4856 c->ctx = &ast_unit->getASTContext();
4857 c->source_manager = &ast_unit->getSourceManager();
4909 c->ctx = ZigClangASTUnit_getASTContext(ast_unit);
4910 c->source_manager = ZigClangASTUnit_getSourceManager(ast_unit);
48584911 c->root = trans_create_node(c, NodeTypeContainerDecl);
48594912 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
48654918 render_macros(c);
48664919 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
263263 return reinterpret_cast<ZigLLVMDIType*>(di_type);
264264}
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
266279ZigLLVMDIType *ZigLLVMCreateDebugArrayType(ZigLLVMDIBuilder *dibuilder, uint64_t size_in_bits,
267280 uint64_t align_in_bits, ZigLLVMDIType *elem_type, int elem_count)
268281{
......@@ -605,7 +618,7 @@ ZigLLVMDISubprogram *ZigLLVMCreateFunction(ZigLLVMDIBuilder *dibuilder, ZigLLVMD
605618 reinterpret_cast<DIFile*>(file),
606619 lineno,
607620 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,
609622 nullptr,
610623 reinterpret_cast<DISubprogram *>(decl_subprogram));
611624 return reinterpret_cast<ZigLLVMDISubprogram*>(result);
src/zig_llvm.h+3
......@@ -191,6 +191,9 @@ ZIG_EXTERN_C struct ZigLLVMDISubprogram *ZigLLVMCreateFunction(struct ZigLLVMDIB
191191 unsigned lineno, struct ZigLLVMDIType *fn_di_type, bool is_local_to_unit, bool is_definition,
192192 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
194197ZIG_EXTERN_C void ZigLLVMFnSetSubprogram(LLVMValueRef fn, struct ZigLLVMDISubprogram *subprogram);
195198
196199ZIG_EXTERN_C void ZigLLVMDIBuilderFinalize(struct ZigLLVMDIBuilder *dibuilder);
std/array_list.zig+63-52
......@@ -1,7 +1,7 @@
11const std = @import("index.zig");
22const debug = std.debug;
33const assert = debug.assert;
4const assertError = debug.assertError;
4const testing = std.testing;
55const mem = std.mem;
66const Allocator = mem.Allocator;
77
......@@ -212,8 +212,8 @@ test "std.ArrayList.init" {
212212 var list = ArrayList(i32).init(allocator);
213213 defer list.deinit();
214214
215 assert(list.count() == 0);
216 assert(list.capacity() == 0);
215 testing.expect(list.count() == 0);
216 testing.expect(list.capacity() == 0);
217217}
218218
219219test "std.ArrayList.basic" {
......@@ -224,7 +224,7 @@ test "std.ArrayList.basic" {
224224 defer list.deinit();
225225
226226 // 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
229229 {
230230 var i: usize = 0;
......@@ -236,44 +236,44 @@ test "std.ArrayList.basic" {
236236 {
237237 var i: usize = 0;
238238 while (i < 10) : (i += 1) {
239 assert(list.items[i] == @intCast(i32, i + 1));
239 testing.expect(list.items[i] == @intCast(i32, i + 1));
240240 }
241241 }
242242
243243 for (list.toSlice()) |v, i| {
244 assert(v == @intCast(i32, i + 1));
244 testing.expect(v == @intCast(i32, i + 1));
245245 }
246246
247247 for (list.toSliceConst()) |v, i| {
248 assert(v == @intCast(i32, i + 1));
248 testing.expect(v == @intCast(i32, i + 1));
249249 }
250250
251 assert(list.pop() == 10);
252 assert(list.len == 9);
251 testing.expect(list.pop() == 10);
252 testing.expect(list.len == 9);
253253
254254 list.appendSlice([]const i32{
255255 1,
256256 2,
257257 3,
258258 }) catch unreachable;
259 assert(list.len == 12);
260 assert(list.pop() == 3);
261 assert(list.pop() == 2);
262 assert(list.pop() == 1);
263 assert(list.len == 9);
259 testing.expect(list.len == 12);
260 testing.expect(list.pop() == 3);
261 testing.expect(list.pop() == 2);
262 testing.expect(list.pop() == 1);
263 testing.expect(list.len == 9);
264264
265265 list.appendSlice([]const i32{}) catch unreachable;
266 assert(list.len == 9);
266 testing.expect(list.len == 9);
267267
268268 // can only set on indices < self.len
269269 list.set(7, 33);
270270 list.set(8, 42);
271271
272 assertError(list.setOrError(9, 99), error.OutOfBounds);
273 assertError(list.setOrError(10, 123), error.OutOfBounds);
272 testing.expectError(error.OutOfBounds, list.setOrError(9, 99));
273 testing.expectError(error.OutOfBounds, list.setOrError(10, 123));
274274
275 assert(list.pop() == 42);
276 assert(list.pop() == 33);
275 testing.expect(list.pop() == 42);
276 testing.expect(list.pop() == 33);
277277}
278278
279279test "std.ArrayList.swapRemove" {
......@@ -289,18 +289,18 @@ test "std.ArrayList.swapRemove" {
289289 try list.append(7);
290290
291291 //remove from middle
292 assert(list.swapRemove(3) == 4);
293 assert(list.at(3) == 7);
294 assert(list.len == 6);
292 testing.expect(list.swapRemove(3) == 4);
293 testing.expect(list.at(3) == 7);
294 testing.expect(list.len == 6);
295295
296296 //remove from end
297 assert(list.swapRemove(5) == 6);
298 assert(list.len == 5);
297 testing.expect(list.swapRemove(5) == 6);
298 testing.expect(list.len == 5);
299299
300300 //remove from front
301 assert(list.swapRemove(0) == 1);
302 assert(list.at(0) == 5);
303 assert(list.len == 4);
301 testing.expect(list.swapRemove(0) == 1);
302 testing.expect(list.at(0) == 5);
303 testing.expect(list.len == 4);
304304}
305305
306306test "std.ArrayList.swapRemoveOrError" {
......@@ -308,27 +308,27 @@ test "std.ArrayList.swapRemoveOrError" {
308308 defer list.deinit();
309309
310310 // Test just after initialization
311 assertError(list.swapRemoveOrError(0), error.OutOfBounds);
311 testing.expectError(error.OutOfBounds, list.swapRemoveOrError(0));
312312
313313 // Test after adding one item and remote it
314314 try list.append(1);
315 assert((try list.swapRemoveOrError(0)) == 1);
316 assertError(list.swapRemoveOrError(0), error.OutOfBounds);
315 testing.expect((try list.swapRemoveOrError(0)) == 1);
316 testing.expectError(error.OutOfBounds, list.swapRemoveOrError(0));
317317
318318 // Test after adding two items and remote both
319319 try list.append(1);
320320 try list.append(2);
321 assert((try list.swapRemoveOrError(1)) == 2);
322 assert((try list.swapRemoveOrError(0)) == 1);
323 assertError(list.swapRemoveOrError(0), error.OutOfBounds);
321 testing.expect((try list.swapRemoveOrError(1)) == 2);
322 testing.expect((try list.swapRemoveOrError(0)) == 1);
323 testing.expectError(error.OutOfBounds, list.swapRemoveOrError(0));
324324
325325 // Test out of bounds with one item
326326 try list.append(1);
327 assertError(list.swapRemoveOrError(1), error.OutOfBounds);
327 testing.expectError(error.OutOfBounds, list.swapRemoveOrError(1));
328328
329329 // Test out of bounds with two items
330330 try list.append(2);
331 assertError(list.swapRemoveOrError(2), error.OutOfBounds);
331 testing.expectError(error.OutOfBounds, list.swapRemoveOrError(2));
332332}
333333
334334test "std.ArrayList.iterator" {
......@@ -342,22 +342,22 @@ test "std.ArrayList.iterator" {
342342 var count: i32 = 0;
343343 var it = list.iterator();
344344 while (it.next()) |next| {
345 assert(next == count + 1);
345 testing.expect(next == count + 1);
346346 count += 1;
347347 }
348348
349 assert(count == 3);
350 assert(it.next() == null);
349 testing.expect(count == 3);
350 testing.expect(it.next() == null);
351351 it.reset();
352352 count = 0;
353353 while (it.next()) |next| {
354 assert(next == count + 1);
354 testing.expect(next == count + 1);
355355 count += 1;
356356 if (count == 2) break;
357357 }
358358
359359 it.reset();
360 assert(it.next().? == 1);
360 testing.expect(it.next().? == 1);
361361}
362362
363363test "std.ArrayList.insert" {
......@@ -368,10 +368,10 @@ test "std.ArrayList.insert" {
368368 try list.append(2);
369369 try list.append(3);
370370 try list.insert(0, 5);
371 assert(list.items[0] == 5);
372 assert(list.items[1] == 1);
373 assert(list.items[2] == 2);
374 assert(list.items[3] == 3);
371 testing.expect(list.items[0] == 5);
372 testing.expect(list.items[1] == 1);
373 testing.expect(list.items[2] == 2);
374 testing.expect(list.items[3] == 3);
375375}
376376
377377test "std.ArrayList.insertSlice" {
......@@ -386,15 +386,26 @@ test "std.ArrayList.insertSlice" {
386386 9,
387387 8,
388388 });
389 assert(list.items[0] == 1);
390 assert(list.items[1] == 9);
391 assert(list.items[2] == 8);
392 assert(list.items[3] == 2);
393 assert(list.items[4] == 3);
394 assert(list.items[5] == 4);
389 testing.expect(list.items[0] == 1);
390 testing.expect(list.items[1] == 9);
391 testing.expect(list.items[2] == 8);
392 testing.expect(list.items[3] == 2);
393 testing.expect(list.items[4] == 3);
394 testing.expect(list.items[5] == 4);
395395
396396 const items = []const i32{1};
397397 try list.insertSlice(0, items[0..0]);
398 assert(list.len == 6);
399 assert(list.items[0] == 1);
398 testing.expect(list.len == 6);
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);
400411}
std/atomic/queue.zig+42-24
......@@ -3,6 +3,7 @@ const builtin = @import("builtin");
33const AtomicOrder = builtin.AtomicOrder;
44const AtomicRmwOp = builtin.AtomicRmwOp;
55const assert = std.debug.assert;
6const expect = std.testing.expect;
67
78/// Many producer, many consumer, non-allocating, thread-safe.
89/// Uses a mutex to protect access.
......@@ -170,20 +171,36 @@ test "std.atomic.Queue" {
170171 .get_count = 0,
171172 };
172173
173 var putters: [put_thread_count]*std.os.Thread = undefined;
174 for (putters) |*t| {
175 t.* = try std.os.spawnThread(&context, startPuts);
176 }
177 var getters: [put_thread_count]*std.os.Thread = undefined;
178 for (getters) |*t| {
179 t.* = try std.os.spawnThread(&context, startGets);
180 }
174 if (builtin.single_threaded) {
175 {
176 var i: usize = 0;
177 while (i < put_thread_count) : (i += 1) {
178 expect(startPuts(&context) == 0);
179 }
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|
183 t.wait();
184 _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
185 for (getters) |t|
186 t.wait();
198 for (putters) |t|
199 t.wait();
200 _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
201 for (getters) |t|
202 t.wait();
203 }
187204
188205 if (context.put_sum != context.get_sum) {
189206 std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum);
......@@ -205,11 +222,12 @@ fn startPuts(ctx: *Context) u8 {
205222 while (put_count != 0) : (put_count -= 1) {
206223 std.os.time.sleep(1); // let the os scheduler be our fuzz
207224 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{
209227 .prev = undefined,
210228 .next = undefined,
211229 .data = x,
212 }) catch unreachable;
230 };
213231 ctx.queue.put(node);
214232 _ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst);
215233 }
......@@ -247,7 +265,7 @@ test "std.atomic.Queue single-threaded" {
247265 };
248266 queue.put(&node_1);
249267
250 assert(queue.get().?.data == 0);
268 expect(queue.get().?.data == 0);
251269
252270 var node_2 = Queue(i32).Node{
253271 .data = 2,
......@@ -263,9 +281,9 @@ test "std.atomic.Queue single-threaded" {
263281 };
264282 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
270288 var node_4 = Queue(i32).Node{
271289 .data = 4,
......@@ -274,12 +292,12 @@ test "std.atomic.Queue single-threaded" {
274292 };
275293 queue.put(&node_4);
276294
277 assert(queue.get().?.data == 3);
295 expect(queue.get().?.data == 3);
278296 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);
283301}
284302
285303test "std.atomic.Queue dump" {
......@@ -294,7 +312,7 @@ test "std.atomic.Queue dump" {
294312 // Test empty stream
295313 sos.reset();
296314 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],
298316 \\head: (null)
299317 \\tail: (null)
300318 \\
......@@ -318,7 +336,7 @@ test "std.atomic.Queue dump" {
318336 \\ (null)
319337 \\
320338 , @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
323341 // Test a stream with two elements
324342 var node_1 = Queue(i32).Node{
......@@ -339,5 +357,5 @@ test "std.atomic.Queue dump" {
339357 \\ (null)
340358 \\
341359 , @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));
343361}
std/atomic/stack.zig+60-28
......@@ -1,13 +1,17 @@
11const assert = std.debug.assert;
22const builtin = @import("builtin");
33const AtomicOrder = builtin.AtomicOrder;
4const expect = std.testing.expect;
45
56/// Many reader, many writer, non-allocating, thread-safe
67/// Uses a spinlock to protect push() and pop()
8/// When building in single threaded mode, this is a simple linked list.
79pub fn Stack(comptime T: type) type {
810 return struct {
911 root: ?*Node,
10 lock: u8,
12 lock: @typeOf(lock_init),
13
14 const lock_init = if (builtin.single_threaded) {} else u8(0);
1115
1216 pub const Self = @This();
1317
......@@ -19,7 +23,7 @@ pub fn Stack(comptime T: type) type {
1923 pub fn init() Self {
2024 return Self{
2125 .root = null,
22 .lock = 0,
26 .lock = lock_init,
2327 };
2428 }
2529
......@@ -31,20 +35,31 @@ pub fn Stack(comptime T: type) type {
3135 }
3236
3337 pub fn push(self: *Self, node: *Node) void {
34 while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
35 defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
36
37 node.next = self.root;
38 self.root = node;
38 if (builtin.single_threaded) {
39 node.next = self.root;
40 self.root = node;
41 } else {
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 }
3948 }
4049
4150 pub fn pop(self: *Self) ?*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 const root = self.root orelse return null;
46 self.root = root.next;
47 return root;
51 if (builtin.single_threaded) {
52 const root = self.root orelse return null;
53 self.root = root.next;
54 return root;
55 } else {
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 }
4863 }
4964
5065 pub fn isEmpty(self: *Self) bool {
......@@ -90,20 +105,36 @@ test "std.atomic.stack" {
90105 .get_count = 0,
91106 };
92107
93 var putters: [put_thread_count]*std.os.Thread = undefined;
94 for (putters) |*t| {
95 t.* = try std.os.spawnThread(&context, startPuts);
96 }
97 var getters: [put_thread_count]*std.os.Thread = undefined;
98 for (getters) |*t| {
99 t.* = try std.os.spawnThread(&context, startGets);
100 }
108 if (builtin.single_threaded) {
109 {
110 var i: usize = 0;
111 while (i < put_thread_count) : (i += 1) {
112 expect(startPuts(&context) == 0);
113 }
114 }
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|
103 t.wait();
104 _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
105 for (getters) |t|
106 t.wait();
132 for (putters) |t|
133 t.wait();
134 _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
135 for (getters) |t|
136 t.wait();
137 }
107138
108139 if (context.put_sum != context.get_sum) {
109140 std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum);
......@@ -125,10 +156,11 @@ fn startPuts(ctx: *Context) u8 {
125156 while (put_count != 0) : (put_count -= 1) {
126157 std.os.time.sleep(1); // let the os scheduler be our fuzz
127158 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{
129161 .next = undefined,
130162 .data = x,
131 }) catch unreachable;
163 };
132164 ctx.stack.push(node);
133165 _ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst);
134166 }
std/base64.zig+7-6
......@@ -1,5 +1,6 @@
11const std = @import("index.zig");
22const assert = std.debug.assert;
3const testing = std.testing;
34const mem = std.mem;
45
56pub const standard_alphabet_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
......@@ -394,7 +395,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void
394395 var buffer: [0x100]u8 = undefined;
395396 var encoded = buffer[0..Base64Encoder.calcSize(expected_decoded.len)];
396397 standard_encoder.encode(encoded, expected_decoded);
397 assert(mem.eql(u8, encoded, expected_encoded));
398 testing.expectEqualSlices(u8, expected_encoded, encoded);
398399 }
399400
400401 // Base64Decoder
......@@ -402,7 +403,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void
402403 var buffer: [0x100]u8 = undefined;
403404 var decoded = buffer[0..try standard_decoder.calcSize(expected_encoded)];
404405 try standard_decoder.decode(decoded, expected_encoded);
405 assert(mem.eql(u8, decoded, expected_decoded));
406 testing.expectEqualSlices(u8, expected_decoded, decoded);
406407 }
407408
408409 // Base64DecoderWithIgnore
......@@ -411,8 +412,8 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void
411412 var buffer: [0x100]u8 = undefined;
412413 var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(expected_encoded.len)];
413414 var written = try standard_decoder_ignore_nothing.decode(decoded, expected_encoded);
414 assert(written <= decoded.len);
415 assert(mem.eql(u8, decoded[0..written], expected_decoded));
415 testing.expect(written <= decoded.len);
416 testing.expectEqualSlices(u8, expected_decoded, decoded[0..written]);
416417 }
417418
418419 // Base64DecoderUnsafe
......@@ -420,7 +421,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void
420421 var buffer: [0x100]u8 = undefined;
421422 var decoded = buffer[0..standard_decoder_unsafe.calcSize(expected_encoded)];
422423 standard_decoder_unsafe.decode(decoded, expected_encoded);
423 assert(mem.eql(u8, decoded, expected_decoded));
424 testing.expectEqualSlices(u8, expected_decoded, decoded);
424425 }
425426}
426427
......@@ -429,7 +430,7 @@ fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !voi
429430 var buffer: [0x100]u8 = undefined;
430431 var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(encoded.len)];
431432 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]);
433434}
434435
435436fn testError(encoded: []const u8, expected_err: anyerror) !void {
std/buf_map.zig+35-17
......@@ -2,7 +2,7 @@ const std = @import("index.zig");
22const HashMap = std.HashMap;
33const mem = std.mem;
44const Allocator = mem.Allocator;
5const assert = std.debug.assert;
5const testing = std.testing;
66
77/// BufMap copies keys and values before they go into the map, and
88/// frees them when they get removed.
......@@ -16,7 +16,7 @@ pub const BufMap = struct {
1616 return self;
1717 }
1818
19 pub fn deinit(self: *const BufMap) void {
19 pub fn deinit(self: *BufMap) void {
2020 var it = self.hash_map.iterator();
2121 while (true) {
2222 const entry = it.next() orelse break;
......@@ -27,16 +27,34 @@ pub const BufMap = struct {
2727 self.hash_map.deinit();
2828 }
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.
3043 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);
3444 const value_copy = try self.copy(value);
3545 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;
3755 }
3856
39 pub fn get(self: *const BufMap, key: []const u8) ?[]const u8 {
57 pub fn get(self: BufMap, key: []const u8) ?[]const u8 {
4058 const entry = self.hash_map.get(key) orelse return null;
4159 return entry.value;
4260 }
......@@ -47,7 +65,7 @@ pub const BufMap = struct {
4765 self.free(entry.value);
4866 }
4967
50 pub fn count(self: *const BufMap) usize {
68 pub fn count(self: BufMap) usize {
5169 return self.hash_map.count();
5270 }
5371
......@@ -55,11 +73,11 @@ pub const BufMap = struct {
5573 return self.hash_map.iterator();
5674 }
5775
58 fn free(self: *const BufMap, value: []const u8) void {
76 fn free(self: BufMap, value: []const u8) void {
5977 self.hash_map.allocator.free(value);
6078 }
6179
62 fn copy(self: *const BufMap, value: []const u8) ![]const u8 {
80 fn copy(self: BufMap, value: []const u8) ![]u8 {
6381 return mem.dupe(self.hash_map.allocator, u8, value);
6482 }
6583};
......@@ -72,17 +90,17 @@ test "BufMap" {
7290 defer bufmap.deinit();
7391
7492 try bufmap.set("x", "1");
75 assert(mem.eql(u8, bufmap.get("x").?, "1"));
76 assert(1 == bufmap.count());
93 testing.expect(mem.eql(u8, bufmap.get("x").?, "1"));
94 testing.expect(1 == bufmap.count());
7795
7896 try bufmap.set("x", "2");
79 assert(mem.eql(u8, bufmap.get("x").?, "2"));
80 assert(1 == bufmap.count());
97 testing.expect(mem.eql(u8, bufmap.get("x").?, "2"));
98 testing.expect(1 == bufmap.count());
8199
82100 try bufmap.set("x", "3");
83 assert(mem.eql(u8, bufmap.get("x").?, "3"));
84 assert(1 == bufmap.count());
101 testing.expect(mem.eql(u8, bufmap.get("x").?, "3"));
102 testing.expect(1 == bufmap.count());
85103
86104 bufmap.delete("x");
87 assert(0 == bufmap.count());
105 testing.expect(0 == bufmap.count());
88106}
std/buf_set.zig+3-3
......@@ -2,7 +2,7 @@ const std = @import("index.zig");
22const HashMap = @import("hash_map.zig").HashMap;
33const mem = @import("mem.zig");
44const Allocator = mem.Allocator;
5const assert = std.debug.assert;
5const testing = std.testing;
66
77pub const BufSet = struct {
88 hash_map: BufSetHashMap,
......@@ -68,9 +68,9 @@ test "BufSet" {
6868 defer bufset.deinit();
6969
7070 try bufset.put("x");
71 assert(bufset.count() == 1);
71 testing.expect(bufset.count() == 1);
7272 bufset.delete("x");
73 assert(bufset.count() == 0);
73 testing.expect(bufset.count() == 0);
7474
7575 try bufset.put("x");
7676 try bufset.put("y");
std/buffer.zig+8-7
......@@ -3,6 +3,7 @@ const debug = std.debug;
33const mem = std.mem;
44const Allocator = mem.Allocator;
55const assert = debug.assert;
6const testing = std.testing;
67const ArrayList = std.ArrayList;
78
89/// A buffer that allocates memory and maintains a null byte at the end.
......@@ -141,19 +142,19 @@ test "simple Buffer" {
141142 const cstr = @import("cstr.zig");
142143
143144 var buf = try Buffer.init(debug.global_allocator, "");
144 assert(buf.len() == 0);
145 testing.expect(buf.len() == 0);
145146 try buf.append("hello");
146147 try buf.append(" ");
147148 try buf.append("world");
148 assert(buf.eql("hello world"));
149 assert(mem.eql(u8, cstr.toSliceConst(buf.toSliceConst().ptr), buf.toSliceConst()));
149 testing.expect(buf.eql("hello world"));
150 testing.expect(mem.eql(u8, cstr.toSliceConst(buf.toSliceConst().ptr), buf.toSliceConst()));
150151
151152 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 assert(buf.endsWith("orld"));
155 testing.expect(buf.startsWith("hell"));
156 testing.expect(buf.endsWith("orld"));
156157
157158 try buf2.resize(4);
158 assert(buf.startsWith(buf2.toSlice()));
159 testing.expect(buf.startsWith(buf2.toSlice()));
159160}
std/build.zig+107-42
......@@ -89,7 +89,7 @@ pub const Builder = struct {
8989 };
9090
9191 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;
9393 env_map.* = os.getEnvMap(allocator) catch unreachable;
9494 var self = Builder{
9595 .zig_exe = zig_exe,
......@@ -145,8 +145,8 @@ pub const Builder = struct {
145145
146146 pub fn setInstallPrefix(self: *Builder, maybe_prefix: ?[]const u8) void {
147147 self.prefix = maybe_prefix orelse "/usr/local"; // TODO better default
148 self.lib_dir = os.path.join(self.allocator, self.prefix, "lib") catch unreachable;
149 self.exe_dir = os.path.join(self.allocator, self.prefix, "bin") 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, [][]const u8{ self.prefix, "bin" }) catch unreachable;
150150 }
151151
152152 pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
......@@ -170,7 +170,8 @@ pub const Builder = struct {
170170 }
171171
172172 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);
174175 return test_step;
175176 }
176177
......@@ -202,18 +203,21 @@ pub const Builder = struct {
202203 }
203204
204205 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);
206208 return write_file_step;
207209 }
208210
209211 pub fn addLog(self: *Builder, comptime format: []const u8, args: ...) *LogStep {
210212 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);
212215 return log_step;
213216 }
214217
215218 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);
217221 return remove_dir_step;
218222 }
219223
......@@ -320,7 +324,7 @@ pub const Builder = struct {
320324
321325 fn processNixOSEnvVars(self: *Builder) void {
322326 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, " ");
324328 while (true) {
325329 const word = it.next() orelse break;
326330 if (mem.eql(u8, word, "-isystem")) {
......@@ -338,7 +342,7 @@ pub const Builder = struct {
338342 assert(err == error.EnvironmentVariableNotFound);
339343 }
340344 if (os.getEnvVarOwned(self.allocator, "NIX_LDFLAGS")) |nix_ldflags| {
341 var it = mem.split(nix_ldflags, " ");
345 var it = mem.tokenize(nix_ldflags, " ");
342346 while (true) {
343347 const word = it.next() orelse break;
344348 if (mem.eql(u8, word, "-rpath")) {
......@@ -414,10 +418,11 @@ pub const Builder = struct {
414418 }
415419
416420 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{
418423 .step = Step.initNoOp(name, self.allocator),
419424 .description = description,
420 }) catch unreachable;
425 };
421426 self.top_level_steps.append(step_info) catch unreachable;
422427 return &step_info.step;
423428 }
......@@ -613,10 +618,14 @@ pub const Builder = struct {
613618
614619 ///::dest_rel_path is relative to prefix path or it can be an absolute path
615620 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;
617625 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);
620629 return install_step;
621630 }
622631
......@@ -647,7 +656,7 @@ pub const Builder = struct {
647656 }
648657
649658 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;
651660 }
652661
653662 pub fn fmt(self: *Builder, comptime format: []const u8, args: ...) []u8 {
......@@ -670,7 +679,7 @@ pub const Builder = struct {
670679 if (os.path.isAbsolute(name)) {
671680 return name;
672681 }
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) });
674683 if (os.path.real(self.allocator, full_path)) |real_path| {
675684 return real_path;
676685 } else |_| {
......@@ -683,9 +692,9 @@ pub const Builder = struct {
683692 if (os.path.isAbsolute(name)) {
684693 return name;
685694 }
686 var it = mem.split(PATH, []u8{os.path.delimiter});
695 var it = mem.tokenize(PATH, []u8{os.path.delimiter});
687696 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) });
689698 if (os.path.real(self.allocator, full_path)) |real_path| {
690699 return real_path;
691700 } else |_| {
......@@ -699,7 +708,7 @@ pub const Builder = struct {
699708 return name;
700709 }
701710 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) });
703712 if (os.path.real(self.allocator, full_path)) |real_path| {
704713 return real_path;
705714 } else |_| {
......@@ -865,43 +874,51 @@ pub const LibExeObjStep = struct {
865874 };
866875
867876 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);
869879 return self;
870880 }
871881
872882 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);
874885 return self;
875886 }
876887
877888 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));
879891 return self;
880892 }
881893
882894 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);
884897 return self;
885898 }
886899
887900 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));
889903 return self;
890904 }
891905
892906 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);
894909 self.object_src = src;
895910 return self;
896911 }
897912
898913 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));
900916 return self;
901917 }
902918
903919 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);
905922 return self;
906923 }
907924
......@@ -1099,7 +1116,10 @@ pub const LibExeObjStep = struct {
10991116 }
11001117
11011118 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;
11031123 }
11041124
11051125 pub fn setOutputHPath(self: *LibExeObjStep, file_path: []const u8) void {
......@@ -1112,7 +1132,10 @@ pub const LibExeObjStep = struct {
11121132 }
11131133
11141134 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;
11161139 }
11171140
11181141 pub fn addAssemblyFile(self: *LibExeObjStep, path: []const u8) void {
......@@ -1212,7 +1235,10 @@ pub const LibExeObjStep = struct {
12121235 }
12131236
12141237 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 );
12161242 try std.io.writeFile(build_options_file, self.build_options_contents.toSliceConst());
12171243 try zig_args.append("--pkg-begin");
12181244 try zig_args.append("build_options");
......@@ -1462,7 +1488,10 @@ pub const LibExeObjStep = struct {
14621488 cc_args.append("-c") catch unreachable;
14631489 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;
14661495 if (os.path.dirname(cache_o_src)) |cache_o_dir| {
14671496 try builder.makePath(cache_o_dir);
14681497 }
......@@ -1514,7 +1543,10 @@ pub const LibExeObjStep = struct {
15141543 cc_args.append("-current_version") catch unreachable;
15151544 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);
15181550 cc_args.append("-install_name") catch unreachable;
15191551 cc_args.append(install_name) catch unreachable;
15201552 } else {
......@@ -1580,7 +1612,10 @@ pub const LibExeObjStep = struct {
15801612 cc_args.append("-c") catch unreachable;
15811613 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;
15841619 if (os.path.dirname(cache_o_src)) |cache_o_dir| {
15851620 try builder.makePath(cache_o_dir);
15861621 }
......@@ -1672,6 +1707,7 @@ pub const TestStep = struct {
16721707 no_rosegment: bool,
16731708 output_path: ?[]const u8,
16741709 system_linker_hack: bool,
1710 override_std_dir: ?[]const u8,
16751711
16761712 pub fn init(builder: *Builder, root_src: []const u8) TestStep {
16771713 const step_name = builder.fmt("test {}", root_src);
......@@ -1693,6 +1729,7 @@ pub const TestStep = struct {
16931729 .no_rosegment = false,
16941730 .output_path = null,
16951731 .system_linker_hack = false,
1732 .override_std_dir = null,
16961733 };
16971734 }
16981735
......@@ -1723,6 +1760,10 @@ pub const TestStep = struct {
17231760 self.build_mode = mode;
17241761 }
17251762
1763 pub fn overrideStdDir(self: *TestStep, dir_path: []const u8) void {
1764 self.override_std_dir = dir_path;
1765 }
1766
17261767 pub fn setOutputPath(self: *TestStep, file_path: []const u8) void {
17271768 self.output_path = file_path;
17281769
......@@ -1737,7 +1778,10 @@ pub const TestStep = struct {
17371778 return output_path;
17381779 } else {
17391780 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;
17411785 }
17421786 }
17431787
......@@ -1900,6 +1944,10 @@ pub const TestStep = struct {
19001944 if (self.system_linker_hack) {
19011945 try zig_args.append("--system-linker-hack");
19021946 }
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
19041952 try builder.spawnChild(zig_args.toSliceConst());
19051953 }
......@@ -1914,13 +1962,14 @@ pub const CommandStep = struct {
19141962
19151963 /// ::argv is copied.
19161964 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{
19181967 .builder = builder,
19191968 .step = Step.init(argv[0], builder.allocator, make),
19201969 .argv = builder.allocator.alloc([]u8, argv.len) catch unreachable,
19211970 .cwd = cwd,
19221971 .env_map = env_map,
1923 }) catch unreachable;
1972 };
19241973
19251974 mem.copy([]const u8, self.argv, argv);
19261975 self.step.name = self.argv[0];
......@@ -1949,17 +1998,27 @@ const InstallArtifactStep = struct {
19491998 LibExeObjStep.Kind.Exe => builder.exe_dir,
19501999 LibExeObjStep.Kind.Lib => builder.lib_dir,
19512000 };
1952 const self = builder.allocator.create(Self{
2001 const self = builder.allocator.create(Self) catch unreachable;
2002 self.* = Self{
19532003 .builder = builder,
19542004 .step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make),
19552005 .artifact = artifact,
1956 .dest_file = os.path.join(builder.allocator, dest_dir, artifact.out_filename) catch unreachable,
1957 }) catch unreachable;
2006 .dest_file = os.path.join(
2007 builder.allocator,
2008 [][]const u8{ dest_dir, artifact.out_filename },
2009 ) catch unreachable,
2010 };
19582011 self.step.dependOn(&artifact.step);
19592012 builder.pushInstalledFile(self.dest_file);
19602013 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);
1962 builder.pushInstalledFile(os.path.join(builder.allocator, builder.lib_dir, artifact.name_only_filename) catch unreachable);
2014 builder.pushInstalledFile(os.path.join(
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);
19632022 }
19642023 return self;
19652024 }
......@@ -2115,13 +2174,19 @@ fn doAtomicSymLinks(allocator: *Allocator, output_path: []const u8, filename_maj
21152174 const out_dir = os.path.dirname(output_path) orelse ".";
21162175 const out_basename = os.path.basename(output_path);
21172176 // 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;
21192181 os.atomicSymLink(allocator, out_basename, major_only_path) catch |err| {
21202182 warn("Unable to symlink {} -> {}\n", major_only_path, out_basename);
21212183 return err;
21222184 };
21232185 // 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;
21252190 os.atomicSymLink(allocator, filename_major_only, name_only_path) catch |err| {
21262191 warn("Unable to symlink {} -> {}\n", name_only_path, filename_major_only);
21272192 return err;
std/c/darwin.zig+20-2
......@@ -73,8 +73,8 @@ pub const sockaddr_in6 = extern struct {
7373};
7474
7575pub const timeval = extern struct {
76 tv_sec: isize,
77 tv_usec: isize,
76 tv_sec: c_long,
77 tv_usec: i32,
7878};
7979
8080pub const timezone = extern struct {
......@@ -176,6 +176,24 @@ pub const kevent64_s = extern struct {
176176 ext: [2]u64,
177177};
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
179197// sys/types.h on macos uses #pragma pack() so these checks are
180198// to make sure the struct is laid out the same. These values were
181199// produced from C code using the offsetof macro.
std/c/freebsd.zig+89-2
......@@ -1,5 +1,3 @@
1const timespec = @import("../os/freebsd/index.zig").timespec;
2
31extern "c" fn __error() *c_int;
42pub const _errno = __error;
53
......@@ -15,6 +13,17 @@ pub extern "c" fn kevent(
1513pub extern "c" fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
1614pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
1715pub 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
1928/// Renamed from `kevent` to `Kevent` to avoid conflict with function name.
2029pub const Kevent = extern struct {
......@@ -31,3 +40,81 @@ pub const pthread_attr_t = extern struct {
3140 __size: [56]u8,
3241 __align: c_long,
3342};
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;
4444pub extern "c" fn readlink(noalias path: [*]const u8, noalias buf: [*]u8, bufsize: usize) isize;
4545pub extern "c" fn realpath(noalias file_name: [*]const u8, noalias resolved_name: [*]u8) ?[*]u8;
4646pub 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;
4848pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int;
4949pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int;
5050pub 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 {
5151
5252 // Seek to PE File Header (coff header)
5353 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);
5555 try self.in_file.seekTo(pe_magic_offset);
5656
5757 var pe_header_magic: [4]u8 = undefined;
......@@ -60,13 +60,13 @@ pub const Coff = struct {
6060 return error.InvalidPEHeader;
6161
6262 self.coff_header = CoffHeader{
63 .machine = try in.readIntLe(u16),
64 .number_of_sections = try in.readIntLe(u16),
65 .timedate_stamp = try in.readIntLe(u32),
66 .pointer_to_symbol_table = try in.readIntLe(u32),
67 .number_of_symbols = try in.readIntLe(u32),
68 .size_of_optional_header = try in.readIntLe(u16),
69 .characteristics = try in.readIntLe(u16),
63 .machine = try in.readIntLittle(u16),
64 .number_of_sections = try in.readIntLittle(u16),
65 .timedate_stamp = try in.readIntLittle(u32),
66 .pointer_to_symbol_table = try in.readIntLittle(u32),
67 .number_of_symbols = try in.readIntLittle(u32),
68 .size_of_optional_header = try in.readIntLittle(u16),
69 .characteristics = try in.readIntLittle(u16),
7070 };
7171
7272 switch (self.coff_header.machine) {
......@@ -79,7 +79,7 @@ pub const Coff = struct {
7979
8080 fn loadOptionalHeader(self: *Coff, file_stream: *os.File.InStream) !void {
8181 const in = &file_stream.stream;
82 self.pe_header.magic = try in.readIntLe(u16);
82 self.pe_header.magic = try in.readIntLittle(u16);
8383 // For now we're only interested in finding the reference to the .pdb,
8484 // so we'll skip most of this header, which size is different in 32
8585 // 64 bits by the way.
......@@ -93,14 +93,14 @@ pub const Coff = struct {
9393
9494 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);
9797 if (number_of_rva_and_sizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
9898 return error.InvalidPEHeader;
9999
100100 for (self.pe_header.data_directory) |*data_dir| {
101101 data_dir.* = OptionalHeader.DataDirectory{
102 .virtual_address = try in.readIntLe(u32),
103 .size = try in.readIntLe(u32),
102 .virtual_address = try in.readIntLittle(u32),
103 .size = try in.readIntLittle(u32),
104104 };
105105 }
106106 }
......@@ -124,7 +124,7 @@ pub const Coff = struct {
124124 if (!mem.eql(u8, cv_signature, "RSDS"))
125125 return error.InvalidPEMagic;
126126 try in.readNoEof(self.guid[0..]);
127 self.age = try in.readIntLe(u32);
127 self.age = try in.readIntLittle(u32);
128128
129129 // Finally read the null-terminated string.
130130 var byte = try in.readByte();
......@@ -157,15 +157,15 @@ pub const Coff = struct {
157157 try self.sections.append(Section{
158158 .header = SectionHeader{
159159 .name = name,
160 .misc = SectionHeader.Misc{ .physical_address = try in.readIntLe(u32) },
161 .virtual_address = try in.readIntLe(u32),
162 .size_of_raw_data = try in.readIntLe(u32),
163 .pointer_to_raw_data = try in.readIntLe(u32),
164 .pointer_to_relocations = try in.readIntLe(u32),
165 .pointer_to_line_numbers = try in.readIntLe(u32),
166 .number_of_relocations = try in.readIntLe(u16),
167 .number_of_line_numbers = try in.readIntLe(u16),
168 .characteristics = try in.readIntLe(u32),
160 .misc = SectionHeader.Misc{ .physical_address = try in.readIntLittle(u32) },
161 .virtual_address = try in.readIntLittle(u32),
162 .size_of_raw_data = try in.readIntLittle(u32),
163 .pointer_to_raw_data = try in.readIntLittle(u32),
164 .pointer_to_relocations = try in.readIntLittle(u32),
165 .pointer_to_line_numbers = try in.readIntLittle(u32),
166 .number_of_relocations = try in.readIntLittle(u16),
167 .number_of_line_numbers = try in.readIntLittle(u16),
168 .characteristics = try in.readIntLittle(u32),
169169 },
170170 });
171171 }
std/crypto/blake2.zig+7-4
......@@ -123,7 +123,8 @@ fn Blake2s(comptime out_len: usize) type {
123123 const rr = d.h[0 .. out_len / 32];
124124
125125 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);
127128 }
128129 }
129130
......@@ -134,7 +135,8 @@ fn Blake2s(comptime out_len: usize) type {
134135 var v: [16]u32 = undefined;
135136
136137 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]);
138140 }
139141
140142 var k: usize = 0;
......@@ -356,7 +358,8 @@ fn Blake2b(comptime out_len: usize) type {
356358 const rr = d.h[0 .. out_len / 64];
357359
358360 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);
360363 }
361364 }
362365
......@@ -367,7 +370,7 @@ fn Blake2b(comptime out_len: usize) type {
367370 var v: [16]u64 = undefined;
368371
369372 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]);
371374 }
372375
373376 var k: usize = 0;
std/crypto/chacha20.zig+35-33
......@@ -4,6 +4,7 @@ const std = @import("../index.zig");
44const mem = std.mem;
55const endian = std.endian;
66const assert = std.debug.assert;
7const testing = std.testing;
78const builtin = @import("builtin");
89const maxInt = std.math.maxInt;
910
......@@ -59,7 +60,8 @@ fn salsa20_wordtobyte(out: []u8, input: [16]u32) void {
5960 }
6061
6162 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]);
6365 }
6466}
6567
......@@ -70,10 +72,10 @@ fn chaCha20_internal(out: []u8, in: []const u8, key: [8]u32, counter: [4]u32) vo
7072
7173 const c = "expand 32-byte k";
7274 const constant_le = []u32{
73 mem.readIntLE(u32, c[0..4]),
74 mem.readIntLE(u32, c[4..8]),
75 mem.readIntLE(u32, c[8..12]),
76 mem.readIntLE(u32, c[12..16]),
75 mem.readIntSliceLittle(u32, c[0..4]),
76 mem.readIntSliceLittle(u32, c[4..8]),
77 mem.readIntSliceLittle(u32, c[8..12]),
78 mem.readIntSliceLittle(u32, c[12..16]),
7779 };
7880
7981 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:
117119 var k: [8]u32 = undefined;
118120 var c: [4]u32 = undefined;
119121
120 k[0] = mem.readIntLE(u32, key[0..4]);
121 k[1] = mem.readIntLE(u32, key[4..8]);
122 k[2] = mem.readIntLE(u32, key[8..12]);
123 k[3] = mem.readIntLE(u32, key[12..16]);
124 k[4] = mem.readIntLE(u32, key[16..20]);
125 k[5] = mem.readIntLE(u32, key[20..24]);
126 k[6] = mem.readIntLE(u32, key[24..28]);
127 k[7] = mem.readIntLE(u32, key[28..32]);
122 k[0] = mem.readIntSliceLittle(u32, key[0..4]);
123 k[1] = mem.readIntSliceLittle(u32, key[4..8]);
124 k[2] = mem.readIntSliceLittle(u32, key[8..12]);
125 k[3] = mem.readIntSliceLittle(u32, key[12..16]);
126 k[4] = mem.readIntSliceLittle(u32, key[16..20]);
127 k[5] = mem.readIntSliceLittle(u32, key[20..24]);
128 k[6] = mem.readIntSliceLittle(u32, key[24..28]);
129 k[7] = mem.readIntSliceLittle(u32, key[28..32]);
128130
129131 c[0] = counter;
130 c[1] = mem.readIntLE(u32, nonce[0..4]);
131 c[2] = mem.readIntLE(u32, nonce[4..8]);
132 c[3] = mem.readIntLE(u32, nonce[8..12]);
132 c[1] = mem.readIntSliceLittle(u32, nonce[0..4]);
133 c[2] = mem.readIntSliceLittle(u32, nonce[4..8]);
134 c[3] = mem.readIntSliceLittle(u32, nonce[8..12]);
133135 chaCha20_internal(out, in, k, c);
134136}
135137
......@@ -144,19 +146,19 @@ pub fn chaCha20With64BitNonce(out: []u8, in: []const u8, counter: u64, key: [32]
144146 var k: [8]u32 = undefined;
145147 var c: [4]u32 = undefined;
146148
147 k[0] = mem.readIntLE(u32, key[0..4]);
148 k[1] = mem.readIntLE(u32, key[4..8]);
149 k[2] = mem.readIntLE(u32, key[8..12]);
150 k[3] = mem.readIntLE(u32, key[12..16]);
151 k[4] = mem.readIntLE(u32, key[16..20]);
152 k[5] = mem.readIntLE(u32, key[20..24]);
153 k[6] = mem.readIntLE(u32, key[24..28]);
154 k[7] = mem.readIntLE(u32, key[28..32]);
149 k[0] = mem.readIntSliceLittle(u32, key[0..4]);
150 k[1] = mem.readIntSliceLittle(u32, key[4..8]);
151 k[2] = mem.readIntSliceLittle(u32, key[8..12]);
152 k[3] = mem.readIntSliceLittle(u32, key[12..16]);
153 k[4] = mem.readIntSliceLittle(u32, key[16..20]);
154 k[5] = mem.readIntSliceLittle(u32, key[20..24]);
155 k[6] = mem.readIntSliceLittle(u32, key[24..28]);
156 k[7] = mem.readIntSliceLittle(u32, key[28..32]);
155157
156158 c[0] = @truncate(u32, counter);
157159 c[1] = @truncate(u32, counter >> 32);
158 c[2] = mem.readIntLE(u32, nonce[0..4]);
159 c[3] = mem.readIntLE(u32, nonce[4..8]);
160 c[2] = mem.readIntSliceLittle(u32, nonce[0..4]);
161 c[3] = mem.readIntSliceLittle(u32, nonce[4..8]);
160162
161163 const block_size = (1 << 6);
162164 const big_block = (block_size << 32);
......@@ -215,12 +217,12 @@ test "crypto.chacha20 test vector sunscreen" {
215217 };
216218
217219 chaCha20IETF(result[0..], input[0..], 1, key, nonce);
218 assert(mem.eql(u8, expected_result, result));
220 testing.expectEqualSlices(u8, expected_result, result);
219221
220222 // Chacha20 is self-reversing.
221223 var plaintext: [114]u8 = undefined;
222224 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);
224226}
225227
226228// https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7
......@@ -255,7 +257,7 @@ test "crypto.chacha20 test vector 1" {
255257 const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 0 };
256258
257259 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
258 assert(mem.eql(u8, expected_result, result));
260 testing.expectEqualSlices(u8, expected_result, result);
259261}
260262
261263test "crypto.chacha20 test vector 2" {
......@@ -289,7 +291,7 @@ test "crypto.chacha20 test vector 2" {
289291 const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 0 };
290292
291293 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
292 assert(mem.eql(u8, expected_result, result));
294 testing.expectEqualSlices(u8, expected_result, result);
293295}
294296
295297test "crypto.chacha20 test vector 3" {
......@@ -323,7 +325,7 @@ test "crypto.chacha20 test vector 3" {
323325 const nonce = []u8{ 0, 0, 0, 0, 0, 0, 0, 1 };
324326
325327 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
326 assert(mem.eql(u8, expected_result, result));
328 testing.expectEqualSlices(u8, expected_result, result);
327329}
328330
329331test "crypto.chacha20 test vector 4" {
......@@ -357,7 +359,7 @@ test "crypto.chacha20 test vector 4" {
357359 const nonce = []u8{ 1, 0, 0, 0, 0, 0, 0, 0 };
358360
359361 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
360 assert(mem.eql(u8, expected_result, result));
362 testing.expectEqualSlices(u8, expected_result, result);
361363}
362364
363365test "crypto.chacha20 test vector 5" {
......@@ -429,5 +431,5 @@ test "crypto.chacha20 test vector 5" {
429431 };
430432
431433 chaCha20With64BitNonce(result[0..], input[0..], 0, key, nonce);
432 assert(mem.eql(u8, expected_result, result));
434 testing.expectEqualSlices(u8, expected_result, result);
433435}
std/crypto/md5.zig+2-1
......@@ -112,7 +112,8 @@ pub const Md5 = struct {
112112 d.round(d.buf[0..]);
113113
114114 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);
116117 }
117118 }
118119
std/crypto/poly1305.zig+15-14
......@@ -6,8 +6,8 @@ const std = @import("../index.zig");
66const builtin = @import("builtin");
77
88const Endian = builtin.Endian;
9const readInt = std.mem.readInt;
10const writeInt = std.mem.writeInt;
9const readIntSliceLittle = std.mem.readIntSliceLittle;
10const writeIntSliceLittle = std.mem.writeIntSliceLittle;
1111
1212pub const Poly1305 = struct {
1313 const Self = @This();
......@@ -59,19 +59,19 @@ pub const Poly1305 = struct {
5959 {
6060 var i: usize = 0;
6161 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;
6363 }
6464 }
6565 {
6666 var i: usize = 1;
6767 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;
6969 }
7070 }
7171 {
7272 var i: usize = 0;
7373 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]);
7575 }
7676 }
7777
......@@ -168,10 +168,10 @@ pub const Poly1305 = struct {
168168 const nb_blocks = nmsg.len >> 4;
169169 var i: usize = 0;
170170 while (i < nb_blocks) : (i += 1) {
171 ctx.c[0] = readInt(nmsg[0..4], u32, Endian.Little);
172 ctx.c[1] = readInt(nmsg[4..8], u32, Endian.Little);
173 ctx.c[2] = readInt(nmsg[8..12], u32, Endian.Little);
174 ctx.c[3] = readInt(nmsg[12..16], u32, Endian.Little);
171 ctx.c[0] = readIntSliceLittle(u32, nmsg[0..4]);
172 ctx.c[1] = readIntSliceLittle(u32, nmsg[4..8]);
173 ctx.c[2] = readIntSliceLittle(u32, nmsg[8..12]);
174 ctx.c[3] = readIntSliceLittle(u32, nmsg[12..16]);
175175 polyBlock(ctx);
176176 nmsg = nmsg[16..];
177177 }
......@@ -210,10 +210,11 @@ pub const Poly1305 = struct {
210210 const uu2 = (uu1 >> 32) + ctx.h[2] + ctx.pad[2]; // <= 2_00000000
211211 const uu3 = (uu2 >> 32) + ctx.h[3] + ctx.pad[3]; // <= 2_00000000
212212
213 writeInt(out[0..], @truncate(u32, uu0), Endian.Little);
214 writeInt(out[4..], @truncate(u32, uu1), Endian.Little);
215 writeInt(out[8..], @truncate(u32, uu2), Endian.Little);
216 writeInt(out[12..], @truncate(u32, uu3), Endian.Little);
213 // TODO https://github.com/ziglang/zig/issues/863
214 writeIntSliceLittle(u32, out[0..], @truncate(u32, uu0));
215 writeIntSliceLittle(u32, out[4..], @truncate(u32, uu1));
216 writeIntSliceLittle(u32, out[8..], @truncate(u32, uu2));
217 writeIntSliceLittle(u32, out[12..], @truncate(u32, uu3));
217218
218219 ctx.secureZero();
219220 }
......@@ -229,5 +230,5 @@ test "poly1305 rfc7439 vector1" {
229230 var mac: [16]u8 = undefined;
230231 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);
233234}
std/crypto/sha1.zig+2-1
......@@ -109,7 +109,8 @@ pub const Sha1 = struct {
109109 d.round(d.buf[0..]);
110110
111111 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);
113114 }
114115 }
115116
std/crypto/sha2.zig+4-2
......@@ -167,7 +167,8 @@ fn Sha2_32(comptime params: Sha2Params32) type {
167167 const rr = d.s[0 .. params.out_len / 32];
168168
169169 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);
171172 }
172173 }
173174
......@@ -508,7 +509,8 @@ fn Sha2_64(comptime params: Sha2Params64) type {
508509 const rr = d.s[0 .. params.out_len / 64];
509510
510511 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);
512514 }
513515 }
514516
std/crypto/sha3.zig+3-2
......@@ -120,7 +120,7 @@ fn keccak_f(comptime F: usize, d: []u8) void {
120120 var c = []const u64{0} ** 5;
121121
122122 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]);
124124 }
125125
126126 comptime var x: usize = 0;
......@@ -167,7 +167,8 @@ fn keccak_f(comptime F: usize, d: []u8) void {
167167 }
168168
169169 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);
171172 }
172173}
173174
std/crypto/test.zig+5-4
......@@ -1,6 +1,7 @@
1const debug = @import("../debug/index.zig");
2const mem = @import("../mem.zig");
3const fmt = @import("../fmt/index.zig");
1const std = @import("../index.zig");
2const testing = std.testing;
3const mem = std.mem;
4const fmt = std.fmt;
45
56// Hash using the specified hasher `H` asserting `expected == H(input)`.
67pub 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 {
1718 r.* = fmt.parseInt(u8, expected[2 * i .. 2 * i + 2], 16) catch unreachable;
1819 }
1920
20 debug.assert(mem.eql(u8, expected_bytes, input));
21 testing.expectEqualSlices(u8, expected_bytes, input);
2122}
std/crypto/x25519.zig+33-32
......@@ -7,8 +7,8 @@ const builtin = @import("builtin");
77const fmt = std.fmt;
88
99const Endian = builtin.Endian;
10const readInt = std.mem.readInt;
11const writeInt = std.mem.writeInt;
10const readIntSliceLittle = std.mem.readIntSliceLittle;
11const writeIntSliceLittle = std.mem.writeIntSliceLittle;
1212
1313// Based on Supercop's ref10 implementation.
1414pub const X25519 = struct {
......@@ -255,16 +255,16 @@ const Fe = struct {
255255
256256 var t: [10]i64 = undefined;
257257
258 t[0] = readInt(s[0..4], u32, Endian.Little);
259 t[1] = readInt(s[4..7], u32, Endian.Little) << 6;
260 t[2] = readInt(s[7..10], u32, Endian.Little) << 5;
261 t[3] = readInt(s[10..13], u32, Endian.Little) << 3;
262 t[4] = readInt(s[13..16], u32, Endian.Little) << 2;
263 t[5] = readInt(s[16..20], u32, Endian.Little);
264 t[6] = readInt(s[20..23], u32, Endian.Little) << 7;
265 t[7] = readInt(s[23..26], u32, Endian.Little) << 5;
266 t[8] = readInt(s[26..29], u32, Endian.Little) << 4;
267 t[9] = (readInt(s[29..32], u32, Endian.Little) & 0x7fffff) << 2;
258 t[0] = readIntSliceLittle(u32, s[0..4]);
259 t[1] = u32(readIntSliceLittle(u24, s[4..7])) << 6;
260 t[2] = u32(readIntSliceLittle(u24, s[7..10])) << 5;
261 t[3] = u32(readIntSliceLittle(u24, s[10..13])) << 3;
262 t[4] = u32(readIntSliceLittle(u24, s[13..16])) << 2;
263 t[5] = readIntSliceLittle(u32, s[16..20]);
264 t[6] = u32(readIntSliceLittle(u24, s[20..23])) << 7;
265 t[7] = u32(readIntSliceLittle(u24, s[23..26])) << 5;
266 t[8] = u32(readIntSliceLittle(u24, s[26..29])) << 4;
267 t[9] = (u32(readIntSliceLittle(u24, s[29..32])) & 0x7fffff) << 2;
268268
269269 carry1(h, t[0..]);
270270 }
......@@ -544,14 +544,15 @@ const Fe = struct {
544544 ut[i] = @bitCast(u32, @intCast(i32, t[i]));
545545 }
546546
547 writeInt(s[0..], (ut[0] >> 0) | (ut[1] << 26), Endian.Little);
548 writeInt(s[4..], (ut[1] >> 6) | (ut[2] << 19), Endian.Little);
549 writeInt(s[8..], (ut[2] >> 13) | (ut[3] << 13), Endian.Little);
550 writeInt(s[12..], (ut[3] >> 19) | (ut[4] << 6), Endian.Little);
551 writeInt(s[16..], (ut[5] >> 0) | (ut[6] << 25), Endian.Little);
552 writeInt(s[20..], (ut[6] >> 7) | (ut[7] << 19), Endian.Little);
553 writeInt(s[24..], (ut[7] >> 13) | (ut[8] << 12), Endian.Little);
554 writeInt(s[28..], (ut[8] >> 20) | (ut[9] << 6), Endian.Little);
547 // TODO https://github.com/ziglang/zig/issues/863
548 writeIntSliceLittle(u32, s[0..4], (ut[0] >> 0) | (ut[1] << 26));
549 writeIntSliceLittle(u32, s[4..8], (ut[1] >> 6) | (ut[2] << 19));
550 writeIntSliceLittle(u32, s[8..12], (ut[2] >> 13) | (ut[3] << 13));
551 writeIntSliceLittle(u32, s[12..16], (ut[3] >> 19) | (ut[4] << 6));
552 writeIntSliceLittle(u32, s[16..20], (ut[5] >> 0) | (ut[6] << 25));
553 writeIntSliceLittle(u32, s[20..24], (ut[6] >> 7) | (ut[7] << 19));
554 writeIntSliceLittle(u32, s[24..28], (ut[7] >> 13) | (ut[8] << 12));
555 writeIntSliceLittle(u32, s[28..], (ut[8] >> 20) | (ut[9] << 6));
555556
556557 std.mem.secureZero(i64, t[0..]);
557558 }
......@@ -580,8 +581,8 @@ test "x25519 public key calculation from secret key" {
580581 var pk_calculated: [32]u8 = undefined;
581582 try fmt.hexToBytes(sk[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");
582583 try fmt.hexToBytes(pk_expected[0..], "f1814f0e8ff1043d8a44d25babff3cedcae6c22c3edaa48f857ae70de2baae50");
583 std.debug.assert(X25519.createPublicKey(pk_calculated[0..], sk));
584 std.debug.assert(std.mem.eql(u8, pk_calculated, pk_expected));
584 std.testing.expect(X25519.createPublicKey(pk_calculated[0..], sk));
585 std.testing.expect(std.mem.eql(u8, pk_calculated, pk_expected));
585586}
586587
587588test "x25519 rfc7748 vector1" {
......@@ -592,8 +593,8 @@ test "x25519 rfc7748 vector1" {
592593
593594 var output: [32]u8 = undefined;
594595
595 std.debug.assert(X25519.create(output[0..], secret_key, public_key));
596 std.debug.assert(std.mem.eql(u8, output, expected_output));
596 std.testing.expect(X25519.create(output[0..], secret_key, public_key));
597 std.testing.expect(std.mem.eql(u8, output, expected_output));
597598}
598599
599600test "x25519 rfc7748 vector2" {
......@@ -604,8 +605,8 @@ test "x25519 rfc7748 vector2" {
604605
605606 var output: [32]u8 = undefined;
606607
607 std.debug.assert(X25519.create(output[0..], secret_key, public_key));
608 std.debug.assert(std.mem.eql(u8, output, expected_output));
608 std.testing.expect(X25519.create(output[0..], secret_key, public_key));
609 std.testing.expect(std.mem.eql(u8, output, expected_output));
609610}
610611
611612test "x25519 rfc7748 one iteration" {
......@@ -618,13 +619,13 @@ test "x25519 rfc7748 one iteration" {
618619 var i: usize = 0;
619620 while (i < 1) : (i += 1) {
620621 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
623624 std.mem.copy(u8, u[0..], k[0..]);
624625 std.mem.copy(u8, k[0..], output[0..]);
625626 }
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));
628629}
629630
630631test "x25519 rfc7748 1,000 iterations" {
......@@ -642,13 +643,13 @@ test "x25519 rfc7748 1,000 iterations" {
642643 var i: usize = 0;
643644 while (i < 1000) : (i += 1) {
644645 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
647648 std.mem.copy(u8, u[0..], k[0..]);
648649 std.mem.copy(u8, k[0..], output[0..]);
649650 }
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));
652653}
653654
654655test "x25519 rfc7748 1,000,000 iterations" {
......@@ -665,11 +666,11 @@ test "x25519 rfc7748 1,000,000 iterations" {
665666 var i: usize = 0;
666667 while (i < 1000000) : (i += 1) {
667668 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
670671 std.mem.copy(u8, u[0..], k[0..]);
671672 std.mem.copy(u8, k[0..], output[0..]);
672673 }
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));
675676}
std/cstr.zig+3-3
......@@ -2,7 +2,7 @@ const std = @import("index.zig");
22const builtin = @import("builtin");
33const debug = std.debug;
44const mem = std.mem;
5const assert = debug.assert;
5const testing = std.testing;
66
77pub const line_sep = switch (builtin.os) {
88 builtin.Os.windows => "\r\n",
......@@ -42,8 +42,8 @@ test "cstr fns" {
4242}
4343
4444fn testCStrFnsImpl() void {
45 assert(cmp(c"aoeu", c"aoez") == -1);
46 assert(len(c"123456789") == 9);
45 testing.expect(cmp(c"aoeu", c"aoez") == -1);
46 testing.expect(len(c"123456789") == 9);
4747}
4848
4949/// 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 {
3737var stderr_file: os.File = undefined;
3838var stderr_file_out_stream: os.File.OutStream = undefined;
3939
40/// TODO multithreaded awareness
4140var stderr_stream: ?*io.OutStream(os.File.WriteError) = null;
4241var stderr_mutex = std.Mutex.init();
4342pub fn warn(comptime fmt: []const u8, args: ...) void {
......@@ -108,37 +107,15 @@ pub fn dumpStackTrace(stack_trace: *const builtin.StackTrace) void {
108107/// This function invokes undefined behavior when `ok` is `false`.
109108/// In Debug and ReleaseSafe modes, calls to this function are always
110109/// generated, and the `unreachable` statement triggers a panic.
111/// In ReleaseFast and ReleaseSmall modes, calls to this function can be
112/// optimized away.
110/// In ReleaseFast and ReleaseSmall modes, calls to this function are
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.
113117pub fn assert(ok: bool) void {
114 if (!ok) {
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 }
118 if (!ok) unreachable; // assertion failure
142119}
143120
144121pub fn panic(comptime format: []const u8, args: ...) noreturn {
......@@ -247,8 +224,7 @@ pub fn writeCurrentStackTraceWindows(
247224 start_addr: ?usize,
248225) !void {
249226 var addr_buf: [1024]usize = undefined;
250 const casted_len = @intCast(u32, addr_buf.len); // TODO shouldn't need this cast
251 const n = windows.RtlCaptureStackBackTrace(0, casted_len, @ptrCast(**c_void, &addr_buf), null);
227 const n = windows.RtlCaptureStackBackTrace(0, addr_buf.len, @ptrCast(**c_void, &addr_buf), null);
252228 const addrs = addr_buf[0..n];
253229 var start_i: usize = if (start_addr) |saddr| blk: {
254230 for (addrs) |addr, i| {
......@@ -264,7 +240,7 @@ pub fn writeCurrentStackTraceWindows(
264240pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {
265241 switch (builtin.os) {
266242 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),
268244 builtin.Os.windows => return printSourceAtAddressWindows(debug_info, out_stream, address, tty_color),
269245 else => return error.UnsupportedOperatingSystem,
270246 }
......@@ -338,50 +314,74 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
338314
339315 switch (subsect_hdr.Kind) {
340316 pdb.DebugSubsectionKind.Lines => {
341 var line_index: usize = sect_offset;
317 var line_index = sect_offset;
342318
343319 const line_hdr = @ptrCast(*pdb.LineFragmentHeader, &subsect_info[line_index]);
344320 if (line_hdr.RelocSegment == 0) return error.MissingDebugInfo;
345321 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
352322 const frag_vaddr_start = coff_section.header.virtual_address + line_hdr.RelocOffset;
353323 const frag_vaddr_end = frag_vaddr_start + line_hdr.CodeSize;
354 if (relative_address >= frag_vaddr_start and relative_address < frag_vaddr_end) {
355 var line_i: usize = 0;
324
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);
356332 const start_line_index = line_index;
357 while (line_i < block_hdr.NumLines) : (line_i += 1) {
358 const line_num_entry = @ptrCast(*pdb.LineNumberEntry, &subsect_info[line_index]);
359 line_index += @sizeOf(pdb.LineNumberEntry);
360 const flags = @ptrCast(*pdb.LineNumberEntry.Flags, &line_num_entry.Flags);
361 const vaddr_start = frag_vaddr_start + line_num_entry.Offset;
362 const vaddr_end = if (flags.End == 0) frag_vaddr_end else vaddr_start + flags.End;
363 if (relative_address >= vaddr_start and relative_address < vaddr_end) {
333
334 const has_column = line_hdr.Flags.LF_HaveColumns;
335
336 if (relative_address >= frag_vaddr_start and relative_address < frag_vaddr_end) {
337 // All line entries are stored inside their line block by ascending start address.
338 // Heuristic: we want to find the last line entry that has a vaddr_start <= relative_address.
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) {
364353 const subsect_index = checksum_offset + block_hdr.NameIndex;
365354 const chksum_hdr = @ptrCast(*pdb.FileChecksumEntryHeader, &mod.subsect_info[subsect_index]);
366355 const strtab_offset = @sizeOf(pdb.PDBStringTableHeader) + chksum_hdr.FileNameOffset;
367356 try di.pdb.string_table.seekTo(strtab_offset);
368357 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
370361 const column = if (has_column) blk: {
371 line_index = start_line_index + @sizeOf(pdb.LineNumberEntry) * block_hdr.NumLines;
372 line_index += @sizeOf(pdb.ColumnNumberEntry) * line_i;
373 const col_num_entry = @ptrCast(*pdb.ColumnNumberEntry, &subsect_info[line_index]);
362 const start_col_index = start_line_index + @sizeOf(pdb.LineNumberEntry) * block_hdr.NumLines;
363 const col_index = start_col_index + @sizeOf(pdb.ColumnNumberEntry) * line_entry_idx;
364 const col_num_entry = @ptrCast(*pdb.ColumnNumberEntry, &subsect_info[col_index]);
374365 break :blk col_num_entry.StartColumn;
375366 } 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
376372 break :subsections LineInfo{
377373 .allocator = allocator,
378374 .file_name = source_file_name,
379 .line = line,
375 .line = flags.Start,
380376 .column = column,
381377 };
382378 }
383379 }
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;
385385 }
386386 },
387387 else => {},
......@@ -523,7 +523,7 @@ fn populateModule(di: *DebugInfo, mod: *Module) !void {
523523
524524 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);
527527 if (signature != 4)
528528 return error.InvalidDebugInfo;
529529
......@@ -717,7 +717,7 @@ pub const OpenSelfDebugInfoError = error{
717717
718718pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo {
719719 switch (builtin.os) {
720 builtin.Os.linux => return openSelfDebugInfoLinux(allocator),
720 builtin.Os.linux, builtin.Os.freebsd => return openSelfDebugInfoLinux(allocator),
721721 builtin.Os.macosx, builtin.Os.ios => return openSelfDebugInfoMacOs(allocator),
722722 builtin.Os.windows => return openSelfDebugInfoWindows(allocator),
723723 else => return error.UnsupportedOperatingSystem,
......@@ -728,7 +728,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
728728 const self_file = try os.openSelfExe();
729729 defer self_file.close();
730730
731 const coff_obj = try allocator.createOne(coff.Coff);
731 const coff_obj = try allocator.create(coff.Coff);
732732 coff_obj.* = coff.Coff{
733733 .in_file = self_file,
734734 .allocator = allocator,
......@@ -752,14 +752,14 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
752752 const len = try di.coff.getPdbPath(path_buf[0..]);
753753 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
757757 try di.pdb.openFile(di.coff, path);
758758
759759 var pdb_stream = di.pdb.getStream(pdb.StreamType.Pdb) orelse return error.InvalidDebugInfo;
760 const version = try pdb_stream.stream.readIntLe(u32);
761 const signature = try pdb_stream.stream.readIntLe(u32);
762 const age = try pdb_stream.stream.readIntLe(u32);
760 const version = try pdb_stream.stream.readIntLittle(u32);
761 const signature = try pdb_stream.stream.readIntLittle(u32);
762 const age = try pdb_stream.stream.readIntLittle(u32);
763763 var guid: [16]u8 = undefined;
764764 try pdb_stream.stream.readNoEof(guid[0..]);
765765 if (!mem.eql(u8, di.coff.guid, guid) or di.coff.age != age)
......@@ -767,7 +767,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
767767 // We validated the executable and pdb match.
768768
769769 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);
771771 const name_bytes = try allocator.alloc(u8, name_bytes_len);
772772 try pdb_stream.stream.readNoEof(name_bytes);
773773
......@@ -797,8 +797,8 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
797797 };
798798 const bucket_list = try allocator.alloc(Bucket, present.len);
799799 for (present) |_| {
800 const name_offset = try pdb_stream.stream.readIntLe(u32);
801 const name_index = try pdb_stream.stream.readIntLe(u32);
800 const name_offset = try pdb_stream.stream.readIntLittle(u32);
801 const name_index = try pdb_stream.stream.readIntLittle(u32);
802802 const name = mem.toSlice(u8, name_bytes.ptr + name_offset);
803803 if (mem.eql(u8, name, "/names")) {
804804 break :str_tab_index name_index;
......@@ -859,7 +859,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
859859 var sect_contribs = ArrayList(pdb.SectionContribEntry).init(allocator);
860860 var sect_cont_offset: usize = 0;
861861 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));
863863 if (ver != pdb.SectionContrSubstreamVersion.Ver60)
864864 return error.InvalidDebugInfo;
865865 sect_cont_offset += @sizeOf(u32);
......@@ -879,11 +879,11 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
879879}
880880
881881fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {
882 const num_words = try stream.readIntLe(u32);
882 const num_words = try stream.readIntLittle(u32);
883883 var word_i: usize = 0;
884884 var list = ArrayList(usize).init(allocator);
885885 while (word_i != num_words) : (word_i += 1) {
886 const word = try stream.readIntLe(u32);
886 const word = try stream.readIntLittle(u32);
887887 var bit_i: u5 = 0;
888888 while (true) : (bit_i += 1) {
889889 if (word & (u32(1) << bit_i) != 0) {
......@@ -1013,7 +1013,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
10131013 }
10141014 }
10151015 }
1016 const sentinel = try allocator.createOne(macho.nlist_64);
1016 const sentinel = try allocator.create(macho.nlist_64);
10171017 sentinel.* = macho.nlist_64{
10181018 .n_strx = 0,
10191019 .n_type = 36,
......@@ -1135,14 +1135,13 @@ pub const DebugInfo = switch (builtin.os) {
11351135 return self.ofiles.allocator;
11361136 }
11371137 },
1138 builtin.Os.windows => struct {
1138 builtin.Os.uefi, builtin.Os.windows => struct {
11391139 pdb: pdb.Pdb,
11401140 coff: *coff.Coff,
11411141 sect_contribs: []pdb.SectionContribEntry,
11421142 modules: []Module,
11431143 },
1144 builtin.Os.linux => DwarfInfo,
1145 builtin.Os.freebsd => struct {},
1144 builtin.Os.linux, builtin.Os.freebsd => DwarfInfo,
11461145 else => @compileError("Unsupported OS"),
11471146};
11481147
......@@ -1200,7 +1199,7 @@ const Constant = struct {
12001199 fn asUnsignedLe(self: *const Constant) !u64 {
12011200 if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo;
12021201 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);
12041203 }
12051204};
12061205
......@@ -1331,7 +1330,7 @@ const LineNumberProgram = struct {
13311330 return error.InvalidDebugInfo;
13321331 } else
13331332 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 });
13351334 errdefer self.file_entries.allocator.free(file_name);
13361335 return LineInfo{
13371336 .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
13811380}
13821381
13831382fn 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);
13851384 return parseFormValueBlockLen(allocator, in_stream, block_len);
13861385}
13871386
......@@ -1395,11 +1394,11 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo
13951394}
13961395
13971396fn 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));
13991398}
14001399
14011400fn 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;
14031402}
14041403
14051404fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
......@@ -1408,7 +1407,7 @@ fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize)
14081407}
14091408
14101409fn 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);
14121411 return parseFormValueRefLen(allocator, in_stream, block_len);
14131412}
14141413
......@@ -1450,7 +1449,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
14501449 },
14511450
14521451 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
14551454 DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },
14561455 DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
......@@ -1747,11 +1746,11 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr
17471746 continue;
17481747 }
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);
17511750 // TODO support 3 and 5
17521751 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);
17551754 const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length;
17561755
17571756 const minimum_instruction_length = try di.dwarf_in_stream.readByte();
......@@ -1820,7 +1819,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr
18201819 return error.MissingDebugInfo;
18211820 },
18221821 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);
18241823 prog.address = addr;
18251824 },
18261825 DW.LNE_define_file => {
......@@ -1882,7 +1881,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr
18821881 prog.address += inc_addr;
18831882 },
18841883 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);
18861885 prog.address += arg;
18871886 },
18881887 DW.LNS_set_prologue_end => {},
......@@ -1914,10 +1913,10 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void {
19141913 if (unit_length == 0) return;
19151914 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);
19181917 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
19221921 const address_size = try di.dwarf_in_stream.readByte();
19231922 if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
......@@ -1927,7 +1926,8 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void {
19271926
19281927 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
19321932 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 {
19781978 if (di.debug_ranges) |debug_ranges| {
19791979 try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset);
19801980 while (true) {
1981 const begin_addr = try di.dwarf_in_stream.readIntLe(usize);
1982 const end_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.readIntLittle(usize);
19831983 if (begin_addr == 0 and end_addr == 0) {
19841984 break;
19851985 }
......@@ -2001,7 +2001,8 @@ fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit {
20012001}
20022002
20032003fn 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);
20052006 ptr.* += @sizeOf(T);
20062007 return result;
20072008}
......@@ -2017,11 +2018,12 @@ fn readByteSignedMem(ptr: *[*]const u8) i8 {
20172018}
20182019
20192020fn 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]);
20212023 is_64.* = (first_32_bits == 0xffffffff);
20222024 if (is_64.*) {
20232025 ptr.* += 4;
2024 const result = mem.readIntLE(u64, ptr.*[0..8]);
2026 const result = mem.readIntSliceLittle(u64, ptr.*[0..8]);
20252027 ptr.* += 8;
20262028 return result;
20272029 } else {
......@@ -2084,10 +2086,10 @@ fn readILeb128Mem(ptr: *[*]const u8) !i64 {
20842086}
20852087
20862088fn 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);
20882090 is_64.* = (first_32_bits == 0xffffffff);
20892091 if (is_64.*) {
2090 return in_stream.readIntLe(u64);
2092 return in_stream.readIntLittle(u64);
20912093 } else {
20922094 if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo;
20932095 return u64(first_32_bits);
std/dynamic_library.zig+3-4
......@@ -6,6 +6,7 @@ const mem = std.mem;
66const cstr = std.cstr;
77const os = std.os;
88const assert = std.debug.assert;
9const testing = std.testing;
910const elf = std.elf;
1011const linux = os.linux;
1112const windows = os.windows;
......@@ -19,7 +20,6 @@ pub const DynLib = switch (builtin.os) {
1920};
2021
2122pub const LinuxDynLib = struct {
22 allocator: *mem.Allocator,
2323 elf_lib: ElfLib,
2424 fd: i32,
2525 map_addr: usize,
......@@ -27,7 +27,7 @@ pub const LinuxDynLib = struct {
2727
2828 /// Trusts the file
2929 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);
3131 errdefer std.os.close(fd);
3232
3333 const size = @intCast(usize, (try std.os.posixFStat(fd)).size);
......@@ -45,7 +45,6 @@ pub const LinuxDynLib = struct {
4545 const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size];
4646
4747 return DynLib{
48 .allocator = allocator,
4948 .elf_lib = try ElfLib.init(bytes),
5049 .fd = fd,
5150 .map_addr = addr,
......@@ -208,7 +207,7 @@ test "dynamic_library" {
208207 };
209208
210209 const dynlib = DynLib.open(std.debug.global_allocator, libname) catch |err| {
211 assert(err == error.FileNotFound);
210 testing.expect(err == error.FileNotFound);
212211 return;
213212 };
214213 @panic("Expected error from function");
std/elf.zig+35-35
......@@ -412,7 +412,7 @@ pub const Elf = struct {
412412 // skip over padding
413413 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)) {
416416 1 => FileType.Relocatable,
417417 2 => FileType.Executable,
418418 3 => FileType.Shared,
......@@ -420,7 +420,7 @@ pub const Elf = struct {
420420 else => return error.InvalidFormat,
421421 };
422422
423 elf.arch = switch (try in.readInt(elf.endian, u16)) {
423 elf.arch = switch (try in.readInt(u16, elf.endian)) {
424424 0x02 => Arch.Sparc,
425425 0x03 => Arch.x86,
426426 0x08 => Arch.Mips,
......@@ -433,32 +433,32 @@ pub const Elf = struct {
433433 else => return error.InvalidFormat,
434434 };
435435
436 const elf_version = try in.readInt(elf.endian, u32);
436 const elf_version = try in.readInt(u32, elf.endian);
437437 if (elf_version != 1) return error.InvalidFormat;
438438
439439 if (elf.is_64) {
440 elf.entry_addr = try in.readInt(elf.endian, u64);
441 elf.program_header_offset = try in.readInt(elf.endian, u64);
442 elf.section_header_offset = try in.readInt(elf.endian, u64);
440 elf.entry_addr = try in.readInt(u64, elf.endian);
441 elf.program_header_offset = try in.readInt(u64, elf.endian);
442 elf.section_header_offset = try in.readInt(u64, elf.endian);
443443 } else {
444 elf.entry_addr = u64(try in.readInt(elf.endian, u32));
445 elf.program_header_offset = u64(try in.readInt(elf.endian, u32));
446 elf.section_header_offset = 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(u32, elf.endian));
446 elf.section_header_offset = u64(try in.readInt(u32, elf.endian));
447447 }
448448
449449 // skip over flags
450450 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);
453453 if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) {
454454 return error.InvalidFormat;
455455 }
456456
457 const ph_entry_size = try in.readInt(elf.endian, u16);
458 const ph_entry_count = try in.readInt(elf.endian, u16);
459 const sh_entry_size = try in.readInt(elf.endian, u16);
460 const sh_entry_count = try in.readInt(elf.endian, u16);
461 elf.string_section_index = u64(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(u16, elf.endian);
459 const sh_entry_size = try in.readInt(u16, elf.endian);
460 const sh_entry_count = try in.readInt(u16, elf.endian);
461 elf.string_section_index = u64(try in.readInt(u16, elf.endian));
462462
463463 if (elf.string_section_index >= sh_entry_count) return error.InvalidFormat;
464464
......@@ -481,32 +481,32 @@ pub const Elf = struct {
481481 if (sh_entry_size != 64) return error.InvalidFormat;
482482
483483 for (elf.section_headers) |*elf_section| {
484 elf_section.name = try in.readInt(elf.endian, u32);
485 elf_section.sh_type = try in.readInt(elf.endian, u32);
486 elf_section.flags = try in.readInt(elf.endian, u64);
487 elf_section.addr = try in.readInt(elf.endian, u64);
488 elf_section.offset = try in.readInt(elf.endian, u64);
489 elf_section.size = try in.readInt(elf.endian, u64);
490 elf_section.link = try in.readInt(elf.endian, u32);
491 elf_section.info = try in.readInt(elf.endian, u32);
492 elf_section.addr_align = try in.readInt(elf.endian, u64);
493 elf_section.ent_size = try in.readInt(elf.endian, u64);
484 elf_section.name = try in.readInt(u32, elf.endian);
485 elf_section.sh_type = try in.readInt(u32, elf.endian);
486 elf_section.flags = try in.readInt(u64, elf.endian);
487 elf_section.addr = try in.readInt(u64, elf.endian);
488 elf_section.offset = try in.readInt(u64, elf.endian);
489 elf_section.size = try in.readInt(u64, elf.endian);
490 elf_section.link = try in.readInt(u32, elf.endian);
491 elf_section.info = try in.readInt(u32, elf.endian);
492 elf_section.addr_align = try in.readInt(u64, elf.endian);
493 elf_section.ent_size = try in.readInt(u64, elf.endian);
494494 }
495495 } else {
496496 if (sh_entry_size != 40) return error.InvalidFormat;
497497
498498 for (elf.section_headers) |*elf_section| {
499499 // TODO (multiple occurrences) allow implicit cast from %u32 -> %u64 ?
500 elf_section.name = try in.readInt(elf.endian, u32);
501 elf_section.sh_type = try in.readInt(elf.endian, u32);
502 elf_section.flags = u64(try in.readInt(elf.endian, u32));
503 elf_section.addr = u64(try in.readInt(elf.endian, u32));
504 elf_section.offset = u64(try in.readInt(elf.endian, u32));
505 elf_section.size = u64(try in.readInt(elf.endian, u32));
506 elf_section.link = try in.readInt(elf.endian, u32);
507 elf_section.info = try in.readInt(elf.endian, u32);
508 elf_section.addr_align = u64(try in.readInt(elf.endian, u32));
509 elf_section.ent_size = u64(try in.readInt(elf.endian, u32));
500 elf_section.name = try in.readInt(u32, elf.endian);
501 elf_section.sh_type = try in.readInt(u32, elf.endian);
502 elf_section.flags = u64(try in.readInt(u32, elf.endian));
503 elf_section.addr = u64(try in.readInt(u32, elf.endian));
504 elf_section.offset = u64(try in.readInt(u32, elf.endian));
505 elf_section.size = u64(try in.readInt(u32, elf.endian));
506 elf_section.link = try in.readInt(u32, elf.endian);
507 elf_section.info = try in.readInt(u32, elf.endian);
508 elf_section.addr_align = u64(try in.readInt(u32, elf.endian));
509 elf_section.ent_size = u64(try in.readInt(u32, elf.endian));
510510 }
511511 }
512512
std/event/channel.zig+11-6
......@@ -1,6 +1,7 @@
11const std = @import("../index.zig");
22const builtin = @import("builtin");
33const assert = std.debug.assert;
4const testing = std.testing;
45const AtomicRmwOp = builtin.AtomicRmwOp;
56const AtomicOrder = builtin.AtomicOrder;
67const Loop = std.event.Loop;
......@@ -54,7 +55,8 @@ pub fn Channel(comptime T: type) type {
5455 const buffer_nodes = try loop.allocator.alloc(T, capacity);
5556 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{
5860 .loop = loop,
5961 .buffer_len = 0,
6062 .buffer_nodes = buffer_nodes,
......@@ -66,7 +68,7 @@ pub fn Channel(comptime T: type) type {
6668 .or_null_queue = std.atomic.Queue(*std.atomic.Queue(GetNode).Node).init(),
6769 .get_count = 0,
6870 .put_count = 0,
69 });
71 };
7072 errdefer loop.allocator.destroy(self);
7173
7274 return self;
......@@ -319,6 +321,9 @@ pub fn Channel(comptime T: type) type {
319321}
320322
321323test "std.event.Channel" {
324 // https://github.com/ziglang/zig/issues/1908
325 if (builtin.single_threaded) return error.SkipZigTest;
326
322327 var da = std.heap.DirectAllocator.init();
323328 defer da.deinit();
324329
......@@ -346,19 +351,19 @@ async fn testChannelGetter(loop: *Loop, channel: *Channel(i32)) void {
346351
347352 const value1_promise = try async channel.get();
348353 const value1 = await value1_promise;
349 assert(value1 == 1234);
354 testing.expect(value1 == 1234);
350355
351356 const value2_promise = try async channel.get();
352357 const value2 = await value2_promise;
353 assert(value2 == 4567);
358 testing.expect(value2 == 4567);
354359
355360 const value3_promise = try async channel.getOrNull();
356361 const value3 = await value3_promise;
357 assert(value3 == null);
362 testing.expect(value3 == null);
358363
359364 const last_put = try async testPut(channel, 4444);
360365 const value4 = await try async channel.getOrNull();
361 assert(value4.? == 4444);
366 testing.expect(value4.? == 4444);
362367 await last_put;
363368}
364369
std/event/fs.zig+34-36
......@@ -2,6 +2,7 @@ const builtin = @import("builtin");
22const std = @import("../index.zig");
33const event = std.event;
44const assert = std.debug.assert;
5const testing = std.testing;
56const os = std.os;
67const mem = std.mem;
78const posix = os.posix;
......@@ -495,7 +496,7 @@ pub const CloseOperation = struct {
495496 };
496497
497498 pub fn start(loop: *Loop) (error{OutOfMemory}!*CloseOperation) {
498 const self = try loop.allocator.createOne(CloseOperation);
499 const self = try loop.allocator.create(CloseOperation);
499500 self.* = CloseOperation{
500501 .loop = loop,
501502 .os_data = switch (builtin.os) {
......@@ -787,7 +788,7 @@ pub fn Watch(comptime V: type) type {
787788 },
788789
789790 builtin.Os.windows => {
790 const self = try loop.allocator.createOne(Self);
791 const self = try loop.allocator.create(Self);
791792 errdefer loop.allocator.destroy(self);
792793 self.* = Self{
793794 .channel = channel,
......@@ -802,7 +803,7 @@ pub fn Watch(comptime V: type) type {
802803 },
803804
804805 builtin.Os.macosx, builtin.Os.freebsd => {
805 const self = try loop.allocator.createOne(Self);
806 const self = try loop.allocator.create(Self);
806807 errdefer loop.allocator.destroy(self);
807808
808809 self.* = Self{
......@@ -871,7 +872,7 @@ pub fn Watch(comptime V: type) type {
871872 }
872873
873874 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});
875876 var resolved_path_consumed = false;
876877 defer if (!resolved_path_consumed) self.channel.loop.allocator.free(resolved_path);
877878
......@@ -1068,7 +1069,7 @@ pub fn Watch(comptime V: type) type {
10681069 }
10691070 } else {
10701071 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);
10721073 errdefer self.channel.loop.allocator.destroy(dir);
10731074
10741075 dir.* = OsData.Dir{
......@@ -1307,39 +1308,36 @@ pub fn Watch(comptime V: type) type {
13071308
13081309const test_tmp_dir = "std_event_fs_test";
13091310
1310test "write a file, watch it, write it again" {
1311 if (builtin.os == builtin.Os.windows) {
1312 // TODO this test is disabled on windows until the coroutine rewrite is finished.
1313 // https://github.com/ziglang/zig/issues/1363
1314 return error.SkipZigTest;
1315 }
1316 var da = std.heap.DirectAllocator.init();
1317 defer da.deinit();
1318
1319 const allocator = &da.allocator;
1320
1321 // TODO move this into event loop too
1322 try os.makePath(allocator, test_tmp_dir);
1323 defer os.deleteTree(allocator, test_tmp_dir) catch {};
1324
1325 var loop: Loop = undefined;
1326 try loop.initMultiThreaded(allocator);
1327 defer loop.deinit();
1328
1329 var result: anyerror!void = error.ResultNeverWritten;
1330 const handle = try async<allocator> testFsWatchCantFail(&loop, &result);
1331 defer cancel handle;
1332
1333 loop.run();
1334 return result;
1335}
1311// TODO this test is disabled until the coroutine rewrite is finished.
1312//test "write a file, watch it, write it again" {
1313// return error.SkipZigTest;
1314// var da = std.heap.DirectAllocator.init();
1315// defer da.deinit();
1316//
1317// const allocator = &da.allocator;
1318//
1319// // TODO move this into event loop too
1320// try os.makePath(allocator, test_tmp_dir);
1321// defer os.deleteTree(allocator, test_tmp_dir) catch {};
1322//
1323// var loop: Loop = undefined;
1324// try loop.initMultiThreaded(allocator);
1325// defer loop.deinit();
1326//
1327// var result: anyerror!void = error.ResultNeverWritten;
1328// const handle = try async<allocator> testFsWatchCantFail(&loop, &result);
1329// defer cancel handle;
1330//
1331// loop.run();
1332// return result;
1333//}
13361334
13371335async fn testFsWatchCantFail(loop: *Loop, result: *(anyerror!void)) void {
13381336 result.* = await (async testFsWatch(loop) catch unreachable);
13391337}
13401338
13411339async 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" });
13431341 defer loop.allocator.free(file_path);
13441342
13451343 const contents =
......@@ -1352,13 +1350,13 @@ async fn testFsWatch(loop: *Loop) !void {
13521350 try await try async writeFile(loop, file_path, contents);
13531351
13541352 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
13571355 // now watch the file
13581356 var watch = try Watch(void).create(loop, 0);
13591357 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
13631361 const ev = try async watch.channel.get();
13641362 var ev_consumed = false;
......@@ -1378,10 +1376,10 @@ async fn testFsWatch(loop: *Loop) !void {
13781376 WatchEventId.Delete => @panic("wrong event"),
13791377 }
13801378 const contents_updated = try await try async readFile(loop, file_path, 1024 * 1024);
1381 assert(mem.eql(u8, contents_updated,
1379 testing.expectEqualSlices(u8,
13821380 \\line 1
13831381 \\lorem ipsum
1384 ));
1382 , contents_updated);
13851383
13861384 // TODO test deleting the file and then re-adding it. we should get events for both
13871385}
std/event/future.zig+5-1
......@@ -1,5 +1,6 @@
11const std = @import("../index.zig");
22const assert = std.debug.assert;
3const testing = std.testing;
34const builtin = @import("builtin");
45const AtomicRmwOp = builtin.AtomicRmwOp;
56const AtomicOrder = builtin.AtomicOrder;
......@@ -84,6 +85,9 @@ pub fn Future(comptime T: type) type {
8485}
8586
8687test "std.event.Future" {
88 // https://github.com/ziglang/zig/issues/1908
89 if (builtin.single_threaded) return error.SkipZigTest;
90
8791 var da = std.heap.DirectAllocator.init();
8892 defer da.deinit();
8993
......@@ -111,7 +115,7 @@ async fn testFuture(loop: *Loop) void {
111115
112116 const result = (await a) + (await b);
113117 cancel c;
114 assert(result == 12);
118 testing.expect(result == 12);
115119}
116120
117121async fn waitOnFuture(future: *Future(i32)) i32 {
std/event/group.zig+9-5
......@@ -4,7 +4,7 @@ const Lock = std.event.Lock;
44const Loop = std.event.Loop;
55const AtomicRmwOp = builtin.AtomicRmwOp;
66const AtomicOrder = builtin.AtomicOrder;
7const assert = std.debug.assert;
7const testing = std.testing;
88
99/// ReturnType must be `void` or `E!void`
1010pub fn Group(comptime ReturnType: type) type {
......@@ -42,10 +42,11 @@ pub fn Group(comptime ReturnType: type) type {
4242
4343 /// Add a promise to the group. Thread-safe.
4444 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{
4647 .next = undefined,
4748 .data = handle,
48 });
49 };
4950 self.alloc_stack.push(node);
5051 }
5152
......@@ -121,6 +122,9 @@ pub fn Group(comptime ReturnType: type) type {
121122}
122123
123124test "std.event.Group" {
125 // https://github.com/ziglang/zig/issues/1908
126 if (builtin.single_threaded) return error.SkipZigTest;
127
124128 var da = std.heap.DirectAllocator.init();
125129 defer da.deinit();
126130
......@@ -142,12 +146,12 @@ async fn testGroup(loop: *Loop) void {
142146 group.add(async sleepALittle(&count) catch @panic("memory")) catch @panic("memory");
143147 group.call(increaseByTen, &count) catch @panic("memory");
144148 await (async group.wait() catch @panic("memory"));
145 assert(count == 11);
149 testing.expect(count == 11);
146150
147151 var another = Group(anyerror!void).init(loop);
148152 another.add(async somethingElse() catch @panic("memory")) catch @panic("memory");
149153 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")));
151155}
152156
153157async fn sleepALittle(count: *usize) void {
std/event/io.zig+9-5
......@@ -39,18 +39,22 @@ pub fn InStream(comptime ReadError: type) type {
3939 if (amt_read < buf.len) return error.EndOfStream;
4040 }
4141
42 pub async fn readIntLe(self: *Self, comptime T: type) !T {
43 return await (async self.readInt(builtin.Endian.Little, T) catch unreachable);
42 pub async fn readIntLittle(self: *Self, comptime T: type) !T {
43 var bytes: [@sizeOf(T)]u8 = undefined;
44 try await (async self.readNoEof(bytes[0..]) catch unreachable);
45 return mem.readIntLittle(T, &bytes);
4446 }
4547
4648 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);
4852 }
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 {
5155 var bytes: [@sizeOf(T)]u8 = undefined;
5256 try await (async self.readNoEof(bytes[0..]) catch unreachable);
53 return mem.readInt(bytes, T, endian);
57 return mem.readInt(T, &bytes, endian);
5458 }
5559
5660 pub async fn readStruct(self: *Self, comptime T: type) !T {
std/event/lock.zig+5-1
......@@ -1,6 +1,7 @@
11const std = @import("../index.zig");
22const builtin = @import("builtin");
33const assert = std.debug.assert;
4const testing = std.testing;
45const mem = std.mem;
56const AtomicRmwOp = builtin.AtomicRmwOp;
67const AtomicOrder = builtin.AtomicOrder;
......@@ -122,6 +123,9 @@ pub const Lock = struct {
122123};
123124
124125test "std.event.Lock" {
126 // https://github.com/ziglang/zig/issues/1908
127 if (builtin.single_threaded) return error.SkipZigTest;
128
125129 var da = std.heap.DirectAllocator.init();
126130 defer da.deinit();
127131
......@@ -138,7 +142,7 @@ test "std.event.Lock" {
138142 defer cancel handle;
139143 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);
142146}
143147
144148async fn testLock(loop: *Loop, lock: *Lock) void {
std/event/loop.zig+25-2
......@@ -1,6 +1,7 @@
11const std = @import("../index.zig");
22const builtin = @import("builtin");
33const assert = std.debug.assert;
4const testing = std.testing;
45const mem = std.mem;
56const AtomicRmwOp = builtin.AtomicRmwOp;
67const AtomicOrder = builtin.AtomicOrder;
......@@ -97,6 +98,7 @@ pub const Loop = struct {
9798 /// TODO copy elision / named return values so that the threads referencing *Loop
9899 /// have the correct pointer value.
99100 pub fn initMultiThreaded(self: *Loop, allocator: *mem.Allocator) !void {
101 if (builtin.single_threaded) @compileError("initMultiThreaded unavailable when building in single-threaded mode");
100102 const core_count = try os.cpuCount(allocator);
101103 return self.initInternal(allocator, core_count);
102104 }
......@@ -201,6 +203,11 @@ pub const Loop = struct {
201203 self.os_data.fs_thread.wait();
202204 }
203205
206 if (builtin.single_threaded) {
207 assert(extra_thread_count == 0);
208 return;
209 }
210
204211 var extra_thread_index: usize = 0;
205212 errdefer {
206213 // writing 8 bytes to an eventfd cannot fail
......@@ -301,6 +308,11 @@ pub const Loop = struct {
301308 self.os_data.fs_thread.wait();
302309 }
303310
311 if (builtin.single_threaded) {
312 assert(extra_thread_count == 0);
313 return;
314 }
315
304316 var extra_thread_index: usize = 0;
305317 errdefer {
306318 _ = os.bsdKEvent(self.os_data.kqfd, final_kev_arr, empty_kevs, null) catch unreachable;
......@@ -338,6 +350,11 @@ pub const Loop = struct {
338350 self.available_eventfd_resume_nodes.push(eventfd_node);
339351 }
340352
353 if (builtin.single_threaded) {
354 assert(extra_thread_count == 0);
355 return;
356 }
357
341358 var extra_thread_index: usize = 0;
342359 errdefer {
343360 var i: usize = 0;
......@@ -845,6 +862,9 @@ pub const Loop = struct {
845862};
846863
847864test "std.event.Loop - basic" {
865 // https://github.com/ziglang/zig/issues/1908
866 if (builtin.single_threaded) return error.SkipZigTest;
867
848868 var da = std.heap.DirectAllocator.init();
849869 defer da.deinit();
850870
......@@ -858,6 +878,9 @@ test "std.event.Loop - basic" {
858878}
859879
860880test "std.event.Loop - call" {
881 // https://github.com/ziglang/zig/issues/1908
882 if (builtin.single_threaded) return error.SkipZigTest;
883
861884 var da = std.heap.DirectAllocator.init();
862885 defer da.deinit();
863886
......@@ -874,7 +897,7 @@ test "std.event.Loop - call" {
874897
875898 loop.run();
876899
877 assert(did_it);
900 testing.expect(did_it);
878901}
879902
880903async fn testEventLoop() i32 {
......@@ -883,6 +906,6 @@ async fn testEventLoop() i32 {
883906
884907async fn testEventLoop2(h: promise->i32, did_it: *bool) void {
885908 const value = await h;
886 assert(value == 1234);
909 testing.expect(value == 1234);
887910 did_it.* = true;
888911}
std/event/net.zig+5-2
......@@ -1,6 +1,6 @@
11const std = @import("../index.zig");
22const builtin = @import("builtin");
3const assert = std.debug.assert;
3const testing = std.testing;
44const event = std.event;
55const mem = std.mem;
66const os = std.os;
......@@ -269,6 +269,9 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !os.File {
269269}
270270
271271test "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
272275 if (builtin.os != builtin.Os.linux) {
273276 // TODO build abstractions for other operating systems
274277 return error.SkipZigTest;
......@@ -323,7 +326,7 @@ async fn doAsyncTest(loop: *Loop, address: *const std.net.Address, server: *Serv
323326 var buf: [512]u8 = undefined;
324327 const amt_read = try socket_file.read(buf[0..]);
325328 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"));
327330 server.close();
328331}
329332
std/event/rwlock.zig+7-3
......@@ -1,6 +1,7 @@
11const std = @import("../index.zig");
22const builtin = @import("builtin");
33const assert = std.debug.assert;
4const testing = std.testing;
45const mem = std.mem;
56const AtomicRmwOp = builtin.AtomicRmwOp;
67const AtomicOrder = builtin.AtomicOrder;
......@@ -211,6 +212,9 @@ pub const RwLock = struct {
211212};
212213
213214test "std.event.RwLock" {
215 // https://github.com/ziglang/zig/issues/1908
216 if (builtin.single_threaded) return error.SkipZigTest;
217
214218 var da = std.heap.DirectAllocator.init();
215219 defer da.deinit();
216220
......@@ -228,7 +232,7 @@ test "std.event.RwLock" {
228232 loop.run();
229233
230234 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);
232236}
233237
234238async fn testLock(loop: *Loop, lock: *RwLock) void {
......@@ -290,7 +294,7 @@ async fn readRunner(lock: *RwLock) void {
290294 const handle = await lock_promise;
291295 defer handle.release();
292296
293 assert(shared_test_index == 0);
294 assert(shared_test_data[i] == @intCast(i32, shared_count));
297 testing.expect(shared_test_index == 0);
298 testing.expect(shared_test_data[i] == @intCast(i32, shared_count));
295299 }
296300}
std/fmt/index.zig+125-83
......@@ -2,7 +2,7 @@ const std = @import("../index.zig");
22const math = std.math;
33const debug = std.debug;
44const assert = debug.assert;
5const assertError = debug.assertError;
5const testing = std.testing;
66const mem = std.mem;
77const builtin = @import("builtin");
88const errol = @import("errol/index.zig");
......@@ -117,7 +117,7 @@ pub fn formatType(
117117 return output(context, @errorName(value));
118118 }
119119 switch (@typeInfo(T)) {
120 builtin.TypeId.Int, builtin.TypeId.Float => {
120 builtin.TypeId.ComptimeInt, builtin.TypeId.Int, builtin.TypeId.Float => {
121121 return formatValue(value, fmt, context, Errors, output);
122122 },
123123 builtin.TypeId.Void => {
......@@ -236,6 +236,9 @@ pub fn formatType(
236236 const casted_value = ([]const u8)(value);
237237 return output(context, casted_value);
238238 },
239 builtin.TypeInfo.Pointer.Size.C => {
240 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(value));
241 },
239242 },
240243 builtin.TypeId.Array => |info| {
241244 if (info.child == u8) {
......@@ -243,6 +246,9 @@ pub fn formatType(
243246 }
244247 return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value));
245248 },
249 builtin.TypeId.Fn => {
250 return format(context, Errors, output, "{}@{x}", @typeName(T), @ptrToInt(value));
251 },
246252 else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
247253 }
248254}
......@@ -268,11 +274,15 @@ fn formatValue(
268274 }
269275 }
270276
271 comptime var T = @typeOf(value);
277 const T = @typeOf(value);
272278 switch (@typeId(T)) {
273279 builtin.TypeId.Float => return formatFloatValue(value, fmt, context, Errors, output),
274280 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,
276286 }
277287}
278288
......@@ -289,9 +299,10 @@ pub fn formatIntValue(
289299 if (fmt.len > 0) {
290300 switch (fmt[0]) {
291301 'c' => {
292 if (@typeOf(value) == u8) {
293 if (fmt.len > 1) @compileError("Unknown format character: " ++ []u8{fmt[1]});
294 return formatAsciiChar(value, context, Errors, output);
302 if (@typeOf(value).bit_count <= 8) {
303 if (fmt.len > 1)
304 @compileError("Unknown format character: " ++ []u8{fmt[1]});
305 return formatAsciiChar(u8(value), context, Errors, output);
295306 }
296307 },
297308 'b' => {
......@@ -580,7 +591,7 @@ pub fn formatFloatDecimal(
580591 }
581592
582593 // Remaining fractional portion, zero-padding if insufficient.
583 debug.assert(precision >= printed);
594 assert(precision >= printed);
584595 if (num_digits_whole_no_pad + precision - printed < float_decimal.digits.len) {
585596 try output(context, float_decimal.digits[num_digits_whole_no_pad .. num_digits_whole_no_pad + precision - printed]);
586597 return;
......@@ -790,13 +801,13 @@ pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {
790801}
791802
792803test "fmt.parseInt" {
793 assert((parseInt(i32, "-10", 10) catch unreachable) == -10);
794 assert((parseInt(i32, "+10", 10) catch unreachable) == 10);
795 assert(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidCharacter);
796 assert(if (parseInt(i32, "10 ", 10)) |_| false else |err| err == error.InvalidCharacter);
797 assert(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter);
798 assert((parseInt(u8, "255", 10) catch unreachable) == 255);
799 assert(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
804 testing.expect((parseInt(i32, "-10", 10) catch unreachable) == -10);
805 testing.expect((parseInt(i32, "+10", 10) catch unreachable) == 10);
806 testing.expect(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);
808 testing.expect(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter);
809 testing.expect((parseInt(u8, "255", 10) catch unreachable) == 255);
810 testing.expect(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
800811}
801812
802813const ParseUnsignedError = error{
......@@ -820,31 +831,37 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned
820831 return x;
821832}
822833
823test "parseUnsigned" {
824 assert((try parseUnsigned(u16, "050124", 10)) == 50124);
825 assert((try parseUnsigned(u16, "65535", 10)) == 65535);
826 assertError(parseUnsigned(u16, "65536", 10), error.Overflow);
834test "fmt.parseUnsigned" {
835 testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);
836 testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);
837 testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
827838
828 assert((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);
829 assertError(parseUnsigned(u64, "10000000000000000", 16), error.Overflow);
839 testing.expect((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);
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);
834 assert((try parseUnsigned(u7, "1000", 2)) == 8);
844 testing.expect((try parseUnsigned(u7, "1", 10)) == 1);
845 testing.expect((try parseUnsigned(u7, "1000", 2)) == 8);
835846
836 assertError(parseUnsigned(u32, "f", 10), error.InvalidCharacter);
837 assertError(parseUnsigned(u8, "109", 8), error.InvalidCharacter);
847 testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10));
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
841852 // these numbers should fit even though the radix itself doesn't fit in the destination type
842 assert((try parseUnsigned(u1, "0", 10)) == 0);
843 assert((try parseUnsigned(u1, "1", 10)) == 1);
844 assertError(parseUnsigned(u1, "2", 10), error.Overflow);
845 assert((try parseUnsigned(u1, "001", 16)) == 1);
846 assert((try parseUnsigned(u2, "3", 16)) == 3);
847 assertError(parseUnsigned(u2, "4", 16), error.Overflow);
853 testing.expect((try parseUnsigned(u1, "0", 10)) == 0);
854 testing.expect((try parseUnsigned(u1, "1", 10)) == 1);
855 testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10));
856 testing.expect((try parseUnsigned(u1, "001", 16)) == 1);
857 testing.expect((try parseUnsigned(u2, "3", 16)) == 3);
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");
848865}
849866
850867pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
......@@ -902,19 +919,19 @@ fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
902919test "buf print int" {
903920 var buffer: [max_int_digits]u8 = undefined;
904921 const buf = buffer[0..];
905 assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 2, false, 0), "-101111000110000101001110"));
906 assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 10, false, 0), "-12345678"));
907 assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, false, 0), "-bc614e"));
908 assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, true, 0), "-BC614E"));
922 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 2, false, 0), "-101111000110000101001110"));
923 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 10, false, 0), "-12345678"));
924 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, false, 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"));
913 assert(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 6), "001234"));
914 assert(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 1), "1234"));
929 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(666), 10, false, 6), "000666"));
930 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 6), "001234"));
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"));
917 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"));
934 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, i32(-42), 10, false, 3), "-42"));
918935}
919936
920937fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, width: usize) []u8 {
......@@ -931,7 +948,7 @@ test "parse u64 digit too big" {
931948
932949test "parse unsigned comptime" {
933950 comptime {
934 assert((try parseUnsigned(usize, "2", 10)) == 2);
951 testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
935952 }
936953}
937954
......@@ -964,6 +981,23 @@ test "fmt.format" {
964981 const value: u8 = 0b1100;
965982 try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", value);
966983 }
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 }
9671001 {
9681002 const value: [3]u8 = "abc";
9691003 try testFmt("array: abc\n", "array: {}\n", value);
......@@ -985,6 +1019,14 @@ test "fmt.format" {
9851019 try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", value);
9861020 try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", value);
9871021 }
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 }
9881030 try testFmt("buf: Test \n", "buf: {s5}\n", "Test");
9891031 try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test");
9901032 try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C");
......@@ -1020,19 +1062,19 @@ test "fmt.format" {
10201062 var buf1: [32]u8 = undefined;
10211063 const value: f32 = 1.34;
10221064 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"));
10241066 }
10251067 {
10261068 var buf1: [32]u8 = undefined;
10271069 const value: f32 = 12.34;
10281070 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"));
10301072 }
10311073 {
10321074 var buf1: [32]u8 = undefined;
10331075 const value: f64 = -12.34e10;
10341076 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"));
10361078 }
10371079 {
10381080 // This fails on release due to a minor rounding difference.
......@@ -1042,26 +1084,26 @@ test "fmt.format" {
10421084 var buf1: [32]u8 = undefined;
10431085 const value: f64 = 9.999960e-40;
10441086 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"));
10461088 }
10471089 }
10481090 {
10491091 var buf1: [32]u8 = undefined;
10501092 const value: f64 = 1.409706e-42;
10511093 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"));
10531095 }
10541096 {
10551097 var buf1: [32]u8 = undefined;
10561098 const value: f64 = @bitCast(f32, u32(814313563));
10571099 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"));
10591101 }
10601102 {
10611103 var buf1: [32]u8 = undefined;
10621104 const value: f64 = @bitCast(f32, u32(1006632960));
10631105 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"));
10651107 }
10661108 {
10671109 // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.
......@@ -1069,47 +1111,47 @@ test "fmt.format" {
10691111 var buf1: [32]u8 = undefined;
10701112 const value: f64 = @bitCast(f32, u32(1203982400));
10711113 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"));
10731115 }
10741116 {
10751117 var buf1: [32]u8 = undefined;
10761118 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"));
10781120 }
10791121 if (builtin.arch != builtin.Arch.armv8) {
10801122 // negative nan is not defined by IEE 754,
10811123 // and ARM thus normalizes it to positive nan
10821124 var buf1: [32]u8 = undefined;
10831125 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"));
10851127 }
10861128 {
10871129 var buf1: [32]u8 = undefined;
10881130 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"));
10901132 }
10911133 {
10921134 var buf1: [32]u8 = undefined;
10931135 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"));
10951137 }
10961138 {
10971139 var buf1: [64]u8 = undefined;
10981140 const value: f64 = 1.52314e+29;
10991141 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"));
11011143 }
11021144 {
11031145 var buf1: [32]u8 = undefined;
11041146 const value: f32 = 1.1234;
11051147 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"));
11071149 }
11081150 {
11091151 var buf1: [32]u8 = undefined;
11101152 const value: f32 = 1234.567;
11111153 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"));
11131155 }
11141156 {
11151157 var buf1: [32]u8 = undefined;
......@@ -1117,92 +1159,92 @@ test "fmt.format" {
11171159 const result = try bufPrint(buf1[0..], "f32: {.4}\n", value);
11181160 // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
11191161 // -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"));
11211163 }
11221164 {
11231165 var buf1: [32]u8 = undefined;
11241166 const value: f32 = 91.12345;
11251167 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"));
11271169 }
11281170 {
11291171 var buf1: [32]u8 = undefined;
11301172 const value: f64 = 91.12345678901235;
11311173 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"));
11331175 }
11341176 {
11351177 var buf1: [32]u8 = undefined;
11361178 const value: f64 = 0.0;
11371179 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"));
11391181 }
11401182 {
11411183 var buf1: [32]u8 = undefined;
11421184 const value: f64 = 5.700;
11431185 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"));
11451187 }
11461188 {
11471189 var buf1: [32]u8 = undefined;
11481190 const value: f64 = 9.999;
11491191 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"));
11511193 }
11521194 {
11531195 var buf1: [32]u8 = undefined;
11541196 const value: f64 = 1.0;
11551197 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"));
11571199 }
11581200 {
11591201 var buf1: [32]u8 = undefined;
11601202 const value: f64 = 0.0003;
11611203 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"));
11631205 }
11641206 {
11651207 var buf1: [32]u8 = undefined;
11661208 const value: f64 = 1.40130e-45;
11671209 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"));
11691211 }
11701212 {
11711213 var buf1: [32]u8 = undefined;
11721214 const value: f64 = 9.999960e-40;
11731215 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"));
11751217 }
11761218 // libc checks
11771219 {
11781220 var buf1: [32]u8 = undefined;
11791221 const value: f64 = f64(@bitCast(f32, u32(916964781)));
11801222 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"));
11821224 }
11831225 {
11841226 var buf1: [32]u8 = undefined;
11851227 const value: f64 = f64(@bitCast(f32, u32(925353389)));
11861228 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"));
11881230 }
11891231 {
11901232 var buf1: [32]u8 = undefined;
11911233 const value: f64 = f64(@bitCast(f32, u32(1036831278)));
11921234 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"));
11941236 }
11951237 {
11961238 var buf1: [32]u8 = undefined;
11971239 const value: f64 = f64(@bitCast(f32, u32(1065353133)));
11981240 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"));
12001242 }
12011243 {
12021244 var buf1: [32]u8 = undefined;
12031245 const value: f64 = f64(@bitCast(f32, u32(1092616192)));
12041246 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"));
12061248 }
12071249 // libc differences
12081250 {
......@@ -1212,7 +1254,7 @@ test "fmt.format" {
12121254 // floats of the form x.yyyy25 on a precision point.
12131255 const value: f64 = f64(@bitCast(f32, u32(1015021568)));
12141256 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"));
12161258 }
12171259 // std-windows-x86_64-Debug-bare test case fails
12181260 {
......@@ -1222,7 +1264,7 @@ test "fmt.format" {
12221264 var buf1: [32]u8 = undefined;
12231265 const value: f64 = f64(@bitCast(f32, u32(1518338049)));
12241266 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"));
12261268 }
12271269 //custom type format
12281270 {
......@@ -1303,10 +1345,10 @@ test "fmt.format" {
13031345
13041346 var buf: [100]u8 = undefined;
13051347 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
13081350 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@"));
13101352 }
13111353 //enum format
13121354 {
......@@ -1365,11 +1407,11 @@ pub fn trim(buf: []const u8) []const u8 {
13651407}
13661408
13671409test "fmt.trim" {
1368 assert(mem.eql(u8, "abc", trim("\n abc \t")));
1369 assert(mem.eql(u8, "", trim(" ")));
1370 assert(mem.eql(u8, "", trim("")));
1371 assert(mem.eql(u8, "abc", trim(" abc")));
1372 assert(mem.eql(u8, "abc", trim("abc ")));
1410 testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
1411 testing.expect(mem.eql(u8, "", trim(" ")));
1412 testing.expect(mem.eql(u8, "", trim("")));
1413 testing.expect(mem.eql(u8, "abc", trim(" abc")));
1414 testing.expect(mem.eql(u8, "abc", trim("abc ")));
13731415}
13741416
13751417pub 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 @@
44// https://github.com/madler/zlib/blob/master/adler32.c
55
66const std = @import("../index.zig");
7const debug = std.debug;
7const testing = std.testing;
88
99pub const Adler32 = struct {
1010 const base = 65521;
......@@ -89,19 +89,19 @@ pub const Adler32 = struct {
8989};
9090
9191test "adler32 sanity" {
92 debug.assert(Adler32.hash("a") == 0x620062);
93 debug.assert(Adler32.hash("example") == 0xbc002ed);
92 testing.expect(Adler32.hash("a") == 0x620062);
93 testing.expect(Adler32.hash("example") == 0xbc002ed);
9494}
9595
9696test "adler32 long" {
9797 const long1 = []u8{1} ** 1024;
98 debug.assert(Adler32.hash(long1[0..]) == 0x06780401);
98 testing.expect(Adler32.hash(long1[0..]) == 0x06780401);
9999
100100 const long2 = []u8{1} ** 1025;
101 debug.assert(Adler32.hash(long2[0..]) == 0x0a7a0402);
101 testing.expect(Adler32.hash(long2[0..]) == 0x0a7a0402);
102102}
103103
104104test "adler32 very long" {
105105 const long = []u8{1} ** 5553;
106 debug.assert(Adler32.hash(long[0..]) == 0x707f15b2);
106 testing.expect(Adler32.hash(long[0..]) == 0x707f15b2);
107107}
std/hash/crc.zig+13-12
......@@ -7,6 +7,7 @@
77
88const std = @import("../index.zig");
99const debug = std.debug;
10const testing = std.testing;
1011
1112pub const Polynomial = struct {
1213 const IEEE = 0xedb88320;
......@@ -101,17 +102,17 @@ pub fn Crc32WithPoly(comptime poly: u32) type {
101102test "crc32 ieee" {
102103 const Crc32Ieee = Crc32WithPoly(Polynomial.IEEE);
103104
104 debug.assert(Crc32Ieee.hash("") == 0x00000000);
105 debug.assert(Crc32Ieee.hash("a") == 0xe8b7be43);
106 debug.assert(Crc32Ieee.hash("abc") == 0x352441c2);
105 testing.expect(Crc32Ieee.hash("") == 0x00000000);
106 testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43);
107 testing.expect(Crc32Ieee.hash("abc") == 0x352441c2);
107108}
108109
109110test "crc32 castagnoli" {
110111 const Crc32Castagnoli = Crc32WithPoly(Polynomial.Castagnoli);
111112
112 debug.assert(Crc32Castagnoli.hash("") == 0x00000000);
113 debug.assert(Crc32Castagnoli.hash("a") == 0xc1d04330);
114 debug.assert(Crc32Castagnoli.hash("abc") == 0x364b3fb7);
113 testing.expect(Crc32Castagnoli.hash("") == 0x00000000);
114 testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330);
115 testing.expect(Crc32Castagnoli.hash("abc") == 0x364b3fb7);
115116}
116117
117118// half-byte lookup table implementation.
......@@ -165,15 +166,15 @@ pub fn Crc32SmallWithPoly(comptime poly: u32) type {
165166test "small crc32 ieee" {
166167 const Crc32Ieee = Crc32SmallWithPoly(Polynomial.IEEE);
167168
168 debug.assert(Crc32Ieee.hash("") == 0x00000000);
169 debug.assert(Crc32Ieee.hash("a") == 0xe8b7be43);
170 debug.assert(Crc32Ieee.hash("abc") == 0x352441c2);
169 testing.expect(Crc32Ieee.hash("") == 0x00000000);
170 testing.expect(Crc32Ieee.hash("a") == 0xe8b7be43);
171 testing.expect(Crc32Ieee.hash("abc") == 0x352441c2);
171172}
172173
173174test "small crc32 castagnoli" {
174175 const Crc32Castagnoli = Crc32SmallWithPoly(Polynomial.Castagnoli);
175176
176 debug.assert(Crc32Castagnoli.hash("") == 0x00000000);
177 debug.assert(Crc32Castagnoli.hash("a") == 0xc1d04330);
178 debug.assert(Crc32Castagnoli.hash("abc") == 0x364b3fb7);
177 testing.expect(Crc32Castagnoli.hash("") == 0x00000000);
178 testing.expect(Crc32Castagnoli.hash("a") == 0xc1d04330);
179 testing.expect(Crc32Castagnoli.hash("abc") == 0x364b3fb7);
179180}
std/hash/fnv.zig+9-9
......@@ -5,7 +5,7 @@
55// https://tools.ietf.org/html/draft-eastlake-fnv-14
66
77const std = @import("../index.zig");
8const debug = std.debug;
8const testing = std.testing;
99
1010pub const Fnv1a_32 = Fnv1a(u32, 0x01000193, 0x811c9dc5);
1111pub const Fnv1a_64 = Fnv1a(u64, 0x100000001b3, 0xcbf29ce484222325);
......@@ -41,18 +41,18 @@ fn Fnv1a(comptime T: type, comptime prime: T, comptime offset: T) type {
4141}
4242
4343test "fnv1a-32" {
44 debug.assert(Fnv1a_32.hash("") == 0x811c9dc5);
45 debug.assert(Fnv1a_32.hash("a") == 0xe40c292c);
46 debug.assert(Fnv1a_32.hash("foobar") == 0xbf9cf968);
44 testing.expect(Fnv1a_32.hash("") == 0x811c9dc5);
45 testing.expect(Fnv1a_32.hash("a") == 0xe40c292c);
46 testing.expect(Fnv1a_32.hash("foobar") == 0xbf9cf968);
4747}
4848
4949test "fnv1a-64" {
50 debug.assert(Fnv1a_64.hash("") == 0xcbf29ce484222325);
51 debug.assert(Fnv1a_64.hash("a") == 0xaf63dc4c8601ec8c);
52 debug.assert(Fnv1a_64.hash("foobar") == 0x85944171f73967e8);
50 testing.expect(Fnv1a_64.hash("") == 0xcbf29ce484222325);
51 testing.expect(Fnv1a_64.hash("a") == 0xaf63dc4c8601ec8c);
52 testing.expect(Fnv1a_64.hash("foobar") == 0x85944171f73967e8);
5353}
5454
5555test "fnv1a-128" {
56 debug.assert(Fnv1a_128.hash("") == 0x6c62272e07bb014262b821756295c58d);
57 debug.assert(Fnv1a_128.hash("a") == 0xd228cb696f1a8caf78912b704e4a8964);
56 testing.expect(Fnv1a_128.hash("") == 0x6c62272e07bb014262b821756295c58d);
57 testing.expect(Fnv1a_128.hash("a") == 0xd228cb696f1a8caf78912b704e4a8964);
5858}
std/hash/siphash.zig+15-14
......@@ -6,7 +6,8 @@
66// https://131002.net/siphash/
77
88const std = @import("../index.zig");
9const debug = std.debug;
9const assert = std.debug.assert;
10const testing = std.testing;
1011const math = std.math;
1112const mem = std.mem;
1213
......@@ -21,8 +22,8 @@ pub fn SipHash128(comptime c_rounds: usize, comptime d_rounds: usize) type {
2122}
2223
2324fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize) type {
24 debug.assert(T == u64 or T == u128);
25 debug.assert(c_rounds > 0 and d_rounds > 0);
25 assert(T == u64 or T == u128);
26 assert(c_rounds > 0 and d_rounds > 0);
2627
2728 return struct {
2829 const Self = @This();
......@@ -40,10 +41,10 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
4041 msg_len: u8,
4142
4243 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 k1 = mem.readInt(key[8..16], u64, Endian.Little);
46 const k0 = mem.readIntSliceLittle(u64, key[0..8]);
47 const k1 = mem.readIntSliceLittle(u64, key[8..16]);
4748
4849 var d = Self{
4950 .v0 = k0 ^ 0x736f6d6570736575,
......@@ -119,9 +120,9 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
119120 }
120121
121122 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..]);
125126 d.v3 ^= m;
126127
127128 comptime var i: usize = 0;
......@@ -162,7 +163,7 @@ fn SipHash(comptime T: type, comptime c_rounds: usize, comptime d_rounds: usize)
162163const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";
163164
164165test "siphash64-2-4 sanity" {
165 const vectors = [][]const u8{
166 const vectors = [][8]u8{
166167 "\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // ""
167168 "\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00"
168169 "\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc
......@@ -235,13 +236,13 @@ test "siphash64-2-4 sanity" {
235236 for (vectors) |vector, i| {
236237 buffer[i] = @intCast(u8, i);
237238
238 const expected = mem.readInt(vector, u64, Endian.Little);
239 debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
239 const expected = mem.readIntLittle(u64, &vector);
240 testing.expect(siphash.hash(test_key, buffer[0..i]) == expected);
240241 }
241242}
242243
243244test "siphash128-2-4 sanity" {
244 const vectors = [][]const u8{
245 const vectors = [][16]u8{
245246 "\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93",
246247 "\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45",
247248 "\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" {
314315 for (vectors) |vector, i| {
315316 buffer[i] = @intCast(u8, i);
316317
317 const expected = mem.readInt(vector, u128, Endian.Little);
318 debug.assert(siphash.hash(test_key, buffer[0..i]) == expected);
318 const expected = mem.readIntLittle(u128, &vector);
319 testing.expect(siphash.hash(test_key, buffer[0..i]) == expected);
319320 }
320321}
std/hash_map.zig+34-29
......@@ -1,6 +1,7 @@
11const std = @import("index.zig");
22const debug = std.debug;
33const assert = debug.assert;
4const testing = std.testing;
45const math = std.math;
56const mem = std.mem;
67const Allocator = mem.Allocator;
......@@ -342,37 +343,37 @@ test "basic hash map usage" {
342343 var map = AutoHashMap(i32, i32).init(&direct_allocator.allocator);
343344 defer map.deinit();
344345
345 assert((try map.put(1, 11)) == null);
346 assert((try map.put(2, 22)) == null);
347 assert((try map.put(3, 33)) == null);
348 assert((try map.put(4, 44)) == null);
349 assert((try map.put(5, 55)) == null);
346 testing.expect((try map.put(1, 11)) == null);
347 testing.expect((try map.put(2, 22)) == null);
348 testing.expect((try map.put(3, 33)) == null);
349 testing.expect((try map.put(4, 44)) == null);
350 testing.expect((try map.put(5, 55)) == null);
350351
351 assert((try map.put(5, 66)).?.value == 55);
352 assert((try map.put(5, 55)).?.value == 66);
352 testing.expect((try map.put(5, 66)).?.value == 55);
353 testing.expect((try map.put(5, 55)).?.value == 66);
353354
354355 const gop1 = try map.getOrPut(5);
355 assert(gop1.found_existing == true);
356 assert(gop1.kv.value == 55);
356 testing.expect(gop1.found_existing == true);
357 testing.expect(gop1.kv.value == 55);
357358 gop1.kv.value = 77;
358 assert(map.get(5).?.value == 77);
359 testing.expect(map.get(5).?.value == 77);
359360
360361 const gop2 = try map.getOrPut(99);
361 assert(gop2.found_existing == false);
362 testing.expect(gop2.found_existing == false);
362363 gop2.kv.value = 42;
363 assert(map.get(99).?.value == 42);
364 testing.expect(map.get(99).?.value == 42);
364365
365366 const gop3 = try map.getOrPutValue(5, 5);
366 assert(gop3.value == 77);
367 testing.expect(gop3.value == 77);
367368
368369 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 assert(map.get(2).?.value == 22);
372 testing.expect(map.contains(2));
373 testing.expect(map.get(2).?.value == 22);
373374 _ = map.remove(2);
374 assert(map.remove(2) == null);
375 assert(map.get(2) == null);
375 testing.expect(map.remove(2) == null);
376 testing.expect(map.get(2) == null);
376377}
377378
378379test "iterator hash map" {
......@@ -382,9 +383,9 @@ test "iterator hash map" {
382383 var reset_map = AutoHashMap(i32, i32).init(&direct_allocator.allocator);
383384 defer reset_map.deinit();
384385
385 assert((try reset_map.put(1, 11)) == null);
386 assert((try reset_map.put(2, 22)) == null);
387 assert((try reset_map.put(3, 33)) == null);
386 testing.expect((try reset_map.put(1, 11)) == null);
387 testing.expect((try reset_map.put(2, 22)) == null);
388 testing.expect((try reset_map.put(3, 33)) == null);
388389
389390 var keys = []i32{
390391 3,
......@@ -400,26 +401,26 @@ test "iterator hash map" {
400401 var it = reset_map.iterator();
401402 var count: usize = 0;
402403 while (it.next()) |next| {
403 assert(next.key == keys[count]);
404 assert(next.value == values[count]);
404 testing.expect(next.key == keys[count]);
405 testing.expect(next.value == values[count]);
405406 count += 1;
406407 }
407408
408 assert(count == 3);
409 assert(it.next() == null);
409 testing.expect(count == 3);
410 testing.expect(it.next() == null);
410411 it.reset();
411412 count = 0;
412413 while (it.next()) |next| {
413 assert(next.key == keys[count]);
414 assert(next.value == values[count]);
414 testing.expect(next.key == keys[count]);
415 testing.expect(next.value == values[count]);
415416 count += 1;
416417 if (count == 2) break;
417418 }
418419
419420 it.reset();
420421 var entry = it.next().?;
421 assert(entry.key == keys[0]);
422 assert(entry.value == values[0]);
422 testing.expect(entry.key == keys[0]);
423 testing.expect(entry.value == values[0]);
423424}
424425
425426pub 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
495496 builtin.TypeId.Pointer => |info| switch (info.size) {
496497 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto hash for single item pointers"),
497498 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"),
498500 builtin.TypeInfo.Pointer.Size.Slice => {
499501 const interval = std.math.max(1, key.len / 256);
500502 var i: usize = 0;
......@@ -508,6 +510,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type
508510
509511 builtin.TypeId.Optional => @compileError("TODO auto hash for optionals"),
510512 builtin.TypeId.Array => @compileError("TODO auto hash for arrays"),
513 builtin.TypeId.Vector => @compileError("TODO auto hash for vectors"),
511514 builtin.TypeId.Struct => @compileError("TODO auto hash for structs"),
512515 builtin.TypeId.Union => @compileError("TODO auto hash for unions"),
513516 builtin.TypeId.ErrorUnion => @compileError("TODO auto hash for unions"),
......@@ -541,6 +544,7 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {
541544 builtin.TypeId.Pointer => |info| switch (info.size) {
542545 builtin.TypeInfo.Pointer.Size.One => @compileError("TODO auto eql for single item pointers"),
543546 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"),
544548 builtin.TypeInfo.Pointer.Size.Slice => {
545549 if (a.len != b.len) return false;
546550 for (a) |a_item, i| {
......@@ -555,5 +559,6 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {
555559 builtin.TypeId.Struct => @compileError("TODO auto eql for structs"),
556560 builtin.TypeId.Union => @compileError("TODO auto eql for unions"),
557561 builtin.TypeId.ErrorUnion => @compileError("TODO auto eql for unions"),
562 builtin.TypeId.Vector => @compileError("TODO auto eql for vectors"),
558563 }
559564}
std/heap.zig+79-74
......@@ -1,6 +1,7 @@
11const std = @import("index.zig");
22const debug = std.debug;
33const assert = debug.assert;
4const testing = std.testing;
45const mem = std.mem;
56const os = std.os;
67const builtin = @import("builtin");
......@@ -66,7 +67,7 @@ pub const DirectAllocator = struct {
6667 }
6768 }
6869
69 fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 {
70 fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 {
7071 const self = @fieldParentPtr(DirectAllocator, "allocator", allocator);
7172
7273 switch (builtin.os) {
......@@ -106,9 +107,7 @@ pub const DirectAllocator = struct {
106107 };
107108 const ptr = os.windows.HeapAlloc(heap_handle, 0, amt) orelse return error.OutOfMemory;
108109 const root_addr = @ptrToInt(ptr);
109 const rem = @rem(root_addr, alignment);
110 const march_forward_bytes = if (rem == 0) 0 else (alignment - rem);
111 const adjusted_addr = root_addr + march_forward_bytes;
110 const adjusted_addr = mem.alignForward(root_addr, alignment);
112111 const record_addr = adjusted_addr + n;
113112 @intToPtr(*align(1) usize, record_addr).* = root_addr;
114113 return @intToPtr([*]u8, adjusted_addr)[0..n];
......@@ -126,8 +125,7 @@ pub const DirectAllocator = struct {
126125 const base_addr = @ptrToInt(old_mem.ptr);
127126 const old_addr_end = base_addr + old_mem.len;
128127 const new_addr_end = base_addr + new_size;
129 const rem = @rem(new_addr_end, os.page_size);
130 const new_addr_end_rounded = new_addr_end + if (rem == 0) 0 else (os.page_size - rem);
128 const new_addr_end_rounded = mem.alignForward(new_addr_end, os.page_size);
131129 if (old_addr_end > new_addr_end_rounded) {
132130 _ = os.posix.munmap(new_addr_end_rounded, old_addr_end - new_addr_end_rounded);
133131 }
......@@ -324,51 +322,57 @@ pub const FixedBufferAllocator = struct {
324322 fn free(allocator: *Allocator, bytes: []u8) void {}
325323};
326324
327/// lock free
328pub const ThreadSafeFixedBufferAllocator = struct {
329 allocator: Allocator,
330 end_index: usize,
331 buffer: []u8,
325pub const ThreadSafeFixedBufferAllocator = blk: {
326 if (builtin.single_threaded) {
327 break :blk FixedBufferAllocator;
328 } else {
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 {
334 return ThreadSafeFixedBufferAllocator{
335 .allocator = Allocator{
336 .allocFn = alloc,
337 .reallocFn = realloc,
338 .freeFn = free,
339 },
340 .buffer = buffer,
341 .end_index = 0,
342 };
343 }
347 fn alloc(allocator: *Allocator, n: usize, alignment: u29) ![]u8 {
348 const self = @fieldParentPtr(ThreadSafeFixedBufferAllocator, "allocator", allocator);
349 var end_index = @atomicLoad(usize, &self.end_index, builtin.AtomicOrder.SeqCst);
350 while (true) {
351 const addr = @ptrToInt(self.buffer.ptr) + end_index;
352 const rem = @rem(addr, alignment);
353 const march_forward_bytes = if (rem == 0) 0 else (alignment - rem);
354 const adjusted_index = end_index + march_forward_bytes;
355 const new_end_index = adjusted_index + n;
356 if (new_end_index > self.buffer.len) {
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 {
346 const self = @fieldParentPtr(ThreadSafeFixedBufferAllocator, "allocator", allocator);
347 var end_index = @atomicLoad(usize, &self.end_index, builtin.AtomicOrder.SeqCst);
348 while (true) {
349 const addr = @ptrToInt(self.buffer.ptr) + end_index;
350 const rem = @rem(addr, alignment);
351 const march_forward_bytes = if (rem == 0) 0 else (alignment - rem);
352 const adjusted_index = end_index + march_forward_bytes;
353 const new_end_index = adjusted_index + n;
354 if (new_end_index > self.buffer.len) {
355 return error.OutOfMemory;
363 fn realloc(allocator: *Allocator, old_mem: []u8, new_size: usize, alignment: u29) ![]u8 {
364 if (new_size <= old_mem.len) {
365 return old_mem[0..new_size];
366 } else {
367 const result = try alloc(allocator, new_size, alignment);
368 mem.copy(u8, result, old_mem);
369 return result;
370 }
356371 }
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 {
362 if (new_size <= old_mem.len) {
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 }
373 fn free(allocator: *Allocator, bytes: []u8) void {}
374 };
369375 }
370
371 fn free(allocator: *Allocator, bytes: []u8) void {}
372376};
373377
374378pub fn stackFallback(comptime size: usize, fallback_allocator: *Allocator) StackFallbackAllocator(size) {
......@@ -484,11 +488,11 @@ test "FixedBufferAllocator Reuse memory on realloc" {
484488 var fixed_buffer_allocator = FixedBufferAllocator.init(small_fixed_buffer[0..]);
485489
486490 var slice0 = try fixed_buffer_allocator.allocator.alloc(u8, 5);
487 assert(slice0.len == 5);
491 testing.expect(slice0.len == 5);
488492 var slice1 = try fixed_buffer_allocator.allocator.realloc(u8, slice0, 10);
489 assert(slice1.ptr == slice0.ptr);
490 assert(slice1.len == 10);
491 debug.assertError(fixed_buffer_allocator.allocator.realloc(u8, slice1, 11), error.OutOfMemory);
493 testing.expect(slice1.ptr == slice0.ptr);
494 testing.expect(slice1.len == 10);
495 testing.expectError(error.OutOfMemory, fixed_buffer_allocator.allocator.realloc(u8, slice1, 11));
492496 }
493497 // check that we don't re-use the memory if it's not the most recent block
494498 {
......@@ -499,10 +503,10 @@ test "FixedBufferAllocator Reuse memory on realloc" {
499503 slice0[1] = 2;
500504 var slice1 = try fixed_buffer_allocator.allocator.alloc(u8, 2);
501505 var slice2 = try fixed_buffer_allocator.allocator.realloc(u8, slice0, 4);
502 assert(slice0.ptr != slice2.ptr);
503 assert(slice1.ptr != slice2.ptr);
504 assert(slice2[0] == 1);
505 assert(slice2[1] == 2);
506 testing.expect(slice0.ptr != slice2.ptr);
507 testing.expect(slice1.ptr != slice2.ptr);
508 testing.expect(slice2[0] == 1);
509 testing.expect(slice2[1] == 2);
506510 }
507511}
508512
......@@ -516,27 +520,28 @@ test "ThreadSafeFixedBufferAllocator" {
516520
517521fn testAllocator(allocator: *mem.Allocator) !void {
518522 var slice = try allocator.alloc(*i32, 100);
519 assert(slice.len == 100);
523 testing.expect(slice.len == 100);
520524 for (slice) |*item, i| {
521 item.* = try allocator.create(@intCast(i32, i));
525 item.* = try allocator.create(i32);
526 item.*.* = @intCast(i32, i);
522527 }
523528
524529 slice = try allocator.realloc(*i32, slice, 20000);
525 assert(slice.len == 20000);
530 testing.expect(slice.len == 20000);
526531
527532 for (slice[0..100]) |item, i| {
528 assert(item.* == @intCast(i32, i));
533 testing.expect(item.* == @intCast(i32, i));
529534 allocator.destroy(item);
530535 }
531536
532537 slice = try allocator.realloc(*i32, slice, 50);
533 assert(slice.len == 50);
538 testing.expect(slice.len == 50);
534539 slice = try allocator.realloc(*i32, slice, 25);
535 assert(slice.len == 25);
540 testing.expect(slice.len == 25);
536541 slice = try allocator.realloc(*i32, slice, 0);
537 assert(slice.len == 0);
542 testing.expect(slice.len == 0);
538543 slice = try allocator.realloc(*i32, slice, 10);
539 assert(slice.len == 10);
544 testing.expect(slice.len == 10);
540545
541546 allocator.free(slice);
542547}
......@@ -544,25 +549,25 @@ fn testAllocator(allocator: *mem.Allocator) !void {
544549fn testAllocatorAligned(allocator: *mem.Allocator, comptime alignment: u29) !void {
545550 // initial
546551 var slice = try allocator.alignedAlloc(u8, alignment, 10);
547 assert(slice.len == 10);
552 testing.expect(slice.len == 10);
548553 // grow
549554 slice = try allocator.alignedRealloc(u8, alignment, slice, 100);
550 assert(slice.len == 100);
555 testing.expect(slice.len == 100);
551556 // shrink
552557 slice = try allocator.alignedRealloc(u8, alignment, slice, 10);
553 assert(slice.len == 10);
558 testing.expect(slice.len == 10);
554559 // go to zero
555560 slice = try allocator.alignedRealloc(u8, alignment, slice, 0);
556 assert(slice.len == 0);
561 testing.expect(slice.len == 0);
557562 // realloc from zero
558563 slice = try allocator.alignedRealloc(u8, alignment, slice, 100);
559 assert(slice.len == 100);
564 testing.expect(slice.len == 100);
560565 // shrink with shrink
561566 slice = allocator.alignedShrink(u8, alignment, slice, 10);
562 assert(slice.len == 10);
567 testing.expect(slice.len == 10);
563568 // shrink to zero
564569 slice = allocator.alignedShrink(u8, alignment, slice, 0);
565 assert(slice.len == 0);
570 testing.expect(slice.len == 0);
566571}
567572
568573fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!void {
......@@ -577,19 +582,19 @@ fn testAllocatorLargeAlignment(allocator: *mem.Allocator) mem.Allocator.Error!vo
577582 _ = @shlWithOverflow(usize, ~usize(0), USizeShift(@ctz(large_align)), &align_mask);
578583
579584 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
582587 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
585590 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
588593 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
591596 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
594599 allocator.free(slice);
595600}
std/index.zig+12-8
......@@ -9,6 +9,7 @@ pub const DynLib = @import("dynamic_library.zig").DynLib;
99pub const HashMap = @import("hash_map.zig").HashMap;
1010pub const LinkedList = @import("linked_list.zig").LinkedList;
1111pub const Mutex = @import("mutex.zig").Mutex;
12pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex;
1213pub const SegmentedList = @import("segmented_list.zig").SegmentedList;
1314pub const SpinLock = @import("spinlock.zig").SpinLock;
1415
......@@ -30,21 +31,21 @@ pub const hash_map = @import("hash_map.zig");
3031pub const heap = @import("heap.zig");
3132pub const io = @import("io.zig");
3233pub const json = @import("json.zig");
34pub const lazyInit = @import("lazy_init.zig").lazyInit;
3335pub const macho = @import("macho.zig");
3436pub const math = @import("math/index.zig");
35pub const meta = @import("meta/index.zig");
3637pub const mem = @import("mem.zig");
38pub const meta = @import("meta/index.zig");
3739pub const net = @import("net.zig");
3840pub const os = @import("os/index.zig");
3941pub const pdb = @import("pdb.zig");
4042pub const rand = @import("rand/index.zig");
4143pub const rb = @import("rb.zig");
4244pub const sort = @import("sort.zig");
45pub const testing = @import("testing.zig");
4346pub const unicode = @import("unicode.zig");
4447pub const zig = @import("zig/index.zig");
4548
46pub const lazyInit = @import("lazy_init.zig").lazyInit;
47
4849test "std" {
4950 // run tests from these
5051 _ = @import("array_list.zig");
......@@ -55,9 +56,10 @@ test "std" {
5556 _ = @import("hash_map.zig");
5657 _ = @import("linked_list.zig");
5758 _ = @import("mutex.zig");
59 _ = @import("statically_initialized_mutex.zig");
5860 _ = @import("segmented_list.zig");
5961 _ = @import("spinlock.zig");
60
62
6163 _ = @import("base64.zig");
6264 _ = @import("build.zig");
6365 _ = @import("c/index.zig");
......@@ -66,24 +68,26 @@ test "std" {
6668 _ = @import("cstr.zig");
6769 _ = @import("debug/index.zig");
6870 _ = @import("dwarf.zig");
71 _ = @import("dynamic_library.zig");
6972 _ = @import("elf.zig");
7073 _ = @import("empty.zig");
7174 _ = @import("event.zig");
7275 _ = @import("fmt/index.zig");
7376 _ = @import("hash/index.zig");
77 _ = @import("heap.zig");
7478 _ = @import("io.zig");
7579 _ = @import("json.zig");
80 _ = @import("lazy_init.zig");
7681 _ = @import("macho.zig");
7782 _ = @import("math/index.zig");
78 _ = @import("meta/index.zig");
7983 _ = @import("mem.zig");
84 _ = @import("meta/index.zig");
8085 _ = @import("net.zig");
81 _ = @import("heap.zig");
8286 _ = @import("os/index.zig");
83 _ = @import("rand/index.zig");
8487 _ = @import("pdb.zig");
88 _ = @import("rand/index.zig");
8589 _ = @import("sort.zig");
90 _ = @import("testing.zig");
8691 _ = @import("unicode.zig");
8792 _ = @import("zig/index.zig");
88 _ = @import("lazy_init.zig");
8993}
std/io.zig+751-53
......@@ -8,9 +8,12 @@ const debug = std.debug;
88const assert = debug.assert;
99const os = std.os;
1010const mem = std.mem;
11const meta = std.meta;
12const trait = meta.trait;
1113const Buffer = std.Buffer;
1214const fmt = std.fmt;
1315const File = std.os.File;
16const testing = std.testing;
1417
1518const is_posix = builtin.os != builtin.Os.windows;
1619const is_windows = builtin.os == builtin.Os.windows;
......@@ -152,35 +155,43 @@ pub fn InStream(comptime ReadError: type) type {
152155 }
153156
154157 /// Reads a native-endian integer
155 pub fn readIntNe(self: *Self, comptime T: type) !T {
156 return self.readInt(builtin.endian, T);
158 pub fn readIntNative(self: *Self, comptime T: type) !T {
159 var bytes: [@sizeOf(T)]u8 = undefined;
160 try self.readNoEof(bytes[0..]);
161 return mem.readIntNative(T, &bytes);
157162 }
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 {
160166 var bytes: [@sizeOf(T)]u8 = undefined;
161167 try self.readNoEof(bytes[0..]);
162 return mem.readIntLE(T, bytes);
168 return mem.readIntForeign(T, &bytes);
163169 }
164170
165 pub fn readIntBe(self: *Self, comptime T: type) !T {
171 pub fn readIntLittle(self: *Self, comptime T: type) !T {
166172 var bytes: [@sizeOf(T)]u8 = undefined;
167173 try self.readNoEof(bytes[0..]);
168 return mem.readIntBE(T, bytes);
174 return mem.readIntLittle(T, &bytes);
169175 }
170176
171 pub fn readInt(self: *Self, endian: builtin.Endian, comptime T: type) !T {
177 pub fn readIntBig(self: *Self, comptime T: type) !T {
172178 var bytes: [@sizeOf(T)]u8 = undefined;
173179 try self.readNoEof(bytes[0..]);
174 return mem.readInt(bytes, T, endian);
180 return mem.readIntBig(T, &bytes);
175181 }
176182
177 pub fn readVarInt(self: *Self, endian: builtin.Endian, comptime T: type, size: usize) !T {
178 assert(size <= @sizeOf(T));
179 assert(size <= 8);
180 var input_buf: [8]u8 = undefined;
181 const input_slice = input_buf[0..size];
182 try self.readNoEof(input_slice);
183 return mem.readInt(input_slice, T, endian);
183 pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T {
184 var bytes: [@sizeOf(T)]u8 = undefined;
185 try self.readNoEof(bytes[0..]);
186 return mem.readInt(T, &bytes, endian);
187 }
188
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);
184195 }
185196
186197 pub fn skipBytes(self: *Self, num_bytes: usize) !void {
......@@ -229,25 +240,34 @@ pub fn OutStream(comptime WriteError: type) type {
229240 }
230241
231242 /// Write a native-endian integer.
232 pub fn writeIntNe(self: *Self, comptime T: type, value: T) Error!void {
233 return self.writeInt(builtin.endian, T, value);
243 pub fn writeIntNative(self: *Self, comptime T: type, value: T) Error!void {
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);
234254 }
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 {
237257 var bytes: [@sizeOf(T)]u8 = undefined;
238 mem.writeIntLE(T, &bytes, value);
258 mem.writeIntLittle(T, &bytes, value);
239259 return self.writeFn(self, bytes);
240260 }
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 {
243263 var bytes: [@sizeOf(T)]u8 = undefined;
244 mem.writeIntBE(T, &bytes, value);
264 mem.writeIntBig(T, &bytes, value);
245265 return self.writeFn(self, bytes);
246266 }
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 {
249269 var bytes: [@sizeOf(T)]u8 = undefined;
250 mem.writeInt(bytes[0..], value, endian);
270 mem.writeInt(T, &bytes, value, endian);
251271 return self.writeFn(self, bytes);
252272 }
253273 };
......@@ -323,23 +343,24 @@ pub fn BufferedInStreamCustom(comptime buffer_size: usize, comptime Error: type)
323343 const amt_buffered = self.end_index - self.start_index;
324344 if (amt_buffered == 0) {
325345 assert(self.end_index <= buffer_size);
326 if (self.end_index == buffer_size) {
327 // we can read more data from the unbuffered stream
328 if (dest_space < buffer_size) {
329 self.start_index = 0;
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.
346 // Make sure the last read actually gave us some data
347 if (self.end_index == 0) {
348 // reading from the unbuffered stream returned nothing
349 // so we have nothing left to read.
340350 return dest_index;
341351 }
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 }
342362 }
363
343364 const copy_amount = math.min(dest_space, amt_buffered);
344365 const copy_end_index = self.start_index + copy_amount;
345366 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)
350371 };
351372}
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
353414/// Creates a stream which supports 'un-reading' data, so that it can be read again.
354415/// This makes look-ahead style parsing much easier.
355416pub fn PeekStream(comptime buffer_size: usize, comptime InStreamError: type) type {
......@@ -446,6 +507,153 @@ pub const SliceInStream = struct {
446507 }
447508};
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
449657/// This is a simple OutStream that writes to a slice, and returns an error
450658/// when it runs out of space.
451659pub const SliceOutStream = struct {
......@@ -498,7 +706,7 @@ test "io.SliceOutStream" {
498706 const stream = &slice_stream.stream;
499707
500708 try stream.print("{}{}!", "Hello", "World");
501 debug.assert(mem.eql(u8, "HelloWorld!", slice_stream.getWritten()));
709 testing.expectEqualSlices(u8, "HelloWorld!", slice_stream.getWritten());
502710}
503711
504712var null_out_stream_state = NullOutStream.init();
......@@ -560,7 +768,7 @@ test "io.CountingOutStream" {
560768
561769 const bytes = "yay" ** 10000;
562770 stream.write(bytes) catch unreachable;
563 debug.assert(counting_stream.bytes_written == bytes.len);
771 testing.expect(counting_stream.bytes_written == bytes.len);
564772}
565773
566774pub fn BufferedOutStream(comptime Error: type) type {
......@@ -639,6 +847,135 @@ pub const BufferOutStream = struct {
639847 }
640848};
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
642979pub const BufferedAtomicFile = struct {
643980 atomic_file: os.AtomicFile,
644981 file_stream: os.File.OutStream,
......@@ -647,12 +984,13 @@ pub const BufferedAtomicFile = struct {
647984
648985 pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile {
649986 // 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{
651989 .atomic_file = undefined,
652990 .file_stream = undefined,
653991 .buffered_stream = undefined,
654992 .allocator = allocator,
655 });
993 };
656994 errdefer allocator.destroy(self);
657995
658996 self.atomic_file = try os.AtomicFile.init(dest_path, os.File.default_mode);
......@@ -679,12 +1017,6 @@ pub const BufferedAtomicFile = struct {
6791017 }
6801018};
6811019
682test "import io tests" {
683 comptime {
684 _ = @import("io_test.zig");
685 }
686}
687
6881020pub fn readLine(buf: *std.Buffer) ![]u8 {
6891021 var stdin = try getStdIn();
6901022 var stdin_stream = stdin.inStream();
......@@ -721,10 +1053,10 @@ test "io.readLineFrom" {
7211053 );
7221054 const stream = &mem_stream.stream;
7231055
724 debug.assert(mem.eql(u8, "Line 1", try readLineFrom(stream, &buf)));
725 debug.assert(mem.eql(u8, "Line 22", try readLineFrom(stream, &buf)));
726 debug.assertError(readLineFrom(stream, &buf), error.EndOfStream);
727 debug.assert(mem.eql(u8, buf.toSlice(), "Line 1Line 22Line 333"));
1056 testing.expectEqualSlices(u8, "Line 1", try readLineFrom(stream, &buf));
1057 testing.expectEqualSlices(u8, "Line 22", try readLineFrom(stream, &buf));
1058 testing.expectError(error.EndOfStream, readLineFrom(stream, &buf));
1059 testing.expectEqualSlices(u8, "Line 1Line 22Line 333", buf.toSlice());
7281060}
7291061
7301062pub fn readLineSlice(slice: []u8) ![]u8 {
......@@ -752,6 +1084,372 @@ test "io.readLineSliceFrom" {
7521084 );
7531085 const stream = &mem_stream.stream;
7541086
755 debug.assert(mem.eql(u8, "Line 1", try readLineSliceFrom(stream, buf[0..])));
756 debug.assertError(readLineSliceFrom(stream, buf[0..]), error.OutOfMemory);
1087 testing.expectEqualSlices(u8, "Line 1", try readLineSliceFrom(stream, buf[0..]));
1088 testing.expectError(error.OutOfMemory, readLineSliceFrom(stream, buf[0..]));
7571089}
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 @@
11const std = @import("index.zig");
22const io = std.io;
3const meta = std.meta;
4const trait = std.trait;
35const DefaultPrng = std.rand.DefaultPrng;
4const assert = std.debug.assert;
5const assertError = std.debug.assertError;
6const expect = std.testing.expect;
7const expectError = std.testing.expectError;
68const mem = std.mem;
79const os = std.os;
810const builtin = @import("builtin");
......@@ -33,7 +35,7 @@ test "write a file, read it, then delete it" {
3335
3436 const file_size = try file.getEndPos();
3537 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
3840 var file_in_stream = file.inStream();
3941 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" {
4143 const contents = try st.readAllAlloc(allocator, 2 * 1024);
4244 defer allocator.free(contents);
4345
44 assert(mem.eql(u8, contents[0.."begin".len], "begin"));
45 assert(mem.eql(u8, contents["begin".len .. contents.len - "end".len], data));
46 assert(mem.eql(u8, contents[contents.len - "end".len ..], "end"));
46 expect(mem.eql(u8, contents[0.."begin".len], "begin"));
47 expect(mem.eql(u8, contents["begin".len .. contents.len - "end".len], data));
48 expect(mem.eql(u8, contents[contents.len - "end".len ..], "end"));
4749 }
4850 try os.deleteFile(tmp_file_name);
4951}
......@@ -59,7 +61,7 @@ test "BufferOutStream" {
5961 const y: i32 = 1234;
6062 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"));
6365}
6466
6567test "SliceInStream" {
......@@ -69,15 +71,15 @@ test "SliceInStream" {
6971 var dest: [4]u8 = undefined;
7072
7173 var read = try ss.stream.read(dest[0..4]);
72 assert(read == 4);
73 assert(mem.eql(u8, dest[0..4], bytes[0..4]));
74 expect(read == 4);
75 expect(mem.eql(u8, dest[0..4], bytes[0..4]));
7476
7577 read = try ss.stream.read(dest[0..4]);
76 assert(read == 3);
77 assert(mem.eql(u8, dest[0..3], bytes[4..7]));
78 expect(read == 3);
79 expect(mem.eql(u8, dest[0..3], bytes[4..7]));
7880
7981 read = try ss.stream.read(dest[0..4]);
80 assert(read == 0);
82 expect(read == 0);
8183}
8284
8385test "PeekStream" {
......@@ -91,26 +93,26 @@ test "PeekStream" {
9193 ps.putBackByte(10);
9294
9395 var read = try ps.stream.read(dest[0..4]);
94 assert(read == 4);
95 assert(dest[0] == 10);
96 assert(dest[1] == 9);
97 assert(mem.eql(u8, dest[2..4], bytes[0..2]));
96 expect(read == 4);
97 expect(dest[0] == 10);
98 expect(dest[1] == 9);
99 expect(mem.eql(u8, dest[2..4], bytes[0..2]));
98100
99101 read = try ps.stream.read(dest[0..4]);
100 assert(read == 4);
101 assert(mem.eql(u8, dest[0..4], bytes[2..6]));
102 expect(read == 4);
103 expect(mem.eql(u8, dest[0..4], bytes[2..6]));
102104
103105 read = try ps.stream.read(dest[0..4]);
104 assert(read == 2);
105 assert(mem.eql(u8, dest[0..2], bytes[6..8]));
106 expect(read == 2);
107 expect(mem.eql(u8, dest[0..2], bytes[6..8]));
106108
107109 ps.putBackByte(11);
108110 ps.putBackByte(12);
109111
110112 read = try ps.stream.read(dest[0..4]);
111 assert(read == 2);
112 assert(dest[0] == 12);
113 assert(dest[1] == 11);
113 expect(read == 2);
114 expect(dest[0] == 12);
115 expect(dest[1] == 11);
114116}
115117
116118test "SliceOutStream" {
......@@ -118,17 +120,461 @@ test "SliceOutStream" {
118120 var ss = io.SliceOutStream.init(buffer[0..]);
119121
120122 try ss.stream.write("Hello");
121 assert(mem.eql(u8, ss.getWritten(), "Hello"));
123 expect(mem.eql(u8, ss.getWritten(), "Hello"));
122124
123125 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);
127 assert(mem.eql(u8, ss.getWritten(), "Helloworld"));
128 expectError(error.OutOfSpace, ss.stream.write("!"));
129 expect(mem.eql(u8, ss.getWritten(), "Helloworld"));
128130
129131 ss.reset();
130 assert(ss.getWritten().len == 0);
132 expect(ss.getWritten().len == 0);
131133
132 assertError(ss.stream.write("Hello world!"), error.OutOfSpace);
133 assert(mem.eql(u8, ss.getWritten(), "Hello worl"));
134 expectError(error.OutOfSpace, ss.stream.write("Hello world!"));
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);
134580}
std/json.zig+15-10
......@@ -4,6 +4,7 @@
44
55const std = @import("index.zig");
66const debug = std.debug;
7const testing = std.testing;
78const mem = std.mem;
89const maxInt = std.math.maxInt;
910
......@@ -960,7 +961,7 @@ test "json.token" {
960961 checkNext(&p, Token.Id.ObjectEnd);
961962 checkNext(&p, Token.Id.ObjectEnd);
962963
963 debug.assert((try p.next()) == null);
964 testing.expect((try p.next()) == null);
964965}
965966
966967// 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 {
981982}
982983
983984test "json.validate" {
984 debug.assert(validate("{}"));
985 testing.expect(validate("{}"));
985986}
986987
987988const Allocator = std.mem.Allocator;
......@@ -1344,7 +1345,7 @@ pub const Parser = struct {
13441345 return if (token.number_is_integer)
13451346 Value{ .Integer = try std.fmt.parseInt(i64, token.slice(input, i), 10) }
13461347 else
1347 @panic("TODO: fmt.parseFloat not yet implemented");
1348 Value{ .Float = try std.fmt.parseFloat(f64, token.slice(input, i)) };
13481349 }
13491350};
13501351
......@@ -1365,7 +1366,8 @@ test "json.parser.dynamic" {
13651366 \\ },
13661367 \\ "Animated" : false,
13671368 \\ "IDs": [116, 943, 234, 38793],
1368 \\ "ArrayOfObject": [{"n": "m"}]
1369 \\ "ArrayOfObject": [{"n": "m"}],
1370 \\ "double": 1.3412
13691371 \\ }
13701372 \\}
13711373 ;
......@@ -1378,20 +1380,23 @@ test "json.parser.dynamic" {
13781380 var image = root.Object.get("Image").?.value;
13791381
13801382 const width = image.Object.get("Width").?.value;
1381 debug.assert(width.Integer == 800);
1383 testing.expect(width.Integer == 800);
13821384
13831385 const height = image.Object.get("Height").?.value;
1384 debug.assert(height.Integer == 600);
1386 testing.expect(height.Integer == 600);
13851387
13861388 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
13891391 const animated = image.Object.get("Animated").?.value;
1390 debug.assert(animated.Bool == false);
1392 testing.expect(animated.Bool == false);
13911393
13921394 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
13951397 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);
13971402}
std/json_test.zig+3-3
......@@ -6,15 +6,15 @@
66const std = @import("index.zig");
77
88fn ok(comptime s: []const u8) void {
9 std.debug.assert(std.json.validate(s));
9 std.testing.expect(std.json.validate(s));
1010}
1111
1212fn err(comptime s: []const u8) void {
13 std.debug.assert(!std.json.validate(s));
13 std.testing.expect(!std.json.validate(s));
1414}
1515
1616fn any(comptime s: []const u8) void {
17 std.debug.assert(true);
17 std.testing.expect(true);
1818}
1919
2020////////////////////////////////////////////////////////////////////////////////////////////////////
std/lazy_init.zig+5-4
......@@ -1,6 +1,7 @@
11const std = @import("index.zig");
22const builtin = @import("builtin");
33const assert = std.debug.assert;
4const testing = std.testing;
45const AtomicRmwOp = builtin.AtomicRmwOp;
56const AtomicOrder = builtin.AtomicOrder;
67
......@@ -63,12 +64,12 @@ test "std.lazyInit" {
6364 global_number.resolve();
6465 }
6566 if (global_number.get()) |x| {
66 assert(x.* == 1234);
67 testing.expect(x.* == 1234);
6768 } else {
6869 @panic("bad");
6970 }
7071 if (global_number.get()) |x| {
71 assert(x.* == 1234);
72 testing.expect(x.* == 1234);
7273 } else {
7374 @panic("bad");
7475 }
......@@ -80,6 +81,6 @@ test "std.lazyInit(void)" {
8081 if (global_void.get()) |_| @panic("bad") else {
8182 global_void.resolve();
8283 }
83 assert(global_void.get() != null);
84 assert(global_void.get() != null);
84 testing.expect(global_void.get() != null);
85 testing.expect(global_void.get() != null);
8586}
std/linked_list.zig+16-15
......@@ -1,6 +1,7 @@
11const std = @import("index.zig");
22const debug = std.debug;
33const assert = debug.assert;
4const testing = std.testing;
45const mem = std.mem;
56const Allocator = mem.Allocator;
67
......@@ -190,7 +191,7 @@ pub fn LinkedList(comptime T: type) type {
190191 /// Returns:
191192 /// A pointer to the new node.
192193 pub fn allocateNode(list: *Self, allocator: *Allocator) !*Node {
193 return allocator.create(Node(undefined));
194 return allocator.create(Node);
194195 }
195196
196197 /// Deallocate a node.
......@@ -246,7 +247,7 @@ test "basic linked list test" {
246247 var it = list.first;
247248 var index: u32 = 1;
248249 while (it) |node| : (it = node.next) {
249 assert(node.data == index);
250 testing.expect(node.data == index);
250251 index += 1;
251252 }
252253 }
......@@ -256,7 +257,7 @@ test "basic linked list test" {
256257 var it = list.last;
257258 var index: u32 = 1;
258259 while (it) |node| : (it = node.prev) {
259 assert(node.data == (6 - index));
260 testing.expect(node.data == (6 - index));
260261 index += 1;
261262 }
262263 }
......@@ -265,9 +266,9 @@ test "basic linked list test" {
265266 var last = list.pop(); // {2, 3, 4}
266267 list.remove(three); // {2, 4}
267268
268 assert(list.first.?.data == 2);
269 assert(list.last.?.data == 4);
270 assert(list.len == 2);
269 testing.expect(list.first.?.data == 2);
270 testing.expect(list.last.?.data == 4);
271 testing.expect(list.len == 2);
271272}
272273
273274test "linked list concatenation" {
......@@ -294,18 +295,18 @@ test "linked list concatenation" {
294295
295296 list1.concatByMoving(&list2);
296297
297 assert(list1.last == five);
298 assert(list1.len == 5);
299 assert(list2.first == null);
300 assert(list2.last == null);
301 assert(list2.len == 0);
298 testing.expect(list1.last == five);
299 testing.expect(list1.len == 5);
300 testing.expect(list2.first == null);
301 testing.expect(list2.last == null);
302 testing.expect(list2.len == 0);
302303
303304 // Traverse forwards.
304305 {
305306 var it = list1.first;
306307 var index: u32 = 1;
307308 while (it) |node| : (it = node.next) {
308 assert(node.data == index);
309 testing.expect(node.data == index);
309310 index += 1;
310311 }
311312 }
......@@ -315,7 +316,7 @@ test "linked list concatenation" {
315316 var it = list1.last;
316317 var index: u32 = 1;
317318 while (it) |node| : (it = node.prev) {
318 assert(node.data == (6 - index));
319 testing.expect(node.data == (6 - index));
319320 index += 1;
320321 }
321322 }
......@@ -328,7 +329,7 @@ test "linked list concatenation" {
328329 var it = list2.first;
329330 var index: u32 = 1;
330331 while (it) |node| : (it = node.next) {
331 assert(node.data == index);
332 testing.expect(node.data == index);
332333 index += 1;
333334 }
334335 }
......@@ -338,7 +339,7 @@ test "linked list concatenation" {
338339 var it = list2.last;
339340 var index: u32 = 1;
340341 while (it) |node| : (it = node.prev) {
341 assert(node.data == (6 - index));
342 testing.expect(node.data == (6 - index));
342343 index += 1;
343344 }
344345 }
std/math/acos.zig+19-19
......@@ -4,7 +4,7 @@
44
55const std = @import("../index.zig");
66const math = std.math;
7const assert = std.debug.assert;
7const expect = std.testing.expect;
88
99pub fn acos(x: var) @typeOf(x) {
1010 const T = @typeOf(x);
......@@ -143,38 +143,38 @@ fn acos64(x: f64) f64 {
143143}
144144
145145test "math.acos" {
146 assert(acos(f32(0.0)) == acos32(0.0));
147 assert(acos(f64(0.0)) == acos64(0.0));
146 expect(acos(f32(0.0)) == acos32(0.0));
147 expect(acos(f64(0.0)) == acos64(0.0));
148148}
149149
150150test "math.acos32" {
151151 const epsilon = 0.000001;
152152
153 assert(math.approxEq(f32, acos32(0.0), 1.570796, epsilon));
154 assert(math.approxEq(f32, acos32(0.2), 1.369438, epsilon));
155 assert(math.approxEq(f32, acos32(0.3434), 1.220262, epsilon));
156 assert(math.approxEq(f32, acos32(0.5), 1.047198, epsilon));
157 assert(math.approxEq(f32, acos32(0.8923), 0.468382, epsilon));
158 assert(math.approxEq(f32, acos32(-0.2), 1.772154, epsilon));
153 expect(math.approxEq(f32, acos32(0.0), 1.570796, epsilon));
154 expect(math.approxEq(f32, acos32(0.2), 1.369438, epsilon));
155 expect(math.approxEq(f32, acos32(0.3434), 1.220262, epsilon));
156 expect(math.approxEq(f32, acos32(0.5), 1.047198, epsilon));
157 expect(math.approxEq(f32, acos32(0.8923), 0.468382, epsilon));
158 expect(math.approxEq(f32, acos32(-0.2), 1.772154, epsilon));
159159}
160160
161161test "math.acos64" {
162162 const epsilon = 0.000001;
163163
164 assert(math.approxEq(f64, acos64(0.0), 1.570796, epsilon));
165 assert(math.approxEq(f64, acos64(0.2), 1.369438, epsilon));
166 assert(math.approxEq(f64, acos64(0.3434), 1.220262, epsilon));
167 assert(math.approxEq(f64, acos64(0.5), 1.047198, epsilon));
168 assert(math.approxEq(f64, acos64(0.8923), 0.468382, epsilon));
169 assert(math.approxEq(f64, acos64(-0.2), 1.772154, epsilon));
164 expect(math.approxEq(f64, acos64(0.0), 1.570796, epsilon));
165 expect(math.approxEq(f64, acos64(0.2), 1.369438, epsilon));
166 expect(math.approxEq(f64, acos64(0.3434), 1.220262, epsilon));
167 expect(math.approxEq(f64, acos64(0.5), 1.047198, epsilon));
168 expect(math.approxEq(f64, acos64(0.8923), 0.468382, epsilon));
169 expect(math.approxEq(f64, acos64(-0.2), 1.772154, epsilon));
170170}
171171
172172test "math.acos32.special" {
173 assert(math.isNan(acos32(-2)));
174 assert(math.isNan(acos32(1.5)));
173 expect(math.isNan(acos32(-2)));
174 expect(math.isNan(acos32(1.5)));
175175}
176176
177177test "math.acos64.special" {
178 assert(math.isNan(acos64(-2)));
179 assert(math.isNan(acos64(1.5)));
178 expect(math.isNan(acos64(-2)));
179 expect(math.isNan(acos64(1.5)));
180180}
std/math/acosh.zig+15-15
......@@ -6,7 +6,7 @@
66const builtin = @import("builtin");
77const std = @import("../index.zig");
88const math = std.math;
9const assert = std.debug.assert;
9const expect = std.testing.expect;
1010
1111pub fn acosh(x: var) @typeOf(x) {
1212 const T = @typeOf(x);
......@@ -55,34 +55,34 @@ fn acosh64(x: f64) f64 {
5555}
5656
5757test "math.acosh" {
58 assert(acosh(f32(1.5)) == acosh32(1.5));
59 assert(acosh(f64(1.5)) == acosh64(1.5));
58 expect(acosh(f32(1.5)) == acosh32(1.5));
59 expect(acosh(f64(1.5)) == acosh64(1.5));
6060}
6161
6262test "math.acosh32" {
6363 const epsilon = 0.000001;
6464
65 assert(math.approxEq(f32, acosh32(1.5), 0.962424, epsilon));
66 assert(math.approxEq(f32, acosh32(37.45), 4.315976, epsilon));
67 assert(math.approxEq(f32, acosh32(89.123), 5.183133, epsilon));
68 assert(math.approxEq(f32, acosh32(123123.234375), 12.414088, epsilon));
65 expect(math.approxEq(f32, acosh32(1.5), 0.962424, epsilon));
66 expect(math.approxEq(f32, acosh32(37.45), 4.315976, epsilon));
67 expect(math.approxEq(f32, acosh32(89.123), 5.183133, epsilon));
68 expect(math.approxEq(f32, acosh32(123123.234375), 12.414088, epsilon));
6969}
7070
7171test "math.acosh64" {
7272 const epsilon = 0.000001;
7373
74 assert(math.approxEq(f64, acosh64(1.5), 0.962424, epsilon));
75 assert(math.approxEq(f64, acosh64(37.45), 4.315976, epsilon));
76 assert(math.approxEq(f64, acosh64(89.123), 5.183133, epsilon));
77 assert(math.approxEq(f64, acosh64(123123.234375), 12.414088, epsilon));
74 expect(math.approxEq(f64, acosh64(1.5), 0.962424, epsilon));
75 expect(math.approxEq(f64, acosh64(37.45), 4.315976, epsilon));
76 expect(math.approxEq(f64, acosh64(89.123), 5.183133, epsilon));
77 expect(math.approxEq(f64, acosh64(123123.234375), 12.414088, epsilon));
7878}
7979
8080test "math.acosh32.special" {
81 assert(math.isNan(acosh32(math.nan(f32))));
82 assert(math.isSignalNan(acosh32(0.5)));
81 expect(math.isNan(acosh32(math.nan(f32))));
82 expect(math.isSignalNan(acosh32(0.5)));
8383}
8484
8585test "math.acosh64.special" {
86 assert(math.isNan(acosh64(math.nan(f64))));
87 assert(math.isSignalNan(acosh64(0.5)));
86 expect(math.isNan(acosh64(math.nan(f64))));
87 expect(math.isSignalNan(acosh64(0.5)));
8888}
std/math/asin.zig+23-23
......@@ -5,7 +5,7 @@
55
66const std = @import("../index.zig");
77const math = std.math;
8const assert = std.debug.assert;
8const expect = std.testing.expect;
99
1010pub fn asin(x: var) @typeOf(x) {
1111 const T = @typeOf(x);
......@@ -136,42 +136,42 @@ fn asin64(x: f64) f64 {
136136}
137137
138138test "math.asin" {
139 assert(asin(f32(0.0)) == asin32(0.0));
140 assert(asin(f64(0.0)) == asin64(0.0));
139 expect(asin(f32(0.0)) == asin32(0.0));
140 expect(asin(f64(0.0)) == asin64(0.0));
141141}
142142
143143test "math.asin32" {
144144 const epsilon = 0.000001;
145145
146 assert(math.approxEq(f32, asin32(0.0), 0.0, epsilon));
147 assert(math.approxEq(f32, asin32(0.2), 0.201358, epsilon));
148 assert(math.approxEq(f32, asin32(-0.2), -0.201358, epsilon));
149 assert(math.approxEq(f32, asin32(0.3434), 0.350535, epsilon));
150 assert(math.approxEq(f32, asin32(0.5), 0.523599, epsilon));
151 assert(math.approxEq(f32, asin32(0.8923), 1.102415, epsilon));
146 expect(math.approxEq(f32, asin32(0.0), 0.0, epsilon));
147 expect(math.approxEq(f32, asin32(0.2), 0.201358, epsilon));
148 expect(math.approxEq(f32, asin32(-0.2), -0.201358, epsilon));
149 expect(math.approxEq(f32, asin32(0.3434), 0.350535, epsilon));
150 expect(math.approxEq(f32, asin32(0.5), 0.523599, epsilon));
151 expect(math.approxEq(f32, asin32(0.8923), 1.102415, epsilon));
152152}
153153
154154test "math.asin64" {
155155 const epsilon = 0.000001;
156156
157 assert(math.approxEq(f64, asin64(0.0), 0.0, epsilon));
158 assert(math.approxEq(f64, asin64(0.2), 0.201358, epsilon));
159 assert(math.approxEq(f64, asin64(-0.2), -0.201358, epsilon));
160 assert(math.approxEq(f64, asin64(0.3434), 0.350535, epsilon));
161 assert(math.approxEq(f64, asin64(0.5), 0.523599, epsilon));
162 assert(math.approxEq(f64, asin64(0.8923), 1.102415, epsilon));
157 expect(math.approxEq(f64, asin64(0.0), 0.0, epsilon));
158 expect(math.approxEq(f64, asin64(0.2), 0.201358, epsilon));
159 expect(math.approxEq(f64, asin64(-0.2), -0.201358, epsilon));
160 expect(math.approxEq(f64, asin64(0.3434), 0.350535, epsilon));
161 expect(math.approxEq(f64, asin64(0.5), 0.523599, epsilon));
162 expect(math.approxEq(f64, asin64(0.8923), 1.102415, epsilon));
163163}
164164
165165test "math.asin32.special" {
166 assert(asin32(0.0) == 0.0);
167 assert(asin32(-0.0) == -0.0);
168 assert(math.isNan(asin32(-2)));
169 assert(math.isNan(asin32(1.5)));
166 expect(asin32(0.0) == 0.0);
167 expect(asin32(-0.0) == -0.0);
168 expect(math.isNan(asin32(-2)));
169 expect(math.isNan(asin32(1.5)));
170170}
171171
172172test "math.asin64.special" {
173 assert(asin64(0.0) == 0.0);
174 assert(asin64(-0.0) == -0.0);
175 assert(math.isNan(asin64(-2)));
176 assert(math.isNan(asin64(1.5)));
173 expect(asin64(0.0) == 0.0);
174 expect(asin64(-0.0) == -0.0);
175 expect(math.isNan(asin64(-2)));
176 expect(math.isNan(asin64(1.5)));
177177}
std/math/asinh.zig+27-27
......@@ -6,7 +6,7 @@
66
77const std = @import("../index.zig");
88const math = std.math;
9const assert = std.debug.assert;
9const expect = std.testing.expect;
1010const maxInt = std.math.maxInt;
1111
1212pub fn asinh(x: var) @typeOf(x) {
......@@ -83,46 +83,46 @@ fn asinh64(x: f64) f64 {
8383}
8484
8585test "math.asinh" {
86 assert(asinh(f32(0.0)) == asinh32(0.0));
87 assert(asinh(f64(0.0)) == asinh64(0.0));
86 expect(asinh(f32(0.0)) == asinh32(0.0));
87 expect(asinh(f64(0.0)) == asinh64(0.0));
8888}
8989
9090test "math.asinh32" {
9191 const epsilon = 0.000001;
9292
93 assert(math.approxEq(f32, asinh32(0.0), 0.0, epsilon));
94 assert(math.approxEq(f32, asinh32(0.2), 0.198690, epsilon));
95 assert(math.approxEq(f32, asinh32(0.8923), 0.803133, epsilon));
96 assert(math.approxEq(f32, asinh32(1.5), 1.194763, epsilon));
97 assert(math.approxEq(f32, asinh32(37.45), 4.316332, epsilon));
98 assert(math.approxEq(f32, asinh32(89.123), 5.183196, epsilon));
99 assert(math.approxEq(f32, asinh32(123123.234375), 12.414088, epsilon));
93 expect(math.approxEq(f32, asinh32(0.0), 0.0, epsilon));
94 expect(math.approxEq(f32, asinh32(0.2), 0.198690, epsilon));
95 expect(math.approxEq(f32, asinh32(0.8923), 0.803133, epsilon));
96 expect(math.approxEq(f32, asinh32(1.5), 1.194763, epsilon));
97 expect(math.approxEq(f32, asinh32(37.45), 4.316332, epsilon));
98 expect(math.approxEq(f32, asinh32(89.123), 5.183196, epsilon));
99 expect(math.approxEq(f32, asinh32(123123.234375), 12.414088, epsilon));
100100}
101101
102102test "math.asinh64" {
103103 const epsilon = 0.000001;
104104
105 assert(math.approxEq(f64, asinh64(0.0), 0.0, epsilon));
106 assert(math.approxEq(f64, asinh64(0.2), 0.198690, epsilon));
107 assert(math.approxEq(f64, asinh64(0.8923), 0.803133, epsilon));
108 assert(math.approxEq(f64, asinh64(1.5), 1.194763, epsilon));
109 assert(math.approxEq(f64, asinh64(37.45), 4.316332, epsilon));
110 assert(math.approxEq(f64, asinh64(89.123), 5.183196, epsilon));
111 assert(math.approxEq(f64, asinh64(123123.234375), 12.414088, epsilon));
105 expect(math.approxEq(f64, asinh64(0.0), 0.0, epsilon));
106 expect(math.approxEq(f64, asinh64(0.2), 0.198690, epsilon));
107 expect(math.approxEq(f64, asinh64(0.8923), 0.803133, epsilon));
108 expect(math.approxEq(f64, asinh64(1.5), 1.194763, epsilon));
109 expect(math.approxEq(f64, asinh64(37.45), 4.316332, epsilon));
110 expect(math.approxEq(f64, asinh64(89.123), 5.183196, epsilon));
111 expect(math.approxEq(f64, asinh64(123123.234375), 12.414088, epsilon));
112112}
113113
114114test "math.asinh32.special" {
115 assert(asinh32(0.0) == 0.0);
116 assert(asinh32(-0.0) == -0.0);
117 assert(math.isPositiveInf(asinh32(math.inf(f32))));
118 assert(math.isNegativeInf(asinh32(-math.inf(f32))));
119 assert(math.isNan(asinh32(math.nan(f32))));
115 expect(asinh32(0.0) == 0.0);
116 expect(asinh32(-0.0) == -0.0);
117 expect(math.isPositiveInf(asinh32(math.inf(f32))));
118 expect(math.isNegativeInf(asinh32(-math.inf(f32))));
119 expect(math.isNan(asinh32(math.nan(f32))));
120120}
121121
122122test "math.asinh64.special" {
123 assert(asinh64(0.0) == 0.0);
124 assert(asinh64(-0.0) == -0.0);
125 assert(math.isPositiveInf(asinh64(math.inf(f64))));
126 assert(math.isNegativeInf(asinh64(-math.inf(f64))));
127 assert(math.isNan(asinh64(math.nan(f64))));
123 expect(asinh64(0.0) == 0.0);
124 expect(asinh64(-0.0) == -0.0);
125 expect(math.isPositiveInf(asinh64(math.inf(f64))));
126 expect(math.isNegativeInf(asinh64(-math.inf(f64))));
127 expect(math.isNan(asinh64(math.nan(f64))));
128128}
std/math/atan.zig+21-21
......@@ -5,7 +5,7 @@
55
66const std = @import("../index.zig");
77const math = std.math;
8const assert = std.debug.assert;
8const expect = std.testing.expect;
99
1010pub fn atan(x: var) @typeOf(x) {
1111 const T = @typeOf(x);
......@@ -206,44 +206,44 @@ fn atan64(x_: f64) f64 {
206206}
207207
208208test "math.atan" {
209 assert(@bitCast(u32, atan(f32(0.2))) == @bitCast(u32, atan32(0.2)));
210 assert(atan(f64(0.2)) == atan64(0.2));
209 expect(@bitCast(u32, atan(f32(0.2))) == @bitCast(u32, atan32(0.2)));
210 expect(atan(f64(0.2)) == atan64(0.2));
211211}
212212
213213test "math.atan32" {
214214 const epsilon = 0.000001;
215215
216 assert(math.approxEq(f32, atan32(0.2), 0.197396, epsilon));
217 assert(math.approxEq(f32, atan32(-0.2), -0.197396, epsilon));
218 assert(math.approxEq(f32, atan32(0.3434), 0.330783, epsilon));
219 assert(math.approxEq(f32, atan32(0.8923), 0.728545, epsilon));
220 assert(math.approxEq(f32, atan32(1.5), 0.982794, epsilon));
216 expect(math.approxEq(f32, atan32(0.2), 0.197396, epsilon));
217 expect(math.approxEq(f32, atan32(-0.2), -0.197396, epsilon));
218 expect(math.approxEq(f32, atan32(0.3434), 0.330783, epsilon));
219 expect(math.approxEq(f32, atan32(0.8923), 0.728545, epsilon));
220 expect(math.approxEq(f32, atan32(1.5), 0.982794, epsilon));
221221}
222222
223223test "math.atan64" {
224224 const epsilon = 0.000001;
225225
226 assert(math.approxEq(f64, atan64(0.2), 0.197396, epsilon));
227 assert(math.approxEq(f64, atan64(-0.2), -0.197396, epsilon));
228 assert(math.approxEq(f64, atan64(0.3434), 0.330783, epsilon));
229 assert(math.approxEq(f64, atan64(0.8923), 0.728545, epsilon));
230 assert(math.approxEq(f64, atan64(1.5), 0.982794, epsilon));
226 expect(math.approxEq(f64, atan64(0.2), 0.197396, epsilon));
227 expect(math.approxEq(f64, atan64(-0.2), -0.197396, epsilon));
228 expect(math.approxEq(f64, atan64(0.3434), 0.330783, epsilon));
229 expect(math.approxEq(f64, atan64(0.8923), 0.728545, epsilon));
230 expect(math.approxEq(f64, atan64(1.5), 0.982794, epsilon));
231231}
232232
233233test "math.atan32.special" {
234234 const epsilon = 0.000001;
235235
236 assert(atan32(0.0) == 0.0);
237 assert(atan32(-0.0) == -0.0);
238 assert(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));
236 expect(atan32(0.0) == 0.0);
237 expect(atan32(-0.0) == -0.0);
238 expect(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));
240240}
241241
242242test "math.atan64.special" {
243243 const epsilon = 0.000001;
244244
245 assert(atan64(0.0) == 0.0);
246 assert(atan64(-0.0) == -0.0);
247 assert(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));
245 expect(atan64(0.0) == 0.0);
246 expect(atan64(-0.0) == -0.0);
247 expect(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));
249249}
std/math/atan2.zig+58-58
......@@ -20,12 +20,12 @@
2020
2121const std = @import("../index.zig");
2222const 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 {
2626 return switch (T) {
27 f32 => atan2_32(x, y),
28 f64 => atan2_64(x, y),
27 f32 => atan2_32(y, x),
28 f64 => atan2_64(y, x),
2929 else => @compileError("atan2 not implemented for " ++ @typeName(T)),
3030 };
3131}
......@@ -206,78 +206,78 @@ fn atan2_64(y: f64, x: f64) f64 {
206206}
207207
208208test "math.atan2" {
209 assert(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));
209 expect(atan2(f32, 0.2, 0.21) == atan2_32(0.2, 0.21));
210 expect(atan2(f64, 0.2, 0.21) == atan2_64(0.2, 0.21));
211211}
212212
213213test "math.atan2_32" {
214214 const epsilon = 0.000001;
215215
216 assert(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));
218 assert(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));
220 assert(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));
222 assert(math.approxEq(f32, atan2_32(0.34, 1.243), 0.267001, epsilon));
216 expect(math.approxEq(f32, atan2_32(0.0, 0.0), 0.0, epsilon));
217 expect(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 expect(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 expect(math.approxEq(f32, atan2_32(0.34, -0.4), 2.437099, epsilon));
222 expect(math.approxEq(f32, atan2_32(0.34, 1.243), 0.267001, epsilon));
223223}
224224
225225test "math.atan2_64" {
226226 const epsilon = 0.000001;
227227
228 assert(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));
230 assert(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));
232 assert(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));
234 assert(math.approxEq(f64, atan2_64(0.34, 1.243), 0.267001, epsilon));
228 expect(math.approxEq(f64, atan2_64(0.0, 0.0), 0.0, epsilon));
229 expect(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 expect(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 expect(math.approxEq(f64, atan2_64(0.34, -0.4), 2.437099, epsilon));
234 expect(math.approxEq(f64, atan2_64(0.34, 1.243), 0.267001, epsilon));
235235}
236236
237237test "math.atan2_32.special" {
238238 const epsilon = 0.000001;
239239
240 assert(math.isNan(atan2_32(1.0, math.nan(f32))));
241 assert(math.isNan(atan2_32(math.nan(f32), 1.0)));
242 assert(atan2_32(0.0, 5.0) == 0.0);
243 assert(atan2_32(-0.0, 5.0) == -0.0);
244 assert(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?
246 assert(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));
248 assert(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));
250 assert(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));
252 assert(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));
254 assert(atan2_32(1.0, math.inf(f32)) == 0.0);
255 assert(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));
257 assert(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));
240 expect(math.isNan(atan2_32(1.0, math.nan(f32))));
241 expect(math.isNan(atan2_32(math.nan(f32), 1.0)));
242 expect(atan2_32(0.0, 5.0) == 0.0);
243 expect(atan2_32(-0.0, 5.0) == -0.0);
244 expect(math.approxEq(f32, atan2_32(0.0, -5.0), math.pi, epsilon));
245 //expect(math.approxEq(f32, atan2_32(-0.0, -5.0), -math.pi, epsilon)); TODO support negative zero?
246 expect(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 expect(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 expect(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 expect(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 expect(atan2_32(1.0, math.inf(f32)) == 0.0);
255 expect(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 expect(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));
259259}
260260
261261test "math.atan2_64.special" {
262262 const epsilon = 0.000001;
263263
264 assert(math.isNan(atan2_64(1.0, math.nan(f64))));
265 assert(math.isNan(atan2_64(math.nan(f64), 1.0)));
266 assert(atan2_64(0.0, 5.0) == 0.0);
267 assert(atan2_64(-0.0, 5.0) == -0.0);
268 assert(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?
270 assert(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));
272 assert(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));
274 assert(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));
276 assert(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));
278 assert(atan2_64(1.0, math.inf(f64)) == 0.0);
279 assert(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));
281 assert(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));
264 expect(math.isNan(atan2_64(1.0, math.nan(f64))));
265 expect(math.isNan(atan2_64(math.nan(f64), 1.0)));
266 expect(atan2_64(0.0, 5.0) == 0.0);
267 expect(atan2_64(-0.0, 5.0) == -0.0);
268 expect(math.approxEq(f64, atan2_64(0.0, -5.0), math.pi, epsilon));
269 //expect(math.approxEq(f64, atan2_64(-0.0, -5.0), -math.pi, epsilon)); TODO support negative zero?
270 expect(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 expect(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 expect(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 expect(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 expect(atan2_64(1.0, math.inf(f64)) == 0.0);
279 expect(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 expect(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));
283283}
std/math/atanh.zig+19-19
......@@ -6,7 +6,7 @@
66
77const std = @import("../index.zig");
88const math = std.math;
9const assert = std.debug.assert;
9const expect = std.testing.expect;
1010const maxInt = std.math.maxInt;
1111
1212pub fn atanh(x: var) @typeOf(x) {
......@@ -78,38 +78,38 @@ fn atanh_64(x: f64) f64 {
7878}
7979
8080test "math.atanh" {
81 assert(atanh(f32(0.0)) == atanh_32(0.0));
82 assert(atanh(f64(0.0)) == atanh_64(0.0));
81 expect(atanh(f32(0.0)) == atanh_32(0.0));
82 expect(atanh(f64(0.0)) == atanh_64(0.0));
8383}
8484
8585test "math.atanh_32" {
8686 const epsilon = 0.000001;
8787
88 assert(math.approxEq(f32, atanh_32(0.0), 0.0, epsilon));
89 assert(math.approxEq(f32, atanh_32(0.2), 0.202733, epsilon));
90 assert(math.approxEq(f32, atanh_32(0.8923), 1.433099, epsilon));
88 expect(math.approxEq(f32, atanh_32(0.0), 0.0, epsilon));
89 expect(math.approxEq(f32, atanh_32(0.2), 0.202733, epsilon));
90 expect(math.approxEq(f32, atanh_32(0.8923), 1.433099, epsilon));
9191}
9292
9393test "math.atanh_64" {
9494 const epsilon = 0.000001;
9595
96 assert(math.approxEq(f64, atanh_64(0.0), 0.0, epsilon));
97 assert(math.approxEq(f64, atanh_64(0.2), 0.202733, epsilon));
98 assert(math.approxEq(f64, atanh_64(0.8923), 1.433099, epsilon));
96 expect(math.approxEq(f64, atanh_64(0.0), 0.0, epsilon));
97 expect(math.approxEq(f64, atanh_64(0.2), 0.202733, epsilon));
98 expect(math.approxEq(f64, atanh_64(0.8923), 1.433099, epsilon));
9999}
100100
101101test "math.atanh32.special" {
102 assert(math.isPositiveInf(atanh_32(1)));
103 assert(math.isNegativeInf(atanh_32(-1)));
104 assert(math.isSignalNan(atanh_32(1.5)));
105 assert(math.isSignalNan(atanh_32(-1.5)));
106 assert(math.isNan(atanh_32(math.nan(f32))));
102 expect(math.isPositiveInf(atanh_32(1)));
103 expect(math.isNegativeInf(atanh_32(-1)));
104 expect(math.isSignalNan(atanh_32(1.5)));
105 expect(math.isSignalNan(atanh_32(-1.5)));
106 expect(math.isNan(atanh_32(math.nan(f32))));
107107}
108108
109109test "math.atanh64.special" {
110 assert(math.isPositiveInf(atanh_64(1)));
111 assert(math.isNegativeInf(atanh_64(-1)));
112 assert(math.isSignalNan(atanh_64(1.5)));
113 assert(math.isSignalNan(atanh_64(-1.5)));
114 assert(math.isNan(atanh_64(math.nan(f64))));
110 expect(math.isPositiveInf(atanh_64(1)));
111 expect(math.isNegativeInf(atanh_64(-1)));
112 expect(math.isSignalNan(atanh_64(1.5)));
113 expect(math.isSignalNan(atanh_64(-1.5)));
114 expect(math.isNan(atanh_64(math.nan(f64))));
115115}
std/math/big/int.zig+180-187
......@@ -1,6 +1,7 @@
11const std = @import("../../index.zig");
22const builtin = @import("builtin");
33const debug = std.debug;
4const testing = std.testing;
45const math = std.math;
56const mem = std.mem;
67const Allocator = mem.Allocator;
......@@ -1086,44 +1087,40 @@ test "big.int comptime_int set" {
10861087 const result = Limb(s & maxInt(Limb));
10871088 s >>= Limb.bit_count / 2;
10881089 s >>= Limb.bit_count / 2;
1089 debug.assert(a.limbs[i] == result);
1090 testing.expect(a.limbs[i] == result);
10901091 }
10911092}
10921093
10931094test "big.int comptime_int set negative" {
10941095 var a = try Int.initSet(al, -10);
10951096
1096 debug.assert(a.limbs[0] == 10);
1097 debug.assert(a.positive == false);
1097 testing.expect(a.limbs[0] == 10);
1098 testing.expect(a.positive == false);
10981099}
10991100
11001101test "big.int int set unaligned small" {
11011102 var a = try Int.initSet(al, u7(45));
11021103
1103 debug.assert(a.limbs[0] == 45);
1104 debug.assert(a.positive == true);
1104 testing.expect(a.limbs[0] == 45);
1105 testing.expect(a.positive == true);
11051106}
11061107
11071108test "big.int comptime_int to" {
11081109 const a = try Int.initSet(al, 0xefffffff00000001eeeeeeefaaaaaaab);
11091110
1110 debug.assert((try a.to(u128)) == 0xefffffff00000001eeeeeeefaaaaaaab);
1111 testing.expect((try a.to(u128)) == 0xefffffff00000001eeeeeeefaaaaaaab);
11111112}
11121113
11131114test "big.int sub-limb to" {
11141115 const a = try Int.initSet(al, 10);
11151116
1116 debug.assert((try a.to(u8)) == 10);
1117 testing.expect((try a.to(u8)) == 10);
11171118}
11181119
11191120test "big.int to target too small error" {
11201121 const a = try Int.initSet(al, 0xffffffff);
11211122
1122 if (a.to(u8)) |_| {
1123 unreachable;
1124 } else |err| {
1125 debug.assert(err == error.TargetTooSmall);
1126 }
1123 testing.expectError(error.TargetTooSmall, a.to(u8));
11271124}
11281125
11291126test "big.int norm1" {
......@@ -1135,22 +1132,22 @@ test "big.int norm1" {
11351132 a.limbs[2] = 3;
11361133 a.limbs[3] = 0;
11371134 a.norm1(4);
1138 debug.assert(a.len == 3);
1135 testing.expect(a.len == 3);
11391136
11401137 a.limbs[0] = 1;
11411138 a.limbs[1] = 2;
11421139 a.limbs[2] = 3;
11431140 a.norm1(3);
1144 debug.assert(a.len == 3);
1141 testing.expect(a.len == 3);
11451142
11461143 a.limbs[0] = 0;
11471144 a.limbs[1] = 0;
11481145 a.norm1(2);
1149 debug.assert(a.len == 1);
1146 testing.expect(a.len == 1);
11501147
11511148 a.limbs[0] = 0;
11521149 a.norm1(1);
1153 debug.assert(a.len == 1);
1150 testing.expect(a.len == 1);
11541151}
11551152
11561153test "big.int normN" {
......@@ -1162,144 +1159,144 @@ test "big.int normN" {
11621159 a.limbs[2] = 0;
11631160 a.limbs[3] = 0;
11641161 a.normN(4);
1165 debug.assert(a.len == 2);
1162 testing.expect(a.len == 2);
11661163
11671164 a.limbs[0] = 1;
11681165 a.limbs[1] = 2;
11691166 a.limbs[2] = 3;
11701167 a.normN(3);
1171 debug.assert(a.len == 3);
1168 testing.expect(a.len == 3);
11721169
11731170 a.limbs[0] = 0;
11741171 a.limbs[1] = 0;
11751172 a.limbs[2] = 0;
11761173 a.limbs[3] = 0;
11771174 a.normN(4);
1178 debug.assert(a.len == 1);
1175 testing.expect(a.len == 1);
11791176
11801177 a.limbs[0] = 0;
11811178 a.normN(1);
1182 debug.assert(a.len == 1);
1179 testing.expect(a.len == 1);
11831180}
11841181
11851182test "big.int parity" {
11861183 var a = try Int.init(al);
11871184 try a.set(0);
1188 debug.assert(a.isEven());
1189 debug.assert(!a.isOdd());
1185 testing.expect(a.isEven());
1186 testing.expect(!a.isOdd());
11901187
11911188 try a.set(7);
1192 debug.assert(!a.isEven());
1193 debug.assert(a.isOdd());
1189 testing.expect(!a.isEven());
1190 testing.expect(a.isOdd());
11941191}
11951192
11961193test "big.int bitcount + sizeInBase" {
11971194 var a = try Int.init(al);
11981195
11991196 try a.set(0b100);
1200 debug.assert(a.bitCountAbs() == 3);
1201 debug.assert(a.sizeInBase(2) >= 3);
1202 debug.assert(a.sizeInBase(10) >= 1);
1197 testing.expect(a.bitCountAbs() == 3);
1198 testing.expect(a.sizeInBase(2) >= 3);
1199 testing.expect(a.sizeInBase(10) >= 1);
12031200
12041201 a.negate();
1205 debug.assert(a.bitCountAbs() == 3);
1206 debug.assert(a.sizeInBase(2) >= 4);
1207 debug.assert(a.sizeInBase(10) >= 2);
1202 testing.expect(a.bitCountAbs() == 3);
1203 testing.expect(a.sizeInBase(2) >= 4);
1204 testing.expect(a.sizeInBase(10) >= 2);
12081205
12091206 try a.set(0xffffffff);
1210 debug.assert(a.bitCountAbs() == 32);
1211 debug.assert(a.sizeInBase(2) >= 32);
1212 debug.assert(a.sizeInBase(10) >= 10);
1207 testing.expect(a.bitCountAbs() == 32);
1208 testing.expect(a.sizeInBase(2) >= 32);
1209 testing.expect(a.sizeInBase(10) >= 10);
12131210
12141211 try a.shiftLeft(a, 5000);
1215 debug.assert(a.bitCountAbs() == 5032);
1216 debug.assert(a.sizeInBase(2) >= 5032);
1212 testing.expect(a.bitCountAbs() == 5032);
1213 testing.expect(a.sizeInBase(2) >= 5032);
12171214 a.positive = false;
12181215
1219 debug.assert(a.bitCountAbs() == 5032);
1220 debug.assert(a.sizeInBase(2) >= 5033);
1216 testing.expect(a.bitCountAbs() == 5032);
1217 testing.expect(a.sizeInBase(2) >= 5033);
12211218}
12221219
12231220test "big.int bitcount/to" {
12241221 var a = try Int.init(al);
12251222
12261223 try a.set(0);
1227 debug.assert(a.bitCountTwosComp() == 0);
1224 testing.expect(a.bitCountTwosComp() == 0);
12281225
12291226 // TODO: stack smashing
1230 // debug.assert((try a.to(u0)) == 0);
1227 // testing.expect((try a.to(u0)) == 0);
12311228 // TODO: sigsegv
1232 // debug.assert((try a.to(i0)) == 0);
1229 // testing.expect((try a.to(i0)) == 0);
12331230
12341231 try a.set(-1);
1235 debug.assert(a.bitCountTwosComp() == 1);
1236 debug.assert((try a.to(i1)) == -1);
1232 testing.expect(a.bitCountTwosComp() == 1);
1233 testing.expect((try a.to(i1)) == -1);
12371234
12381235 try a.set(-8);
1239 debug.assert(a.bitCountTwosComp() == 4);
1240 debug.assert((try a.to(i4)) == -8);
1236 testing.expect(a.bitCountTwosComp() == 4);
1237 testing.expect((try a.to(i4)) == -8);
12411238
12421239 try a.set(127);
1243 debug.assert(a.bitCountTwosComp() == 7);
1244 debug.assert((try a.to(u7)) == 127);
1240 testing.expect(a.bitCountTwosComp() == 7);
1241 testing.expect((try a.to(u7)) == 127);
12451242
12461243 try a.set(-128);
1247 debug.assert(a.bitCountTwosComp() == 8);
1248 debug.assert((try a.to(i8)) == -128);
1244 testing.expect(a.bitCountTwosComp() == 8);
1245 testing.expect((try a.to(i8)) == -128);
12491246
12501247 try a.set(-129);
1251 debug.assert(a.bitCountTwosComp() == 9);
1252 debug.assert((try a.to(i9)) == -129);
1248 testing.expect(a.bitCountTwosComp() == 9);
1249 testing.expect((try a.to(i9)) == -129);
12531250}
12541251
12551252test "big.int fits" {
12561253 var a = try Int.init(al);
12571254
12581255 try a.set(0);
1259 debug.assert(a.fits(u0));
1260 debug.assert(a.fits(i0));
1256 testing.expect(a.fits(u0));
1257 testing.expect(a.fits(i0));
12611258
12621259 try a.set(255);
1263 debug.assert(!a.fits(u0));
1264 debug.assert(!a.fits(u1));
1265 debug.assert(!a.fits(i8));
1266 debug.assert(a.fits(u8));
1267 debug.assert(a.fits(u9));
1268 debug.assert(a.fits(i9));
1260 testing.expect(!a.fits(u0));
1261 testing.expect(!a.fits(u1));
1262 testing.expect(!a.fits(i8));
1263 testing.expect(a.fits(u8));
1264 testing.expect(a.fits(u9));
1265 testing.expect(a.fits(i9));
12691266
12701267 try a.set(-128);
1271 debug.assert(!a.fits(i7));
1272 debug.assert(a.fits(i8));
1273 debug.assert(a.fits(i9));
1274 debug.assert(!a.fits(u9));
1268 testing.expect(!a.fits(i7));
1269 testing.expect(a.fits(i8));
1270 testing.expect(a.fits(i9));
1271 testing.expect(!a.fits(u9));
12751272
12761273 try a.set(0x1ffffffffeeeeeeee);
1277 debug.assert(!a.fits(u32));
1278 debug.assert(!a.fits(u64));
1279 debug.assert(a.fits(u65));
1274 testing.expect(!a.fits(u32));
1275 testing.expect(!a.fits(u64));
1276 testing.expect(a.fits(u65));
12801277}
12811278
12821279test "big.int string set" {
12831280 var a = try Int.init(al);
12841281 try a.setString(10, "120317241209124781241290847124");
12851282
1286 debug.assert((try a.to(u128)) == 120317241209124781241290847124);
1283 testing.expect((try a.to(u128)) == 120317241209124781241290847124);
12871284}
12881285
12891286test "big.int string negative" {
12901287 var a = try Int.init(al);
12911288 try a.setString(10, "-1023");
1292 debug.assert((try a.to(i32)) == -1023);
1289 testing.expect((try a.to(i32)) == -1023);
12931290}
12941291
12951292test "big.int string set bad char error" {
12961293 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"));
12981295}
12991296
13001297test "big.int string set bad base error" {
13011298 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"));
13031300}
13041301
13051302test "big.int string to" {
......@@ -1308,17 +1305,13 @@ test "big.int string to" {
13081305 const as = try a.toString(al, 10);
13091306 const es = "120317241209124781241290847124";
13101307
1311 debug.assert(mem.eql(u8, as, es));
1308 testing.expect(mem.eql(u8, as, es));
13121309}
13131310
13141311test "big.int string to base base error" {
13151312 const a = try Int.initSet(al, 0xffffffff);
13161313
1317 if (a.toString(al, 45)) |_| {
1318 unreachable;
1319 } else |err| {
1320 debug.assert(err == error.InvalidBase);
1321 }
1314 testing.expectError(error.InvalidBase, a.toString(al, 45));
13221315}
13231316
13241317test "big.int string to base 2" {
......@@ -1327,7 +1320,7 @@ test "big.int string to base 2" {
13271320 const as = try a.toString(al, 2);
13281321 const es = "-1011";
13291322
1330 debug.assert(mem.eql(u8, as, es));
1323 testing.expect(mem.eql(u8, as, es));
13311324}
13321325
13331326test "big.int string to base 16" {
......@@ -1336,7 +1329,7 @@ test "big.int string to base 16" {
13361329 const as = try a.toString(al, 16);
13371330 const es = "efffffff00000001eeeeeeefaaaaaaab";
13381331
1339 debug.assert(mem.eql(u8, as, es));
1332 testing.expect(mem.eql(u8, as, es));
13401333}
13411334
13421335test "big.int neg string to" {
......@@ -1345,7 +1338,7 @@ test "big.int neg string to" {
13451338 const as = try a.toString(al, 10);
13461339 const es = "-123907434";
13471340
1348 debug.assert(mem.eql(u8, as, es));
1341 testing.expect(mem.eql(u8, as, es));
13491342}
13501343
13511344test "big.int zero string to" {
......@@ -1354,98 +1347,98 @@ test "big.int zero string to" {
13541347 const as = try a.toString(al, 10);
13551348 const es = "0";
13561349
1357 debug.assert(mem.eql(u8, as, es));
1350 testing.expect(mem.eql(u8, as, es));
13581351}
13591352
13601353test "big.int clone" {
13611354 var a = try Int.initSet(al, 1234);
13621355 const b = try a.clone();
13631356
1364 debug.assert((try a.to(u32)) == 1234);
1365 debug.assert((try b.to(u32)) == 1234);
1357 testing.expect((try a.to(u32)) == 1234);
1358 testing.expect((try b.to(u32)) == 1234);
13661359
13671360 try a.set(77);
1368 debug.assert((try a.to(u32)) == 77);
1369 debug.assert((try b.to(u32)) == 1234);
1361 testing.expect((try a.to(u32)) == 77);
1362 testing.expect((try b.to(u32)) == 1234);
13701363}
13711364
13721365test "big.int swap" {
13731366 var a = try Int.initSet(al, 1234);
13741367 var b = try Int.initSet(al, 5678);
13751368
1376 debug.assert((try a.to(u32)) == 1234);
1377 debug.assert((try b.to(u32)) == 5678);
1369 testing.expect((try a.to(u32)) == 1234);
1370 testing.expect((try b.to(u32)) == 5678);
13781371
13791372 a.swap(&b);
13801373
1381 debug.assert((try a.to(u32)) == 5678);
1382 debug.assert((try b.to(u32)) == 1234);
1374 testing.expect((try a.to(u32)) == 5678);
1375 testing.expect((try b.to(u32)) == 1234);
13831376}
13841377
13851378test "big.int to negative" {
13861379 var a = try Int.initSet(al, -10);
13871380
1388 debug.assert((try a.to(i32)) == -10);
1381 testing.expect((try a.to(i32)) == -10);
13891382}
13901383
13911384test "big.int compare" {
13921385 var a = try Int.initSet(al, -11);
13931386 var b = try Int.initSet(al, 10);
13941387
1395 debug.assert(a.cmpAbs(b) == 1);
1396 debug.assert(a.cmp(b) == -1);
1388 testing.expect(a.cmpAbs(b) == 1);
1389 testing.expect(a.cmp(b) == -1);
13971390}
13981391
13991392test "big.int compare similar" {
14001393 var a = try Int.initSet(al, 0xffffffffeeeeeeeeffffffffeeeeeeee);
14011394 var b = try Int.initSet(al, 0xffffffffeeeeeeeeffffffffeeeeeeef);
14021395
1403 debug.assert(a.cmpAbs(b) == -1);
1404 debug.assert(b.cmpAbs(a) == 1);
1396 testing.expect(a.cmpAbs(b) == -1);
1397 testing.expect(b.cmpAbs(a) == 1);
14051398}
14061399
14071400test "big.int compare different limb size" {
14081401 var a = try Int.initSet(al, maxInt(Limb) + 1);
14091402 var b = try Int.initSet(al, 1);
14101403
1411 debug.assert(a.cmpAbs(b) == 1);
1412 debug.assert(b.cmpAbs(a) == -1);
1404 testing.expect(a.cmpAbs(b) == 1);
1405 testing.expect(b.cmpAbs(a) == -1);
14131406}
14141407
14151408test "big.int compare multi-limb" {
14161409 var a = try Int.initSet(al, -0x7777777799999999ffffeeeeffffeeeeffffeeeef);
14171410 var b = try Int.initSet(al, 0x7777777799999999ffffeeeeffffeeeeffffeeeee);
14181411
1419 debug.assert(a.cmpAbs(b) == 1);
1420 debug.assert(a.cmp(b) == -1);
1412 testing.expect(a.cmpAbs(b) == 1);
1413 testing.expect(a.cmp(b) == -1);
14211414}
14221415
14231416test "big.int equality" {
14241417 var a = try Int.initSet(al, 0xffffffff1);
14251418 var b = try Int.initSet(al, -0xffffffff1);
14261419
1427 debug.assert(a.eqAbs(b));
1428 debug.assert(!a.eq(b));
1420 testing.expect(a.eqAbs(b));
1421 testing.expect(!a.eq(b));
14291422}
14301423
14311424test "big.int abs" {
14321425 var a = try Int.initSet(al, -5);
14331426
14341427 a.abs();
1435 debug.assert((try a.to(u32)) == 5);
1428 testing.expect((try a.to(u32)) == 5);
14361429
14371430 a.abs();
1438 debug.assert((try a.to(u32)) == 5);
1431 testing.expect((try a.to(u32)) == 5);
14391432}
14401433
14411434test "big.int negate" {
14421435 var a = try Int.initSet(al, 5);
14431436
14441437 a.negate();
1445 debug.assert((try a.to(i32)) == -5);
1438 testing.expect((try a.to(i32)) == -5);
14461439
14471440 a.negate();
1448 debug.assert((try a.to(i32)) == 5);
1441 testing.expect((try a.to(i32)) == 5);
14491442}
14501443
14511444test "big.int add single-single" {
......@@ -1455,7 +1448,7 @@ test "big.int add single-single" {
14551448 var c = try Int.init(al);
14561449 try c.add(a, b);
14571450
1458 debug.assert((try c.to(u32)) == 55);
1451 testing.expect((try c.to(u32)) == 55);
14591452}
14601453
14611454test "big.int add multi-single" {
......@@ -1465,10 +1458,10 @@ test "big.int add multi-single" {
14651458 var c = try Int.init(al);
14661459
14671460 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
14701463 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);
14721465}
14731466
14741467test "big.int add multi-multi" {
......@@ -1480,7 +1473,7 @@ test "big.int add multi-multi" {
14801473 var c = try Int.init(al);
14811474 try c.add(a, b);
14821475
1483 debug.assert((try c.to(u128)) == op1 + op2);
1476 testing.expect((try c.to(u128)) == op1 + op2);
14841477}
14851478
14861479test "big.int add zero-zero" {
......@@ -1490,7 +1483,7 @@ test "big.int add zero-zero" {
14901483 var c = try Int.init(al);
14911484 try c.add(a, b);
14921485
1493 debug.assert((try c.to(u32)) == 0);
1486 testing.expect((try c.to(u32)) == 0);
14941487}
14951488
14961489test "big.int add alias multi-limb nonzero-zero" {
......@@ -1500,7 +1493,7 @@ test "big.int add alias multi-limb nonzero-zero" {
15001493
15011494 try a.add(a, b);
15021495
1503 debug.assert((try a.to(u128)) == op1);
1496 testing.expect((try a.to(u128)) == op1);
15041497}
15051498
15061499test "big.int add sign" {
......@@ -1512,16 +1505,16 @@ test "big.int add sign" {
15121505 const neg_two = try Int.initSet(al, -2);
15131506
15141507 try a.add(one, two);
1515 debug.assert((try a.to(i32)) == 3);
1508 testing.expect((try a.to(i32)) == 3);
15161509
15171510 try a.add(neg_one, two);
1518 debug.assert((try a.to(i32)) == 1);
1511 testing.expect((try a.to(i32)) == 1);
15191512
15201513 try a.add(one, neg_two);
1521 debug.assert((try a.to(i32)) == -1);
1514 testing.expect((try a.to(i32)) == -1);
15221515
15231516 try a.add(neg_one, neg_two);
1524 debug.assert((try a.to(i32)) == -3);
1517 testing.expect((try a.to(i32)) == -3);
15251518}
15261519
15271520test "big.int sub single-single" {
......@@ -1531,7 +1524,7 @@ test "big.int sub single-single" {
15311524 var c = try Int.init(al);
15321525 try c.sub(a, b);
15331526
1534 debug.assert((try c.to(u32)) == 45);
1527 testing.expect((try c.to(u32)) == 45);
15351528}
15361529
15371530test "big.int sub multi-single" {
......@@ -1541,7 +1534,7 @@ test "big.int sub multi-single" {
15411534 var c = try Int.init(al);
15421535 try c.sub(a, b);
15431536
1544 debug.assert((try c.to(Limb)) == maxInt(Limb));
1537 testing.expect((try c.to(Limb)) == maxInt(Limb));
15451538}
15461539
15471540test "big.int sub multi-multi" {
......@@ -1554,7 +1547,7 @@ test "big.int sub multi-multi" {
15541547 var c = try Int.init(al);
15551548 try c.sub(a, b);
15561549
1557 debug.assert((try c.to(u128)) == op1 - op2);
1550 testing.expect((try c.to(u128)) == op1 - op2);
15581551}
15591552
15601553test "big.int sub equal" {
......@@ -1564,7 +1557,7 @@ test "big.int sub equal" {
15641557 var c = try Int.init(al);
15651558 try c.sub(a, b);
15661559
1567 debug.assert((try c.to(u32)) == 0);
1560 testing.expect((try c.to(u32)) == 0);
15681561}
15691562
15701563test "big.int sub sign" {
......@@ -1576,19 +1569,19 @@ test "big.int sub sign" {
15761569 const neg_two = try Int.initSet(al, -2);
15771570
15781571 try a.sub(one, two);
1579 debug.assert((try a.to(i32)) == -1);
1572 testing.expect((try a.to(i32)) == -1);
15801573
15811574 try a.sub(neg_one, two);
1582 debug.assert((try a.to(i32)) == -3);
1575 testing.expect((try a.to(i32)) == -3);
15831576
15841577 try a.sub(one, neg_two);
1585 debug.assert((try a.to(i32)) == 3);
1578 testing.expect((try a.to(i32)) == 3);
15861579
15871580 try a.sub(neg_one, neg_two);
1588 debug.assert((try a.to(i32)) == 1);
1581 testing.expect((try a.to(i32)) == 1);
15891582
15901583 try a.sub(neg_two, neg_one);
1591 debug.assert((try a.to(i32)) == -1);
1584 testing.expect((try a.to(i32)) == -1);
15921585}
15931586
15941587test "big.int mul single-single" {
......@@ -1598,7 +1591,7 @@ test "big.int mul single-single" {
15981591 var c = try Int.init(al);
15991592 try c.mul(a, b);
16001593
1601 debug.assert((try c.to(u64)) == 250);
1594 testing.expect((try c.to(u64)) == 250);
16021595}
16031596
16041597test "big.int mul multi-single" {
......@@ -1608,7 +1601,7 @@ test "big.int mul multi-single" {
16081601 var c = try Int.init(al);
16091602 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));
16121605}
16131606
16141607test "big.int mul multi-multi" {
......@@ -1620,7 +1613,7 @@ test "big.int mul multi-multi" {
16201613 var c = try Int.init(al);
16211614 try c.mul(a, b);
16221615
1623 debug.assert((try c.to(u256)) == op1 * op2);
1616 testing.expect((try c.to(u256)) == op1 * op2);
16241617}
16251618
16261619test "big.int mul alias r with a" {
......@@ -1629,7 +1622,7 @@ test "big.int mul alias r with a" {
16291622
16301623 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));
16331626}
16341627
16351628test "big.int mul alias r with b" {
......@@ -1638,7 +1631,7 @@ test "big.int mul alias r with b" {
16381631
16391632 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));
16421635}
16431636
16441637test "big.int mul alias r with a and b" {
......@@ -1646,7 +1639,7 @@ test "big.int mul alias r with a and b" {
16461639
16471640 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));
16501643}
16511644
16521645test "big.int mul a*0" {
......@@ -1656,7 +1649,7 @@ test "big.int mul a*0" {
16561649 var c = try Int.init(al);
16571650 try c.mul(a, b);
16581651
1659 debug.assert((try c.to(u32)) == 0);
1652 testing.expect((try c.to(u32)) == 0);
16601653}
16611654
16621655test "big.int mul 0*0" {
......@@ -1666,7 +1659,7 @@ test "big.int mul 0*0" {
16661659 var c = try Int.init(al);
16671660 try c.mul(a, b);
16681661
1669 debug.assert((try c.to(u32)) == 0);
1662 testing.expect((try c.to(u32)) == 0);
16701663}
16711664
16721665test "big.int div single-single no rem" {
......@@ -1677,8 +1670,8 @@ test "big.int div single-single no rem" {
16771670 var r = try Int.init(al);
16781671 try Int.divTrunc(&q, &r, a, b);
16791672
1680 debug.assert((try q.to(u32)) == 10);
1681 debug.assert((try r.to(u32)) == 0);
1673 testing.expect((try q.to(u32)) == 10);
1674 testing.expect((try r.to(u32)) == 0);
16821675}
16831676
16841677test "big.int div single-single with rem" {
......@@ -1689,8 +1682,8 @@ test "big.int div single-single with rem" {
16891682 var r = try Int.init(al);
16901683 try Int.divTrunc(&q, &r, a, b);
16911684
1692 debug.assert((try q.to(u32)) == 9);
1693 debug.assert((try r.to(u32)) == 4);
1685 testing.expect((try q.to(u32)) == 9);
1686 testing.expect((try r.to(u32)) == 4);
16941687}
16951688
16961689test "big.int div multi-single no rem" {
......@@ -1704,8 +1697,8 @@ test "big.int div multi-single no rem" {
17041697 var r = try Int.init(al);
17051698 try Int.divTrunc(&q, &r, a, b);
17061699
1707 debug.assert((try q.to(u64)) == op1 / op2);
1708 debug.assert((try r.to(u64)) == 0);
1700 testing.expect((try q.to(u64)) == op1 / op2);
1701 testing.expect((try r.to(u64)) == 0);
17091702}
17101703
17111704test "big.int div multi-single with rem" {
......@@ -1719,8 +1712,8 @@ test "big.int div multi-single with rem" {
17191712 var r = try Int.init(al);
17201713 try Int.divTrunc(&q, &r, a, b);
17211714
1722 debug.assert((try q.to(u64)) == op1 / op2);
1723 debug.assert((try r.to(u64)) == 3);
1715 testing.expect((try q.to(u64)) == op1 / op2);
1716 testing.expect((try r.to(u64)) == 3);
17241717}
17251718
17261719test "big.int div multi>2-single" {
......@@ -1734,8 +1727,8 @@ test "big.int div multi>2-single" {
17341727 var r = try Int.init(al);
17351728 try Int.divTrunc(&q, &r, a, b);
17361729
1737 debug.assert((try q.to(u128)) == op1 / op2);
1738 debug.assert((try r.to(u32)) == 0x3e4e);
1730 testing.expect((try q.to(u128)) == op1 / op2);
1731 testing.expect((try r.to(u32)) == 0x3e4e);
17391732}
17401733
17411734test "big.int div single-single q < r" {
......@@ -1746,8 +1739,8 @@ test "big.int div single-single q < r" {
17461739 var r = try Int.init(al);
17471740 try Int.divTrunc(&q, &r, a, b);
17481741
1749 debug.assert((try q.to(u64)) == 0);
1750 debug.assert((try r.to(u64)) == 0x0078f432);
1742 testing.expect((try q.to(u64)) == 0);
1743 testing.expect((try r.to(u64)) == 0x0078f432);
17511744}
17521745
17531746test "big.int div single-single q == r" {
......@@ -1758,8 +1751,8 @@ test "big.int div single-single q == r" {
17581751 var r = try Int.init(al);
17591752 try Int.divTrunc(&q, &r, a, b);
17601753
1761 debug.assert((try q.to(u64)) == 1);
1762 debug.assert((try r.to(u64)) == 0);
1754 testing.expect((try q.to(u64)) == 1);
1755 testing.expect((try r.to(u64)) == 0);
17631756}
17641757
17651758test "big.int div q=0 alias" {
......@@ -1768,8 +1761,8 @@ test "big.int div q=0 alias" {
17681761
17691762 try Int.divTrunc(&a, &b, a, b);
17701763
1771 debug.assert((try a.to(u64)) == 0);
1772 debug.assert((try b.to(u64)) == 3);
1764 testing.expect((try a.to(u64)) == 0);
1765 testing.expect((try b.to(u64)) == 3);
17731766}
17741767
17751768test "big.int div multi-multi q < r" {
......@@ -1782,8 +1775,8 @@ test "big.int div multi-multi q < r" {
17821775 var r = try Int.init(al);
17831776 try Int.divTrunc(&q, &r, a, b);
17841777
1785 debug.assert((try q.to(u128)) == 0);
1786 debug.assert((try r.to(u128)) == op1);
1778 testing.expect((try q.to(u128)) == 0);
1779 testing.expect((try r.to(u128)) == op1);
17871780}
17881781
17891782test "big.int div trunc single-single +/+" {
......@@ -1802,8 +1795,8 @@ test "big.int div trunc single-single +/+" {
18021795 const eq = @divTrunc(u, v);
18031796 const er = @mod(u, v);
18041797
1805 debug.assert((try q.to(i32)) == eq);
1806 debug.assert((try r.to(i32)) == er);
1798 testing.expect((try q.to(i32)) == eq);
1799 testing.expect((try r.to(i32)) == er);
18071800}
18081801
18091802test "big.int div trunc single-single -/+" {
......@@ -1822,8 +1815,8 @@ test "big.int div trunc single-single -/+" {
18221815 const eq = -1;
18231816 const er = -2;
18241817
1825 debug.assert((try q.to(i32)) == eq);
1826 debug.assert((try r.to(i32)) == er);
1818 testing.expect((try q.to(i32)) == eq);
1819 testing.expect((try r.to(i32)) == er);
18271820}
18281821
18291822test "big.int div trunc single-single +/-" {
......@@ -1842,8 +1835,8 @@ test "big.int div trunc single-single +/-" {
18421835 const eq = -1;
18431836 const er = 2;
18441837
1845 debug.assert((try q.to(i32)) == eq);
1846 debug.assert((try r.to(i32)) == er);
1838 testing.expect((try q.to(i32)) == eq);
1839 testing.expect((try r.to(i32)) == er);
18471840}
18481841
18491842test "big.int div trunc single-single -/-" {
......@@ -1862,8 +1855,8 @@ test "big.int div trunc single-single -/-" {
18621855 const eq = 1;
18631856 const er = -2;
18641857
1865 debug.assert((try q.to(i32)) == eq);
1866 debug.assert((try r.to(i32)) == er);
1858 testing.expect((try q.to(i32)) == eq);
1859 testing.expect((try r.to(i32)) == er);
18671860}
18681861
18691862test "big.int div floor single-single +/+" {
......@@ -1882,8 +1875,8 @@ test "big.int div floor single-single +/+" {
18821875 const eq = 1;
18831876 const er = 2;
18841877
1885 debug.assert((try q.to(i32)) == eq);
1886 debug.assert((try r.to(i32)) == er);
1878 testing.expect((try q.to(i32)) == eq);
1879 testing.expect((try r.to(i32)) == er);
18871880}
18881881
18891882test "big.int div floor single-single -/+" {
......@@ -1902,8 +1895,8 @@ test "big.int div floor single-single -/+" {
19021895 const eq = -2;
19031896 const er = 1;
19041897
1905 debug.assert((try q.to(i32)) == eq);
1906 debug.assert((try r.to(i32)) == er);
1898 testing.expect((try q.to(i32)) == eq);
1899 testing.expect((try r.to(i32)) == er);
19071900}
19081901
19091902test "big.int div floor single-single +/-" {
......@@ -1922,8 +1915,8 @@ test "big.int div floor single-single +/-" {
19221915 const eq = -2;
19231916 const er = -1;
19241917
1925 debug.assert((try q.to(i32)) == eq);
1926 debug.assert((try r.to(i32)) == er);
1918 testing.expect((try q.to(i32)) == eq);
1919 testing.expect((try r.to(i32)) == er);
19271920}
19281921
19291922test "big.int div floor single-single -/-" {
......@@ -1942,8 +1935,8 @@ test "big.int div floor single-single -/-" {
19421935 const eq = 1;
19431936 const er = -2;
19441937
1945 debug.assert((try q.to(i32)) == eq);
1946 debug.assert((try r.to(i32)) == er);
1938 testing.expect((try q.to(i32)) == eq);
1939 testing.expect((try r.to(i32)) == er);
19471940}
19481941
19491942test "big.int div multi-multi with rem" {
......@@ -1954,8 +1947,8 @@ test "big.int div multi-multi with rem" {
19541947 var r = try Int.init(al);
19551948 try Int.divTrunc(&q, &r, a, b);
19561949
1957 debug.assert((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b);
1958 debug.assert((try r.to(u128)) == 0x28de0acacd806823638);
1950 testing.expect((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b);
1951 testing.expect((try r.to(u128)) == 0x28de0acacd806823638);
19591952}
19601953
19611954test "big.int div multi-multi no rem" {
......@@ -1966,8 +1959,8 @@ test "big.int div multi-multi no rem" {
19661959 var r = try Int.init(al);
19671960 try Int.divTrunc(&q, &r, a, b);
19681961
1969 debug.assert((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b);
1970 debug.assert((try r.to(u128)) == 0);
1962 testing.expect((try q.to(u128)) == 0xe38f38e39161aaabd03f0f1b);
1963 testing.expect((try r.to(u128)) == 0);
19711964}
19721965
19731966test "big.int div multi-multi (2 branch)" {
......@@ -1978,8 +1971,8 @@ test "big.int div multi-multi (2 branch)" {
19781971 var r = try Int.init(al);
19791972 try Int.divTrunc(&q, &r, a, b);
19801973
1981 debug.assert((try q.to(u128)) == 0x10000000000000000);
1982 debug.assert((try r.to(u128)) == 0x44444443444444431111111111111111);
1974 testing.expect((try q.to(u128)) == 0x10000000000000000);
1975 testing.expect((try r.to(u128)) == 0x44444443444444431111111111111111);
19831976}
19841977
19851978test "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)" {
19901983 var r = try Int.init(al);
19911984 try Int.divTrunc(&q, &r, a, b);
19921985
1993 debug.assert((try q.to(u128)) == 0xfffffffffffffffffff);
1994 debug.assert((try r.to(u256)) == 0x1111111111111111111110b12222222222222222282);
1986 testing.expect((try q.to(u128)) == 0xfffffffffffffffffff);
1987 testing.expect((try r.to(u256)) == 0x1111111111111111111110b12222222222222222282);
19951988}
19961989
19971990test "big.int shift-right single" {
19981991 var a = try Int.initSet(al, 0xffff0000);
19991992 try a.shiftRight(a, 16);
20001993
2001 debug.assert((try a.to(u32)) == 0xffff);
1994 testing.expect((try a.to(u32)) == 0xffff);
20021995}
20031996
20041997test "big.int shift-right multi" {
20051998 var a = try Int.initSet(al, 0xffff0000eeee1111dddd2222cccc3333);
20061999 try a.shiftRight(a, 67);
20072000
2008 debug.assert((try a.to(u64)) == 0x1fffe0001dddc222);
2001 testing.expect((try a.to(u64)) == 0x1fffe0001dddc222);
20092002}
20102003
20112004test "big.int shift-left single" {
20122005 var a = try Int.initSet(al, 0xffff);
20132006 try a.shiftLeft(a, 16);
20142007
2015 debug.assert((try a.to(u64)) == 0xffff0000);
2008 testing.expect((try a.to(u64)) == 0xffff0000);
20162009}
20172010
20182011test "big.int shift-left multi" {
20192012 var a = try Int.initSet(al, 0x1fffe0001dddc222);
20202013 try a.shiftLeft(a, 67);
20212014
2022 debug.assert((try a.to(u128)) == 0xffff0000eeee11100000000000000000);
2015 testing.expect((try a.to(u128)) == 0xffff0000eeee11100000000000000000);
20232016}
20242017
20252018test "big.int shift-right negative" {
20262019 var a = try Int.init(al);
20272020
20282021 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
20312024 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);
20332026}
20342027
20352028test "big.int shift-left negative" {
20362029 var a = try Int.init(al);
20372030
20382031 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);
20402033}
20412034
20422035test "big.int bitwise and simple" {
......@@ -2045,7 +2038,7 @@ test "big.int bitwise and simple" {
20452038
20462039 try a.bitAnd(a, b);
20472040
2048 debug.assert((try a.to(u64)) == 0xeeeeeeee00000000);
2041 testing.expect((try a.to(u64)) == 0xeeeeeeee00000000);
20492042}
20502043
20512044test "big.int bitwise and multi-limb" {
......@@ -2054,7 +2047,7 @@ test "big.int bitwise and multi-limb" {
20542047
20552048 try a.bitAnd(a, b);
20562049
2057 debug.assert((try a.to(u128)) == 0);
2050 testing.expect((try a.to(u128)) == 0);
20582051}
20592052
20602053test "big.int bitwise xor simple" {
......@@ -2063,7 +2056,7 @@ test "big.int bitwise xor simple" {
20632056
20642057 try a.bitXor(a, b);
20652058
2066 debug.assert((try a.to(u64)) == 0x1111111133333333);
2059 testing.expect((try a.to(u64)) == 0x1111111133333333);
20672060}
20682061
20692062test "big.int bitwise xor multi-limb" {
......@@ -2072,7 +2065,7 @@ test "big.int bitwise xor multi-limb" {
20722065
20732066 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));
20762069}
20772070
20782071test "big.int bitwise or simple" {
......@@ -2081,7 +2074,7 @@ test "big.int bitwise or simple" {
20812074
20822075 try a.bitOr(a, b);
20832076
2084 debug.assert((try a.to(u64)) == 0xffffffff33333333);
2077 testing.expect((try a.to(u64)) == 0xffffffff33333333);
20852078}
20862079
20872080test "big.int bitwise or multi-limb" {
......@@ -2091,15 +2084,15 @@ test "big.int bitwise or multi-limb" {
20912084 try a.bitOr(a, b);
20922085
20932086 // 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));
20952088}
20962089
20972090test "big.int var args" {
20982091 var a = try Int.initSet(al, 5);
20992092
21002093 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);
2104 debug.assert(a.cmp(try Int.initSet(al, 14)) <= 0);
2096 testing.expect(a.cmp(try Int.initSet(al, 11)) == 0);
2097 testing.expect(a.cmp(try Int.initSet(al, 14)) <= 0);
21052098}
std/math/cbrt.zig+25-25
......@@ -6,7 +6,7 @@
66
77const std = @import("../index.zig");
88const math = std.math;
9const assert = std.debug.assert;
9const expect = std.testing.expect;
1010
1111pub fn cbrt(x: var) @typeOf(x) {
1212 const T = @typeOf(x);
......@@ -114,44 +114,44 @@ fn cbrt64(x: f64) f64 {
114114}
115115
116116test "math.cbrt" {
117 assert(cbrt(f32(0.0)) == cbrt32(0.0));
118 assert(cbrt(f64(0.0)) == cbrt64(0.0));
117 expect(cbrt(f32(0.0)) == cbrt32(0.0));
118 expect(cbrt(f64(0.0)) == cbrt64(0.0));
119119}
120120
121121test "math.cbrt32" {
122122 const epsilon = 0.000001;
123123
124 assert(cbrt32(0.0) == 0.0);
125 assert(math.approxEq(f32, cbrt32(0.2), 0.584804, epsilon));
126 assert(math.approxEq(f32, cbrt32(0.8923), 0.962728, epsilon));
127 assert(math.approxEq(f32, cbrt32(1.5), 1.144714, epsilon));
128 assert(math.approxEq(f32, cbrt32(37.45), 3.345676, epsilon));
129 assert(math.approxEq(f32, cbrt32(123123.234375), 49.748501, epsilon));
124 expect(cbrt32(0.0) == 0.0);
125 expect(math.approxEq(f32, cbrt32(0.2), 0.584804, epsilon));
126 expect(math.approxEq(f32, cbrt32(0.8923), 0.962728, epsilon));
127 expect(math.approxEq(f32, cbrt32(1.5), 1.144714, epsilon));
128 expect(math.approxEq(f32, cbrt32(37.45), 3.345676, epsilon));
129 expect(math.approxEq(f32, cbrt32(123123.234375), 49.748501, epsilon));
130130}
131131
132132test "math.cbrt64" {
133133 const epsilon = 0.000001;
134134
135 assert(cbrt64(0.0) == 0.0);
136 assert(math.approxEq(f64, cbrt64(0.2), 0.584804, epsilon));
137 assert(math.approxEq(f64, cbrt64(0.8923), 0.962728, epsilon));
138 assert(math.approxEq(f64, cbrt64(1.5), 1.144714, epsilon));
139 assert(math.approxEq(f64, cbrt64(37.45), 3.345676, epsilon));
140 assert(math.approxEq(f64, cbrt64(123123.234375), 49.748501, epsilon));
135 expect(cbrt64(0.0) == 0.0);
136 expect(math.approxEq(f64, cbrt64(0.2), 0.584804, epsilon));
137 expect(math.approxEq(f64, cbrt64(0.8923), 0.962728, epsilon));
138 expect(math.approxEq(f64, cbrt64(1.5), 1.144714, epsilon));
139 expect(math.approxEq(f64, cbrt64(37.45), 3.345676, epsilon));
140 expect(math.approxEq(f64, cbrt64(123123.234375), 49.748501, epsilon));
141141}
142142
143143test "math.cbrt.special" {
144 assert(cbrt32(0.0) == 0.0);
145 assert(cbrt32(-0.0) == -0.0);
146 assert(math.isPositiveInf(cbrt32(math.inf(f32))));
147 assert(math.isNegativeInf(cbrt32(-math.inf(f32))));
148 assert(math.isNan(cbrt32(math.nan(f32))));
144 expect(cbrt32(0.0) == 0.0);
145 expect(cbrt32(-0.0) == -0.0);
146 expect(math.isPositiveInf(cbrt32(math.inf(f32))));
147 expect(math.isNegativeInf(cbrt32(-math.inf(f32))));
148 expect(math.isNan(cbrt32(math.nan(f32))));
149149}
150150
151151test "math.cbrt64.special" {
152 assert(cbrt64(0.0) == 0.0);
153 assert(cbrt64(-0.0) == -0.0);
154 assert(math.isPositiveInf(cbrt64(math.inf(f64))));
155 assert(math.isNegativeInf(cbrt64(-math.inf(f64))));
156 assert(math.isNan(cbrt64(math.nan(f64))));
152 expect(cbrt64(0.0) == 0.0);
153 expect(cbrt64(-0.0) == -0.0);
154 expect(math.isPositiveInf(cbrt64(math.inf(f64))));
155 expect(math.isNegativeInf(cbrt64(-math.inf(f64))));
156 expect(math.isNan(cbrt64(math.nan(f64))));
157157}
std/math/ceil.zig+19-19
......@@ -7,7 +7,7 @@
77const builtin = @import("builtin");
88const std = @import("../index.zig");
99const math = std.math;
10const assert = std.debug.assert;
10const expect = std.testing.expect;
1111
1212pub fn ceil(x: var) @typeOf(x) {
1313 const T = @typeOf(x);
......@@ -81,34 +81,34 @@ fn ceil64(x: f64) f64 {
8181}
8282
8383test "math.ceil" {
84 assert(ceil(f32(0.0)) == ceil32(0.0));
85 assert(ceil(f64(0.0)) == ceil64(0.0));
84 expect(ceil(f32(0.0)) == ceil32(0.0));
85 expect(ceil(f64(0.0)) == ceil64(0.0));
8686}
8787
8888test "math.ceil32" {
89 assert(ceil32(1.3) == 2.0);
90 assert(ceil32(-1.3) == -1.0);
91 assert(ceil32(0.2) == 1.0);
89 expect(ceil32(1.3) == 2.0);
90 expect(ceil32(-1.3) == -1.0);
91 expect(ceil32(0.2) == 1.0);
9292}
9393
9494test "math.ceil64" {
95 assert(ceil64(1.3) == 2.0);
96 assert(ceil64(-1.3) == -1.0);
97 assert(ceil64(0.2) == 1.0);
95 expect(ceil64(1.3) == 2.0);
96 expect(ceil64(-1.3) == -1.0);
97 expect(ceil64(0.2) == 1.0);
9898}
9999
100100test "math.ceil32.special" {
101 assert(ceil32(0.0) == 0.0);
102 assert(ceil32(-0.0) == -0.0);
103 assert(math.isPositiveInf(ceil32(math.inf(f32))));
104 assert(math.isNegativeInf(ceil32(-math.inf(f32))));
105 assert(math.isNan(ceil32(math.nan(f32))));
101 expect(ceil32(0.0) == 0.0);
102 expect(ceil32(-0.0) == -0.0);
103 expect(math.isPositiveInf(ceil32(math.inf(f32))));
104 expect(math.isNegativeInf(ceil32(-math.inf(f32))));
105 expect(math.isNan(ceil32(math.nan(f32))));
106106}
107107
108108test "math.ceil64.special" {
109 assert(ceil64(0.0) == 0.0);
110 assert(ceil64(-0.0) == -0.0);
111 assert(math.isPositiveInf(ceil64(math.inf(f64))));
112 assert(math.isNegativeInf(ceil64(-math.inf(f64))));
113 assert(math.isNan(ceil64(math.nan(f64))));
109 expect(ceil64(0.0) == 0.0);
110 expect(ceil64(-0.0) == -0.0);
111 expect(math.isPositiveInf(ceil64(math.inf(f64))));
112 expect(math.isNegativeInf(ceil64(-math.inf(f64))));
113 expect(math.isNan(ceil64(math.nan(f64))));
114114}
std/math/complex/abs.zig+2-2
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -14,5 +14,5 @@ const epsilon = 0.0001;
1414test "complex.cabs" {
1515 const a = Complex(f32).new(5, 3);
1616 const c = abs(a);
17 debug.assert(math.approxEq(f32, c, 5.83095, epsilon));
17 testing.expect(math.approxEq(f32, c, 5.83095, epsilon));
1818}
std/math/complex/acos.zig+3-3
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -16,6 +16,6 @@ test "complex.cacos" {
1616 const a = Complex(f32).new(5, 3);
1717 const c = acos(a);
1818
19 debug.assert(math.approxEq(f32, c.re, 0.546975, epsilon));
20 debug.assert(math.approxEq(f32, c.im, -2.452914, epsilon));
19 testing.expect(math.approxEq(f32, c.re, 0.546975, epsilon));
20 testing.expect(math.approxEq(f32, c.im, -2.452914, epsilon));
2121}
std/math/complex/acosh.zig+3-3
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -16,6 +16,6 @@ test "complex.cacosh" {
1616 const a = Complex(f32).new(5, 3);
1717 const c = acosh(a);
1818
19 debug.assert(math.approxEq(f32, c.re, 2.452914, epsilon));
20 debug.assert(math.approxEq(f32, c.im, 0.546975, epsilon));
19 testing.expect(math.approxEq(f32, c.re, 2.452914, epsilon));
20 testing.expect(math.approxEq(f32, c.im, 0.546975, epsilon));
2121}
std/math/complex/arg.zig+2-2
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -14,5 +14,5 @@ const epsilon = 0.0001;
1414test "complex.carg" {
1515 const a = Complex(f32).new(5, 3);
1616 const c = arg(a);
17 debug.assert(math.approxEq(f32, c, 0.540420, epsilon));
17 testing.expect(math.approxEq(f32, c, 0.540420, epsilon));
1818}
std/math/complex/asin.zig+3-3
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -22,6 +22,6 @@ test "complex.casin" {
2222 const a = Complex(f32).new(5, 3);
2323 const c = asin(a);
2424
25 debug.assert(math.approxEq(f32, c.re, 1.023822, epsilon));
26 debug.assert(math.approxEq(f32, c.im, 2.452914, epsilon));
25 testing.expect(math.approxEq(f32, c.re, 1.023822, epsilon));
26 testing.expect(math.approxEq(f32, c.im, 2.452914, epsilon));
2727}
std/math/complex/asinh.zig+3-3
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -17,6 +17,6 @@ test "complex.casinh" {
1717 const a = Complex(f32).new(5, 3);
1818 const c = asinh(a);
1919
20 debug.assert(math.approxEq(f32, c.re, 2.459831, epsilon));
21 debug.assert(math.approxEq(f32, c.im, 0.533999, epsilon));
20 testing.expect(math.approxEq(f32, c.re, 2.459831, epsilon));
21 testing.expect(math.approxEq(f32, c.im, 0.533999, epsilon));
2222}
std/math/complex/atan.zig+5-5
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -117,14 +117,14 @@ test "complex.catan32" {
117117 const a = Complex(f32).new(5, 3);
118118 const c = atan(a);
119119
120 debug.assert(math.approxEq(f32, c.re, 1.423679, epsilon));
121 debug.assert(math.approxEq(f32, c.im, 0.086569, epsilon));
120 testing.expect(math.approxEq(f32, c.re, 1.423679, epsilon));
121 testing.expect(math.approxEq(f32, c.im, 0.086569, epsilon));
122122}
123123
124124test "complex.catan64" {
125125 const a = Complex(f64).new(5, 3);
126126 const c = atan(a);
127127
128 debug.assert(math.approxEq(f64, c.re, 1.423679, epsilon));
129 debug.assert(math.approxEq(f64, c.im, 0.086569, epsilon));
128 testing.expect(math.approxEq(f64, c.re, 1.423679, epsilon));
129 testing.expect(math.approxEq(f64, c.im, 0.086569, epsilon));
130130}
std/math/complex/atanh.zig+3-3
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -17,6 +17,6 @@ test "complex.catanh" {
1717 const a = Complex(f32).new(5, 3);
1818 const c = atanh(a);
1919
20 debug.assert(math.approxEq(f32, c.re, 0.146947, epsilon));
21 debug.assert(math.approxEq(f32, c.im, 1.480870, epsilon));
20 testing.expect(math.approxEq(f32, c.re, 0.146947, epsilon));
21 testing.expect(math.approxEq(f32, c.im, 1.480870, epsilon));
2222}
std/math/complex/conj.zig+2-2
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -13,5 +13,5 @@ test "complex.conj" {
1313 const a = Complex(f32).new(5, 3);
1414 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);
1717}
std/math/complex/cos.zig+3-3
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -16,6 +16,6 @@ test "complex.ccos" {
1616 const a = Complex(f32).new(5, 3);
1717 const c = cos(a);
1818
19 debug.assert(math.approxEq(f32, c.re, 2.855815, epsilon));
20 debug.assert(math.approxEq(f32, c.im, 9.606383, epsilon));
19 testing.expect(math.approxEq(f32, c.re, 2.855815, epsilon));
20 testing.expect(math.approxEq(f32, c.im, 9.606383, epsilon));
2121}
std/math/complex/cosh.zig+5-5
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -152,14 +152,14 @@ test "complex.ccosh32" {
152152 const a = Complex(f32).new(5, 3);
153153 const c = cosh(a);
154154
155 debug.assert(math.approxEq(f32, c.re, -73.467300, epsilon));
156 debug.assert(math.approxEq(f32, c.im, 10.471557, epsilon));
155 testing.expect(math.approxEq(f32, c.re, -73.467300, epsilon));
156 testing.expect(math.approxEq(f32, c.im, 10.471557, epsilon));
157157}
158158
159159test "complex.ccosh64" {
160160 const a = Complex(f64).new(5, 3);
161161 const c = cosh(a);
162162
163 debug.assert(math.approxEq(f64, c.re, -73.467300, epsilon));
164 debug.assert(math.approxEq(f64, c.im, 10.471557, epsilon));
163 testing.expect(math.approxEq(f64, c.re, -73.467300, epsilon));
164 testing.expect(math.approxEq(f64, c.im, 10.471557, epsilon));
165165}
std/math/complex/exp.zig+5-5
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -118,14 +118,14 @@ test "complex.cexp32" {
118118 const a = Complex(f32).new(5, 3);
119119 const c = exp(a);
120120
121 debug.assert(math.approxEq(f32, c.re, -146.927917, epsilon));
122 debug.assert(math.approxEq(f32, c.im, 20.944065, epsilon));
121 testing.expect(math.approxEq(f32, c.re, -146.927917, epsilon));
122 testing.expect(math.approxEq(f32, c.im, 20.944065, epsilon));
123123}
124124
125125test "complex.cexp64" {
126126 const a = Complex(f64).new(5, 3);
127127 const c = exp(a);
128128
129 debug.assert(math.approxEq(f64, c.re, -146.927917, epsilon));
130 debug.assert(math.approxEq(f64, c.im, 20.944065, epsilon));
129 testing.expect(math.approxEq(f64, c.re, -146.927917, epsilon));
130 testing.expect(math.approxEq(f64, c.im, 20.944065, epsilon));
131131}
std/math/complex/index.zig+8-8
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44
55pub const abs = @import("abs.zig").abs;
......@@ -97,7 +97,7 @@ test "complex.add" {
9797 const b = Complex(f32).new(2, 7);
9898 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);
101101}
102102
103103test "complex.sub" {
......@@ -105,7 +105,7 @@ test "complex.sub" {
105105 const b = Complex(f32).new(2, 7);
106106 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);
109109}
110110
111111test "complex.mul" {
......@@ -113,7 +113,7 @@ test "complex.mul" {
113113 const b = Complex(f32).new(2, 7);
114114 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);
117117}
118118
119119test "complex.div" {
......@@ -121,7 +121,7 @@ test "complex.div" {
121121 const b = Complex(f32).new(2, 7);
122122 const c = a.div(b);
123123
124 debug.assert(math.approxEq(f32, c.re, f32(31) / 53, epsilon) and
124 testing.expect(math.approxEq(f32, c.re, f32(31) / 53, epsilon) and
125125 math.approxEq(f32, c.im, f32(-29) / 53, epsilon));
126126}
127127
......@@ -129,14 +129,14 @@ test "complex.conjugate" {
129129 const a = Complex(f32).new(5, 3);
130130 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);
133133}
134134
135135test "complex.reciprocal" {
136136 const a = Complex(f32).new(5, 3);
137137 const c = a.reciprocal();
138138
139 debug.assert(math.approxEq(f32, c.re, f32(5) / 34, epsilon) and
139 testing.expect(math.approxEq(f32, c.re, f32(5) / 34, epsilon) and
140140 math.approxEq(f32, c.im, f32(-3) / 34, epsilon));
141141}
142142
......@@ -144,7 +144,7 @@ test "complex.magnitude" {
144144 const a = Complex(f32).new(5, 3);
145145 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));
148148}
149149
150150test "complex.cmath" {
std/math/complex/log.zig+3-3
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -18,6 +18,6 @@ test "complex.clog" {
1818 const a = Complex(f32).new(5, 3);
1919 const c = log(a);
2020
21 debug.assert(math.approxEq(f32, c.re, 1.763180, epsilon));
22 debug.assert(math.approxEq(f32, c.im, 0.540419, epsilon));
21 testing.expect(math.approxEq(f32, c.re, 1.763180, epsilon));
22 testing.expect(math.approxEq(f32, c.im, 0.540419, epsilon));
2323}
std/math/complex/pow.zig+3-3
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -17,6 +17,6 @@ test "complex.cpow" {
1717 const b = Complex(f32).new(2.3, -1.3);
1818 const c = pow(Complex(f32), a, b);
1919
20 debug.assert(math.approxEq(f32, c.re, 58.049110, epsilon));
21 debug.assert(math.approxEq(f32, c.im, -101.003433, epsilon));
20 testing.expect(math.approxEq(f32, c.re, 58.049110, epsilon));
21 testing.expect(math.approxEq(f32, c.im, -101.003433, epsilon));
2222}
std/math/complex/proj.zig+2-2
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -20,5 +20,5 @@ test "complex.cproj" {
2020 const a = Complex(f32).new(5, 3);
2121 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);
2424}
std/math/complex/sin.zig+3-3
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -17,6 +17,6 @@ test "complex.csin" {
1717 const a = Complex(f32).new(5, 3);
1818 const c = sin(a);
1919
20 debug.assert(math.approxEq(f32, c.re, -9.654126, epsilon));
21 debug.assert(math.approxEq(f32, c.im, 2.841692, epsilon));
20 testing.expect(math.approxEq(f32, c.re, -9.654126, epsilon));
21 testing.expect(math.approxEq(f32, c.im, 2.841692, epsilon));
2222}
std/math/complex/sinh.zig+5-5
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -151,14 +151,14 @@ test "complex.csinh32" {
151151 const a = Complex(f32).new(5, 3);
152152 const c = sinh(a);
153153
154 debug.assert(math.approxEq(f32, c.re, -73.460617, epsilon));
155 debug.assert(math.approxEq(f32, c.im, 10.472508, epsilon));
154 testing.expect(math.approxEq(f32, c.re, -73.460617, epsilon));
155 testing.expect(math.approxEq(f32, c.im, 10.472508, epsilon));
156156}
157157
158158test "complex.csinh64" {
159159 const a = Complex(f64).new(5, 3);
160160 const c = sinh(a);
161161
162 debug.assert(math.approxEq(f64, c.re, -73.460617, epsilon));
163 debug.assert(math.approxEq(f64, c.im, 10.472508, epsilon));
162 testing.expect(math.approxEq(f64, c.re, -73.460617, epsilon));
163 testing.expect(math.approxEq(f64, c.im, 10.472508, epsilon));
164164}
std/math/complex/sqrt.zig+5-5
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -125,14 +125,14 @@ test "complex.csqrt32" {
125125 const a = Complex(f32).new(5, 3);
126126 const c = sqrt(a);
127127
128 debug.assert(math.approxEq(f32, c.re, 2.327117, epsilon));
129 debug.assert(math.approxEq(f32, c.im, 0.644574, epsilon));
128 testing.expect(math.approxEq(f32, c.re, 2.327117, epsilon));
129 testing.expect(math.approxEq(f32, c.im, 0.644574, epsilon));
130130}
131131
132132test "complex.csqrt64" {
133133 const a = Complex(f64).new(5, 3);
134134 const c = sqrt(a);
135135
136 debug.assert(math.approxEq(f64, c.re, 2.3271175190399496, epsilon));
137 debug.assert(math.approxEq(f64, c.im, 0.6445742373246469, epsilon));
136 testing.expect(math.approxEq(f64, c.re, 2.3271175190399496, epsilon));
137 testing.expect(math.approxEq(f64, c.im, 0.6445742373246469, epsilon));
138138}
std/math/complex/tan.zig+3-3
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -17,6 +17,6 @@ test "complex.ctan" {
1717 const a = Complex(f32).new(5, 3);
1818 const c = tan(a);
1919
20 debug.assert(math.approxEq(f32, c.re, -0.002708233, epsilon));
21 debug.assert(math.approxEq(f32, c.im, 1.004165, epsilon));
20 testing.expect(math.approxEq(f32, c.re, -0.002708233, epsilon));
21 testing.expect(math.approxEq(f32, c.im, 1.004165, epsilon));
2222}
std/math/complex/tanh.zig+5-5
......@@ -1,5 +1,5 @@
11const std = @import("../../index.zig");
2const debug = std.debug;
2const testing = std.testing;
33const math = std.math;
44const cmath = math.complex;
55const Complex = cmath.Complex;
......@@ -100,14 +100,14 @@ test "complex.ctanh32" {
100100 const a = Complex(f32).new(5, 3);
101101 const c = tanh(a);
102102
103 debug.assert(math.approxEq(f32, c.re, 0.999913, epsilon));
104 debug.assert(math.approxEq(f32, c.im, -0.000025, epsilon));
103 testing.expect(math.approxEq(f32, c.re, 0.999913, epsilon));
104 testing.expect(math.approxEq(f32, c.im, -0.000025, epsilon));
105105}
106106
107107test "complex.ctanh64" {
108108 const a = Complex(f64).new(5, 3);
109109 const c = tanh(a);
110110
111 debug.assert(math.approxEq(f64, c.re, 0.999913, epsilon));
112 debug.assert(math.approxEq(f64, c.im, -0.000025, epsilon));
111 testing.expect(math.approxEq(f64, c.re, 0.999913, epsilon));
112 testing.expect(math.approxEq(f64, c.im, -0.000025, epsilon));
113113}
std/math/copysign.zig+16-16
......@@ -1,6 +1,6 @@
11const std = @import("../index.zig");
22const math = std.math;
3const assert = std.debug.assert;
3const expect = std.testing.expect;
44const maxInt = std.math.maxInt;
55
66pub fn copysign(comptime T: type, x: T, y: T) T {
......@@ -40,28 +40,28 @@ fn copysign64(x: f64, y: f64) f64 {
4040}
4141
4242test "math.copysign" {
43 assert(copysign(f16, 1.0, 1.0) == copysign16(1.0, 1.0));
44 assert(copysign(f32, 1.0, 1.0) == copysign32(1.0, 1.0));
45 assert(copysign(f64, 1.0, 1.0) == copysign64(1.0, 1.0));
43 expect(copysign(f16, 1.0, 1.0) == copysign16(1.0, 1.0));
44 expect(copysign(f32, 1.0, 1.0) == copysign32(1.0, 1.0));
45 expect(copysign(f64, 1.0, 1.0) == copysign64(1.0, 1.0));
4646}
4747
4848test "math.copysign16" {
49 assert(copysign16(5.0, 1.0) == 5.0);
50 assert(copysign16(5.0, -1.0) == -5.0);
51 assert(copysign16(-5.0, -1.0) == -5.0);
52 assert(copysign16(-5.0, 1.0) == 5.0);
49 expect(copysign16(5.0, 1.0) == 5.0);
50 expect(copysign16(5.0, -1.0) == -5.0);
51 expect(copysign16(-5.0, -1.0) == -5.0);
52 expect(copysign16(-5.0, 1.0) == 5.0);
5353}
5454
5555test "math.copysign32" {
56 assert(copysign32(5.0, 1.0) == 5.0);
57 assert(copysign32(5.0, -1.0) == -5.0);
58 assert(copysign32(-5.0, -1.0) == -5.0);
59 assert(copysign32(-5.0, 1.0) == 5.0);
56 expect(copysign32(5.0, 1.0) == 5.0);
57 expect(copysign32(5.0, -1.0) == -5.0);
58 expect(copysign32(-5.0, -1.0) == -5.0);
59 expect(copysign32(-5.0, 1.0) == 5.0);
6060}
6161
6262test "math.copysign64" {
63 assert(copysign64(5.0, 1.0) == 5.0);
64 assert(copysign64(5.0, -1.0) == -5.0);
65 assert(copysign64(-5.0, -1.0) == -5.0);
66 assert(copysign64(-5.0, 1.0) == 5.0);
63 expect(copysign64(5.0, 1.0) == 5.0);
64 expect(copysign64(5.0, -1.0) == -5.0);
65 expect(copysign64(-5.0, -1.0) == -5.0);
66 expect(copysign64(-5.0, 1.0) == 5.0);
6767}
std/math/cos.zig+21-21
......@@ -6,7 +6,7 @@
66const builtin = @import("builtin");
77const std = @import("../index.zig");
88const math = std.math;
9const assert = std.debug.assert;
9const expect = std.testing.expect;
1010
1111pub fn cos(x: var) @typeOf(x) {
1212 const T = @typeOf(x);
......@@ -139,40 +139,40 @@ fn cos64(x_: f64) f64 {
139139}
140140
141141test "math.cos" {
142 assert(cos(f32(0.0)) == cos32(0.0));
143 assert(cos(f64(0.0)) == cos64(0.0));
142 expect(cos(f32(0.0)) == cos32(0.0));
143 expect(cos(f64(0.0)) == cos64(0.0));
144144}
145145
146146test "math.cos32" {
147147 const epsilon = 0.000001;
148148
149 assert(math.approxEq(f32, cos32(0.0), 1.0, epsilon));
150 assert(math.approxEq(f32, cos32(0.2), 0.980067, epsilon));
151 assert(math.approxEq(f32, cos32(0.8923), 0.627623, epsilon));
152 assert(math.approxEq(f32, cos32(1.5), 0.070737, epsilon));
153 assert(math.approxEq(f32, cos32(37.45), 0.969132, epsilon));
154 assert(math.approxEq(f32, cos32(89.123), 0.400798, epsilon));
149 expect(math.approxEq(f32, cos32(0.0), 1.0, epsilon));
150 expect(math.approxEq(f32, cos32(0.2), 0.980067, epsilon));
151 expect(math.approxEq(f32, cos32(0.8923), 0.627623, epsilon));
152 expect(math.approxEq(f32, cos32(1.5), 0.070737, epsilon));
153 expect(math.approxEq(f32, cos32(37.45), 0.969132, epsilon));
154 expect(math.approxEq(f32, cos32(89.123), 0.400798, epsilon));
155155}
156156
157157test "math.cos64" {
158158 const epsilon = 0.000001;
159159
160 assert(math.approxEq(f64, cos64(0.0), 1.0, epsilon));
161 assert(math.approxEq(f64, cos64(0.2), 0.980067, epsilon));
162 assert(math.approxEq(f64, cos64(0.8923), 0.627623, epsilon));
163 assert(math.approxEq(f64, cos64(1.5), 0.070737, epsilon));
164 assert(math.approxEq(f64, cos64(37.45), 0.969132, epsilon));
165 assert(math.approxEq(f64, cos64(89.123), 0.40080, epsilon));
160 expect(math.approxEq(f64, cos64(0.0), 1.0, epsilon));
161 expect(math.approxEq(f64, cos64(0.2), 0.980067, epsilon));
162 expect(math.approxEq(f64, cos64(0.8923), 0.627623, epsilon));
163 expect(math.approxEq(f64, cos64(1.5), 0.070737, epsilon));
164 expect(math.approxEq(f64, cos64(37.45), 0.969132, epsilon));
165 expect(math.approxEq(f64, cos64(89.123), 0.40080, epsilon));
166166}
167167
168168test "math.cos32.special" {
169 assert(math.isNan(cos32(math.inf(f32))));
170 assert(math.isNan(cos32(-math.inf(f32))));
171 assert(math.isNan(cos32(math.nan(f32))));
169 expect(math.isNan(cos32(math.inf(f32))));
170 expect(math.isNan(cos32(-math.inf(f32))));
171 expect(math.isNan(cos32(math.nan(f32))));
172172}
173173
174174test "math.cos64.special" {
175 assert(math.isNan(cos64(math.inf(f64))));
176 assert(math.isNan(cos64(-math.inf(f64))));
177 assert(math.isNan(cos64(math.nan(f64))));
175 expect(math.isNan(cos64(math.inf(f64))));
176 expect(math.isNan(cos64(-math.inf(f64))));
177 expect(math.isNan(cos64(math.nan(f64))));
178178}
std/math/cosh.zig+21-21
......@@ -8,7 +8,7 @@ const builtin = @import("builtin");
88const std = @import("../index.zig");
99const math = std.math;
1010const expo2 = @import("expo2.zig").expo2;
11const assert = std.debug.assert;
11const expect = std.testing.expect;
1212const maxInt = std.math.maxInt;
1313
1414pub fn cosh(x: var) @typeOf(x) {
......@@ -82,40 +82,40 @@ fn cosh64(x: f64) f64 {
8282}
8383
8484test "math.cosh" {
85 assert(cosh(f32(1.5)) == cosh32(1.5));
86 assert(cosh(f64(1.5)) == cosh64(1.5));
85 expect(cosh(f32(1.5)) == cosh32(1.5));
86 expect(cosh(f64(1.5)) == cosh64(1.5));
8787}
8888
8989test "math.cosh32" {
9090 const epsilon = 0.000001;
9191
92 assert(math.approxEq(f32, cosh32(0.0), 1.0, epsilon));
93 assert(math.approxEq(f32, cosh32(0.2), 1.020067, epsilon));
94 assert(math.approxEq(f32, cosh32(0.8923), 1.425225, epsilon));
95 assert(math.approxEq(f32, cosh32(1.5), 2.352410, epsilon));
92 expect(math.approxEq(f32, cosh32(0.0), 1.0, epsilon));
93 expect(math.approxEq(f32, cosh32(0.2), 1.020067, epsilon));
94 expect(math.approxEq(f32, cosh32(0.8923), 1.425225, epsilon));
95 expect(math.approxEq(f32, cosh32(1.5), 2.352410, epsilon));
9696}
9797
9898test "math.cosh64" {
9999 const epsilon = 0.000001;
100100
101 assert(math.approxEq(f64, cosh64(0.0), 1.0, epsilon));
102 assert(math.approxEq(f64, cosh64(0.2), 1.020067, epsilon));
103 assert(math.approxEq(f64, cosh64(0.8923), 1.425225, epsilon));
104 assert(math.approxEq(f64, cosh64(1.5), 2.352410, epsilon));
101 expect(math.approxEq(f64, cosh64(0.0), 1.0, epsilon));
102 expect(math.approxEq(f64, cosh64(0.2), 1.020067, epsilon));
103 expect(math.approxEq(f64, cosh64(0.8923), 1.425225, epsilon));
104 expect(math.approxEq(f64, cosh64(1.5), 2.352410, epsilon));
105105}
106106
107107test "math.cosh32.special" {
108 assert(cosh32(0.0) == 1.0);
109 assert(cosh32(-0.0) == 1.0);
110 assert(math.isPositiveInf(cosh32(math.inf(f32))));
111 assert(math.isPositiveInf(cosh32(-math.inf(f32))));
112 assert(math.isNan(cosh32(math.nan(f32))));
108 expect(cosh32(0.0) == 1.0);
109 expect(cosh32(-0.0) == 1.0);
110 expect(math.isPositiveInf(cosh32(math.inf(f32))));
111 expect(math.isPositiveInf(cosh32(-math.inf(f32))));
112 expect(math.isNan(cosh32(math.nan(f32))));
113113}
114114
115115test "math.cosh64.special" {
116 assert(cosh64(0.0) == 1.0);
117 assert(cosh64(-0.0) == 1.0);
118 assert(math.isPositiveInf(cosh64(math.inf(f64))));
119 assert(math.isPositiveInf(cosh64(-math.inf(f64))));
120 assert(math.isNan(cosh64(math.nan(f64))));
116 expect(cosh64(0.0) == 1.0);
117 expect(cosh64(-0.0) == 1.0);
118 expect(math.isPositiveInf(cosh64(math.inf(f64))));
119 expect(math.isPositiveInf(cosh64(-math.inf(f64))));
120 expect(math.isNan(cosh64(math.nan(f64))));
121121}
std/math/exp2.zig+16-16
......@@ -5,7 +5,7 @@
55
66const std = @import("../index.zig");
77const math = std.math;
8const assert = std.debug.assert;
8const expect = std.testing.expect;
99
1010pub fn exp2(x: var) @typeOf(x) {
1111 const T = @typeOf(x);
......@@ -415,35 +415,35 @@ fn exp2_64(x: f64) f64 {
415415}
416416
417417test "math.exp2" {
418 assert(exp2(f32(0.8923)) == exp2_32(0.8923));
419 assert(exp2(f64(0.8923)) == exp2_64(0.8923));
418 expect(exp2(f32(0.8923)) == exp2_32(0.8923));
419 expect(exp2(f64(0.8923)) == exp2_64(0.8923));
420420}
421421
422422test "math.exp2_32" {
423423 const epsilon = 0.000001;
424424
425 assert(exp2_32(0.0) == 1.0);
426 assert(math.approxEq(f32, exp2_32(0.2), 1.148698, epsilon));
427 assert(math.approxEq(f32, exp2_32(0.8923), 1.856133, epsilon));
428 assert(math.approxEq(f32, exp2_32(1.5), 2.828427, epsilon));
429 assert(math.approxEq(f32, exp2_32(37.45), 187747237888, epsilon));
425 expect(exp2_32(0.0) == 1.0);
426 expect(math.approxEq(f32, exp2_32(0.2), 1.148698, epsilon));
427 expect(math.approxEq(f32, exp2_32(0.8923), 1.856133, epsilon));
428 expect(math.approxEq(f32, exp2_32(1.5), 2.828427, epsilon));
429 expect(math.approxEq(f32, exp2_32(37.45), 187747237888, epsilon));
430430}
431431
432432test "math.exp2_64" {
433433 const epsilon = 0.000001;
434434
435 assert(exp2_64(0.0) == 1.0);
436 assert(math.approxEq(f64, exp2_64(0.2), 1.148698, epsilon));
437 assert(math.approxEq(f64, exp2_64(0.8923), 1.856133, epsilon));
438 assert(math.approxEq(f64, exp2_64(1.5), 2.828427, epsilon));
435 expect(exp2_64(0.0) == 1.0);
436 expect(math.approxEq(f64, exp2_64(0.2), 1.148698, epsilon));
437 expect(math.approxEq(f64, exp2_64(0.8923), 1.856133, epsilon));
438 expect(math.approxEq(f64, exp2_64(1.5), 2.828427, epsilon));
439439}
440440
441441test "math.exp2_32.special" {
442 assert(math.isPositiveInf(exp2_32(math.inf(f32))));
443 assert(math.isNan(exp2_32(math.nan(f32))));
442 expect(math.isPositiveInf(exp2_32(math.inf(f32))));
443 expect(math.isNan(exp2_32(math.nan(f32))));
444444}
445445
446446test "math.exp2_64.special" {
447 assert(math.isPositiveInf(exp2_64(math.inf(f64))));
448 assert(math.isNan(exp2_64(math.nan(f64))));
447 expect(math.isPositiveInf(exp2_64(math.inf(f64))));
448 expect(math.isNan(exp2_64(math.nan(f64))));
449449}
std/math/expm1.zig+19-19
......@@ -7,7 +7,7 @@
77const builtin = @import("builtin");
88const std = @import("../index.zig");
99const math = std.math;
10const assert = std.debug.assert;
10const expect = std.testing.expect;
1111
1212pub fn expm1(x: var) @typeOf(x) {
1313 const T = @typeOf(x);
......@@ -278,42 +278,42 @@ fn expm1_64(x_: f64) f64 {
278278}
279279
280280test "math.exp1m" {
281 assert(expm1(f32(0.0)) == expm1_32(0.0));
282 assert(expm1(f64(0.0)) == expm1_64(0.0));
281 expect(expm1(f32(0.0)) == expm1_32(0.0));
282 expect(expm1(f64(0.0)) == expm1_64(0.0));
283283}
284284
285285test "math.expm1_32" {
286286 const epsilon = 0.000001;
287287
288 assert(expm1_32(0.0) == 0.0);
289 assert(math.approxEq(f32, expm1_32(0.0), 0.0, epsilon));
290 assert(math.approxEq(f32, expm1_32(0.2), 0.221403, epsilon));
291 assert(math.approxEq(f32, expm1_32(0.8923), 1.440737, epsilon));
292 assert(math.approxEq(f32, expm1_32(1.5), 3.481689, epsilon));
288 expect(expm1_32(0.0) == 0.0);
289 expect(math.approxEq(f32, expm1_32(0.0), 0.0, epsilon));
290 expect(math.approxEq(f32, expm1_32(0.2), 0.221403, epsilon));
291 expect(math.approxEq(f32, expm1_32(0.8923), 1.440737, epsilon));
292 expect(math.approxEq(f32, expm1_32(1.5), 3.481689, epsilon));
293293}
294294
295295test "math.expm1_64" {
296296 const epsilon = 0.000001;
297297
298 assert(expm1_64(0.0) == 0.0);
299 assert(math.approxEq(f64, expm1_64(0.0), 0.0, epsilon));
300 assert(math.approxEq(f64, expm1_64(0.2), 0.221403, epsilon));
301 assert(math.approxEq(f64, expm1_64(0.8923), 1.440737, epsilon));
302 assert(math.approxEq(f64, expm1_64(1.5), 3.481689, epsilon));
298 expect(expm1_64(0.0) == 0.0);
299 expect(math.approxEq(f64, expm1_64(0.0), 0.0, epsilon));
300 expect(math.approxEq(f64, expm1_64(0.2), 0.221403, epsilon));
301 expect(math.approxEq(f64, expm1_64(0.8923), 1.440737, epsilon));
302 expect(math.approxEq(f64, expm1_64(1.5), 3.481689, epsilon));
303303}
304304
305305test "math.expm1_32.special" {
306306 const epsilon = 0.000001;
307307
308 assert(math.isPositiveInf(expm1_32(math.inf(f32))));
309 assert(expm1_32(-math.inf(f32)) == -1.0);
310 assert(math.isNan(expm1_32(math.nan(f32))));
308 expect(math.isPositiveInf(expm1_32(math.inf(f32))));
309 expect(expm1_32(-math.inf(f32)) == -1.0);
310 expect(math.isNan(expm1_32(math.nan(f32))));
311311}
312312
313313test "math.expm1_64.special" {
314314 const epsilon = 0.000001;
315315
316 assert(math.isPositiveInf(expm1_64(math.inf(f64))));
317 assert(expm1_64(-math.inf(f64)) == -1.0);
318 assert(math.isNan(expm1_64(math.nan(f64))));
316 expect(math.isPositiveInf(expm1_64(math.inf(f64))));
317 expect(expm1_64(-math.inf(f64)) == -1.0);
318 expect(math.isNan(expm1_64(math.nan(f64))));
319319}
std/math/fabs.zig+38-19
......@@ -5,7 +5,7 @@
55
66const std = @import("../index.zig");
77const math = std.math;
8const assert = std.debug.assert;
8const expect = std.testing.expect;
99const maxInt = std.math.maxInt;
1010
1111pub fn fabs(x: var) @typeOf(x) {
......@@ -14,6 +14,7 @@ pub fn fabs(x: var) @typeOf(x) {
1414 f16 => fabs16(x),
1515 f32 => fabs32(x),
1616 f64 => fabs64(x),
17 f128 => fabs128(x),
1718 else => @compileError("fabs not implemented for " ++ @typeName(T)),
1819 };
1920}
......@@ -36,41 +37,59 @@ fn fabs64(x: f64) f64 {
3637 return @bitCast(f64, u);
3738}
3839
40fn fabs128(x: f128) f128 {
41 var u = @bitCast(u128, x);
42 u &= maxInt(u128) >> 1;
43 return @bitCast(f128, u);
44}
45
3946test "math.fabs" {
40 assert(fabs(f16(1.0)) == fabs16(1.0));
41 assert(fabs(f32(1.0)) == fabs32(1.0));
42 assert(fabs(f64(1.0)) == fabs64(1.0));
47 expect(fabs(f16(1.0)) == fabs16(1.0));
48 expect(fabs(f32(1.0)) == fabs32(1.0));
49 expect(fabs(f64(1.0)) == fabs64(1.0));
50 expect(fabs(f128(1.0)) == fabs128(1.0));
4351}
4452
4553test "math.fabs16" {
46 assert(fabs16(1.0) == 1.0);
47 assert(fabs16(-1.0) == 1.0);
54 expect(fabs16(1.0) == 1.0);
55 expect(fabs16(-1.0) == 1.0);
4856}
4957
5058test "math.fabs32" {
51 assert(fabs32(1.0) == 1.0);
52 assert(fabs32(-1.0) == 1.0);
59 expect(fabs32(1.0) == 1.0);
60 expect(fabs32(-1.0) == 1.0);
5361}
5462
5563test "math.fabs64" {
56 assert(fabs64(1.0) == 1.0);
57 assert(fabs64(-1.0) == 1.0);
64 expect(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);
5871}
5972
6073test "math.fabs16.special" {
61 assert(math.isPositiveInf(fabs(math.inf(f16))));
62 assert(math.isPositiveInf(fabs(-math.inf(f16))));
63 assert(math.isNan(fabs(math.nan(f16))));
74 expect(math.isPositiveInf(fabs(math.inf(f16))));
75 expect(math.isPositiveInf(fabs(-math.inf(f16))));
76 expect(math.isNan(fabs(math.nan(f16))));
6477}
6578
6679test "math.fabs32.special" {
67 assert(math.isPositiveInf(fabs(math.inf(f32))));
68 assert(math.isPositiveInf(fabs(-math.inf(f32))));
69 assert(math.isNan(fabs(math.nan(f32))));
80 expect(math.isPositiveInf(fabs(math.inf(f32))));
81 expect(math.isPositiveInf(fabs(-math.inf(f32))));
82 expect(math.isNan(fabs(math.nan(f32))));
7083}
7184
7285test "math.fabs64.special" {
73 assert(math.isPositiveInf(fabs(math.inf(f64))));
74 assert(math.isPositiveInf(fabs(-math.inf(f64))));
75 assert(math.isNan(fabs(math.nan(f64))));
86 expect(math.isPositiveInf(fabs(math.inf(f64))));
87 expect(math.isPositiveInf(fabs(-math.inf(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))));
7695}
std/math/floor.zig+28-28
......@@ -5,7 +5,7 @@
55// - floor(nan) = nan
66
77const builtin = @import("builtin");
8const assert = std.debug.assert;
8const expect = std.testing.expect;
99const std = @import("../index.zig");
1010const math = std.math;
1111
......@@ -117,49 +117,49 @@ fn floor64(x: f64) f64 {
117117}
118118
119119test "math.floor" {
120 assert(floor(f16(1.3)) == floor16(1.3));
121 assert(floor(f32(1.3)) == floor32(1.3));
122 assert(floor(f64(1.3)) == floor64(1.3));
120 expect(floor(f16(1.3)) == floor16(1.3));
121 expect(floor(f32(1.3)) == floor32(1.3));
122 expect(floor(f64(1.3)) == floor64(1.3));
123123}
124124
125125test "math.floor16" {
126 assert(floor16(1.3) == 1.0);
127 assert(floor16(-1.3) == -2.0);
128 assert(floor16(0.2) == 0.0);
126 expect(floor16(1.3) == 1.0);
127 expect(floor16(-1.3) == -2.0);
128 expect(floor16(0.2) == 0.0);
129129}
130130
131131test "math.floor32" {
132 assert(floor32(1.3) == 1.0);
133 assert(floor32(-1.3) == -2.0);
134 assert(floor32(0.2) == 0.0);
132 expect(floor32(1.3) == 1.0);
133 expect(floor32(-1.3) == -2.0);
134 expect(floor32(0.2) == 0.0);
135135}
136136
137137test "math.floor64" {
138 assert(floor64(1.3) == 1.0);
139 assert(floor64(-1.3) == -2.0);
140 assert(floor64(0.2) == 0.0);
138 expect(floor64(1.3) == 1.0);
139 expect(floor64(-1.3) == -2.0);
140 expect(floor64(0.2) == 0.0);
141141}
142142
143143test "math.floor16.special" {
144 assert(floor16(0.0) == 0.0);
145 assert(floor16(-0.0) == -0.0);
146 assert(math.isPositiveInf(floor16(math.inf(f16))));
147 assert(math.isNegativeInf(floor16(-math.inf(f16))));
148 assert(math.isNan(floor16(math.nan(f16))));
144 expect(floor16(0.0) == 0.0);
145 expect(floor16(-0.0) == -0.0);
146 expect(math.isPositiveInf(floor16(math.inf(f16))));
147 expect(math.isNegativeInf(floor16(-math.inf(f16))));
148 expect(math.isNan(floor16(math.nan(f16))));
149149}
150150
151151test "math.floor32.special" {
152 assert(floor32(0.0) == 0.0);
153 assert(floor32(-0.0) == -0.0);
154 assert(math.isPositiveInf(floor32(math.inf(f32))));
155 assert(math.isNegativeInf(floor32(-math.inf(f32))));
156 assert(math.isNan(floor32(math.nan(f32))));
152 expect(floor32(0.0) == 0.0);
153 expect(floor32(-0.0) == -0.0);
154 expect(math.isPositiveInf(floor32(math.inf(f32))));
155 expect(math.isNegativeInf(floor32(-math.inf(f32))));
156 expect(math.isNan(floor32(math.nan(f32))));
157157}
158158
159159test "math.floor64.special" {
160 assert(floor64(0.0) == 0.0);
161 assert(floor64(-0.0) == -0.0);
162 assert(math.isPositiveInf(floor64(math.inf(f64))));
163 assert(math.isNegativeInf(floor64(-math.inf(f64))));
164 assert(math.isNan(floor64(math.nan(f64))));
160 expect(floor64(0.0) == 0.0);
161 expect(floor64(-0.0) == -0.0);
162 expect(math.isPositiveInf(floor64(math.inf(f64))));
163 expect(math.isNegativeInf(floor64(-math.inf(f64))));
164 expect(math.isNan(floor64(math.nan(f64))));
165165}
std/math/fma.zig+17-17
......@@ -1,6 +1,6 @@
11const std = @import("../index.zig");
22const math = std.math;
3const assert = std.debug.assert;
3const expect = std.testing.expect;
44
55pub fn fma(comptime T: type, x: T, y: T, z: T) T {
66 return switch (T) {
......@@ -135,30 +135,30 @@ fn add_and_denorm(a: f64, b: f64, scale: i32) f64 {
135135}
136136
137137test "math.fma" {
138 assert(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));
138 expect(fma(f32, 0.0, 1.0, 1.0) == fma32(0.0, 1.0, 1.0));
139 expect(fma(f64, 0.0, 1.0, 1.0) == fma64(0.0, 1.0, 1.0));
140140}
141141
142142test "math.fma32" {
143143 const epsilon = 0.000001;
144144
145 assert(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));
147 assert(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));
149 assert(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));
151 assert(math.approxEq(f32, fma32(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
145 expect(math.approxEq(f32, fma32(0.0, 5.0, 9.124), 9.124, epsilon));
146 expect(math.approxEq(f32, fma32(0.2, 5.0, 9.124), 10.124, epsilon));
147 expect(math.approxEq(f32, fma32(0.8923, 5.0, 9.124), 13.5855, epsilon));
148 expect(math.approxEq(f32, fma32(1.5, 5.0, 9.124), 16.624, epsilon));
149 expect(math.approxEq(f32, fma32(37.45, 5.0, 9.124), 196.374004, epsilon));
150 expect(math.approxEq(f32, fma32(89.123, 5.0, 9.124), 454.739005, epsilon));
151 expect(math.approxEq(f32, fma32(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
152152}
153153
154154test "math.fma64" {
155155 const epsilon = 0.000001;
156156
157 assert(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));
159 assert(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));
161 assert(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));
163 assert(math.approxEq(f64, fma64(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
157 expect(math.approxEq(f64, fma64(0.0, 5.0, 9.124), 9.124, epsilon));
158 expect(math.approxEq(f64, fma64(0.2, 5.0, 9.124), 10.124, epsilon));
159 expect(math.approxEq(f64, fma64(0.8923, 5.0, 9.124), 13.5855, epsilon));
160 expect(math.approxEq(f64, fma64(1.5, 5.0, 9.124), 16.624, epsilon));
161 expect(math.approxEq(f64, fma64(37.45, 5.0, 9.124), 196.374, epsilon));
162 expect(math.approxEq(f64, fma64(89.123, 5.0, 9.124), 454.739, epsilon));
163 expect(math.approxEq(f64, fma64(123123.234375, 5.0, 9.124), 615625.295875, epsilon));
164164}
std/math/frexp.zig+17-17
......@@ -6,7 +6,7 @@
66
77const std = @import("../index.zig");
88const math = std.math;
9const assert = std.debug.assert;
9const expect = std.testing.expect;
1010
1111fn frexp_result(comptime T: type) type {
1212 return struct {
......@@ -103,11 +103,11 @@ fn frexp64(x: f64) frexp64_result {
103103test "math.frexp" {
104104 const a = frexp(f32(1.3));
105105 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
108108 const c = frexp(f64(1.3));
109109 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);
111111}
112112
113113test "math.frexp32" {
......@@ -115,10 +115,10 @@ test "math.frexp32" {
115115 var r: frexp32_result = undefined;
116116
117117 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
120120 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);
122122}
123123
124124test "math.frexp64" {
......@@ -126,46 +126,46 @@ test "math.frexp64" {
126126 var r: frexp64_result = undefined;
127127
128128 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
131131 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);
133133}
134134
135135test "math.frexp32.special" {
136136 var r: frexp32_result = undefined;
137137
138138 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
141141 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
144144 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
147147 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
150150 r = frexp32(math.nan(f32));
151 assert(math.isNan(r.significand));
151 expect(math.isNan(r.significand));
152152}
153153
154154test "math.frexp64.special" {
155155 var r: frexp64_result = undefined;
156156
157157 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
160160 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
163163 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
166166 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
169169 r = frexp64(math.nan(f64));
170 assert(math.isNan(r.significand));
170 expect(math.isNan(r.significand));
171171}
std/math/hypot.zig+29-29
......@@ -7,7 +7,7 @@
77
88const std = @import("../index.zig");
99const math = std.math;
10const assert = std.debug.assert;
10const expect = std.testing.expect;
1111const maxInt = std.math.maxInt;
1212
1313pub fn hypot(comptime T: type, x: T, y: T) T {
......@@ -115,48 +115,48 @@ fn hypot64(x: f64, y: f64) f64 {
115115}
116116
117117test "math.hypot" {
118 assert(hypot(f32, 0.0, -1.2) == hypot32(0.0, -1.2));
119 assert(hypot(f64, 0.0, -1.2) == hypot64(0.0, -1.2));
118 expect(hypot(f32, 0.0, -1.2) == hypot32(0.0, -1.2));
119 expect(hypot(f64, 0.0, -1.2) == hypot64(0.0, -1.2));
120120}
121121
122122test "math.hypot32" {
123123 const epsilon = 0.000001;
124124
125 assert(math.approxEq(f32, hypot32(0.0, -1.2), 1.2, epsilon));
126 assert(math.approxEq(f32, hypot32(0.2, -0.34), 0.394462, epsilon));
127 assert(math.approxEq(f32, hypot32(0.8923, 2.636890), 2.783772, epsilon));
128 assert(math.approxEq(f32, hypot32(1.5, 5.25), 5.460083, epsilon));
129 assert(math.approxEq(f32, hypot32(37.45, 159.835), 164.163742, epsilon));
130 assert(math.approxEq(f32, hypot32(89.123, 382.028905), 392.286865, epsilon));
131 assert(math.approxEq(f32, hypot32(123123.234375, 529428.707813), 543556.875, epsilon));
125 expect(math.approxEq(f32, hypot32(0.0, -1.2), 1.2, epsilon));
126 expect(math.approxEq(f32, hypot32(0.2, -0.34), 0.394462, epsilon));
127 expect(math.approxEq(f32, hypot32(0.8923, 2.636890), 2.783772, epsilon));
128 expect(math.approxEq(f32, hypot32(1.5, 5.25), 5.460083, epsilon));
129 expect(math.approxEq(f32, hypot32(37.45, 159.835), 164.163742, epsilon));
130 expect(math.approxEq(f32, hypot32(89.123, 382.028905), 392.286865, epsilon));
131 expect(math.approxEq(f32, hypot32(123123.234375, 529428.707813), 543556.875, epsilon));
132132}
133133
134134test "math.hypot64" {
135135 const epsilon = 0.000001;
136136
137 assert(math.approxEq(f64, hypot64(0.0, -1.2), 1.2, epsilon));
138 assert(math.approxEq(f64, hypot64(0.2, -0.34), 0.394462, epsilon));
139 assert(math.approxEq(f64, hypot64(0.8923, 2.636890), 2.783772, epsilon));
140 assert(math.approxEq(f64, hypot64(1.5, 5.25), 5.460082, epsilon));
141 assert(math.approxEq(f64, hypot64(37.45, 159.835), 164.163728, epsilon));
142 assert(math.approxEq(f64, hypot64(89.123, 382.028905), 392.286876, epsilon));
143 assert(math.approxEq(f64, hypot64(123123.234375, 529428.707813), 543556.885247, epsilon));
137 expect(math.approxEq(f64, hypot64(0.0, -1.2), 1.2, epsilon));
138 expect(math.approxEq(f64, hypot64(0.2, -0.34), 0.394462, epsilon));
139 expect(math.approxEq(f64, hypot64(0.8923, 2.636890), 2.783772, epsilon));
140 expect(math.approxEq(f64, hypot64(1.5, 5.25), 5.460082, epsilon));
141 expect(math.approxEq(f64, hypot64(37.45, 159.835), 164.163728, epsilon));
142 expect(math.approxEq(f64, hypot64(89.123, 382.028905), 392.286876, epsilon));
143 expect(math.approxEq(f64, hypot64(123123.234375, 529428.707813), 543556.885247, epsilon));
144144}
145145
146146test "math.hypot32.special" {
147 assert(math.isPositiveInf(hypot32(math.inf(f32), 0.0)));
148 assert(math.isPositiveInf(hypot32(-math.inf(f32), 0.0)));
149 assert(math.isPositiveInf(hypot32(0.0, math.inf(f32))));
150 assert(math.isPositiveInf(hypot32(0.0, -math.inf(f32))));
151 assert(math.isNan(hypot32(math.nan(f32), 0.0)));
152 assert(math.isNan(hypot32(0.0, math.nan(f32))));
147 expect(math.isPositiveInf(hypot32(math.inf(f32), 0.0)));
148 expect(math.isPositiveInf(hypot32(-math.inf(f32), 0.0)));
149 expect(math.isPositiveInf(hypot32(0.0, math.inf(f32))));
150 expect(math.isPositiveInf(hypot32(0.0, -math.inf(f32))));
151 expect(math.isNan(hypot32(math.nan(f32), 0.0)));
152 expect(math.isNan(hypot32(0.0, math.nan(f32))));
153153}
154154
155155test "math.hypot64.special" {
156 assert(math.isPositiveInf(hypot64(math.inf(f64), 0.0)));
157 assert(math.isPositiveInf(hypot64(-math.inf(f64), 0.0)));
158 assert(math.isPositiveInf(hypot64(0.0, math.inf(f64))));
159 assert(math.isPositiveInf(hypot64(0.0, -math.inf(f64))));
160 assert(math.isNan(hypot64(math.nan(f64), 0.0)));
161 assert(math.isNan(hypot64(0.0, math.nan(f64))));
156 expect(math.isPositiveInf(hypot64(math.inf(f64), 0.0)));
157 expect(math.isPositiveInf(hypot64(-math.inf(f64), 0.0)));
158 expect(math.isPositiveInf(hypot64(0.0, math.inf(f64))));
159 expect(math.isPositiveInf(hypot64(0.0, -math.inf(f64))));
160 expect(math.isNan(hypot64(math.nan(f64), 0.0)));
161 expect(math.isNan(hypot64(0.0, math.nan(f64))));
162162}
std/math/ilogb.zig+23-23
......@@ -6,7 +6,7 @@
66
77const std = @import("../index.zig");
88const math = std.math;
9const assert = std.debug.assert;
9const expect = std.testing.expect;
1010const maxInt = std.math.maxInt;
1111const minInt = std.math.minInt;
1212
......@@ -95,38 +95,38 @@ fn ilogb64(x: f64) i32 {
9595}
9696
9797test "math.ilogb" {
98 assert(ilogb(f32(0.2)) == ilogb32(0.2));
99 assert(ilogb(f64(0.2)) == ilogb64(0.2));
98 expect(ilogb(f32(0.2)) == ilogb32(0.2));
99 expect(ilogb(f64(0.2)) == ilogb64(0.2));
100100}
101101
102102test "math.ilogb32" {
103 assert(ilogb32(0.0) == fp_ilogb0);
104 assert(ilogb32(0.5) == -1);
105 assert(ilogb32(0.8923) == -1);
106 assert(ilogb32(10.0) == 3);
107 assert(ilogb32(-123984) == 16);
108 assert(ilogb32(2398.23) == 11);
103 expect(ilogb32(0.0) == fp_ilogb0);
104 expect(ilogb32(0.5) == -1);
105 expect(ilogb32(0.8923) == -1);
106 expect(ilogb32(10.0) == 3);
107 expect(ilogb32(-123984) == 16);
108 expect(ilogb32(2398.23) == 11);
109109}
110110
111111test "math.ilogb64" {
112 assert(ilogb64(0.0) == fp_ilogb0);
113 assert(ilogb64(0.5) == -1);
114 assert(ilogb64(0.8923) == -1);
115 assert(ilogb64(10.0) == 3);
116 assert(ilogb64(-123984) == 16);
117 assert(ilogb64(2398.23) == 11);
112 expect(ilogb64(0.0) == fp_ilogb0);
113 expect(ilogb64(0.5) == -1);
114 expect(ilogb64(0.8923) == -1);
115 expect(ilogb64(10.0) == 3);
116 expect(ilogb64(-123984) == 16);
117 expect(ilogb64(2398.23) == 11);
118118}
119119
120120test "math.ilogb32.special" {
121 assert(ilogb32(math.inf(f32)) == maxInt(i32));
122 assert(ilogb32(-math.inf(f32)) == maxInt(i32));
123 assert(ilogb32(0.0) == minInt(i32));
124 assert(ilogb32(math.nan(f32)) == maxInt(i32));
121 expect(ilogb32(math.inf(f32)) == maxInt(i32));
122 expect(ilogb32(-math.inf(f32)) == maxInt(i32));
123 expect(ilogb32(0.0) == minInt(i32));
124 expect(ilogb32(math.nan(f32)) == maxInt(i32));
125125}
126126
127127test "math.ilogb64.special" {
128 assert(ilogb64(math.inf(f64)) == maxInt(i32));
129 assert(ilogb64(-math.inf(f64)) == maxInt(i32));
130 assert(ilogb64(0.0) == minInt(i32));
131 assert(ilogb64(math.nan(f64)) == maxInt(i32));
128 expect(ilogb64(math.inf(f64)) == maxInt(i32));
129 expect(ilogb64(-math.inf(f64)) == maxInt(i32));
130 expect(ilogb64(0.0) == minInt(i32));
131 expect(ilogb64(math.nan(f64)) == maxInt(i32));
132132}
std/math/index.zig+190-172
......@@ -2,10 +2,18 @@ const builtin = @import("builtin");
22const std = @import("../index.zig");
33const TypeId = builtin.TypeId;
44const assert = std.debug.assert;
5const testing = std.testing;
56
67pub const e = 2.71828182845904523536028747135266249775724709369995;
78pub 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
917// float.h details
1018pub const f64_true_min = 4.94065645841246544177e-324;
1119pub const f64_min = 2.2250738585072014e-308;
......@@ -43,6 +51,12 @@ pub const nan_f64 = @bitCast(f64, nan_u64);
4351pub const inf_u64 = u64(0x7FF << 52);
4452pub 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
4660pub const nan = @import("nan.zig").nan;
4761pub const snan = @import("nan.zig").snan;
4862pub const inf = @import("inf.zig").inf;
......@@ -233,7 +247,7 @@ pub fn min(x: var, y: var) @typeOf(x + y) {
233247}
234248
235249test "math.min" {
236 assert(min(i32(-1), i32(2)) == -1);
250 testing.expect(min(i32(-1), i32(2)) == -1);
237251}
238252
239253pub fn max(x: var, y: var) @typeOf(x + y) {
......@@ -241,7 +255,7 @@ pub fn max(x: var, y: var) @typeOf(x + y) {
241255}
242256
243257test "math.max" {
244 assert(max(i32(-1), i32(2)) == 2);
258 testing.expect(max(i32(-1), i32(2)) == 2);
245259}
246260
247261pub 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 {
286300}
287301
288302test "math.shl" {
289 assert(shl(u8, 0b11111111, usize(3)) == 0b11111000);
290 assert(shl(u8, 0b11111111, usize(8)) == 0);
291 assert(shl(u8, 0b11111111, usize(9)) == 0);
292 assert(shl(u8, 0b11111111, isize(-2)) == 0b00111111);
303 testing.expect(shl(u8, 0b11111111, usize(3)) == 0b11111000);
304 testing.expect(shl(u8, 0b11111111, usize(8)) == 0);
305 testing.expect(shl(u8, 0b11111111, usize(9)) == 0);
306 testing.expect(shl(u8, 0b11111111, isize(-2)) == 0b00111111);
293307}
294308
295309/// Shifts right. Overflowed bits are truncated.
......@@ -310,10 +324,10 @@ pub fn shr(comptime T: type, a: T, shift_amt: var) T {
310324}
311325
312326test "math.shr" {
313 assert(shr(u8, 0b11111111, usize(3)) == 0b00011111);
314 assert(shr(u8, 0b11111111, usize(8)) == 0);
315 assert(shr(u8, 0b11111111, usize(9)) == 0);
316 assert(shr(u8, 0b11111111, isize(-2)) == 0b11111100);
327 testing.expect(shr(u8, 0b11111111, usize(3)) == 0b00011111);
328 testing.expect(shr(u8, 0b11111111, usize(8)) == 0);
329 testing.expect(shr(u8, 0b11111111, usize(9)) == 0);
330 testing.expect(shr(u8, 0b11111111, isize(-2)) == 0b11111100);
317331}
318332
319333/// Rotates right. Only unsigned values can be rotated.
......@@ -328,11 +342,11 @@ pub fn rotr(comptime T: type, x: T, r: var) T {
328342}
329343
330344test "math.rotr" {
331 assert(rotr(u8, 0b00000001, usize(0)) == 0b00000001);
332 assert(rotr(u8, 0b00000001, usize(9)) == 0b10000000);
333 assert(rotr(u8, 0b00000001, usize(8)) == 0b00000001);
334 assert(rotr(u8, 0b00000001, usize(4)) == 0b00010000);
335 assert(rotr(u8, 0b00000001, isize(-1)) == 0b00000010);
345 testing.expect(rotr(u8, 0b00000001, usize(0)) == 0b00000001);
346 testing.expect(rotr(u8, 0b00000001, usize(9)) == 0b10000000);
347 testing.expect(rotr(u8, 0b00000001, usize(8)) == 0b00000001);
348 testing.expect(rotr(u8, 0b00000001, usize(4)) == 0b00010000);
349 testing.expect(rotr(u8, 0b00000001, isize(-1)) == 0b00000010);
336350}
337351
338352/// Rotates left. Only unsigned values can be rotated.
......@@ -347,11 +361,11 @@ pub fn rotl(comptime T: type, x: T, r: var) T {
347361}
348362
349363test "math.rotl" {
350 assert(rotl(u8, 0b00000001, usize(0)) == 0b00000001);
351 assert(rotl(u8, 0b00000001, usize(9)) == 0b00000010);
352 assert(rotl(u8, 0b00000001, usize(8)) == 0b00000001);
353 assert(rotl(u8, 0b00000001, usize(4)) == 0b00010000);
354 assert(rotl(u8, 0b00000001, isize(-1)) == 0b10000000);
364 testing.expect(rotl(u8, 0b00000001, usize(0)) == 0b00000001);
365 testing.expect(rotl(u8, 0b00000001, usize(9)) == 0b00000010);
366 testing.expect(rotl(u8, 0b00000001, usize(8)) == 0b00000001);
367 testing.expect(rotl(u8, 0b00000001, usize(4)) == 0b00010000);
368 testing.expect(rotl(u8, 0b00000001, isize(-1)) == 0b10000000);
355369}
356370
357371pub fn Log2Int(comptime T: type) type {
......@@ -371,7 +385,7 @@ pub fn IntFittingRange(comptime from: comptime_int, comptime to: comptime_int) t
371385 return u0;
372386 }
373387 const is_signed = from < 0;
374 const largest_positive_integer = max(if (from<0) (-from)-1 else from, to); // two's complement
388 const largest_positive_integer = max(if (from < 0) (-from) - 1 else from, to); // two's complement
375389 const base = log2(largest_positive_integer);
376390 const upper = (1 << base) - 1;
377391 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
382396}
383397
384398test "math.IntFittingRange" {
385 assert(IntFittingRange(0, 0) == u0);
386 assert(IntFittingRange(0, 1) == u1);
387 assert(IntFittingRange(0, 2) == u2);
388 assert(IntFittingRange(0, 3) == u2);
389 assert(IntFittingRange(0, 4) == u3);
390 assert(IntFittingRange(0, 7) == u3);
391 assert(IntFittingRange(0, 8) == u4);
392 assert(IntFittingRange(0, 9) == u4);
393 assert(IntFittingRange(0, 15) == u4);
394 assert(IntFittingRange(0, 16) == u5);
395 assert(IntFittingRange(0, 17) == u5);
396 assert(IntFittingRange(0, 4095) == u12);
397 assert(IntFittingRange(2000, 4095) == u12);
398 assert(IntFittingRange(0, 4096) == u13);
399 assert(IntFittingRange(2000, 4096) == u13);
400 assert(IntFittingRange(0, 4097) == u13);
401 assert(IntFittingRange(2000, 4097) == u13);
402 assert(IntFittingRange(0, 123456789123456798123456789) == u87);
403 assert(IntFittingRange(0, 123456789123456798123456789123456789123456798123456789) == u177);
404
405 assert(IntFittingRange(-1, -1) == i1);
406 assert(IntFittingRange(-1, 0) == i1);
407 assert(IntFittingRange(-1, 1) == i2);
408 assert(IntFittingRange(-2, -2) == i2);
409 assert(IntFittingRange(-2, -1) == i2);
410 assert(IntFittingRange(-2, 0) == i2);
411 assert(IntFittingRange(-2, 1) == i2);
412 assert(IntFittingRange(-2, 2) == i3);
413 assert(IntFittingRange(-1, 2) == i3);
414 assert(IntFittingRange(-1, 3) == i3);
415 assert(IntFittingRange(-1, 4) == i4);
416 assert(IntFittingRange(-1, 7) == i4);
417 assert(IntFittingRange(-1, 8) == i5);
418 assert(IntFittingRange(-1, 9) == i5);
419 assert(IntFittingRange(-1, 15) == i5);
420 assert(IntFittingRange(-1, 16) == i6);
421 assert(IntFittingRange(-1, 17) == i6);
422 assert(IntFittingRange(-1, 4095) == i13);
423 assert(IntFittingRange(-4096, 4095) == i13);
424 assert(IntFittingRange(-1, 4096) == i14);
425 assert(IntFittingRange(-4097, 4095) == i14);
426 assert(IntFittingRange(-1, 4097) == i14);
427 assert(IntFittingRange(-1, 123456789123456798123456789) == i88);
428 assert(IntFittingRange(-1, 123456789123456798123456789123456789123456798123456789) == i178);
399 testing.expect(IntFittingRange(0, 0) == u0);
400 testing.expect(IntFittingRange(0, 1) == u1);
401 testing.expect(IntFittingRange(0, 2) == u2);
402 testing.expect(IntFittingRange(0, 3) == u2);
403 testing.expect(IntFittingRange(0, 4) == u3);
404 testing.expect(IntFittingRange(0, 7) == u3);
405 testing.expect(IntFittingRange(0, 8) == u4);
406 testing.expect(IntFittingRange(0, 9) == u4);
407 testing.expect(IntFittingRange(0, 15) == u4);
408 testing.expect(IntFittingRange(0, 16) == u5);
409 testing.expect(IntFittingRange(0, 17) == u5);
410 testing.expect(IntFittingRange(0, 4095) == u12);
411 testing.expect(IntFittingRange(2000, 4095) == u12);
412 testing.expect(IntFittingRange(0, 4096) == u13);
413 testing.expect(IntFittingRange(2000, 4096) == u13);
414 testing.expect(IntFittingRange(0, 4097) == u13);
415 testing.expect(IntFittingRange(2000, 4097) == u13);
416 testing.expect(IntFittingRange(0, 123456789123456798123456789) == u87);
417 testing.expect(IntFittingRange(0, 123456789123456798123456789123456789123456798123456789) == u177);
418
419 testing.expect(IntFittingRange(-1, -1) == i1);
420 testing.expect(IntFittingRange(-1, 0) == i1);
421 testing.expect(IntFittingRange(-1, 1) == i2);
422 testing.expect(IntFittingRange(-2, -2) == i2);
423 testing.expect(IntFittingRange(-2, -1) == i2);
424 testing.expect(IntFittingRange(-2, 0) == i2);
425 testing.expect(IntFittingRange(-2, 1) == i2);
426 testing.expect(IntFittingRange(-2, 2) == i3);
427 testing.expect(IntFittingRange(-1, 2) == i3);
428 testing.expect(IntFittingRange(-1, 3) == i3);
429 testing.expect(IntFittingRange(-1, 4) == i4);
430 testing.expect(IntFittingRange(-1, 7) == i4);
431 testing.expect(IntFittingRange(-1, 8) == i5);
432 testing.expect(IntFittingRange(-1, 9) == i5);
433 testing.expect(IntFittingRange(-1, 15) == i5);
434 testing.expect(IntFittingRange(-1, 16) == i6);
435 testing.expect(IntFittingRange(-1, 17) == i6);
436 testing.expect(IntFittingRange(-1, 4095) == i13);
437 testing.expect(IntFittingRange(-4096, 4095) == i13);
438 testing.expect(IntFittingRange(-1, 4096) == i14);
439 testing.expect(IntFittingRange(-4097, 4095) == i14);
440 testing.expect(IntFittingRange(-1, 4097) == i14);
441 testing.expect(IntFittingRange(-1, 123456789123456798123456789) == i88);
442 testing.expect(IntFittingRange(-1, 123456789123456798123456789123456789123456798123456789) == i178);
429443}
430444
431445test "math overflow functions" {
......@@ -434,10 +448,10 @@ test "math overflow functions" {
434448}
435449
436450fn testOverflow() void {
437 assert((mul(i32, 3, 4) catch unreachable) == 12);
438 assert((add(i32, 3, 4) catch unreachable) == 7);
439 assert((sub(i32, 3, 4) catch unreachable) == -1);
440 assert((shlExact(i32, 0b11, 4) catch unreachable) == 0b110000);
451 testing.expect((mul(i32, 3, 4) catch unreachable) == 12);
452 testing.expect((add(i32, 3, 4) catch unreachable) == 7);
453 testing.expect((sub(i32, 3, 4) catch unreachable) == -1);
454 testing.expect((shlExact(i32, 0b11, 4) catch unreachable) == 0b110000);
441455}
442456
443457pub fn absInt(x: var) !@typeOf(x) {
......@@ -458,8 +472,8 @@ test "math.absInt" {
458472 comptime testAbsInt();
459473}
460474fn testAbsInt() void {
461 assert((absInt(i32(-10)) catch unreachable) == 10);
462 assert((absInt(i32(10)) catch unreachable) == 10);
475 testing.expect((absInt(i32(-10)) catch unreachable) == 10);
476 testing.expect((absInt(i32(10)) catch unreachable) == 10);
463477}
464478
465479pub const absFloat = @import("fabs.zig").fabs;
......@@ -476,13 +490,13 @@ test "math.divTrunc" {
476490 comptime testDivTrunc();
477491}
478492fn testDivTrunc() void {
479 assert((divTrunc(i32, 5, 3) catch unreachable) == 1);
480 assert((divTrunc(i32, -5, 3) catch unreachable) == -1);
481 if (divTrunc(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
482 if (divTrunc(i8, -128, -1)) |_| unreachable else |err| assert(err == error.Overflow);
493 testing.expect((divTrunc(i32, 5, 3) catch unreachable) == 1);
494 testing.expect((divTrunc(i32, -5, 3) catch unreachable) == -1);
495 testing.expectError(error.DivisionByZero, divTrunc(i8, -5, 0));
496 testing.expectError(error.Overflow, divTrunc(i8, -128, -1));
483497
484 assert((divTrunc(f32, 5.0, 3.0) catch unreachable) == 1.0);
485 assert((divTrunc(f32, -5.0, 3.0) catch unreachable) == -1.0);
498 testing.expect((divTrunc(f32, 5.0, 3.0) catch unreachable) == 1.0);
499 testing.expect((divTrunc(f32, -5.0, 3.0) catch unreachable) == -1.0);
486500}
487501
488502pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T {
......@@ -497,13 +511,13 @@ test "math.divFloor" {
497511 comptime testDivFloor();
498512}
499513fn testDivFloor() void {
500 assert((divFloor(i32, 5, 3) catch unreachable) == 1);
501 assert((divFloor(i32, -5, 3) catch unreachable) == -2);
502 if (divFloor(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
503 if (divFloor(i8, -128, -1)) |_| unreachable else |err| assert(err == error.Overflow);
514 testing.expect((divFloor(i32, 5, 3) catch unreachable) == 1);
515 testing.expect((divFloor(i32, -5, 3) catch unreachable) == -2);
516 testing.expectError(error.DivisionByZero, divFloor(i8, -5, 0));
517 testing.expectError(error.Overflow, divFloor(i8, -128, -1));
504518
505 assert((divFloor(f32, 5.0, 3.0) catch unreachable) == 1.0);
506 assert((divFloor(f32, -5.0, 3.0) catch unreachable) == -2.0);
519 testing.expect((divFloor(f32, 5.0, 3.0) catch unreachable) == 1.0);
520 testing.expect((divFloor(f32, -5.0, 3.0) catch unreachable) == -2.0);
507521}
508522
509523pub fn divExact(comptime T: type, numerator: T, denominator: T) !T {
......@@ -520,15 +534,15 @@ test "math.divExact" {
520534 comptime testDivExact();
521535}
522536fn testDivExact() void {
523 assert((divExact(i32, 10, 5) catch unreachable) == 2);
524 assert((divExact(i32, -10, 5) catch unreachable) == -2);
525 if (divExact(i8, -5, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
526 if (divExact(i8, -128, -1)) |_| unreachable else |err| assert(err == error.Overflow);
527 if (divExact(i32, 5, 2)) |_| unreachable else |err| assert(err == error.UnexpectedRemainder);
537 testing.expect((divExact(i32, 10, 5) catch unreachable) == 2);
538 testing.expect((divExact(i32, -10, 5) catch unreachable) == -2);
539 testing.expectError(error.DivisionByZero, divExact(i8, -5, 0));
540 testing.expectError(error.Overflow, divExact(i8, -128, -1));
541 testing.expectError(error.UnexpectedRemainder, divExact(i32, 5, 2));
528542
529 assert((divExact(f32, 10.0, 5.0) catch unreachable) == 2.0);
530 assert((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);
543 testing.expect((divExact(f32, 10.0, 5.0) catch unreachable) == 2.0);
544 testing.expect((divExact(f32, -10.0, 5.0) catch unreachable) == -2.0);
545 testing.expectError(error.UnexpectedRemainder, divExact(f32, 5.0, 2.0));
532546}
533547
534548pub fn mod(comptime T: type, numerator: T, denominator: T) !T {
......@@ -543,15 +557,15 @@ test "math.mod" {
543557 comptime testMod();
544558}
545559fn testMod() void {
546 assert((mod(i32, -5, 3) catch unreachable) == 1);
547 assert((mod(i32, 5, 3) catch unreachable) == 2);
548 if (mod(i32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator);
549 if (mod(i32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
560 testing.expect((mod(i32, -5, 3) catch unreachable) == 1);
561 testing.expect((mod(i32, 5, 3) catch unreachable) == 2);
562 testing.expectError(error.NegativeDenominator, mod(i32, 10, -1));
563 testing.expectError(error.DivisionByZero, mod(i32, 10, 0));
550564
551 assert((mod(f32, -5, 3) catch unreachable) == 1);
552 assert((mod(f32, 5, 3) catch unreachable) == 2);
553 if (mod(f32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator);
554 if (mod(f32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
565 testing.expect((mod(f32, -5, 3) catch unreachable) == 1);
566 testing.expect((mod(f32, 5, 3) catch unreachable) == 2);
567 testing.expectError(error.NegativeDenominator, mod(f32, 10, -1));
568 testing.expectError(error.DivisionByZero, mod(f32, 10, 0));
555569}
556570
557571pub fn rem(comptime T: type, numerator: T, denominator: T) !T {
......@@ -566,15 +580,15 @@ test "math.rem" {
566580 comptime testRem();
567581}
568582fn testRem() void {
569 assert((rem(i32, -5, 3) catch unreachable) == -2);
570 assert((rem(i32, 5, 3) catch unreachable) == 2);
571 if (rem(i32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator);
572 if (rem(i32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
583 testing.expect((rem(i32, -5, 3) catch unreachable) == -2);
584 testing.expect((rem(i32, 5, 3) catch unreachable) == 2);
585 testing.expectError(error.NegativeDenominator, rem(i32, 10, -1));
586 testing.expectError(error.DivisionByZero, rem(i32, 10, 0));
573587
574 assert((rem(f32, -5, 3) catch unreachable) == -2);
575 assert((rem(f32, 5, 3) catch unreachable) == 2);
576 if (rem(f32, 10, -1)) |_| unreachable else |err| assert(err == error.NegativeDenominator);
577 if (rem(f32, 10, 0)) |_| unreachable else |err| assert(err == error.DivisionByZero);
588 testing.expect((rem(f32, -5, 3) catch unreachable) == -2);
589 testing.expect((rem(f32, 5, 3) catch unreachable) == 2);
590 testing.expectError(error.NegativeDenominator, rem(f32, 10, -1));
591 testing.expectError(error.DivisionByZero, rem(f32, 10, 0));
578592}
579593
580594/// Returns the absolute value of the integer parameter.
......@@ -587,14 +601,14 @@ pub fn absCast(x: var) @IntType(false, @typeOf(x).bit_count) {
587601}
588602
589603test "math.absCast" {
590 assert(absCast(i32(-999)) == 999);
591 assert(@typeOf(absCast(i32(-999))) == u32);
604 testing.expect(absCast(i32(-999)) == 999);
605 testing.expect(@typeOf(absCast(i32(-999))) == u32);
592606
593 assert(absCast(i32(999)) == 999);
594 assert(@typeOf(absCast(i32(999))) == u32);
607 testing.expect(absCast(i32(999)) == 999);
608 testing.expect(@typeOf(absCast(i32(999))) == u32);
595609
596 assert(absCast(i32(minInt(i32))) == -minInt(i32));
597 assert(@typeOf(absCast(i32(minInt(i32)))) == u32);
610 testing.expect(absCast(i32(minInt(i32))) == -minInt(i32));
611 testing.expect(@typeOf(absCast(i32(minInt(i32)))) == u32);
598612}
599613
600614/// Returns the negation of the integer parameter.
......@@ -611,13 +625,13 @@ pub fn negateCast(x: var) !@IntType(true, @typeOf(x).bit_count) {
611625}
612626
613627test "math.negateCast" {
614 assert((negateCast(u32(999)) catch unreachable) == -999);
615 assert(@typeOf(negateCast(u32(999)) catch unreachable) == i32);
628 testing.expect((negateCast(u32(999)) catch unreachable) == -999);
629 testing.expect(@typeOf(negateCast(u32(999)) catch unreachable) == i32);
616630
617 assert((negateCast(u32(-minInt(i32))) catch unreachable) == minInt(i32));
618 assert(@typeOf(negateCast(u32(-minInt(i32))) catch unreachable) == i32);
631 testing.expect((negateCast(u32(-minInt(i32))) catch unreachable) == minInt(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)));
621635}
622636
623637/// 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) {
635649}
636650
637651test "math.cast" {
638 if (cast(u8, u32(300))) |_| @panic("fail") else |err| assert(err == error.Overflow);
639 if (cast(i8, i32(-200))) |_| @panic("fail") else |err| assert(err == error.Overflow);
640 if (cast(u8, i8(-1))) |_| @panic("fail") else |err| assert(err == error.Overflow);
641 if (cast(u64, i8(-1))) |_| @panic("fail") else |err| assert(err == error.Overflow);
652 testing.expectError(error.Overflow, cast(u8, u32(300)));
653 testing.expectError(error.Overflow, cast(i8, i32(-200)));
654 testing.expectError(error.Overflow, cast(u8, i8(-1)));
655 testing.expectError(error.Overflow, cast(u64, i8(-1)));
642656
643 assert((try cast(u8, u32(255))) == u8(255));
644 assert(@typeOf(try cast(u8, u32(255))) == u8);
657 testing.expect((try cast(u8, u32(255))) == u8(255));
658 testing.expect(@typeOf(try cast(u8, u32(255))) == u8);
645659}
646660
647661pub const AlignCastError = error{UnalignedMemory};
......@@ -685,25 +699,25 @@ pub fn log2_int_ceil(comptime T: type, x: T) Log2Int(T) {
685699}
686700
687701test "std.math.log2_int_ceil" {
688 assert(log2_int_ceil(u32, 1) == 0);
689 assert(log2_int_ceil(u32, 2) == 1);
690 assert(log2_int_ceil(u32, 3) == 2);
691 assert(log2_int_ceil(u32, 4) == 2);
692 assert(log2_int_ceil(u32, 5) == 3);
693 assert(log2_int_ceil(u32, 6) == 3);
694 assert(log2_int_ceil(u32, 7) == 3);
695 assert(log2_int_ceil(u32, 8) == 3);
696 assert(log2_int_ceil(u32, 9) == 4);
697 assert(log2_int_ceil(u32, 10) == 4);
702 testing.expect(log2_int_ceil(u32, 1) == 0);
703 testing.expect(log2_int_ceil(u32, 2) == 1);
704 testing.expect(log2_int_ceil(u32, 3) == 2);
705 testing.expect(log2_int_ceil(u32, 4) == 2);
706 testing.expect(log2_int_ceil(u32, 5) == 3);
707 testing.expect(log2_int_ceil(u32, 6) == 3);
708 testing.expect(log2_int_ceil(u32, 7) == 3);
709 testing.expect(log2_int_ceil(u32, 8) == 3);
710 testing.expect(log2_int_ceil(u32, 9) == 4);
711 testing.expect(log2_int_ceil(u32, 10) == 4);
698712}
699713
700714fn testFloorPowerOfTwo() void {
701 assert(floorPowerOfTwo(u32, 63) == 32);
702 assert(floorPowerOfTwo(u32, 64) == 64);
703 assert(floorPowerOfTwo(u32, 65) == 64);
704 assert(floorPowerOfTwo(u4, 7) == 4);
705 assert(floorPowerOfTwo(u4, 8) == 8);
706 assert(floorPowerOfTwo(u4, 9) == 8);
715 testing.expect(floorPowerOfTwo(u32, 63) == 32);
716 testing.expect(floorPowerOfTwo(u32, 64) == 64);
717 testing.expect(floorPowerOfTwo(u32, 65) == 64);
718 testing.expect(floorPowerOfTwo(u4, 7) == 4);
719 testing.expect(floorPowerOfTwo(u4, 8) == 8);
720 testing.expect(floorPowerOfTwo(u4, 9) == 8);
707721}
708722
709723pub fn lossyCast(comptime T: type, value: var) T {
......@@ -719,7 +733,7 @@ pub fn lossyCast(comptime T: type, value: var) T {
719733test "math.f64_min" {
720734 const f64_min_u64 = 0x0010000000000000;
721735 const fmin: f64 = f64_min;
722 assert(@bitCast(u64, fmin) == f64_min_u64);
736 testing.expect(@bitCast(u64, fmin) == f64_min_u64);
723737}
724738
725739pub fn maxInt(comptime T: type) comptime_int {
......@@ -738,36 +752,40 @@ pub fn minInt(comptime T: type) comptime_int {
738752}
739753
740754test "minInt and maxInt" {
741 assert(maxInt(u0) == 0);
742 assert(maxInt(u1) == 1);
743 assert(maxInt(u8) == 255);
744 assert(maxInt(u16) == 65535);
745 assert(maxInt(u32) == 4294967295);
746 assert(maxInt(u64) == 18446744073709551615);
747
748 assert(maxInt(i0) == 0);
749 assert(maxInt(i1) == 0);
750 assert(maxInt(i8) == 127);
751 assert(maxInt(i16) == 32767);
752 assert(maxInt(i32) == 2147483647);
753 assert(maxInt(i63) == 4611686018427387903);
754 assert(maxInt(i64) == 9223372036854775807);
755
756 assert(minInt(u0) == 0);
757 assert(minInt(u1) == 0);
758 assert(minInt(u8) == 0);
759 assert(minInt(u16) == 0);
760 assert(minInt(u32) == 0);
761 assert(minInt(u63) == 0);
762 assert(minInt(u64) == 0);
763
764 assert(minInt(i0) == 0);
765 assert(minInt(i1) == -1);
766 assert(minInt(i8) == -128);
767 assert(minInt(i16) == -32768);
768 assert(minInt(i32) == -2147483648);
769 assert(minInt(i63) == -4611686018427387904);
770 assert(minInt(i64) == -9223372036854775808);
755 testing.expect(maxInt(u0) == 0);
756 testing.expect(maxInt(u1) == 1);
757 testing.expect(maxInt(u8) == 255);
758 testing.expect(maxInt(u16) == 65535);
759 testing.expect(maxInt(u32) == 4294967295);
760 testing.expect(maxInt(u64) == 18446744073709551615);
761 testing.expect(maxInt(u128) == 340282366920938463463374607431768211455);
762
763 testing.expect(maxInt(i0) == 0);
764 testing.expect(maxInt(i1) == 0);
765 testing.expect(maxInt(i8) == 127);
766 testing.expect(maxInt(i16) == 32767);
767 testing.expect(maxInt(i32) == 2147483647);
768 testing.expect(maxInt(i63) == 4611686018427387903);
769 testing.expect(maxInt(i64) == 9223372036854775807);
770 testing.expect(maxInt(i128) == 170141183460469231731687303715884105727);
771
772 testing.expect(minInt(u0) == 0);
773 testing.expect(minInt(u1) == 0);
774 testing.expect(minInt(u8) == 0);
775 testing.expect(minInt(u16) == 0);
776 testing.expect(minInt(u32) == 0);
777 testing.expect(minInt(u63) == 0);
778 testing.expect(minInt(u64) == 0);
779 testing.expect(minInt(u128) == 0);
780
781 testing.expect(minInt(i0) == 0);
782 testing.expect(minInt(i1) == -1);
783 testing.expect(minInt(i8) == -128);
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);
771789}
772790
773791test "max value type" {
......@@ -775,5 +793,5 @@ test "max value type" {
775793 // u32 would not work. But since the value is a number literal,
776794 // it works fine.
777795 const x: u32 = maxInt(i32);
778 assert(x == 2147483647);
796 testing.expect(x == 2147483647);
779797}
std/math/inf.zig+4-3
......@@ -3,9 +3,10 @@ const math = std.math;
33
44pub fn inf(comptime T: type) T {
55 return switch (T) {
6 f16 => @bitCast(f16, math.inf_u16),
7 f32 => @bitCast(f32, math.inf_u32),
8 f64 => @bitCast(f64, math.inf_u64),
6 f16 => math.inf_f16,
7 f32 => math.inf_f32,
8 f64 => math.inf_f64,
9 f128 => math.inf_f128,
910 else => @compileError("inf not implemented for " ++ @typeName(T)),
1011 };
1112}
std/math/isfinite.zig+13-13
......@@ -1,6 +1,6 @@
11const std = @import("../index.zig");
22const math = std.math;
3const assert = std.debug.assert;
3const expect = std.testing.expect;
44const maxInt = std.math.maxInt;
55
66pub fn isFinite(x: var) bool {
......@@ -25,16 +25,16 @@ pub fn isFinite(x: var) bool {
2525}
2626
2727test "math.isFinite" {
28 assert(isFinite(f16(0.0)));
29 assert(isFinite(f16(-0.0)));
30 assert(isFinite(f32(0.0)));
31 assert(isFinite(f32(-0.0)));
32 assert(isFinite(f64(0.0)));
33 assert(isFinite(f64(-0.0)));
34 assert(!isFinite(math.inf(f16)));
35 assert(!isFinite(-math.inf(f16)));
36 assert(!isFinite(math.inf(f32)));
37 assert(!isFinite(-math.inf(f32)));
38 assert(!isFinite(math.inf(f64)));
39 assert(!isFinite(-math.inf(f64)));
28 expect(isFinite(f16(0.0)));
29 expect(isFinite(f16(-0.0)));
30 expect(isFinite(f32(0.0)));
31 expect(isFinite(f32(-0.0)));
32 expect(isFinite(f64(0.0)));
33 expect(isFinite(f64(-0.0)));
34 expect(!isFinite(math.inf(f16)));
35 expect(!isFinite(-math.inf(f16)));
36 expect(!isFinite(math.inf(f32)));
37 expect(!isFinite(-math.inf(f32)));
38 expect(!isFinite(math.inf(f64)));
39 expect(!isFinite(-math.inf(f64)));
4040}
std/math/isinf.zig+59-37
......@@ -1,6 +1,6 @@
11const std = @import("../index.zig");
22const math = std.math;
3const assert = std.debug.assert;
3const expect = std.testing.expect;
44const maxInt = std.math.maxInt;
55
66pub fn isInf(x: var) bool {
......@@ -18,6 +18,10 @@ pub fn isInf(x: var) bool {
1818 const bits = @bitCast(u64, x);
1919 return bits & (maxInt(u64) >> 1) == (0x7FF << 52);
2020 },
21 f128 => {
22 const bits = @bitCast(u128, x);
23 return bits & (maxInt(u128) >> 1) == (0x7FFF << 112);
24 },
2125 else => {
2226 @compileError("isInf not implemented for " ++ @typeName(T));
2327 },
......@@ -36,6 +40,9 @@ pub fn isPositiveInf(x: var) bool {
3640 f64 => {
3741 return @bitCast(u64, x) == 0x7FF << 52;
3842 },
43 f128 => {
44 return @bitCast(u128, x) == 0x7FFF << 112;
45 },
3946 else => {
4047 @compileError("isPositiveInf not implemented for " ++ @typeName(T));
4148 },
......@@ -54,6 +61,9 @@ pub fn isNegativeInf(x: var) bool {
5461 f64 => {
5562 return @bitCast(u64, x) == 0xFFF << 52;
5663 },
64 f128 => {
65 return @bitCast(u128, x) == 0xFFFF << 112;
66 },
5767 else => {
5868 @compileError("isNegativeInf not implemented for " ++ @typeName(T));
5969 },
......@@ -61,46 +71,58 @@ pub fn isNegativeInf(x: var) bool {
6171}
6272
6373test "math.isInf" {
64 assert(!isInf(f16(0.0)));
65 assert(!isInf(f16(-0.0)));
66 assert(!isInf(f32(0.0)));
67 assert(!isInf(f32(-0.0)));
68 assert(!isInf(f64(0.0)));
69 assert(!isInf(f64(-0.0)));
70 assert(isInf(math.inf(f16)));
71 assert(isInf(-math.inf(f16)));
72 assert(isInf(math.inf(f32)));
73 assert(isInf(-math.inf(f32)));
74 assert(isInf(math.inf(f64)));
75 assert(isInf(-math.inf(f64)));
74 expect(!isInf(f16(0.0)));
75 expect(!isInf(f16(-0.0)));
76 expect(!isInf(f32(0.0)));
77 expect(!isInf(f32(-0.0)));
78 expect(!isInf(f64(0.0)));
79 expect(!isInf(f64(-0.0)));
80 expect(!isInf(f128(0.0)));
81 expect(!isInf(f128(-0.0)));
82 expect(isInf(math.inf(f16)));
83 expect(isInf(-math.inf(f16)));
84 expect(isInf(math.inf(f32)));
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)));
7690}
7791
7892test "math.isPositiveInf" {
79 assert(!isPositiveInf(f16(0.0)));
80 assert(!isPositiveInf(f16(-0.0)));
81 assert(!isPositiveInf(f32(0.0)));
82 assert(!isPositiveInf(f32(-0.0)));
83 assert(!isPositiveInf(f64(0.0)));
84 assert(!isPositiveInf(f64(-0.0)));
85 assert(isPositiveInf(math.inf(f16)));
86 assert(!isPositiveInf(-math.inf(f16)));
87 assert(isPositiveInf(math.inf(f32)));
88 assert(!isPositiveInf(-math.inf(f32)));
89 assert(isPositiveInf(math.inf(f64)));
90 assert(!isPositiveInf(-math.inf(f64)));
93 expect(!isPositiveInf(f16(0.0)));
94 expect(!isPositiveInf(f16(-0.0)));
95 expect(!isPositiveInf(f32(0.0)));
96 expect(!isPositiveInf(f32(-0.0)));
97 expect(!isPositiveInf(f64(0.0)));
98 expect(!isPositiveInf(f64(-0.0)));
99 expect(!isPositiveInf(f128(0.0)));
100 expect(!isPositiveInf(f128(-0.0)));
101 expect(isPositiveInf(math.inf(f16)));
102 expect(!isPositiveInf(-math.inf(f16)));
103 expect(isPositiveInf(math.inf(f32)));
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)));
91109}
92110
93111test "math.isNegativeInf" {
94 assert(!isNegativeInf(f16(0.0)));
95 assert(!isNegativeInf(f16(-0.0)));
96 assert(!isNegativeInf(f32(0.0)));
97 assert(!isNegativeInf(f32(-0.0)));
98 assert(!isNegativeInf(f64(0.0)));
99 assert(!isNegativeInf(f64(-0.0)));
100 assert(!isNegativeInf(math.inf(f16)));
101 assert(isNegativeInf(-math.inf(f16)));
102 assert(!isNegativeInf(math.inf(f32)));
103 assert(isNegativeInf(-math.inf(f32)));
104 assert(!isNegativeInf(math.inf(f64)));
105 assert(isNegativeInf(-math.inf(f64)));
112 expect(!isNegativeInf(f16(0.0)));
113 expect(!isNegativeInf(f16(-0.0)));
114 expect(!isNegativeInf(f32(0.0)));
115 expect(!isNegativeInf(f32(-0.0)));
116 expect(!isNegativeInf(f64(0.0)));
117 expect(!isNegativeInf(f64(-0.0)));
118 expect(!isNegativeInf(f128(0.0)));
119 expect(!isNegativeInf(f128(-0.0)));
120 expect(!isNegativeInf(math.inf(f16)));
121 expect(isNegativeInf(-math.inf(f16)));
122 expect(!isNegativeInf(math.inf(f32)));
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)));
106128}
std/math/isnan.zig+13-7
......@@ -1,6 +1,6 @@
11const std = @import("../index.zig");
22const math = std.math;
3const assert = std.debug.assert;
3const expect = std.testing.expect;
44const maxInt = std.math.maxInt;
55
66pub fn isNan(x: var) bool {
......@@ -18,6 +18,10 @@ pub fn isNan(x: var) bool {
1818 const bits = @bitCast(u64, x);
1919 return (bits & (maxInt(u64) >> 1)) > (u64(0x7FF) << 52);
2020 },
21 f128 => {
22 const bits = @bitCast(u128, x);
23 return (bits & (maxInt(u128) >> 1)) > (u128(0x7FFF) << 112);
24 },
2125 else => {
2226 @compileError("isNan not implemented for " ++ @typeName(T));
2327 },
......@@ -31,10 +35,12 @@ pub fn isSignalNan(x: var) bool {
3135}
3236
3337test "math.isNan" {
34 assert(isNan(math.nan(f16)));
35 assert(isNan(math.nan(f32)));
36 assert(isNan(math.nan(f64)));
37 assert(!isNan(f16(1.0)));
38 assert(!isNan(f32(1.0)));
39 assert(!isNan(f64(1.0)));
38 expect(isNan(math.nan(f16)));
39 expect(isNan(math.nan(f32)));
40 expect(isNan(math.nan(f64)));
41 expect(isNan(math.nan(f128)));
42 expect(!isNan(f16(1.0)));
43 expect(!isNan(f32(1.0)));
44 expect(!isNan(f64(1.0)));
45 expect(!isNan(f128(1.0)));
4046}
std/math/isnormal.zig+10-10
......@@ -1,6 +1,6 @@
11const std = @import("../index.zig");
22const math = std.math;
3const assert = std.debug.assert;
3const expect = std.testing.expect;
44const maxInt = std.math.maxInt;
55
66pub fn isNormal(x: var) bool {
......@@ -25,13 +25,13 @@ pub fn isNormal(x: var) bool {
2525}
2626
2727test "math.isNormal" {
28 assert(!isNormal(math.nan(f16)));
29 assert(!isNormal(math.nan(f32)));
30 assert(!isNormal(math.nan(f64)));
31 assert(!isNormal(f16(0)));
32 assert(!isNormal(f32(0)));
33 assert(!isNormal(f64(0)));
34 assert(isNormal(f16(1.0)));
35 assert(isNormal(f32(1.0)));
36 assert(isNormal(f64(1.0)));
28 expect(!isNormal(math.nan(f16)));
29 expect(!isNormal(math.nan(f32)));
30 expect(!isNormal(math.nan(f64)));
31 expect(!isNormal(f16(0)));
32 expect(!isNormal(f32(0)));
33 expect(!isNormal(f64(0)));
34 expect(isNormal(f16(1.0)));
35 expect(isNormal(f32(1.0)));
36 expect(isNormal(f64(1.0)));
3737}
std/math/ln.zig+23-23
......@@ -7,7 +7,7 @@
77
88const std = @import("../index.zig");
99const math = std.math;
10const assert = std.debug.assert;
10const expect = std.testing.expect;
1111const builtin = @import("builtin");
1212const TypeId = builtin.TypeId;
1313
......@@ -143,42 +143,42 @@ pub fn ln_64(x_: f64) f64 {
143143}
144144
145145test "math.ln" {
146 assert(ln(f32(0.2)) == ln_32(0.2));
147 assert(ln(f64(0.2)) == ln_64(0.2));
146 expect(ln(f32(0.2)) == ln_32(0.2));
147 expect(ln(f64(0.2)) == ln_64(0.2));
148148}
149149
150150test "math.ln32" {
151151 const epsilon = 0.000001;
152152
153 assert(math.approxEq(f32, ln_32(0.2), -1.609438, epsilon));
154 assert(math.approxEq(f32, ln_32(0.8923), -0.113953, epsilon));
155 assert(math.approxEq(f32, ln_32(1.5), 0.405465, epsilon));
156 assert(math.approxEq(f32, ln_32(37.45), 3.623007, epsilon));
157 assert(math.approxEq(f32, ln_32(89.123), 4.490017, epsilon));
158 assert(math.approxEq(f32, ln_32(123123.234375), 11.720941, epsilon));
153 expect(math.approxEq(f32, ln_32(0.2), -1.609438, epsilon));
154 expect(math.approxEq(f32, ln_32(0.8923), -0.113953, epsilon));
155 expect(math.approxEq(f32, ln_32(1.5), 0.405465, epsilon));
156 expect(math.approxEq(f32, ln_32(37.45), 3.623007, epsilon));
157 expect(math.approxEq(f32, ln_32(89.123), 4.490017, epsilon));
158 expect(math.approxEq(f32, ln_32(123123.234375), 11.720941, epsilon));
159159}
160160
161161test "math.ln64" {
162162 const epsilon = 0.000001;
163163
164 assert(math.approxEq(f64, ln_64(0.2), -1.609438, epsilon));
165 assert(math.approxEq(f64, ln_64(0.8923), -0.113953, epsilon));
166 assert(math.approxEq(f64, ln_64(1.5), 0.405465, epsilon));
167 assert(math.approxEq(f64, ln_64(37.45), 3.623007, epsilon));
168 assert(math.approxEq(f64, ln_64(89.123), 4.490017, epsilon));
169 assert(math.approxEq(f64, ln_64(123123.234375), 11.720941, epsilon));
164 expect(math.approxEq(f64, ln_64(0.2), -1.609438, epsilon));
165 expect(math.approxEq(f64, ln_64(0.8923), -0.113953, epsilon));
166 expect(math.approxEq(f64, ln_64(1.5), 0.405465, epsilon));
167 expect(math.approxEq(f64, ln_64(37.45), 3.623007, epsilon));
168 expect(math.approxEq(f64, ln_64(89.123), 4.490017, epsilon));
169 expect(math.approxEq(f64, ln_64(123123.234375), 11.720941, epsilon));
170170}
171171
172172test "math.ln32.special" {
173 assert(math.isPositiveInf(ln_32(math.inf(f32))));
174 assert(math.isNegativeInf(ln_32(0.0)));
175 assert(math.isNan(ln_32(-1.0)));
176 assert(math.isNan(ln_32(math.nan(f32))));
173 expect(math.isPositiveInf(ln_32(math.inf(f32))));
174 expect(math.isNegativeInf(ln_32(0.0)));
175 expect(math.isNan(ln_32(-1.0)));
176 expect(math.isNan(ln_32(math.nan(f32))));
177177}
178178
179179test "math.ln64.special" {
180 assert(math.isPositiveInf(ln_64(math.inf(f64))));
181 assert(math.isNegativeInf(ln_64(0.0)));
182 assert(math.isNan(ln_64(-1.0)));
183 assert(math.isNan(ln_64(math.nan(f64))));
180 expect(math.isPositiveInf(ln_64(math.inf(f64))));
181 expect(math.isNegativeInf(ln_64(0.0)));
182 expect(math.isNan(ln_64(-1.0)));
183 expect(math.isNan(ln_64(math.nan(f64))));
184184}
std/math/log.zig+13-13
......@@ -2,7 +2,7 @@ const std = @import("../index.zig");
22const math = std.math;
33const builtin = @import("builtin");
44const TypeId = builtin.TypeId;
5const assert = std.debug.assert;
5const expect = std.testing.expect;
66
77pub fn log(comptime T: type, base: T, x: T) T {
88 if (base == 2) {
......@@ -41,25 +41,25 @@ pub fn log(comptime T: type, base: T, x: T) T {
4141}
4242
4343test "math.log integer" {
44 assert(log(u8, 2, 0x1) == 0);
45 assert(log(u8, 2, 0x2) == 1);
46 assert(log(i16, 2, 0x72) == 6);
47 assert(log(u32, 2, 0xFFFFFF) == 23);
48 assert(log(u64, 2, 0x7FF0123456789ABC) == 62);
44 expect(log(u8, 2, 0x1) == 0);
45 expect(log(u8, 2, 0x2) == 1);
46 expect(log(i16, 2, 0x72) == 6);
47 expect(log(u32, 2, 0xFFFFFF) == 23);
48 expect(log(u64, 2, 0x7FF0123456789ABC) == 62);
4949}
5050
5151test "math.log float" {
5252 const epsilon = 0.000001;
5353
54 assert(math.approxEq(f32, log(f32, 6, 0.23947), -0.797723, epsilon));
55 assert(math.approxEq(f32, log(f32, 89, 0.23947), -0.318432, epsilon));
56 assert(math.approxEq(f64, log(f64, 123897, 12389216414), 1.981724596, epsilon));
54 expect(math.approxEq(f32, log(f32, 6, 0.23947), -0.797723, epsilon));
55 expect(math.approxEq(f32, log(f32, 89, 0.23947), -0.318432, epsilon));
56 expect(math.approxEq(f64, log(f64, 123897, 12389216414), 1.981724596, epsilon));
5757}
5858
5959test "math.log float_special" {
60 assert(log(f32, 2, 0.2301974) == math.log2(f32(0.2301974)));
61 assert(log(f32, 10, 0.2301974) == math.log10(f32(0.2301974)));
60 expect(log(f32, 2, 0.2301974) == math.log2(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)));
64 assert(log(f64, 10, 213.23019799993) == math.log10(f64(213.23019799993)));
63 expect(log(f64, 2, 213.23019799993) == math.log2(f64(213.23019799993)));
64 expect(log(f64, 10, 213.23019799993) == math.log10(f64(213.23019799993)));
6565}
std/math/log10.zig+23-23
......@@ -7,7 +7,7 @@
77
88const std = @import("../index.zig");
99const math = std.math;
10const assert = std.debug.assert;
10const testing = std.testing;
1111const builtin = @import("builtin");
1212const TypeId = builtin.TypeId;
1313const maxInt = std.math.maxInt;
......@@ -171,42 +171,42 @@ pub fn log10_64(x_: f64) f64 {
171171}
172172
173173test "math.log10" {
174 assert(log10(f32(0.2)) == log10_32(0.2));
175 assert(log10(f64(0.2)) == log10_64(0.2));
174 testing.expect(log10(f32(0.2)) == log10_32(0.2));
175 testing.expect(log10(f64(0.2)) == log10_64(0.2));
176176}
177177
178178test "math.log10_32" {
179179 const epsilon = 0.000001;
180180
181 assert(math.approxEq(f32, log10_32(0.2), -0.698970, epsilon));
182 assert(math.approxEq(f32, log10_32(0.8923), -0.049489, epsilon));
183 assert(math.approxEq(f32, log10_32(1.5), 0.176091, epsilon));
184 assert(math.approxEq(f32, log10_32(37.45), 1.573452, epsilon));
185 assert(math.approxEq(f32, log10_32(89.123), 1.94999, epsilon));
186 assert(math.approxEq(f32, log10_32(123123.234375), 5.09034, epsilon));
181 testing.expect(math.approxEq(f32, log10_32(0.2), -0.698970, epsilon));
182 testing.expect(math.approxEq(f32, log10_32(0.8923), -0.049489, epsilon));
183 testing.expect(math.approxEq(f32, log10_32(1.5), 0.176091, epsilon));
184 testing.expect(math.approxEq(f32, log10_32(37.45), 1.573452, epsilon));
185 testing.expect(math.approxEq(f32, log10_32(89.123), 1.94999, epsilon));
186 testing.expect(math.approxEq(f32, log10_32(123123.234375), 5.09034, epsilon));
187187}
188188
189189test "math.log10_64" {
190190 const epsilon = 0.000001;
191191
192 assert(math.approxEq(f64, log10_64(0.2), -0.698970, epsilon));
193 assert(math.approxEq(f64, log10_64(0.8923), -0.049489, epsilon));
194 assert(math.approxEq(f64, log10_64(1.5), 0.176091, epsilon));
195 assert(math.approxEq(f64, log10_64(37.45), 1.573452, epsilon));
196 assert(math.approxEq(f64, log10_64(89.123), 1.94999, epsilon));
197 assert(math.approxEq(f64, log10_64(123123.234375), 5.09034, epsilon));
192 testing.expect(math.approxEq(f64, log10_64(0.2), -0.698970, epsilon));
193 testing.expect(math.approxEq(f64, log10_64(0.8923), -0.049489, epsilon));
194 testing.expect(math.approxEq(f64, log10_64(1.5), 0.176091, epsilon));
195 testing.expect(math.approxEq(f64, log10_64(37.45), 1.573452, epsilon));
196 testing.expect(math.approxEq(f64, log10_64(89.123), 1.94999, epsilon));
197 testing.expect(math.approxEq(f64, log10_64(123123.234375), 5.09034, epsilon));
198198}
199199
200200test "math.log10_32.special" {
201 assert(math.isPositiveInf(log10_32(math.inf(f32))));
202 assert(math.isNegativeInf(log10_32(0.0)));
203 assert(math.isNan(log10_32(-1.0)));
204 assert(math.isNan(log10_32(math.nan(f32))));
201 testing.expect(math.isPositiveInf(log10_32(math.inf(f32))));
202 testing.expect(math.isNegativeInf(log10_32(0.0)));
203 testing.expect(math.isNan(log10_32(-1.0)));
204 testing.expect(math.isNan(log10_32(math.nan(f32))));
205205}
206206
207207test "math.log10_64.special" {
208 assert(math.isPositiveInf(log10_64(math.inf(f64))));
209 assert(math.isNegativeInf(log10_64(0.0)));
210 assert(math.isNan(log10_64(-1.0)));
211 assert(math.isNan(log10_64(math.nan(f64))));
208 testing.expect(math.isPositiveInf(log10_64(math.inf(f64))));
209 testing.expect(math.isNegativeInf(log10_64(0.0)));
210 testing.expect(math.isNan(log10_64(-1.0)));
211 testing.expect(math.isNan(log10_64(math.nan(f64))));
212212}
std/math/log1p.zig+29-29
......@@ -9,7 +9,7 @@
99const builtin = @import("builtin");
1010const std = @import("../index.zig");
1111const math = std.math;
12const assert = std.debug.assert;
12const expect = std.testing.expect;
1313
1414pub fn log1p(x: var) @typeOf(x) {
1515 const T = @typeOf(x);
......@@ -177,48 +177,48 @@ fn log1p_64(x: f64) f64 {
177177}
178178
179179test "math.log1p" {
180 assert(log1p(f32(0.0)) == log1p_32(0.0));
181 assert(log1p(f64(0.0)) == log1p_64(0.0));
180 expect(log1p(f32(0.0)) == log1p_32(0.0));
181 expect(log1p(f64(0.0)) == log1p_64(0.0));
182182}
183183
184184test "math.log1p_32" {
185185 const epsilon = 0.000001;
186186
187 assert(math.approxEq(f32, log1p_32(0.0), 0.0, epsilon));
188 assert(math.approxEq(f32, log1p_32(0.2), 0.182322, epsilon));
189 assert(math.approxEq(f32, log1p_32(0.8923), 0.637793, epsilon));
190 assert(math.approxEq(f32, log1p_32(1.5), 0.916291, epsilon));
191 assert(math.approxEq(f32, log1p_32(37.45), 3.649359, epsilon));
192 assert(math.approxEq(f32, log1p_32(89.123), 4.501175, epsilon));
193 assert(math.approxEq(f32, log1p_32(123123.234375), 11.720949, epsilon));
187 expect(math.approxEq(f32, log1p_32(0.0), 0.0, epsilon));
188 expect(math.approxEq(f32, log1p_32(0.2), 0.182322, epsilon));
189 expect(math.approxEq(f32, log1p_32(0.8923), 0.637793, epsilon));
190 expect(math.approxEq(f32, log1p_32(1.5), 0.916291, epsilon));
191 expect(math.approxEq(f32, log1p_32(37.45), 3.649359, epsilon));
192 expect(math.approxEq(f32, log1p_32(89.123), 4.501175, epsilon));
193 expect(math.approxEq(f32, log1p_32(123123.234375), 11.720949, epsilon));
194194}
195195
196196test "math.log1p_64" {
197197 const epsilon = 0.000001;
198198
199 assert(math.approxEq(f64, log1p_64(0.0), 0.0, epsilon));
200 assert(math.approxEq(f64, log1p_64(0.2), 0.182322, epsilon));
201 assert(math.approxEq(f64, log1p_64(0.8923), 0.637793, epsilon));
202 assert(math.approxEq(f64, log1p_64(1.5), 0.916291, epsilon));
203 assert(math.approxEq(f64, log1p_64(37.45), 3.649359, epsilon));
204 assert(math.approxEq(f64, log1p_64(89.123), 4.501175, epsilon));
205 assert(math.approxEq(f64, log1p_64(123123.234375), 11.720949, epsilon));
199 expect(math.approxEq(f64, log1p_64(0.0), 0.0, epsilon));
200 expect(math.approxEq(f64, log1p_64(0.2), 0.182322, epsilon));
201 expect(math.approxEq(f64, log1p_64(0.8923), 0.637793, epsilon));
202 expect(math.approxEq(f64, log1p_64(1.5), 0.916291, epsilon));
203 expect(math.approxEq(f64, log1p_64(37.45), 3.649359, epsilon));
204 expect(math.approxEq(f64, log1p_64(89.123), 4.501175, epsilon));
205 expect(math.approxEq(f64, log1p_64(123123.234375), 11.720949, epsilon));
206206}
207207
208208test "math.log1p_32.special" {
209 assert(math.isPositiveInf(log1p_32(math.inf(f32))));
210 assert(log1p_32(0.0) == 0.0);
211 assert(log1p_32(-0.0) == -0.0);
212 assert(math.isNegativeInf(log1p_32(-1.0)));
213 assert(math.isNan(log1p_32(-2.0)));
214 assert(math.isNan(log1p_32(math.nan(f32))));
209 expect(math.isPositiveInf(log1p_32(math.inf(f32))));
210 expect(log1p_32(0.0) == 0.0);
211 expect(log1p_32(-0.0) == -0.0);
212 expect(math.isNegativeInf(log1p_32(-1.0)));
213 expect(math.isNan(log1p_32(-2.0)));
214 expect(math.isNan(log1p_32(math.nan(f32))));
215215}
216216
217217test "math.log1p_64.special" {
218 assert(math.isPositiveInf(log1p_64(math.inf(f64))));
219 assert(log1p_64(0.0) == 0.0);
220 assert(log1p_64(-0.0) == -0.0);
221 assert(math.isNegativeInf(log1p_64(-1.0)));
222 assert(math.isNan(log1p_64(-2.0)));
223 assert(math.isNan(log1p_64(math.nan(f64))));
218 expect(math.isPositiveInf(log1p_64(math.inf(f64))));
219 expect(log1p_64(0.0) == 0.0);
220 expect(log1p_64(-0.0) == -0.0);
221 expect(math.isNegativeInf(log1p_64(-1.0)));
222 expect(math.isNan(log1p_64(-2.0)));
223 expect(math.isNan(log1p_64(math.nan(f64))));
224224}
std/math/log2.zig+21-21
......@@ -7,7 +7,7 @@
77
88const std = @import("../index.zig");
99const math = std.math;
10const assert = std.debug.assert;
10const expect = std.testing.expect;
1111const builtin = @import("builtin");
1212const TypeId = builtin.TypeId;
1313const maxInt = std.math.maxInt;
......@@ -169,40 +169,40 @@ pub fn log2_64(x_: f64) f64 {
169169}
170170
171171test "math.log2" {
172 assert(log2(f32(0.2)) == log2_32(0.2));
173 assert(log2(f64(0.2)) == log2_64(0.2));
172 expect(log2(f32(0.2)) == log2_32(0.2));
173 expect(log2(f64(0.2)) == log2_64(0.2));
174174}
175175
176176test "math.log2_32" {
177177 const epsilon = 0.000001;
178178
179 assert(math.approxEq(f32, log2_32(0.2), -2.321928, epsilon));
180 assert(math.approxEq(f32, log2_32(0.8923), -0.164399, epsilon));
181 assert(math.approxEq(f32, log2_32(1.5), 0.584962, epsilon));
182 assert(math.approxEq(f32, log2_32(37.45), 5.226894, epsilon));
183 assert(math.approxEq(f32, log2_32(123123.234375), 16.909744, epsilon));
179 expect(math.approxEq(f32, log2_32(0.2), -2.321928, epsilon));
180 expect(math.approxEq(f32, log2_32(0.8923), -0.164399, epsilon));
181 expect(math.approxEq(f32, log2_32(1.5), 0.584962, epsilon));
182 expect(math.approxEq(f32, log2_32(37.45), 5.226894, epsilon));
183 expect(math.approxEq(f32, log2_32(123123.234375), 16.909744, epsilon));
184184}
185185
186186test "math.log2_64" {
187187 const epsilon = 0.000001;
188188
189 assert(math.approxEq(f64, log2_64(0.2), -2.321928, epsilon));
190 assert(math.approxEq(f64, log2_64(0.8923), -0.164399, epsilon));
191 assert(math.approxEq(f64, log2_64(1.5), 0.584962, epsilon));
192 assert(math.approxEq(f64, log2_64(37.45), 5.226894, epsilon));
193 assert(math.approxEq(f64, log2_64(123123.234375), 16.909744, epsilon));
189 expect(math.approxEq(f64, log2_64(0.2), -2.321928, epsilon));
190 expect(math.approxEq(f64, log2_64(0.8923), -0.164399, epsilon));
191 expect(math.approxEq(f64, log2_64(1.5), 0.584962, epsilon));
192 expect(math.approxEq(f64, log2_64(37.45), 5.226894, epsilon));
193 expect(math.approxEq(f64, log2_64(123123.234375), 16.909744, epsilon));
194194}
195195
196196test "math.log2_32.special" {
197 assert(math.isPositiveInf(log2_32(math.inf(f32))));
198 assert(math.isNegativeInf(log2_32(0.0)));
199 assert(math.isNan(log2_32(-1.0)));
200 assert(math.isNan(log2_32(math.nan(f32))));
197 expect(math.isPositiveInf(log2_32(math.inf(f32))));
198 expect(math.isNegativeInf(log2_32(0.0)));
199 expect(math.isNan(log2_32(-1.0)));
200 expect(math.isNan(log2_32(math.nan(f32))));
201201}
202202
203203test "math.log2_64.special" {
204 assert(math.isPositiveInf(log2_64(math.inf(f64))));
205 assert(math.isNegativeInf(log2_64(0.0)));
206 assert(math.isNan(log2_64(-1.0)));
207 assert(math.isNan(log2_64(math.nan(f64))));
204 expect(math.isPositiveInf(log2_64(math.inf(f64))));
205 expect(math.isNegativeInf(log2_64(0.0)));
206 expect(math.isNan(log2_64(-1.0)));
207 expect(math.isNan(log2_64(math.nan(f64))));
208208}
std/math/modf.zig+29-29
......@@ -5,7 +5,7 @@
55
66const std = @import("../index.zig");
77const math = std.math;
8const assert = std.debug.assert;
8const expect = std.testing.expect;
99const maxInt = std.math.maxInt;
1010
1111fn modf_result(comptime T: type) type {
......@@ -119,11 +119,11 @@ test "math.modf" {
119119 const a = modf(f32(1.0));
120120 const b = modf32(1.0);
121121 // 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
124124 const c = modf(f64(1.0));
125125 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);
127127}
128128
129129test "math.modf32" {
......@@ -131,24 +131,24 @@ test "math.modf32" {
131131 var r: modf32_result = undefined;
132132
133133 r = modf32(1.0);
134 assert(math.approxEq(f32, r.ipart, 1.0, epsilon));
135 assert(math.approxEq(f32, r.fpart, 0.0, epsilon));
134 expect(math.approxEq(f32, r.ipart, 1.0, epsilon));
135 expect(math.approxEq(f32, r.fpart, 0.0, epsilon));
136136
137137 r = modf32(2.545);
138 assert(math.approxEq(f32, r.ipart, 2.0, epsilon));
139 assert(math.approxEq(f32, r.fpart, 0.545, epsilon));
138 expect(math.approxEq(f32, r.ipart, 2.0, epsilon));
139 expect(math.approxEq(f32, r.fpart, 0.545, epsilon));
140140
141141 r = modf32(3.978123);
142 assert(math.approxEq(f32, r.ipart, 3.0, epsilon));
143 assert(math.approxEq(f32, r.fpart, 0.978123, epsilon));
142 expect(math.approxEq(f32, r.ipart, 3.0, epsilon));
143 expect(math.approxEq(f32, r.fpart, 0.978123, epsilon));
144144
145145 r = modf32(43874.3);
146 assert(math.approxEq(f32, r.ipart, 43874, epsilon));
147 assert(math.approxEq(f32, r.fpart, 0.300781, epsilon));
146 expect(math.approxEq(f32, r.ipart, 43874, epsilon));
147 expect(math.approxEq(f32, r.fpart, 0.300781, epsilon));
148148
149149 r = modf32(1234.340780);
150 assert(math.approxEq(f32, r.ipart, 1234, epsilon));
151 assert(math.approxEq(f32, r.fpart, 0.340820, epsilon));
150 expect(math.approxEq(f32, r.ipart, 1234, epsilon));
151 expect(math.approxEq(f32, r.fpart, 0.340820, epsilon));
152152}
153153
154154test "math.modf64" {
......@@ -156,48 +156,48 @@ test "math.modf64" {
156156 var r: modf64_result = undefined;
157157
158158 r = modf64(1.0);
159 assert(math.approxEq(f64, r.ipart, 1.0, epsilon));
160 assert(math.approxEq(f64, r.fpart, 0.0, epsilon));
159 expect(math.approxEq(f64, r.ipart, 1.0, epsilon));
160 expect(math.approxEq(f64, r.fpart, 0.0, epsilon));
161161
162162 r = modf64(2.545);
163 assert(math.approxEq(f64, r.ipart, 2.0, epsilon));
164 assert(math.approxEq(f64, r.fpart, 0.545, epsilon));
163 expect(math.approxEq(f64, r.ipart, 2.0, epsilon));
164 expect(math.approxEq(f64, r.fpart, 0.545, epsilon));
165165
166166 r = modf64(3.978123);
167 assert(math.approxEq(f64, r.ipart, 3.0, epsilon));
168 assert(math.approxEq(f64, r.fpart, 0.978123, epsilon));
167 expect(math.approxEq(f64, r.ipart, 3.0, epsilon));
168 expect(math.approxEq(f64, r.fpart, 0.978123, epsilon));
169169
170170 r = modf64(43874.3);
171 assert(math.approxEq(f64, r.ipart, 43874, epsilon));
172 assert(math.approxEq(f64, r.fpart, 0.3, epsilon));
171 expect(math.approxEq(f64, r.ipart, 43874, epsilon));
172 expect(math.approxEq(f64, r.fpart, 0.3, epsilon));
173173
174174 r = modf64(1234.340780);
175 assert(math.approxEq(f64, r.ipart, 1234, epsilon));
176 assert(math.approxEq(f64, r.fpart, 0.340780, epsilon));
175 expect(math.approxEq(f64, r.ipart, 1234, epsilon));
176 expect(math.approxEq(f64, r.fpart, 0.340780, epsilon));
177177}
178178
179179test "math.modf32.special" {
180180 var r: modf32_result = undefined;
181181
182182 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
185185 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
188188 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));
190190}
191191
192192test "math.modf64.special" {
193193 var r: modf64_result = undefined;
194194
195195 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
198198 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
201201 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));
203203}
std/math/nan.zig+4-3
......@@ -2,9 +2,10 @@ const math = @import("index.zig");
22
33pub fn nan(comptime T: type) T {
44 return switch (T) {
5 f16 => @bitCast(f16, math.nan_u16),
6 f32 => @bitCast(f32, math.nan_u32),
7 f64 => @bitCast(f64, math.nan_u64),
5 f16 => math.nan_f16,
6 f32 => math.nan_f32,
7 f64 => math.nan_f64,
8 f128 => math.nan_f128,
89 else => @compileError("nan not implemented for " ++ @typeName(T)),
910 };
1011}
std/math/pow.zig+48-48
......@@ -24,7 +24,7 @@
2424const builtin = @import("builtin");
2525const std = @import("../index.zig");
2626const math = std.math;
27const assert = std.debug.assert;
27const expect = std.testing.expect;
2828
2929// This implementation is taken from the go stlib, musl is a bit more complex.
3030pub fn pow(comptime T: type, x: T, y: T) T {
......@@ -179,56 +179,56 @@ fn isOddInteger(x: f64) bool {
179179test "math.pow" {
180180 const epsilon = 0.000001;
181181
182 assert(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));
184 assert(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));
186 assert(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));
188
189 assert(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));
191 assert(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));
193 assert(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));
182 expect(math.approxEq(f32, pow(f32, 0.0, 3.3), 0.0, epsilon));
183 expect(math.approxEq(f32, pow(f32, 0.8923, 3.3), 0.686572, epsilon));
184 expect(math.approxEq(f32, pow(f32, 0.2, 3.3), 0.004936, epsilon));
185 expect(math.approxEq(f32, pow(f32, 1.5, 3.3), 3.811546, epsilon));
186 expect(math.approxEq(f32, pow(f32, 37.45, 3.3), 155736.703125, epsilon));
187 expect(math.approxEq(f32, pow(f32, 89.123, 3.3), 2722489.5, epsilon));
188
189 expect(math.approxEq(f64, pow(f64, 0.0, 3.3), 0.0, epsilon));
190 expect(math.approxEq(f64, pow(f64, 0.8923, 3.3), 0.686572, epsilon));
191 expect(math.approxEq(f64, pow(f64, 0.2, 3.3), 0.004936, epsilon));
192 expect(math.approxEq(f64, pow(f64, 1.5, 3.3), 3.811546, epsilon));
193 expect(math.approxEq(f64, pow(f64, 37.45, 3.3), 155736.7160616, epsilon));
194 expect(math.approxEq(f64, pow(f64, 89.123, 3.3), 2722490.231436, epsilon));
195195}
196196
197197test "math.pow.special" {
198198 const epsilon = 0.000001;
199199
200 assert(pow(f32, 4, 0.0) == 1.0);
201 assert(pow(f32, 7, -0.0) == 1.0);
202 assert(pow(f32, 45, 1.0) == 45);
203 assert(pow(f32, -45, 1.0) == -45);
204 assert(math.isNan(pow(f32, math.nan(f32), 5.0)));
205 assert(math.isNan(pow(f32, 5.0, math.nan(f32))));
206 assert(math.isPositiveInf(pow(f32, 0.0, -1.0)));
207 //assert(math.isNegativeInf(pow(f32, -0.0, -3.0))); TODO is this required?
208 assert(math.isPositiveInf(pow(f32, 0.0, -math.inf(f32))));
209 assert(math.isPositiveInf(pow(f32, -0.0, -math.inf(f32))));
210 assert(pow(f32, 0.0, math.inf(f32)) == 0.0);
211 assert(pow(f32, -0.0, math.inf(f32)) == 0.0);
212 assert(math.isPositiveInf(pow(f32, 0.0, -2.0)));
213 assert(math.isPositiveInf(pow(f32, -0.0, -2.0)));
214 assert(pow(f32, 0.0, 1.0) == 0.0);
215 assert(pow(f32, -0.0, 1.0) == -0.0);
216 assert(pow(f32, 0.0, 2.0) == 0.0);
217 assert(pow(f32, -0.0, 2.0) == 0.0);
218 assert(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));
220 assert(math.isPositiveInf(pow(f32, 1.2, math.inf(f32))));
221 assert(math.isPositiveInf(pow(f32, -1.2, math.inf(f32))));
222 assert(pow(f32, 1.2, -math.inf(f32)) == 0.0);
223 assert(pow(f32, -1.2, -math.inf(f32)) == 0.0);
224 assert(pow(f32, 0.2, math.inf(f32)) == 0.0);
225 assert(pow(f32, -0.2, math.inf(f32)) == 0.0);
226 assert(math.isPositiveInf(pow(f32, 0.2, -math.inf(f32))));
227 assert(math.isPositiveInf(pow(f32, -0.2, -math.inf(f32))));
228 assert(math.isPositiveInf(pow(f32, math.inf(f32), 1.0)));
229 assert(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?
231 assert(pow(f32, -math.inf(f32), -5.2) == pow(f32, -0.0, 5.2));
232 assert(math.isNan(pow(f32, -1.0, 1.2)));
233 assert(math.isNan(pow(f32, -12.4, 78.5)));
200 expect(pow(f32, 4, 0.0) == 1.0);
201 expect(pow(f32, 7, -0.0) == 1.0);
202 expect(pow(f32, 45, 1.0) == 45);
203 expect(pow(f32, -45, 1.0) == -45);
204 expect(math.isNan(pow(f32, math.nan(f32), 5.0)));
205 expect(math.isNan(pow(f32, 5.0, math.nan(f32))));
206 expect(math.isPositiveInf(pow(f32, 0.0, -1.0)));
207 //expect(math.isNegativeInf(pow(f32, -0.0, -3.0))); TODO is this required?
208 expect(math.isPositiveInf(pow(f32, 0.0, -math.inf(f32))));
209 expect(math.isPositiveInf(pow(f32, -0.0, -math.inf(f32))));
210 expect(pow(f32, 0.0, math.inf(f32)) == 0.0);
211 expect(pow(f32, -0.0, math.inf(f32)) == 0.0);
212 expect(math.isPositiveInf(pow(f32, 0.0, -2.0)));
213 expect(math.isPositiveInf(pow(f32, -0.0, -2.0)));
214 expect(pow(f32, 0.0, 1.0) == 0.0);
215 expect(pow(f32, -0.0, 1.0) == -0.0);
216 expect(pow(f32, 0.0, 2.0) == 0.0);
217 expect(pow(f32, -0.0, 2.0) == 0.0);
218 expect(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 expect(math.isPositiveInf(pow(f32, 1.2, math.inf(f32))));
221 expect(math.isPositiveInf(pow(f32, -1.2, math.inf(f32))));
222 expect(pow(f32, 1.2, -math.inf(f32)) == 0.0);
223 expect(pow(f32, -1.2, -math.inf(f32)) == 0.0);
224 expect(pow(f32, 0.2, math.inf(f32)) == 0.0);
225 expect(pow(f32, -0.2, math.inf(f32)) == 0.0);
226 expect(math.isPositiveInf(pow(f32, 0.2, -math.inf(f32))));
227 expect(math.isPositiveInf(pow(f32, -0.2, -math.inf(f32))));
228 expect(math.isPositiveInf(pow(f32, math.inf(f32), 1.0)));
229 expect(pow(f32, math.inf(f32), -1.0) == 0.0);
230 //expect(pow(f32, -math.inf(f32), 5.0) == pow(f32, -0.0, -5.0)); TODO support negative 0?
231 expect(pow(f32, -math.inf(f32), -5.2) == pow(f32, -0.0, 5.2));
232 expect(math.isNan(pow(f32, -1.0, 1.2)));
233 expect(math.isNan(pow(f32, -12.4, 78.5)));
234234}
std/math/powi.zig+69-69
......@@ -12,7 +12,7 @@ const builtin = @import("builtin");
1212const std = @import("../index.zig");
1313const math = std.math;
1414const assert = std.debug.assert;
15const assertError = std.debug.assertError;
15const testing = std.testing;
1616
1717// This implementation is based on that from the rust stlib
1818pub 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{
103103}
104104
105105test "math.powi" {
106 assertError(powi(i8, -66, 6), error.Underflow);
107 assertError(powi(i16, -13, 13), error.Underflow);
108 assertError(powi(i32, -32, 21), error.Underflow);
109 assertError(powi(i64, -24, 61), error.Underflow);
110 assertError(powi(i17, -15, 15), error.Underflow);
111 assertError(powi(i42, -6, 40), error.Underflow);
112
113 assert((try powi(i8, -5, 3)) == -125);
114 assert((try powi(i16, -16, 3)) == -4096);
115 assert((try powi(i32, -91, 3)) == -753571);
116 assert((try powi(i64, -36, 6)) == 2176782336);
117 assert((try powi(i17, -2, 15)) == -32768);
118 assert((try powi(i42, -5, 7)) == -78125);
119
120 assert((try powi(u8, 6, 2)) == 36);
121 assert((try powi(u16, 5, 4)) == 625);
122 assert((try powi(u32, 12, 6)) == 2985984);
123 assert((try powi(u64, 34, 2)) == 1156);
124 assert((try powi(u17, 16, 3)) == 4096);
125 assert((try powi(u42, 34, 6)) == 1544804416);
126
127 assertError(powi(i8, 120, 7), error.Overflow);
128 assertError(powi(i16, 73, 15), error.Overflow);
129 assertError(powi(i32, 23, 31), error.Overflow);
130 assertError(powi(i64, 68, 61), error.Overflow);
131 assertError(powi(i17, 15, 15), error.Overflow);
132 assertError(powi(i42, 121312, 41), error.Overflow);
133
134 assertError(powi(u8, 123, 7), error.Overflow);
135 assertError(powi(u16, 2313, 15), error.Overflow);
136 assertError(powi(u32, 8968, 31), error.Overflow);
137 assertError(powi(u64, 2342, 63), error.Overflow);
138 assertError(powi(u17, 2723, 16), error.Overflow);
139 assertError(powi(u42, 8234, 41), error.Overflow);
106 testing.expectError(error.Underflow, powi(i8, -66, 6));
107 testing.expectError(error.Underflow, powi(i16, -13, 13));
108 testing.expectError(error.Underflow, powi(i32, -32, 21));
109 testing.expectError(error.Underflow, powi(i64, -24, 61));
110 testing.expectError(error.Underflow, powi(i17, -15, 15));
111 testing.expectError(error.Underflow, powi(i42, -6, 40));
112
113 testing.expect((try powi(i8, -5, 3)) == -125);
114 testing.expect((try powi(i16, -16, 3)) == -4096);
115 testing.expect((try powi(i32, -91, 3)) == -753571);
116 testing.expect((try powi(i64, -36, 6)) == 2176782336);
117 testing.expect((try powi(i17, -2, 15)) == -32768);
118 testing.expect((try powi(i42, -5, 7)) == -78125);
119
120 testing.expect((try powi(u8, 6, 2)) == 36);
121 testing.expect((try powi(u16, 5, 4)) == 625);
122 testing.expect((try powi(u32, 12, 6)) == 2985984);
123 testing.expect((try powi(u64, 34, 2)) == 1156);
124 testing.expect((try powi(u17, 16, 3)) == 4096);
125 testing.expect((try powi(u42, 34, 6)) == 1544804416);
126
127 testing.expectError(error.Overflow, powi(i8, 120, 7));
128 testing.expectError(error.Overflow, powi(i16, 73, 15));
129 testing.expectError(error.Overflow, powi(i32, 23, 31));
130 testing.expectError(error.Overflow, powi(i64, 68, 61));
131 testing.expectError(error.Overflow, powi(i17, 15, 15));
132 testing.expectError(error.Overflow, powi(i42, 121312, 41));
133
134 testing.expectError(error.Overflow, powi(u8, 123, 7));
135 testing.expectError(error.Overflow, powi(u16, 2313, 15));
136 testing.expectError(error.Overflow, powi(u32, 8968, 31));
137 testing.expectError(error.Overflow, powi(u64, 2342, 63));
138 testing.expectError(error.Overflow, powi(u17, 2723, 16));
139 testing.expectError(error.Overflow, powi(u42, 8234, 41));
140140}
141141
142142test "math.powi.special" {
143 assertError(powi(i8, -2, 8), error.Underflow);
144 assertError(powi(i16, -2, 16), error.Underflow);
145 assertError(powi(i32, -2, 32), error.Underflow);
146 assertError(powi(i64, -2, 64), error.Underflow);
147 assertError(powi(i17, -2, 17), error.Underflow);
148 assertError(powi(i42, -2, 42), error.Underflow);
149
150 assert((try powi(i8, -1, 3)) == -1);
151 assert((try powi(i16, -1, 2)) == 1);
152 assert((try powi(i32, -1, 16)) == 1);
153 assert((try powi(i64, -1, 6)) == 1);
154 assert((try powi(i17, -1, 15)) == -1);
155 assert((try powi(i42, -1, 7)) == -1);
156
157 assert((try powi(u8, 1, 2)) == 1);
158 assert((try powi(u16, 1, 4)) == 1);
159 assert((try powi(u32, 1, 6)) == 1);
160 assert((try powi(u64, 1, 2)) == 1);
161 assert((try powi(u17, 1, 3)) == 1);
162 assert((try powi(u42, 1, 6)) == 1);
163
164 assertError(powi(i8, 2, 7), error.Overflow);
165 assertError(powi(i16, 2, 15), error.Overflow);
166 assertError(powi(i32, 2, 31), error.Overflow);
167 assertError(powi(i64, 2, 63), error.Overflow);
168 assertError(powi(i17, 2, 16), error.Overflow);
169 assertError(powi(i42, 2, 41), error.Overflow);
170
171 assertError(powi(u8, 2, 8), error.Overflow);
172 assertError(powi(u16, 2, 16), error.Overflow);
173 assertError(powi(u32, 2, 32), error.Overflow);
174 assertError(powi(u64, 2, 64), error.Overflow);
175 assertError(powi(u17, 2, 17), error.Overflow);
176 assertError(powi(u42, 2, 42), error.Overflow);
143 testing.expectError(error.Underflow, powi(i8, -2, 8));
144 testing.expectError(error.Underflow, powi(i16, -2, 16));
145 testing.expectError(error.Underflow, powi(i32, -2, 32));
146 testing.expectError(error.Underflow, powi(i64, -2, 64));
147 testing.expectError(error.Underflow, powi(i17, -2, 17));
148 testing.expectError(error.Underflow, powi(i42, -2, 42));
149
150 testing.expect((try powi(i8, -1, 3)) == -1);
151 testing.expect((try powi(i16, -1, 2)) == 1);
152 testing.expect((try powi(i32, -1, 16)) == 1);
153 testing.expect((try powi(i64, -1, 6)) == 1);
154 testing.expect((try powi(i17, -1, 15)) == -1);
155 testing.expect((try powi(i42, -1, 7)) == -1);
156
157 testing.expect((try powi(u8, 1, 2)) == 1);
158 testing.expect((try powi(u16, 1, 4)) == 1);
159 testing.expect((try powi(u32, 1, 6)) == 1);
160 testing.expect((try powi(u64, 1, 2)) == 1);
161 testing.expect((try powi(u17, 1, 3)) == 1);
162 testing.expect((try powi(u42, 1, 6)) == 1);
163
164 testing.expectError(error.Overflow, powi(i8, 2, 7));
165 testing.expectError(error.Overflow, powi(i16, 2, 15));
166 testing.expectError(error.Overflow, powi(i32, 2, 31));
167 testing.expectError(error.Overflow, powi(i64, 2, 63));
168 testing.expectError(error.Overflow, powi(i17, 2, 16));
169 testing.expectError(error.Overflow, powi(i42, 2, 41));
170
171 testing.expectError(error.Overflow, powi(u8, 2, 8));
172 testing.expectError(error.Overflow, powi(u16, 2, 16));
173 testing.expectError(error.Overflow, powi(u32, 2, 32));
174 testing.expectError(error.Overflow, powi(u64, 2, 64));
175 testing.expectError(error.Overflow, powi(u17, 2, 17));
176 testing.expectError(error.Overflow, powi(u42, 2, 42));
177177}
std/math/round.zig+21-21
......@@ -5,7 +5,7 @@
55// - round(nan) = nan
66
77const builtin = @import("builtin");
8const assert = std.debug.assert;
8const expect = std.testing.expect;
99const std = @import("../index.zig");
1010const math = std.math;
1111
......@@ -85,36 +85,36 @@ fn round64(x_: f64) f64 {
8585}
8686
8787test "math.round" {
88 assert(round(f32(1.3)) == round32(1.3));
89 assert(round(f64(1.3)) == round64(1.3));
88 expect(round(f32(1.3)) == round32(1.3));
89 expect(round(f64(1.3)) == round64(1.3));
9090}
9191
9292test "math.round32" {
93 assert(round32(1.3) == 1.0);
94 assert(round32(-1.3) == -1.0);
95 assert(round32(0.2) == 0.0);
96 assert(round32(1.8) == 2.0);
93 expect(round32(1.3) == 1.0);
94 expect(round32(-1.3) == -1.0);
95 expect(round32(0.2) == 0.0);
96 expect(round32(1.8) == 2.0);
9797}
9898
9999test "math.round64" {
100 assert(round64(1.3) == 1.0);
101 assert(round64(-1.3) == -1.0);
102 assert(round64(0.2) == 0.0);
103 assert(round64(1.8) == 2.0);
100 expect(round64(1.3) == 1.0);
101 expect(round64(-1.3) == -1.0);
102 expect(round64(0.2) == 0.0);
103 expect(round64(1.8) == 2.0);
104104}
105105
106106test "math.round32.special" {
107 assert(round32(0.0) == 0.0);
108 assert(round32(-0.0) == -0.0);
109 assert(math.isPositiveInf(round32(math.inf(f32))));
110 assert(math.isNegativeInf(round32(-math.inf(f32))));
111 assert(math.isNan(round32(math.nan(f32))));
107 expect(round32(0.0) == 0.0);
108 expect(round32(-0.0) == -0.0);
109 expect(math.isPositiveInf(round32(math.inf(f32))));
110 expect(math.isNegativeInf(round32(-math.inf(f32))));
111 expect(math.isNan(round32(math.nan(f32))));
112112}
113113
114114test "math.round64.special" {
115 assert(round64(0.0) == 0.0);
116 assert(round64(-0.0) == -0.0);
117 assert(math.isPositiveInf(round64(math.inf(f64))));
118 assert(math.isNegativeInf(round64(-math.inf(f64))));
119 assert(math.isNan(round64(math.nan(f64))));
115 expect(round64(0.0) == 0.0);
116 expect(round64(-0.0) == -0.0);
117 expect(math.isPositiveInf(round64(math.inf(f64))));
118 expect(math.isNegativeInf(round64(-math.inf(f64))));
119 expect(math.isNan(round64(math.nan(f64))));
120120}
std/math/scalbn.zig+5-5
......@@ -1,6 +1,6 @@
11const std = @import("../index.zig");
22const math = std.math;
3const assert = std.debug.assert;
3const expect = std.testing.expect;
44
55pub fn scalbn(x: var, n: i32) @typeOf(x) {
66 const T = @typeOf(x);
......@@ -72,14 +72,14 @@ fn scalbn64(x: f64, n_: i32) f64 {
7272}
7373
7474test "math.scalbn" {
75 assert(scalbn(f32(1.5), 4) == scalbn32(1.5, 4));
76 assert(scalbn(f64(1.5), 4) == scalbn64(1.5, 4));
75 expect(scalbn(f32(1.5), 4) == scalbn32(1.5, 4));
76 expect(scalbn(f64(1.5), 4) == scalbn64(1.5, 4));
7777}
7878
7979test "math.scalbn32" {
80 assert(scalbn32(1.5, 4) == 24.0);
80 expect(scalbn32(1.5, 4) == 24.0);
8181}
8282
8383test "math.scalbn64" {
84 assert(scalbn64(1.5, 4) == 24.0);
84 expect(scalbn64(1.5, 4) == 24.0);
8585}
std/math/signbit.zig+10-10
......@@ -1,6 +1,6 @@
11const std = @import("../index.zig");
22const math = std.math;
3const assert = std.debug.assert;
3const expect = std.testing.expect;
44
55pub fn signbit(x: var) bool {
66 const T = @typeOf(x);
......@@ -28,22 +28,22 @@ fn signbit64(x: f64) bool {
2828}
2929
3030test "math.signbit" {
31 assert(signbit(f16(4.0)) == signbit16(4.0));
32 assert(signbit(f32(4.0)) == signbit32(4.0));
33 assert(signbit(f64(4.0)) == signbit64(4.0));
31 expect(signbit(f16(4.0)) == signbit16(4.0));
32 expect(signbit(f32(4.0)) == signbit32(4.0));
33 expect(signbit(f64(4.0)) == signbit64(4.0));
3434}
3535
3636test "math.signbit16" {
37 assert(!signbit16(4.0));
38 assert(signbit16(-3.0));
37 expect(!signbit16(4.0));
38 expect(signbit16(-3.0));
3939}
4040
4141test "math.signbit32" {
42 assert(!signbit32(4.0));
43 assert(signbit32(-3.0));
42 expect(!signbit32(4.0));
43 expect(signbit32(-3.0));
4444}
4545
4646test "math.signbit64" {
47 assert(!signbit64(4.0));
48 assert(signbit64(-3.0));
47 expect(!signbit64(4.0));
48 expect(signbit64(-3.0));
4949}
std/math/sin.zig+26-26
......@@ -7,7 +7,7 @@
77const builtin = @import("builtin");
88const std = @import("../index.zig");
99const math = std.math;
10const assert = std.debug.assert;
10const expect = std.testing.expect;
1111
1212pub fn sin(x: var) @typeOf(x) {
1313 const T = @typeOf(x);
......@@ -142,45 +142,45 @@ fn sin64(x_: f64) f64 {
142142}
143143
144144test "math.sin" {
145 assert(sin(f32(0.0)) == sin32(0.0));
146 assert(sin(f64(0.0)) == sin64(0.0));
147 assert(comptime (math.sin(f64(2))) == math.sin(f64(2)));
145 expect(sin(f32(0.0)) == sin32(0.0));
146 expect(sin(f64(0.0)) == sin64(0.0));
147 expect(comptime (math.sin(f64(2))) == math.sin(f64(2)));
148148}
149149
150150test "math.sin32" {
151151 const epsilon = 0.000001;
152152
153 assert(math.approxEq(f32, sin32(0.0), 0.0, epsilon));
154 assert(math.approxEq(f32, sin32(0.2), 0.198669, epsilon));
155 assert(math.approxEq(f32, sin32(0.8923), 0.778517, epsilon));
156 assert(math.approxEq(f32, sin32(1.5), 0.997495, epsilon));
157 assert(math.approxEq(f32, sin32(37.45), -0.246544, epsilon));
158 assert(math.approxEq(f32, sin32(89.123), 0.916166, epsilon));
153 expect(math.approxEq(f32, sin32(0.0), 0.0, epsilon));
154 expect(math.approxEq(f32, sin32(0.2), 0.198669, epsilon));
155 expect(math.approxEq(f32, sin32(0.8923), 0.778517, epsilon));
156 expect(math.approxEq(f32, sin32(1.5), 0.997495, epsilon));
157 expect(math.approxEq(f32, sin32(37.45), -0.246544, epsilon));
158 expect(math.approxEq(f32, sin32(89.123), 0.916166, epsilon));
159159}
160160
161161test "math.sin64" {
162162 const epsilon = 0.000001;
163163
164 assert(math.approxEq(f64, sin64(0.0), 0.0, epsilon));
165 assert(math.approxEq(f64, sin64(0.2), 0.198669, epsilon));
166 assert(math.approxEq(f64, sin64(0.8923), 0.778517, epsilon));
167 assert(math.approxEq(f64, sin64(1.5), 0.997495, epsilon));
168 assert(math.approxEq(f64, sin64(37.45), -0.246543, epsilon));
169 assert(math.approxEq(f64, sin64(89.123), 0.916166, epsilon));
164 expect(math.approxEq(f64, sin64(0.0), 0.0, epsilon));
165 expect(math.approxEq(f64, sin64(0.2), 0.198669, epsilon));
166 expect(math.approxEq(f64, sin64(0.8923), 0.778517, epsilon));
167 expect(math.approxEq(f64, sin64(1.5), 0.997495, epsilon));
168 expect(math.approxEq(f64, sin64(37.45), -0.246543, epsilon));
169 expect(math.approxEq(f64, sin64(89.123), 0.916166, epsilon));
170170}
171171
172172test "math.sin32.special" {
173 assert(sin32(0.0) == 0.0);
174 assert(sin32(-0.0) == -0.0);
175 assert(math.isNan(sin32(math.inf(f32))));
176 assert(math.isNan(sin32(-math.inf(f32))));
177 assert(math.isNan(sin32(math.nan(f32))));
173 expect(sin32(0.0) == 0.0);
174 expect(sin32(-0.0) == -0.0);
175 expect(math.isNan(sin32(math.inf(f32))));
176 expect(math.isNan(sin32(-math.inf(f32))));
177 expect(math.isNan(sin32(math.nan(f32))));
178178}
179179
180180test "math.sin64.special" {
181 assert(sin64(0.0) == 0.0);
182 assert(sin64(-0.0) == -0.0);
183 assert(math.isNan(sin64(math.inf(f64))));
184 assert(math.isNan(sin64(-math.inf(f64))));
185 assert(math.isNan(sin64(math.nan(f64))));
181 expect(sin64(0.0) == 0.0);
182 expect(sin64(-0.0) == -0.0);
183 expect(math.isNan(sin64(math.inf(f64))));
184 expect(math.isNan(sin64(-math.inf(f64))));
185 expect(math.isNan(sin64(math.nan(f64))));
186186}
std/math/sinh.zig+21-21
......@@ -7,7 +7,7 @@
77const builtin = @import("builtin");
88const std = @import("../index.zig");
99const math = std.math;
10const assert = std.debug.assert;
10const expect = std.testing.expect;
1111const expo2 = @import("expo2.zig").expo2;
1212const maxInt = std.math.maxInt;
1313
......@@ -87,40 +87,40 @@ fn sinh64(x: f64) f64 {
8787}
8888
8989test "math.sinh" {
90 assert(sinh(f32(1.5)) == sinh32(1.5));
91 assert(sinh(f64(1.5)) == sinh64(1.5));
90 expect(sinh(f32(1.5)) == sinh32(1.5));
91 expect(sinh(f64(1.5)) == sinh64(1.5));
9292}
9393
9494test "math.sinh32" {
9595 const epsilon = 0.000001;
9696
97 assert(math.approxEq(f32, sinh32(0.0), 0.0, epsilon));
98 assert(math.approxEq(f32, sinh32(0.2), 0.201336, epsilon));
99 assert(math.approxEq(f32, sinh32(0.8923), 1.015512, epsilon));
100 assert(math.approxEq(f32, sinh32(1.5), 2.129279, epsilon));
97 expect(math.approxEq(f32, sinh32(0.0), 0.0, epsilon));
98 expect(math.approxEq(f32, sinh32(0.2), 0.201336, epsilon));
99 expect(math.approxEq(f32, sinh32(0.8923), 1.015512, epsilon));
100 expect(math.approxEq(f32, sinh32(1.5), 2.129279, epsilon));
101101}
102102
103103test "math.sinh64" {
104104 const epsilon = 0.000001;
105105
106 assert(math.approxEq(f64, sinh64(0.0), 0.0, epsilon));
107 assert(math.approxEq(f64, sinh64(0.2), 0.201336, epsilon));
108 assert(math.approxEq(f64, sinh64(0.8923), 1.015512, epsilon));
109 assert(math.approxEq(f64, sinh64(1.5), 2.129279, epsilon));
106 expect(math.approxEq(f64, sinh64(0.0), 0.0, epsilon));
107 expect(math.approxEq(f64, sinh64(0.2), 0.201336, epsilon));
108 expect(math.approxEq(f64, sinh64(0.8923), 1.015512, epsilon));
109 expect(math.approxEq(f64, sinh64(1.5), 2.129279, epsilon));
110110}
111111
112112test "math.sinh32.special" {
113 assert(sinh32(0.0) == 0.0);
114 assert(sinh32(-0.0) == -0.0);
115 assert(math.isPositiveInf(sinh32(math.inf(f32))));
116 assert(math.isNegativeInf(sinh32(-math.inf(f32))));
117 assert(math.isNan(sinh32(math.nan(f32))));
113 expect(sinh32(0.0) == 0.0);
114 expect(sinh32(-0.0) == -0.0);
115 expect(math.isPositiveInf(sinh32(math.inf(f32))));
116 expect(math.isNegativeInf(sinh32(-math.inf(f32))));
117 expect(math.isNan(sinh32(math.nan(f32))));
118118}
119119
120120test "math.sinh64.special" {
121 assert(sinh64(0.0) == 0.0);
122 assert(sinh64(-0.0) == -0.0);
123 assert(math.isPositiveInf(sinh64(math.inf(f64))));
124 assert(math.isNegativeInf(sinh64(-math.inf(f64))));
125 assert(math.isNan(sinh64(math.nan(f64))));
121 expect(sinh64(0.0) == 0.0);
122 expect(sinh64(-0.0) == -0.0);
123 expect(math.isPositiveInf(sinh64(math.inf(f64))));
124 expect(math.isNegativeInf(sinh64(-math.inf(f64))));
125 expect(math.isNan(sinh64(math.nan(f64))));
126126}
std/math/sqrt.zig+52-52
......@@ -7,7 +7,7 @@
77
88const std = @import("../index.zig");
99const math = std.math;
10const assert = std.debug.assert;
10const expect = std.testing.expect;
1111const builtin = @import("builtin");
1212const TypeId = builtin.TypeId;
1313const maxInt = std.math.maxInt;
......@@ -32,75 +32,75 @@ pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typ
3232}
3333
3434test "math.sqrt" {
35 assert(sqrt(f16(0.0)) == @sqrt(f16, 0.0));
36 assert(sqrt(f32(0.0)) == @sqrt(f32, 0.0));
37 assert(sqrt(f64(0.0)) == @sqrt(f64, 0.0));
35 expect(sqrt(f16(0.0)) == @sqrt(f16, 0.0));
36 expect(sqrt(f32(0.0)) == @sqrt(f32, 0.0));
37 expect(sqrt(f64(0.0)) == @sqrt(f64, 0.0));
3838}
3939
4040test "math.sqrt16" {
4141 const epsilon = 0.000001;
4242
43 assert(@sqrt(f16, 0.0) == 0.0);
44 assert(math.approxEq(f16, @sqrt(f16, 2.0), 1.414214, epsilon));
45 assert(math.approxEq(f16, @sqrt(f16, 3.6), 1.897367, epsilon));
46 assert(@sqrt(f16, 4.0) == 2.0);
47 assert(math.approxEq(f16, @sqrt(f16, 7.539840), 2.745877, epsilon));
48 assert(math.approxEq(f16, @sqrt(f16, 19.230934), 4.385309, epsilon));
49 assert(@sqrt(f16, 64.0) == 8.0);
50 assert(math.approxEq(f16, @sqrt(f16, 64.1), 8.006248, epsilon));
51 assert(math.approxEq(f16, @sqrt(f16, 8942.230469), 94.563370, epsilon));
43 expect(@sqrt(f16, 0.0) == 0.0);
44 expect(math.approxEq(f16, @sqrt(f16, 2.0), 1.414214, epsilon));
45 expect(math.approxEq(f16, @sqrt(f16, 3.6), 1.897367, epsilon));
46 expect(@sqrt(f16, 4.0) == 2.0);
47 expect(math.approxEq(f16, @sqrt(f16, 7.539840), 2.745877, epsilon));
48 expect(math.approxEq(f16, @sqrt(f16, 19.230934), 4.385309, epsilon));
49 expect(@sqrt(f16, 64.0) == 8.0);
50 expect(math.approxEq(f16, @sqrt(f16, 64.1), 8.006248, epsilon));
51 expect(math.approxEq(f16, @sqrt(f16, 8942.230469), 94.563370, epsilon));
5252}
5353
5454test "math.sqrt32" {
5555 const epsilon = 0.000001;
5656
57 assert(@sqrt(f32, 0.0) == 0.0);
58 assert(math.approxEq(f32, @sqrt(f32, 2.0), 1.414214, epsilon));
59 assert(math.approxEq(f32, @sqrt(f32, 3.6), 1.897367, epsilon));
60 assert(@sqrt(f32, 4.0) == 2.0);
61 assert(math.approxEq(f32, @sqrt(f32, 7.539840), 2.745877, epsilon));
62 assert(math.approxEq(f32, @sqrt(f32, 19.230934), 4.385309, epsilon));
63 assert(@sqrt(f32, 64.0) == 8.0);
64 assert(math.approxEq(f32, @sqrt(f32, 64.1), 8.006248, epsilon));
65 assert(math.approxEq(f32, @sqrt(f32, 8942.230469), 94.563370, epsilon));
57 expect(@sqrt(f32, 0.0) == 0.0);
58 expect(math.approxEq(f32, @sqrt(f32, 2.0), 1.414214, epsilon));
59 expect(math.approxEq(f32, @sqrt(f32, 3.6), 1.897367, epsilon));
60 expect(@sqrt(f32, 4.0) == 2.0);
61 expect(math.approxEq(f32, @sqrt(f32, 7.539840), 2.745877, epsilon));
62 expect(math.approxEq(f32, @sqrt(f32, 19.230934), 4.385309, epsilon));
63 expect(@sqrt(f32, 64.0) == 8.0);
64 expect(math.approxEq(f32, @sqrt(f32, 64.1), 8.006248, epsilon));
65 expect(math.approxEq(f32, @sqrt(f32, 8942.230469), 94.563370, epsilon));
6666}
6767
6868test "math.sqrt64" {
6969 const epsilon = 0.000001;
7070
71 assert(@sqrt(f64, 0.0) == 0.0);
72 assert(math.approxEq(f64, @sqrt(f64, 2.0), 1.414214, epsilon));
73 assert(math.approxEq(f64, @sqrt(f64, 3.6), 1.897367, epsilon));
74 assert(@sqrt(f64, 4.0) == 2.0);
75 assert(math.approxEq(f64, @sqrt(f64, 7.539840), 2.745877, epsilon));
76 assert(math.approxEq(f64, @sqrt(f64, 19.230934), 4.385309, epsilon));
77 assert(@sqrt(f64, 64.0) == 8.0);
78 assert(math.approxEq(f64, @sqrt(f64, 64.1), 8.006248, epsilon));
79 assert(math.approxEq(f64, @sqrt(f64, 8942.230469), 94.563367, epsilon));
71 expect(@sqrt(f64, 0.0) == 0.0);
72 expect(math.approxEq(f64, @sqrt(f64, 2.0), 1.414214, epsilon));
73 expect(math.approxEq(f64, @sqrt(f64, 3.6), 1.897367, epsilon));
74 expect(@sqrt(f64, 4.0) == 2.0);
75 expect(math.approxEq(f64, @sqrt(f64, 7.539840), 2.745877, epsilon));
76 expect(math.approxEq(f64, @sqrt(f64, 19.230934), 4.385309, epsilon));
77 expect(@sqrt(f64, 64.0) == 8.0);
78 expect(math.approxEq(f64, @sqrt(f64, 64.1), 8.006248, epsilon));
79 expect(math.approxEq(f64, @sqrt(f64, 8942.230469), 94.563367, epsilon));
8080}
8181
8282test "math.sqrt16.special" {
83 assert(math.isPositiveInf(@sqrt(f16, math.inf(f16))));
84 assert(@sqrt(f16, 0.0) == 0.0);
85 assert(@sqrt(f16, -0.0) == -0.0);
86 assert(math.isNan(@sqrt(f16, -1.0)));
87 assert(math.isNan(@sqrt(f16, math.nan(f16))));
83 expect(math.isPositiveInf(@sqrt(f16, math.inf(f16))));
84 expect(@sqrt(f16, 0.0) == 0.0);
85 expect(@sqrt(f16, -0.0) == -0.0);
86 expect(math.isNan(@sqrt(f16, -1.0)));
87 expect(math.isNan(@sqrt(f16, math.nan(f16))));
8888}
8989
9090test "math.sqrt32.special" {
91 assert(math.isPositiveInf(@sqrt(f32, math.inf(f32))));
92 assert(@sqrt(f32, 0.0) == 0.0);
93 assert(@sqrt(f32, -0.0) == -0.0);
94 assert(math.isNan(@sqrt(f32, -1.0)));
95 assert(math.isNan(@sqrt(f32, math.nan(f32))));
91 expect(math.isPositiveInf(@sqrt(f32, math.inf(f32))));
92 expect(@sqrt(f32, 0.0) == 0.0);
93 expect(@sqrt(f32, -0.0) == -0.0);
94 expect(math.isNan(@sqrt(f32, -1.0)));
95 expect(math.isNan(@sqrt(f32, math.nan(f32))));
9696}
9797
9898test "math.sqrt64.special" {
99 assert(math.isPositiveInf(@sqrt(f64, math.inf(f64))));
100 assert(@sqrt(f64, 0.0) == 0.0);
101 assert(@sqrt(f64, -0.0) == -0.0);
102 assert(math.isNan(@sqrt(f64, -1.0)));
103 assert(math.isNan(@sqrt(f64, math.nan(f64))));
99 expect(math.isPositiveInf(@sqrt(f64, math.inf(f64))));
100 expect(@sqrt(f64, 0.0) == 0.0);
101 expect(@sqrt(f64, -0.0) == -0.0);
102 expect(math.isNan(@sqrt(f64, -1.0)));
103 expect(math.isNan(@sqrt(f64, math.nan(f64))));
104104}
105105
106106fn 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) {
127127}
128128
129129test "math.sqrt_int" {
130 assert(sqrt_int(u32, 3) == 1);
131 assert(sqrt_int(u32, 4) == 2);
132 assert(sqrt_int(u32, 5) == 2);
133 assert(sqrt_int(u32, 8) == 2);
134 assert(sqrt_int(u32, 9) == 3);
135 assert(sqrt_int(u32, 10) == 3);
130 expect(sqrt_int(u32, 3) == 1);
131 expect(sqrt_int(u32, 4) == 2);
132 expect(sqrt_int(u32, 5) == 2);
133 expect(sqrt_int(u32, 8) == 2);
134 expect(sqrt_int(u32, 9) == 3);
135 expect(sqrt_int(u32, 10) == 3);
136136}
std/math/tan.zig+25-25
......@@ -7,7 +7,7 @@
77const builtin = @import("builtin");
88const std = @import("../index.zig");
99const math = std.math;
10const assert = std.debug.assert;
10const expect = std.testing.expect;
1111
1212pub fn tan(x: var) @typeOf(x) {
1313 const T = @typeOf(x);
......@@ -129,44 +129,44 @@ fn tan64(x_: f64) f64 {
129129}
130130
131131test "math.tan" {
132 assert(tan(f32(0.0)) == tan32(0.0));
133 assert(tan(f64(0.0)) == tan64(0.0));
132 expect(tan(f32(0.0)) == tan32(0.0));
133 expect(tan(f64(0.0)) == tan64(0.0));
134134}
135135
136136test "math.tan32" {
137137 const epsilon = 0.000001;
138138
139 assert(math.approxEq(f32, tan32(0.0), 0.0, epsilon));
140 assert(math.approxEq(f32, tan32(0.2), 0.202710, epsilon));
141 assert(math.approxEq(f32, tan32(0.8923), 1.240422, epsilon));
142 assert(math.approxEq(f32, tan32(1.5), 14.101420, epsilon));
143 assert(math.approxEq(f32, tan32(37.45), -0.254397, epsilon));
144 assert(math.approxEq(f32, tan32(89.123), 2.285852, epsilon));
139 expect(math.approxEq(f32, tan32(0.0), 0.0, epsilon));
140 expect(math.approxEq(f32, tan32(0.2), 0.202710, epsilon));
141 expect(math.approxEq(f32, tan32(0.8923), 1.240422, epsilon));
142 expect(math.approxEq(f32, tan32(1.5), 14.101420, epsilon));
143 expect(math.approxEq(f32, tan32(37.45), -0.254397, epsilon));
144 expect(math.approxEq(f32, tan32(89.123), 2.285852, epsilon));
145145}
146146
147147test "math.tan64" {
148148 const epsilon = 0.000001;
149149
150 assert(math.approxEq(f64, tan64(0.0), 0.0, epsilon));
151 assert(math.approxEq(f64, tan64(0.2), 0.202710, epsilon));
152 assert(math.approxEq(f64, tan64(0.8923), 1.240422, epsilon));
153 assert(math.approxEq(f64, tan64(1.5), 14.101420, epsilon));
154 assert(math.approxEq(f64, tan64(37.45), -0.254397, epsilon));
155 assert(math.approxEq(f64, tan64(89.123), 2.2858376, epsilon));
150 expect(math.approxEq(f64, tan64(0.0), 0.0, epsilon));
151 expect(math.approxEq(f64, tan64(0.2), 0.202710, epsilon));
152 expect(math.approxEq(f64, tan64(0.8923), 1.240422, epsilon));
153 expect(math.approxEq(f64, tan64(1.5), 14.101420, epsilon));
154 expect(math.approxEq(f64, tan64(37.45), -0.254397, epsilon));
155 expect(math.approxEq(f64, tan64(89.123), 2.2858376, epsilon));
156156}
157157
158158test "math.tan32.special" {
159 assert(tan32(0.0) == 0.0);
160 assert(tan32(-0.0) == -0.0);
161 assert(math.isNan(tan32(math.inf(f32))));
162 assert(math.isNan(tan32(-math.inf(f32))));
163 assert(math.isNan(tan32(math.nan(f32))));
159 expect(tan32(0.0) == 0.0);
160 expect(tan32(-0.0) == -0.0);
161 expect(math.isNan(tan32(math.inf(f32))));
162 expect(math.isNan(tan32(-math.inf(f32))));
163 expect(math.isNan(tan32(math.nan(f32))));
164164}
165165
166166test "math.tan64.special" {
167 assert(tan64(0.0) == 0.0);
168 assert(tan64(-0.0) == -0.0);
169 assert(math.isNan(tan64(math.inf(f64))));
170 assert(math.isNan(tan64(-math.inf(f64))));
171 assert(math.isNan(tan64(math.nan(f64))));
167 expect(tan64(0.0) == 0.0);
168 expect(tan64(-0.0) == -0.0);
169 expect(math.isNan(tan64(math.inf(f64))));
170 expect(math.isNan(tan64(-math.inf(f64))));
171 expect(math.isNan(tan64(math.nan(f64))));
172172}
std/math/tanh.zig+23-23
......@@ -7,7 +7,7 @@
77const builtin = @import("builtin");
88const std = @import("../index.zig");
99const math = std.math;
10const assert = std.debug.assert;
10const expect = std.testing.expect;
1111const expo2 = @import("expo2.zig").expo2;
1212const maxInt = std.math.maxInt;
1313
......@@ -113,42 +113,42 @@ fn tanh64(x: f64) f64 {
113113}
114114
115115test "math.tanh" {
116 assert(tanh(f32(1.5)) == tanh32(1.5));
117 assert(tanh(f64(1.5)) == tanh64(1.5));
116 expect(tanh(f32(1.5)) == tanh32(1.5));
117 expect(tanh(f64(1.5)) == tanh64(1.5));
118118}
119119
120120test "math.tanh32" {
121121 const epsilon = 0.000001;
122122
123 assert(math.approxEq(f32, tanh32(0.0), 0.0, epsilon));
124 assert(math.approxEq(f32, tanh32(0.2), 0.197375, epsilon));
125 assert(math.approxEq(f32, tanh32(0.8923), 0.712528, epsilon));
126 assert(math.approxEq(f32, tanh32(1.5), 0.905148, epsilon));
127 assert(math.approxEq(f32, tanh32(37.45), 1.0, epsilon));
123 expect(math.approxEq(f32, tanh32(0.0), 0.0, epsilon));
124 expect(math.approxEq(f32, tanh32(0.2), 0.197375, epsilon));
125 expect(math.approxEq(f32, tanh32(0.8923), 0.712528, epsilon));
126 expect(math.approxEq(f32, tanh32(1.5), 0.905148, epsilon));
127 expect(math.approxEq(f32, tanh32(37.45), 1.0, epsilon));
128128}
129129
130130test "math.tanh64" {
131131 const epsilon = 0.000001;
132132
133 assert(math.approxEq(f64, tanh64(0.0), 0.0, epsilon));
134 assert(math.approxEq(f64, tanh64(0.2), 0.197375, epsilon));
135 assert(math.approxEq(f64, tanh64(0.8923), 0.712528, epsilon));
136 assert(math.approxEq(f64, tanh64(1.5), 0.905148, epsilon));
137 assert(math.approxEq(f64, tanh64(37.45), 1.0, epsilon));
133 expect(math.approxEq(f64, tanh64(0.0), 0.0, epsilon));
134 expect(math.approxEq(f64, tanh64(0.2), 0.197375, epsilon));
135 expect(math.approxEq(f64, tanh64(0.8923), 0.712528, epsilon));
136 expect(math.approxEq(f64, tanh64(1.5), 0.905148, epsilon));
137 expect(math.approxEq(f64, tanh64(37.45), 1.0, epsilon));
138138}
139139
140140test "math.tanh32.special" {
141 assert(tanh32(0.0) == 0.0);
142 assert(tanh32(-0.0) == -0.0);
143 assert(tanh32(math.inf(f32)) == 1.0);
144 assert(tanh32(-math.inf(f32)) == -1.0);
145 assert(math.isNan(tanh32(math.nan(f32))));
141 expect(tanh32(0.0) == 0.0);
142 expect(tanh32(-0.0) == -0.0);
143 expect(tanh32(math.inf(f32)) == 1.0);
144 expect(tanh32(-math.inf(f32)) == -1.0);
145 expect(math.isNan(tanh32(math.nan(f32))));
146146}
147147
148148test "math.tanh64.special" {
149 assert(tanh64(0.0) == 0.0);
150 assert(tanh64(-0.0) == -0.0);
151 assert(tanh64(math.inf(f64)) == 1.0);
152 assert(tanh64(-math.inf(f64)) == -1.0);
153 assert(math.isNan(tanh64(math.nan(f64))));
149 expect(tanh64(0.0) == 0.0);
150 expect(tanh64(-0.0) == -0.0);
151 expect(tanh64(math.inf(f64)) == 1.0);
152 expect(tanh64(-math.inf(f64)) == -1.0);
153 expect(math.isNan(tanh64(math.nan(f64))));
154154}
std/math/trunc.zig+19-19
......@@ -6,7 +6,7 @@
66
77const std = @import("../index.zig");
88const math = std.math;
9const assert = std.debug.assert;
9const expect = std.testing.expect;
1010const maxInt = std.math.maxInt;
1111
1212pub fn trunc(x: var) @typeOf(x) {
......@@ -61,34 +61,34 @@ fn trunc64(x: f64) f64 {
6161}
6262
6363test "math.trunc" {
64 assert(trunc(f32(1.3)) == trunc32(1.3));
65 assert(trunc(f64(1.3)) == trunc64(1.3));
64 expect(trunc(f32(1.3)) == trunc32(1.3));
65 expect(trunc(f64(1.3)) == trunc64(1.3));
6666}
6767
6868test "math.trunc32" {
69 assert(trunc32(1.3) == 1.0);
70 assert(trunc32(-1.3) == -1.0);
71 assert(trunc32(0.2) == 0.0);
69 expect(trunc32(1.3) == 1.0);
70 expect(trunc32(-1.3) == -1.0);
71 expect(trunc32(0.2) == 0.0);
7272}
7373
7474test "math.trunc64" {
75 assert(trunc64(1.3) == 1.0);
76 assert(trunc64(-1.3) == -1.0);
77 assert(trunc64(0.2) == 0.0);
75 expect(trunc64(1.3) == 1.0);
76 expect(trunc64(-1.3) == -1.0);
77 expect(trunc64(0.2) == 0.0);
7878}
7979
8080test "math.trunc32.special" {
81 assert(trunc32(0.0) == 0.0); // 0x3F800000
82 assert(trunc32(-0.0) == -0.0);
83 assert(math.isPositiveInf(trunc32(math.inf(f32))));
84 assert(math.isNegativeInf(trunc32(-math.inf(f32))));
85 assert(math.isNan(trunc32(math.nan(f32))));
81 expect(trunc32(0.0) == 0.0); // 0x3F800000
82 expect(trunc32(-0.0) == -0.0);
83 expect(math.isPositiveInf(trunc32(math.inf(f32))));
84 expect(math.isNegativeInf(trunc32(-math.inf(f32))));
85 expect(math.isNan(trunc32(math.nan(f32))));
8686}
8787
8888test "math.trunc64.special" {
89 assert(trunc64(0.0) == 0.0);
90 assert(trunc64(-0.0) == -0.0);
91 assert(math.isPositiveInf(trunc64(math.inf(f64))));
92 assert(math.isNegativeInf(trunc64(-math.inf(f64))));
93 assert(math.isNan(trunc64(math.nan(f64))));
89 expect(trunc64(0.0) == 0.0);
90 expect(trunc64(-0.0) == -0.0);
91 expect(math.isPositiveInf(trunc64(math.inf(f64))));
92 expect(math.isNegativeInf(trunc64(-math.inf(f64))));
93 expect(math.isNan(trunc64(math.nan(f64))));
9494}
std/mem.zig+526-278
......@@ -6,6 +6,7 @@ const builtin = @import("builtin");
66const mem = @This();
77const meta = std.meta;
88const trait = meta.trait;
9const testing = std.testing;
910
1011pub const Allocator = struct {
1112 pub const Error = error{OutOfMemory};
......@@ -36,20 +37,9 @@ pub const Allocator = struct {
3637 /// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn`
3738 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
5040 /// Call `destroy` with the result.
5141 /// 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 {
5343 if (@sizeOf(T) == 0) return &(T{});
5444 const slice = try self.alloc(T, 1);
5545 return &slice[0];
......@@ -192,7 +182,7 @@ test "mem.secureZero" {
192182 set(u8, a[0..], 0);
193183 secureZero(u8, b[0..]);
194184
195 assert(eql(u8, a[0..], b[0..]));
185 testing.expectEqualSlices(u8, a[0..], b[0..]);
196186}
197187
198188pub 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 {
221211}
222212
223213test "mem.compare" {
224 assert(compare(u8, "abcd", "bee") == Compare.LessThan);
225 assert(compare(u8, "abc", "abc") == Compare.Equal);
226 assert(compare(u8, "abc", "abc0") == Compare.LessThan);
227 assert(compare(u8, "", "") == Compare.Equal);
228 assert(compare(u8, "", "a") == Compare.LessThan);
214 testing.expect(compare(u8, "abcd", "bee") == Compare.LessThan);
215 testing.expect(compare(u8, "abc", "abc") == Compare.Equal);
216 testing.expect(compare(u8, "abc", "abc0") == Compare.LessThan);
217 testing.expect(compare(u8, "", "") == Compare.Equal);
218 testing.expect(compare(u8, "", "a") == Compare.LessThan);
229219}
230220
231221/// Returns true if lhs < rhs, false otherwise
......@@ -238,11 +228,11 @@ pub fn lessThan(comptime T: type, lhs: []const T, rhs: []const T) bool {
238228}
239229
240230test "mem.lessThan" {
241 assert(lessThan(u8, "abcd", "bee"));
242 assert(!lessThan(u8, "abc", "abc"));
243 assert(lessThan(u8, "abc", "abc0"));
244 assert(!lessThan(u8, "", ""));
245 assert(lessThan(u8, "", "a"));
231 testing.expect(lessThan(u8, "abcd", "bee"));
232 testing.expect(!lessThan(u8, "abc", "abc"));
233 testing.expect(lessThan(u8, "abc", "abc0"));
234 testing.expect(!lessThan(u8, "", ""));
235 testing.expect(lessThan(u8, "", "a"));
246236}
247237
248238/// 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
307297}
308298
309299test "mem.trim" {
310 assert(eql(u8, trimLeft(u8, " foo\n ", " \n"), "foo\n "));
311 assert(eql(u8, trimRight(u8, " foo\n ", " \n"), " foo"));
312 assert(eql(u8, trim(u8, " foo\n ", " \n"), "foo"));
313 assert(eql(u8, trim(u8, "foo", " \n"), "foo"));
300 testing.expectEqualSlices(u8, "foo\n ", trimLeft(u8, " foo\n ", " \n"));
301 testing.expectEqualSlices(u8, " foo", trimRight(u8, " foo\n ", " \n"));
302 testing.expectEqualSlices(u8, "foo", trim(u8, " foo\n ", " \n"));
303 testing.expectEqualSlices(u8, "foo", trim(u8, "foo", " \n"));
314304}
315305
316306/// 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
391381}
392382
393383test "mem.indexOf" {
394 assert(indexOf(u8, "one two three four", "four").? == 14);
395 assert(lastIndexOf(u8, "one two three two four", "two").? == 14);
396 assert(indexOf(u8, "one two three four", "gour") == null);
397 assert(lastIndexOf(u8, "one two three four", "gour") == null);
398 assert(indexOf(u8, "foo", "foo").? == 0);
399 assert(lastIndexOf(u8, "foo", "foo").? == 0);
400 assert(indexOf(u8, "foo", "fool") == null);
401 assert(lastIndexOf(u8, "foo", "lfoo") == null);
402 assert(lastIndexOf(u8, "foo", "fool") == null);
403
404 assert(indexOf(u8, "foo foo", "foo").? == 0);
405 assert(lastIndexOf(u8, "foo foo", "foo").? == 4);
406 assert(lastIndexOfAny(u8, "boo, cat", "abo").? == 6);
407 assert(lastIndexOfScalar(u8, "boo", 'o').? == 2);
384 testing.expect(indexOf(u8, "one two three four", "four").? == 14);
385 testing.expect(lastIndexOf(u8, "one two three two four", "two").? == 14);
386 testing.expect(indexOf(u8, "one two three four", "gour") == null);
387 testing.expect(lastIndexOf(u8, "one two three four", "gour") == null);
388 testing.expect(indexOf(u8, "foo", "foo").? == 0);
389 testing.expect(lastIndexOf(u8, "foo", "foo").? == 0);
390 testing.expect(indexOf(u8, "foo", "fool") == null);
391 testing.expect(lastIndexOf(u8, "foo", "lfoo") == null);
392 testing.expect(lastIndexOf(u8, "foo", "fool") == null);
393
394 testing.expect(indexOf(u8, "foo foo", "foo").? == 0);
395 testing.expect(lastIndexOf(u8, "foo foo", "foo").? == 4);
396 testing.expect(lastIndexOfAny(u8, "boo, cat", "abo").? == 6);
397 testing.expect(lastIndexOfScalar(u8, "boo", 'o').? == 2);
408398}
409399
410400/// Reads an integer from memory with size equal to bytes.len.
411401/// T specifies the return type, which must be large enough to store
412402/// the result.
413/// See also ::readIntBE or ::readIntLE.
414pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T {
415 if (T.bit_count == 8) {
416 return bytes[0];
417 }
418 var result: T = 0;
403pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: builtin.Endian) ReturnType {
404 var result: ReturnType = 0;
419405 switch (endian) {
420406 builtin.Endian.Big => {
421407 for (bytes) |b| {
......@@ -423,171 +409,262 @@ pub fn readInt(bytes: []const u8, comptime T: type, endian: builtin.Endian) T {
423409 }
424410 },
425411 builtin.Endian.Little => {
426 const ShiftType = math.Log2Int(T);
412 const ShiftType = math.Log2Int(ReturnType);
427413 for (bytes) |b, index| {
428 result = result | (T(b) << @intCast(ShiftType, index * 8));
414 result = result | (ReturnType(b) << @intCast(ShiftType, index * 8));
429415 }
430416 },
431417 }
432418 return result;
433419}
434420
435/// Reads a big-endian int of type T from bytes.
436/// bytes.len must be exactly @sizeOf(T).
437pub fn readIntBE(comptime T: type, bytes: []const u8) T {
438 if (T.is_signed) {
439 return @bitCast(T, readIntBE(@IntType(false, T.bit_count), bytes));
440 }
441 assert(bytes.len == @sizeOf(T));
442 if (T == u8) return bytes[0];
443 var result: T = 0;
444 {
445 comptime var i = 0;
446 inline while (i < @sizeOf(T)) : (i += 1) {
447 result = (result << 8) | T(bytes[i]);
448 }
421/// Reads an integer from memory with bit count specified by T.
422/// The bit count of T must be evenly divisible by 8.
423/// This function cannot fail and cannot cause undefined behavior.
424/// Assumes the endianness of memory is native. This means the function can
425/// simply pointer cast memory.
426pub fn readIntNative(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8) T {
427 return @ptrCast(*align(1) const T, bytes).*;
428}
429
430/// Reads an integer from memory with bit count specified by T.
431/// The bit count of T must be evenly divisible by 8.
432/// This function cannot fail and cannot cause undefined behavior.
433/// Assumes the endianness of memory is foreign, so it must byte-swap.
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);
449486 }
450 return result;
451487}
452488
453/// Reads a little-endian int of type T from bytes.
454/// bytes.len must be exactly @sizeOf(T).
455pub fn readIntLE(comptime T: type, bytes: []const u8) T {
456 if (T.is_signed) {
457 return @bitCast(T, readIntLE(@IntType(false, T.bit_count), bytes));
489/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0
490/// and ignores extra bytes.
491/// The bit count of T must be evenly divisible by 8.
492pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T {
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);
458505 }
459 assert(bytes.len == @sizeOf(T));
460 if (T == u8) return bytes[0];
461 var result: T = 0;
462 {
463 comptime var i = 0;
464 inline while (i < @sizeOf(T)) : (i += 1) {
465 result |= T(bytes[i]) << i * 8;
466 }
506 comptime {
507 var bytes: [2]u8 = undefined;
508 std.mem.writeIntBig(u16, &bytes, 0x1234);
509 const result = std.mem.readIntLittle(u16, &bytes);
510 testing.expect(result == 0x3412);
467511 }
468 return result;
469512}
470513
471test "readIntBE/LE" {
472 assert(readIntBE(u0, []u8{}) == 0x0);
473 assert(readIntLE(u0, []u8{}) == 0x0);
514test "readIntBig and readIntLittle" {
515 testing.expect(readIntSliceBig(u0, []u8{}) == 0x0);
516 testing.expect(readIntSliceLittle(u0, []u8{}) == 0x0);
474517
475 assert(readIntBE(u8, []u8{0x32}) == 0x32);
476 assert(readIntLE(u8, []u8{0x12}) == 0x12);
518 testing.expect(readIntSliceBig(u8, []u8{0x32}) == 0x32);
519 testing.expect(readIntSliceLittle(u8, []u8{0x12}) == 0x12);
477520
478 assert(readIntBE(u16, []u8{ 0x12, 0x34 }) == 0x1234);
479 assert(readIntLE(u16, []u8{ 0x12, 0x34 }) == 0x3412);
521 testing.expect(readIntSliceBig(u16, []u8{ 0x12, 0x34 }) == 0x1234);
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);
482 assert(readIntLE(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec);
524 testing.expect(readIntSliceBig(u72, []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }) == 0x123456789abcdef024);
525 testing.expect(readIntSliceLittle(u72, []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }) == 0xfedcba9876543210ec);
483526
484 assert(readIntBE(i8, []u8{0xff}) == -1);
485 assert(readIntLE(i8, []u8{0xfe}) == -2);
527 testing.expect(readIntSliceBig(i8, []u8{0xff}) == -1);
528 testing.expect(readIntSliceLittle(i8, []u8{0xfe}) == -2);
486529
487 assert(readIntBE(i16, []u8{ 0xff, 0xfd }) == -3);
488 assert(readIntLE(i16, []u8{ 0xfc, 0xff }) == -4);
530 testing.expect(readIntSliceBig(i16, []u8{ 0xff, 0xfd }) == -3);
531 testing.expect(readIntSliceLittle(i16, []u8{ 0xfc, 0xff }) == -4);
489532}
490533
491/// Writes an integer to memory with size equal to bytes.len. Pads with zeroes
492/// to fill the entire buffer provided.
493/// value must be an integer.
494pub fn writeInt(buf: []u8, value: var, endian: builtin.Endian) void {
495 const uint = @IntType(false, @typeOf(value).bit_count);
496 var bits = @truncate(uint, value);
497 switch (endian) {
498 builtin.Endian.Big => {
499 var index: usize = buf.len;
500 while (index != 0) {
501 index -= 1;
534/// Writes an integer to memory, storing it in twos-complement.
535/// This function always succeeds, has defined behavior for all inputs, and
536/// accepts any integer bit width.
537/// This function stores in native endian, which means it is implemented as a simple
538/// memory store.
539pub fn writeIntNative(comptime T: type, buf: *[(T.bit_count + 7) / 8]u8, value: T) void {
540 @ptrCast(*align(1) T, buf).* = value;
541}
502542
503 buf[index] = @truncate(u8, bits);
504 bits >>= 8;
505 }
506 },
507 builtin.Endian.Little => {
508 for (buf) |*b| {
509 b.* = @truncate(u8, bits);
510 bits >>= 8;
511 }
512 },
543/// Writes an integer to memory, storing it in twos-complement.
544/// This function always succeeds, has defined behavior for all inputs, but
545/// the integer bit width must be divisible by 8.
546/// This function stores in foreign endian, which means it does a @bswap first.
547pub fn writeIntForeign(comptime T: type, buf: *[@divExact(T.bit_count, 8)]u8, value: T) void {
548 writeIntNative(T, buf, @bswap(T, value));
549}
550
551pub const writeIntLittle = switch (builtin.endian) {
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);
513569 }
514 assert(bits == 0);
515570}
516571
517pub fn writeIntBE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
518 assert(T.bit_count % 8 == 0);
572/// Writes a twos-complement little-endian integer to memory.
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
519582 const uint = @IntType(false, T.bit_count);
520 if (uint == u0) {
521 return;
522 }
523 var bits = @bitCast(uint, value);
524 if (uint == u8) {
525 buf[0] = bits;
526 return;
583 var bits = @truncate(uint, value);
584 for (buffer) |*b| {
585 b.* = @truncate(u8, bits);
586 bits >>= 8;
527587 }
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;
529602 while (index != 0) {
530603 index -= 1;
531
532 buf[index] = @truncate(u8, bits);
604 buffer[index] = @truncate(u8, bits);
533605 bits >>= 8;
534606 }
535 assert(bits == 0);
536607}
537608
538pub fn writeIntLE(comptime T: type, buf: *[@sizeOf(T)]u8, value: T) void {
539 assert(T.bit_count % 8 == 0);
540 const uint = @IntType(false, T.bit_count);
541 if (uint == u0) {
542 return;
543 }
544 var bits = @bitCast(uint, value);
545 if (uint == u8) {
546 buf[0] = bits;
547 return;
548 }
549 for (buf) |*b| {
550 b.* = @truncate(u8, bits);
551 bits >>= 8;
609pub const writeIntSliceNative = switch (builtin.endian) {
610 builtin.Endian.Little => writeIntSliceLittle,
611 builtin.Endian.Big => writeIntSliceBig,
612};
613
614pub const writeIntSliceForeign = switch (builtin.endian) {
615 builtin.Endian.Little => writeIntSliceBig,
616 builtin.Endian.Big => writeIntSliceLittle,
617};
618
619/// Writes a twos-complement integer to memory, with the specified endianness.
620/// Asserts that buf.len >= T.bit_count / 8.
621/// The bit count of T must be evenly divisible by 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),
552630 }
553 assert(bits == 0);
554631}
555632
556test "writeIntBE/LE" {
633test "writeIntBig and writeIntLittle" {
557634 var buf0: [0]u8 = undefined;
558635 var buf1: [1]u8 = undefined;
559636 var buf2: [2]u8 = undefined;
560637 var buf9: [9]u8 = undefined;
561638
562 writeIntBE(u0, &buf0, 0x0);
563 assert(eql_slice_u8(buf0[0..], []u8{}));
564 writeIntLE(u0, &buf0, 0x0);
565 assert(eql_slice_u8(buf0[0..], []u8{}));
639 writeIntBig(u0, &buf0, 0x0);
640 testing.expect(eql_slice_u8(buf0[0..], []u8{}));
641 writeIntLittle(u0, &buf0, 0x0);
642 testing.expect(eql_slice_u8(buf0[0..], []u8{}));
566643
567 writeIntBE(u8, &buf1, 0x12);
568 assert(eql_slice_u8(buf1[0..], []u8{0x12}));
569 writeIntLE(u8, &buf1, 0x34);
570 assert(eql_slice_u8(buf1[0..], []u8{0x34}));
644 writeIntBig(u8, &buf1, 0x12);
645 testing.expect(eql_slice_u8(buf1[0..], []u8{0x12}));
646 writeIntLittle(u8, &buf1, 0x34);
647 testing.expect(eql_slice_u8(buf1[0..], []u8{0x34}));
571648
572 writeIntBE(u16, &buf2, 0x1234);
573 assert(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 }));
574 writeIntLE(u16, &buf2, 0x5678);
575 assert(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 }));
649 writeIntBig(u16, &buf2, 0x1234);
650 testing.expect(eql_slice_u8(buf2[0..], []u8{ 0x12, 0x34 }));
651 writeIntLittle(u16, &buf2, 0x5678);
652 testing.expect(eql_slice_u8(buf2[0..], []u8{ 0x78, 0x56 }));
576653
577 writeIntBE(u72, &buf9, 0x123456789abcdef024);
578 assert(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }));
579 writeIntLE(u72, &buf9, 0xfedcba9876543210ec);
580 assert(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }));
654 writeIntBig(u72, &buf9, 0x123456789abcdef024);
655 testing.expect(eql_slice_u8(buf9[0..], []u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }));
656 writeIntLittle(u72, &buf9, 0xfedcba9876543210ec);
657 testing.expect(eql_slice_u8(buf9[0..], []u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }));
581658
582 writeIntBE(i8, &buf1, -1);
583 assert(eql_slice_u8(buf1[0..], []u8{0xff}));
584 writeIntLE(i8, &buf1, -2);
585 assert(eql_slice_u8(buf1[0..], []u8{0xfe}));
659 writeIntBig(i8, &buf1, -1);
660 testing.expect(eql_slice_u8(buf1[0..], []u8{0xff}));
661 writeIntLittle(i8, &buf1, -2);
662 testing.expect(eql_slice_u8(buf1[0..], []u8{0xfe}));
586663
587 writeIntBE(i16, &buf2, -3);
588 assert(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd }));
589 writeIntLE(i16, &buf2, -4);
590 assert(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff }));
664 writeIntBig(i16, &buf2, -3);
665 testing.expect(eql_slice_u8(buf2[0..], []u8{ 0xff, 0xfd }));
666 writeIntLittle(i16, &buf2, -4);
667 testing.expect(eql_slice_u8(buf2[0..], []u8{ 0xfc, 0xff }));
591668}
592669
593670pub fn hash_slice_u8(k: []const u8) u32 {
......@@ -604,23 +681,114 @@ pub fn eql_slice_u8(a: []const u8, b: []const u8) bool {
604681}
605682
606683/// Returns an iterator that iterates over the slices of `buffer` that are not
607/// any of the bytes in `split_bytes`.
608/// split(" abc def ghi ", " ")
684/// any of the bytes in `delimiter_bytes`.
685/// tokenize(" abc def ghi ", " ")
609686/// 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);
611755 return SplitIterator{
612756 .index = 0,
613757 .buffer = buffer,
614 .split_bytes = split_bytes,
758 .delimiter = delimiter,
615759 };
616760}
617761
618test "mem.split" {
619 var it = split(" abc def ghi ", " ");
620 assert(eql(u8, it.next().?, "abc"));
621 assert(eql(u8, it.next().?, "def"));
622 assert(eql(u8, it.next().?, "ghi"));
623 assert(it.next() == null);
762test "mem.separate" {
763 var it = separate("abc|def||ghi", "|");
764 testing.expect(eql(u8, it.next().?, "abc"));
765 testing.expect(eql(u8, it.next().?, "def"));
766 testing.expect(eql(u8, it.next().?, ""));
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);
624792}
625793
626794pub 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
628796}
629797
630798test "mem.startsWith" {
631 assert(startsWith(u8, "Bob", "Bo"));
632 assert(!startsWith(u8, "Needle in haystack", "haystack"));
799 testing.expect(startsWith(u8, "Bob", "Bo"));
800 testing.expect(!startsWith(u8, "Needle in haystack", "haystack"));
633801}
634802
635803pub 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 {
637805}
638806
639807test "mem.endsWith" {
640 assert(endsWith(u8, "Needle in haystack", "haystack"));
641 assert(!endsWith(u8, "Bob", "Bo"));
808 testing.expect(endsWith(u8, "Needle in haystack", "haystack"));
809 testing.expect(!endsWith(u8, "Bob", "Bo"));
642810}
643811
644pub const SplitIterator = struct {
812pub const TokenIterator = struct {
645813 buffer: []const u8,
646 split_bytes: []const u8,
814 delimiter_bytes: []const u8,
647815 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 {
650819 // move to beginning of token
651820 while (self.index < self.buffer.len and self.isSplitByte(self.buffer[self.index])) : (self.index += 1) {}
652821 const start = self.index;
......@@ -662,16 +831,16 @@ pub const SplitIterator = struct {
662831 }
663832
664833 /// 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 {
666835 // move to beginning of token
667836 var index: usize = self.index;
668837 while (index < self.buffer.len and self.isSplitByte(self.buffer[index])) : (index += 1) {}
669838 return self.buffer[index..];
670839 }
671840
672 fn isSplitByte(self: *const SplitIterator, byte: u8) bool {
673 for (self.split_bytes) |split_byte| {
674 if (byte == split_byte) {
841 fn isSplitByte(self: TokenIterator, byte: u8) bool {
842 for (self.delimiter_bytes) |delimiter_byte| {
843 if (byte == delimiter_byte) {
675844 return true;
676845 }
677846 }
......@@ -679,48 +848,72 @@ pub const SplitIterator = struct {
679848 }
680849};
681850
682/// Naively combines a series of strings with a separator.
683/// Allocates memory for the result, which must be freed by the caller.
684pub fn join(allocator: *Allocator, sep: u8, strings: ...) ![]u8 {
685 comptime assert(strings.len >= 1);
686 var total_strings_len: usize = strings.len; // 1 sep per string
687 {
688 comptime var string_i = 0;
689 inline while (string_i < strings.len) : (string_i += 1) {
690 const arg = ([]const u8)(strings[string_i]);
691 total_strings_len += arg.len;
692 }
851pub const SplitIterator = struct {
852 buffer: []const u8,
853 index: ?usize,
854 delimiter: []const u8,
855
856 /// Returns a slice of the next field, or null if splitting is complete.
857 pub fn next(self: *SplitIterator) ?[]const u8 {
858 const start = self.index orelse return null;
859 const end = if (indexOfPos(u8, self.buffer, start, self.delimiter)) |delim_start| blk: {
860 self.index = delim_start + self.delimiter.len;
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];
693867 }
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);
696890 errdefer allocator.free(buf);
697891
698 var buf_index: usize = 0;
699 comptime var string_i = 0;
700 inline while (true) {
701 const arg = ([]const u8)(strings[string_i]);
702 string_i += 1;
703 copy(u8, buf[buf_index..], arg);
704 buf_index += arg.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 }
892 copy(u8, buf, slices[0]);
893 var buf_index: usize = slices[0].len;
894 for (slices[1..]) |slice| {
895 copy(u8, buf[buf_index..], separator);
896 buf_index += separator.len;
897 copy(u8, buf[buf_index..], slice);
898 buf_index += slice.len;
710899 }
711900
712 return allocator.shrink(u8, buf, buf_index);
901 // No need for shrink since buf is exactly the correct size.
902 return buf;
713903}
714904
715905test "mem.join" {
716 assert(eql(u8, try join(debug.global_allocator, ',', "a", "b", "c"), "a,b,c"));
717 assert(eql(u8, try join(debug.global_allocator, ',', "a"), "a"));
906 var buf: [1024]u8 = undefined;
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"));
718911}
719912
720913test "testStringEquality" {
721 assert(eql(u8, "abcd", "abcd"));
722 assert(!eql(u8, "abcdef", "abZdef"));
723 assert(!eql(u8, "abcdefg", "abcdef"));
914 testing.expect(eql(u8, "abcd", "abcd"));
915 testing.expect(!eql(u8, "abcdef", "abZdef"));
916 testing.expect(!eql(u8, "abcdefg", "abcdef"));
724917}
725918
726919test "testReadInt" {
......@@ -735,12 +928,12 @@ fn testReadIntImpl() void {
735928 0x56,
736929 0x78,
737930 };
738 assert(readInt(bytes, u32, builtin.Endian.Big) == 0x12345678);
739 assert(readIntBE(u32, bytes) == 0x12345678);
740 assert(readIntBE(i32, bytes) == 0x12345678);
741 assert(readInt(bytes, u32, builtin.Endian.Little) == 0x78563412);
742 assert(readIntLE(u32, bytes) == 0x78563412);
743 assert(readIntLE(i32, bytes) == 0x78563412);
931 testing.expect(readInt(u32, &bytes, builtin.Endian.Big) == 0x12345678);
932 testing.expect(readIntBig(u32, &bytes) == 0x12345678);
933 testing.expect(readIntBig(i32, &bytes) == 0x12345678);
934 testing.expect(readInt(u32, &bytes, builtin.Endian.Little) == 0x78563412);
935 testing.expect(readIntLittle(u32, &bytes) == 0x78563412);
936 testing.expect(readIntLittle(i32, &bytes) == 0x78563412);
744937 }
745938 {
746939 const buf = []u8{
......@@ -749,8 +942,8 @@ fn testReadIntImpl() void {
749942 0x12,
750943 0x34,
751944 };
752 const answer = readInt(buf, u64, builtin.Endian.Big);
753 assert(answer == 0x00001234);
945 const answer = readInt(u32, &buf, builtin.Endian.Big);
946 testing.expect(answer == 0x00001234);
754947 }
755948 {
756949 const buf = []u8{
......@@ -759,30 +952,42 @@ fn testReadIntImpl() void {
759952 0x00,
760953 0x00,
761954 };
762 const answer = readInt(buf, u64, builtin.Endian.Little);
763 assert(answer == 0x00003412);
955 const answer = readInt(u32, &buf, builtin.Endian.Little);
956 testing.expect(answer == 0x00003412);
764957 }
765958 {
766959 const bytes = []u8{
767960 0xff,
768961 0xfe,
769962 };
770 assert(readIntBE(u16, bytes) == 0xfffe);
771 assert(readIntBE(i16, bytes) == -0x0002);
772 assert(readIntLE(u16, bytes) == 0xfeff);
773 assert(readIntLE(i16, bytes) == -0x0101);
963 testing.expect(readIntBig(u16, &bytes) == 0xfffe);
964 testing.expect(readIntBig(i16, &bytes) == -0x0002);
965 testing.expect(readIntLittle(u16, &bytes) == 0xfeff);
966 testing.expect(readIntLittle(i16, &bytes) == -0x0101);
774967 }
775968}
776969
777test "testWriteInt" {
970test "std.mem.writeIntSlice" {
778971 testWriteIntImpl();
779972 comptime testWriteIntImpl();
780973}
781974fn testWriteIntImpl() void {
782975 var bytes: [8]u8 = undefined;
783976
784 writeInt(bytes[0..], u64(0x12345678CAFEBABE), builtin.Endian.Big);
785 assert(eql(u8, bytes, []u8{
977 writeIntSlice(u0, bytes[0..], 0, builtin.Endian.Big);
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{
786991 0x12,
787992 0x34,
788993 0x56,
......@@ -793,8 +998,8 @@ fn testWriteIntImpl() void {
793998 0xBE,
794999 }));
7951000
796 writeInt(bytes[0..], u64(0xBEBAFECA78563412), builtin.Endian.Little);
797 assert(eql(u8, bytes, []u8{
1001 writeIntSlice(u64, bytes[0..], 0xBEBAFECA78563412, builtin.Endian.Little);
1002 testing.expect(eql(u8, bytes, []u8{
7981003 0x12,
7991004 0x34,
8001005 0x56,
......@@ -805,8 +1010,8 @@ fn testWriteIntImpl() void {
8051010 0xBE,
8061011 }));
8071012
808 writeInt(bytes[0..], u32(0x12345678), builtin.Endian.Big);
809 assert(eql(u8, bytes, []u8{
1013 writeIntSlice(u32, bytes[0..], 0x12345678, builtin.Endian.Big);
1014 testing.expect(eql(u8, bytes, []u8{
8101015 0x00,
8111016 0x00,
8121017 0x00,
......@@ -817,8 +1022,8 @@ fn testWriteIntImpl() void {
8171022 0x78,
8181023 }));
8191024
820 writeInt(bytes[0..], u32(0x78563412), builtin.Endian.Little);
821 assert(eql(u8, bytes, []u8{
1025 writeIntSlice(u32, bytes[0..], 0x78563412, builtin.Endian.Little);
1026 testing.expect(eql(u8, bytes, []u8{
8221027 0x12,
8231028 0x34,
8241029 0x56,
......@@ -829,8 +1034,8 @@ fn testWriteIntImpl() void {
8291034 0x00,
8301035 }));
8311036
832 writeInt(bytes[0..], u16(0x1234), builtin.Endian.Big);
833 assert(eql(u8, bytes, []u8{
1037 writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Big);
1038 testing.expect(eql(u8, bytes, []u8{
8341039 0x00,
8351040 0x00,
8361041 0x00,
......@@ -841,8 +1046,8 @@ fn testWriteIntImpl() void {
8411046 0x34,
8421047 }));
8431048
844 writeInt(bytes[0..], u16(0x1234), builtin.Endian.Little);
845 assert(eql(u8, bytes, []u8{
1049 writeIntSlice(u16, bytes[0..], 0x1234, builtin.Endian.Little);
1050 testing.expect(eql(u8, bytes, []u8{
8461051 0x34,
8471052 0x12,
8481053 0x00,
......@@ -863,7 +1068,7 @@ pub fn min(comptime T: type, slice: []const T) T {
8631068}
8641069
8651070test "mem.min" {
866 assert(min(u8, "abcdefg") == 'a');
1071 testing.expect(min(u8, "abcdefg") == 'a');
8671072}
8681073
8691074pub fn max(comptime T: type, slice: []const T) T {
......@@ -875,7 +1080,7 @@ pub fn max(comptime T: type, slice: []const T) T {
8751080}
8761081
8771082test "mem.max" {
878 assert(max(u8, "abcdefg") == 'g');
1083 testing.expect(max(u8, "abcdefg") == 'g');
8791084}
8801085
8811086pub fn swap(comptime T: type, a: *T, b: *T) void {
......@@ -903,7 +1108,7 @@ test "std.mem.reverse" {
9031108 };
9041109 reverse(i32, arr[0..]);
9051110
906 assert(eql(i32, arr, []i32{
1111 testing.expect(eql(i32, arr, []i32{
9071112 4,
9081113 2,
9091114 1,
......@@ -930,7 +1135,7 @@ test "std.mem.rotate" {
9301135 };
9311136 rotate(i32, arr[0..], 2);
9321137
933 assert(eql(i32, arr, []i32{
1138 testing.expect(eql(i32, arr, []i32{
9341139 1,
9351140 2,
9361141 4,
......@@ -939,29 +1144,52 @@ test "std.mem.rotate" {
9391144 }));
9401145}
9411146
942// TODO: When https://github.com/ziglang/zig/issues/649 is solved these can be done by
943// endian-casting the pointer and then dereferencing
1147/// Converts a little-endian integer to host endianness.
1148pub 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 {
946 return endianSwapIf(builtin.Endian.Little, T, x);
1155/// Converts a big-endian integer to host endianness.
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 };
9471161}
9481162
949pub fn endianSwapIfBe(comptime T: type, x: T) T {
950 return endianSwapIf(builtin.Endian.Big, T, x);
1163/// Converts an integer from specified endianness to host endianness.
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 };
9511169}
9521170
953pub fn endianSwapIf(endian: builtin.Endian, comptime T: type, x: T) T {
954 return if (builtin.endian == endian) endianSwap(T, x) else x;
1171/// Converts an integer which has host endianness to the desired endianness.
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 };
9551177}
9561178
957pub fn endianSwap(comptime T: type, x: T) T {
958 var buf: [@sizeOf(T)]u8 = undefined;
959 mem.writeInt(buf[0..], x, builtin.Endian.Little);
960 return mem.readInt(buf, T, builtin.Endian.Big);
1179/// Converts an integer which has host endianness to little endian.
1180pub fn nativeToLittle(comptime T: type, x: T) T {
1181 return switch (builtin.endian) {
1182 builtin.Endian.Little => x,
1183 builtin.Endian.Big => @bswap(T, x),
1184 };
9611185}
9621186
963test "std.mem.endianSwap" {
964 assert(endianSwap(u32, 0xDEADBEEF) == 0xEFBEADDE);
1187/// Converts an integer which has host endianness to big endian.
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 };
9651193}
9661194
9671195fn AsBytesReturnType(comptime P: type) type {
......@@ -989,12 +1217,12 @@ test "std.mem.asBytes" {
9891217 builtin.Endian.Little => "\xEF\xBE\xAD\xDE",
9901218 };
9911219
992 debug.assert(std.mem.eql(u8, asBytes(&deadbeef), deadbeef_bytes));
1220 testing.expect(std.mem.eql(u8, asBytes(&deadbeef), deadbeef_bytes));
9931221
9941222 var codeface = u32(0xC0DEFACE);
9951223 for (asBytes(&codeface).*) |*b|
9961224 b.* = 0;
997 debug.assert(codeface == 0);
1225 testing.expect(codeface == 0);
9981226
9991227 const S = packed struct {
10001228 a: u8,
......@@ -1009,7 +1237,7 @@ test "std.mem.asBytes" {
10091237 .c = 0xDE,
10101238 .d = 0xA1,
10111239 };
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"));
10131241}
10141242
10151243///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 {
10201248test "std.mem.toBytes" {
10211249 var my_bytes = toBytes(u32(0x12345678));
10221250 switch (builtin.endian) {
1023 builtin.Endian.Big => debug.assert(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")),
1251 builtin.Endian.Big => testing.expect(std.mem.eql(u8, my_bytes, "\x12\x34\x56\x78")),
1252 builtin.Endian.Little => testing.expect(std.mem.eql(u8, my_bytes, "\x78\x56\x34\x12")),
10251253 }
10261254
10271255 my_bytes[0] = '\x99';
10281256 switch (builtin.endian) {
1029 builtin.Endian.Big => debug.assert(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")),
1257 builtin.Endian.Big => testing.expect(std.mem.eql(u8, my_bytes, "\x99\x34\x56\x78")),
1258 builtin.Endian.Little => testing.expect(std.mem.eql(u8, my_bytes, "\x99\x56\x34\x12")),
10311259 }
10321260}
10331261
......@@ -1056,17 +1284,17 @@ test "std.mem.bytesAsValue" {
10561284 builtin.Endian.Little => "\xEF\xBE\xAD\xDE",
10571285 };
10581286
1059 debug.assert(deadbeef == bytesAsValue(u32, &deadbeef_bytes).*);
1287 testing.expect(deadbeef == bytesAsValue(u32, &deadbeef_bytes).*);
10601288
10611289 var codeface_bytes = switch (builtin.endian) {
10621290 builtin.Endian.Big => "\xC0\xDE\xFA\xCE",
10631291 builtin.Endian.Little => "\xCE\xFA\xDE\xC0",
10641292 };
10651293 var codeface = bytesAsValue(u32, &codeface_bytes);
1066 debug.assert(codeface.* == 0xC0DEFACE);
1294 testing.expect(codeface.* == 0xC0DEFACE);
10671295 codeface.* = 0;
10681296 for (codeface_bytes) |b|
1069 debug.assert(b == 0);
1297 testing.expect(b == 0);
10701298
10711299 const S = packed struct {
10721300 a: u8,
......@@ -1083,7 +1311,7 @@ test "std.mem.bytesAsValue" {
10831311 };
10841312 const inst_bytes = "\xBE\xEF\xDE\xA1";
10851313 const inst2 = bytesAsValue(S, &inst_bytes);
1086 debug.assert(meta.eql(inst, inst2.*));
1314 testing.expect(meta.eql(inst, inst2.*));
10871315}
10881316
10891317///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" {
10981326 };
10991327
11001328 const deadbeef = bytesToValue(u32, deadbeef_bytes);
1101 debug.assert(deadbeef == u32(0xDEADBEEF));
1329 testing.expect(deadbeef == u32(0xDEADBEEF));
11021330}
11031331
11041332fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type {
......@@ -1109,7 +1337,7 @@ fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type {
11091337
11101338///Given a pointer to an array, returns a pointer to a portion of that array, preserving constness.
11111339pub 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
11141342 const ReturnType = SubArrayPtrReturnType(@typeOf(ptr), length);
11151343 const T = meta.Child(meta.Child(@typeOf(ptr)));
......@@ -1119,12 +1347,32 @@ pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubA
11191347test "std.mem.subArrayPtr" {
11201348 const a1 = "abcdef";
11211349 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
11241352 var a2 = "abcdef";
11251353 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"));
11281356 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);
11301378}
std/meta/index.zig+112-76
......@@ -3,6 +3,7 @@ const builtin = @import("builtin");
33const debug = std.debug;
44const mem = std.mem;
55const math = std.math;
6const testing = std.testing;
67
78pub const trait = @import("trait.zig");
89
......@@ -64,16 +65,16 @@ test "std.meta.tagName" {
6465 var u2a = U2{ .C = 0 };
6566 var u2b = U2{ .D = 0 };
6667
67 debug.assert(mem.eql(u8, tagName(E1.A), "A"));
68 debug.assert(mem.eql(u8, tagName(E1.B), "B"));
69 debug.assert(mem.eql(u8, tagName(E2.C), "C"));
70 debug.assert(mem.eql(u8, tagName(E2.D), "D"));
71 debug.assert(mem.eql(u8, tagName(error.E), "E"));
72 debug.assert(mem.eql(u8, tagName(error.F), "F"));
73 debug.assert(mem.eql(u8, tagName(u1g), "G"));
74 debug.assert(mem.eql(u8, tagName(u1h), "H"));
75 debug.assert(mem.eql(u8, tagName(u2a), "C"));
76 debug.assert(mem.eql(u8, tagName(u2b), "D"));
68 testing.expect(mem.eql(u8, tagName(E1.A), "A"));
69 testing.expect(mem.eql(u8, tagName(E1.B), "B"));
70 testing.expect(mem.eql(u8, tagName(E2.C), "C"));
71 testing.expect(mem.eql(u8, tagName(E2.D), "D"));
72 testing.expect(mem.eql(u8, tagName(error.E), "E"));
73 testing.expect(mem.eql(u8, tagName(error.F), "F"));
74 testing.expect(mem.eql(u8, tagName(u1g), "G"));
75 testing.expect(mem.eql(u8, tagName(u1h), "H"));
76 testing.expect(mem.eql(u8, tagName(u2a), "C"));
77 testing.expect(mem.eql(u8, tagName(u2b), "D"));
7778}
7879
7980pub fn stringToEnum(comptime T: type, str: []const u8) ?T {
......@@ -90,12 +91,12 @@ test "std.meta.stringToEnum" {
9091 A,
9192 B,
9293 };
93 debug.assert(E1.A == stringToEnum(E1, "A").?);
94 debug.assert(E1.B == stringToEnum(E1, "B").?);
95 debug.assert(null == stringToEnum(E1, "C"));
94 testing.expect(E1.A == stringToEnum(E1, "A").?);
95 testing.expect(E1.B == stringToEnum(E1, "B").?);
96 testing.expect(null == stringToEnum(E1, "C"));
9697}
9798
98pub fn bitCount(comptime T: type) u32 {
99pub fn bitCount(comptime T: type) comptime_int {
99100 return switch (@typeInfo(T)) {
100101 TypeId.Int => |info| info.bits,
101102 TypeId.Float => |info| info.bits,
......@@ -104,22 +105,22 @@ pub fn bitCount(comptime T: type) u32 {
104105}
105106
106107test "std.meta.bitCount" {
107 debug.assert(bitCount(u8) == 8);
108 debug.assert(bitCount(f32) == 32);
108 testing.expect(bitCount(u8) == 8);
109 testing.expect(bitCount(f32) == 32);
109110}
110111
111pub fn alignment(comptime T: type) u29 {
112pub fn alignment(comptime T: type) comptime_int {
112113 //@alignOf works on non-pointer types
113114 const P = if (comptime trait.is(TypeId.Pointer)(T)) T else *T;
114115 return @typeInfo(P).Pointer.alignment;
115116}
116117
117118test "std.meta.alignment" {
118 debug.assert(alignment(u8) == 1);
119 debug.assert(alignment(*align(1) u8) == 1);
120 debug.assert(alignment(*align(2) u8) == 2);
121 debug.assert(alignment([]align(1) u8) == 1);
122 debug.assert(alignment([]align(2) u8) == 2);
119 testing.expect(alignment(u8) == 1);
120 testing.expect(alignment(*align(1) u8) == 1);
121 testing.expect(alignment(*align(2) u8) == 2);
122 testing.expect(alignment([]align(1) u8) == 1);
123 testing.expect(alignment([]align(2) u8) == 2);
123124}
124125
125126pub fn Child(comptime T: type) type {
......@@ -133,11 +134,11 @@ pub fn Child(comptime T: type) type {
133134}
134135
135136test "std.meta.Child" {
136 debug.assert(Child([1]u8) == u8);
137 debug.assert(Child(*u8) == u8);
138 debug.assert(Child([]u8) == u8);
139 debug.assert(Child(?u8) == u8);
140 debug.assert(Child(promise->u8) == u8);
137 testing.expect(Child([1]u8) == u8);
138 testing.expect(Child(*u8) == u8);
139 testing.expect(Child([]u8) == u8);
140 testing.expect(Child(?u8) == u8);
141 testing.expect(Child(promise->u8) == u8);
141142}
142143
143144pub fn containerLayout(comptime T: type) TypeInfo.ContainerLayout {
......@@ -172,15 +173,15 @@ test "std.meta.containerLayout" {
172173 a: u8,
173174 };
174175
175 debug.assert(containerLayout(E1) == TypeInfo.ContainerLayout.Auto);
176 debug.assert(containerLayout(E2) == TypeInfo.ContainerLayout.Packed);
177 debug.assert(containerLayout(E3) == TypeInfo.ContainerLayout.Extern);
178 debug.assert(containerLayout(S1) == TypeInfo.ContainerLayout.Auto);
179 debug.assert(containerLayout(S2) == TypeInfo.ContainerLayout.Packed);
180 debug.assert(containerLayout(S3) == TypeInfo.ContainerLayout.Extern);
181 debug.assert(containerLayout(U1) == TypeInfo.ContainerLayout.Auto);
182 debug.assert(containerLayout(U2) == TypeInfo.ContainerLayout.Packed);
183 debug.assert(containerLayout(U3) == TypeInfo.ContainerLayout.Extern);
176 testing.expect(containerLayout(E1) == TypeInfo.ContainerLayout.Auto);
177 testing.expect(containerLayout(E2) == TypeInfo.ContainerLayout.Packed);
178 testing.expect(containerLayout(E3) == TypeInfo.ContainerLayout.Extern);
179 testing.expect(containerLayout(S1) == TypeInfo.ContainerLayout.Auto);
180 testing.expect(containerLayout(S2) == TypeInfo.ContainerLayout.Packed);
181 testing.expect(containerLayout(S3) == TypeInfo.ContainerLayout.Extern);
182 testing.expect(containerLayout(U1) == TypeInfo.ContainerLayout.Auto);
183 testing.expect(containerLayout(U2) == TypeInfo.ContainerLayout.Packed);
184 testing.expect(containerLayout(U3) == TypeInfo.ContainerLayout.Extern);
184185}
185186
186187pub fn definitions(comptime T: type) []TypeInfo.Definition {
......@@ -214,8 +215,8 @@ test "std.meta.definitions" {
214215 };
215216
216217 inline for (defs) |def| {
217 debug.assert(def.len == 1);
218 debug.assert(comptime mem.eql(u8, def[0].name, "a"));
218 testing.expect(def.len == 1);
219 testing.expect(comptime mem.eql(u8, def[0].name, "a"));
219220 }
220221}
221222
......@@ -250,8 +251,8 @@ test "std.meta.definitionInfo" {
250251 };
251252
252253 inline for (infos) |info| {
253 debug.assert(comptime mem.eql(u8, info.name, "a"));
254 debug.assert(!info.is_pub);
254 testing.expect(comptime mem.eql(u8, info.name, "a"));
255 testing.expect(!info.is_pub);
255256 }
256257}
257258
......@@ -288,16 +289,16 @@ test "std.meta.fields" {
288289 const sf = comptime fields(S1);
289290 const uf = comptime fields(U1);
290291
291 debug.assert(e1f.len == 1);
292 debug.assert(e2f.len == 1);
293 debug.assert(sf.len == 1);
294 debug.assert(uf.len == 1);
295 debug.assert(mem.eql(u8, e1f[0].name, "A"));
296 debug.assert(mem.eql(u8, e2f[0].name, "A"));
297 debug.assert(mem.eql(u8, sf[0].name, "a"));
298 debug.assert(mem.eql(u8, uf[0].name, "a"));
299 debug.assert(comptime sf[0].field_type == u8);
300 debug.assert(comptime uf[0].field_type == u8);
292 testing.expect(e1f.len == 1);
293 testing.expect(e2f.len == 1);
294 testing.expect(sf.len == 1);
295 testing.expect(uf.len == 1);
296 testing.expect(mem.eql(u8, e1f[0].name, "A"));
297 testing.expect(mem.eql(u8, e2f[0].name, "A"));
298 testing.expect(mem.eql(u8, sf[0].name, "a"));
299 testing.expect(mem.eql(u8, uf[0].name, "a"));
300 testing.expect(comptime sf[0].field_type == u8);
301 testing.expect(comptime uf[0].field_type == u8);
301302}
302303
303304pub fn fieldInfo(comptime T: type, comptime field_name: []const u8) switch (@typeInfo(T)) {
......@@ -332,12 +333,12 @@ test "std.meta.fieldInfo" {
332333 const sf = comptime fieldInfo(S1, "a");
333334 const uf = comptime fieldInfo(U1, "a");
334335
335 debug.assert(mem.eql(u8, e1f.name, "A"));
336 debug.assert(mem.eql(u8, e2f.name, "A"));
337 debug.assert(mem.eql(u8, sf.name, "a"));
338 debug.assert(mem.eql(u8, uf.name, "a"));
339 debug.assert(comptime sf.field_type == u8);
340 debug.assert(comptime uf.field_type == u8);
336 testing.expect(mem.eql(u8, e1f.name, "A"));
337 testing.expect(mem.eql(u8, e2f.name, "A"));
338 testing.expect(mem.eql(u8, sf.name, "a"));
339 testing.expect(mem.eql(u8, uf.name, "a"));
340 testing.expect(comptime sf.field_type == u8);
341 testing.expect(comptime uf.field_type == u8);
341342}
342343
343344pub fn TagType(comptime T: type) type {
......@@ -358,8 +359,8 @@ test "std.meta.TagType" {
358359 D: u16,
359360 };
360361
361 debug.assert(TagType(E) == u8);
362 debug.assert(TagType(U) == E);
362 testing.expect(TagType(E) == u8);
363 testing.expect(TagType(U) == E);
363364}
364365
365366///Returns the active tag of a tagged union
......@@ -380,10 +381,37 @@ test "std.meta.activeTag" {
380381 };
381382
382383 var u = U{ .Int = 32 };
383 debug.assert(activeTag(u) == UE.Int);
384 testing.expect(activeTag(u) == UE.Int);
384385
385386 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));
387415}
388416
389417///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 {
435463 builtin.TypeId.Pointer => {
436464 const info = @typeInfo(T).Pointer;
437465 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,
439470 builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len,
440471 }
441472 },
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 },
442478 else => return a == b,
443479 }
444480}
......@@ -452,7 +488,7 @@ test "std.meta.eql" {
452488
453489 const U = union(enum) {
454490 s: S,
455 f: f32,
491 f: ?f32,
456492 };
457493
458494 const s_1 = S{
......@@ -477,19 +513,19 @@ test "std.meta.eql" {
477513 const u_2 = U{ .s = s_1 };
478514 const u_3 = U{ .f = 24 };
479515
480 debug.assert(eql(s_1, s_3));
481 debug.assert(eql(&s_1, &s_1));
482 debug.assert(!eql(&s_1, &s_3));
483 debug.assert(eql(u_1, u_3));
484 debug.assert(!eql(u_1, u_2));
516 testing.expect(eql(s_1, s_3));
517 testing.expect(eql(&s_1, &s_1));
518 testing.expect(!eql(&s_1, &s_3));
519 testing.expect(eql(u_1, u_3));
520 testing.expect(!eql(u_1, u_2));
485521
486522 var a1 = "abcdef";
487523 var a2 = "abcdef";
488524 var a3 = "ghijkl";
489525
490 debug.assert(eql(a1, a2));
491 debug.assert(!eql(a1, a3));
492 debug.assert(!eql(a1[0..], a2[0..]));
526 testing.expect(eql(a1, a2));
527 testing.expect(!eql(a1, a3));
528 testing.expect(!eql(a1[0..], a2[0..]));
493529
494530 const EU = struct {
495531 fn tst(err: bool) !u8 {
......@@ -498,9 +534,9 @@ test "std.meta.eql" {
498534 }
499535 };
500536
501 debug.assert(eql(EU.tst(true), EU.tst(true)));
502 debug.assert(eql(EU.tst(false), EU.tst(false)));
503 debug.assert(!eql(EU.tst(false), EU.tst(true)));
537 testing.expect(eql(EU.tst(true), EU.tst(true)));
538 testing.expect(eql(EU.tst(false), EU.tst(false)));
539 testing.expect(!eql(EU.tst(false), EU.tst(true)));
504540}
505541
506542test "intToEnum with error return" {
......@@ -514,9 +550,9 @@ test "intToEnum with error return" {
514550
515551 var zero: u8 = 0;
516552 var one: u16 = 1;
517 debug.assert(intToEnum(E1, zero) catch unreachable == E1.A);
518 debug.assert(intToEnum(E2, one) catch unreachable == E2.B);
519 debug.assertError(intToEnum(E1, one), error.InvalidEnumTag);
553 testing.expect(intToEnum(E1, zero) catch unreachable == E1.A);
554 testing.expect(intToEnum(E2, one) catch unreachable == E2.B);
555 testing.expectError(error.InvalidEnumTag, intToEnum(E1, one));
520556}
521557
522558pub const IntToEnumError = error{InvalidEnumTag};
std/meta/trait.zig+90-58
......@@ -2,6 +2,7 @@ const std = @import("../index.zig");
22const builtin = @import("builtin");
33const mem = std.mem;
44const debug = std.debug;
5const testing = std.testing;
56const warn = debug.warn;
67
78const meta = @import("index.zig");
......@@ -50,8 +51,8 @@ test "std.meta.trait.multiTrait" {
5051 hasField("x"),
5152 hasField("y"),
5253 });
53 debug.assert(isVector(Vector2));
54 debug.assert(!isVector(u8));
54 testing.expect(isVector(Vector2));
55 testing.expect(!isVector(u8));
5556}
5657
5758///
......@@ -85,12 +86,12 @@ test "std.meta.trait.hasDef" {
8586 const value = u8(16);
8687 };
8788
88 debug.assert(hasDef("value")(TestStruct));
89 debug.assert(!hasDef("value")(TestStructFail));
90 debug.assert(!hasDef("value")(*TestStruct));
91 debug.assert(!hasDef("value")(**TestStructFail));
92 debug.assert(!hasDef("x")(TestStruct));
93 debug.assert(!hasDef("value")(u8));
89 testing.expect(hasDef("value")(TestStruct));
90 testing.expect(!hasDef("value")(TestStructFail));
91 testing.expect(!hasDef("value")(*TestStruct));
92 testing.expect(!hasDef("value")(**TestStructFail));
93 testing.expect(!hasDef("x")(TestStruct));
94 testing.expect(!hasDef("value")(u8));
9495}
9596
9697///
......@@ -111,9 +112,9 @@ test "std.meta.trait.hasFn" {
111112 pub fn useless() void {}
112113 };
113114
114 debug.assert(hasFn("useless")(TestStruct));
115 debug.assert(!hasFn("append")(TestStruct));
116 debug.assert(!hasFn("useless")(u8));
115 testing.expect(hasFn("useless")(TestStruct));
116 testing.expect(!hasFn("append")(TestStruct));
117 testing.expect(!hasFn("useless")(u8));
117118}
118119
119120///
......@@ -143,11 +144,11 @@ test "std.meta.trait.hasField" {
143144 value: u32,
144145 };
145146
146 debug.assert(hasField("value")(TestStruct));
147 debug.assert(!hasField("value")(*TestStruct));
148 debug.assert(!hasField("x")(TestStruct));
149 debug.assert(!hasField("x")(**TestStruct));
150 debug.assert(!hasField("value")(u8));
147 testing.expect(hasField("value")(TestStruct));
148 testing.expect(!hasField("value")(*TestStruct));
149 testing.expect(!hasField("x")(TestStruct));
150 testing.expect(!hasField("x")(**TestStruct));
151 testing.expect(!hasField("value")(u8));
151152}
152153
153154///
......@@ -161,11 +162,11 @@ pub fn is(comptime id: builtin.TypeId) TraitFn {
161162}
162163
163164test "std.meta.trait.is" {
164 debug.assert(is(builtin.TypeId.Int)(u8));
165 debug.assert(!is(builtin.TypeId.Int)(f32));
166 debug.assert(is(builtin.TypeId.Pointer)(*u8));
167 debug.assert(is(builtin.TypeId.Void)(void));
168 debug.assert(!is(builtin.TypeId.Optional)(anyerror));
165 testing.expect(is(builtin.TypeId.Int)(u8));
166 testing.expect(!is(builtin.TypeId.Int)(f32));
167 testing.expect(is(builtin.TypeId.Pointer)(*u8));
168 testing.expect(is(builtin.TypeId.Void)(void));
169 testing.expect(!is(builtin.TypeId.Optional)(anyerror));
169170}
170171
171172///
......@@ -180,9 +181,9 @@ pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn {
180181}
181182
182183test "std.meta.trait.isPtrTo" {
183 debug.assert(!isPtrTo(builtin.TypeId.Struct)(struct {}));
184 debug.assert(isPtrTo(builtin.TypeId.Struct)(*struct {}));
185 debug.assert(!isPtrTo(builtin.TypeId.Struct)(**struct {}));
184 testing.expect(!isPtrTo(builtin.TypeId.Struct)(struct {}));
185 testing.expect(isPtrTo(builtin.TypeId.Struct)(*struct {}));
186 testing.expect(!isPtrTo(builtin.TypeId.Struct)(**struct {}));
186187}
187188
188189///////////Strait trait Fns
......@@ -205,9 +206,9 @@ test "std.meta.trait.isExtern" {
205206 const TestExStruct = extern struct {};
206207 const TestStruct = struct {};
207208
208 debug.assert(isExtern(TestExStruct));
209 debug.assert(!isExtern(TestStruct));
210 debug.assert(!isExtern(u8));
209 testing.expect(isExtern(TestExStruct));
210 testing.expect(!isExtern(TestStruct));
211 testing.expect(!isExtern(u8));
211212}
212213
213214///
......@@ -226,9 +227,40 @@ test "std.meta.trait.isPacked" {
226227 const TestPStruct = packed struct {};
227228 const TestStruct = struct {};
228229
229 debug.assert(isPacked(TestPStruct));
230 debug.assert(!isPacked(TestStruct));
231 debug.assert(!isPacked(u8));
230 testing.expect(isPacked(TestPStruct));
231 testing.expect(!isPacked(TestStruct));
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);
232264}
233265
234266///
......@@ -242,9 +274,9 @@ pub fn isSingleItemPtr(comptime T: type) bool {
242274
243275test "std.meta.trait.isSingleItemPtr" {
244276 const array = []u8{0} ** 10;
245 debug.assert(isSingleItemPtr(@typeOf(&array[0])));
246 debug.assert(!isSingleItemPtr(@typeOf(array)));
247 debug.assert(!isSingleItemPtr(@typeOf(array[0..1])));
277 testing.expect(isSingleItemPtr(@typeOf(&array[0])));
278 testing.expect(!isSingleItemPtr(@typeOf(array)));
279 testing.expect(!isSingleItemPtr(@typeOf(array[0..1])));
248280}
249281
250282///
......@@ -259,9 +291,9 @@ pub fn isManyItemPtr(comptime T: type) bool {
259291test "std.meta.trait.isManyItemPtr" {
260292 const array = []u8{0} ** 10;
261293 const mip = @ptrCast([*]const u8, &array[0]);
262 debug.assert(isManyItemPtr(@typeOf(mip)));
263 debug.assert(!isManyItemPtr(@typeOf(array)));
264 debug.assert(!isManyItemPtr(@typeOf(array[0..1])));
294 testing.expect(isManyItemPtr(@typeOf(mip)));
295 testing.expect(!isManyItemPtr(@typeOf(array)));
296 testing.expect(!isManyItemPtr(@typeOf(array[0..1])));
265297}
266298
267299///
......@@ -275,9 +307,9 @@ pub fn isSlice(comptime T: type) bool {
275307
276308test "std.meta.trait.isSlice" {
277309 const array = []u8{0} ** 10;
278 debug.assert(isSlice(@typeOf(array[0..])));
279 debug.assert(!isSlice(@typeOf(array)));
280 debug.assert(!isSlice(@typeOf(&array[0])));
310 testing.expect(isSlice(@typeOf(array[0..])));
311 testing.expect(!isSlice(@typeOf(array)));
312 testing.expect(!isSlice(@typeOf(&array[0])));
281313}
282314
283315///
......@@ -297,10 +329,10 @@ test "std.meta.trait.isIndexable" {
297329 const array = []u8{0} ** 10;
298330 const slice = array[0..];
299331
300 debug.assert(isIndexable(@typeOf(array)));
301 debug.assert(isIndexable(@typeOf(&array)));
302 debug.assert(isIndexable(@typeOf(slice)));
303 debug.assert(!isIndexable(meta.Child(@typeOf(slice))));
332 testing.expect(isIndexable(@typeOf(array)));
333 testing.expect(isIndexable(@typeOf(&array)));
334 testing.expect(isIndexable(@typeOf(slice)));
335 testing.expect(!isIndexable(meta.Child(@typeOf(slice))));
304336}
305337
306338///
......@@ -316,13 +348,13 @@ test "std.meta.trait.isNumber" {
316348 number: u8,
317349 };
318350
319 debug.assert(isNumber(u32));
320 debug.assert(isNumber(f32));
321 debug.assert(isNumber(u64));
322 debug.assert(isNumber(@typeOf(102)));
323 debug.assert(isNumber(@typeOf(102.123)));
324 debug.assert(!isNumber([]u8));
325 debug.assert(!isNumber(NotANumber));
351 testing.expect(isNumber(u32));
352 testing.expect(isNumber(f32));
353 testing.expect(isNumber(u64));
354 testing.expect(isNumber(@typeOf(102)));
355 testing.expect(isNumber(@typeOf(102.123)));
356 testing.expect(!isNumber([]u8));
357 testing.expect(!isNumber(NotANumber));
326358}
327359
328360///
......@@ -335,10 +367,10 @@ pub fn isConstPtr(comptime T: type) bool {
335367test "std.meta.trait.isConstPtr" {
336368 var t = u8(0);
337369 const c = u8(0);
338 debug.assert(isConstPtr(*const @typeOf(t)));
339 debug.assert(isConstPtr(@typeOf(&c)));
340 debug.assert(!isConstPtr(*@typeOf(t)));
341 debug.assert(!isConstPtr(@typeOf(6)));
370 testing.expect(isConstPtr(*const @typeOf(t)));
371 testing.expect(isConstPtr(@typeOf(&c)));
372 testing.expect(!isConstPtr(*@typeOf(t)));
373 testing.expect(!isConstPtr(@typeOf(6)));
342374}
343375
344376///
......@@ -362,8 +394,8 @@ test "std.meta.trait.isContainer" {
362394 B,
363395 };
364396
365 debug.assert(isContainer(TestStruct));
366 debug.assert(isContainer(TestUnion));
367 debug.assert(isContainer(TestEnum));
368 debug.assert(!isContainer(u8));
397 testing.expect(isContainer(TestStruct));
398 testing.expect(isContainer(TestUnion));
399 testing.expect(isContainer(TestEnum));
400 testing.expect(!isContainer(u8));
369401}
std/mutex.zig+105-48
......@@ -2,77 +2,127 @@ const std = @import("index.zig");
22const builtin = @import("builtin");
33const AtomicOrder = builtin.AtomicOrder;
44const AtomicRmwOp = builtin.AtomicRmwOp;
5const assert = std.debug.assert;
5const testing = std.testing;
66const SpinLock = std.SpinLock;
77const linux = std.os.linux;
8const windows = std.os.windows;
89
910/// Lock may be held only once. If the same thread
1011/// 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.
1115/// The Linux implementation is based on mutex3 from
1216/// https://www.akkadia.org/drepper/futex.pdf
13pub const Mutex = struct {
14 /// 0: unlocked
15 /// 1: locked, no waiters
16 /// 2: locked, one or more waiters
17 linux_lock: @typeOf(linux_lock_init),
17/// When an application is built in single threaded release mode, all the functions are
18/// no-ops. In single threaded debug mode, there is deadlock detection.
19pub const Mutex = if (builtin.single_threaded)
20 struct {
21 lock: @typeOf(lock_init),
1822
19 /// TODO better implementation than spin lock
20 spin_lock: @typeOf(spin_lock_init),
23 const lock_init = if (std.debug.runtime_safety) false else {};
2124
22 const linux_lock_init = if (builtin.os == builtin.Os.linux) i32(0) else {};
23 const spin_lock_init = if (builtin.os != builtin.Os.linux) SpinLock.init() else {};
25 pub const Held = struct {
26 mutex: *Mutex,
2427
25 pub const Held = struct {
26 mutex: *Mutex,
28 pub fn release(self: Held) void {
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 {
29 if (builtin.os == builtin.Os.linux) {
30 const c = @atomicRmw(i32, &self.mutex.linux_lock, AtomicRmwOp.Sub, 1, AtomicOrder.Release);
39 pub fn acquire(self: *Mutex) Held {
40 if (std.debug.runtime_safety and self.lock) {
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);
3158 if (c != 1) {
32 _ = @atomicRmw(i32, &self.mutex.linux_lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release);
33 const rc = linux.futex_wake(&self.mutex.linux_lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1);
59 _ = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release);
60 const rc = linux.futex_wake(&self.mutex.lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1);
3461 switch (linux.getErrno(rc)) {
3562 0 => {},
3663 linux.EINVAL => unreachable,
3764 else => unreachable,
3865 }
3966 }
40 } else {
41 SpinLock.Held.release(SpinLock.Held{ .spinlock = &self.mutex.spin_lock });
4267 }
68 };
69
70 pub fn init() Mutex {
71 return Mutex{ .lock = 0 };
4372 }
44 };
4573
46 pub fn init() Mutex {
47 return Mutex{
48 .linux_lock = linux_lock_init,
49 .spin_lock = spin_lock_init,
50 };
51 }
74 pub fn deinit(self: *Mutex) void {}
5275
53 pub fn acquire(self: *Mutex) Held {
54 if (builtin.os == builtin.Os.linux) {
55 var c = @cmpxchgWeak(i32, &self.linux_lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse
76 pub fn acquire(self: *Mutex) Held {
77 var c = @cmpxchgWeak(i32, &self.lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse
5678 return Held{ .mutex = self };
5779 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);
5981 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);
6183 switch (linux.getErrno(rc)) {
6284 0, linux.EINTR, linux.EAGAIN => {},
6385 linux.EINVAL => unreachable,
6486 else => unreachable,
6587 }
66 c = @atomicRmw(i32, &self.linux_lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
88 c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
6789 }
68 } else {
69 _ = self.spin_lock.acquire();
90 return Held{ .mutex = self };
7091 }
71 return Held{ .mutex = self };
72 }
92 },
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 },
73123};
74124
75const Context = struct {
125const TestContext = struct {
76126 mutex: *Mutex,
77127 data: i128,
78128
......@@ -90,25 +140,32 @@ test "std.Mutex" {
90140 var a = &fixed_buffer_allocator.allocator;
91141
92142 var mutex = Mutex.init();
93 var context = Context{
143 defer mutex.deinit();
144
145 var context = TestContext{
94146 .mutex = &mutex,
95147 .data = 0,
96148 };
97149
98 const thread_count = 10;
99 var threads: [thread_count]*std.os.Thread = undefined;
100 for (threads) |*t| {
101 t.* = try std.os.spawnThread(&context, worker);
102 }
103 for (threads) |t|
104 t.wait();
150 if (builtin.single_threaded) {
151 worker(&context);
152 testing.expect(context.data == TestContext.incr_count);
153 } else {
154 const thread_count = 10;
155 var threads: [thread_count]*std.os.Thread = undefined;
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 }
107164}
108165
109fn worker(ctx: *Context) void {
166fn worker(ctx: *TestContext) void {
110167 var i: usize = 0;
111 while (i != Context.incr_count) : (i += 1) {
168 while (i != TestContext.incr_count) : (i += 1) {
112169 const held = ctx.mutex.acquire();
113170 defer held.release();
114171
std/net.zig+6-6
......@@ -23,7 +23,7 @@ pub const Address = struct {
2323 .os_addr = posix.sockaddr{
2424 .in = posix.sockaddr_in{
2525 .family = posix.AF_INET,
26 .port = std.mem.endianSwapIfLe(u16, _port),
26 .port = mem.nativeToBig(u16, _port),
2727 .addr = ip4,
2828 .zero = []u8{0} ** 8,
2929 },
......@@ -37,7 +37,7 @@ pub const Address = struct {
3737 .os_addr = posix.sockaddr{
3838 .in6 = posix.sockaddr_in6{
3939 .family = posix.AF_INET6,
40 .port = std.mem.endianSwapIfLe(u16, _port),
40 .port = mem.nativeToBig(u16, _port),
4141 .flowinfo = 0,
4242 .addr = ip6.addr,
4343 .scope_id = ip6.scope_id,
......@@ -47,7 +47,7 @@ pub const Address = struct {
4747 }
4848
4949 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);
5151 }
5252
5353 pub fn initPosix(addr: posix.sockaddr) Address {
......@@ -57,12 +57,12 @@ pub const Address = struct {
5757 pub fn format(self: *const Address, out_stream: var) !void {
5858 switch (self.os_addr.in.family) {
5959 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);
6161 const bytes = ([]const u8)((*self.os_addr.in.addr)[0..1]);
6262 try out_stream.print("{}.{}.{}.{}:{}", bytes[0], bytes[1], bytes[2], bytes[3], native_endian_port);
6363 },
6464 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);
6666 try out_stream.print("[TODO render ip6 address]:{}", native_endian_port);
6767 },
6868 else => try out_stream.write("(unrecognized address family)"),
......@@ -193,7 +193,7 @@ pub fn parseIp6(buf: []const u8) !Ip6Addr {
193193}
194194
195195test "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
198198 testParseIp4Fail("256.0.0.1", error.Overflow);
199199 testParseIp4Fail("x.0.0.1", error.InvalidCharacter);
std/os/child_process.zig+12-9
......@@ -7,7 +7,6 @@ const posix = os.posix;
77const windows = os.windows;
88const mem = std.mem;
99const debug = std.debug;
10const assert = debug.assert;
1110const BufMap = std.BufMap;
1211const Buffer = std.Buffer;
1312const builtin = @import("builtin");
......@@ -88,7 +87,8 @@ pub const ChildProcess = struct {
8887 /// First argument in argv is the executable.
8988 /// On success must call deinit.
9089 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{
9292 .allocator = allocator,
9393 .argv = argv,
9494 .pid = undefined,
......@@ -109,7 +109,7 @@ pub const ChildProcess = struct {
109109 .stdin_behavior = StdIo.Inherit,
110110 .stdout_behavior = StdIo.Inherit,
111111 .stderr_behavior = StdIo.Inherit,
112 });
112 };
113113 errdefer allocator.destroy(child);
114114 return child;
115115 }
......@@ -573,7 +573,7 @@ pub const ChildProcess = struct {
573573 // to match posix semantics
574574 const app_name = x: {
575575 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] });
577577 defer self.allocator.free(resolved);
578578 break :x try cstr.addNullByte(self.allocator, resolved);
579579 } else {
......@@ -594,12 +594,12 @@ pub const ChildProcess = struct {
594594 const PATH = try os.getEnvVarOwned(self.allocator, "PATH");
595595 defer self.allocator.free(PATH);
596596
597 var it = mem.split(PATH, ";");
597 var it = mem.tokenize(PATH, ";");
598598 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 });
600600 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);
603603 defer self.allocator.free(joined_path_w);
604604
605605 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 {
609609 } else {
610610 return err;
611611 }
612 } else {
613 // Every other error would have been returned earlier.
614 return error.FileNotFound;
612615 }
613616 };
614617
......@@ -807,10 +810,10 @@ const ErrInt = @IntType(false, @sizeOf(anyerror) * 8);
807810
808811fn writeIntFd(fd: i32, value: ErrInt) !void {
809812 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;
811814}
812815
813816fn readIntFd(fd: i32) !ErrInt {
814817 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;
816819}
std/os/darwin.zig+1-1
......@@ -665,7 +665,7 @@ pub fn pwrite(fd: i32, buf: [*]const u8, nbyte: usize, offset: u64) usize {
665665
666666pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
667667 const ptr_result = c.mmap(
668 @ptrCast(*c_void, address),
668 @ptrCast(?*c_void, address),
669669 length,
670670 @bitCast(c_int, @intCast(c_uint, prot)),
671671 @bitCast(c_int, c_uint(flags)),
std/os/freebsd/index.zig+171-120
......@@ -1,16 +1,20 @@
1const assert = @import("../debug.zig").assert;
21const builtin = @import("builtin");
3const arch = switch (builtin.arch) {
4 builtin.Arch.x86_64 => @import("x86_64.zig"),
5 else => @compileError("unsupported arch"),
6};
7pub use @import("syscall.zig");
2
83pub use @import("errno.zig");
94
105const std = @import("../../index.zig");
116const c = std.c;
7
8const assert = std.debug.assert;
9const maxInt = std.math.maxInt;
1210pub 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
1418pub const PATH_MAX = 1024;
1519
1620pub const STDIN_FILENO = 0;
......@@ -22,7 +26,22 @@ pub const PROT_READ = 1;
2226pub const PROT_WRITE = 2;
2327pub 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);
2645pub const MAP_SHARED = 0x0001;
2746pub const MAP_PRIVATE = 0x0002;
2847pub const MAP_FIXED = 0x0010;
......@@ -94,26 +113,33 @@ pub const SIGLIBRT = 33;
94113pub const SIGRTMIN = 65;
95114pub const SIGRTMAX = 126;
96115
97pub const O_RDONLY = 0o0;
98pub const O_WRONLY = 0o1;
99pub const O_RDWR = 0o2;
100pub const O_ACCMODE = 0o3;
101
102pub const O_CREAT = 0o100;
103pub const O_EXCL = 0o200;
104pub const O_NOCTTY = 0o400;
105pub const O_TRUNC = 0o1000;
106pub const O_APPEND = 0o2000;
107pub const O_NONBLOCK = 0o4000;
116// access function
117pub const F_OK = 0; // test for existence of file
118pub const X_OK = 1; // test for execute or search permission
119pub const W_OK = 2; // test for write permission
120pub const R_OK = 4; // test for read permission
121
122
123pub const O_RDONLY = 0x0000;
124pub const O_WRONLY = 0x0001;
125pub const O_RDWR = 0x0002;
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;
108134pub const O_DSYNC = 0o10000;
109pub const O_SYNC = 0o4010000;
135pub const O_SYNC = 0x0080;
110136pub const O_RSYNC = 0o4010000;
111137pub const O_DIRECTORY = 0o200000;
112pub const O_NOFOLLOW = 0o400000;
113pub const O_CLOEXEC = 0o2000000;
138pub const O_NOFOLLOW = 0x0100;
139pub const O_CLOEXEC = 0x00100000;
114140
115pub const O_ASYNC = 0o20000;
116pub const O_DIRECT = 0o40000;
141pub const O_ASYNC = 0x0040;
142pub const O_DIRECT = 0x00010000;
117143pub const O_LARGEFILE = 0;
118144pub const O_NOATIME = 0o1000000;
119145pub const O_PATH = 0o10000000;
......@@ -157,7 +183,6 @@ pub const SOCK_SEQPACKET = 5;
157183pub const SOCK_CLOEXEC = 0x10000000;
158184pub const SOCK_NONBLOCK = 0x20000000;
159185
160// TODO: From here
161186pub const PROTO_ip = 0o000;
162187pub const PROTO_icmp = 0o001;
163188pub const PROTO_igmp = 0o002;
......@@ -500,6 +525,10 @@ pub const TIOCGPKT = 0x80045438;
500525pub const TIOCGPTLCK = 0x80045439;
501526pub const TIOCGEXCL = 0x80045440;
502527
528pub const sockaddr = c.sockaddr;
529pub const sockaddr_in = c.sockaddr_in;
530pub const sockaddr_in6 = c.sockaddr_in6;
531
503532fn unsigned(s: i32) u32 {
504533 return @bitCast(u32, s);
505534}
......@@ -539,96 +568,117 @@ pub fn getErrno(r: usize) usize {
539568}
540569
541570pub 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));
543572}
544573
545574pub fn chdir(path: [*]const u8) usize {
546 return arch.syscall1(SYS_chdir, @ptrToInt(path));
575 return errnoWrap(c.chdir(path));
547576}
548577
549578pub 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));
551580}
552581
553582pub 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));
555588}
556589
557590pub 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;
559592}
560593
561594pub 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;
563604}
564605
565606pub fn isatty(fd: i32) bool {
566 var wsz: winsize = undefined;
567 return arch.syscall3(SYS_ioctl, @intCast(usize, fd), TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
607 return c.isatty(fd) != 0;
568608}
569609
570610pub 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));
572612}
573613
574614pub fn mkdir(path: [*]const u8, mode: u32) usize {
575 return arch.syscall2(SYS_mkdir, @ptrToInt(path), mode);
615 return errnoWrap(c.mkdir(path, mode));
576616}
577617
578pub fn mmap(address: ?*u8, length: usize, prot: usize, flags: usize, fd: i32, offset: isize) usize {
579 return arch.syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @intCast(usize, fd), @bitCast(usize, offset));
618pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
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);
580629}
581630
582631pub 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));
584633}
585634
586pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
587 return arch.syscall3(SYS_read, @intCast(usize, fd), @ptrToInt(buf), count);
635pub fn read(fd: i32, buf: [*]u8, nbyte: usize) usize {
636 return errnoWrap(c.read(fd, @ptrCast(*c_void, buf), nbyte));
588637}
589638
590639pub fn rmdir(path: [*]const u8) usize {
591 return arch.syscall1(SYS_rmdir, @ptrToInt(path));
640 return errnoWrap(c.rmdir(path));
592641}
593642
594643pub 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));
596645}
597646
598pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize {
599 return arch.syscall4(SYS_pread, @intCast(usize, fd), @ptrToInt(buf), count, offset);
647pub fn pread(fd: i32, buf: [*]u8, nbyte: usize, offset: u64) usize {
648 return errnoWrap(c.pread(fd, @ptrCast(*c_void, buf), nbyte, offset));
600649}
601650
602651pub 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));
604653}
605654
606655pub fn pipe(fd: *[2]i32) usize {
607656 return pipe2(fd, 0);
608657}
609658
610pub fn pipe2(fd: *[2]i32, flags: usize) usize {
611 return arch.syscall2(SYS_pipe2, @ptrToInt(fd), flags);
659pub fn pipe2(fd: *[2]i32, flags: u32) usize {
660 comptime assert(i32.bit_count == c_int.bit_count);
661 return errnoWrap(c.pipe2(@ptrCast(*[2]c_int, fd), flags));
612662}
613663
614pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
615 return arch.syscall3(SYS_write, @intCast(usize, fd), @ptrToInt(buf), count);
664pub fn write(fd: i32, buf: [*]const u8, nbyte: usize) usize {
665 return errnoWrap(c.write(fd, @ptrCast(*const c_void, buf), nbyte));
616666}
617667
618pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
619 return arch.syscall4(SYS_pwrite, @intCast(usize, fd), @ptrToInt(buf), count, offset);
668pub fn pwrite(fd: i32, buf: [*]const u8, nbyte: usize, offset: u64) usize {
669 return errnoWrap(c.pwrite(fd, @ptrCast(*const c_void, buf), nbyte, offset));
620670}
621671
622672pub 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));
624674}
625675
626676pub 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));
628678}
629679
630pub fn open(path: [*]const u8, flags: u32, perm: usize) usize {
631 return arch.syscall3(SYS_open, @ptrToInt(path), flags, perm);
680pub fn open(path: [*]const u8, flags: u32, mode: usize) usize {
681 return errnoWrap(c.open(path, @bitCast(c_int, flags), mode));
632682}
633683
634684pub fn create(path: [*]const u8, perm: usize) usize {
......@@ -636,120 +686,114 @@ pub fn create(path: [*]const u8, perm: usize) usize {
636686}
637687
638688pub 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));
640690}
641691
642692pub fn close(fd: i32) usize {
643 return arch.syscall1(SYS_close, @intCast(usize, fd));
693 return errnoWrap(c.close(fd));
644694}
645695
646pub fn lseek(fd: i32, offset: isize, ref_pos: usize) usize {
647 return arch.syscall3(SYS_lseek, @intCast(usize, fd), @bitCast(usize, offset), ref_pos);
696pub fn lseek(fd: i32, offset: isize, whence: c_int) usize {
697 return errnoWrap(c.lseek(fd, offset, whence));
648698}
649699
650pub fn exit(status: i32) noreturn {
651 _ = arch.syscall1(SYS_exit, @bitCast(usize, isize(status)));
652 unreachable;
653}
654
655pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
656 return arch.syscall3(SYS_getrandom, @ptrToInt(buf), count, @intCast(usize, flags));
700pub fn exit(code: i32) noreturn {
701 c.exit(code);
657702}
658703
659704pub 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));
661706}
662707
663708pub fn unlink(path: [*]const u8) usize {
664 return arch.syscall1(SYS_unlink, @ptrToInt(path));
709 return errnoWrap(c.unlink(path));
665710}
666711
667pub fn waitpid(pid: i32, status: *i32, options: i32) usize {
668 return arch.syscall4(SYS_wait4, @bitCast(usize, isize(pid)), @ptrToInt(status), @bitCast(usize, isize(options)), 0);
712pub fn waitpid(pid: i32, status: *i32, options: u32) usize {
713 comptime assert(i32.bit_count == c_int.bit_count);
714 return errnoWrap(c.waitpid(pid, @ptrCast(*c_int, status), @bitCast(c_int, options)));
669715}
670716
671717pub 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));
673727}
674728
675729pub fn setuid(uid: u32) usize {
676 return arch.syscall1(SYS_setuid, uid);
730 return errnoWrap(c.setuid(uid));
677731}
678732
679733pub fn setgid(gid: u32) usize {
680 return arch.syscall1(SYS_setgid, gid);
734 return errnoWrap(c.setgid(gid));
681735}
682736
683737pub fn setreuid(ruid: u32, euid: u32) usize {
684 return arch.syscall2(SYS_setreuid, ruid, euid);
738 return errnoWrap(c.setreuid(ruid, euid));
685739}
686740
687741pub fn setregid(rgid: u32, egid: u32) usize {
688 return arch.syscall2(SYS_setregid, rgid, egid);
742 return errnoWrap(c.setregid(rgid, egid));
689743}
690744
691pub fn sigprocmask(flags: u32, noalias set: *const sigset_t, noalias oldset: ?*sigset_t) usize {
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}
745const NSIG = 32;
700746
701const NSIG = 65;
702const sigset_t = [128 / @sizeOf(usize)]usize;
703const all_mask = []usize{@maxValue(usize)};
704const app_mask = []usize{0xfffffffc7fffffff};
747pub const SIG_ERR = @intToPtr(extern fn (i32) void, maxInt(usize));
748pub const SIG_DFL = @intToPtr(extern fn (i32) void, 0);
749pub const SIG_IGN = @intToPtr(extern fn (i32) void, 1);
705750
706751/// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall.
707pub const Sigaction = struct {
708 // TODO: Adjust to use freebsd struct layout
709 handler: extern fn (i32) void,
710 mask: sigset_t,
711 flags: u32,
752pub const Sigaction = extern struct {
753 /// signal handler
754 __sigaction_u: extern union {
755 __sa_handler: extern fn (i32) void,
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,
712764};
713765
714pub const SIG_ERR = @intToPtr(extern fn (i32) void, @maxValue(usize));
715pub const SIG_DFL = @intToPtr(extern fn (i32) void, 0);
716pub const SIG_IGN = @intToPtr(extern fn (i32) void, 1);
717pub const empty_sigset = []usize{0} ** sigset_t.len;
766pub const _SIG_WORDS = 4;
767pub const _SIG_MAXSIG = 128;
718768
719pub fn raise(sig: i32) usize {
720 // TODO implement, see linux equivalent for what we want to try and do
721 return 0;
769pub inline fn _SIG_IDX(sig: usize) usize {
770 return sig - 1;
722771}
723
724fn blockAllSignals(set: *sigset_t) void {
725 // TODO implement
772pub inline fn _SIG_WORD(sig: usize) usize {
773 return_SIG_IDX(sig) >> 5;
726774}
727
728fn blockAppSignals(set: *sigset_t) void {
729 // TODO implement
775pub inline fn _SIG_BIT(sig: usize) usize {
776 return 1 << (_SIG_IDX(sig) & 31);
730777}
731
732fn restoreSignals(set: *sigset_t) void {
733 // TODO implement
778pub inline fn _SIG_VALID(sig: usize) usize {
779 return sig <= _SIG_MAXSIG and sig > 0;
734780}
735781
736pub fn sigaddset(set: *sigset_t, sig: u6) void {
737 const s = sig - 1;
738 (*set)[usize(s) / usize.bit_count] |= usize(1) << (s & (usize.bit_count - 1));
739}
782pub const sigset_t = extern struct {
783 __bits: [_SIG_WORDS]u32,
784};
740785
741pub fn sigismember(set: *const sigset_t, sig: u6) bool {
742 const s = sig - 1;
743 return ((*set)[usize(s) / usize.bit_count] & (usize(1) << (s & (usize.bit_count - 1)))) != 0;
786pub fn raise(sig: i32) usize {
787 return errnoWrap(c.raise(sig));
744788}
745789
746pub const Stat = arch.Stat;
747pub const timespec = arch.timespec;
790pub const Stat = c.Stat;
791pub const dirent = c.dirent;
792pub const timespec = c.timespec;
748793
749pub fn fstat(fd: i32, stat_buf: *Stat) usize {
750 return arch.syscall2(SYS_fstat, @intCast(usize, fd), @ptrToInt(stat_buf));
794pub fn fstat(fd: i32, buf: *c.Stat) usize {
795 return errnoWrap(c.fstat(fd, buf));
751796}
752
753797pub const iovec = extern struct {
754798 iov_base: [*]u8,
755799 iov_len: usize,
......@@ -760,10 +804,12 @@ pub const iovec_const = extern struct {
760804 iov_len: usize,
761805};
762806
807// TODO avoid libc dependency
763808pub fn kqueue() usize {
764809 return errnoWrap(c.kqueue());
765810}
766811
812// TODO avoid libc dependency
767813pub fn kevent(kq: i32, changelist: []const Kevent, eventlist: []Kevent, timeout: ?*const timespec) usize {
768814 return errnoWrap(c.kevent(
769815 kq,
......@@ -775,18 +821,23 @@ pub fn kevent(kq: i32, changelist: []const Kevent, eventlist: []Kevent, timeout:
775821 ));
776822}
777823
824// TODO avoid libc dependency
778825pub fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize {
779826 return errnoWrap(c.sysctl(name, namelen, oldp, oldlenp, newp, newlen));
780827}
781828
829// TODO avoid libc dependency
782830pub fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) usize {
783831 return errnoWrap(c.sysctlbyname(name, oldp, oldlenp, newp, newlen));
784832}
785833
834// TODO avoid libc dependency
786835pub fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) usize {
787836 return errnoWrap(c.sysctlnametomib(name, wibp, sizep));
788837}
789838
839// TODO avoid libc dependency
840
790841/// Takes the return value from a syscall and formats it back in the way
791842/// that the kernel represents it to libc. Errno was a mistake, let's make
792843/// 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
3030 error.OutOfMemory => return error.OutOfMemory,
3131 };
3232 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 });
3434 },
3535 os.windows.E_OUTOFMEMORY => return error.OutOfMemory,
3636 else => return error.AppDataDirUnavailable,
......@@ -41,14 +41,14 @@ pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataD
4141 // TODO look in /etc/passwd
4242 return error.AppDataDirUnavailable;
4343 };
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 });
4545 },
4646 builtin.Os.linux, builtin.Os.freebsd => {
4747 const home_dir = os.getEnvPosix("HOME") orelse {
4848 // TODO look in /etc/passwd
4949 return error.AppDataDirUnavailable;
5050 };
51 return os.path.join(allocator, home_dir, ".local", "share", appname);
51 return os.path.join(allocator, [][]const u8{ home_dir, ".local", "share", appname });
5252 },
5353 else => @compileError("Unsupported OS"),
5454 }
......@@ -67,4 +67,3 @@ test "std.os.getAppDataDir" {
6767 // We can't actually validate the result
6868 _ = getAppDataDir(allocator, "zig") catch return;
6969}
70
std/os/index.zig+187-64
......@@ -8,6 +8,10 @@ const is_posix = switch (builtin.os) {
88};
99const os = @This();
1010
11comptime {
12 assert(@import("std") == std); // You have to run the std lib tests with --override-std-dir
13}
14
1115test "std.os" {
1216 _ = @import("child_process.zig");
1317 _ = @import("darwin.zig");
......@@ -18,6 +22,7 @@ test "std.os" {
1822 _ = @import("test.zig");
1923 _ = @import("time.zig");
2024 _ = @import("windows/index.zig");
25 _ = @import("uefi.zig");
2126 _ = @import("get_app_data_dir.zig");
2227}
2328
......@@ -26,6 +31,8 @@ pub const darwin = @import("darwin.zig");
2631pub const linux = @import("linux/index.zig");
2732pub const freebsd = @import("freebsd/index.zig");
2833pub const zen = @import("zen.zig");
34pub const uefi = @import("uefi.zig");
35
2936pub const posix = switch (builtin.os) {
3037 Os.linux => linux,
3138 Os.macosx, Os.ios => darwin,
......@@ -33,6 +40,7 @@ pub const posix = switch (builtin.os) {
3340 Os.zen => zen,
3441 else => @compileError("Unsupported OS"),
3542};
43
3644pub const net = @import("net.zig");
3745
3846pub const ChildProcess = @import("child_process.zig").ChildProcess;
......@@ -83,6 +91,7 @@ pub const GetAppDataDirError = @import("get_app_data_dir.zig").GetAppDataDirErro
8391
8492const debug = std.debug;
8593const assert = debug.assert;
94const testing = std.testing;
8695
8796const c = std.c;
8897
......@@ -103,7 +112,7 @@ const math = std.math;
103112/// library implementation.
104113pub fn getRandomBytes(buf: []u8) !void {
105114 switch (builtin.os) {
106 Os.linux, Os.freebsd => while (true) {
115 Os.linux => while (true) {
107116 // TODO check libc version and potentially call c.getrandom.
108117 // See #397
109118 const errno = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0));
......@@ -116,7 +125,7 @@ pub fn getRandomBytes(buf: []u8) !void {
116125 else => return unexpectedErrorPosix(errno),
117126 }
118127 },
119 Os.macosx, Os.ios => return getRandomBytesDevURandom(buf),
128 Os.macosx, Os.ios, Os.freebsd => return getRandomBytesDevURandom(buf),
120129 Os.windows => {
121130 // Call RtlGenRandom() instead of CryptGetRandom() on Windows
122131 // https://github.com/rust-lang-nursery/rand/issues/111
......@@ -164,7 +173,7 @@ test "os.getRandomBytes" {
164173 try getRandomBytes(buf_b[0..]);
165174
166175 // 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));
168177}
169178
170179/// Raises a signal in the current kernel thread, ending its execution.
......@@ -187,6 +196,10 @@ pub fn abort() noreturn {
187196 }
188197 windows.ExitProcess(3);
189198 },
199 Os.uefi => {
200 // TODO there's gotta be a better thing to do here than loop forever
201 while (true) {}
202 },
190203 else => @compileError("Unsupported OS"),
191204 }
192205}
......@@ -459,6 +472,7 @@ pub const PosixOpenError = error{
459472 NoSpaceLeft,
460473 NotDir,
461474 PathAlreadyExists,
475 DeviceBusy,
462476
463477 /// See https://github.com/ziglang/zig/issues/1396
464478 Unexpected,
......@@ -497,6 +511,7 @@ pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 {
497511 posix.ENOTDIR => return PosixOpenError.NotDir,
498512 posix.EPERM => return PosixOpenError.AccessDenied,
499513 posix.EEXIST => return PosixOpenError.PathAlreadyExists,
514 posix.EBUSY => return PosixOpenError.DeviceBusy,
500515 else => return unexpectedErrorPosix(err),
501516 }
502517 }
......@@ -598,7 +613,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: *const BufMap, allocator:
598613 // +1 for the null terminating byte
599614 const path_buf = try allocator.alloc(u8, PATH.len + exe_path.len + 2);
600615 defer allocator.free(path_buf);
601 var it = mem.split(PATH, ":");
616 var it = mem.tokenize(PATH, ":");
602617 var seen_eacces = false;
603618 var err: usize = undefined;
604619 while (it.next()) |search_path| {
......@@ -682,12 +697,7 @@ pub fn getBaseAddress() usize {
682697 return base;
683698 }
684699 const phdr = linuxGetAuxVal(std.elf.AT_PHDR);
685 const ElfHeader = switch (@sizeOf(usize)) {
686 4 => std.elf.Elf32_Ehdr,
687 8 => std.elf.Elf64_Ehdr,
688 else => @compileError("Unsupported architecture"),
689 };
690 return phdr - @sizeOf(ElfHeader);
700 return phdr - @sizeOf(std.elf.Ehdr);
691701 },
692702 builtin.Os.macosx, builtin.Os.freebsd => return @ptrToInt(&std.c._mh_execute_header),
693703 builtin.Os.windows => return @ptrToInt(windows.GetModuleHandleW(null)),
......@@ -702,8 +712,8 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
702712 errdefer result.deinit();
703713
704714 if (is_windows) {
705 const ptr = windows.GetEnvironmentStringsA() orelse return error.OutOfMemory;
706 defer assert(windows.FreeEnvironmentStringsA(ptr) != 0);
715 const ptr = windows.GetEnvironmentStringsW() orelse return error.OutOfMemory;
716 defer assert(windows.FreeEnvironmentStringsW(ptr) != 0);
707717
708718 var i: usize = 0;
709719 while (true) {
......@@ -712,17 +722,21 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
712722 const key_start = i;
713723
714724 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
717729 if (ptr[i] == '=') i += 1;
718730
719731 const value_start = i;
720732 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
723737 i += 1; // skip over null byte
724738
725 try result.set(key, value);
739 try result.setMove(key, value);
726740 }
727741 } else {
728742 for (posix_environ_raw) |ptr| {
......@@ -740,6 +754,11 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
740754 }
741755}
742756
757test "os.getEnvMap" {
758 var env = try getEnvMap(std.debug.global_allocator);
759 defer env.deinit();
760}
761
743762/// TODO make this go through libc when we have it
744763pub fn getEnvPosix(key: []const u8) ?[]const u8 {
745764 for (posix_environ_raw) |ptr| {
......@@ -760,21 +779,24 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 {
760779pub const GetEnvVarOwnedError = error{
761780 OutOfMemory,
762781 EnvironmentVariableNotFound,
782
783 /// See https://github.com/ziglang/zig/issues/1774
784 InvalidUtf8,
763785};
764786
765787/// Caller must free returned memory.
766788/// TODO make this go through libc when we have it
767789pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 {
768790 if (is_windows) {
769 const key_with_null = try cstr.addNullByte(allocator, key);
791 const key_with_null = try std.unicode.utf8ToUtf16LeWithNull(allocator, key);
770792 defer allocator.free(key_with_null);
771793
772 var buf = try allocator.alloc(u8, 256);
773 errdefer allocator.free(buf);
794 var buf = try allocator.alloc(u16, 256);
795 defer allocator.free(buf);
774796
775797 while (true) {
776798 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
779801 if (result == 0) {
780802 const err = windows.GetLastError();
......@@ -788,11 +810,16 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned
788810 }
789811
790812 if (result > buf.len) {
791 buf = try allocator.realloc(u8, buf, result);
813 buf = try allocator.realloc(u16, buf, result);
792814 continue;
793815 }
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 };
796823 }
797824 } else {
798825 const result = getEnvPosix(key) orelse return error.EnvironmentVariableNotFound;
......@@ -800,6 +827,11 @@ pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwned
800827 }
801828}
802829
830test "os.getEnvVarOwned" {
831 var ga = debug.global_allocator;
832 testing.expectError(error.EnvironmentVariableNotFound, getEnvVarOwned(ga, "BADENV"));
833}
834
803835/// Caller must free the returned memory.
804836pub fn getCwdAlloc(allocator: *Allocator) ![]u8 {
805837 var buf: [MAX_PATH_BYTES]u8 = undefined;
......@@ -1253,7 +1285,7 @@ pub fn makeDirPosix(dir_path: []const u8) !void {
12531285/// already exists and is a directory.
12541286/// TODO determine if we can remove the allocator requirement from this function
12551287pub 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});
12571289 defer allocator.free(resolved_path);
12581290
12591291 var end_index: usize = resolved_path.len;
......@@ -1380,6 +1412,7 @@ const DeleteTreeError = error{
13801412 FileSystem,
13811413 FileBusy,
13821414 DirNotEmpty,
1415 DeviceBusy,
13831416
13841417 /// On Windows, file paths must be valid Unicode.
13851418 InvalidUtf8,
......@@ -1441,6 +1474,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError!
14411474 error.Unexpected,
14421475 error.InvalidUtf8,
14431476 error.BadPathName,
1477 error.DeviceBusy,
14441478 => return err,
14451479 };
14461480 defer dir.close();
......@@ -1523,6 +1557,7 @@ pub const Dir = struct {
15231557 OutOfMemory,
15241558 InvalidUtf8,
15251559 BadPathName,
1560 DeviceBusy,
15261561
15271562 /// See https://github.com/ziglang/zig/issues/1396
15281563 Unexpected,
......@@ -1731,8 +1766,57 @@ pub const Dir = struct {
17311766 }
17321767
17331768 fn nextFreebsd(self: *Dir) !?Entry {
1734 //self.handle.buf = try self.allocator.alloc(u8, page_size);
1735 @compileError("TODO implement dirs for FreeBSD");
1769 start_over: while (true) {
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 }
17361820 }
17371821};
17381822
......@@ -2136,9 +2220,9 @@ fn testWindowsCmdLine(input_cmd_line: [*]const u8, expected_args: []const []cons
21362220 var it = ArgIteratorWindows.initWithCmdLine(input_cmd_line);
21372221 for (expected_args) |expected_arg| {
21382222 const arg = it.next(debug.global_allocator).? catch unreachable;
2139 assert(mem.eql(u8, arg, expected_arg));
2223 testing.expectEqualSlices(u8, expected_arg, arg);
21402224 }
2141 assert(it.next(debug.global_allocator) == null);
2225 testing.expect(it.next(debug.global_allocator) == null);
21422226}
21432227
21442228// 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 {
22202304pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
22212305 switch (builtin.os) {
22222306 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 },
22242320 Os.windows => {
22252321 var utf16le_buf: [windows_util.PATH_MAX_WIDE]u16 = undefined;
22262322 const utf16le_slice = try selfExePathW(&utf16le_buf);
......@@ -2811,14 +2907,15 @@ pub const Thread = struct {
28112907 pub const Data = if (use_pthreads)
28122908 struct {
28132909 handle: Thread.Handle,
2814 stack_addr: usize,
2815 stack_len: usize,
2910 mmap_addr: usize,
2911 mmap_len: usize,
28162912 }
28172913 else switch (builtin.os) {
28182914 builtin.Os.linux => struct {
28192915 handle: Thread.Handle,
2820 stack_addr: usize,
2821 stack_len: usize,
2916 mmap_addr: usize,
2917 mmap_len: usize,
2918 tls_end_addr: usize,
28222919 },
28232920 builtin.Os.windows => struct {
28242921 handle: Thread.Handle,
......@@ -2858,7 +2955,7 @@ pub const Thread = struct {
28582955 posix.EDEADLK => unreachable,
28592956 else => unreachable,
28602957 }
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);
28622959 } else switch (builtin.os) {
28632960 builtin.Os.linux => {
28642961 while (true) {
......@@ -2872,7 +2969,7 @@ pub const Thread = struct {
28722969 else => unreachable,
28732970 }
28742971 }
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);
28762973 },
28772974 builtin.Os.windows => {
28782975 assert(windows.WaitForSingleObject(self.data.handle, windows.INFINITE) == windows.WAIT_OBJECT_0);
......@@ -2911,11 +3008,15 @@ pub const SpawnThreadError = error{
29113008 Unexpected,
29123009};
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
29143014/// caller must call wait on the returned thread
29153015/// fn startFn(@typeOf(context)) T
29163016/// where T is u8, noreturn, void, or !void
29173017/// caller must call wait on the returned thread
29183018pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread {
3019 if (builtin.single_threaded) @compileError("cannot spawn thread when building in single-threaded mode");
29193020 // TODO compile-time call graph analysis to determine stack upper bound
29203021 // https://github.com/ziglang/zig/issues/157
29213022 const default_stack_size = 8 * 1024 * 1024;
......@@ -2949,7 +3050,8 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
29493050 const bytes_ptr = windows.HeapAlloc(heap_handle, 0, byte_count) orelse return SpawnThreadError.OutOfMemory;
29503051 errdefer assert(windows.HeapFree(heap_handle, 0, bytes_ptr) != 0);
29513052 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{
29533055 .thread = Thread{
29543056 .data = Thread.Data{
29553057 .heap_handle = heap_handle,
......@@ -2958,7 +3060,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
29583060 },
29593061 },
29603062 .inner = context,
2961 }) catch unreachable;
3063 };
29623064
29633065 const parameter = if (@sizeOf(Context) == 0) null else @ptrCast(*c_void, &outer_context.inner);
29643066 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
29983100
29993101 const MAP_GROWSDOWN = if (builtin.os == builtin.Os.linux) linux.MAP_GROWSDOWN else 0;
30003102
3001 const mmap_len = default_stack_size;
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);
3003 if (stack_addr == posix.MAP_FAILED) return error.OutOfMemory;
3004 errdefer assert(posix.munmap(stack_addr, mmap_len) == 0);
3103 var stack_end_offset: usize = undefined;
3104 var thread_start_offset: usize = undefined;
3105 var context_start_offset: usize = undefined;
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;
30073139 var arg: usize = undefined;
30083140 if (@sizeOf(Context) != 0) {
3009 stack_end -= @sizeOf(Context);
3010 stack_end -= stack_end % @alignOf(Context);
3011 assert(stack_end >= stack_addr);
3012 const context_ptr = @alignCast(@alignOf(Context), @intToPtr(*Context, stack_end));
3141 arg = mmap_addr + context_start_offset;
3142 const context_ptr = @alignCast(@alignOf(Context), @intToPtr(*Context, arg));
30133143 context_ptr.* = context;
3014 arg = stack_end;
30153144 }
30163145
3017 stack_end -= @sizeOf(Thread);
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) {
3146 if (Thread.use_pthreads) {
30293147 // use pthreads
30303148 var attr: c.pthread_attr_t = undefined;
30313149 if (c.pthread_attr_init(&attr) != 0) return SpawnThreadError.SystemResources;
30323150 defer assert(c.pthread_attr_destroy(&attr) == 0);
30333151
3034 // align to page
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);
3152 assert(c.pthread_attr_setstack(&attr, @intToPtr(*c_void, mmap_addr), stack_end_offset) == 0);
30373153
30383154 const err = c.pthread_create(&thread_ptr.data.handle, &attr, MainFuncs.posixThreadMain, @intToPtr(*c_void, arg));
30393155 switch (err) {
......@@ -3044,10 +3160,17 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
30443160 else => return unexpectedErrorPosix(@intCast(usize, err)),
30453161 }
30463162 } else if (builtin.os == builtin.Os.linux) {
3047 // use linux API directly. TODO use posix.CLONE_SETTLS and initialize thread local storage correctly
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;
3049 const newtls: usize = 0;
3050 const rc = posix.clone(MainFuncs.linuxThreadMain, stack_end, flags, arg, &thread_ptr.data.handle, newtls, &thread_ptr.data.handle);
3163 var flags: u32 = posix.CLONE_VM | posix.CLONE_FS | posix.CLONE_FILES | posix.CLONE_SIGHAND |
3164 posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID |
3165 posix.CLONE_DETACHED;
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);
30513174 const err = posix.getErrno(rc);
30523175 switch (err) {
30533176 0 => return thread_ptr,
std/os/linux/test.zig+6-6
......@@ -1,19 +1,19 @@
11const std = @import("../../index.zig");
22const builtin = @import("builtin");
33const linux = std.os.linux;
4const assert = std.debug.assert;
4const expect = std.testing.expect;
55
66test "getpid" {
7 assert(linux.getpid() != 0);
7 expect(linux.getpid() != 0);
88}
99
1010test "timer" {
1111 const epoll_fd = linux.epoll_create();
1212 var err = linux.getErrno(epoll_fd);
13 assert(err == 0);
13 expect(err == 0);
1414
1515 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
1818 const time_interval = linux.timespec{
1919 .tv_sec = 0,
......@@ -26,7 +26,7 @@ test "timer" {
2626 };
2727
2828 err = linux.timerfd_settime(@intCast(i32, timer_fd), 0, &new_time, null);
29 assert(err == 0);
29 expect(err == 0);
3030
3131 var event = linux.epoll_event{
3232 .events = linux.EPOLLIN | linux.EPOLLOUT | linux.EPOLLET,
......@@ -34,7 +34,7 @@ test "timer" {
3434 };
3535
3636 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
3939 const events_one: linux.epoll_event = undefined;
4040 var events = []linux.epoll_event{events_one} ** 8;
std/os/path.zig+168-112
......@@ -3,6 +3,7 @@ const builtin = @import("builtin");
33const Os = builtin.Os;
44const debug = std.debug;
55const assert = debug.assert;
6const testing = std.testing;
67const mem = std.mem;
78const fmt = std.fmt;
89const Allocator = mem.Allocator;
......@@ -33,40 +34,103 @@ pub fn isSep(byte: u8) bool {
3334 }
3435}
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
3682/// Naively combines a series of paths with the native path seperator.
3783/// Allocates memory for the result, which must be freed by the caller.
38pub fn join(allocator: *Allocator, paths: ...) ![]u8 {
39 if (is_windows) {
40 return joinWindows(allocator, paths);
41 } else {
42 return joinPosix(allocator, paths);
43 }
84pub fn joinWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
85 return joinSep(allocator, sep_windows, paths);
86}
87
88/// Naively combines a series of paths with the native path seperator.
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);
4492}
4593
46pub fn joinWindows(allocator: *Allocator, paths: ...) ![]u8 {
47 return mem.join(allocator, sep_windows, paths);
94fn testJoinWindows(paths: []const []const u8, expected: []const u8) void {
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);
4899}
49100
50pub fn joinPosix(allocator: *Allocator, paths: ...) ![]u8 {
51 return mem.join(allocator, sep_posix, paths);
101fn testJoinPosix(paths: []const []const u8, expected: []const u8) void {
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);
52106}
53107
54108test "os.path.join" {
55 assert(mem.eql(u8, try joinWindows(debug.global_allocator, "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"));
109 testJoinWindows([][]const u8{ "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"));
59 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");
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"));
64 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");
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"));
67 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");
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");
70134}
71135
72136pub fn isAbsolute(path: []const u8) bool {
......@@ -130,11 +194,11 @@ test "os.path.isAbsolutePosix" {
130194}
131195
132196fn testIsAbsoluteWindows(path: []const u8, expected_result: bool) void {
133 assert(isAbsoluteWindows(path) == expected_result);
197 testing.expectEqual(expected_result, isAbsoluteWindows(path));
134198}
135199
136200fn testIsAbsolutePosix(path: []const u8, expected_result: bool) void {
137 assert(isAbsolutePosix(path) == expected_result);
201 testing.expectEqual(expected_result, isAbsolutePosix(path));
138202}
139203
140204pub const WindowsPath = struct {
......@@ -184,7 +248,7 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {
184248 return relative_path;
185249 }
186250
187 var it = mem.split(path, []u8{this_sep});
251 var it = mem.tokenize(path, []u8{this_sep});
188252 _ = (it.next() orelse return relative_path);
189253 _ = (it.next() orelse return relative_path);
190254 return WindowsPath{
......@@ -202,7 +266,7 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {
202266 return relative_path;
203267 }
204268
205 var it = mem.split(path, []u8{this_sep});
269 var it = mem.tokenize(path, []u8{this_sep});
206270 _ = (it.next() orelse return relative_path);
207271 _ = (it.next() orelse return relative_path);
208272 return WindowsPath{
......@@ -218,33 +282,33 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {
218282test "os.path.windowsParsePath" {
219283 {
220284 const parsed = windowsParsePath("//a/b");
221 assert(parsed.is_abs);
222 assert(parsed.kind == WindowsPath.Kind.NetworkShare);
223 assert(mem.eql(u8, parsed.disk_designator, "//a/b"));
285 testing.expect(parsed.is_abs);
286 testing.expect(parsed.kind == WindowsPath.Kind.NetworkShare);
287 testing.expect(mem.eql(u8, parsed.disk_designator, "//a/b"));
224288 }
225289 {
226290 const parsed = windowsParsePath("\\\\a\\b");
227 assert(parsed.is_abs);
228 assert(parsed.kind == WindowsPath.Kind.NetworkShare);
229 assert(mem.eql(u8, parsed.disk_designator, "\\\\a\\b"));
291 testing.expect(parsed.is_abs);
292 testing.expect(parsed.kind == WindowsPath.Kind.NetworkShare);
293 testing.expect(mem.eql(u8, parsed.disk_designator, "\\\\a\\b"));
230294 }
231295 {
232296 const parsed = windowsParsePath("\\\\a\\");
233 assert(!parsed.is_abs);
234 assert(parsed.kind == WindowsPath.Kind.None);
235 assert(mem.eql(u8, parsed.disk_designator, ""));
297 testing.expect(!parsed.is_abs);
298 testing.expect(parsed.kind == WindowsPath.Kind.None);
299 testing.expect(mem.eql(u8, parsed.disk_designator, ""));
236300 }
237301 {
238302 const parsed = windowsParsePath("/usr/local");
239 assert(parsed.is_abs);
240 assert(parsed.kind == WindowsPath.Kind.None);
241 assert(mem.eql(u8, parsed.disk_designator, ""));
303 testing.expect(parsed.is_abs);
304 testing.expect(parsed.kind == WindowsPath.Kind.None);
305 testing.expect(mem.eql(u8, parsed.disk_designator, ""));
242306 }
243307 {
244308 const parsed = windowsParsePath("c:../");
245 assert(!parsed.is_abs);
246 assert(parsed.kind == WindowsPath.Kind.Drive);
247 assert(mem.eql(u8, parsed.disk_designator, "c:"));
309 testing.expect(!parsed.is_abs);
310 testing.expect(parsed.kind == WindowsPath.Kind.Drive);
311 testing.expect(mem.eql(u8, parsed.disk_designator, "c:"));
248312 }
249313}
250314
......@@ -264,8 +328,8 @@ fn networkShareServersEql(ns1: []const u8, ns2: []const u8) bool {
264328 const sep1 = ns1[0];
265329 const sep2 = ns2[0];
266330
267 var it1 = mem.split(ns1, []u8{sep1});
268 var it2 = mem.split(ns2, []u8{sep2});
331 var it1 = mem.tokenize(ns1, []u8{sep1});
332 var it2 = mem.tokenize(ns2, []u8{sep2});
269333
270334 // TODO ASCII is wrong, we actually need full unicode support to compare paths.
271335 return asciiEqlIgnoreCase(it1.next().?, it2.next().?);
......@@ -285,8 +349,8 @@ fn compareDiskDesignators(kind: WindowsPath.Kind, p1: []const u8, p2: []const u8
285349 const sep1 = p1[0];
286350 const sep2 = p2[0];
287351
288 var it1 = mem.split(p1, []u8{sep1});
289 var it2 = mem.split(p2, []u8{sep2});
352 var it1 = mem.tokenize(p1, []u8{sep1});
353 var it2 = mem.tokenize(p2, []u8{sep2});
290354
291355 // TODO ASCII is wrong, we actually need full unicode support to compare paths.
292356 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 {
312376 return true;
313377}
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
325379/// 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 {
327381 if (is_windows) {
328382 return resolveWindows(allocator, paths);
329383 } else {
......@@ -337,6 +391,8 @@ pub fn resolveSlice(allocator: *Allocator, paths: []const []const u8) ![]u8 {
337391/// If all paths are relative it uses the current working directory as a starting point.
338392/// Each drive has its own current working directory.
339393/// 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.
340396pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
341397 if (paths.len == 0) {
342398 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 {
416472 },
417473 WindowsPath.Kind.NetworkShare => {
418474 result = try allocator.alloc(u8, max_size);
419 var it = mem.split(paths[first_index], "/\\");
475 var it = mem.tokenize(paths[first_index], "/\\");
420476 const server_name = it.next().?;
421477 const other_name = it.next().?;
422478
......@@ -483,7 +539,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
483539 if (!correct_disk_designator) {
484540 continue;
485541 }
486 var it = mem.split(p[parsed.disk_designator.len..], "/\\");
542 var it = mem.tokenize(p[parsed.disk_designator.len..], "/\\");
487543 while (it.next()) |component| {
488544 if (mem.eql(u8, component, ".")) {
489545 continue;
......@@ -516,6 +572,8 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
516572/// It resolves "." and "..".
517573/// The result does not have a trailing path separator.
518574/// 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.
519577pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
520578 if (paths.len == 0) {
521579 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 {
550608 errdefer allocator.free(result);
551609
552610 for (paths[first_index..]) |p, i| {
553 var it = mem.split(p, "/");
611 var it = mem.tokenize(p, "/");
554612 while (it.next()) |component| {
555613 if (mem.eql(u8, component, ".")) {
556614 continue;
......@@ -585,10 +643,10 @@ test "os.path.resolve" {
585643 if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) {
586644 cwd[0] = asciiUpper(cwd[0]);
587645 }
588 assert(mem.eql(u8, testResolveWindows([][]const u8{"."}), cwd));
646 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{"."}), cwd));
589647 } else {
590 assert(mem.eql(u8, testResolvePosix([][]const u8{ "a/b/c/", "../../.." }), cwd));
591 assert(mem.eql(u8, testResolvePosix([][]const u8{"."}), cwd));
648 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "a/b/c/", "../../.." }), cwd));
649 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{"."}), cwd));
592650 }
593651}
594652
......@@ -598,48 +656,54 @@ test "os.path.resolveWindows" {
598656 const parsed_cwd = windowsParsePath(cwd);
599657 {
600658 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 });
602663 if (parsed_cwd.kind == WindowsPath.Kind.Drive) {
603664 expected[0] = asciiUpper(parsed_cwd.disk_designator[0]);
604665 }
605 assert(mem.eql(u8, result, expected));
666 testing.expect(mem.eql(u8, result, expected));
606667 }
607668 {
608669 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 });
610674 if (parsed_cwd.kind == WindowsPath.Kind.Drive) {
611675 expected[0] = asciiUpper(parsed_cwd.disk_designator[0]);
612676 }
613 assert(mem.eql(u8, result, expected));
677 testing.expect(mem.eql(u8, result, expected));
614678 }
615679 }
616680
617 assert(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"));
619 assert(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"));
621 assert(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"));
623 assert(mem.eql(u8, testResolveWindows([][]const u8{ "//server/share", "..", "relative\\" }), "\\\\server\\share\\relative"));
624 assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//" }), "C:\\"));
625 assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//dir" }), "C:\\dir"));
626 assert(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//server/share" }), "\\\\server\\share\\"));
627 assert(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"));
629 assert(mem.eql(u8, testResolveWindows([][]const u8{ "C:\\foo\\tmp.3\\", "..\\tmp.3\\cycles\\root.js" }), "C:\\foo\\tmp.3\\cycles\\root.js"));
681 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:\\a\\b\\c", "/hi", "ok" }), "C:\\hi\\ok"));
682 testing.expect(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"));
684 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/ignore", "d:\\a/b\\c/d", "\\e.exe" }), "D:\\e.exe"));
685 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/ignore", "c:/some/file" }), "C:\\some\\file"));
686 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "d:/ignore", "d:some/dir//" }), "D:\\ignore\\some\\dir"));
687 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "//server/share", "..", "relative\\" }), "\\\\server\\share\\relative"));
688 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//" }), "C:\\"));
689 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "//dir" }), "C:\\dir"));
690 testing.expect(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\\"));
692 testing.expect(mem.eql(u8, testResolveWindows([][]const u8{ "c:/", "///some//dir" }), "C:\\some\\dir"));
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"));
630694}
631695
632696test "os.path.resolvePosix" {
633 assert(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"));
635 assert(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b/c", "..", "../" }), "/a"));
636 assert(mem.eql(u8, testResolvePosix([][]const u8{ "/", "..", ".." }), "/"));
637 assert(mem.eql(u8, testResolvePosix([][]const u8{"/a/b/c/"}), "/a/b/c"));
638
639 assert(mem.eql(u8, testResolvePosix([][]const u8{ "/var/lib", "../", "file/" }), "/var/file"));
640 assert(mem.eql(u8, testResolvePosix([][]const u8{ "/var/lib", "/../", "file/" }), "/file"));
641 assert(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"));
697 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b", "c" }), "/a/b/c"));
698 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b", "c", "//d", "e///" }), "/d/e"));
699 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/a/b/c", "..", "../" }), "/a"));
700 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/", "..", ".." }), "/"));
701 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{"/a/b/c/"}), "/a/b/c"));
702
703 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/var/lib", "../", "file/" }), "/var/file"));
704 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/var/lib", "/../", "file/" }), "/file"));
705 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/some/dir", ".", "/absolute/" }), "/absolute"));
706 testing.expect(mem.eql(u8, testResolvePosix([][]const u8{ "/foo/tmp.3/", "../tmp.3/cycles/root.js" }), "/foo/tmp.3/cycles/root.js"));
643707}
644708
645709fn testResolveWindows(paths: []const []const u8) []u8 {
......@@ -770,17 +834,17 @@ test "os.path.dirnameWindows" {
770834
771835fn testDirnamePosix(input: []const u8, expected_output: ?[]const u8) void {
772836 if (dirnamePosix(input)) |output| {
773 assert(mem.eql(u8, output, expected_output.?));
837 testing.expect(mem.eql(u8, output, expected_output.?));
774838 } else {
775 assert(expected_output == null);
839 testing.expect(expected_output == null);
776840 }
777841}
778842
779843fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) void {
780844 if (dirnameWindows(input)) |output| {
781 assert(mem.eql(u8, output, expected_output.?));
845 testing.expect(mem.eql(u8, output, expected_output.?));
782846 } else {
783 assert(expected_output == null);
847 testing.expect(expected_output == null);
784848 }
785849}
786850
......@@ -885,15 +949,15 @@ test "os.path.basename" {
885949}
886950
887951fn 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));
889953}
890954
891955fn 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));
893957}
894958
895959fn 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));
897961}
898962
899963/// 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)
9371001 return resolved_to;
9381002 }
9391003
940 var from_it = mem.split(resolved_from, "/\\");
941 var to_it = mem.split(resolved_to, "/\\");
1004 var from_it = mem.tokenize(resolved_from, "/\\");
1005 var to_it = mem.tokenize(resolved_to, "/\\");
9421006 while (true) {
9431007 const from_component = from_it.next() orelse return mem.dupe(allocator, u8, to_it.rest());
9441008 const to_rest = to_it.rest();
......@@ -967,7 +1031,7 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8)
9671031 // shave off the trailing slash
9681032 result_index -= 1;
9691033
970 var rest_it = mem.split(to_rest, "/\\");
1034 var rest_it = mem.tokenize(to_rest, "/\\");
9711035 while (rest_it.next()) |to_component| {
9721036 result[result_index] = '\\';
9731037 result_index += 1;
......@@ -988,8 +1052,8 @@ pub fn relativePosix(allocator: *Allocator, from: []const u8, to: []const u8) ![
9881052 const resolved_to = try resolvePosix(allocator, [][]const u8{to});
9891053 defer allocator.free(resolved_to);
9901054
991 var from_it = mem.split(resolved_from, "/");
992 var to_it = mem.split(resolved_to, "/");
1055 var from_it = mem.tokenize(resolved_from, "/");
1056 var to_it = mem.tokenize(resolved_to, "/");
9931057 while (true) {
9941058 const from_component = from_it.next() orelse return mem.dupe(allocator, u8, to_it.rest());
9951059 const to_rest = to_it.rest();
......@@ -1068,12 +1132,12 @@ test "os.path.relative" {
10681132
10691133fn testRelativePosix(from: []const u8, to: []const u8, expected_output: []const u8) void {
10701134 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);
10721136}
10731137
10741138fn testRelativeWindows(from: []const u8, to: []const u8, expected_output: []const u8) void {
10751139 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);
10771141}
10781142
10791143pub const RealError = error{
......@@ -1093,6 +1157,7 @@ pub const RealError = error{
10931157 NoSpaceLeft,
10941158 FileSystem,
10951159 BadPathName,
1160 DeviceBusy,
10961161
10971162 /// On Windows, file paths must be valid Unicode.
10981163 InvalidUtf8,
......@@ -1161,7 +1226,7 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro
11611226 const pathname_w = try windows_util.cStrToPrefixedFileW(pathname);
11621227 return realW(out_buffer, pathname_w);
11631228 },
1164 Os.macosx, Os.ios => {
1229 Os.freebsd, Os.macosx, Os.ios => {
11651230 // TODO instead of calling the libc function here, port the implementation to Zig
11661231 const err = posix.getErrno(posix.realpath(pathname, out_buffer));
11671232 switch (err) {
......@@ -1188,15 +1253,6 @@ pub fn realC(out_buffer: *[os.MAX_PATH_BYTES]u8, pathname: [*]const u8) RealErro
11881253
11891254 return os.readLinkC(out_buffer, proc_path.ptr);
11901255 },
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 },
12001256 else => @compileError("TODO implement os.path.real for " ++ @tagName(builtin.os)),
12011257 }
12021258}
......@@ -1228,5 +1284,5 @@ pub fn realAlloc(allocator: *Allocator, pathname: []const u8) ![]u8 {
12281284test "os.path.real" {
12291285 // at least call it so it gets compiled
12301286 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"));
12321288}
std/os/test.zig+28-8
......@@ -1,6 +1,6 @@
11const std = @import("../index.zig");
22const os = std.os;
3const assert = std.debug.assert;
3const expect = std.testing.expect;
44const io = std.io;
55const mem = std.mem;
66
......@@ -18,7 +18,7 @@ test "makePath, put some files in it, deleteTree" {
1818 if (os.Dir.open(a, "os_test_tmp")) |dir| {
1919 @panic("expected error");
2020 } else |err| {
21 assert(err == error.FileNotFound);
21 expect(err == error.FileNotFound);
2222 }
2323}
2424
......@@ -27,7 +27,7 @@ test "access file" {
2727 if (os.File.access("os_test_tmp" ++ os.path.sep_str ++ "file.txt")) |ok| {
2828 @panic("expected error");
2929 } else |err| {
30 assert(err == error.FileNotFound);
30 expect(err == error.FileNotFound);
3131 }
3232
3333 try io.writeFile("os_test_tmp" ++ os.path.sep_str ++ "file.txt", "");
......@@ -40,19 +40,23 @@ fn testThreadIdFn(thread_id: *os.Thread.Id) void {
4040}
4141
4242test "std.os.Thread.getCurrentId" {
43 if (builtin.single_threaded) return error.SkipZigTest;
44
4345 var thread_current_id: os.Thread.Id = undefined;
4446 const thread = try os.spawnThread(&thread_current_id, testThreadIdFn);
4547 const thread_id = thread.handle();
4648 thread.wait();
4749 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),
4951 else => {
50 assert(thread_current_id == thread_id);
52 expect(thread_current_id == thread_id);
5153 },
5254 }
5355}
5456
5557test "spawn threads" {
58 if (builtin.single_threaded) return error.SkipZigTest;
59
5660 var shared_ctx: i32 = 1;
5761
5862 const thread1 = try std.os.spawnThread({}, start1);
......@@ -65,7 +69,7 @@ test "spawn threads" {
6569 thread3.wait();
6670 thread4.wait();
6771
68 assert(shared_ctx == 4);
72 expect(shared_ctx == 4);
6973}
7074
7175fn start1(ctx: void) u8 {
......@@ -79,7 +83,7 @@ fn start2(ctx: *i32) u8 {
7983
8084test "cpu count" {
8185 const cpu_count = try std.os.cpuCount(a);
82 assert(cpu_count >= 1);
86 expect(cpu_count >= 1);
8387}
8488
8589test "AtomicFile" {
......@@ -97,7 +101,23 @@ test "AtomicFile" {
97101 try af.finish();
98102 }
99103 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
102106 try os.deleteFile(test_out_file);
103107}
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");
22const builtin = @import("builtin");
33const Os = builtin.Os;
44const debug = std.debug;
5const testing = std.testing;
56
67const windows = std.os.windows;
78const linux = std.os.linux;
......@@ -13,7 +14,7 @@ pub const epoch = @import("epoch.zig");
1314/// Sleep for the specified duration
1415pub fn sleep(nanoseconds: u64) void {
1516 switch (builtin.os) {
16 Os.linux, Os.macosx, Os.ios => {
17 Os.linux, Os.macosx, Os.ios, Os.freebsd => {
1718 const s = nanoseconds / ns_per_s;
1819 const ns = nanoseconds % ns_per_s;
1920 posixSleep(@intCast(u63, s), @intCast(u63, ns));
......@@ -61,7 +62,7 @@ pub fn timestamp() u64 {
6162/// Get the posix timestamp, UTC, in milliseconds
6263pub const milliTimestamp = switch (builtin.os) {
6364 Os.windows => milliTimestampWindows,
64 Os.linux => milliTimestampPosix,
65 Os.linux, Os.freebsd => milliTimestampPosix,
6566 Os.macosx, Os.ios => milliTimestampDarwin,
6667 else => @compileError("Unsupported OS"),
6768};
......@@ -79,14 +80,12 @@ fn milliTimestampWindows() u64 {
7980}
8081
8182fn milliTimestampDarwin() u64 {
82 //Sources suggest MacOS 10.12 has support for
83 // posix clock_gettime.
8483 var tv: darwin.timeval = undefined;
8584 var err = darwin.gettimeofday(&tv, null);
8685 debug.assert(err == 0);
87 const sec_ms = @intCast(u64, tv.tv_sec) * ms_per_s;
88 const usec_ms = @divFloor(@intCast(u64, tv.tv_usec), us_per_s / ms_per_s);
89 return u64(sec_ms) + u64(usec_ms);
86 const sec_ms = tv.tv_sec * ms_per_s;
87 const usec_ms = @divFloor(tv.tv_usec, us_per_s / ms_per_s);
88 return @intCast(u64, sec_ms + usec_ms);
9089}
9190
9291fn milliTimestampPosix() u64 {
......@@ -179,7 +178,7 @@ pub const Timer = struct {
179178 debug.assert(err != windows.FALSE);
180179 self.start_time = @intCast(u64, start_time);
181180 },
182 Os.linux => {
181 Os.linux, Os.freebsd => {
183182 //On Linux, seccomp can do arbitrary things to our ability to call
184183 // syscalls, including return any errno value it wants and
185184 // inconsistently throwing errors. Since we can't account for
......@@ -215,7 +214,7 @@ pub const Timer = struct {
215214 var clock = clockNative() - self.start_time;
216215 return switch (builtin.os) {
217216 Os.windows => @divFloor(clock * ns_per_s, self.frequency),
218 Os.linux => clock,
217 Os.linux, Os.freebsd => clock,
219218 Os.macosx, Os.ios => @divFloor(clock * self.frequency.numer, self.frequency.denom),
220219 else => @compileError("Unsupported OS"),
221220 };
......@@ -236,7 +235,7 @@ pub const Timer = struct {
236235
237236 const clockNative = switch (builtin.os) {
238237 Os.windows => clockWindows,
239 Os.linux => clockLinux,
238 Os.linux, Os.freebsd => clockLinux,
240239 Os.macosx, Os.ios => clockDarwin,
241240 else => @compileError("Unsupported OS"),
242241 };
......@@ -272,7 +271,7 @@ test "os.time.timestamp" {
272271 sleep(ns_per_ms);
273272 const time_1 = milliTimestamp();
274273 const interval = time_1 - time_0;
275 debug.assert(interval > 0 and interval < margin);
274 testing.expect(interval > 0 and interval < margin);
276275}
277276
278277test "os.time.Timer" {
......@@ -282,11 +281,11 @@ test "os.time.Timer" {
282281 var timer = try Timer.start();
283282 sleep(10 * ns_per_ms);
284283 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
287286 const time_1 = timer.lap();
288 debug.assert(time_1 >= time_0);
287 testing.expect(time_1 >= time_0);
289288
290289 timer.reset();
291 debug.assert(timer.read() < time_1);
290 testing.expect(timer.read() < time_1);
292291}
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;
4949pub const WCHAR = u16;
5050pub const WORD = u16;
5151pub const LARGE_INTEGER = i64;
52pub const ULONG = u32;
53pub const LONG = i32;
54pub const ULONGLONG = u64;
55pub const LONGLONG = i64;
5256
5357pub const TRUE = 1;
5458pub const FALSE = 0;
......@@ -379,3 +383,17 @@ pub const COORD = extern struct {
379383};
380384
381385pub 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
5050pub extern "kernel32" stdcallcc fn FindClose(hFindFile: HANDLE) BOOL;
5151pub 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
5555pub extern "kernel32" stdcallcc fn GetCommandLineA() LPSTR;
5656
......@@ -63,9 +63,9 @@ pub extern "kernel32" stdcallcc fn GetCurrentDirectoryW(nBufferLength: DWORD, lp
6363pub extern "kernel32" stdcallcc fn GetCurrentThread() HANDLE;
6464pub 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
7070pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: *DWORD) BOOL;
7171
......@@ -164,6 +164,10 @@ pub extern "kernel32" stdcallcc fn Sleep(dwMilliseconds: DWORD) void;
164164
165165pub 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
167171pub extern "kernel32" stdcallcc fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) DWORD;
168172
169173pub extern "kernel32" stdcallcc fn WriteFile(
......@@ -220,3 +224,50 @@ pub const FOREGROUND_BLUE = 1;
220224pub const FOREGROUND_GREEN = 2;
221225pub const FOREGROUND_RED = 4;
222226pub 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;
99
1010const 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
1216// https://llvm.org/docs/PDB/DbiStream.html#stream-header
1317pub const DbiStreamHeader = packed struct {
1418 VersionSignature: i32,
......@@ -345,6 +349,10 @@ pub const RecordPrefix = packed struct {
345349 RecordKind: SymbolKind,
346350};
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.
348356pub const LineFragmentHeader = packed struct {
349357 /// Code offset of line contribution.
350358 RelocOffset: u32,
......@@ -386,7 +394,11 @@ pub const LineNumberEntry = packed struct {
386394
387395 /// TODO runtime crash when I make the actual type of Flags this
388396 const Flags = packed struct {
397 /// Start line number
389398 Start: u24,
399
400 /// Delta of lines to the end of the expression. Still unclear.
401 // TODO figure out the point of this field.
390402 End: u7,
391403 IsStatement: bool,
392404 };
......@@ -508,11 +520,11 @@ const Msf = struct {
508520 allocator,
509521 );
510522
511 const stream_count = try self.directory.stream.readIntLe(u32);
523 const stream_count = try self.directory.stream.readIntLittle(u32);
512524
513525 const stream_sizes = try allocator.alloc(u32, stream_count);
514526 for (stream_sizes) |*s| {
515 const size = try self.directory.stream.readIntLe(u32);
527 const size = try self.directory.stream.readIntLittle(u32);
516528 s.* = blockCountFromSize(size, superblock.BlockSize);
517529 }
518530
......@@ -603,7 +615,7 @@ const MsfStream = struct {
603615
604616 var i: u32 = 0;
605617 while (i < block_count) : (i += 1) {
606 stream.blocks[i] = try in.readIntLe(u32);
618 stream.blocks[i] = try in.readIntLittle(u32);
607619 }
608620
609621 return stream;
std/rand/index.zig+87-82
......@@ -5,7 +5,7 @@
55// ```
66// var buf: [8]u8 = undefined;
77// try std.os.getRandomBytes(buf[0..]);
8// const seed = mem.readIntLE(u64, buf[0..8]);
8// const seed = mem.readIntSliceLittle(u64, buf[0..8]);
99//
1010// var r = DefaultPrng.init(seed);
1111//
......@@ -17,6 +17,7 @@
1717const std = @import("../index.zig");
1818const builtin = @import("builtin");
1919const assert = std.debug.assert;
20const expect = std.testing.expect;
2021const mem = std.mem;
2122const math = std.math;
2223const ziggurat = @import("ziggurat.zig");
......@@ -52,7 +53,7 @@ pub const Random = struct {
5253 // use LE instead of native endian for better portability maybe?
5354 // TODO: endian portability is pointless if the underlying prng isn't endian portable.
5455 // 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);
5657 const unsigned_result = @truncate(UnsignedT, byte_aligned_result);
5758 return @bitCast(T, unsigned_result);
5859 }
......@@ -69,6 +70,7 @@ pub const Random = struct {
6970 return @intCast(T, limitRangeBiased(u64, r.int(u64), less_than));
7071 }
7172 }
73
7274 /// Returns an evenly distributed random unsigned integer `0 <= i < less_than`.
7375 /// This function assumes that the underlying ::fillFn produces evenly distributed values.
7476 /// Within this assumption, the runtime of this function is exponentially distributed.
......@@ -123,6 +125,7 @@ pub const Random = struct {
123125 }
124126 return r.uintLessThanBiased(T, at_most + 1);
125127 }
128
126129 /// Returns an evenly distributed random unsigned integer `0 <= i <= at_most`.
127130 /// See ::uintLessThan, which this function uses in most cases,
128131 /// for commentary on the runtime of this function.
......@@ -151,6 +154,7 @@ pub const Random = struct {
151154 return at_least + r.uintLessThanBiased(T, less_than - at_least);
152155 }
153156 }
157
154158 /// Returns an evenly distributed random integer `at_least <= i < less_than`.
155159 /// See ::uintLessThan, which this function uses in most cases,
156160 /// for commentary on the runtime of this function.
......@@ -185,6 +189,7 @@ pub const Random = struct {
185189 return at_least + r.uintAtMostBiased(T, at_most - at_least);
186190 }
187191 }
192
188193 /// Returns an evenly distributed random integer `at_least <= i <= at_most`.
189194 /// See ::uintLessThan, which this function uses in most cases,
190195 /// for commentary on the runtime of this function.
......@@ -312,43 +317,43 @@ test "Random int" {
312317fn testRandomInt() void {
313318 var r = SequentialPrng.init();
314319
315 assert(r.random.int(u0) == 0);
320 expect(r.random.int(u0) == 0);
316321
317322 r.next_value = 0;
318 assert(r.random.int(u1) == 0);
319 assert(r.random.int(u1) == 1);
320 assert(r.random.int(u2) == 2);
321 assert(r.random.int(u2) == 3);
322 assert(r.random.int(u2) == 0);
323 expect(r.random.int(u1) == 0);
324 expect(r.random.int(u1) == 1);
325 expect(r.random.int(u2) == 2);
326 expect(r.random.int(u2) == 3);
327 expect(r.random.int(u2) == 0);
323328
324329 r.next_value = 0xff;
325 assert(r.random.int(u8) == 0xff);
330 expect(r.random.int(u8) == 0xff);
326331 r.next_value = 0x11;
327 assert(r.random.int(u8) == 0x11);
332 expect(r.random.int(u8) == 0x11);
328333
329334 r.next_value = 0xff;
330 assert(r.random.int(u32) == 0xffffffff);
335 expect(r.random.int(u32) == 0xffffffff);
331336 r.next_value = 0x11;
332 assert(r.random.int(u32) == 0x11111111);
337 expect(r.random.int(u32) == 0x11111111);
333338
334339 r.next_value = 0xff;
335 assert(r.random.int(i32) == -1);
340 expect(r.random.int(i32) == -1);
336341 r.next_value = 0x11;
337 assert(r.random.int(i32) == 0x11111111);
342 expect(r.random.int(i32) == 0x11111111);
338343
339344 r.next_value = 0xff;
340 assert(r.random.int(i8) == -1);
345 expect(r.random.int(i8) == -1);
341346 r.next_value = 0x11;
342 assert(r.random.int(i8) == 0x11);
347 expect(r.random.int(i8) == 0x11);
343348
344349 r.next_value = 0xff;
345 assert(r.random.int(u33) == 0x1ffffffff);
350 expect(r.random.int(u33) == 0x1ffffffff);
346351 r.next_value = 0xff;
347 assert(r.random.int(i1) == -1);
352 expect(r.random.int(i1) == -1);
348353 r.next_value = 0xff;
349 assert(r.random.int(i2) == -1);
354 expect(r.random.int(i2) == -1);
350355 r.next_value = 0xff;
351 assert(r.random.int(i33) == -1);
356 expect(r.random.int(i33) == -1);
352357}
353358
354359test "Random boolean" {
......@@ -357,10 +362,10 @@ test "Random boolean" {
357362}
358363fn testRandomBoolean() void {
359364 var r = SequentialPrng.init();
360 assert(r.random.boolean() == false);
361 assert(r.random.boolean() == true);
362 assert(r.random.boolean() == false);
363 assert(r.random.boolean() == true);
365 expect(r.random.boolean() == false);
366 expect(r.random.boolean() == true);
367 expect(r.random.boolean() == false);
368 expect(r.random.boolean() == true);
364369}
365370
366371test "Random intLessThan" {
......@@ -371,36 +376,36 @@ test "Random intLessThan" {
371376fn testRandomIntLessThan() void {
372377 var r = SequentialPrng.init();
373378 r.next_value = 0xff;
374 assert(r.random.uintLessThan(u8, 4) == 3);
375 assert(r.next_value == 0);
376 assert(r.random.uintLessThan(u8, 4) == 0);
377 assert(r.next_value == 1);
379 expect(r.random.uintLessThan(u8, 4) == 3);
380 expect(r.next_value == 0);
381 expect(r.random.uintLessThan(u8, 4) == 0);
382 expect(r.next_value == 1);
378383
379384 r.next_value = 0;
380 assert(r.random.uintLessThan(u64, 32) == 0);
385 expect(r.random.uintLessThan(u64, 32) == 0);
381386
382387 // trigger the bias rejection code path
383388 r.next_value = 0;
384 assert(r.random.uintLessThan(u8, 3) == 0);
389 expect(r.random.uintLessThan(u8, 3) == 0);
385390 // verify we incremented twice
386 assert(r.next_value == 2);
391 expect(r.next_value == 2);
387392
388393 r.next_value = 0xff;
389 assert(r.random.intRangeLessThan(u8, 0, 0x80) == 0x7f);
394 expect(r.random.intRangeLessThan(u8, 0, 0x80) == 0x7f);
390395 r.next_value = 0xff;
391 assert(r.random.intRangeLessThan(u8, 0x7f, 0xff) == 0xfe);
396 expect(r.random.intRangeLessThan(u8, 0x7f, 0xff) == 0xfe);
392397
393398 r.next_value = 0xff;
394 assert(r.random.intRangeLessThan(i8, 0, 0x40) == 0x3f);
399 expect(r.random.intRangeLessThan(i8, 0, 0x40) == 0x3f);
395400 r.next_value = 0xff;
396 assert(r.random.intRangeLessThan(i8, -0x40, 0x40) == 0x3f);
401 expect(r.random.intRangeLessThan(i8, -0x40, 0x40) == 0x3f);
397402 r.next_value = 0xff;
398 assert(r.random.intRangeLessThan(i8, -0x80, 0) == -1);
403 expect(r.random.intRangeLessThan(i8, -0x80, 0) == -1);
399404
400405 r.next_value = 0xff;
401 assert(r.random.intRangeLessThan(i3, -4, 0) == -1);
406 expect(r.random.intRangeLessThan(i3, -4, 0) == -1);
402407 r.next_value = 0xff;
403 assert(r.random.intRangeLessThan(i3, -2, 2) == 1);
408 expect(r.random.intRangeLessThan(i3, -2, 2) == 1);
404409}
405410
406411test "Random intAtMost" {
......@@ -411,34 +416,34 @@ test "Random intAtMost" {
411416fn testRandomIntAtMost() void {
412417 var r = SequentialPrng.init();
413418 r.next_value = 0xff;
414 assert(r.random.uintAtMost(u8, 3) == 3);
415 assert(r.next_value == 0);
416 assert(r.random.uintAtMost(u8, 3) == 0);
419 expect(r.random.uintAtMost(u8, 3) == 3);
420 expect(r.next_value == 0);
421 expect(r.random.uintAtMost(u8, 3) == 0);
417422
418423 // trigger the bias rejection code path
419424 r.next_value = 0;
420 assert(r.random.uintAtMost(u8, 2) == 0);
425 expect(r.random.uintAtMost(u8, 2) == 0);
421426 // verify we incremented twice
422 assert(r.next_value == 2);
427 expect(r.next_value == 2);
423428
424429 r.next_value = 0xff;
425 assert(r.random.intRangeAtMost(u8, 0, 0x7f) == 0x7f);
430 expect(r.random.intRangeAtMost(u8, 0, 0x7f) == 0x7f);
426431 r.next_value = 0xff;
427 assert(r.random.intRangeAtMost(u8, 0x7f, 0xfe) == 0xfe);
432 expect(r.random.intRangeAtMost(u8, 0x7f, 0xfe) == 0xfe);
428433
429434 r.next_value = 0xff;
430 assert(r.random.intRangeAtMost(i8, 0, 0x3f) == 0x3f);
435 expect(r.random.intRangeAtMost(i8, 0, 0x3f) == 0x3f);
431436 r.next_value = 0xff;
432 assert(r.random.intRangeAtMost(i8, -0x40, 0x3f) == 0x3f);
437 expect(r.random.intRangeAtMost(i8, -0x40, 0x3f) == 0x3f);
433438 r.next_value = 0xff;
434 assert(r.random.intRangeAtMost(i8, -0x80, -1) == -1);
439 expect(r.random.intRangeAtMost(i8, -0x80, -1) == -1);
435440
436441 r.next_value = 0xff;
437 assert(r.random.intRangeAtMost(i3, -4, -1) == -1);
442 expect(r.random.intRangeAtMost(i3, -4, -1) == -1);
438443 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);
442447}
443448
444449test "Random Biased" {
......@@ -446,30 +451,30 @@ test "Random Biased" {
446451 // Not thoroughly checking the logic here.
447452 // Just want to execute all the paths with different types.
448453
449 assert(r.random.uintLessThanBiased(u1, 1) == 0);
450 assert(r.random.uintLessThanBiased(u32, 10) < 10);
451 assert(r.random.uintLessThanBiased(u64, 20) < 20);
454 expect(r.random.uintLessThanBiased(u1, 1) == 0);
455 expect(r.random.uintLessThanBiased(u32, 10) < 10);
456 expect(r.random.uintLessThanBiased(u64, 20) < 20);
452457
453 assert(r.random.uintAtMostBiased(u0, 0) == 0);
454 assert(r.random.uintAtMostBiased(u1, 0) <= 0);
455 assert(r.random.uintAtMostBiased(u32, 10) <= 10);
456 assert(r.random.uintAtMostBiased(u64, 20) <= 20);
458 expect(r.random.uintAtMostBiased(u0, 0) == 0);
459 expect(r.random.uintAtMostBiased(u1, 0) <= 0);
460 expect(r.random.uintAtMostBiased(u32, 10) <= 10);
461 expect(r.random.uintAtMostBiased(u64, 20) <= 20);
457462
458 assert(r.random.intRangeLessThanBiased(u1, 0, 1) == 0);
459 assert(r.random.intRangeLessThanBiased(i1, -1, 0) == -1);
460 assert(r.random.intRangeLessThanBiased(u32, 10, 20) >= 10);
461 assert(r.random.intRangeLessThanBiased(i32, 10, 20) >= 10);
462 assert(r.random.intRangeLessThanBiased(u64, 20, 40) >= 20);
463 assert(r.random.intRangeLessThanBiased(i64, 20, 40) >= 20);
463 expect(r.random.intRangeLessThanBiased(u1, 0, 1) == 0);
464 expect(r.random.intRangeLessThanBiased(i1, -1, 0) == -1);
465 expect(r.random.intRangeLessThanBiased(u32, 10, 20) >= 10);
466 expect(r.random.intRangeLessThanBiased(i32, 10, 20) >= 10);
467 expect(r.random.intRangeLessThanBiased(u64, 20, 40) >= 20);
468 expect(r.random.intRangeLessThanBiased(i64, 20, 40) >= 20);
464469
465470 // uncomment for broken module error:
466 //assert(r.random.intRangeAtMostBiased(u0, 0, 0) == 0);
467 assert(r.random.intRangeAtMostBiased(u1, 0, 1) >= 0);
468 assert(r.random.intRangeAtMostBiased(i1, -1, 0) >= -1);
469 assert(r.random.intRangeAtMostBiased(u32, 10, 20) >= 10);
470 assert(r.random.intRangeAtMostBiased(i32, 10, 20) >= 10);
471 assert(r.random.intRangeAtMostBiased(u64, 20, 40) >= 20);
472 assert(r.random.intRangeAtMostBiased(i64, 20, 40) >= 20);
471 //expect(r.random.intRangeAtMostBiased(u0, 0, 0) == 0);
472 expect(r.random.intRangeAtMostBiased(u1, 0, 1) >= 0);
473 expect(r.random.intRangeAtMostBiased(i1, -1, 0) >= -1);
474 expect(r.random.intRangeAtMostBiased(u32, 10, 20) >= 10);
475 expect(r.random.intRangeAtMostBiased(i32, 10, 20) >= 10);
476 expect(r.random.intRangeAtMostBiased(u64, 20, 40) >= 20);
477 expect(r.random.intRangeAtMostBiased(i64, 20, 40) >= 20);
473478}
474479
475480// Generator to extend 64-bit seed values into longer sequences.
......@@ -506,7 +511,7 @@ test "splitmix64 sequence" {
506511 };
507512
508513 for (seq) |s| {
509 std.debug.assert(s == r.next());
514 expect(s == r.next());
510515 }
511516}
512517
......@@ -599,7 +604,7 @@ test "pcg sequence" {
599604 };
600605
601606 for (seq) |s| {
602 std.debug.assert(s == r.next());
607 expect(s == r.next());
603608 }
604609}
605610
......@@ -708,7 +713,7 @@ test "xoroshiro sequence" {
708713 };
709714
710715 for (seq1) |s| {
711 std.debug.assert(s == r.next());
716 expect(s == r.next());
712717 }
713718
714719 r.jump();
......@@ -723,7 +728,7 @@ test "xoroshiro sequence" {
723728 };
724729
725730 for (seq2) |s| {
726 std.debug.assert(s == r.next());
731 expect(s == r.next());
727732 }
728733}
729734
......@@ -926,7 +931,7 @@ test "isaac64 sequence" {
926931 };
927932
928933 for (seq) |s| {
929 std.debug.assert(s == r.next());
934 expect(s == r.next());
930935 }
931936}
932937
......@@ -937,12 +942,12 @@ test "Random float" {
937942 var i: usize = 0;
938943 while (i < 1000) : (i += 1) {
939944 const val1 = prng.random.float(f32);
940 std.debug.assert(val1 >= 0.0);
941 std.debug.assert(val1 < 1.0);
945 expect(val1 >= 0.0);
946 expect(val1 < 1.0);
942947
943948 const val2 = prng.random.float(f64);
944 std.debug.assert(val2 >= 0.0);
945 std.debug.assert(val2 < 1.0);
949 expect(val2 >= 0.0);
950 expect(val2 < 1.0);
946951 }
947952}
948953
......@@ -956,12 +961,12 @@ test "Random shuffle" {
956961 while (i < 1000) : (i += 1) {
957962 prng.random.shuffle(u8, seq[0..]);
958963 seen[seq[0]] = true;
959 std.debug.assert(sumArray(seq[0..]) == 10);
964 expect(sumArray(seq[0..]) == 10);
960965 }
961966
962967 // we should see every entry at the head at least once
963968 for (seen) |e| {
964 std.debug.assert(e == true);
969 expect(e == true);
965970 }
966971}
967972
std/rb.zig+3-2
......@@ -1,5 +1,6 @@
11const std = @import("index.zig");
22const assert = std.debug.assert;
3const testing = std.testing;
34const mem = std.mem; // For mem.Compare
45
56const Color = enum(u1) {
......@@ -533,13 +534,13 @@ test "rb" {
533534 _ = tree.insert(&ns[8].node);
534535 _ = tree.insert(&ns[9].node);
535536 tree.remove(&ns[3].node);
536 assert(tree.insert(&dup.node) == &ns[7].node);
537 testing.expect(tree.insert(&dup.node) == &ns[7].node);
537538 try tree.replace(&ns[7].node, &dup.node);
538539
539540 var num: *testNumber = undefined;
540541 num = testGetNumber(tree.first().?);
541542 while (num.node.next() != null) {
542 assert(testGetNumber(num.node.next().?).value > num.value);
543 testing.expect(testGetNumber(num.node.next().?).value > num.value);
543544 num = testGetNumber(num.node.next().?);
544545 }
545546}
std/segmented_list.zig+16-15
......@@ -1,5 +1,6 @@
11const std = @import("index.zig");
22const assert = std.debug.assert;
3const testing = std.testing;
34const Allocator = std.mem.Allocator;
45
56// 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 {
352353 var i: usize = 0;
353354 while (i < 100) : (i += 1) {
354355 try list.push(@intCast(i32, i + 1));
355 assert(list.len == i + 1);
356 testing.expect(list.len == i + 1);
356357 }
357358 }
358359
359360 {
360361 var i: usize = 0;
361362 while (i < 100) : (i += 1) {
362 assert(list.at(i).* == @intCast(i32, i + 1));
363 testing.expect(list.at(i).* == @intCast(i32, i + 1));
363364 }
364365 }
365366
......@@ -368,35 +369,35 @@ fn testSegmentedList(comptime prealloc: usize, allocator: *Allocator) !void {
368369 var x: i32 = 0;
369370 while (it.next()) |item| {
370371 x += 1;
371 assert(item.* == x);
372 testing.expect(item.* == x);
372373 }
373 assert(x == 100);
374 testing.expect(x == 100);
374375 while (it.prev()) |item| : (x -= 1) {
375 assert(item.* == x);
376 testing.expect(item.* == x);
376377 }
377 assert(x == 0);
378 testing.expect(x == 0);
378379 }
379380
380 assert(list.pop().? == 100);
381 assert(list.len == 99);
381 testing.expect(list.pop().? == 100);
382 testing.expect(list.len == 99);
382383
383384 try list.pushMany([]i32{
384385 1,
385386 2,
386387 3,
387388 });
388 assert(list.len == 102);
389 assert(list.pop().? == 3);
390 assert(list.pop().? == 2);
391 assert(list.pop().? == 1);
392 assert(list.len == 99);
389 testing.expect(list.len == 102);
390 testing.expect(list.pop().? == 3);
391 testing.expect(list.pop().? == 2);
392 testing.expect(list.pop().? == 1);
393 testing.expect(list.len == 99);
393394
394395 try list.pushMany([]const i32{});
395 assert(list.len == 99);
396 testing.expect(list.len == 99);
396397
397398 var i: i32 = 99;
398399 while (list.pop()) |item| : (i -= 1) {
399 assert(item == i);
400 testing.expect(item == i);
400401 list.shrinkCapacity(list.len);
401402 }
402403}
std/sort.zig+9-8
......@@ -1,5 +1,6 @@
11const std = @import("index.zig");
22const assert = std.debug.assert;
3const testing = std.testing;
34const mem = std.mem;
45const math = std.math;
56const builtin = @import("builtin");
......@@ -1031,8 +1032,8 @@ fn testStableSort() void {
10311032 for (cases) |*case| {
10321033 insertionSort(IdAndValue, (case.*)[0..], cmpByValue);
10331034 for (case.*) |item, i| {
1034 assert(item.id == expected[i].id);
1035 assert(item.value == expected[i].value);
1035 testing.expect(item.id == expected[i].id);
1036 testing.expect(item.value == expected[i].value);
10361037 }
10371038 }
10381039}
......@@ -1077,7 +1078,7 @@ test "std.sort" {
10771078 const slice = buf[0..case[0].len];
10781079 mem.copy(u8, slice, case[0]);
10791080 sort(u8, slice, asc(u8));
1080 assert(mem.eql(u8, slice, case[1]));
1081 testing.expect(mem.eql(u8, slice, case[1]));
10811082 }
10821083
10831084 const i32cases = [][]const []const i32{
......@@ -1112,7 +1113,7 @@ test "std.sort" {
11121113 const slice = buf[0..case[0].len];
11131114 mem.copy(i32, slice, case[0]);
11141115 sort(i32, slice, asc(i32));
1115 assert(mem.eql(i32, slice, case[1]));
1116 testing.expect(mem.eql(i32, slice, case[1]));
11161117 }
11171118}
11181119
......@@ -1149,7 +1150,7 @@ test "std.sort descending" {
11491150 const slice = buf[0..case[0].len];
11501151 mem.copy(i32, slice, case[0]);
11511152 sort(i32, slice, desc(i32));
1152 assert(mem.eql(i32, slice, case[1]));
1153 testing.expect(mem.eql(i32, slice, case[1]));
11531154 }
11541155}
11551156
......@@ -1157,7 +1158,7 @@ test "another sort case" {
11571158 var arr = []i32{ 5, 3, 1, 2, 4 };
11581159 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 }));
11611162}
11621163
11631164test "sort fuzz testing" {
......@@ -1185,9 +1186,9 @@ fn fuzzTest(rng: *std.rand.Random) void {
11851186 var index: usize = 1;
11861187 while (index < array.len) : (index += 1) {
11871188 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);
11891190 } else {
1190 assert(array[index].value > array[index - 1].value);
1191 testing.expect(array[index].value > array[index - 1].value);
11911192 }
11921193 }
11931194}
std/special/bootstrap.zig+63-15
......@@ -4,6 +4,7 @@
44const root = @import("@root");
55const std = @import("std");
66const builtin = @import("builtin");
7const assert = std.debug.assert;
78
89var argc_ptr: [*]usize = undefined;
910
......@@ -20,17 +21,10 @@ comptime {
2021
2122nakedcc fn _start() noreturn {
2223 switch (builtin.arch) {
23 builtin.Arch.x86_64 => switch (builtin.os) {
24 builtin.Os.freebsd => {
25 argc_ptr = asm ("lea (%%rdi), %[argc]"
26 : [argc] "=r" (-> [*]usize)
27 );
28 },
29 else => {
30 argc_ptr = asm ("lea (%%rsp), %[argc]"
31 : [argc] "=r" (-> [*]usize)
32 );
33 },
24 builtin.Arch.x86_64 => {
25 argc_ptr = asm ("lea (%%rsp), %[argc]"
26 : [argc] "=r" (-> [*]usize)
27 );
3428 },
3529 builtin.Arch.i386 => {
3630 argc_ptr = asm ("lea (%%esp), %[argc]"
......@@ -51,7 +45,9 @@ nakedcc fn _start() noreturn {
5145
5246extern fn WinMainCRTStartup() noreturn {
5347 @setAlignStack(16);
54
48 if (!builtin.single_threaded) {
49 _ = @import("../os/windows/tls.zig");
50 }
5551 std.os.windows.ExitProcess(callMain());
5652}
5753
......@@ -68,9 +64,23 @@ fn posixCallMainAndExit() noreturn {
6864 while (envp_optional[envp_count]) |_| : (envp_count += 1) {}
6965 const envp = @ptrCast([*][*]u8, envp_optional)[0..envp_count];
7066 if (builtin.os == builtin.Os.linux) {
71 const auxv = @ptrCast([*]usize, envp.ptr + envp_count + 1);
72 std.os.linux_elf_aux_maybe = @ptrCast([*]std.elf.Auxv, auxv);
73 std.debug.assert(std.os.linuxGetAuxVal(std.elf.AT_PAGESZ) == std.os.page_size);
67 // Scan auxiliary vector.
68 const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1);
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);
7484 }
7585
7686 std.os.posix.exit(callMainWithArgs(argc, argv, envp));
......@@ -123,3 +133,41 @@ inline fn callMain() u8 {
123133 else => @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'"),
124134 }
125135}
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 @@
11const __divti3 = @import("divti3.zig").__divti3;
2const assert = @import("std").debug.assert;
2const testing = @import("std").testing;
33
44fn test__divti3(a: i128, b: i128, expected: i128) void {
55 const x = __divti3(a, b);
6 assert(x == expected);
6 testing.expect(x == expected);
77}
88
99test "divti3" {
std/special/compiler_rt/extendXfYf2_test.zig-1
......@@ -1,7 +1,6 @@
11const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2;
22const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2;
33const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2;
4const assert = @import("std").debug.assert;
54
65fn test__extenddftf2(a: f64, expectedHi: u64, expectedLo: u64) void {
76 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 @@
11const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi;
2const assert = @import("std").debug.assert;
2const testing = @import("std").testing;
33
44fn test__fixunsdfdi(a: f64, expected: u64) void {
55 const x = __fixunsdfdi(a);
6 assert(x == expected);
6 testing.expect(x == expected);
77}
88
99test "fixunsdfdi" {
std/special/compiler_rt/fixunsdfsi_test.zig+2-2
......@@ -1,9 +1,9 @@
11const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi;
2const assert = @import("std").debug.assert;
2const testing = @import("std").testing;
33
44fn test__fixunsdfsi(a: f64, expected: u32) void {
55 const x = __fixunsdfsi(a);
6 assert(x == expected);
6 testing.expect(x == expected);
77}
88
99test "fixunsdfsi" {
std/special/compiler_rt/fixunsdfti_test.zig+2-2
......@@ -1,9 +1,9 @@
11const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti;
2const assert = @import("std").debug.assert;
2const testing = @import("std").testing;
33
44fn test__fixunsdfti(a: f64, expected: u128) void {
55 const x = __fixunsdfti(a);
6 assert(x == expected);
6 testing.expect(x == expected);
77}
88
99test "fixunsdfti" {
std/special/compiler_rt/fixunssfdi_test.zig+2-2
......@@ -1,9 +1,9 @@
11const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi;
2const assert = @import("std").debug.assert;
2const testing = @import("std").testing;
33
44fn test__fixunssfdi(a: f32, expected: u64) void {
55 const x = __fixunssfdi(a);
6 assert(x == expected);
6 testing.expect(x == expected);
77}
88
99test "fixunssfdi" {
std/special/compiler_rt/fixunssfsi_test.zig+2-2
......@@ -1,9 +1,9 @@
11const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi;
2const assert = @import("std").debug.assert;
2const testing = @import("std").testing;
33
44fn test__fixunssfsi(a: f32, expected: u32) void {
55 const x = __fixunssfsi(a);
6 assert(x == expected);
6 testing.expect(x == expected);
77}
88
99test "fixunssfsi" {
std/special/compiler_rt/fixunssfti_test.zig+2-2
......@@ -1,9 +1,9 @@
11const __fixunssfti = @import("fixunssfti.zig").__fixunssfti;
2const assert = @import("std").debug.assert;
2const testing = @import("std").testing;
33
44fn test__fixunssfti(a: f32, expected: u128) void {
55 const x = __fixunssfti(a);
6 assert(x == expected);
6 testing.expect(x == expected);
77}
88
99test "fixunssfti" {
std/special/compiler_rt/fixunstfdi_test.zig+2-2
......@@ -1,9 +1,9 @@
11const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi;
2const assert = @import("std").debug.assert;
2const testing = @import("std").testing;
33
44fn test__fixunstfdi(a: f128, expected: u64) void {
55 const x = __fixunstfdi(a);
6 assert(x == expected);
6 testing.expect(x == expected);
77}
88
99test "fixunstfdi" {
std/special/compiler_rt/fixunstfsi_test.zig+2-2
......@@ -1,9 +1,9 @@
11const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi;
2const assert = @import("std").debug.assert;
2const testing = @import("std").testing;
33
44fn test__fixunstfsi(a: f128, expected: u32) void {
55 const x = __fixunstfsi(a);
6 assert(x == expected);
6 testing.expect(x == expected);
77}
88
99const inf128 = @bitCast(f128, u128(0x7fff0000000000000000000000000000));
std/special/compiler_rt/fixunstfti_test.zig+2-2
......@@ -1,9 +1,9 @@
11const __fixunstfti = @import("fixunstfti.zig").__fixunstfti;
2const assert = @import("std").debug.assert;
2const testing = @import("std").testing;
33
44fn test__fixunstfti(a: f128, expected: u128) void {
55 const x = __fixunstfti(a);
6 assert(x == expected);
6 testing.expect(x == expected);
77}
88
99const inf128 = @bitCast(f128, u128(0x7fff0000000000000000000000000000));
std/special/compiler_rt/floattidf_test.zig+2-2
......@@ -1,9 +1,9 @@
11const __floattidf = @import("floattidf.zig").__floattidf;
2const assert = @import("std").debug.assert;
2const testing = @import("std").testing;
33
44fn test__floattidf(a: i128, expected: f64) void {
55 const x = __floattidf(a);
6 assert(x == expected);
6 testing.expect(x == expected);
77}
88
99test "floattidf" {
std/special/compiler_rt/floattisf_test.zig+2-2
......@@ -1,9 +1,9 @@
11const __floattisf = @import("floattisf.zig").__floattisf;
2const assert = @import("std").debug.assert;
2const testing = @import("std").testing;
33
44fn test__floattisf(a: i128, expected: f32) void {
55 const x = __floattisf(a);
6 assert(x == expected);
6 testing.expect(x == expected);
77}
88
99test "floattisf" {
std/special/compiler_rt/floattitf_test.zig+2-2
......@@ -1,9 +1,9 @@
11const __floattitf = @import("floattitf.zig").__floattitf;
2const assert = @import("std").debug.assert;
2const testing = @import("std").testing;
33
44fn test__floattitf(a: i128, expected: f128) void {
55 const x = __floattitf(a);
6 assert(x == expected);
6 testing.expect(x == expected);
77}
88
99test "floattitf" {
std/special/compiler_rt/floatunditf_test.zig-1
......@@ -1,5 +1,4 @@
11const __floatunditf = @import("floatunditf.zig").__floatunditf;
2const assert = @import("std").debug.assert;
32
43fn test__floatunditf(a: u128, expected_hi: u64, expected_lo: u64) void {
54 const x = __floatunditf(a);
std/special/compiler_rt/floatunsitf_test.zig-1
......@@ -1,5 +1,4 @@
11const __floatunsitf = @import("floatunsitf.zig").__floatunsitf;
2const assert = @import("std").debug.assert;
32
43fn test__floatunsitf(a: u64, expected_hi: u64, expected_lo: u64) void {
54 const x = __floatunsitf(a);
std/special/compiler_rt/floatuntidf_test.zig+2-2
......@@ -1,9 +1,9 @@
11const __floatuntidf = @import("floatuntidf.zig").__floatuntidf;
2const assert = @import("std").debug.assert;
2const testing = @import("std").testing;
33
44fn test__floatuntidf(a: u128, expected: f64) void {
55 const x = __floatuntidf(a);
6 assert(x == expected);
6 testing.expect(x == expected);
77}
88
99test "floatuntidf" {
std/special/compiler_rt/floatuntisf_test.zig+2-2
......@@ -1,9 +1,9 @@
11const __floatuntisf = @import("floatuntisf.zig").__floatuntisf;
2const assert = @import("std").debug.assert;
2const testing = @import("std").testing;
33
44fn test__floatuntisf(a: u128, expected: f32) void {
55 const x = __floatuntisf(a);
6 assert(x == expected);
6 testing.expect(x == expected);
77}
88
99test "floatuntisf" {
std/special/compiler_rt/floatuntitf_test.zig+2-2
......@@ -1,9 +1,9 @@
11const __floatuntitf = @import("floatuntitf.zig").__floatuntitf;
2const assert = @import("std").debug.assert;
2const testing = @import("std").testing;
33
44fn test__floatuntitf(a: u128, expected: f128) void {
55 const x = __floatuntitf(a);
6 assert(x == expected);
6 testing.expect(x == expected);
77}
88
99test "floatuntitf" {
std/special/compiler_rt/index.zig+17-2
......@@ -21,6 +21,9 @@ comptime {
2121
2222 @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
2427 @export("__floattitf", @import("floattitf.zig").__floattitf, linkage);
2528 @export("__floattidf", @import("floattidf.zig").__floattidf, linkage);
2629 @export("__floattisf", @import("floattisf.zig").__floattisf, linkage);
......@@ -37,6 +40,7 @@ comptime {
3740 @export("__extendhfsf2", @import("extendXfYf2.zig").__extendhfsf2, linkage);
3841
3942 @export("__truncsfhf2", @import("truncXfYf2.zig").__truncsfhf2, linkage);
43 @export("__truncdfhf2", @import("truncXfYf2.zig").__truncdfhf2, linkage);
4044 @export("__trunctfdf2", @import("truncXfYf2.zig").__trunctfdf2, linkage);
4145 @export("__trunctfsf2", @import("truncXfYf2.zig").__trunctfsf2, linkage);
4246
......@@ -52,6 +56,16 @@ comptime {
5256 @export("__fixunstfdi", @import("fixunstfdi.zig").__fixunstfdi, linkage);
5357 @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
5569 @export("__udivmoddi4", @import("udivmoddi4.zig").__udivmoddi4, linkage);
5670
5771 @export("__udivsi3", __udivsi3, linkage);
......@@ -100,6 +114,7 @@ comptime {
100114
101115const std = @import("std");
102116const assert = std.debug.assert;
117const testing = std.testing;
103118
104119const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4;
105120
......@@ -407,7 +422,7 @@ test "test_umoddi3" {
407422
408423fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) void {
409424 const r = __umoddi3(a, b);
410 assert(r == expected_r);
425 testing.expect(r == expected_r);
411426}
412427
413428test "test_udivsi3" {
......@@ -1081,5 +1096,5 @@ test "test_udivsi3" {
10811096
10821097fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) void {
10831098 const q: u32 = __udivsi3(a, b);
1084 assert(q == expected_q);
1099 testing.expect(q == expected_q);
10851100}
std/special/compiler_rt/muloti4_test.zig+2-2
......@@ -1,10 +1,10 @@
11const __muloti4 = @import("muloti4.zig").__muloti4;
2const assert = @import("std").debug.assert;
2const testing = @import("std").testing;
33
44fn test__muloti4(a: i128, b: i128, expected: i128, expected_overflow: c_int) void {
55 var overflow: c_int = undefined;
66 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));
88}
99
1010test "muloti4" {
std/special/compiler_rt/multi3_test.zig+2-2
......@@ -1,9 +1,9 @@
11const __multi3 = @import("multi3.zig").__multi3;
2const assert = @import("std").debug.assert;
2const testing = @import("std").testing;
33
44fn test__multi3(a: i128, b: i128, expected: i128) void {
55 const x = __multi3(a, b);
6 assert(x == expected);
6 testing.expect(x == expected);
77}
88
99test "multi3" {
std/special/compiler_rt/truncXfYf2.zig+4
......@@ -4,6 +4,10 @@ pub extern fn __truncsfhf2(a: f32) u16 {
44 return @bitCast(u16, truncXfYf2(f16, f32, a));
55}
66
7pub extern fn __truncdfhf2(a: f64) u16 {
8 return @bitCast(u16, truncXfYf2(f16, f64, a));
9}
10
711pub extern fn __trunctfsf2(a: f128) f32 {
812 return truncXfYf2(f32, f128, a);
913}
std/special/compiler_rt/truncXfYf2_test.zig+68
......@@ -63,6 +63,74 @@ test "truncsfhf2" {
6363 test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero
6464}
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
66134const __trunctfsf2 = @import("truncXfYf2.zig").__trunctfsf2;
67135
68136fn test__trunctfsf2(a: f128, expected: u32) void {
std/special/compiler_rt/udivmoddi4_test.zig+3-3
......@@ -1,13 +1,13 @@
11// Disable formatting to avoid unnecessary source repository bloat.
22// zig fmt: off
33const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4;
4const assert = @import("std").debug.assert;
4const testing = @import("std").testing;
55
66fn test__udivmoddi4(a: u64, b: u64, expected_q: u64, expected_r: u64) void {
77 var r: u64 = undefined;
88 const q = __udivmoddi4(a, b, &r);
9 assert(q == expected_q);
10 assert(r == expected_r);
9 testing.expect(q == expected_q);
10 testing.expect(r == expected_r);
1111}
1212
1313test "udivmoddi4" {
std/special/compiler_rt/udivmodti4_test.zig+3-3
......@@ -1,13 +1,13 @@
11// Disable formatting to avoid unnecessary source repository bloat.
22// zig fmt: off
33const __udivmodti4 = @import("udivmodti4.zig").__udivmodti4;
4const assert = @import("std").debug.assert;
4const testing = @import("std").testing;
55
66fn test__udivmodti4(a: u128, b: u128, expected_q: u128, expected_r: u128) void {
77 var r: u128 = undefined;
88 const q = __udivmodti4(a, b, &r);
9 assert(q == expected_q);
10 assert(r == expected_r);
9 testing.expect(q == expected_q);
10 testing.expect(r == expected_r);
1111}
1212
1313test "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 @@
11const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
2const testing = std.testing;
33
44export fn add(a: i32, b: i32) i32 {
55 return a + b;
66}
77
88test "basic add functionality" {
9 assertOrPanic(add(3, 7) == 10);
9 testing.expect(add(3, 7) == 10);
1010}
std/special/panic.zig+4
......@@ -13,6 +13,10 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn
1313 builtin.Os.freestanding, builtin.Os.zen => {
1414 while (true) {}
1515 },
16 builtin.Os.uefi => {
17 // TODO look into using the debug info and logging helpful messages
18 std.os.abort();
19 },
1620 else => {
1721 const first_trace_addr = @ptrToInt(@returnAddress());
1822 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 @@
11const std = @import("./index.zig");
22const builtin = @import("builtin");
3const debug = std.debug;
43const assert = std.debug.assert;
4const testing = std.testing;
55const mem = std.mem;
66
77/// Returns how many bytes the UTF-8 representation would require
......@@ -32,7 +32,7 @@ pub fn utf8ByteSequenceLength(first_byte: u8) !u3 {
3232/// Returns: the number of bytes written to out.
3333pub fn utf8Encode(c: u32, out: []u8) !u3 {
3434 const length = try utf8CodepointSequenceLength(c);
35 debug.assert(out.len >= length);
35 assert(out.len >= length);
3636 switch (length) {
3737 // The pattern for each is the same
3838 // - Increasing the initial shift by 6 each time
......@@ -81,8 +81,8 @@ const Utf8Decode2Error = error{
8181 Utf8OverlongEncoding,
8282};
8383pub fn utf8Decode2(bytes: []const u8) Utf8Decode2Error!u32 {
84 debug.assert(bytes.len == 2);
85 debug.assert(bytes[0] & 0b11100000 == 0b11000000);
84 assert(bytes.len == 2);
85 assert(bytes[0] & 0b11100000 == 0b11000000);
8686 var value: u32 = bytes[0] & 0b00011111;
8787
8888 if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation;
......@@ -100,8 +100,8 @@ const Utf8Decode3Error = error{
100100 Utf8EncodesSurrogateHalf,
101101};
102102pub fn utf8Decode3(bytes: []const u8) Utf8Decode3Error!u32 {
103 debug.assert(bytes.len == 3);
104 debug.assert(bytes[0] & 0b11110000 == 0b11100000);
103 assert(bytes.len == 3);
104 assert(bytes[0] & 0b11110000 == 0b11100000);
105105 var value: u32 = bytes[0] & 0b00001111;
106106
107107 if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation;
......@@ -124,8 +124,8 @@ const Utf8Decode4Error = error{
124124 Utf8CodepointTooLarge,
125125};
126126pub fn utf8Decode4(bytes: []const u8) Utf8Decode4Error!u32 {
127 debug.assert(bytes.len == 4);
128 debug.assert(bytes[0] & 0b11111000 == 0b11110000);
127 assert(bytes.len == 4);
128 assert(bytes[0] & 0b11111000 == 0b11110000);
129129 var value: u32 = bytes[0] & 0b00000111;
130130
131131 if (bytes[1] & 0b11000000 != 0b10000000) return error.Utf8ExpectedContinuation;
......@@ -249,12 +249,12 @@ pub const Utf16LeIterator = struct {
249249 pub fn nextCodepoint(it: *Utf16LeIterator) !?u32 {
250250 assert(it.i <= it.bytes.len);
251251 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]);
253253 if (c0 & ~u32(0x03ff) == 0xd800) {
254254 // surrogate pair
255255 it.i += 2;
256256 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]);
258258 if (c1 & ~u32(0x03ff) != 0xdc00) return error.ExpectedSecondSurrogateHalf;
259259 it.i += 2;
260260 return 0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff));
......@@ -274,23 +274,23 @@ test "utf8 encode" {
274274fn testUtf8Encode() !void {
275275 // A few taken from wikipedia a few taken elsewhere
276276 var array: [4]u8 = undefined;
277 debug.assert((try utf8Encode(try utf8Decode("€"), array[0..])) == 3);
278 debug.assert(array[0] == 0b11100010);
279 debug.assert(array[1] == 0b10000010);
280 debug.assert(array[2] == 0b10101100);
277 testing.expect((try utf8Encode(try utf8Decode("€"), array[0..])) == 3);
278 testing.expect(array[0] == 0b11100010);
279 testing.expect(array[1] == 0b10000010);
280 testing.expect(array[2] == 0b10101100);
281281
282 debug.assert((try utf8Encode(try utf8Decode("$"), array[0..])) == 1);
283 debug.assert(array[0] == 0b00100100);
282 testing.expect((try utf8Encode(try utf8Decode("$"), array[0..])) == 1);
283 testing.expect(array[0] == 0b00100100);
284284
285 debug.assert((try utf8Encode(try utf8Decode("¢"), array[0..])) == 2);
286 debug.assert(array[0] == 0b11000010);
287 debug.assert(array[1] == 0b10100010);
285 testing.expect((try utf8Encode(try utf8Decode("¢"), array[0..])) == 2);
286 testing.expect(array[0] == 0b11000010);
287 testing.expect(array[1] == 0b10100010);
288288
289 debug.assert((try utf8Encode(try utf8Decode("𐍈"), array[0..])) == 4);
290 debug.assert(array[0] == 0b11110000);
291 debug.assert(array[1] == 0b10010000);
292 debug.assert(array[2] == 0b10001101);
293 debug.assert(array[3] == 0b10001000);
289 testing.expect((try utf8Encode(try utf8Decode("𐍈"), array[0..])) == 4);
290 testing.expect(array[0] == 0b11110000);
291 testing.expect(array[1] == 0b10010000);
292 testing.expect(array[2] == 0b10001101);
293 testing.expect(array[3] == 0b10001000);
294294}
295295
296296test "utf8 encode error" {
......@@ -306,11 +306,7 @@ fn testUtf8EncodeError() void {
306306}
307307
308308fn testErrorEncode(codePoint: u32, array: []u8, expectedErr: anyerror) void {
309 if (utf8Encode(codePoint, array)) |_| {
310 unreachable;
311 } else |err| {
312 debug.assert(err == expectedErr);
313 }
309 testing.expectError(expectedErr, utf8Encode(codePoint, array));
314310}
315311
316312test "utf8 iterator on ascii" {
......@@ -321,16 +317,16 @@ fn testUtf8IteratorOnAscii() void {
321317 const s = Utf8View.initComptime("abc");
322318
323319 var it1 = s.iterator();
324 debug.assert(std.mem.eql(u8, "a", it1.nextCodepointSlice().?));
325 debug.assert(std.mem.eql(u8, "b", it1.nextCodepointSlice().?));
326 debug.assert(std.mem.eql(u8, "c", it1.nextCodepointSlice().?));
327 debug.assert(it1.nextCodepointSlice() == null);
320 testing.expect(std.mem.eql(u8, "a", it1.nextCodepointSlice().?));
321 testing.expect(std.mem.eql(u8, "b", it1.nextCodepointSlice().?));
322 testing.expect(std.mem.eql(u8, "c", it1.nextCodepointSlice().?));
323 testing.expect(it1.nextCodepointSlice() == null);
328324
329325 var it2 = s.iterator();
330 debug.assert(it2.nextCodepoint().? == 'a');
331 debug.assert(it2.nextCodepoint().? == 'b');
332 debug.assert(it2.nextCodepoint().? == 'c');
333 debug.assert(it2.nextCodepoint() == null);
326 testing.expect(it2.nextCodepoint().? == 'a');
327 testing.expect(it2.nextCodepoint().? == 'b');
328 testing.expect(it2.nextCodepoint().? == 'c');
329 testing.expect(it2.nextCodepoint() == null);
334330}
335331
336332test "utf8 view bad" {
......@@ -340,12 +336,7 @@ test "utf8 view bad" {
340336fn testUtf8ViewBad() void {
341337 // Compile-time error.
342338 // const s3 = Utf8View.initComptime("\xfe\xf2");
343 const s = Utf8View.init("hel\xadlo");
344 if (s) |_| {
345 unreachable;
346 } else |err| {
347 debug.assert(err == error.InvalidUtf8);
348 }
339 testing.expectError(error.InvalidUtf8, Utf8View.init("hel\xadlo"));
349340}
350341
351342test "utf8 view ok" {
......@@ -356,16 +347,16 @@ fn testUtf8ViewOk() void {
356347 const s = Utf8View.initComptime("東京市");
357348
358349 var it1 = s.iterator();
359 debug.assert(std.mem.eql(u8, "東", it1.nextCodepointSlice().?));
360 debug.assert(std.mem.eql(u8, "京", it1.nextCodepointSlice().?));
361 debug.assert(std.mem.eql(u8, "市", it1.nextCodepointSlice().?));
362 debug.assert(it1.nextCodepointSlice() == null);
350 testing.expect(std.mem.eql(u8, "東", it1.nextCodepointSlice().?));
351 testing.expect(std.mem.eql(u8, "京", it1.nextCodepointSlice().?));
352 testing.expect(std.mem.eql(u8, "市", it1.nextCodepointSlice().?));
353 testing.expect(it1.nextCodepointSlice() == null);
363354
364355 var it2 = s.iterator();
365 debug.assert(it2.nextCodepoint().? == 0x6771);
366 debug.assert(it2.nextCodepoint().? == 0x4eac);
367 debug.assert(it2.nextCodepoint().? == 0x5e02);
368 debug.assert(it2.nextCodepoint() == null);
356 testing.expect(it2.nextCodepoint().? == 0x6771);
357 testing.expect(it2.nextCodepoint().? == 0x4eac);
358 testing.expect(it2.nextCodepoint().? == 0x5e02);
359 testing.expect(it2.nextCodepoint() == null);
369360}
370361
371362test "bad utf8 slice" {
......@@ -373,10 +364,10 @@ test "bad utf8 slice" {
373364 testBadUtf8Slice();
374365}
375366fn testBadUtf8Slice() void {
376 debug.assert(utf8ValidateSlice("abc"));
377 debug.assert(!utf8ValidateSlice("abc\xc0"));
378 debug.assert(!utf8ValidateSlice("abc\xc0abc"));
379 debug.assert(utf8ValidateSlice("abc\xdf\xbf"));
367 testing.expect(utf8ValidateSlice("abc"));
368 testing.expect(!utf8ValidateSlice("abc\xc0"));
369 testing.expect(!utf8ValidateSlice("abc\xc0abc"));
370 testing.expect(utf8ValidateSlice("abc\xdf\xbf"));
380371}
381372
382373test "valid utf8" {
......@@ -459,21 +450,17 @@ fn testMiscInvalidUtf8() void {
459450}
460451
461452fn testError(bytes: []const u8, expected_err: anyerror) void {
462 if (testDecode(bytes)) |_| {
463 unreachable;
464 } else |err| {
465 debug.assert(err == expected_err);
466 }
453 testing.expectError(expected_err, testDecode(bytes));
467454}
468455
469456fn 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);
471458}
472459
473460fn testDecode(bytes: []const u8) !u32 {
474461 const length = try utf8ByteSequenceLength(bytes[0]);
475462 if (bytes.len < length) return error.UnexpectedEof;
476 debug.assert(bytes.len == length);
463 testing.expect(bytes.len == length);
477464 return utf8Decode(bytes);
478465}
479466
......@@ -510,48 +497,48 @@ test "utf16leToUtf8" {
510497 const utf16le_as_bytes = @sliceToBytes(utf16le[0..]);
511498
512499 {
513 mem.writeInt(utf16le_as_bytes[0..], u16('A'), builtin.Endian.Little);
514 mem.writeInt(utf16le_as_bytes[2..], u16('a'), builtin.Endian.Little);
500 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 'A');
501 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 'a');
515502 const utf8 = try utf16leToUtf8Alloc(std.debug.global_allocator, utf16le);
516 assert(mem.eql(u8, utf8, "Aa"));
503 testing.expect(mem.eql(u8, utf8, "Aa"));
517504 }
518505
519506 {
520 mem.writeInt(utf16le_as_bytes[0..], u16(0x80), builtin.Endian.Little);
521 mem.writeInt(utf16le_as_bytes[2..], u16(0xffff), builtin.Endian.Little);
507 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0x80);
508 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xffff);
522509 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"));
524511 }
525512
526513 {
527514 // the values just outside the surrogate half range
528 mem.writeInt(utf16le_as_bytes[0..], u16(0xd7ff), builtin.Endian.Little);
529 mem.writeInt(utf16le_as_bytes[2..], u16(0xe000), builtin.Endian.Little);
515 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd7ff);
516 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xe000);
530517 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"));
532519 }
533520
534521 {
535522 // smallest surrogate pair
536 mem.writeInt(utf16le_as_bytes[0..], u16(0xd800), builtin.Endian.Little);
537 mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little);
523 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xd800);
524 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00);
538525 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"));
540527 }
541528
542529 {
543530 // largest surrogate pair
544 mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little);
545 mem.writeInt(utf16le_as_bytes[2..], u16(0xdfff), builtin.Endian.Little);
531 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff);
532 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdfff);
546533 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"));
548535 }
549536
550537 {
551 mem.writeInt(utf16le_as_bytes[0..], u16(0xdbff), builtin.Endian.Little);
552 mem.writeInt(utf16le_as_bytes[2..], u16(0xdc00), builtin.Endian.Little);
538 mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 0xdbff);
539 mem.writeIntSliceLittle(u16, utf16le_as_bytes[2..], 0xdc00);
553540 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"));
555542 }
556543}
557544
......@@ -583,7 +570,7 @@ pub fn utf8ToUtf16Le(utf16le: []u16, utf8: []const u8) !usize {
583570 while (it.nextCodepoint()) |codepoint| {
584571 if (end_index == utf16le_as_bytes.len) return (end_index / 2) + 1;
585572 // 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));
587574 end_index += 2;
588575 }
589576 return end_index / 2;
std/zig/ast.zig+8-1
......@@ -1,5 +1,6 @@
11const std = @import("../index.zig");
22const assert = std.debug.assert;
3const testing = std.testing;
34const SegmentedList = std.SegmentedList;
45const mem = std.mem;
56const Token = std.zig.Token;
......@@ -109,6 +110,7 @@ pub const Tree = struct {
109110pub const Error = union(enum) {
110111 InvalidToken: InvalidToken,
111112 ExpectedVarDeclOrFn: ExpectedVarDeclOrFn,
113 ExpectedVarDecl: ExpectedVarDecl,
112114 ExpectedAggregateKw: ExpectedAggregateKw,
113115 UnattachedDocComment: UnattachedDocComment,
114116 ExpectedEqOrSemi: ExpectedEqOrSemi,
......@@ -132,6 +134,7 @@ pub const Error = union(enum) {
132134 // TODO https://github.com/ziglang/zig/issues/683
133135 @TagType(Error).InvalidToken => |*x| return x.render(tokens, stream),
134136 @TagType(Error).ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream),
137 @TagType(Error).ExpectedVarDecl => |*x| return x.render(tokens, stream),
135138 @TagType(Error).ExpectedAggregateKw => |*x| return x.render(tokens, stream),
136139 @TagType(Error).UnattachedDocComment => |*x| return x.render(tokens, stream),
137140 @TagType(Error).ExpectedEqOrSemi => |*x| return x.render(tokens, stream),
......@@ -157,6 +160,7 @@ pub const Error = union(enum) {
157160 // TODO https://github.com/ziglang/zig/issues/683
158161 @TagType(Error).InvalidToken => |x| return x.token,
159162 @TagType(Error).ExpectedVarDeclOrFn => |x| return x.token,
163 @TagType(Error).ExpectedVarDecl => |x| return x.token,
160164 @TagType(Error).ExpectedAggregateKw => |x| return x.token,
161165 @TagType(Error).UnattachedDocComment => |x| return x.token,
162166 @TagType(Error).ExpectedEqOrSemi => |x| return x.token,
......@@ -179,6 +183,7 @@ pub const Error = union(enum) {
179183
180184 pub const InvalidToken = SingleTokenError("Invalid token {}");
181185 pub const ExpectedVarDeclOrFn = SingleTokenError("Expected variable declaration or function, found {}");
186 pub const ExpectedVarDecl = SingleTokenError("Expected variable declaration, found {}");
182187 pub const ExpectedAggregateKw = SingleTokenError("Expected " ++ @tagName(Token.Id.Keyword_struct) ++ ", " ++ @tagName(Token.Id.Keyword_union) ++ ", or " ++ @tagName(Token.Id.Keyword_enum) ++ ", found {}");
183188 pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found {}");
184189 pub const ExpectedSemiOrLBrace = SingleTokenError("Expected ';' or '{{', found {}");
......@@ -495,6 +500,7 @@ pub const Node = struct {
495500 base: Node,
496501 doc_comments: ?*DocComment,
497502 visib_token: ?TokenIndex,
503 thread_local_token: ?TokenIndex,
498504 name_token: TokenIndex,
499505 eq_token: TokenIndex,
500506 mut_token: TokenIndex,
......@@ -535,6 +541,7 @@ pub const Node = struct {
535541
536542 pub fn firstToken(self: *const VarDecl) TokenIndex {
537543 if (self.visib_token) |visib_token| return visib_token;
544 if (self.thread_local_token) |thread_local_token| return thread_local_token;
538545 if (self.comptime_token) |comptime_token| return comptime_token;
539546 if (self.extern_export_token) |extern_export_token| return extern_export_token;
540547 assert(self.lib_name == null);
......@@ -2224,5 +2231,5 @@ test "iterate" {
22242231 .shebang = null,
22252232 };
22262233 var base = &root.base;
2227 assert(base.iterate(0) == null);
2234 testing.expect(base.iterate(0) == null);
22282235}
std/zig/parse.zig+286-151
......@@ -17,14 +17,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1717 defer stack.deinit();
1818
1919 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{
2122 .base = ast.Node{ .id = ast.Node.Id.Root },
2223 .decls = ast.Node.Root.DeclList.init(arena),
2324 .doc_comments = null,
2425 .shebang = null,
2526 // initialized when we get the eof token
2627 .eof_token = undefined,
27 });
28 };
2829
2930 var tree = ast.Tree{
3031 .source = source,
......@@ -75,20 +76,22 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
7576 Token.Id.Keyword_test => {
7677 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{
7981 .base = ast.Node{ .id = ast.Node.Id.Block },
8082 .label = null,
8183 .lbrace = undefined,
8284 .statements = ast.Node.Block.StatementList.init(arena),
8385 .rbrace = undefined,
84 });
85 const test_node = try arena.create(ast.Node.TestDecl{
86 };
87 const test_node = try arena.create(ast.Node.TestDecl);
88 test_node.* = ast.Node.TestDecl{
8689 .base = ast.Node{ .id = ast.Node.Id.TestDecl },
8790 .doc_comments = comments,
8891 .test_token = token_index,
8992 .name = undefined,
9093 .body_node = &block.base,
91 });
94 };
9295 try root_node.decls.push(&test_node.base);
9396 try stack.append(State{ .Block = block });
9497 try stack.append(State{
......@@ -119,19 +122,21 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
119122 continue;
120123 },
121124 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{
123127 .base = ast.Node{ .id = ast.Node.Id.Block },
124128 .label = null,
125129 .lbrace = undefined,
126130 .statements = ast.Node.Block.StatementList.init(arena),
127131 .rbrace = undefined,
128 });
129 const node = try arena.create(ast.Node.Comptime{
132 };
133 const node = try arena.create(ast.Node.Comptime);
134 node.* = ast.Node.Comptime{
130135 .base = ast.Node{ .id = ast.Node.Id.Comptime },
131136 .comptime_token = token_index,
132137 .expr = &block.base,
133138 .doc_comments = comments,
134 });
139 };
135140 try root_node.decls.push(&node.base);
136141
137142 stack.append(State.TopLevel) catch unreachable;
......@@ -224,6 +229,32 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
224229 }) catch unreachable;
225230 continue;
226231 },
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 },
227258 State.TopLevelDecl => |ctx| {
228259 const token = nextToken(&tok_it, &tree);
229260 const token_index = token.index;
......@@ -235,14 +266,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
235266 return tree;
236267 }
237268
238 const node = try arena.create(ast.Node.Use{
269 const node = try arena.create(ast.Node.Use);
270 node.* = ast.Node.Use{
239271 .base = ast.Node{ .id = ast.Node.Id.Use },
240272 .use_token = token_index,
241273 .visib_token = ctx.visib_token,
242274 .expr = undefined,
243275 .semicolon_token = undefined,
244276 .doc_comments = ctx.comments,
245 });
277 };
246278 try ctx.decls.push(&node.base);
247279
248280 stack.append(State{
......@@ -254,6 +286,28 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
254286 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } });
255287 continue;
256288 },
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 },
257311 Token.Id.Keyword_var, Token.Id.Keyword_const => {
258312 if (ctx.extern_export_inline_token) |annotated_token| {
259313 if (annotated_token.ptr.id == Token.Id.Keyword_inline) {
......@@ -266,6 +320,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
266320 .VarDecl = VarDeclCtx{
267321 .comments = ctx.comments,
268322 .visib_token = ctx.visib_token,
323 .thread_local_token = null,
269324 .lib_name = ctx.lib_name,
270325 .comptime_token = null,
271326 .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 {
276331 continue;
277332 },
278333 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{
280336 .base = ast.Node{ .id = ast.Node.Id.FnProto },
281337 .doc_comments = ctx.comments,
282338 .visib_token = ctx.visib_token,
......@@ -292,7 +348,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
292348 .lib_name = ctx.lib_name,
293349 .align_expr = null,
294350 .section_expr = null,
295 });
351 };
296352 try ctx.decls.push(&fn_proto.base);
297353 stack.append(State{ .FnDef = fn_proto }) catch unreachable;
298354 try stack.append(State{ .FnProto = fn_proto });
......@@ -309,12 +365,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
309365 continue;
310366 },
311367 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{
313370 .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },
314371 .async_token = token_index,
315372 .allocator_type = null,
316373 .rangle_bracket = null,
317 });
374 };
318375 fn_proto.async_attr = async_node;
319376
320377 try stack.append(State{
......@@ -341,13 +398,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
341398 },
342399 State.TopLevelExternOrField => |ctx| {
343400 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{
345403 .base = ast.Node{ .id = ast.Node.Id.StructField },
346404 .doc_comments = ctx.comments,
347405 .visib_token = ctx.visib_token,
348406 .name_token = identifier,
349407 .type_expr = undefined,
350 });
408 };
351409 const node_ptr = try ctx.container_decl.fields_and_decls.addOne();
352410 node_ptr.* = &node.base;
353411
......@@ -391,7 +449,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
391449 const token = nextToken(&tok_it, &tree);
392450 const token_index = token.index;
393451 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{
395454 .base = ast.Node{ .id = ast.Node.Id.ContainerDecl },
396455 .layout_token = ctx.layout_token,
397456 .kind_token = switch (token_ptr.id) {
......@@ -405,7 +464,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
405464 .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(arena),
406465 .lbrace_token = undefined,
407466 .rbrace_token = undefined,
408 });
467 };
409468 ctx.opt_ctx.store(&node.base);
410469
411470 stack.append(State{ .ContainerDecl = node }) catch unreachable;
......@@ -464,13 +523,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
464523 Token.Id.Identifier => {
465524 switch (tree.tokens.at(container_decl.kind_token).id) {
466525 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{
468528 .base = ast.Node{ .id = ast.Node.Id.StructField },
469529 .doc_comments = comments,
470530 .visib_token = null,
471531 .name_token = token_index,
472532 .type_expr = undefined,
473 });
533 };
474534 const node_ptr = try container_decl.fields_and_decls.addOne();
475535 node_ptr.* = &node.base;
476536
......@@ -485,13 +545,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
485545 continue;
486546 },
487547 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{
489550 .base = ast.Node{ .id = ast.Node.Id.UnionTag },
490551 .name_token = token_index,
491552 .type_expr = null,
492553 .value_expr = null,
493554 .doc_comments = comments,
494 });
555 };
495556 try container_decl.fields_and_decls.push(&node.base);
496557
497558 try stack.append(State{
......@@ -506,12 +567,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
506567 continue;
507568 },
508569 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{
510572 .base = ast.Node{ .id = ast.Node.Id.EnumTag },
511573 .name_token = token_index,
512574 .value = null,
513575 .doc_comments = comments,
514 });
576 };
515577 try container_decl.fields_and_decls.push(&node.base);
516578
517579 try stack.append(State{
......@@ -593,10 +655,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
593655 },
594656
595657 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{
597660 .base = ast.Node{ .id = ast.Node.Id.VarDecl },
598661 .doc_comments = ctx.comments,
599662 .visib_token = ctx.visib_token,
663 .thread_local_token = ctx.thread_local_token,
600664 .mut_token = ctx.mut_token,
601665 .comptime_token = ctx.comptime_token,
602666 .extern_export_token = ctx.extern_export_token,
......@@ -609,7 +673,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
609673 .name_token = undefined,
610674 .eq_token = undefined,
611675 .semicolon_token = undefined,
612 });
676 };
613677 try ctx.list.push(&var_decl.base);
614678
615679 try stack.append(State{ .VarDeclAlign = var_decl });
......@@ -708,13 +772,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
708772 const token_ptr = token.ptr;
709773 switch (token_ptr.id) {
710774 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{
712777 .base = ast.Node{ .id = ast.Node.Id.Block },
713778 .label = null,
714779 .lbrace = token_index,
715780 .statements = ast.Node.Block.StatementList.init(arena),
716781 .rbrace = undefined,
717 });
782 };
718783 fn_proto.body_node = &block.base;
719784 stack.append(State{ .Block = block }) catch unreachable;
720785 continue;
......@@ -770,10 +835,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
770835 // TODO: this is a special case. Remove this when #760 is fixed
771836 if (token_ptr.id == Token.Id.Keyword_anyerror) {
772837 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{
774840 .base = ast.Node{ .id = ast.Node.Id.ErrorType },
775841 .token = token_index,
776 });
842 };
777843 fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = &error_type_node.base };
778844 continue;
779845 }
......@@ -791,14 +857,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
791857 if (eatToken(&tok_it, &tree, Token.Id.RParen)) |_| {
792858 continue;
793859 }
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{
795862 .base = ast.Node{ .id = ast.Node.Id.ParamDecl },
796863 .comptime_token = null,
797864 .noalias_token = null,
798865 .name_token = null,
799866 .type_node = undefined,
800867 .var_args_token = null,
801 });
868 };
802869 try fn_proto.params.push(&param_decl.base);
803870
804871 stack.append(State{
......@@ -877,13 +944,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
877944 const token_ptr = token.ptr;
878945 switch (token_ptr.id) {
879946 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{
881949 .base = ast.Node{ .id = ast.Node.Id.Block },
882950 .label = ctx.label,
883951 .lbrace = token_index,
884952 .statements = ast.Node.Block.StatementList.init(arena),
885953 .rbrace = undefined,
886 });
954 };
887955 ctx.opt_ctx.store(&block.base);
888956 stack.append(State{ .Block = block }) catch unreachable;
889957 continue;
......@@ -970,7 +1038,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
9701038 }
9711039 },
9721040 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{
9741043 .base = ast.Node{ .id = ast.Node.Id.While },
9751044 .label = ctx.label,
9761045 .inline_token = ctx.inline_token,
......@@ -980,7 +1049,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
9801049 .continue_expr = null,
9811050 .body = undefined,
9821051 .@"else" = null,
983 });
1052 };
9841053 ctx.opt_ctx.store(&node.base);
9851054 stack.append(State{ .Else = &node.@"else" }) catch unreachable;
9861055 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } });
......@@ -999,7 +1068,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
9991068 continue;
10001069 },
10011070 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{
10031073 .base = ast.Node{ .id = ast.Node.Id.For },
10041074 .label = ctx.label,
10051075 .inline_token = ctx.inline_token,
......@@ -1008,7 +1078,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
10081078 .payload = null,
10091079 .body = undefined,
10101080 .@"else" = null,
1011 });
1081 };
10121082 ctx.opt_ctx.store(&node.base);
10131083 stack.append(State{ .Else = &node.@"else" }) catch unreachable;
10141084 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } });
......@@ -1020,12 +1090,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
10201090 },
10211091 State.Else => |dest| {
10221092 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{
10241095 .base = ast.Node{ .id = ast.Node.Id.Else },
10251096 .else_token = else_token,
10261097 .payload = null,
10271098 .body = undefined,
1028 });
1099 };
10291100 dest.* = node;
10301101
10311102 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 {
10731144 .VarDecl = VarDeclCtx{
10741145 .comments = null,
10751146 .visib_token = null,
1147 .thread_local_token = null,
10761148 .comptime_token = null,
10771149 .extern_export_token = null,
10781150 .lib_name = null,
......@@ -1083,11 +1155,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
10831155 continue;
10841156 },
10851157 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{
10871160 .base = ast.Node{ .id = ast.Node.Id.Defer },
10881161 .defer_token = token_index,
10891162 .expr = undefined,
1090 });
1163 };
10911164 const node_ptr = try block.statements.addOne();
10921165 node_ptr.* = &node.base;
10931166
......@@ -1096,13 +1169,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
10961169 continue;
10971170 },
10981171 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{
11001174 .base = ast.Node{ .id = ast.Node.Id.Block },
11011175 .label = null,
11021176 .lbrace = token_index,
11031177 .statements = ast.Node.Block.StatementList.init(arena),
11041178 .rbrace = undefined,
1105 });
1179 };
11061180 try block.statements.push(&inner_block.base);
11071181
11081182 stack.append(State{ .Block = inner_block }) catch unreachable;
......@@ -1127,6 +1201,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
11271201 .VarDecl = VarDeclCtx{
11281202 .comments = null,
11291203 .visib_token = null,
1204 .thread_local_token = null,
11301205 .comptime_token = ctx.comptime_token,
11311206 .extern_export_token = null,
11321207 .lib_name = null,
......@@ -1164,14 +1239,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
11641239 continue;
11651240 }
11661241
1167 const node = try arena.create(ast.Node.AsmOutput{
1242 const node = try arena.create(ast.Node.AsmOutput);
1243 node.* = ast.Node.AsmOutput{
11681244 .base = ast.Node{ .id = ast.Node.Id.AsmOutput },
11691245 .lbracket = lbracket_index,
11701246 .symbolic_name = undefined,
11711247 .constraint = undefined,
11721248 .kind = undefined,
11731249 .rparen = undefined,
1174 });
1250 };
11751251 try items.push(node);
11761252
11771253 stack.append(State{ .AsmOutputItems = items }) catch unreachable;
......@@ -1218,14 +1294,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
12181294 continue;
12191295 }
12201296
1221 const node = try arena.create(ast.Node.AsmInput{
1297 const node = try arena.create(ast.Node.AsmInput);
1298 node.* = ast.Node.AsmInput{
12221299 .base = ast.Node{ .id = ast.Node.Id.AsmInput },
12231300 .lbracket = lbracket_index,
12241301 .symbolic_name = undefined,
12251302 .constraint = undefined,
12261303 .expr = undefined,
12271304 .rparen = undefined,
1228 });
1305 };
12291306 try items.push(node);
12301307
12311308 stack.append(State{ .AsmInputItems = items }) catch unreachable;
......@@ -1283,12 +1360,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
12831360 continue;
12841361 }
12851362
1286 const node = try arena.create(ast.Node.FieldInitializer{
1363 const node = try arena.create(ast.Node.FieldInitializer);
1364 node.* = ast.Node.FieldInitializer{
12871365 .base = ast.Node{ .id = ast.Node.Id.FieldInitializer },
12881366 .period_token = undefined,
12891367 .name_token = undefined,
12901368 .expr = undefined,
1291 });
1369 };
12921370 try list_state.list.push(&node.base);
12931371
12941372 stack.append(State{ .FieldInitListCommaOrEnd = list_state }) catch unreachable;
......@@ -1390,13 +1468,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
13901468 }
13911469
13921470 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{
13941473 .base = ast.Node{ .id = ast.Node.Id.SwitchCase },
13951474 .items = ast.Node.SwitchCase.ItemList.init(arena),
13961475 .payload = null,
13971476 .expr = undefined,
13981477 .arrow_token = undefined,
1399 });
1478 };
14001479 try list_state.list.push(&node.base);
14011480 try stack.append(State{ .SwitchCaseCommaOrEnd = list_state });
14021481 try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } });
......@@ -1427,10 +1506,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
14271506 const token_index = token.index;
14281507 const token_ptr = token.ptr;
14291508 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{
14311511 .base = ast.Node{ .id = ast.Node.Id.SwitchElse },
14321512 .token = token_index,
1433 });
1513 };
14341514 try switch_case.items.push(&else_node.base);
14351515
14361516 try stack.append(State{
......@@ -1537,7 +1617,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
15371617
15381618 State.ExternType => |ctx| {
15391619 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{
15411622 .base = ast.Node{ .id = ast.Node.Id.FnProto },
15421623 .doc_comments = ctx.comments,
15431624 .visib_token = null,
......@@ -1553,7 +1634,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
15531634 .lib_name = null,
15541635 .align_expr = null,
15551636 .section_expr = null,
1556 });
1637 };
15571638 ctx.opt_ctx.store(&fn_proto.base);
15581639 stack.append(State{ .FnProto = fn_proto }) catch unreachable;
15591640 continue;
......@@ -1711,12 +1792,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
17111792 continue;
17121793 }
17131794
1714 const node = try arena.create(ast.Node.Payload{
1795 const node = try arena.create(ast.Node.Payload);
1796 node.* = ast.Node.Payload{
17151797 .base = ast.Node{ .id = ast.Node.Id.Payload },
17161798 .lpipe = token_index,
17171799 .error_symbol = undefined,
17181800 .rpipe = undefined,
1719 });
1801 };
17201802 opt_ctx.store(&node.base);
17211803
17221804 stack.append(State{
......@@ -1747,13 +1829,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
17471829 continue;
17481830 }
17491831
1750 const node = try arena.create(ast.Node.PointerPayload{
1832 const node = try arena.create(ast.Node.PointerPayload);
1833 node.* = ast.Node.PointerPayload{
17511834 .base = ast.Node{ .id = ast.Node.Id.PointerPayload },
17521835 .lpipe = token_index,
17531836 .ptr_token = null,
17541837 .value_symbol = undefined,
17551838 .rpipe = undefined,
1756 });
1839 };
17571840 opt_ctx.store(&node.base);
17581841
17591842 try stack.append(State{
......@@ -1790,14 +1873,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
17901873 continue;
17911874 }
17921875
1793 const node = try arena.create(ast.Node.PointerIndexPayload{
1876 const node = try arena.create(ast.Node.PointerIndexPayload);
1877 node.* = ast.Node.PointerIndexPayload{
17941878 .base = ast.Node{ .id = ast.Node.Id.PointerIndexPayload },
17951879 .lpipe = token_index,
17961880 .ptr_token = null,
17971881 .value_symbol = undefined,
17981882 .index_symbol = null,
17991883 .rpipe = undefined,
1800 });
1884 };
18011885 opt_ctx.store(&node.base);
18021886
18031887 stack.append(State{
......@@ -1824,12 +1908,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
18241908 const token_ptr = token.ptr;
18251909 switch (token_ptr.id) {
18261910 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{
18281913 .base = ast.Node{ .id = ast.Node.Id.ControlFlowExpression },
18291914 .ltoken = token_index,
18301915 .kind = undefined,
18311916 .rhs = null,
1832 });
1917 };
18331918 opt_ctx.store(&node.base);
18341919
18351920 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 {
18531938 continue;
18541939 },
18551940 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{
18571943 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
18581944 .op_token = token_index,
18591945 .op = switch (token_ptr.id) {
......@@ -1863,7 +1949,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
18631949 else => unreachable,
18641950 },
18651951 .rhs = undefined,
1866 });
1952 };
18671953 opt_ctx.store(&node.base);
18681954
18691955 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 {
18871973 const lhs = opt_ctx.get() orelse continue;
18881974
18891975 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{
18911978 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
18921979 .lhs = lhs,
18931980 .op_token = ellipsis3,
18941981 .op = ast.Node.InfixOp.Op.Range,
18951982 .rhs = undefined,
1896 });
1983 };
18971984 opt_ctx.store(&node.base);
18981985 stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
18991986 continue;
......@@ -1912,13 +1999,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
19121999 const token_index = token.index;
19132000 const token_ptr = token.ptr;
19142001 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{
19162004 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
19172005 .lhs = lhs,
19182006 .op_token = token_index,
19192007 .op = ass_id,
19202008 .rhs = undefined,
1921 });
2009 };
19222010 opt_ctx.store(&node.base);
19232011 stack.append(State{ .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
19242012 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } });
......@@ -1942,13 +2030,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
19422030 const token_index = token.index;
19432031 const token_ptr = token.ptr;
19442032 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{
19462035 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
19472036 .lhs = lhs,
19482037 .op_token = token_index,
19492038 .op = unwrap_id,
19502039 .rhs = undefined,
1951 });
2040 };
19522041 opt_ctx.store(&node.base);
19532042
19542043 stack.append(State{ .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
......@@ -1974,13 +2063,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
19742063 const lhs = opt_ctx.get() orelse continue;
19752064
19762065 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{
19782068 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
19792069 .lhs = lhs,
19802070 .op_token = or_token,
19812071 .op = ast.Node.InfixOp.Op.BoolOr,
19822072 .rhs = undefined,
1983 });
2073 };
19842074 opt_ctx.store(&node.base);
19852075 stack.append(State{ .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
19862076 try stack.append(State{ .BoolAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
......@@ -1998,13 +2088,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
19982088 const lhs = opt_ctx.get() orelse continue;
19992089
20002090 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{
20022093 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
20032094 .lhs = lhs,
20042095 .op_token = and_token,
20052096 .op = ast.Node.InfixOp.Op.BoolAnd,
20062097 .rhs = undefined,
2007 });
2098 };
20082099 opt_ctx.store(&node.base);
20092100 stack.append(State{ .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
20102101 try stack.append(State{ .ComparisonExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
......@@ -2025,13 +2116,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
20252116 const token_index = token.index;
20262117 const token_ptr = token.ptr;
20272118 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{
20292121 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
20302122 .lhs = lhs,
20312123 .op_token = token_index,
20322124 .op = comp_id,
20332125 .rhs = undefined,
2034 });
2126 };
20352127 opt_ctx.store(&node.base);
20362128 stack.append(State{ .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
20372129 try stack.append(State{ .BinaryOrExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
......@@ -2052,13 +2144,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
20522144 const lhs = opt_ctx.get() orelse continue;
20532145
20542146 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{
20562149 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
20572150 .lhs = lhs,
20582151 .op_token = pipe,
20592152 .op = ast.Node.InfixOp.Op.BitOr,
20602153 .rhs = undefined,
2061 });
2154 };
20622155 opt_ctx.store(&node.base);
20632156 stack.append(State{ .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
20642157 try stack.append(State{ .BinaryXorExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
......@@ -2076,13 +2169,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
20762169 const lhs = opt_ctx.get() orelse continue;
20772170
20782171 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{
20802174 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
20812175 .lhs = lhs,
20822176 .op_token = caret,
20832177 .op = ast.Node.InfixOp.Op.BitXor,
20842178 .rhs = undefined,
2085 });
2179 };
20862180 opt_ctx.store(&node.base);
20872181 stack.append(State{ .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
20882182 try stack.append(State{ .BinaryAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
......@@ -2100,13 +2194,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
21002194 const lhs = opt_ctx.get() orelse continue;
21012195
21022196 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{
21042199 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
21052200 .lhs = lhs,
21062201 .op_token = ampersand,
21072202 .op = ast.Node.InfixOp.Op.BitAnd,
21082203 .rhs = undefined,
2109 });
2204 };
21102205 opt_ctx.store(&node.base);
21112206 stack.append(State{ .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
21122207 try stack.append(State{ .BitShiftExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
......@@ -2127,13 +2222,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
21272222 const token_index = token.index;
21282223 const token_ptr = token.ptr;
21292224 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{
21312227 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
21322228 .lhs = lhs,
21332229 .op_token = token_index,
21342230 .op = bitshift_id,
21352231 .rhs = undefined,
2136 });
2232 };
21372233 opt_ctx.store(&node.base);
21382234 stack.append(State{ .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
21392235 try stack.append(State{ .AdditionExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
......@@ -2157,13 +2253,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
21572253 const token_index = token.index;
21582254 const token_ptr = token.ptr;
21592255 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{
21612258 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
21622259 .lhs = lhs,
21632260 .op_token = token_index,
21642261 .op = add_id,
21652262 .rhs = undefined,
2166 });
2263 };
21672264 opt_ctx.store(&node.base);
21682265 stack.append(State{ .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
21692266 try stack.append(State{ .MultiplyExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
......@@ -2187,13 +2284,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
21872284 const token_index = token.index;
21882285 const token_ptr = token.ptr;
21892286 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{
21912289 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
21922290 .lhs = lhs,
21932291 .op_token = token_index,
21942292 .op = mult_id,
21952293 .rhs = undefined,
2196 });
2294 };
21972295 opt_ctx.store(&node.base);
21982296 stack.append(State{ .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
21992297 try stack.append(State{ .CurlySuffixExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
......@@ -2215,12 +2313,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
22152313 const lhs = opt_ctx.get() orelse continue;
22162314
22172315 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{
22192318 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
22202319 .lhs = lhs,
22212320 .op = ast.Node.SuffixOp.Op{ .StructInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) },
22222321 .rtoken = undefined,
2223 });
2322 };
22242323 opt_ctx.store(&node.base);
22252324
22262325 stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
......@@ -2234,12 +2333,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
22342333 continue;
22352334 }
22362335
2237 const node = try arena.create(ast.Node.SuffixOp{
2336 const node = try arena.create(ast.Node.SuffixOp);
2337 node.* = ast.Node.SuffixOp{
22382338 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
22392339 .lhs = lhs,
22402340 .op = ast.Node.SuffixOp.Op{ .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) },
22412341 .rtoken = undefined,
2242 });
2342 };
22432343 opt_ctx.store(&node.base);
22442344 stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
22452345 try stack.append(State{ .IfToken = Token.Id.LBrace });
......@@ -2263,13 +2363,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
22632363 const lhs = opt_ctx.get() orelse continue;
22642364
22652365 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{
22672368 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
22682369 .lhs = lhs,
22692370 .op_token = bang,
22702371 .op = ast.Node.InfixOp.Op.ErrorUnion,
22712372 .rhs = undefined,
2272 });
2373 };
22732374 opt_ctx.store(&node.base);
22742375 stack.append(State{ .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable;
22752376 try stack.append(State{ .PrefixOpExpression = OptionalCtx{ .Required = &node.rhs } });
......@@ -2282,22 +2383,24 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
22822383 const token_index = token.index;
22832384 const token_ptr = token.ptr;
22842385 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{
22862388 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
22872389 .op_token = token_index,
22882390 .op = prefix_id,
22892391 .rhs = undefined,
2290 });
2392 };
22912393 opt_ctx.store(&node.base);
22922394
22932395 // Treat '**' token as two pointer types
22942396 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{
22962399 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
22972400 .op_token = token_index,
22982401 .op = prefix_id,
22992402 .rhs = undefined,
2300 });
2403 };
23012404 node.rhs = &child.base;
23022405 node = child;
23032406 }
......@@ -2316,12 +2419,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
23162419
23172420 State.SuffixOpExpressionBegin => |opt_ctx| {
23182421 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{
23202424 .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },
23212425 .async_token = async_token,
23222426 .allocator_type = null,
23232427 .rangle_bracket = null,
2324 });
2428 };
23252429 stack.append(State{
23262430 .AsyncEnd = AsyncEndCtx{
23272431 .ctx = opt_ctx,
......@@ -2347,7 +2451,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
23472451 const token_ptr = token.ptr;
23482452 switch (token_ptr.id) {
23492453 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{
23512456 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
23522457 .lhs = lhs,
23532458 .op = ast.Node.SuffixOp.Op{
......@@ -2357,7 +2462,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
23572462 },
23582463 },
23592464 .rtoken = undefined,
2360 });
2465 };
23612466 opt_ctx.store(&node.base);
23622467
23632468 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
......@@ -2371,12 +2476,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
23712476 continue;
23722477 },
23732478 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{
23752481 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
23762482 .lhs = lhs,
23772483 .op = ast.Node.SuffixOp.Op{ .ArrayAccess = undefined },
23782484 .rtoken = undefined,
2379 });
2485 };
23802486 opt_ctx.store(&node.base);
23812487
23822488 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
......@@ -2386,34 +2492,37 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
23862492 },
23872493 Token.Id.Period => {
23882494 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{
23902497 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
23912498 .lhs = lhs,
23922499 .op = ast.Node.SuffixOp.Op.Deref,
23932500 .rtoken = asterisk_token,
2394 });
2501 };
23952502 opt_ctx.store(&node.base);
23962503 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
23972504 continue;
23982505 }
23992506 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{
24012509 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
24022510 .lhs = lhs,
24032511 .op = ast.Node.SuffixOp.Op.UnwrapOptional,
24042512 .rtoken = question_token,
2405 });
2513 };
24062514 opt_ctx.store(&node.base);
24072515 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
24082516 continue;
24092517 }
2410 const node = try arena.create(ast.Node.InfixOp{
2518 const node = try arena.create(ast.Node.InfixOp);
2519 node.* = ast.Node.InfixOp{
24112520 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
24122521 .lhs = lhs,
24132522 .op_token = token_index,
24142523 .op = ast.Node.InfixOp.Op.Period,
24152524 .rhs = undefined,
2416 });
2525 };
24172526 opt_ctx.store(&node.base);
24182527
24192528 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
......@@ -2467,11 +2576,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
24672576 continue;
24682577 },
24692578 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{
24712581 .base = ast.Node{ .id = ast.Node.Id.PromiseType },
24722582 .promise_token = token.index,
24732583 .result = null,
2474 });
2584 };
24752585 opt_ctx.store(&node.base);
24762586 const next_token = nextToken(&tok_it, &tree);
24772587 const next_token_index = next_token.index;
......@@ -2493,12 +2603,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
24932603 continue;
24942604 },
24952605 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{
24972608 .base = ast.Node{ .id = ast.Node.Id.GroupedExpression },
24982609 .lparen = token.index,
24992610 .expr = undefined,
25002611 .rparen = undefined,
2501 });
2612 };
25022613 opt_ctx.store(&node.base);
25032614
25042615 stack.append(State{
......@@ -2511,12 +2622,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
25112622 continue;
25122623 },
25132624 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{
25152627 .base = ast.Node{ .id = ast.Node.Id.BuiltinCall },
25162628 .builtin_token = token.index,
25172629 .params = ast.Node.BuiltinCall.ParamList.init(arena),
25182630 .rparen_token = undefined,
2519 });
2631 };
25202632 opt_ctx.store(&node.base);
25212633
25222634 stack.append(State{
......@@ -2530,12 +2642,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
25302642 continue;
25312643 },
25322644 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{
25342647 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
25352648 .op_token = token.index,
25362649 .op = undefined,
25372650 .rhs = undefined,
2538 });
2651 };
25392652 opt_ctx.store(&node.base);
25402653
25412654 stack.append(State{ .SliceOrArrayType = node }) catch unreachable;
......@@ -2593,7 +2706,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
25932706 continue;
25942707 },
25952708 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{
25972711 .base = ast.Node{ .id = ast.Node.Id.FnProto },
25982712 .doc_comments = null,
25992713 .visib_token = null,
......@@ -2609,13 +2723,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
26092723 .lib_name = null,
26102724 .align_expr = null,
26112725 .section_expr = null,
2612 });
2726 };
26132727 opt_ctx.store(&fn_proto.base);
26142728 stack.append(State{ .FnProto = fn_proto }) catch unreachable;
26152729 continue;
26162730 },
26172731 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{
26192734 .base = ast.Node{ .id = ast.Node.Id.FnProto },
26202735 .doc_comments = null,
26212736 .visib_token = null,
......@@ -2631,7 +2746,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
26312746 .lib_name = null,
26322747 .align_expr = null,
26332748 .section_expr = null,
2634 });
2749 };
26352750 opt_ctx.store(&fn_proto.base);
26362751 stack.append(State{ .FnProto = fn_proto }) catch unreachable;
26372752 try stack.append(State{
......@@ -2643,7 +2758,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
26432758 continue;
26442759 },
26452760 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{
26472763 .base = ast.Node{ .id = ast.Node.Id.Asm },
26482764 .asm_token = token.index,
26492765 .volatile_token = null,
......@@ -2652,7 +2768,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
26522768 .inputs = ast.Node.Asm.InputList.init(arena),
26532769 .clobbers = ast.Node.Asm.ClobberList.init(arena),
26542770 .rparen = undefined,
2655 });
2771 };
26562772 opt_ctx.store(&node.base);
26572773
26582774 stack.append(State{
......@@ -2701,13 +2817,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
27012817
27022818 State.ErrorTypeOrSetDecl => |ctx| {
27032819 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{
27052822 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
27062823 .lhs = &(try createLiteral(arena, ast.Node.ErrorType, ctx.error_token)).base,
27072824 .op_token = undefined,
27082825 .op = ast.Node.InfixOp.Op.Period,
27092826 .rhs = undefined,
2710 });
2827 };
27112828 ctx.opt_ctx.store(&node.base);
27122829 stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
27132830 try stack.append(State{
......@@ -2719,12 +2836,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
27192836 continue;
27202837 }
27212838
2722 const node = try arena.create(ast.Node.ErrorSetDecl{
2839 const node = try arena.create(ast.Node.ErrorSetDecl);
2840 node.* = ast.Node.ErrorSetDecl{
27232841 .base = ast.Node{ .id = ast.Node.Id.ErrorSetDecl },
27242842 .error_token = ctx.error_token,
27252843 .decls = ast.Node.ErrorSetDecl.DeclList.init(arena),
27262844 .rbrace_token = undefined,
2727 });
2845 };
27282846 ctx.opt_ctx.store(&node.base);
27292847
27302848 stack.append(State{
......@@ -2785,11 +2903,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
27852903 return tree;
27862904 }
27872905
2788 const node = try arena.create(ast.Node.ErrorTag{
2906 const node = try arena.create(ast.Node.ErrorTag);
2907 node.* = ast.Node.ErrorTag{
27892908 .base = ast.Node{ .id = ast.Node.Id.ErrorTag },
27902909 .doc_comments = comments,
27912910 .name_token = ident_token_index,
2792 });
2911 };
27932912 node_ptr.* = &node.base;
27942913 continue;
27952914 },
......@@ -2870,6 +2989,7 @@ const TopLevelDeclCtx = struct {
28702989const VarDeclCtx = struct {
28712990 mut_token: TokenIndex,
28722991 visib_token: ?TokenIndex,
2992 thread_local_token: ?TokenIndex,
28732993 comptime_token: ?TokenIndex,
28742994 extern_export_token: ?TokenIndex,
28752995 lib_name: ?*ast.Node,
......@@ -3014,6 +3134,7 @@ const State = union(enum) {
30143134 ContainerInitArg: *ast.Node.ContainerDecl,
30153135 ContainerDecl: *ast.Node.ContainerDecl,
30163136
3137 ThreadLocal: VarDeclCtx,
30173138 VarDecl: VarDeclCtx,
30183139 VarDeclAlign: *ast.Node.VarDecl,
30193140 VarDeclSection: *ast.Node.VarDecl,
......@@ -3129,10 +3250,11 @@ fn pushDocComment(arena: *mem.Allocator, line_comment: TokenIndex, result: *?*as
31293250 if (result.*) |comment_node| {
31303251 break :blk comment_node;
31313252 } 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{
31333255 .base = ast.Node{ .id = ast.Node.Id.DocComment },
31343256 .lines = ast.Node.DocComment.LineList.init(arena),
3135 });
3257 };
31363258 result.* = comment_node;
31373259 break :blk comment_node;
31383260 }
......@@ -3158,10 +3280,11 @@ fn parseStringLiteral(arena: *mem.Allocator, tok_it: *ast.Tree.TokenList.Iterato
31583280 return &(try createLiteral(arena, ast.Node.StringLiteral, token_index)).base;
31593281 },
31603282 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{
31623285 .base = ast.Node{ .id = ast.Node.Id.MultilineStringLiteral },
31633286 .lines = ast.Node.MultilineStringLiteral.LineList.init(arena),
3164 });
3287 };
31653288 try node.lines.push(token_index);
31663289 while (true) {
31673290 const multiline_str = nextToken(tok_it, tree);
......@@ -3186,25 +3309,27 @@ fn parseStringLiteral(arena: *mem.Allocator, tok_it: *ast.Tree.TokenList.Iterato
31863309fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: OptionalCtx, token_ptr: Token, token_index: TokenIndex) !bool {
31873310 switch (token_ptr.id) {
31883311 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{
31903314 .base = ast.Node{ .id = ast.Node.Id.Suspend },
31913315 .suspend_token = token_index,
31923316 .body = null,
3193 });
3317 };
31943318 ctx.store(&node.base);
31953319
31963320 stack.append(State{ .SuspendBody = node }) catch unreachable;
31973321 return true;
31983322 },
31993323 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{
32013326 .base = ast.Node{ .id = ast.Node.Id.If },
32023327 .if_token = token_index,
32033328 .condition = undefined,
32043329 .payload = null,
32053330 .body = undefined,
32063331 .@"else" = null,
3207 });
3332 };
32083333 ctx.store(&node.base);
32093334
32103335 stack.append(State{ .Else = &node.@"else" }) catch unreachable;
......@@ -3238,13 +3363,14 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: Opti
32383363 return true;
32393364 },
32403365 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{
32423368 .base = ast.Node{ .id = ast.Node.Id.Switch },
32433369 .switch_token = token_index,
32443370 .expr = undefined,
32453371 .cases = ast.Node.Switch.CaseList.init(arena),
32463372 .rbrace = undefined,
3247 });
3373 };
32483374 ctx.store(&node.base);
32493375
32503376 stack.append(State{
......@@ -3260,25 +3386,27 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: Opti
32603386 return true;
32613387 },
32623388 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{
32643391 .base = ast.Node{ .id = ast.Node.Id.Comptime },
32653392 .comptime_token = token_index,
32663393 .expr = undefined,
32673394 .doc_comments = null,
3268 });
3395 };
32693396 ctx.store(&node.base);
32703397
32713398 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } });
32723399 return true;
32733400 },
32743401 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{
32763404 .base = ast.Node{ .id = ast.Node.Id.Block },
32773405 .label = null,
32783406 .lbrace = token_index,
32793407 .statements = ast.Node.Block.StatementList.init(arena),
32803408 .rbrace = undefined,
3281 });
3409 };
32823410 ctx.store(&block.base);
32833411 stack.append(State{ .Block = block }) catch unreachable;
32843412 return true;
......@@ -3397,7 +3525,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {
33973525 Token.Id.Minus => ast.Node.PrefixOp.Op{ .Negation = void{} },
33983526 Token.Id.MinusPercent => ast.Node.PrefixOp.Op{ .NegationWrap = void{} },
33993527 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{
34013534 .PtrType = ast.Node.PrefixOp.PtrInfo{
34023535 .align_info = null,
34033536 .const_token = null,
......@@ -3412,10 +3545,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {
34123545}
34133546
34143547fn 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{
34163550 .base = ast.Node{ .id = ast.Node.typeToId(T) },
34173551 .token = token_index,
3418 });
3552 };
3553 return result;
34193554}
34203555
34213556fn 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 @@
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
115test "zig fmt: linksection" {
216 try testCanonical(
317 \\export var aoeu: u64 linksection(".text.derp") = 1234;
......@@ -5,6 +19,7 @@ test "zig fmt: linksection" {
519 \\
620 );
721}
22
823test "zig fmt: shebang line" {
924 try testCanonical(
1025 \\#!/usr/bin/env zig
......@@ -1940,7 +1955,7 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {
19401955 warn("std.zig.render returned {} instead of {}\n", anything_changed, changes_expected);
19411956 return error.TestFailed;
19421957 }
1943 std.debug.assert(anything_changed == changes_expected);
1958 std.testing.expect(anything_changed == changes_expected);
19441959 failing_allocator.allocator.free(result_source);
19451960 break :x failing_allocator.index;
19461961 };
std/zig/render.zig+3
......@@ -1706,6 +1706,9 @@ fn renderVarDecl(
17061706 try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space); // comptime
17071707 }
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 }
17091712 try renderToken(tree, stream, var_decl.mut_token, indent, start_col, Space.Space); // var
17101713
17111714 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 {
5353 Keyword{ .bytes = "switch", .id = Id.Keyword_switch },
5454 Keyword{ .bytes = "test", .id = Id.Keyword_test },
5555 Keyword{ .bytes = "this", .id = Id.Keyword_this },
56 Keyword{ .bytes = "threadlocal", .id = Id.Keyword_threadlocal },
5657 Keyword{ .bytes = "true", .id = Id.Keyword_true },
5758 Keyword{ .bytes = "try", .id = Id.Keyword_try },
5859 Keyword{ .bytes = "undefined", .id = Id.Keyword_undefined },
......@@ -140,6 +141,7 @@ pub const Token = struct {
140141 LineComment,
141142 DocComment,
142143 BracketStarBracket,
144 BracketStarCBracket,
143145 ShebangLine,
144146 Keyword_align,
145147 Keyword_and,
......@@ -182,6 +184,7 @@ pub const Token = struct {
182184 Keyword_switch,
183185 Keyword_test,
184186 Keyword_this,
187 Keyword_threadlocal,
185188 Keyword_true,
186189 Keyword_try,
187190 Keyword_undefined,
......@@ -277,6 +280,7 @@ pub const Tokenizer = struct {
277280 SawAtSign,
278281 LBracket,
279282 LBracketStar,
283 LBracketStarC,
280284 };
281285
282286 pub fn next(self: *Tokenizer) Token {
......@@ -454,6 +458,9 @@ pub const Tokenizer = struct {
454458 },
455459
456460 State.LBracketStar => switch (c) {
461 'c' => {
462 state = State.LBracketStarC;
463 },
457464 ']' => {
458465 result.id = Token.Id.BracketStarBracket;
459466 self.index += 1;
......@@ -465,6 +472,18 @@ pub const Tokenizer = struct {
465472 },
466473 },
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
468487 State.Ampersand => switch (c) {
469488 '=' => {
470489 result.id = Token.Id.AmpersandEqual;
......@@ -1033,6 +1052,7 @@ pub const Tokenizer = struct {
10331052 State.CharLiteralEnd,
10341053 State.StringLiteralBackslash,
10351054 State.LBracketStar,
1055 State.LBracketStarC,
10361056 => {
10371057 result.id = Token.Id.Invalid;
10381058 },
......@@ -1167,12 +1187,15 @@ test "tokenizer" {
11671187 testTokenize("test", []Token.Id{Token.Id.Keyword_test});
11681188}
11691189
1170test "tokenizer - unknown length pointer" {
1190test "tokenizer - unknown length pointer and then c pointer" {
11711191 testTokenize(
11721192 \\[*]u8
1193 \\[*c]u8
11731194 , []Token.Id{
11741195 Token.Id.BracketStarBracket,
11751196 Token.Id.Identifier,
1197 Token.Id.BracketStarCBracket,
1198 Token.Id.Identifier,
11761199 });
11771200}
11781201
......@@ -1345,5 +1368,5 @@ fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void {
13451368 }
13461369 }
13471370 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);
13491372}
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 @@
11const std = @import("std");
22const builtin = @import("builtin");
33const os = std.os;
4const assertOrPanic = std.debug.assertOrPanic;
4const testing = std.testing;
55
66var a: *std.mem.Allocator = undefined;
77
......@@ -27,9 +27,9 @@ pub fn main() !void {
2727 std.debug.warn("Expected second argument to be cache root directory path\n");
2828 return error.InvalidArgs;
2929 });
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" });
3333 const TestFn = fn ([]const u8, []const u8) anyerror!void;
3434 const test_fns = []TestFn{
3535 testZigInitLib,
......@@ -87,20 +87,20 @@ fn exec(cwd: []const u8, argv: []const []const u8) !os.ChildProcess.ExecResult {
8787fn testZigInitLib(zig_exe: []const u8, dir_path: []const u8) !void {
8888 _ = try exec(dir_path, [][]const u8{ zig_exe, "init-lib" });
8989 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"));
9191}
9292
9393fn testZigInitExe(zig_exe: []const u8, dir_path: []const u8) !void {
9494 _ = try exec(dir_path, [][]const u8{ zig_exe, "init-exe" });
9595 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"));
9797}
9898
9999fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void {
100100 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");
103 const example_s_path = try os.path.join(a, dir_path, "example.s");
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, [][]const u8{ dir_path, "example.s" });
104104
105105 try std.io.writeFile(example_zig_path,
106106 \\// Type your code here, or load an example.
......@@ -126,6 +126,6 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void {
126126 _ = try exec(dir_path, args);
127127
128128 const out_asm = try std.io.readFileAlloc(a, example_s_path);
129 assertOrPanic(std.mem.indexOf(u8, out_asm, "square:") != null);
130 assertOrPanic(std.mem.indexOf(u8, out_asm, "imul\tedi, edi") != null);
129 testing.expect(std.mem.indexOf(u8, out_asm, "square:") != null);
130 testing.expect(std.mem.indexOf(u8, out_asm, "imul\tedi, edi") != null);
131131}
test/compile_errors.zig+366-66
......@@ -1,6 +1,270 @@
11const tests = @import("tests.zig");
22
33pub 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
4268 cases.add(
5269 "error note for function parameter incompatibility",
6270 \\fn do_the_thing(func: fn (arg: i32) void) void {}
......@@ -82,13 +346,23 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
82346 );
83347
84348 cases.add(
85 "Panic declared with wrong type signature in tests",
349 "wrong panic signature, runtime function",
86350 \\test "" {}
87351 \\
88352 \\pub fn panic() void {}
89353 \\
90354 ,
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",
92366 );
93367
94368 cases.add(
......@@ -208,8 +482,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
208482 \\ const Errors = error{} || u16;
209483 \\}
210484 ,
211 ".tmp_source.zig:2:20: error: expected error set type, found 'u8'",
212 ".tmp_source.zig:5:31: error: expected error set type, found 'u16'",
485 ".tmp_source.zig:2:20: error: expected error set type, found type 'u8'",
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",
213489 );
214490
215491 cases.add(
......@@ -238,7 +514,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
238514 \\ f(i32);
239515 \\}
240516 ,
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",
242518 );
243519
244520 cases.add(
......@@ -638,7 +914,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
638914 \\ command.exec();
639915 \\}
640916 ,
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",
642918 );
643919
644920 cases.add(
......@@ -651,7 +927,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
651927 \\ command.exec();
652928 \\}
653929 ,
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",
655931 );
656932
657933 cases.add(
......@@ -2559,7 +2835,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
25592835 \\
25602836 \\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
25612837 ,
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",
25632839 );
25642840
25652841 cases.add(
......@@ -2622,7 +2898,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
26222898 \\
26232899 \\export fn entry() usize { return @sizeOf(@typeOf(x)); }
26242900 ,
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",
26262902 );
26272903
26282904 cases.add(
......@@ -2632,7 +2908,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
26322908 \\ _ = a / a;
26332909 \\}
26342910 ,
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",
26362912 );
26372913
26382914 cases.add(
......@@ -2642,7 +2918,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
26422918 \\ a /= a;
26432919 \\}
26442920 ,
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",
26462922 );
26472923
26482924 cases.add(
......@@ -2652,7 +2928,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
26522928 \\ _ = a % a;
26532929 \\}
26542930 ,
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",
26562932 );
26572933
26582934 cases.add(
......@@ -2662,7 +2938,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
26622938 \\ a %= a;
26632939 \\}
26642940 ,
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",
26662942 );
26672943
26682944 cases.add(
......@@ -2672,7 +2948,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
26722948 \\ _ = a + a;
26732949 \\}
26742950 ,
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",
26762952 );
26772953
26782954 cases.add(
......@@ -2682,7 +2958,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
26822958 \\ a += a;
26832959 \\}
26842960 ,
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",
26862962 );
26872963
26882964 cases.add(
......@@ -2692,7 +2968,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
26922968 \\ _ = a +% a;
26932969 \\}
26942970 ,
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",
26962972 );
26972973
26982974 cases.add(
......@@ -2702,7 +2978,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27022978 \\ a +%= a;
27032979 \\}
27042980 ,
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",
27062982 );
27072983
27082984 cases.add(
......@@ -2712,7 +2988,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27122988 \\ _ = a - a;
27132989 \\}
27142990 ,
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",
27162992 );
27172993
27182994 cases.add(
......@@ -2722,7 +2998,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27222998 \\ a -= a;
27232999 \\}
27243000 ,
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",
27263002 );
27273003
27283004 cases.add(
......@@ -2732,7 +3008,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27323008 \\ _ = a -% a;
27333009 \\}
27343010 ,
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",
27363012 );
27373013
27383014 cases.add(
......@@ -2742,7 +3018,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27423018 \\ a -%= a;
27433019 \\}
27443020 ,
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",
27463022 );
27473023
27483024 cases.add(
......@@ -2752,7 +3028,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27523028 \\ _ = a * a;
27533029 \\}
27543030 ,
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",
27563032 );
27573033
27583034 cases.add(
......@@ -2762,7 +3038,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27623038 \\ a *= a;
27633039 \\}
27643040 ,
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",
27663042 );
27673043
27683044 cases.add(
......@@ -2772,7 +3048,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27723048 \\ _ = a *% a;
27733049 \\}
27743050 ,
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",
27763052 );
27773053
27783054 cases.add(
......@@ -2782,7 +3058,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27823058 \\ a *%= a;
27833059 \\}
27843060 ,
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",
27863062 );
27873063
27883064 cases.add(
......@@ -2792,7 +3068,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
27923068 \\ _ = a << 2;
27933069 \\}
27943070 ,
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",
27963072 );
27973073
27983074 cases.add(
......@@ -2802,7 +3078,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28023078 \\ a <<= 2;
28033079 \\}
28043080 ,
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",
28063082 );
28073083
28083084 cases.add(
......@@ -2812,7 +3088,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28123088 \\ _ = a >> 2;
28133089 \\}
28143090 ,
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",
28163092 );
28173093
28183094 cases.add(
......@@ -2822,7 +3098,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28223098 \\ a >>= 2;
28233099 \\}
28243100 ,
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",
28263102 );
28273103
28283104 cases.add(
......@@ -2832,7 +3108,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28323108 \\ _ = a & a;
28333109 \\}
28343110 ,
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",
28363112 );
28373113
28383114 cases.add(
......@@ -2842,7 +3118,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28423118 \\ a &= a;
28433119 \\}
28443120 ,
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",
28463122 );
28473123
28483124 cases.add(
......@@ -2852,7 +3128,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28523128 \\ _ = a | a;
28533129 \\}
28543130 ,
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",
28563132 );
28573133
28583134 cases.add(
......@@ -2862,7 +3138,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28623138 \\ a |= a;
28633139 \\}
28643140 ,
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",
28663142 );
28673143
28683144 cases.add(
......@@ -2872,7 +3148,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28723148 \\ _ = a ^ a;
28733149 \\}
28743150 ,
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",
28763152 );
28773153
28783154 cases.add(
......@@ -2882,7 +3158,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28823158 \\ a ^= a;
28833159 \\}
28843160 ,
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",
28863162 );
28873163
28883164 cases.add(
......@@ -2892,7 +3168,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
28923168 \\ _ = a == a;
28933169 \\}
28943170 ,
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",
28963172 );
28973173
28983174 cases.add(
......@@ -2902,7 +3178,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29023178 \\ _ = a != a;
29033179 \\}
29043180 ,
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",
29063182 );
29073183
29083184 cases.add(
......@@ -2912,7 +3188,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29123188 \\ _ = a > a;
29133189 \\}
29143190 ,
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",
29163192 );
29173193
29183194 cases.add(
......@@ -2922,7 +3198,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29223198 \\ _ = a >= a;
29233199 \\}
29243200 ,
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",
29263202 );
29273203
29283204 cases.add(
......@@ -2932,7 +3208,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29323208 \\ _ = a < a;
29333209 \\}
29343210 ,
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",
29363212 );
29373213
29383214 cases.add(
......@@ -2942,7 +3218,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29423218 \\ _ = a <= a;
29433219 \\}
29443220 ,
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",
29463222 );
29473223
29483224 cases.add(
......@@ -2952,7 +3228,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29523228 \\ _ = a and a;
29533229 \\}
29543230 ,
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",
29563232 );
29573233
29583234 cases.add(
......@@ -2962,7 +3238,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29623238 \\ _ = a or a;
29633239 \\}
29643240 ,
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",
29663242 );
29673243
29683244 cases.add(
......@@ -2972,7 +3248,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29723248 \\ _ = -a;
29733249 \\}
29743250 ,
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",
29763252 );
29773253
29783254 cases.add(
......@@ -2982,7 +3258,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29823258 \\ _ = -%a;
29833259 \\}
29843260 ,
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",
29863262 );
29873263
29883264 cases.add(
......@@ -2992,7 +3268,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
29923268 \\ _ = ~a;
29933269 \\}
29943270 ,
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",
29963272 );
29973273
29983274 cases.add(
......@@ -3002,7 +3278,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30023278 \\ _ = !a;
30033279 \\}
30043280 ,
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",
30063282 );
30073283
30083284 cases.add(
......@@ -3012,7 +3288,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30123288 \\ _ = a orelse false;
30133289 \\}
30143290 ,
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",
30163292 );
30173293
30183294 cases.add(
......@@ -3022,7 +3298,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
30223298 \\ _ = a catch |err| false;
30233299 \\}
30243300 ,
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",
30263302 );
30273303
30283304 cases.add(
......@@ -3134,7 +3410,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
31343410 \\ return 2;
31353411 \\}
31363412 ,
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",
31383414 );
31393415
31403416 cases.add(
......@@ -3214,7 +3490,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
32143490 cases.add(
32153491 "truncate sign mismatch",
32163492 \\fn f() i8 {
3217 \\ const x: u32 = 10;
3493 \\ var x: u32 = 10;
32183494 \\ return @truncate(i8, x);
32193495 \\}
32203496 \\
......@@ -3480,7 +3756,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
34803756 \\
34813757 \\export fn entry() usize { return @sizeOf(@typeOf(a)); }
34823758 ,
3483 ".tmp_source.zig:2:11: error: expected type, found 'i32'",
3759 ".tmp_source.zig:2:11: error: expected type 'type', found 'i32'",
34843760 );
34853761
34863762 cases.add(
......@@ -4424,20 +4700,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
44244700 ".tmp_source.zig:2:24: error: expected [2]u8 literal, found [3]u8 literal",
44254701 );
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
44414703 cases.add(
44424704 "wrong pointer implicitly casted to pointer to @OpaqueType()",
44434705 \\const Derp = @OpaqueType();
......@@ -5272,4 +5534,42 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
52725534 ,
52735535 ".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_float",
52745536 );
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 );
52755575}
test/runtime_safety.zig+41
......@@ -1,6 +1,16 @@
11const tests = @import("tests.zig");
22
33pub 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
414 cases.addRuntimeSafety("@intToEnum - no matching tag value",
515 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
616 \\ @import("std").os.exit(126);
......@@ -94,6 +104,20 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
94104 \\}
95105 );
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
97121 cases.addRuntimeSafety("integer subtraction overflow",
98122 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
99123 \\ @import("std").os.exit(126);
......@@ -362,6 +386,23 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
362386 \\}
363387 );
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
365406 // This case makes sure that the code compiles and runs. There is not actually a special
366407 // runtime safety check having to do specifically with error return traces across suspend points.
367408 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 @@
11const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
2const expect = std.testing.expect;
33
44extern fn run_c_tests() void;
55
......@@ -33,28 +33,28 @@ test "C ABI integers" {
3333}
3434
3535export fn zig_u8(x: u8) void {
36 assertOrPanic(x == 0xff);
36 expect(x == 0xff);
3737}
3838export fn zig_u16(x: u16) void {
39 assertOrPanic(x == 0xfffe);
39 expect(x == 0xfffe);
4040}
4141export fn zig_u32(x: u32) void {
42 assertOrPanic(x == 0xfffffffd);
42 expect(x == 0xfffffffd);
4343}
4444export fn zig_u64(x: u64) void {
45 assertOrPanic(x == 0xfffffffffffffffc);
45 expect(x == 0xfffffffffffffffc);
4646}
4747export fn zig_i8(x: i8) void {
48 assertOrPanic(x == -1);
48 expect(x == -1);
4949}
5050export fn zig_i16(x: i16) void {
51 assertOrPanic(x == -2);
51 expect(x == -2);
5252}
5353export fn zig_i32(x: i32) void {
54 assertOrPanic(x == -3);
54 expect(x == -3);
5555}
5656export fn zig_i64(x: i64) void {
57 assertOrPanic(x == -4);
57 expect(x == -4);
5858}
5959
6060extern fn c_f32(f32) void;
......@@ -66,10 +66,10 @@ test "C ABI floats" {
6666}
6767
6868export fn zig_f32(x: f32) void {
69 assertOrPanic(x == 12.34);
69 expect(x == 12.34);
7070}
7171export fn zig_f64(x: f64) void {
72 assertOrPanic(x == 56.78);
72 expect(x == 56.78);
7373}
7474
7575extern fn c_ptr(*c_void) void;
......@@ -79,7 +79,7 @@ test "C ABI pointer" {
7979}
8080
8181export fn zig_ptr(x: *c_void) void {
82 assertOrPanic(@ptrToInt(x) == 0xdeadbeef);
82 expect(@ptrToInt(x) == 0xdeadbeef);
8383}
8484
8585extern fn c_bool(bool) void;
......@@ -89,7 +89,7 @@ test "C ABI bool" {
8989}
9090
9191export fn zig_bool(x: bool) void {
92 assertOrPanic(x);
92 expect(x);
9393}
9494
9595extern fn c_array([10]u8) void;
......@@ -100,7 +100,7 @@ test "C ABI array" {
100100}
101101
102102export fn zig_array(x: [10]u8) void {
103 assertOrPanic(std.mem.eql(u8, x, "1234567890"));
103 expect(std.mem.eql(u8, x, "1234567890"));
104104}
105105
106106const BigStruct = extern struct {
......@@ -124,11 +124,11 @@ test "C ABI big struct" {
124124}
125125
126126export fn zig_big_struct(x: BigStruct) void {
127 assertOrPanic(x.a == 1);
128 assertOrPanic(x.b == 2);
129 assertOrPanic(x.c == 3);
130 assertOrPanic(x.d == 4);
131 assertOrPanic(x.e == 5);
127 expect(x.a == 1);
128 expect(x.b == 2);
129 expect(x.c == 3);
130 expect(x.d == 4);
131 expect(x.e == 5);
132132}
133133
134134const BigUnion = extern union {
......@@ -150,11 +150,11 @@ test "C ABI big union" {
150150}
151151
152152export fn zig_big_union(x: BigUnion) void {
153 assertOrPanic(x.a.a == 1);
154 assertOrPanic(x.a.b == 2);
155 assertOrPanic(x.a.c == 3);
156 assertOrPanic(x.a.d == 4);
157 assertOrPanic(x.a.e == 5);
153 expect(x.a.a == 1);
154 expect(x.a.b == 2);
155 expect(x.a.c == 3);
156 expect(x.a.d == 4);
157 expect(x.a.e == 5);
158158}
159159
160160const SmallStructInts = extern struct {
......@@ -176,10 +176,10 @@ test "C ABI small struct of ints" {
176176}
177177
178178export fn zig_small_struct_ints(x: SmallStructInts) void {
179 assertOrPanic(x.a == 1);
180 assertOrPanic(x.b == 2);
181 assertOrPanic(x.c == 3);
182 assertOrPanic(x.d == 4);
179 expect(x.a == 1);
180 expect(x.b == 2);
181 expect(x.c == 3);
182 expect(x.d == 4);
183183}
184184
185185const SplitStructInt = extern struct {
......@@ -199,9 +199,9 @@ test "C ABI split struct of ints" {
199199}
200200
201201export fn zig_split_struct_ints(x: SplitStructInt) void {
202 assertOrPanic(x.a == 1234);
203 assertOrPanic(x.b == 100);
204 assertOrPanic(x.c == 1337);
202 expect(x.a == 1234);
203 expect(x.b == 100);
204 expect(x.c == 1337);
205205}
206206
207207extern fn c_big_struct_both(BigStruct) BigStruct;
......@@ -215,19 +215,19 @@ test "C ABI sret and byval together" {
215215 .e = 5,
216216 };
217217 var y = c_big_struct_both(s);
218 assertOrPanic(y.a == 10);
219 assertOrPanic(y.b == 11);
220 assertOrPanic(y.c == 12);
221 assertOrPanic(y.d == 13);
222 assertOrPanic(y.e == 14);
218 expect(y.a == 10);
219 expect(y.b == 11);
220 expect(y.c == 12);
221 expect(y.d == 13);
222 expect(y.e == 14);
223223}
224224
225225export fn zig_big_struct_both(x: BigStruct) BigStruct {
226 assertOrPanic(x.a == 30);
227 assertOrPanic(x.b == 31);
228 assertOrPanic(x.c == 32);
229 assertOrPanic(x.d == 33);
230 assertOrPanic(x.e == 34);
226 expect(x.a == 30);
227 expect(x.b == 31);
228 expect(x.c == 32);
229 expect(x.d == 33);
230 expect(x.e == 34);
231231 var s = BigStruct{
232232 .a = 20,
233233 .b = 21,
test/standalone/brace_expansion/main.zig+3-6
......@@ -3,6 +3,7 @@ const io = std.io;
33const mem = std.mem;
44const debug = std.debug;
55const assert = debug.assert;
6const testing = std.testing;
67const Buffer = std.Buffer;
78const ArrayList = std.ArrayList;
89const maxInt = std.math.maxInt;
......@@ -220,11 +221,7 @@ fn expectError(test_input: []const u8, expected_err: anyerror) void {
220221 var output_buf = Buffer.initSize(global_allocator, 0) catch unreachable;
221222 defer output_buf.deinit();
222223
223 if (expandString(test_input, &output_buf)) {
224 unreachable;
225 } else |err| {
226 assert(expected_err == err);
227 }
224 testing.expectError(expected_err, expandString(test_input, &output_buf));
228225}
229226
230227test "valid inputs" {
......@@ -256,5 +253,5 @@ fn expectExpansion(test_input: []const u8, expected_result: []const u8) void {
256253
257254 expandString(test_input, &result) catch unreachable;
258255
259 assert(mem.eql(u8, result.toSlice(), expected_result));
256 testing.expectEqualSlices(u8, expected_result, result.toSlice());
260257}
test/standalone/issue_794/main.zig+2-2
......@@ -1,7 +1,7 @@
11const c = @cImport(@cInclude("foo.h"));
22const std = @import("std");
3const assert = std.debug.assert;
3const testing = std.testing;
44
55test "c import" {
6 comptime assert(c.NUMBER == 1234);
6 comptime testing.expect(c.NUMBER == 1234);
77}
test/tests.zig+132-60
......@@ -48,13 +48,14 @@ const test_targets = []TestTarget{
4848const max_stdout_size = 1 * 1024 * 1024; // 1 MB
4949
5050pub 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{
5253 .b = b,
5354 .step = b.step("test-compare-output", "Run the compare output tests"),
5455 .test_index = 0,
5556 .test_filter = test_filter,
5657 .modes = modes,
57 }) catch unreachable;
58 };
5859
5960 compare_output.addCases(cases);
6061
......@@ -62,13 +63,14 @@ pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes:
6263}
6364
6465pub 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{
6668 .b = b,
6769 .step = b.step("test-runtime-safety", "Run the runtime safety tests"),
6870 .test_index = 0,
6971 .test_filter = test_filter,
7072 .modes = modes,
71 }) catch unreachable;
73 };
7274
7375 runtime_safety.addCases(cases);
7476
......@@ -76,13 +78,14 @@ pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes:
7678}
7779
7880pub 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{
8083 .b = b,
8184 .step = b.step("test-compile-errors", "Run the compile error tests"),
8285 .test_index = 0,
8386 .test_filter = test_filter,
8487 .modes = modes,
85 }) catch unreachable;
88 };
8689
8790 compile_errors.addCases(cases);
8891
......@@ -90,13 +93,14 @@ pub fn addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes:
9093}
9194
9295pub 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{
9498 .b = b,
9599 .step = b.step("test-build-examples", "Build the examples"),
96100 .test_index = 0,
97101 .test_filter = test_filter,
98102 .modes = modes,
99 }) catch unreachable;
103 };
100104
101105 build_examples.addCases(cases);
102106
......@@ -119,13 +123,14 @@ pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const M
119123}
120124
121125pub 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{
123128 .b = b,
124129 .step = b.step("test-asm-link", "Run the assemble and link tests"),
125130 .test_index = 0,
126131 .test_filter = test_filter,
127132 .modes = modes,
128 }) catch unreachable;
133 };
129134
130135 assemble_and_link.addCases(cases);
131136
......@@ -133,12 +138,13 @@ pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, mode
133138}
134139
135140pub 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{
137143 .b = b,
138144 .step = b.step("test-translate-c", "Run the C transation tests"),
139145 .test_index = 0,
140146 .test_filter = test_filter,
141 }) catch unreachable;
147 };
142148
143149 translate_c.addCases(cases);
144150
......@@ -146,12 +152,13 @@ pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.St
146152}
147153
148154pub 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{
150157 .b = b,
151158 .step = b.step("test-gen-h", "Run the C header file generation tests"),
152159 .test_index = 0,
153160 .test_filter = test_filter,
154 }) catch unreachable;
161 };
155162
156163 gen_h.addCases(cases);
157164
......@@ -163,25 +170,35 @@ pub fn addPkgTests(b: *build.Builder, test_filter: ?[]const u8, root_src: []cons
163170 for (test_targets) |test_target| {
164171 const is_native = (test_target.os == builtin.os and test_target.arch == builtin.arch);
165172 for (modes) |mode| {
166 for ([]bool{
167 false,
168 true,
169 }) |link_libc| {
170 if (link_libc and !is_native) {
171 // don't assume we have a cross-compiling libc set up
172 continue;
173 }
174 const these_tests = b.addTest(root_src);
175 these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os), @tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare"));
176 these_tests.setFilter(test_filter);
177 these_tests.setBuildMode(mode);
178 if (!is_native) {
179 these_tests.setTarget(test_target.arch, test_target.os, test_target.environ);
180 }
181 if (link_libc) {
182 these_tests.linkSystemLibrary("c");
173 for ([]bool{ false, true }) |link_libc| {
174 for ([]bool{ false, true }) |single_threaded| {
175 if (link_libc and !is_native) {
176 // don't assume we have a cross-compiling libc set up
177 continue;
178 }
179 const these_tests = b.addTest(root_src);
180 these_tests.setNamePrefix(b.fmt(
181 "{}-{}-{}-{}-{}-{} ",
182 name,
183 @tagName(test_target.os),
184 @tagName(test_target.arch),
185 @tagName(mode),
186 if (link_libc) "c" else "bare",
187 if (single_threaded) "single" else "multi",
188 ));
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);
183201 }
184 step.dependOn(&these_tests.step);
185202 }
186203 }
187204 }
......@@ -237,7 +254,8 @@ pub const CompareOutputContext = struct {
237254
238255 pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8, expected_output: []const u8, cli_args: []const []const u8) *RunCompareOutputStep {
239256 const allocator = context.b.allocator;
240 const ptr = allocator.create(RunCompareOutputStep{
257 const ptr = allocator.create(RunCompareOutputStep) catch unreachable;
258 ptr.* = RunCompareOutputStep{
241259 .context = context,
242260 .exe_path = exe_path,
243261 .name = name,
......@@ -245,7 +263,7 @@ pub const CompareOutputContext = struct {
245263 .test_index = context.test_index,
246264 .step = build.Step.init("RunCompareOutput", allocator, make),
247265 .cli_args = cli_args,
248 }) catch unreachable;
266 };
249267 context.test_index += 1;
250268 return ptr;
251269 }
......@@ -324,13 +342,14 @@ pub const CompareOutputContext = struct {
324342
325343 pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8) *RuntimeSafetyRunStep {
326344 const allocator = context.b.allocator;
327 const ptr = allocator.create(RuntimeSafetyRunStep{
345 const ptr = allocator.create(RuntimeSafetyRunStep) catch unreachable;
346 ptr.* = RuntimeSafetyRunStep{
328347 .context = context,
329348 .exe_path = exe_path,
330349 .name = name,
331350 .test_index = context.test_index,
332351 .step = build.Step.init("RuntimeSafetyRun", allocator, make),
333 }) catch unreachable;
352 };
334353
335354 context.test_index += 1;
336355 return ptr;
......@@ -420,7 +439,10 @@ pub const CompareOutputContext = struct {
420439 pub fn addCase(self: *CompareOutputContext, case: TestCase) void {
421440 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
425447 switch (case.special) {
426448 Special.Asm => {
......@@ -433,7 +455,10 @@ pub const CompareOutputContext = struct {
433455 exe.addAssemblyFile(root_src);
434456
435457 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;
437462 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
438463 exe.step.dependOn(&write_src.step);
439464 }
......@@ -457,7 +482,10 @@ pub const CompareOutputContext = struct {
457482 }
458483
459484 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;
461489 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
462490 exe.step.dependOn(&write_src.step);
463491 }
......@@ -480,7 +508,10 @@ pub const CompareOutputContext = struct {
480508 }
481509
482510 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;
484515 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
485516 exe.step.dependOn(&write_src.step);
486517 }
......@@ -507,6 +538,7 @@ pub const CompileErrorContext = struct {
507538 expected_errors: ArrayList([]const u8),
508539 link_libc: bool,
509540 is_exe: bool,
541 is_test: bool,
510542
511543 const SourceFile = struct {
512544 filename: []const u8,
......@@ -535,14 +567,15 @@ pub const CompileErrorContext = struct {
535567
536568 pub fn create(context: *CompileErrorContext, name: []const u8, case: *const TestCase, build_mode: Mode) *CompileCmpOutputStep {
537569 const allocator = context.b.allocator;
538 const ptr = allocator.create(CompileCmpOutputStep{
570 const ptr = allocator.create(CompileCmpOutputStep) catch unreachable;
571 ptr.* = CompileCmpOutputStep{
539572 .step = build.Step.init("CompileCmpOutput", allocator, make),
540573 .context = context,
541574 .name = name,
542575 .test_index = context.test_index,
543576 .case = case,
544577 .build_mode = build_mode,
545 }) catch unreachable;
578 };
546579
547580 context.test_index += 1;
548581 return ptr;
......@@ -552,13 +585,25 @@ pub const CompileErrorContext = struct {
552585 const self = @fieldParentPtr(CompileCmpOutputStep, "step", step);
553586 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;
556 const obj_path = os.path.join(b.allocator, b.cache_root, "test.o") catch unreachable;
588 const root_src = os.path.join(
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
558597 var zig_args = ArrayList([]const u8).init(b.allocator);
559598 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 }
562607 zig_args.append(b.pathFromRoot(root_src)) catch unreachable;
563608
564609 zig_args.append("--name") catch unreachable;
......@@ -654,13 +699,15 @@ pub const CompileErrorContext = struct {
654699 }
655700
656701 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{
658704 .name = name,
659705 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
660706 .expected_errors = ArrayList([]const u8).init(self.b.allocator),
661707 .link_libc = false,
662708 .is_exe = false,
663 }) catch unreachable;
709 .is_test = false,
710 };
664711
665712 tc.addSourceFile(".tmp_source.zig", source);
666713 comptime var arg_i = 0;
......@@ -687,6 +734,12 @@ pub const CompileErrorContext = struct {
687734 self.addCase(tc);
688735 }
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
690743 pub fn addCase(self: *CompileErrorContext, case: *const TestCase) void {
691744 const b = self.b;
692745
......@@ -700,7 +753,10 @@ pub const CompileErrorContext = struct {
700753 self.step.dependOn(&compile_and_cmp_errors.step);
701754
702755 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;
704760 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
705761 compile_and_cmp_errors.step.dependOn(&write_src.step);
706762 }
......@@ -814,13 +870,14 @@ pub const TranslateCContext = struct {
814870
815871 pub fn create(context: *TranslateCContext, name: []const u8, case: *const TestCase) *TranslateCCmpOutputStep {
816872 const allocator = context.b.allocator;
817 const ptr = allocator.create(TranslateCCmpOutputStep{
873 const ptr = allocator.create(TranslateCCmpOutputStep) catch unreachable;
874 ptr.* = TranslateCCmpOutputStep{
818875 .step = build.Step.init("ParseCCmpOutput", allocator, make),
819876 .context = context,
820877 .name = name,
821878 .test_index = context.test_index,
822879 .case = case,
823 }) catch unreachable;
880 };
824881
825882 context.test_index += 1;
826883 return ptr;
......@@ -830,7 +887,10 @@ pub const TranslateCContext = struct {
830887 const self = @fieldParentPtr(TranslateCCmpOutputStep, "step", step);
831888 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
835895 var zig_args = ArrayList([]const u8).init(b.allocator);
836896 zig_args.append(b.zig_exe) catch unreachable;
......@@ -921,12 +981,13 @@ pub const TranslateCContext = struct {
921981 }
922982
923983 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{
925986 .name = name,
926987 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
927988 .expected_lines = ArrayList([]const u8).init(self.b.allocator),
928989 .allow_warnings = allow_warnings,
929 }) catch unreachable;
990 };
930991
931992 tc.addSourceFile(filename, source);
932993 comptime var arg_i = 0;
......@@ -963,7 +1024,10 @@ pub const TranslateCContext = struct {
9631024 self.step.dependOn(&translate_c_and_cmp.step);
9641025
9651026 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;
9671031 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
9681032 translate_c_and_cmp.step.dependOn(&write_src.step);
9691033 }
......@@ -1008,14 +1072,15 @@ pub const GenHContext = struct {
10081072
10091073 pub fn create(context: *GenHContext, h_path: []const u8, name: []const u8, case: *const TestCase) *GenHCmpOutputStep {
10101074 const allocator = context.b.allocator;
1011 const ptr = allocator.create(GenHCmpOutputStep{
1075 const ptr = allocator.create(GenHCmpOutputStep) catch unreachable;
1076 ptr.* = GenHCmpOutputStep{
10121077 .step = build.Step.init("ParseCCmpOutput", allocator, make),
10131078 .context = context,
10141079 .h_path = h_path,
10151080 .name = name,
10161081 .test_index = context.test_index,
10171082 .case = case,
1018 }) catch unreachable;
1083 };
10191084
10201085 context.test_index += 1;
10211086 return ptr;
......@@ -1055,11 +1120,12 @@ pub const GenHContext = struct {
10551120 }
10561121
10571122 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{
10591125 .name = name,
10601126 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
10611127 .expected_lines = ArrayList([]const u8).init(self.b.allocator),
1062 }) catch unreachable;
1128 };
10631129
10641130 tc.addSourceFile(filename, source);
10651131 comptime var arg_i = 0;
......@@ -1076,7 +1142,10 @@ pub const GenHContext = struct {
10761142
10771143 pub fn addCase(self: *GenHContext, case: *const TestCase) void {
10781144 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
10811150 const mode = builtin.Mode.Debug;
10821151 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 {
10881157 obj.setBuildMode(mode);
10891158
10901159 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;
10921164 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
10931165 obj.step.dependOn(&write_src.step);
10941166 }
test/translate_c.zig+61-31
......@@ -117,11 +117,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
117117 \\};
118118 ,
119119 \\pub const struct_Foo = extern struct {
120 \\ a: ?[*]Foo,
120 \\ a: [*c]Foo,
121121 \\};
122122 \\pub const Foo = struct_Foo;
123123 \\pub const struct_Bar = extern struct {
124 \\ a: ?[*]Foo,
124 \\ a: [*c]Foo,
125125 \\};
126126 );
127127
......@@ -213,7 +213,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
213213 ,
214214 \\const struct_Foo = extern struct {
215215 \\ x: c_int,
216 \\ y: ?[*]u8,
216 \\ y: [*c]u8,
217217 \\};
218218 ,
219219 \\pub const Foo = struct_Foo;
......@@ -244,7 +244,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
244244 ,
245245 \\pub const BarB = enum_Bar.B;
246246 ,
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;
248248 ,
249249 \\pub const Foo = struct_Foo;
250250 ,
......@@ -254,7 +254,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
254254 cases.add("constant size array",
255255 \\void func(int array[20]);
256256 ,
257 \\pub extern fn func(array: ?[*]c_int) void;
257 \\pub extern fn func(array: [*c]c_int) void;
258258 );
259259
260260 cases.add("self referential struct with function pointer",
......@@ -263,7 +263,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
263263 \\};
264264 ,
265265 \\pub const struct_Foo = extern struct {
266 \\ derp: ?extern fn(?[*]struct_Foo) void,
266 \\ derp: ?extern fn([*c]struct_Foo) void,
267267 \\};
268268 ,
269269 \\pub const Foo = struct_Foo;
......@@ -322,11 +322,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
322322 \\};
323323 ,
324324 \\pub const struct_Bar = extern struct {
325 \\ next: ?[*]struct_Foo,
325 \\ next: [*c]struct_Foo,
326326 \\};
327327 ,
328328 \\pub const struct_Foo = extern struct {
329 \\ next: ?[*]struct_Bar,
329 \\ next: [*c]struct_Bar,
330330 \\};
331331 );
332332
......@@ -610,11 +610,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
610610 ,
611611 \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
612612 \\ if ((a != 0) and (b != 0)) return 0;
613 \\ if ((b != 0) and (c != null)) return 1;
614 \\ if ((a != 0) and (c != null)) return 2;
613 \\ if ((b != 0) and (c != 0)) return 1;
614 \\ if ((a != 0) and (c != 0)) return 2;
615615 \\ if ((a != 0) or (b != 0)) return 3;
616 \\ if ((b != 0) or (c != null)) return 4;
617 \\ if ((a != 0) or (c != null)) return 5;
616 \\ if ((b != 0) or (c != 0)) return 4;
617 \\ if ((a != 0) or (c != 0)) return 5;
618618 \\ return 6;
619619 \\}
620620 );
......@@ -710,7 +710,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
710710 \\pub const struct_Foo = extern struct {
711711 \\ field: c_int,
712712 \\};
713 \\pub export fn read_field(foo: ?[*]struct_Foo) c_int {
713 \\pub export fn read_field(foo: [*c]struct_Foo) c_int {
714714 \\ return foo.?.field;
715715 \\}
716716 );
......@@ -756,7 +756,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
756756 \\ return x;
757757 \\}
758758 ,
759 \\pub export fn foo(x: ?[*]c_ushort) ?*c_void {
759 \\pub export fn foo(x: [*c]c_ushort) ?*c_void {
760760 \\ return @ptrCast(?*c_void, x);
761761 \\}
762762 );
......@@ -777,8 +777,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
777777 \\ return 0;
778778 \\}
779779 ,
780 \\pub export fn foo() ?[*]c_int {
781 \\ return null;
780 \\pub export fn foo() [*c]c_int {
781 \\ return 0;
782782 \\}
783783 );
784784
......@@ -1086,7 +1086,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
10861086 \\ *x = 1;
10871087 \\}
10881088 ,
1089 \\pub export fn foo(x: ?[*]c_int) void {
1089 \\pub export fn foo(x: [*c]c_int) void {
10901090 \\ x.?.* = 1;
10911091 \\}
10921092 );
......@@ -1114,7 +1114,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
11141114 ,
11151115 \\pub fn foo() c_int {
11161116 \\ var x: c_int = 1234;
1117 \\ var ptr: ?[*]c_int = &x;
1117 \\ var ptr: [*c]c_int = &x;
11181118 \\ return ptr.?.*;
11191119 \\}
11201120 );
......@@ -1124,7 +1124,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
11241124 \\ return "bar";
11251125 \\}
11261126 ,
1127 \\pub fn foo() ?[*]const u8 {
1127 \\pub fn foo() [*c]const u8 {
11281128 \\ return c"bar";
11291129 \\}
11301130 );
......@@ -1253,8 +1253,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12531253 \\ return (float *)a;
12541254 \\}
12551255 ,
1256 \\fn ptrcast(a: ?[*]c_int) ?[*]f32 {
1257 \\ return @ptrCast(?[*]f32, a);
1256 \\fn ptrcast(a: [*c]c_int) [*c]f32 {
1257 \\ return @ptrCast([*c]f32, a);
12581258 \\}
12591259 );
12601260
......@@ -1280,7 +1280,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12801280 \\ return !(a == 0);
12811281 \\ return !(a != 0);
12821282 \\ return !(b != 0);
1283 \\ return !(c != null);
1283 \\ return !(c != 0);
12841284 \\}
12851285 );
12861286
......@@ -1297,7 +1297,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
12971297 cases.add("const ptr initializer",
12981298 \\static const char *v0 = "0.0.0";
12991299 ,
1300 \\pub var v0: ?[*]const u8 = c"0.0.0";
1300 \\pub var v0: [*c]const u8 = c"0.0.0";
13011301 );
13021302
13031303 cases.add("static incomplete array inside function",
......@@ -1306,17 +1306,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13061306 \\}
13071307 ,
13081308 \\pub fn foo() void {
1309 \\ const v2: [*]const u8 = c"2.2.2";
1309 \\ const v2: [*c]const u8 = c"2.2.2";
13101310 \\}
13111311 );
13121312
13131313 cases.add("macro pointer cast",
13141314 \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
13151315 ,
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);
13171317 );
13181318
1319 cases.add("if on none bool",
1319 cases.add("if on non-bool",
13201320 \\enum SomeEnum { A, B, C };
13211321 \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) {
13221322 \\ if (a) return 0;
......@@ -1337,13 +1337,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13371337 \\pub fn if_none_bool(a: c_int, b: f32, c: ?*c_void, d: enum_SomeEnum) c_int {
13381338 \\ if (a != 0) return 0;
13391339 \\ if (b != 0) return 1;
1340 \\ if (c != null) return 2;
1340 \\ if (c != 0) return 2;
13411341 \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3;
13421342 \\ return 4;
13431343 \\}
13441344 );
13451345
1346 cases.add("while on none bool",
1346 cases.add("while on non-bool",
13471347 \\int while_none_bool(int a, float b, void *c) {
13481348 \\ while (a) return 0;
13491349 \\ while (b) return 1;
......@@ -1354,12 +1354,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13541354 \\pub fn while_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
13551355 \\ while (a != 0) return 0;
13561356 \\ while (b != 0) return 1;
1357 \\ while (c != null) return 2;
1357 \\ while (c != 0) return 2;
13581358 \\ return 3;
13591359 \\}
13601360 );
13611361
1362 cases.add("for on none bool",
1362 cases.add("for on non-bool",
13631363 \\int for_none_bool(int a, float b, void *c) {
13641364 \\ for (;a;) return 0;
13651365 \\ for (;b;) return 1;
......@@ -1370,7 +1370,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13701370 \\pub fn for_none_bool(a: c_int, b: f32, c: ?*c_void) c_int {
13711371 \\ while (a != 0) return 0;
13721372 \\ while (b != 0) return 1;
1373 \\ while (c != null) return 2;
1373 \\ while (c != 0) return 2;
13741374 \\ return 3;
13751375 \\}
13761376 );
......@@ -1416,4 +1416,34 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
14161416 \\ }
14171417 \\}
14181418 );
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 // );
14191449}