authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-04 21:26:50-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-04 21:26:50-05:00
logf32f7a937fa7150aaba450b1282bba9f01918807
treeecb462e15546a50b2e948b8f2907872dd39a2dc6
parent1411df4e2705e677003e6e5b5cbe1ca30bf637d7
parent8c6fa982cd0a02775264b616c37da9907cc603bb
signature Commit is signed but in an unrecognized format.

Merge remote-tracking branch 'origin/master' into llvm8


234 files changed, 13794 insertions(+), 10517 deletions(-)

.builds/freebsd.yml+8-8
...@@ -12,28 +12,28 @@ tasks:...@@ -12,28 +12,28 @@ tasks:
12 ninja install12 ninja install
13 - test: |13 - test: |
14 cd zig/build14 cd zig/build
15 bin/zig test ../test/behavior.zig15 bin/zig test ../test/stage1/behavior.zig
16 bin/zig test ../std/special/compiler_rt/index.zig16 bin/zig test ../std/special/compiler_rt/index.zig
1717
18 bin/zig test ../test/behavior.zig --library c18 bin/zig test ../test/stage1/behavior.zig --library c
19 bin/zig test ../std/special/compiler_rt/index.zig --library c19 bin/zig test ../std/special/compiler_rt/index.zig --library c
2020
21 bin/zig test ../test/behavior.zig --release-fast21 bin/zig test ../test/stage1/behavior.zig --release-fast
22 bin/zig test ../std/special/compiler_rt/index.zig --release-fast22 bin/zig test ../std/special/compiler_rt/index.zig --release-fast
2323
24 bin/zig test ../test/behavior.zig --release-fast --library c24 bin/zig test ../test/stage1/behavior.zig --release-fast --library c
25 bin/zig test ../std/special/compiler_rt/index.zig --release-fast --library c25 bin/zig test ../std/special/compiler_rt/index.zig --release-fast --library c
2626
27 bin/zig test ../test/behavior.zig --release-small --library c27 bin/zig test ../test/stage1/behavior.zig --release-small --library c
28 bin/zig test ../std/special/compiler_rt/index.zig --release-small --library c28 bin/zig test ../std/special/compiler_rt/index.zig --release-small --library c
2929
30 bin/zig test ../test/behavior.zig --release-small30 bin/zig test ../test/stage1/behavior.zig --release-small
31 bin/zig test ../std/special/compiler_rt/index.zig --release-small31 bin/zig test ../std/special/compiler_rt/index.zig --release-small
3232
33 bin/zig test ../test/behavior.zig --release-safe33 bin/zig test ../test/stage1/behavior.zig --release-safe
34 bin/zig test ../std/special/compiler_rt/index.zig --release-safe34 bin/zig test ../std/special/compiler_rt/index.zig --release-safe
3535
36 bin/zig test ../test/behavior.zig --release-safe --library c36 bin/zig test ../test/stage1/behavior.zig --release-safe --library c
37 bin/zig test ../std/special/compiler_rt/index.zig --release-safe --library c37 bin/zig test ../std/special/compiler_rt/index.zig --release-safe --library c
38 # TODO enable all tests38 # TODO enable all tests
39 #bin/zig build --build-file ../build.zig test39 #bin/zig build --build-file ../build.zig test
CMakeLists.txt+16-15
...@@ -454,10 +454,10 @@ set(ZIG_STD_FILES...@@ -454,10 +454,10 @@ set(ZIG_STD_FILES
454 "crypto/hmac.zig"454 "crypto/hmac.zig"
455 "crypto/index.zig"455 "crypto/index.zig"
456 "crypto/md5.zig"456 "crypto/md5.zig"
457 "crypto/poly1305.zig"
457 "crypto/sha1.zig"458 "crypto/sha1.zig"
458 "crypto/sha2.zig"459 "crypto/sha2.zig"
459 "crypto/sha3.zig"460 "crypto/sha3.zig"
460 "crypto/poly1305.zig"
461 "crypto/x25519.zig"461 "crypto/x25519.zig"
462 "cstr.zig"462 "cstr.zig"
463 "debug/failing_allocator.zig"463 "debug/failing_allocator.zig"
...@@ -566,9 +566,9 @@ set(ZIG_STD_FILES...@@ -566,9 +566,9 @@ set(ZIG_STD_FILES
566 "math/tan.zig"566 "math/tan.zig"
567 "math/tanh.zig"567 "math/tanh.zig"
568 "math/trunc.zig"568 "math/trunc.zig"
569 "mem.zig"
569 "meta/index.zig"570 "meta/index.zig"
570 "meta/trait.zig"571 "meta/trait.zig"
571 "mem.zig"
572 "mutex.zig"572 "mutex.zig"
573 "net.zig"573 "net.zig"
574 "os/child_process.zig"574 "os/child_process.zig"
...@@ -576,16 +576,16 @@ set(ZIG_STD_FILES...@@ -576,16 +576,16 @@ set(ZIG_STD_FILES
576 "os/darwin/errno.zig"576 "os/darwin/errno.zig"
577 "os/epoch.zig"577 "os/epoch.zig"
578 "os/file.zig"578 "os/file.zig"
579 "os/freebsd/errno.zig"
580 "os/freebsd/index.zig"
579 "os/get_app_data_dir.zig"581 "os/get_app_data_dir.zig"
580 "os/get_user_id.zig"582 "os/get_user_id.zig"
581 "os/index.zig"583 "os/index.zig"
584 "os/linux/arm64.zig"
582 "os/linux/errno.zig"585 "os/linux/errno.zig"
583 "os/linux/index.zig"586 "os/linux/index.zig"
584 "os/linux/vdso.zig"587 "os/linux/vdso.zig"
585 "os/linux/x86_64.zig"588 "os/linux/x86_64.zig"
586 "os/linux/arm64.zig"
587 "os/freebsd/errno.zig"
588 "os/freebsd/index.zig"
589 "os/path.zig"589 "os/path.zig"
590 "os/time.zig"590 "os/time.zig"
591 "os/uefi.zig"591 "os/uefi.zig"
...@@ -612,6 +612,16 @@ set(ZIG_STD_FILES...@@ -612,6 +612,16 @@ set(ZIG_STD_FILES
612 "special/compiler_rt/comparetf2.zig"612 "special/compiler_rt/comparetf2.zig"
613 "special/compiler_rt/divti3.zig"613 "special/compiler_rt/divti3.zig"
614 "special/compiler_rt/extendXfYf2.zig"614 "special/compiler_rt/extendXfYf2.zig"
615 "special/compiler_rt/fixdfdi.zig"
616 "special/compiler_rt/fixdfsi.zig"
617 "special/compiler_rt/fixdfti.zig"
618 "special/compiler_rt/fixint.zig"
619 "special/compiler_rt/fixsfdi.zig"
620 "special/compiler_rt/fixsfsi.zig"
621 "special/compiler_rt/fixsfti.zig"
622 "special/compiler_rt/fixtfdi.zig"
623 "special/compiler_rt/fixtfsi.zig"
624 "special/compiler_rt/fixtfti.zig"
615 "special/compiler_rt/fixuint.zig"625 "special/compiler_rt/fixuint.zig"
616 "special/compiler_rt/fixunsdfdi.zig"626 "special/compiler_rt/fixunsdfdi.zig"
617 "special/compiler_rt/fixunsdfsi.zig"627 "special/compiler_rt/fixunsdfsi.zig"
...@@ -622,16 +632,6 @@ set(ZIG_STD_FILES...@@ -622,16 +632,6 @@ set(ZIG_STD_FILES
622 "special/compiler_rt/fixunstfdi.zig"632 "special/compiler_rt/fixunstfdi.zig"
623 "special/compiler_rt/fixunstfsi.zig"633 "special/compiler_rt/fixunstfsi.zig"
624 "special/compiler_rt/fixunstfti.zig"634 "special/compiler_rt/fixunstfti.zig"
625 "special/compiler_rt/fixint.zig"
626 "special/compiler_rt/fixdfdi.zig"
627 "special/compiler_rt/fixdfsi.zig"
628 "special/compiler_rt/fixdfti.zig"
629 "special/compiler_rt/fixsfdi.zig"
630 "special/compiler_rt/fixsfsi.zig"
631 "special/compiler_rt/fixsfti.zig"
632 "special/compiler_rt/fixtfdi.zig"
633 "special/compiler_rt/fixtfsi.zig"
634 "special/compiler_rt/fixtfti.zig"
635 "special/compiler_rt/floattidf.zig"635 "special/compiler_rt/floattidf.zig"
636 "special/compiler_rt/floattisf.zig"636 "special/compiler_rt/floattisf.zig"
637 "special/compiler_rt/floattitf.zig"637 "special/compiler_rt/floattitf.zig"
...@@ -656,6 +656,7 @@ set(ZIG_STD_FILES...@@ -656,6 +656,7 @@ set(ZIG_STD_FILES
656 "special/panic.zig"656 "special/panic.zig"
657 "special/test_runner.zig"657 "special/test_runner.zig"
658 "spinlock.zig"658 "spinlock.zig"
659 "statically_initialized_mutex.zig"
659 "unicode.zig"660 "unicode.zig"
660 "zig/ast.zig"661 "zig/ast.zig"
661 "zig/index.zig"662 "zig/index.zig"
build.zig+10-11
...@@ -104,7 +104,7 @@ pub fn build(b: *Builder) !void {...@@ -104,7 +104,7 @@ pub fn build(b: *Builder) !void {
104 }104 }
105 const modes = chosen_modes[0..chosen_mode_index];105 const modes = chosen_modes[0..chosen_mode_index];
106106
107 test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", modes));107 test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/behavior.zig", "behavior", "Run the behavior tests", modes));
108108
109 test_step.dependOn(tests.addPkgTests(b, test_filter, "std/index.zig", "std", "Run the standard library tests", modes));109 test_step.dependOn(tests.addPkgTests(b, test_filter, "std/index.zig", "std", "Run the standard library tests", modes));
110110
...@@ -189,14 +189,14 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {...@@ -189,14 +189,14 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
189 const prefix_output = try b.exec([][]const u8{ llvm_config_exe, "--prefix" });189 const prefix_output = try b.exec([][]const u8{ llvm_config_exe, "--prefix" });
190190
191 var result = LibraryDep{191 var result = LibraryDep{
192 .prefix = mem.split(prefix_output, " \r\n").next().?,192 .prefix = mem.tokenize(prefix_output, " \r\n").next().?,
193 .libs = ArrayList([]const u8).init(b.allocator),193 .libs = ArrayList([]const u8).init(b.allocator),
194 .system_libs = ArrayList([]const u8).init(b.allocator),194 .system_libs = ArrayList([]const u8).init(b.allocator),
195 .includes = ArrayList([]const u8).init(b.allocator),195 .includes = ArrayList([]const u8).init(b.allocator),
196 .libdirs = ArrayList([]const u8).init(b.allocator),196 .libdirs = ArrayList([]const u8).init(b.allocator),
197 };197 };
198 {198 {
199 var it = mem.split(libs_output, " \r\n");199 var it = mem.tokenize(libs_output, " \r\n");
200 while (it.next()) |lib_arg| {200 while (it.next()) |lib_arg| {
201 if (mem.startsWith(u8, lib_arg, "-l")) {201 if (mem.startsWith(u8, lib_arg, "-l")) {
202 try result.system_libs.append(lib_arg[2..]);202 try result.system_libs.append(lib_arg[2..]);
...@@ -210,7 +210,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {...@@ -210,7 +210,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
210 }210 }
211 }211 }
212 {212 {
213 var it = mem.split(includes_output, " \r\n");213 var it = mem.tokenize(includes_output, " \r\n");
214 while (it.next()) |include_arg| {214 while (it.next()) |include_arg| {
215 if (mem.startsWith(u8, include_arg, "-I")) {215 if (mem.startsWith(u8, include_arg, "-I")) {
216 try result.includes.append(include_arg[2..]);216 try result.includes.append(include_arg[2..]);
...@@ -220,7 +220,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {...@@ -220,7 +220,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
220 }220 }
221 }221 }
222 {222 {
223 var it = mem.split(libdir_output, " \r\n");223 var it = mem.tokenize(libdir_output, " \r\n");
224 while (it.next()) |libdir| {224 while (it.next()) |libdir| {
225 if (mem.startsWith(u8, libdir, "-L")) {225 if (mem.startsWith(u8, libdir, "-L")) {
226 try result.libdirs.append(libdir[2..]);226 try result.libdirs.append(libdir[2..]);
...@@ -233,7 +233,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {...@@ -233,7 +233,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
233}233}
234234
235pub fn installStdLib(b: *Builder, stdlib_files: []const u8) void {235pub fn installStdLib(b: *Builder, stdlib_files: []const u8) void {
236 var it = mem.split(stdlib_files, ";");236 var it = mem.tokenize(stdlib_files, ";");
237 while (it.next()) |stdlib_file| {237 while (it.next()) |stdlib_file| {
238 const src_path = os.path.join(b.allocator, "std", stdlib_file) catch unreachable;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;239 const dest_path = os.path.join(b.allocator, "lib", "zig", "std", stdlib_file) catch unreachable;
...@@ -242,7 +242,7 @@ pub fn installStdLib(b: *Builder, stdlib_files: []const u8) void {...@@ -242,7 +242,7 @@ pub fn installStdLib(b: *Builder, stdlib_files: []const u8) void {
242}242}
243243
244pub fn installCHeaders(b: *Builder, c_header_files: []const u8) void {244pub fn installCHeaders(b: *Builder, c_header_files: []const u8) void {
245 var it = mem.split(c_header_files, ";");245 var it = mem.tokenize(c_header_files, ";");
246 while (it.next()) |c_header_file| {246 while (it.next()) |c_header_file| {
247 const src_path = os.path.join(b.allocator, "c_headers", c_header_file) catch unreachable;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;248 const dest_path = os.path.join(b.allocator, "lib", "zig", "include", c_header_file) catch unreachable;
...@@ -277,7 +277,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {...@@ -277,7 +277,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
277 addCppLib(b, exe, ctx.cmake_binary_dir, "zig_cpp");277 addCppLib(b, exe, ctx.cmake_binary_dir, "zig_cpp");
278 if (ctx.lld_include_dir.len != 0) {278 if (ctx.lld_include_dir.len != 0) {
279 exe.addIncludeDir(ctx.lld_include_dir);279 exe.addIncludeDir(ctx.lld_include_dir);
280 var it = mem.split(ctx.lld_libraries, ";");280 var it = mem.tokenize(ctx.lld_libraries, ";");
281 while (it.next()) |lib| {281 while (it.next()) |lib| {
282 exe.addObjectFile(lib);282 exe.addObjectFile(lib);
283 }283 }
...@@ -299,8 +299,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {...@@ -299,8 +299,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
299 } else if (exe.target.isFreeBSD()) {299 } else if (exe.target.isFreeBSD()) {
300 try addCxxKnownPath(b, ctx, exe, "libc++.a", null);300 try addCxxKnownPath(b, ctx, exe, "libc++.a", null);
301 exe.linkSystemLibrary("pthread");301 exe.linkSystemLibrary("pthread");
302 }302 } else if (exe.target.isDarwin()) {
303 else if (exe.target.isDarwin()) {
304 if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) {303 if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) {
305 // Compiler is GCC.304 // Compiler is GCC.
306 try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null);305 try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null);
...@@ -335,7 +334,7 @@ fn addCxxKnownPath(...@@ -335,7 +334,7 @@ fn addCxxKnownPath(
335 ctx.cxx_compiler,334 ctx.cxx_compiler,
336 b.fmt("-print-file-name={}", objname),335 b.fmt("-print-file-name={}", objname),
337 });336 });
338 const path_unpadded = mem.split(path_padded, "\r\n").next().?;337 const path_unpadded = mem.tokenize(path_padded, "\r\n").next().?;
339 if (mem.eql(u8, path_unpadded, objname)) {338 if (mem.eql(u8, path_unpadded, objname)) {
340 if (errtxt) |msg| {339 if (errtxt) |msg| {
341 warn("{}", msg);340 warn("{}", msg);
doc/langref.html.in+60-6
...@@ -1531,6 +1531,29 @@ test "array initialization with function calls" {...@@ -1531,6 +1531,29 @@ test "array initialization with function calls" {
1531 {#code_end#}1531 {#code_end#}
1532 {#see_also|for|Slices#}1532 {#see_also|for|Slices#}
1533 {#header_close#}1533 {#header_close#}
1534
1535 {#header_open|Vectors#}
1536 <p>
1537 A vector is a group of {#link|Integers#}, {#link|Floats#}, or {#link|Pointers#} which are operated on
1538 in parallel using a single instruction ({#link|SIMD#}). Vector types are created with the builtin
1539 function {#link|@Vector#}.
1540 </p>
1541 <p>
1542 TODO talk about C ABI interop
1543 </p>
1544 {#header_open|SIMD#}
1545 <p>
1546 TODO Zig's SIMD abilities are just beginning to be fleshed out. Here are some talking points to update the
1547 docs with:
1548 * What kind of operations can you do? All the operations on integers and floats? What about mixing scalar and vector?
1549 * How to convert to/from vectors/arrays
1550 * How to access individual elements from vectors, how to loop over the elements
1551 * "shuffle"
1552 * Advice on writing high perf software, how to abstract the best way
1553 </p>
1554 {#header_close#}
1555 {#header_close#}
1556
1534 {#header_open|Pointers#}1557 {#header_open|Pointers#}
1535 <p>1558 <p>
1536 Zig has two kinds of pointers:1559 Zig has two kinds of pointers:
...@@ -4327,7 +4350,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {...@@ -4327,7 +4350,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {
4327 <p>4350 <p>
4328 For example, if we were to introduce another function to the above snippet:4351 For example, if we were to introduce another function to the above snippet:
4329 </p>4352 </p>
4330 {#code_begin|test_err|unable to evaluate constant expression#}4353 {#code_begin|test_err|values of type 'type' must be comptime known#}
4331fn max(comptime T: type, a: T, b: T) T {4354fn max(comptime T: type, a: T, b: T) T {
4332 return if (a > b) a else b;4355 return if (a > b) a else b;
4333}4356}
...@@ -5905,13 +5928,13 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -5905,13 +5928,13 @@ fn add(a: i32, b: i32) i32 { return a + b; }
5905 This function is a low level intrinsic with no safety mechanisms. Most code5928 This function is a low level intrinsic with no safety mechanisms. Most code
5906 should not use this function, instead using something like this:5929 should not use this function, instead using something like this:
5907 </p>5930 </p>
5908 <pre>{#syntax#}for (source[0...byte_count]) |b, i| dest[i] = b;{#endsyntax#}</pre>5931 <pre>{#syntax#}for (source[0..byte_count]) |b, i| dest[i] = b;{#endsyntax#}</pre>
5909 <p>5932 <p>
5910 The optimizer is intelligent enough to turn the above snippet into a memcpy.5933 The optimizer is intelligent enough to turn the above snippet into a memcpy.
5911 </p>5934 </p>
5912 <p>There is also a standard library function for this:</p>5935 <p>There is also a standard library function for this:</p>
5913 <pre>{#syntax#}const mem = @import("std").mem;5936 <pre>{#syntax#}const mem = @import("std").mem;
5914mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>5937mem.copy(u8, dest[0..byte_count], source[0..byte_count]);{#endsyntax#}</pre>
5915 {#header_close#}5938 {#header_close#}
59165939
5917 {#header_open|@memset#}5940 {#header_open|@memset#}
...@@ -5923,7 +5946,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>...@@ -5923,7 +5946,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>
5923 This function is a low level intrinsic with no safety mechanisms. Most5946 This function is a low level intrinsic with no safety mechanisms. Most
5924 code should not use this function, instead using something like this:5947 code should not use this function, instead using something like this:
5925 </p>5948 </p>
5926 <pre>{#syntax#}for (dest[0...byte_count]) |*b| b.* = c;{#endsyntax#}</pre>5949 <pre>{#syntax#}for (dest[0..byte_count]) |*b| b.* = c;{#endsyntax#}</pre>
5927 <p>5950 <p>
5928 The optimizer is intelligent enough to turn the above snippet into a memset.5951 The optimizer is intelligent enough to turn the above snippet into a memset.
5929 </p>5952 </p>
...@@ -6592,9 +6615,10 @@ pub const TypeInfo = union(TypeId) {...@@ -6592,9 +6615,10 @@ pub const TypeInfo = union(TypeId) {
6592 {#header_close#}6615 {#header_close#}
65936616
6594 {#header_open|@typeName#}6617 {#header_open|@typeName#}
6595 <pre>{#syntax#}@typeName(T: type) []u8{#endsyntax#}</pre>6618 <pre>{#syntax#}@typeName(T: type) [N]u8{#endsyntax#}</pre>
6596 <p>6619 <p>
6597 This function returns the string representation of a type.6620 This function returns the string representation of a type, as
6621 an array. It is equivalent to a string literal of the type name.
6598 </p>6622 </p>
65996623
6600 {#header_close#}6624 {#header_close#}
...@@ -6606,6 +6630,17 @@ pub const TypeInfo = union(TypeId) {...@@ -6606,6 +6630,17 @@ pub const TypeInfo = union(TypeId) {
6606 expression passed as an argument. The expression is evaluated.6630 expression passed as an argument. The expression is evaluated.
6607 </p>6631 </p>
66086632
6633 {#header_close#}
6634
6635 {#header_open|@Vector#}
6636 <pre>{#syntax#}@Vector(comptime len: u32, comptime ElemType: type) type{#endsyntax#}</pre>
6637 <p>
6638 This function returns a vector type for {#link|SIMD#}.
6639 </p>
6640 <p>
6641 {#syntax#}ElemType{#endsyntax#} must be an {#link|integer|Integers#}, a {#link|float|Floats#}, or a
6642 {#link|pointer|Pointers#}.
6643 </p>
6609 {#header_close#}6644 {#header_close#}
6610 {#header_close#}6645 {#header_close#}
66116646
...@@ -6679,6 +6714,25 @@ pub fn build(b: *Builder) void {...@@ -6679,6 +6714,25 @@ pub fn build(b: *Builder) void {
6679 {#header_close#}6714 {#header_close#}
6680 {#see_also|Compile Variables|Zig Build System|Undefined Behavior#}6715 {#see_also|Compile Variables|Zig Build System|Undefined Behavior#}
6681 {#header_close#}6716 {#header_close#}
6717
6718 {#header_open|Single Threaded Builds#}
6719 <p>Zig has a compile option <code>--single-threaded</code> which has the following effects:
6720 <ul>
6721 <li>{#link|@atomicLoad#} is emitted as a normal load.</li>
6722 <li>{#link|@atomicRmw#} is emitted as a normal memory load, modify, store.</li>
6723 <li>{#link|@fence#} becomes a no-op.</li>
6724 <li>Variables which have Thread Local Storage instead become globals. TODO thread local variables
6725 are not implemented yet.</li>
6726 <li>The overhead of {#link|Coroutines#} becomes equivalent to function call overhead.
6727 TODO: please note this will not be implemented until the upcoming Coroutine Rewrite</li>
6728 <li>The {#syntax#}@import("builtin").single_threaded{#endsyntax#} becomes {#syntax#}true{#endsyntax#}
6729 and therefore various userland APIs which read this variable become more efficient.
6730 For example {#syntax#}std.Mutex{#endsyntax#} becomes
6731 an empty data structure and all of its functions become no-ops.</li>
6732 </ul>
6733 </p>
6734 {#header_close#}
6735
6682 {#header_open|Undefined Behavior#}6736 {#header_open|Undefined Behavior#}
6683 <p>6737 <p>
6684 Zig has many instances of undefined behavior. If undefined behavior is6738 Zig has many instances of undefined behavior. If undefined behavior is
src-self-hosted/compilation.zig+43-29
...@@ -83,10 +83,11 @@ pub const ZigCompiler = struct {...@@ -83,10 +83,11 @@ pub const ZigCompiler = struct {
83 const context_ref = c.LLVMContextCreate() orelse return error.OutOfMemory;83 const context_ref = c.LLVMContextCreate() orelse return error.OutOfMemory;
84 errdefer c.LLVMContextDispose(context_ref);84 errdefer c.LLVMContextDispose(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.ContextRef).Node);
87 node.* = std.atomic.Stack(llvm.ContextRef).Node{
87 .next = undefined,88 .next = undefined,
88 .data = context_ref,89 .data = context_ref,
89 });90 };
90 errdefer self.loop.allocator.destroy(node);91 errdefer self.loop.allocator.destroy(node);
9192
92 return LlvmHandle{ .node = node };93 return LlvmHandle{ .node = node };
...@@ -596,7 +597,8 @@ pub const Compilation = struct {...@@ -596,7 +597,8 @@ pub const Compilation = struct {
596 }597 }
597598
598 fn initTypes(comp: *Compilation) !void {599 fn initTypes(comp: *Compilation) !void {
599 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{
600 .base = Type{602 .base = Type{
601 .name = "type",603 .name = "type",
602 .base = Value{604 .base = Value{
...@@ -608,12 +610,13 @@ pub const Compilation = struct {...@@ -608,12 +610,13 @@ pub const Compilation = struct {
608 .abi_alignment = Type.AbiAlignment.init(comp.loop),610 .abi_alignment = Type.AbiAlignment.init(comp.loop),
609 },611 },
610 .value = undefined,612 .value = undefined,
611 });613 };
612 comp.meta_type.value = &comp.meta_type.base;614 comp.meta_type.value = &comp.meta_type.base;
613 comp.meta_type.base.base.typ = &comp.meta_type.base;615 comp.meta_type.base.base.typ = &comp.meta_type.base;
614 assert((try comp.primitive_type_table.put(comp.meta_type.base.name, &comp.meta_type.base)) == null);616 assert((try comp.primitive_type_table.put(comp.meta_type.base.name, &comp.meta_type.base)) == null);
615617
616 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{
617 .base = Type{620 .base = Type{
618 .name = "void",621 .name = "void",
619 .base = Value{622 .base = Value{
...@@ -624,10 +627,11 @@ pub const Compilation = struct {...@@ -624,10 +627,11 @@ pub const Compilation = struct {
624 .id = builtin.TypeId.Void,627 .id = builtin.TypeId.Void,
625 .abi_alignment = Type.AbiAlignment.init(comp.loop),628 .abi_alignment = Type.AbiAlignment.init(comp.loop),
626 },629 },
627 });630 };
628 assert((try comp.primitive_type_table.put(comp.void_type.base.name, &comp.void_type.base)) == null);631 assert((try comp.primitive_type_table.put(comp.void_type.base.name, &comp.void_type.base)) == null);
629632
630 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{
631 .base = Type{635 .base = Type{
632 .name = "noreturn",636 .name = "noreturn",
633 .base = Value{637 .base = Value{
...@@ -638,10 +642,11 @@ pub const Compilation = struct {...@@ -638,10 +642,11 @@ pub const Compilation = struct {
638 .id = builtin.TypeId.NoReturn,642 .id = builtin.TypeId.NoReturn,
639 .abi_alignment = Type.AbiAlignment.init(comp.loop),643 .abi_alignment = Type.AbiAlignment.init(comp.loop),
640 },644 },
641 });645 };
642 assert((try comp.primitive_type_table.put(comp.noreturn_type.base.name, &comp.noreturn_type.base)) == null);646 assert((try comp.primitive_type_table.put(comp.noreturn_type.base.name, &comp.noreturn_type.base)) == null);
643647
644 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{
645 .base = Type{650 .base = Type{
646 .name = "comptime_int",651 .name = "comptime_int",
647 .base = Value{652 .base = Value{
...@@ -652,10 +657,11 @@ pub const Compilation = struct {...@@ -652,10 +657,11 @@ pub const Compilation = struct {
652 .id = builtin.TypeId.ComptimeInt,657 .id = builtin.TypeId.ComptimeInt,
653 .abi_alignment = Type.AbiAlignment.init(comp.loop),658 .abi_alignment = Type.AbiAlignment.init(comp.loop),
654 },659 },
655 });660 };
656 assert((try comp.primitive_type_table.put(comp.comptime_int_type.base.name, &comp.comptime_int_type.base)) == null);661 assert((try comp.primitive_type_table.put(comp.comptime_int_type.base.name, &comp.comptime_int_type.base)) == null);
657662
658 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{
659 .base = Type{665 .base = Type{
660 .name = "bool",666 .name = "bool",
661 .base = Value{667 .base = Value{
...@@ -666,45 +672,50 @@ pub const Compilation = struct {...@@ -666,45 +672,50 @@ pub const Compilation = struct {
666 .id = builtin.TypeId.Bool,672 .id = builtin.TypeId.Bool,
667 .abi_alignment = Type.AbiAlignment.init(comp.loop),673 .abi_alignment = Type.AbiAlignment.init(comp.loop),
668 },674 },
669 });675 };
670 assert((try comp.primitive_type_table.put(comp.bool_type.base.name, &comp.bool_type.base)) == null);676 assert((try comp.primitive_type_table.put(comp.bool_type.base.name, &comp.bool_type.base)) == null);
671677
672 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{
673 .base = Value{680 .base = Value{
674 .id = Value.Id.Void,681 .id = Value.Id.Void,
675 .typ = &Type.Void.get(comp).base,682 .typ = &Type.Void.get(comp).base,
676 .ref_count = std.atomic.Int(usize).init(1),683 .ref_count = std.atomic.Int(usize).init(1),
677 },684 },
678 });685 };
679686
680 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{
681 .base = Value{689 .base = Value{
682 .id = Value.Id.Bool,690 .id = Value.Id.Bool,
683 .typ = &Type.Bool.get(comp).base,691 .typ = &Type.Bool.get(comp).base,
684 .ref_count = std.atomic.Int(usize).init(1),692 .ref_count = std.atomic.Int(usize).init(1),
685 },693 },
686 .x = true,694 .x = true,
687 });695 };
688696
689 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{
690 .base = Value{699 .base = Value{
691 .id = Value.Id.Bool,700 .id = Value.Id.Bool,
692 .typ = &Type.Bool.get(comp).base,701 .typ = &Type.Bool.get(comp).base,
693 .ref_count = std.atomic.Int(usize).init(1),702 .ref_count = std.atomic.Int(usize).init(1),
694 },703 },
695 .x = false,704 .x = false,
696 });705 };
697706
698 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{
699 .base = Value{709 .base = Value{
700 .id = Value.Id.NoReturn,710 .id = Value.Id.NoReturn,
701 .typ = &Type.NoReturn.get(comp).base,711 .typ = &Type.NoReturn.get(comp).base,
702 .ref_count = std.atomic.Int(usize).init(1),712 .ref_count = std.atomic.Int(usize).init(1),
703 },713 },
704 });714 };
705715
706 for (CInt.list) |cint, i| {716 for (CInt.list) |cint, i| {
707 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{
708 .base = Type{719 .base = Type{
709 .name = cint.zig_name,720 .name = cint.zig_name,
710 .base = Value{721 .base = Value{
...@@ -720,11 +731,12 @@ pub const Compilation = struct {...@@ -720,11 +731,12 @@ pub const Compilation = struct {
720 .bit_count = comp.target.cIntTypeSizeInBits(cint.id),731 .bit_count = comp.target.cIntTypeSizeInBits(cint.id),
721 },732 },
722 .garbage_node = undefined,733 .garbage_node = undefined,
723 });734 };
724 comp.c_int_types[i] = c_int_type;735 comp.c_int_types[i] = c_int_type;
725 assert((try comp.primitive_type_table.put(cint.zig_name, &c_int_type.base)) == null);736 assert((try comp.primitive_type_table.put(cint.zig_name, &c_int_type.base)) == null);
726 }737 }
727 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{
728 .base = Type{740 .base = Type{
729 .name = "u8",741 .name = "u8",
730 .base = Value{742 .base = Value{
...@@ -740,7 +752,7 @@ pub const Compilation = struct {...@@ -740,7 +752,7 @@ pub const Compilation = struct {
740 .bit_count = 8,752 .bit_count = 8,
741 },753 },
742 .garbage_node = undefined,754 .garbage_node = undefined,
743 });755 };
744 assert((try comp.primitive_type_table.put(comp.u8_type.base.name, &comp.u8_type.base)) == null);756 assert((try comp.primitive_type_table.put(comp.u8_type.base.name, &comp.u8_type.base)) == null);
745 }757 }
746758
...@@ -829,7 +841,7 @@ pub const Compilation = struct {...@@ -829,7 +841,7 @@ pub const Compilation = struct {
829 };841 };
830 errdefer self.gpa().free(source_code);842 errdefer self.gpa().free(source_code);
831843
832 const tree = try self.gpa().createOne(ast.Tree);844 const tree = try self.gpa().create(ast.Tree);
833 tree.* = try std.zig.parse(self.gpa(), source_code);845 tree.* = try std.zig.parse(self.gpa(), source_code);
834 errdefer {846 errdefer {
835 tree.deinit();847 tree.deinit();
...@@ -925,7 +937,8 @@ pub const Compilation = struct {...@@ -925,7 +937,8 @@ pub const Compilation = struct {
925 }937 }
926 } else {938 } else {
927 // add new decl939 // add new decl
928 const fn_decl = try self.gpa().create(Decl.Fn{940 const fn_decl = try self.gpa().create(Decl.Fn);
941 fn_decl.* = Decl.Fn{
929 .base = Decl{942 .base = Decl{
930 .id = Decl.Id.Fn,943 .id = Decl.Id.Fn,
931 .name = name,944 .name = name,
...@@ -936,7 +949,7 @@ pub const Compilation = struct {...@@ -936,7 +949,7 @@ pub const Compilation = struct {
936 },949 },
937 .value = Decl.Fn.Val{ .Unresolved = {} },950 .value = Decl.Fn.Val{ .Unresolved = {} },
938 .fn_proto = fn_proto,951 .fn_proto = fn_proto,
939 });952 };
940 tree_scope.base.ref();953 tree_scope.base.ref();
941 errdefer self.gpa().destroy(fn_decl);954 errdefer self.gpa().destroy(fn_decl);
942955
...@@ -1140,12 +1153,13 @@ pub const Compilation = struct {...@@ -1140,12 +1153,13 @@ pub const Compilation = struct {
1140 }1153 }
1141 }1154 }
11421155
1143 const link_lib = try self.gpa().create(LinkLib{1156 const link_lib = try self.gpa().create(LinkLib);
1157 link_lib.* = LinkLib{
1144 .name = name,1158 .name = name,
1145 .path = null,1159 .path = null,
1146 .provided_explicitly = provided_explicitly,1160 .provided_explicitly = provided_explicitly,
1147 .symbols = ArrayList([]u8).init(self.gpa()),1161 .symbols = ArrayList([]u8).init(self.gpa()),
1148 });1162 };
1149 try self.link_libs_list.append(link_lib);1163 try self.link_libs_list.append(link_lib);
1150 if (is_libc) {1164 if (is_libc) {
1151 self.libc_link_lib = link_lib;1165 self.libc_link_lib = link_lib;
src-self-hosted/errmsg.zig+12-8
...@@ -118,7 +118,8 @@ pub const Msg = struct {...@@ -118,7 +118,8 @@ pub const Msg = struct {
118 const realpath = try mem.dupe(comp.gpa(), u8, tree_scope.root().realpath);118 const realpath = try mem.dupe(comp.gpa(), u8, tree_scope.root().realpath);
119 errdefer comp.gpa().free(realpath);119 errdefer comp.gpa().free(realpath);
120120
121 const msg = try comp.gpa().create(Msg{121 const msg = try comp.gpa().create(Msg);
122 msg.* = Msg{
122 .text = text,123 .text = text,
123 .realpath = realpath,124 .realpath = realpath,
124 .data = Data{125 .data = Data{
...@@ -128,7 +129,7 @@ pub const Msg = struct {...@@ -128,7 +129,7 @@ pub const Msg = struct {
128 .span = span,129 .span = span,
129 },130 },
130 },131 },
131 });132 };
132 tree_scope.base.ref();133 tree_scope.base.ref();
133 return msg;134 return msg;
134 }135 }
...@@ -139,13 +140,14 @@ pub const Msg = struct {...@@ -139,13 +140,14 @@ pub const Msg = struct {
139 const realpath_copy = try mem.dupe(comp.gpa(), u8, realpath);140 const realpath_copy = try mem.dupe(comp.gpa(), u8, realpath);
140 errdefer comp.gpa().free(realpath_copy);141 errdefer comp.gpa().free(realpath_copy);
141142
142 const msg = try comp.gpa().create(Msg{143 const msg = try comp.gpa().create(Msg);
144 msg.* = Msg{
143 .text = text,145 .text = text,
144 .realpath = realpath_copy,146 .realpath = realpath_copy,
145 .data = Data{147 .data = Data{
146 .Cli = Cli{ .allocator = comp.gpa() },148 .Cli = Cli{ .allocator = comp.gpa() },
147 },149 },
148 });150 };
149 return msg;151 return msg;
150 }152 }
151153
...@@ -164,7 +166,8 @@ pub const Msg = struct {...@@ -164,7 +166,8 @@ pub const Msg = struct {
164 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;166 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
165 try parse_error.render(&tree_scope.tree.tokens, out_stream);167 try parse_error.render(&tree_scope.tree.tokens, out_stream);
166168
167 const msg = try comp.gpa().create(Msg{169 const msg = try comp.gpa().create(Msg);
170 msg.* = Msg{
168 .text = undefined,171 .text = undefined,
169 .realpath = realpath_copy,172 .realpath = realpath_copy,
170 .data = Data{173 .data = Data{
...@@ -177,7 +180,7 @@ pub const Msg = struct {...@@ -177,7 +180,7 @@ pub const Msg = struct {
177 },180 },
178 },181 },
179 },182 },
180 });183 };
181 tree_scope.base.ref();184 tree_scope.base.ref();
182 msg.text = text_buf.toOwnedSlice();185 msg.text = text_buf.toOwnedSlice();
183 return msg;186 return msg;
...@@ -203,7 +206,8 @@ pub const Msg = struct {...@@ -203,7 +206,8 @@ pub const Msg = struct {
203 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;206 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
204 try parse_error.render(&tree.tokens, out_stream);207 try parse_error.render(&tree.tokens, out_stream);
205208
206 const msg = try allocator.create(Msg{209 const msg = try allocator.create(Msg);
210 msg.* = Msg{
207 .text = undefined,211 .text = undefined,
208 .realpath = realpath_copy,212 .realpath = realpath_copy,
209 .data = Data{213 .data = Data{
...@@ -216,7 +220,7 @@ pub const Msg = struct {...@@ -216,7 +220,7 @@ pub const Msg = struct {
216 },220 },
217 },221 },
218 },222 },
219 });223 };
220 msg.text = text_buf.toOwnedSlice();224 msg.text = text_buf.toOwnedSlice();
221 errdefer allocator.destroy(msg);225 errdefer allocator.destroy(msg);
222226
src-self-hosted/ir.zig+9-6
...@@ -1021,12 +1021,13 @@ pub const Builder = struct {...@@ -1021,12 +1021,13 @@ pub const Builder = struct {
1021 pub const Error = Analyze.Error;1021 pub const Error = Analyze.Error;
10221022
1023 pub fn init(comp: *Compilation, tree_scope: *Scope.AstTree, begin_scope: ?*Scope) !Builder {1023 pub fn init(comp: *Compilation, tree_scope: *Scope.AstTree, begin_scope: ?*Scope) !Builder {
1024 const code = try comp.gpa().create(Code{1024 const code = try comp.gpa().create(Code);
1025 code.* = Code{
1025 .basic_block_list = undefined,1026 .basic_block_list = undefined,
1026 .arena = std.heap.ArenaAllocator.init(comp.gpa()),1027 .arena = std.heap.ArenaAllocator.init(comp.gpa()),
1027 .return_type = null,1028 .return_type = null,
1028 .tree_scope = tree_scope,1029 .tree_scope = tree_scope,
1029 });1030 };
1030 code.basic_block_list = std.ArrayList(*BasicBlock).init(&code.arena.allocator);1031 code.basic_block_list = std.ArrayList(*BasicBlock).init(&code.arena.allocator);
1031 errdefer code.destroy(comp.gpa());1032 errdefer code.destroy(comp.gpa());
10321033
...@@ -1052,7 +1053,8 @@ pub const Builder = struct {...@@ -1052,7 +1053,8 @@ pub const Builder = struct {
10521053
1053 /// No need to clean up resources thanks to the arena allocator.1054 /// No need to clean up resources thanks to the arena allocator.
1054 pub fn createBasicBlock(self: *Builder, scope: *Scope, name_hint: [*]const u8) !*BasicBlock {1055 pub fn createBasicBlock(self: *Builder, scope: *Scope, name_hint: [*]const u8) !*BasicBlock {
1055 const basic_block = try self.arena().create(BasicBlock{1056 const basic_block = try self.arena().create(BasicBlock);
1057 basic_block.* = BasicBlock{
1056 .ref_count = 0,1058 .ref_count = 0,
1057 .name_hint = name_hint,1059 .name_hint = name_hint,
1058 .debug_id = self.next_debug_id,1060 .debug_id = self.next_debug_id,
...@@ -1063,7 +1065,7 @@ pub const Builder = struct {...@@ -1063,7 +1065,7 @@ pub const Builder = struct {
1063 .ref_instruction = null,1065 .ref_instruction = null,
1064 .llvm_block = undefined,1066 .llvm_block = undefined,
1065 .llvm_exit_block = undefined,1067 .llvm_exit_block = undefined,
1066 });1068 };
1067 self.next_debug_id += 1;1069 self.next_debug_id += 1;
1068 return basic_block;1070 return basic_block;
1069 }1071 }
...@@ -1774,7 +1776,8 @@ pub const Builder = struct {...@@ -1774,7 +1776,8 @@ pub const Builder = struct {
1774 params: I.Params,1776 params: I.Params,
1775 is_generated: bool,1777 is_generated: bool,
1776 ) !*Inst {1778 ) !*Inst {
1777 const inst = try self.arena().create(I{1779 const inst = try self.arena().create(I);
1780 inst.* = I{
1778 .base = Inst{1781 .base = Inst{
1779 .id = Inst.typeToId(I),1782 .id = Inst.typeToId(I),
1780 .is_generated = is_generated,1783 .is_generated = is_generated,
...@@ -1793,7 +1796,7 @@ pub const Builder = struct {...@@ -1793,7 +1796,7 @@ pub const Builder = struct {
1793 .owner_bb = self.current_basic_block,1796 .owner_bb = self.current_basic_block,
1794 },1797 },
1795 .params = params,1798 .params = params,
1796 });1799 };
17971800
1798 // Look at the params and ref() other instructions1801 // Look at the params and ref() other instructions
1799 comptime var i = 0;1802 comptime var i = 0;
src-self-hosted/libc_installation.zig+4-4
...@@ -57,10 +57,10 @@ pub const LibCInstallation = struct {...@@ -57,10 +57,10 @@ pub const LibCInstallation = struct {
57 const contents = try std.io.readFileAlloc(allocator, libc_file);57 const contents = try std.io.readFileAlloc(allocator, libc_file);
58 defer allocator.free(contents);58 defer allocator.free(contents);
5959
60 var it = std.mem.split(contents, "\n");60 var it = std.mem.tokenize(contents, "\n");
61 while (it.next()) |line| {61 while (it.next()) |line| {
62 if (line.len == 0 or line[0] == '#') continue;62 if (line.len == 0 or line[0] == '#') continue;
63 var line_it = std.mem.split(line, "=");63 var line_it = std.mem.separate(line, "=");
64 const name = line_it.next() orelse {64 const name = line_it.next() orelse {
65 try stderr.print("missing equal sign after field name\n");65 try stderr.print("missing equal sign after field name\n");
66 return error.ParseError;66 return error.ParseError;
...@@ -213,7 +213,7 @@ pub const LibCInstallation = struct {...@@ -213,7 +213,7 @@ pub const LibCInstallation = struct {
213 },213 },
214 }214 }
215215
216 var it = std.mem.split(exec_result.stderr, "\n\r");216 var it = std.mem.tokenize(exec_result.stderr, "\n\r");
217 var search_paths = std.ArrayList([]const u8).init(loop.allocator);217 var search_paths = std.ArrayList([]const u8).init(loop.allocator);
218 defer search_paths.deinit();218 defer search_paths.deinit();
219 while (it.next()) |line| {219 while (it.next()) |line| {
...@@ -410,7 +410,7 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo...@@ -410,7 +410,7 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo
410 return error.CCompilerCrashed;410 return error.CCompilerCrashed;
411 },411 },
412 }412 }
413 var it = std.mem.split(exec_result.stdout, "\n\r");413 var it = std.mem.tokenize(exec_result.stdout, "\n\r");
414 const line = it.next() orelse return error.LibCRuntimeNotFound;414 const line = it.next() orelse return error.LibCRuntimeNotFound;
415 const dirname = std.os.path.dirname(line) orelse return error.LibCRuntimeNotFound;415 const dirname = std.os.path.dirname(line) orelse return error.LibCRuntimeNotFound;
416416
src-self-hosted/main.zig+4-3
...@@ -351,7 +351,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -351,7 +351,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
351 const root_name = if (provided_name) |n| n else blk: {351 const root_name = if (provided_name) |n| n else blk: {
352 if (root_source_file) |file| {352 if (root_source_file) |file| {
353 const basename = os.path.basename(file);353 const basename = os.path.basename(file);
354 var it = mem.split(basename, ".");354 var it = mem.separate(basename, ".");
355 break :blk it.next() orelse basename;355 break :blk it.next() orelse basename;
356 } else {356 } else {
357 try stderr.write("--name [name] not provided and unable to infer\n");357 try stderr.write("--name [name] not provided and unable to infer\n");
...@@ -944,12 +944,13 @@ const CliPkg = struct {...@@ -944,12 +944,13 @@ const CliPkg = struct {
944 parent: ?*CliPkg,944 parent: ?*CliPkg,
945945
946 pub fn init(allocator: *mem.Allocator, name: []const u8, path: []const u8, parent: ?*CliPkg) !*CliPkg {946 pub fn init(allocator: *mem.Allocator, name: []const u8, path: []const u8, parent: ?*CliPkg) !*CliPkg {
947 var pkg = try allocator.create(CliPkg{947 var pkg = try allocator.create(CliPkg);
948 pkg.* = CliPkg{
948 .name = name,949 .name = name,
949 .path = path,950 .path = path,
950 .children = ArrayList(*CliPkg).init(allocator),951 .children = ArrayList(*CliPkg).init(allocator),
951 .parent = parent,952 .parent = parent,
952 });953 };
953 return pkg;954 return pkg;
954 }955 }
955956
src-self-hosted/package.zig+4-2
...@@ -15,11 +15,13 @@ pub const Package = struct {...@@ -15,11 +15,13 @@ pub const Package = struct {
15 /// makes internal copies of root_src_dir and root_src_path15 /// makes internal copies of root_src_dir and root_src_path
16 /// allocator should be an arena allocator because Package never frees anything16 /// allocator should be an arena allocator because Package never frees anything
17 pub fn create(allocator: *mem.Allocator, root_src_dir: []const u8, root_src_path: []const u8) !*Package {17 pub fn create(allocator: *mem.Allocator, root_src_dir: []const u8, root_src_path: []const u8) !*Package {
18 return allocator.create(Package{18 const ptr = try allocator.create(Package);
19 ptr.* = Package{
19 .root_src_dir = try Buffer.init(allocator, root_src_dir),20 .root_src_dir = try Buffer.init(allocator, root_src_dir),
20 .root_src_path = try Buffer.init(allocator, root_src_path),21 .root_src_path = try Buffer.init(allocator, root_src_path),
21 .table = Table.init(allocator),22 .table = Table.init(allocator),
22 });23 };
24 return ptr;
23 }25 }
2426
25 pub fn add(self: *Package, name: []const u8, package: *Package) !void {27 pub fn add(self: *Package, name: []const u8, package: *Package) !void {
src-self-hosted/scope.zig+9-9
...@@ -120,7 +120,7 @@ pub const Scope = struct {...@@ -120,7 +120,7 @@ pub const Scope = struct {
120 /// Creates a Root scope with 1 reference120 /// Creates a Root scope with 1 reference
121 /// Takes ownership of realpath121 /// Takes ownership of realpath
122 pub fn create(comp: *Compilation, realpath: []u8) !*Root {122 pub fn create(comp: *Compilation, realpath: []u8) !*Root {
123 const self = try comp.gpa().createOne(Root);123 const self = try comp.gpa().create(Root);
124 self.* = Root{124 self.* = Root{
125 .base = Scope{125 .base = Scope{
126 .id = Id.Root,126 .id = Id.Root,
...@@ -150,7 +150,7 @@ pub const Scope = struct {...@@ -150,7 +150,7 @@ pub const Scope = struct {
150 /// Creates a scope with 1 reference150 /// Creates a scope with 1 reference
151 /// Takes ownership of tree, will deinit and destroy when done.151 /// Takes ownership of tree, will deinit and destroy when done.
152 pub fn create(comp: *Compilation, tree: *ast.Tree, root_scope: *Root) !*AstTree {152 pub fn create(comp: *Compilation, tree: *ast.Tree, root_scope: *Root) !*AstTree {
153 const self = try comp.gpa().createOne(AstTree);153 const self = try comp.gpa().create(AstTree);
154 self.* = AstTree{154 self.* = AstTree{
155 .base = undefined,155 .base = undefined,
156 .tree = tree,156 .tree = tree,
...@@ -182,7 +182,7 @@ pub const Scope = struct {...@@ -182,7 +182,7 @@ pub const Scope = struct {
182182
183 /// Creates a Decls scope with 1 reference183 /// Creates a Decls scope with 1 reference
184 pub fn create(comp: *Compilation, parent: *Scope) !*Decls {184 pub fn create(comp: *Compilation, parent: *Scope) !*Decls {
185 const self = try comp.gpa().createOne(Decls);185 const self = try comp.gpa().create(Decls);
186 self.* = Decls{186 self.* = Decls{
187 .base = undefined,187 .base = undefined,
188 .table = event.RwLocked(Decl.Table).init(comp.loop, Decl.Table.init(comp.gpa())),188 .table = event.RwLocked(Decl.Table).init(comp.loop, Decl.Table.init(comp.gpa())),
...@@ -235,7 +235,7 @@ pub const Scope = struct {...@@ -235,7 +235,7 @@ pub const Scope = struct {
235235
236 /// Creates a Block scope with 1 reference236 /// Creates a Block scope with 1 reference
237 pub fn create(comp: *Compilation, parent: *Scope) !*Block {237 pub fn create(comp: *Compilation, parent: *Scope) !*Block {
238 const self = try comp.gpa().createOne(Block);238 const self = try comp.gpa().create(Block);
239 self.* = Block{239 self.* = Block{
240 .base = undefined,240 .base = undefined,
241 .incoming_values = undefined,241 .incoming_values = undefined,
...@@ -262,7 +262,7 @@ pub const Scope = struct {...@@ -262,7 +262,7 @@ pub const Scope = struct {
262 /// Creates a FnDef scope with 1 reference262 /// Creates a FnDef scope with 1 reference
263 /// Must set the fn_val later263 /// Must set the fn_val later
264 pub fn create(comp: *Compilation, parent: *Scope) !*FnDef {264 pub fn create(comp: *Compilation, parent: *Scope) !*FnDef {
265 const self = try comp.gpa().createOne(FnDef);265 const self = try comp.gpa().create(FnDef);
266 self.* = FnDef{266 self.* = FnDef{
267 .base = undefined,267 .base = undefined,
268 .fn_val = null,268 .fn_val = null,
...@@ -281,7 +281,7 @@ pub const Scope = struct {...@@ -281,7 +281,7 @@ pub const Scope = struct {
281281
282 /// Creates a CompTime scope with 1 reference282 /// Creates a CompTime scope with 1 reference
283 pub fn create(comp: *Compilation, parent: *Scope) !*CompTime {283 pub fn create(comp: *Compilation, parent: *Scope) !*CompTime {
284 const self = try comp.gpa().createOne(CompTime);284 const self = try comp.gpa().create(CompTime);
285 self.* = CompTime{ .base = undefined };285 self.* = CompTime{ .base = undefined };
286 self.base.init(Id.CompTime, parent);286 self.base.init(Id.CompTime, parent);
287 return self;287 return self;
...@@ -309,7 +309,7 @@ pub const Scope = struct {...@@ -309,7 +309,7 @@ pub const Scope = struct {
309 kind: Kind,309 kind: Kind,
310 defer_expr_scope: *DeferExpr,310 defer_expr_scope: *DeferExpr,
311 ) !*Defer {311 ) !*Defer {
312 const self = try comp.gpa().createOne(Defer);312 const self = try comp.gpa().create(Defer);
313 self.* = Defer{313 self.* = Defer{
314 .base = undefined,314 .base = undefined,
315 .defer_expr_scope = defer_expr_scope,315 .defer_expr_scope = defer_expr_scope,
...@@ -333,7 +333,7 @@ pub const Scope = struct {...@@ -333,7 +333,7 @@ pub const Scope = struct {
333333
334 /// Creates a DeferExpr scope with 1 reference334 /// Creates a DeferExpr scope with 1 reference
335 pub fn create(comp: *Compilation, parent: *Scope, expr_node: *ast.Node) !*DeferExpr {335 pub fn create(comp: *Compilation, parent: *Scope, expr_node: *ast.Node) !*DeferExpr {
336 const self = try comp.gpa().createOne(DeferExpr);336 const self = try comp.gpa().create(DeferExpr);
337 self.* = DeferExpr{337 self.* = DeferExpr{
338 .base = undefined,338 .base = undefined,
339 .expr_node = expr_node,339 .expr_node = expr_node,
...@@ -398,7 +398,7 @@ pub const Scope = struct {...@@ -398,7 +398,7 @@ pub const Scope = struct {
398 }398 }
399399
400 fn create(comp: *Compilation, parent: *Scope, name: []const u8, src_node: *ast.Node) !*Var {400 fn create(comp: *Compilation, parent: *Scope, name: []const u8, src_node: *ast.Node) !*Var {
401 const self = try comp.gpa().createOne(Var);401 const self = try comp.gpa().create(Var);
402 self.* = Var{402 self.* = Var{
403 .base = undefined,403 .base = undefined,
404 .name = name,404 .name = name,
src-self-hosted/type.zig+26-7
...@@ -44,6 +44,7 @@ pub const Type = struct {...@@ -44,6 +44,7 @@ pub const Type = struct {
44 Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),44 Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),
45 Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),45 Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),
46 Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(comp),46 Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(comp),
47 Id.Vector => @fieldParentPtr(Vector, "base", base).destroy(comp),
47 }48 }
48 }49 }
4950
...@@ -77,6 +78,7 @@ pub const Type = struct {...@@ -77,6 +78,7 @@ pub const Type = struct {
77 Id.ArgTuple => unreachable,78 Id.ArgTuple => unreachable,
78 Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context),79 Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context),
79 Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(allocator, llvm_context),80 Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(allocator, llvm_context),
81 Id.Vector => return @fieldParentPtr(Vector, "base", base).getLlvmType(allocator, llvm_context),
80 }82 }
81 }83 }
8284
...@@ -103,6 +105,7 @@ pub const Type = struct {...@@ -103,6 +105,7 @@ pub const Type = struct {
103 Id.Enum,105 Id.Enum,
104 Id.Fn,106 Id.Fn,
105 Id.Promise,107 Id.Promise,
108 Id.Vector,
106 => return false,109 => return false,
107110
108 Id.Struct => @panic("TODO"),111 Id.Struct => @panic("TODO"),
...@@ -135,6 +138,7 @@ pub const Type = struct {...@@ -135,6 +138,7 @@ pub const Type = struct {
135 Id.Float,138 Id.Float,
136 Id.Fn,139 Id.Fn,
137 Id.Promise,140 Id.Promise,
141 Id.Vector,
138 => return true,142 => return true,
139143
140 Id.Pointer => {144 Id.Pointer => {
...@@ -409,7 +413,7 @@ pub const Type = struct {...@@ -409,7 +413,7 @@ pub const Type = struct {
409 key.ref();413 key.ref();
410 errdefer key.deref(comp);414 errdefer key.deref(comp);
411415
412 const self = try comp.gpa().createOne(Fn);416 const self = try comp.gpa().create(Fn);
413 self.* = Fn{417 self.* = Fn{
414 .base = undefined,418 .base = undefined,
415 .key = key,419 .key = key,
...@@ -611,11 +615,12 @@ pub const Type = struct {...@@ -611,11 +615,12 @@ pub const Type = struct {
611 }615 }
612 }616 }
613617
614 const self = try comp.gpa().create(Int{618 const self = try comp.gpa().create(Int);
619 self.* = Int{
615 .base = undefined,620 .base = undefined,
616 .key = key,621 .key = key,
617 .garbage_node = undefined,622 .garbage_node = undefined,
618 });623 };
619 errdefer comp.gpa().destroy(self);624 errdefer comp.gpa().destroy(self);
620625
621 const u_or_i = "ui"[@boolToInt(key.is_signed)];626 const u_or_i = "ui"[@boolToInt(key.is_signed)];
...@@ -777,11 +782,12 @@ pub const Type = struct {...@@ -777,11 +782,12 @@ pub const Type = struct {
777 }782 }
778 }783 }
779784
780 const self = try comp.gpa().create(Pointer{785 const self = try comp.gpa().create(Pointer);
786 self.* = Pointer{
781 .base = undefined,787 .base = undefined,
782 .key = normal_key,788 .key = normal_key,
783 .garbage_node = undefined,789 .garbage_node = undefined,
784 });790 };
785 errdefer comp.gpa().destroy(self);791 errdefer comp.gpa().destroy(self);
786792
787 const size_str = switch (self.key.size) {793 const size_str = switch (self.key.size) {
...@@ -875,11 +881,12 @@ pub const Type = struct {...@@ -875,11 +881,12 @@ pub const Type = struct {
875 }881 }
876 }882 }
877883
878 const self = try comp.gpa().create(Array{884 const self = try comp.gpa().create(Array);
885 self.* = Array{
879 .base = undefined,886 .base = undefined,
880 .key = key,887 .key = key,
881 .garbage_node = undefined,888 .garbage_node = undefined,
882 });889 };
883 errdefer comp.gpa().destroy(self);890 errdefer comp.gpa().destroy(self);
884891
885 const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", key.len, key.elem_type.name);892 const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", key.len, key.elem_type.name);
...@@ -902,6 +909,18 @@ pub const Type = struct {...@@ -902,6 +909,18 @@ pub const Type = struct {
902 }909 }
903 };910 };
904911
912 pub const Vector = struct {
913 base: Type,
914
915 pub fn destroy(self: *Vector, comp: *Compilation) void {
916 comp.gpa().destroy(self);
917 }
918
919 pub fn getLlvmType(self: *Vector, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
920 @panic("TODO");
921 }
922 };
923
905 pub const ComptimeFloat = struct {924 pub const ComptimeFloat = struct {
906 base: Type,925 base: Type,
907926
src-self-hosted/value.zig+21-14
...@@ -135,14 +135,15 @@ pub const Value = struct {...@@ -135,14 +135,15 @@ pub const Value = struct {
135 symbol_name: Buffer,135 symbol_name: Buffer,
136136
137 pub fn create(comp: *Compilation, fn_type: *Type.Fn, symbol_name: Buffer) !*FnProto {137 pub fn create(comp: *Compilation, fn_type: *Type.Fn, symbol_name: Buffer) !*FnProto {
138 const self = try comp.gpa().create(FnProto{138 const self = try comp.gpa().create(FnProto);
139 self.* = FnProto{
139 .base = Value{140 .base = Value{
140 .id = Value.Id.FnProto,141 .id = Value.Id.FnProto,
141 .typ = &fn_type.base,142 .typ = &fn_type.base,
142 .ref_count = std.atomic.Int(usize).init(1),143 .ref_count = std.atomic.Int(usize).init(1),
143 },144 },
144 .symbol_name = symbol_name,145 .symbol_name = symbol_name,
145 });146 };
146 fn_type.base.base.ref();147 fn_type.base.base.ref();
147 return self;148 return self;
148 }149 }
...@@ -190,14 +191,16 @@ pub const Value = struct {...@@ -190,14 +191,16 @@ pub const Value = struct {
190 /// Creates a Fn value with 1 ref191 /// Creates a Fn value with 1 ref
191 /// Takes ownership of symbol_name192 /// Takes ownership of symbol_name
192 pub fn create(comp: *Compilation, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: Buffer) !*Fn {193 pub fn create(comp: *Compilation, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: Buffer) !*Fn {
193 const link_set_node = try comp.gpa().create(Compilation.FnLinkSet.Node{194 const link_set_node = try comp.gpa().create(Compilation.FnLinkSet.Node);
195 link_set_node.* = Compilation.FnLinkSet.Node{
194 .data = null,196 .data = null,
195 .next = undefined,197 .next = undefined,
196 .prev = undefined,198 .prev = undefined,
197 });199 };
198 errdefer comp.gpa().destroy(link_set_node);200 errdefer comp.gpa().destroy(link_set_node);
199201
200 const self = try comp.gpa().create(Fn{202 const self = try comp.gpa().create(Fn);
203 self.* = Fn{
201 .base = Value{204 .base = Value{
202 .id = Value.Id.Fn,205 .id = Value.Id.Fn,
203 .typ = &fn_type.base,206 .typ = &fn_type.base,
...@@ -209,7 +212,7 @@ pub const Value = struct {...@@ -209,7 +212,7 @@ pub const Value = struct {
209 .symbol_name = symbol_name,212 .symbol_name = symbol_name,
210 .containing_object = Buffer.initNull(comp.gpa()),213 .containing_object = Buffer.initNull(comp.gpa()),
211 .link_set_node = link_set_node,214 .link_set_node = link_set_node,
212 });215 };
213 fn_type.base.base.ref();216 fn_type.base.base.ref();
214 fndef_scope.fn_val = self;217 fndef_scope.fn_val = self;
215 fndef_scope.base.ref();218 fndef_scope.base.ref();
...@@ -353,7 +356,8 @@ pub const Value = struct {...@@ -353,7 +356,8 @@ pub const Value = struct {
353 var ptr_type_consumed = false;356 var ptr_type_consumed = false;
354 errdefer if (!ptr_type_consumed) ptr_type.base.base.deref(comp);357 errdefer if (!ptr_type_consumed) ptr_type.base.base.deref(comp);
355358
356 const self = try comp.gpa().create(Value.Ptr{359 const self = try comp.gpa().create(Value.Ptr);
360 self.* = Value.Ptr{
357 .base = Value{361 .base = Value{
358 .id = Value.Id.Ptr,362 .id = Value.Id.Ptr,
359 .typ = &ptr_type.base,363 .typ = &ptr_type.base,
...@@ -366,7 +370,7 @@ pub const Value = struct {...@@ -366,7 +370,7 @@ pub const Value = struct {
366 },370 },
367 },371 },
368 .mut = Mut.CompTimeConst,372 .mut = Mut.CompTimeConst,
369 });373 };
370 ptr_type_consumed = true;374 ptr_type_consumed = true;
371 errdefer comp.gpa().destroy(self);375 errdefer comp.gpa().destroy(self);
372376
...@@ -430,14 +434,15 @@ pub const Value = struct {...@@ -430,14 +434,15 @@ pub const Value = struct {
430 }) catch unreachable);434 }) catch unreachable);
431 errdefer array_type.base.base.deref(comp);435 errdefer array_type.base.base.deref(comp);
432436
433 const self = try comp.gpa().create(Value.Array{437 const self = try comp.gpa().create(Value.Array);
438 self.* = Value.Array{
434 .base = Value{439 .base = Value{
435 .id = Value.Id.Array,440 .id = Value.Id.Array,
436 .typ = &array_type.base,441 .typ = &array_type.base,
437 .ref_count = std.atomic.Int(usize).init(1),442 .ref_count = std.atomic.Int(usize).init(1),
438 },443 },
439 .special = Special{ .OwnedBuffer = buffer },444 .special = Special{ .OwnedBuffer = buffer },
440 });445 };
441 errdefer comp.gpa().destroy(self);446 errdefer comp.gpa().destroy(self);
442447
443 return self;448 return self;
...@@ -509,14 +514,15 @@ pub const Value = struct {...@@ -509,14 +514,15 @@ pub const Value = struct {
509 big_int: std.math.big.Int,514 big_int: std.math.big.Int,
510515
511 pub fn createFromString(comp: *Compilation, typ: *Type, base: u8, value: []const u8) !*Int {516 pub fn createFromString(comp: *Compilation, typ: *Type, base: u8, value: []const u8) !*Int {
512 const self = try comp.gpa().create(Value.Int{517 const self = try comp.gpa().create(Value.Int);
518 self.* = Value.Int{
513 .base = Value{519 .base = Value{
514 .id = Value.Id.Int,520 .id = Value.Id.Int,
515 .typ = typ,521 .typ = typ,
516 .ref_count = std.atomic.Int(usize).init(1),522 .ref_count = std.atomic.Int(usize).init(1),
517 },523 },
518 .big_int = undefined,524 .big_int = undefined,
519 });525 };
520 typ.base.ref();526 typ.base.ref();
521 errdefer comp.gpa().destroy(self);527 errdefer comp.gpa().destroy(self);
522528
...@@ -557,14 +563,15 @@ pub const Value = struct {...@@ -557,14 +563,15 @@ pub const Value = struct {
557 old.base.typ.base.ref();563 old.base.typ.base.ref();
558 errdefer old.base.typ.base.deref(comp);564 errdefer old.base.typ.base.deref(comp);
559565
560 const new = try comp.gpa().create(Value.Int{566 const new = try comp.gpa().create(Value.Int);
567 new.* = Value.Int{
561 .base = Value{568 .base = Value{
562 .id = Value.Id.Int,569 .id = Value.Id.Int,
563 .typ = old.base.typ,570 .typ = old.base.typ,
564 .ref_count = std.atomic.Int(usize).init(1),571 .ref_count = std.atomic.Int(usize).init(1),
565 },572 },
566 .big_int = undefined,573 .big_int = undefined,
567 });574 };
568 errdefer comp.gpa().destroy(new);575 errdefer comp.gpa().destroy(new);
569576
570 new.big_int = try old.big_int.clone();577 new.big_int = try old.big_int.clone();
src/all_types.hpp+152-50
...@@ -56,9 +56,6 @@ struct IrExecutable {...@@ -56,9 +56,6 @@ struct IrExecutable {
56 size_t next_debug_id;56 size_t next_debug_id;
57 size_t *backward_branch_count;57 size_t *backward_branch_count;
58 size_t backward_branch_quota;58 size_t backward_branch_quota;
59 bool invalid;
60 bool is_inline;
61 bool is_generic_instantiation;
62 ZigFn *fn_entry;59 ZigFn *fn_entry;
63 Buf *c_import_buf;60 Buf *c_import_buf;
64 AstNode *source_node;61 AstNode *source_node;
...@@ -78,6 +75,10 @@ struct IrExecutable {...@@ -78,6 +75,10 @@ struct IrExecutable {
78 IrBasicBlock *coro_suspend_block;75 IrBasicBlock *coro_suspend_block;
79 IrBasicBlock *coro_final_cleanup_block;76 IrBasicBlock *coro_final_cleanup_block;
80 ZigVar *coro_allocator_var;77 ZigVar *coro_allocator_var;
78
79 bool invalid;
80 bool is_inline;
81 bool is_generic_instantiation;
81};82};
8283
83enum OutType {84enum OutType {
...@@ -90,6 +91,9 @@ enum OutType {...@@ -90,6 +91,9 @@ enum OutType {
90enum ConstParentId {91enum ConstParentId {
91 ConstParentIdNone,92 ConstParentIdNone,
92 ConstParentIdStruct,93 ConstParentIdStruct,
94 ConstParentIdErrUnionCode,
95 ConstParentIdErrUnionPayload,
96 ConstParentIdOptionalPayload,
93 ConstParentIdArray,97 ConstParentIdArray,
94 ConstParentIdUnion,98 ConstParentIdUnion,
95 ConstParentIdScalar,99 ConstParentIdScalar,
...@@ -107,6 +111,15 @@ struct ConstParent {...@@ -107,6 +111,15 @@ struct ConstParent {
107 ConstExprValue *struct_val;111 ConstExprValue *struct_val;
108 size_t field_index;112 size_t field_index;
109 } p_struct;113 } p_struct;
114 struct {
115 ConstExprValue *err_union_val;
116 } p_err_union_code;
117 struct {
118 ConstExprValue *err_union_val;
119 } p_err_union_payload;
120 struct {
121 ConstExprValue *optional_val;
122 } p_optional_payload;
110 struct {123 struct {
111 ConstExprValue *union_val;124 ConstExprValue *union_val;
112 } p_union;125 } p_union;
...@@ -118,13 +131,11 @@ struct ConstParent {...@@ -118,13 +131,11 @@ struct ConstParent {
118131
119struct ConstStructValue {132struct ConstStructValue {
120 ConstExprValue *fields;133 ConstExprValue *fields;
121 ConstParent parent;
122};134};
123135
124struct ConstUnionValue {136struct ConstUnionValue {
125 BigInt tag;137 BigInt tag;
126 ConstExprValue *payload;138 ConstExprValue *payload;
127 ConstParent parent;
128};139};
129140
130enum ConstArraySpecial {141enum ConstArraySpecial {
...@@ -138,7 +149,6 @@ struct ConstArrayValue {...@@ -138,7 +149,6 @@ struct ConstArrayValue {
138 union {149 union {
139 struct {150 struct {
140 ConstExprValue *elements;151 ConstExprValue *elements;
141 ConstParent parent;
142 } s_none;152 } s_none;
143 Buf *s_buf;153 Buf *s_buf;
144 } data;154 } data;
...@@ -153,19 +163,29 @@ enum ConstPtrSpecial {...@@ -153,19 +163,29 @@ enum ConstPtrSpecial {
153 ConstPtrSpecialBaseArray,163 ConstPtrSpecialBaseArray,
154 // The pointer points to a field in an underlying struct.164 // The pointer points to a field in an underlying struct.
155 ConstPtrSpecialBaseStruct,165 ConstPtrSpecialBaseStruct,
166 // The pointer points to the error set field of an error union
167 ConstPtrSpecialBaseErrorUnionCode,
168 // The pointer points to the payload field of an error union
169 ConstPtrSpecialBaseErrorUnionPayload,
170 // The pointer points to the payload field of an optional
171 ConstPtrSpecialBaseOptionalPayload,
156 // This means that we did a compile-time pointer reinterpret and we cannot172 // This means that we did a compile-time pointer reinterpret and we cannot
157 // understand the value of pointee at compile time. However, we will still173 // understand the value of pointee at compile time. However, we will still
158 // emit a binary with a compile time known address.174 // emit a binary with a compile time known address.
159 // In this case index is the numeric address value.175 // In this case index is the numeric address value.
160 // We also use this for null pointer. We need the data layout for ConstCastOnly == true
161 // types to be the same, so all optionals of pointer types use x_ptr
162 // instead of x_optional
163 ConstPtrSpecialHardCodedAddr,176 ConstPtrSpecialHardCodedAddr,
164 // This means that the pointer represents memory of assigning to _.177 // This means that the pointer represents memory of assigning to _.
165 // That is, storing discards the data, and loading is invalid.178 // That is, storing discards the data, and loading is invalid.
166 ConstPtrSpecialDiscard,179 ConstPtrSpecialDiscard,
167 // This is actually a function.180 // This is actually a function.
168 ConstPtrSpecialFunction,181 ConstPtrSpecialFunction,
182 // This means the pointer is null. This is only allowed when the type is ?*T.
183 // We use this instead of ConstPtrSpecialHardCodedAddr because often we check
184 // for that value to avoid doing comptime work.
185 // We need the data layout for ConstCastOnly == true
186 // types to be the same, so all optionals of pointer types use x_ptr
187 // instead of x_optional.
188 ConstPtrSpecialNull,
169};189};
170190
171enum ConstPtrMut {191enum ConstPtrMut {
...@@ -199,6 +219,15 @@ struct ConstPtrValue {...@@ -199,6 +219,15 @@ struct ConstPtrValue {
199 ConstExprValue *struct_val;219 ConstExprValue *struct_val;
200 size_t field_index;220 size_t field_index;
201 } base_struct;221 } base_struct;
222 struct {
223 ConstExprValue *err_union_val;
224 } base_err_union_code;
225 struct {
226 ConstExprValue *err_union_val;
227 } base_err_union_payload;
228 struct {
229 ConstExprValue *optional_val;
230 } base_optional_payload;
202 struct {231 struct {
203 uint64_t addr;232 uint64_t addr;
204 } hard_coded_addr;233 } hard_coded_addr;
...@@ -209,7 +238,7 @@ struct ConstPtrValue {...@@ -209,7 +238,7 @@ struct ConstPtrValue {
209};238};
210239
211struct ConstErrValue {240struct ConstErrValue {
212 ErrorTableEntry *err;241 ConstExprValue *error_set;
213 ConstExprValue *payload;242 ConstExprValue *payload;
214};243};
215244
...@@ -265,6 +294,7 @@ struct ConstGlobalRefs {...@@ -265,6 +294,7 @@ struct ConstGlobalRefs {
265struct ConstExprValue {294struct ConstExprValue {
266 ZigType *type;295 ZigType *type;
267 ConstValSpecial special;296 ConstValSpecial special;
297 ConstParent parent;
268 ConstGlobalRefs *global_refs;298 ConstGlobalRefs *global_refs;
269299
270 union {300 union {
...@@ -433,7 +463,7 @@ enum NodeType {...@@ -433,7 +463,7 @@ enum NodeType {
433 NodeTypeArrayType,463 NodeTypeArrayType,
434 NodeTypeErrorType,464 NodeTypeErrorType,
435 NodeTypeIfErrorExpr,465 NodeTypeIfErrorExpr,
436 NodeTypeTestExpr,466 NodeTypeIfOptional,
437 NodeTypeErrorSetDecl,467 NodeTypeErrorSetDecl,
438 NodeTypeCancel,468 NodeTypeCancel,
439 NodeTypeResume,469 NodeTypeResume,
...@@ -677,7 +707,7 @@ struct AstNodeUse {...@@ -677,7 +707,7 @@ struct AstNodeUse {
677 AstNode *expr;707 AstNode *expr;
678708
679 TldResolution resolution;709 TldResolution resolution;
680 IrInstruction *value;710 ConstExprValue *value;
681};711};
682712
683struct AstNodeIfBoolExpr {713struct AstNodeIfBoolExpr {
...@@ -1180,6 +1210,12 @@ struct ZigTypePromise {...@@ -1180,6 +1210,12 @@ struct ZigTypePromise {
1180 ZigType *result_type;1210 ZigType *result_type;
1181};1211};
11821212
1213struct ZigTypeVector {
1214 // The type must be a pointer, integer, or float
1215 ZigType *elem_type;
1216 uint32_t len;
1217};
1218
1183enum ZigTypeId {1219enum ZigTypeId {
1184 ZigTypeIdInvalid,1220 ZigTypeIdInvalid,
1185 ZigTypeIdMetaType,1221 ZigTypeIdMetaType,
...@@ -1206,6 +1242,7 @@ enum ZigTypeId {...@@ -1206,6 +1242,7 @@ enum ZigTypeId {
1206 ZigTypeIdArgTuple,1242 ZigTypeIdArgTuple,
1207 ZigTypeIdOpaque,1243 ZigTypeIdOpaque,
1208 ZigTypeIdPromise,1244 ZigTypeIdPromise,
1245 ZigTypeIdVector,
1209};1246};
12101247
1211struct ZigType {1248struct ZigType {
...@@ -1232,6 +1269,7 @@ struct ZigType {...@@ -1232,6 +1269,7 @@ struct ZigType {
1232 ZigTypeFn fn;1269 ZigTypeFn fn;
1233 ZigTypeBoundFn bound_fn;1270 ZigTypeBoundFn bound_fn;
1234 ZigTypePromise promise;1271 ZigTypePromise promise;
1272 ZigTypeVector vector;
1235 } data;1273 } data;
12361274
1237 // use these fields to make sure we don't duplicate type table entries for the same type1275 // use these fields to make sure we don't duplicate type table entries for the same type
...@@ -1385,6 +1423,7 @@ enum BuiltinFnId {...@@ -1385,6 +1423,7 @@ enum BuiltinFnId {
1385 BuiltinFnIdEnumToInt,1423 BuiltinFnIdEnumToInt,
1386 BuiltinFnIdIntToEnum,1424 BuiltinFnIdIntToEnum,
1387 BuiltinFnIdIntType,1425 BuiltinFnIdIntType,
1426 BuiltinFnIdVectorType,
1388 BuiltinFnIdSetCold,1427 BuiltinFnIdSetCold,
1389 BuiltinFnIdSetRuntimeSafety,1428 BuiltinFnIdSetRuntimeSafety,
1390 BuiltinFnIdSetFloatMode,1429 BuiltinFnIdSetFloatMode,
...@@ -1475,6 +1514,10 @@ struct TypeId {...@@ -1475,6 +1514,10 @@ struct TypeId {
1475 ZigType *err_set_type;1514 ZigType *err_set_type;
1476 ZigType *payload_type;1515 ZigType *payload_type;
1477 } error_union;1516 } error_union;
1517 struct {
1518 ZigType *elem_type;
1519 uint32_t len;
1520 } vector;
1478 } data;1521 } data;
1479};1522};
14801523
...@@ -1610,7 +1653,7 @@ struct CodeGen {...@@ -1610,7 +1653,7 @@ struct CodeGen {
1610 HashMap<FnTypeId *, ZigType *, fn_type_id_hash, fn_type_id_eql> fn_type_table;1653 HashMap<FnTypeId *, ZigType *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
1611 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;1654 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
1612 HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;1655 HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;
1613 HashMap<Scope *, IrInstruction *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;1656 HashMap<Scope *, ConstExprValue *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;
1614 HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;1657 HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;
1615 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names;1658 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names;
1616 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;1659 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
...@@ -1760,6 +1803,7 @@ struct CodeGen {...@@ -1760,6 +1803,7 @@ struct CodeGen {
1760 bool is_static;1803 bool is_static;
1761 bool strip_debug_symbols;1804 bool strip_debug_symbols;
1762 bool is_test_build;1805 bool is_test_build;
1806 bool is_single_threaded;
1763 bool is_native_target;1807 bool is_native_target;
1764 bool linker_rdynamic;1808 bool linker_rdynamic;
1765 bool no_rosegment_workaround;1809 bool no_rosegment_workaround;
...@@ -1802,10 +1846,9 @@ enum VarLinkage {...@@ -1802,10 +1846,9 @@ enum VarLinkage {
18021846
1803struct ZigVar {1847struct ZigVar {
1804 Buf name;1848 Buf name;
1805 ConstExprValue *value;1849 ConstExprValue *const_value;
1850 ZigType *var_type;
1806 LLVMValueRef value_ref;1851 LLVMValueRef value_ref;
1807 bool src_is_const;
1808 bool gen_is_const;
1809 IrInstruction *is_comptime;1852 IrInstruction *is_comptime;
1810 // which node is the declaration of the variable1853 // which node is the declaration of the variable
1811 AstNode *decl_node;1854 AstNode *decl_node;
...@@ -1815,17 +1858,21 @@ struct ZigVar {...@@ -1815,17 +1858,21 @@ struct ZigVar {
1815 Scope *parent_scope;1858 Scope *parent_scope;
1816 Scope *child_scope;1859 Scope *child_scope;
1817 LLVMValueRef param_value_ref;1860 LLVMValueRef param_value_ref;
1818 bool shadowable;
1819 size_t mem_slot_index;1861 size_t mem_slot_index;
1820 IrExecutable *owner_exec;1862 IrExecutable *owner_exec;
1821 size_t ref_count;1863 size_t ref_count;
1822 VarLinkage linkage;
1823 uint32_t align_bytes;
18241864
1825 // In an inline loop, multiple variables may be created,1865 // In an inline loop, multiple variables may be created,
1826 // In this case, a reference to a variable should follow1866 // In this case, a reference to a variable should follow
1827 // this pointer to the redefined variable.1867 // this pointer to the redefined variable.
1828 ZigVar *next_var;1868 ZigVar *next_var;
1869
1870 uint32_t align_bytes;
1871 VarLinkage linkage;
1872
1873 bool shadowable;
1874 bool src_is_const;
1875 bool gen_is_const;
1829};1876};
18301877
1831struct ErrorTableEntry {1878struct ErrorTableEntry {
...@@ -1891,10 +1938,11 @@ struct ScopeBlock {...@@ -1891,10 +1938,11 @@ struct ScopeBlock {
1891 ZigList<IrInstruction *> *incoming_values;1938 ZigList<IrInstruction *> *incoming_values;
1892 ZigList<IrBasicBlock *> *incoming_blocks;1939 ZigList<IrBasicBlock *> *incoming_blocks;
18931940
1894 bool safety_off;
1895 AstNode *safety_set_node;1941 AstNode *safety_set_node;
1896 bool fast_math_on;
1897 AstNode *fast_math_set_node;1942 AstNode *fast_math_set_node;
1943
1944 bool safety_off;
1945 bool fast_math_on;
1898};1946};
18991947
1900// This scope is created from every defer expression.1948// This scope is created from every defer expression.
...@@ -2030,8 +2078,19 @@ struct IrBasicBlock {...@@ -2030,8 +2078,19 @@ struct IrBasicBlock {
2030 IrInstruction *must_be_comptime_source_instr;2078 IrInstruction *must_be_comptime_source_instr;
2031};2079};
20322080
2081// These instructions are in transition to having "pass 1" instructions
2082// and "pass 2" instructions. The pass 1 instructions are suffixed with Src
2083// and pass 2 are suffixed with Gen.
2084// Once all instructions are separated in this way, they'll have different
2085// base types for better type safety.
2086// Src instructions are generated by ir_gen_* functions in ir.cpp from AST.
2087// ir_analyze_* functions consume Src instructions and produce Gen instructions.
2088// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR.
2089// Src instructions do not have type information; Gen instructions do.
2033enum IrInstructionId {2090enum IrInstructionId {
2034 IrInstructionIdInvalid,2091 IrInstructionIdInvalid,
2092 IrInstructionIdDeclVarSrc,
2093 IrInstructionIdDeclVarGen,
2035 IrInstructionIdBr,2094 IrInstructionIdBr,
2036 IrInstructionIdCondBr,2095 IrInstructionIdCondBr,
2037 IrInstructionIdSwitchBr,2096 IrInstructionIdSwitchBr,
...@@ -2040,7 +2099,6 @@ enum IrInstructionId {...@@ -2040,7 +2099,6 @@ enum IrInstructionId {
2040 IrInstructionIdPhi,2099 IrInstructionIdPhi,
2041 IrInstructionIdUnOp,2100 IrInstructionIdUnOp,
2042 IrInstructionIdBinOp,2101 IrInstructionIdBinOp,
2043 IrInstructionIdDeclVar,
2044 IrInstructionIdLoadPtr,2102 IrInstructionIdLoadPtr,
2045 IrInstructionIdStorePtr,2103 IrInstructionIdStorePtr,
2046 IrInstructionIdFieldPtr,2104 IrInstructionIdFieldPtr,
...@@ -2069,7 +2127,7 @@ enum IrInstructionId {...@@ -2069,7 +2127,7 @@ enum IrInstructionId {
2069 IrInstructionIdAsm,2127 IrInstructionIdAsm,
2070 IrInstructionIdSizeOf,2128 IrInstructionIdSizeOf,
2071 IrInstructionIdTestNonNull,2129 IrInstructionIdTestNonNull,
2072 IrInstructionIdUnwrapOptional,2130 IrInstructionIdOptionalUnwrapPtr,
2073 IrInstructionIdOptionalWrap,2131 IrInstructionIdOptionalWrap,
2074 IrInstructionIdUnionTag,2132 IrInstructionIdUnionTag,
2075 IrInstructionIdClz,2133 IrInstructionIdClz,
...@@ -2085,7 +2143,8 @@ enum IrInstructionId {...@@ -2085,7 +2143,8 @@ enum IrInstructionId {
2085 IrInstructionIdCompileLog,2143 IrInstructionIdCompileLog,
2086 IrInstructionIdErrName,2144 IrInstructionIdErrName,
2087 IrInstructionIdEmbedFile,2145 IrInstructionIdEmbedFile,
2088 IrInstructionIdCmpxchg,2146 IrInstructionIdCmpxchgSrc,
2147 IrInstructionIdCmpxchgGen,
2089 IrInstructionIdFence,2148 IrInstructionIdFence,
2090 IrInstructionIdTruncate,2149 IrInstructionIdTruncate,
2091 IrInstructionIdIntCast,2150 IrInstructionIdIntCast,
...@@ -2094,6 +2153,7 @@ enum IrInstructionId {...@@ -2094,6 +2153,7 @@ enum IrInstructionId {
2094 IrInstructionIdFloatToInt,2153 IrInstructionIdFloatToInt,
2095 IrInstructionIdBoolToInt,2154 IrInstructionIdBoolToInt,
2096 IrInstructionIdIntType,2155 IrInstructionIdIntType,
2156 IrInstructionIdVectorType,
2097 IrInstructionIdBoolNot,2157 IrInstructionIdBoolNot,
2098 IrInstructionIdMemset,2158 IrInstructionIdMemset,
2099 IrInstructionIdMemcpy,2159 IrInstructionIdMemcpy,
...@@ -2114,7 +2174,8 @@ enum IrInstructionId {...@@ -2114,7 +2174,8 @@ enum IrInstructionId {
2114 IrInstructionIdErrWrapPayload,2174 IrInstructionIdErrWrapPayload,
2115 IrInstructionIdFnProto,2175 IrInstructionIdFnProto,
2116 IrInstructionIdTestComptime,2176 IrInstructionIdTestComptime,
2117 IrInstructionIdPtrCast,2177 IrInstructionIdPtrCastSrc,
2178 IrInstructionIdPtrCastGen,
2118 IrInstructionIdBitCast,2179 IrInstructionIdBitCast,
2119 IrInstructionIdWidenOrShorten,2180 IrInstructionIdWidenOrShorten,
2120 IrInstructionIdIntToPtr,2181 IrInstructionIdIntToPtr,
...@@ -2173,6 +2234,8 @@ enum IrInstructionId {...@@ -2173,6 +2234,8 @@ enum IrInstructionId {
2173 IrInstructionIdToBytes,2234 IrInstructionIdToBytes,
2174 IrInstructionIdFromBytes,2235 IrInstructionIdFromBytes,
2175 IrInstructionIdCheckRuntimeScope,2236 IrInstructionIdCheckRuntimeScope,
2237 IrInstructionIdVectorToArray,
2238 IrInstructionIdArrayToVector,
2176};2239};
21772240
2178struct IrInstruction {2241struct IrInstruction {
...@@ -2194,6 +2257,22 @@ struct IrInstruction {...@@ -2194,6 +2257,22 @@ struct IrInstruction {
2194 bool is_gen;2257 bool is_gen;
2195};2258};
21962259
2260struct IrInstructionDeclVarSrc {
2261 IrInstruction base;
2262
2263 ZigVar *var;
2264 IrInstruction *var_type;
2265 IrInstruction *align_value;
2266 IrInstruction *init_value;
2267};
2268
2269struct IrInstructionDeclVarGen {
2270 IrInstruction base;
2271
2272 ZigVar *var;
2273 IrInstruction *init_value;
2274};
2275
2197struct IrInstructionCondBr {2276struct IrInstructionCondBr {
2198 IrInstruction base;2277 IrInstruction base;
21992278
...@@ -2302,20 +2381,11 @@ struct IrInstructionBinOp {...@@ -2302,20 +2381,11 @@ struct IrInstructionBinOp {
2302 IrInstruction base;2381 IrInstruction base;
23032382
2304 IrInstruction *op1;2383 IrInstruction *op1;
2305 IrBinOp op_id;
2306 IrInstruction *op2;2384 IrInstruction *op2;
2385 IrBinOp op_id;
2307 bool safety_check_on;2386 bool safety_check_on;
2308};2387};
23092388
2310struct IrInstructionDeclVar {
2311 IrInstruction base;
2312
2313 ZigVar *var;
2314 IrInstruction *var_type;
2315 IrInstruction *align_value;
2316 IrInstruction *init_value;
2317};
2318
2319struct IrInstructionLoadPtr {2389struct IrInstructionLoadPtr {
2320 IrInstruction base;2390 IrInstruction base;
23212391
...@@ -2335,7 +2405,6 @@ struct IrInstructionFieldPtr {...@@ -2335,7 +2405,6 @@ struct IrInstructionFieldPtr {
2335 IrInstruction *container_ptr;2405 IrInstruction *container_ptr;
2336 Buf *field_name_buffer;2406 Buf *field_name_buffer;
2337 IrInstruction *field_name_expr;2407 IrInstruction *field_name_expr;
2338 bool is_const;
2339};2408};
23402409
2341struct IrInstructionStructFieldPtr {2410struct IrInstructionStructFieldPtr {
...@@ -2378,13 +2447,13 @@ struct IrInstructionCall {...@@ -2378,13 +2447,13 @@ struct IrInstructionCall {
2378 ZigFn *fn_entry;2447 ZigFn *fn_entry;
2379 size_t arg_count;2448 size_t arg_count;
2380 IrInstruction **args;2449 IrInstruction **args;
2381 bool is_comptime;
2382 LLVMValueRef tmp_ptr;2450 LLVMValueRef tmp_ptr;
2383 FnInline fn_inline;
2384 bool is_async;
23852451
2386 IrInstruction *async_allocator;2452 IrInstruction *async_allocator;
2387 IrInstruction *new_stack;2453 IrInstruction *new_stack;
2454 FnInline fn_inline;
2455 bool is_async;
2456 bool is_comptime;
2388};2457};
23892458
2390struct IrInstructionConst {2459struct IrInstructionConst {
...@@ -2527,9 +2596,9 @@ struct IrInstructionSliceType {...@@ -2527,9 +2596,9 @@ struct IrInstructionSliceType {
2527 IrInstruction base;2596 IrInstruction base;
25282597
2529 IrInstruction *align_value;2598 IrInstruction *align_value;
2599 IrInstruction *child_type;
2530 bool is_const;2600 bool is_const;
2531 bool is_volatile;2601 bool is_volatile;
2532 IrInstruction *child_type;
2533};2602};
25342603
2535struct IrInstructionAsm {2604struct IrInstructionAsm {
...@@ -2557,10 +2626,12 @@ struct IrInstructionTestNonNull {...@@ -2557,10 +2626,12 @@ struct IrInstructionTestNonNull {
2557 IrInstruction *value;2626 IrInstruction *value;
2558};2627};
25592628
2560struct IrInstructionUnwrapOptional {2629// Takes a pointer to an optional value, returns a pointer
2630// to the payload.
2631struct IrInstructionOptionalUnwrapPtr {
2561 IrInstruction base;2632 IrInstruction base;
25622633
2563 IrInstruction *value;2634 IrInstruction *base_ptr;
2564 bool safety_check_on;2635 bool safety_check_on;
2565};2636};
25662637
...@@ -2651,7 +2722,7 @@ struct IrInstructionEmbedFile {...@@ -2651,7 +2722,7 @@ struct IrInstructionEmbedFile {
2651 IrInstruction *name;2722 IrInstruction *name;
2652};2723};
26532724
2654struct IrInstructionCmpxchg {2725struct IrInstructionCmpxchgSrc {
2655 IrInstruction base;2726 IrInstruction base;
26562727
2657 IrInstruction *type_value;2728 IrInstruction *type_value;
...@@ -2661,14 +2732,19 @@ struct IrInstructionCmpxchg {...@@ -2661,14 +2732,19 @@ struct IrInstructionCmpxchg {
2661 IrInstruction *success_order_value;2732 IrInstruction *success_order_value;
2662 IrInstruction *failure_order_value;2733 IrInstruction *failure_order_value;
26632734
2664 // if this instruction gets to runtime then we know these values:
2665 ZigType *type;
2666 AtomicOrder success_order;
2667 AtomicOrder failure_order;
2668
2669 bool is_weak;2735 bool is_weak;
2736};
26702737
2738struct IrInstructionCmpxchgGen {
2739 IrInstruction base;
2740
2741 IrInstruction *ptr;
2742 IrInstruction *cmp_value;
2743 IrInstruction *new_value;
2671 LLVMValueRef tmp_ptr;2744 LLVMValueRef tmp_ptr;
2745 AtomicOrder success_order;
2746 AtomicOrder failure_order;
2747 bool is_weak;
2672};2748};
26732749
2674struct IrInstructionFence {2750struct IrInstructionFence {
...@@ -2748,6 +2824,13 @@ struct IrInstructionIntType {...@@ -2748,6 +2824,13 @@ struct IrInstructionIntType {
2748 IrInstruction *bit_count;2824 IrInstruction *bit_count;
2749};2825};
27502826
2827struct IrInstructionVectorType {
2828 IrInstruction base;
2829
2830 IrInstruction *len;
2831 IrInstruction *elem_type;
2832};
2833
2751struct IrInstructionBoolNot {2834struct IrInstructionBoolNot {
2752 IrInstruction base;2835 IrInstruction base;
27532836
...@@ -2851,7 +2934,7 @@ struct IrInstructionTestErr {...@@ -2851,7 +2934,7 @@ struct IrInstructionTestErr {
2851struct IrInstructionUnwrapErrCode {2934struct IrInstructionUnwrapErrCode {
2852 IrInstruction base;2935 IrInstruction base;
28532936
2854 IrInstruction *value;2937 IrInstruction *err_union;
2855};2938};
28562939
2857struct IrInstructionUnwrapErrPayload {2940struct IrInstructionUnwrapErrPayload {
...@@ -2899,13 +2982,19 @@ struct IrInstructionTestComptime {...@@ -2899,13 +2982,19 @@ struct IrInstructionTestComptime {
2899 IrInstruction *value;2982 IrInstruction *value;
2900};2983};
29012984
2902struct IrInstructionPtrCast {2985struct IrInstructionPtrCastSrc {
2903 IrInstruction base;2986 IrInstruction base;
29042987
2905 IrInstruction *dest_type;2988 IrInstruction *dest_type;
2906 IrInstruction *ptr;2989 IrInstruction *ptr;
2907};2990};
29082991
2992struct IrInstructionPtrCastGen {
2993 IrInstruction base;
2994
2995 IrInstruction *ptr;
2996};
2997
2909struct IrInstructionBitCast {2998struct IrInstructionBitCast {
2910 IrInstruction base;2999 IrInstruction base;
29113000
...@@ -3276,6 +3365,19 @@ struct IrInstructionBitReverse {...@@ -3276,6 +3365,19 @@ struct IrInstructionBitReverse {
3276 IrInstruction *op;3365 IrInstruction *op;
3277};3366};
32783367
3368struct IrInstructionArrayToVector {
3369 IrInstruction base;
3370
3371 IrInstruction *array;
3372};
3373
3374struct IrInstructionVectorToArray {
3375 IrInstruction base;
3376
3377 IrInstruction *vector;
3378 LLVMValueRef tmp_ptr;
3379};
3380
3279static const size_t slice_ptr_index = 0;3381static const size_t slice_ptr_index = 0;
3280static const size_t slice_len_index = 1;3382static const size_t slice_len_index = 1;
32813383
src/analyze.cpp+361-151
...@@ -250,6 +250,7 @@ AstNode *type_decl_node(ZigType *type_entry) {...@@ -250,6 +250,7 @@ AstNode *type_decl_node(ZigType *type_entry) {
250 case ZigTypeIdBoundFn:250 case ZigTypeIdBoundFn:
251 case ZigTypeIdArgTuple:251 case ZigTypeIdArgTuple:
252 case ZigTypeIdPromise:252 case ZigTypeIdPromise:
253 case ZigTypeIdVector:
253 return nullptr;254 return nullptr;
254 }255 }
255 zig_unreachable();256 zig_unreachable();
...@@ -311,6 +312,7 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {...@@ -311,6 +312,7 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
311 case ZigTypeIdBoundFn:312 case ZigTypeIdBoundFn:
312 case ZigTypeIdArgTuple:313 case ZigTypeIdArgTuple:
313 case ZigTypeIdPromise:314 case ZigTypeIdPromise:
315 case ZigTypeIdVector:
314 return true;316 return true;
315 }317 }
316 zig_unreachable();318 zig_unreachable();
...@@ -570,7 +572,7 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {...@@ -570,7 +572,7 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
570 if (child_type->zero_bits) {572 if (child_type->zero_bits) {
571 entry->type_ref = LLVMInt1Type();573 entry->type_ref = LLVMInt1Type();
572 entry->di_type = g->builtin_types.entry_bool->di_type;574 entry->di_type = g->builtin_types.entry_bool->di_type;
573 } else if (type_is_codegen_pointer(child_type)) {575 } else if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) {
574 assert(child_type->di_type);576 assert(child_type->di_type);
575 // this is an optimization but also is necessary for calling C577 // this is an optimization but also is necessary for calling C
576 // functions where all pointers are maybe pointers578 // functions where all pointers are maybe pointers
...@@ -1055,11 +1057,7 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {...@@ -1055,11 +1057,7 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
1055 }1057 }
1056 if (g->zig_target.arch.arch == ZigLLVM_x86_64) {1058 if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
1057 X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);1059 X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);
1058 if (abi_class == X64CABIClass_MEMORY) {1060 return abi_class == X64CABIClass_MEMORY;
1059 return true;
1060 }
1061 zig_panic("TODO implement C ABI for x86_64 return types. type '%s'\nSee https://github.com/ziglang/zig/issues/1481",
1062 buf_ptr(&fn_type_id->return_type->name));
1063 } else if (target_is_arm(&g->zig_target)) {1061 } else if (target_is_arm(&g->zig_target)) {
1064 return type_size(g, fn_type_id->return_type) > 16;1062 return type_size(g, fn_type_id->return_type) > 16;
1065 }1063 }
...@@ -1278,7 +1276,9 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind...@@ -1278,7 +1276,9 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
1278 return entry;1276 return entry;
1279}1277}
12801278
1281static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, Buf *type_name) {1279static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry,
1280 Buf *type_name)
1281{
1282 size_t backward_branch_count = 0;1282 size_t backward_branch_count = 0;
1283 return ir_eval_const_value(g, scope, node, type_entry,1283 return ir_eval_const_value(g, scope, node, type_entry,
1284 &backward_branch_count, default_backward_branch_quota,1284 &backward_branch_count, default_backward_branch_quota,
...@@ -1286,12 +1286,12 @@ static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *nod...@@ -1286,12 +1286,12 @@ static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *nod
1286}1286}
12871287
1288ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {1288ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
1289 IrInstruction *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);1289 ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
1290 if (result->value.type->id == ZigTypeIdInvalid)1290 if (type_is_invalid(result->type))
1291 return g->builtin_types.entry_invalid;1291 return g->builtin_types.entry_invalid;
12921292
1293 assert(result->value.special != ConstValSpecialRuntime);1293 assert(result->special != ConstValSpecialRuntime);
1294 return result->value.data.x_type;1294 return result->data.x_type;
1295}1295}
12961296
1297ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {1297ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
...@@ -1342,11 +1342,11 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou...@@ -1342,11 +1342,11 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou
1342}1342}
13431343
1344static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) {1344static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_t *result) {
1345 IrInstruction *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);1345 ConstExprValue *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);
1346 if (type_is_invalid(align_result->value.type))1346 if (type_is_invalid(align_result->type))
1347 return false;1347 return false;
13481348
1349 uint32_t align_bytes = bigint_as_unsigned(&align_result->value.data.x_bigint);1349 uint32_t align_bytes = bigint_as_unsigned(&align_result->data.x_bigint);
1350 if (align_bytes == 0) {1350 if (align_bytes == 0) {
1351 add_node_error(g, node, buf_sprintf("alignment must be >= 1"));1351 add_node_error(g, node, buf_sprintf("alignment must be >= 1"));
1352 return false;1352 return false;
...@@ -1364,12 +1364,12 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **...@@ -1364,12 +1364,12 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
1364 ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,1364 ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
1365 PtrLenUnknown, 0, 0, 0);1365 PtrLenUnknown, 0, 0, 0);
1366 ZigType *str_type = get_slice_type(g, ptr_type);1366 ZigType *str_type = get_slice_type(g, ptr_type);
1367 IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr);1367 ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr);
1368 if (type_is_invalid(instr->value.type))1368 if (type_is_invalid(result_val->type))
1369 return false;1369 return false;
13701370
1371 ConstExprValue *ptr_field = &instr->value.data.x_struct.fields[slice_ptr_index];1371 ConstExprValue *ptr_field = &result_val->data.x_struct.fields[slice_ptr_index];
1372 ConstExprValue *len_field = &instr->value.data.x_struct.fields[slice_len_index];1372 ConstExprValue *len_field = &result_val->data.x_struct.fields[slice_len_index];
13731373
1374 assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);1374 assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);
1375 ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val;1375 ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val;
...@@ -1422,6 +1422,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {...@@ -1422,6 +1422,7 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {
1422 case ZigTypeIdPointer:1422 case ZigTypeIdPointer:
1423 case ZigTypeIdArray:1423 case ZigTypeIdArray:
1424 case ZigTypeIdFn:1424 case ZigTypeIdFn:
1425 case ZigTypeIdVector:
1425 return true;1426 return true;
1426 case ZigTypeIdStruct:1427 case ZigTypeIdStruct:
1427 return type_entry->data.structure.layout == ContainerLayoutPacked;1428 return type_entry->data.structure.layout == ContainerLayoutPacked;
...@@ -1470,6 +1471,8 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {...@@ -1470,6 +1471,8 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
1470 default:1471 default:
1471 return false;1472 return false;
1472 }1473 }
1474 case ZigTypeIdVector:
1475 return type_allowed_in_extern(g, type_entry->data.vector.elem_type);
1473 case ZigTypeIdFloat:1476 case ZigTypeIdFloat:
1474 return true;1477 return true;
1475 case ZigTypeIdArray:1478 case ZigTypeIdArray:
...@@ -1623,6 +1626,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc...@@ -1623,6 +1626,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
1623 case ZigTypeIdUnion:1626 case ZigTypeIdUnion:
1624 case ZigTypeIdFn:1627 case ZigTypeIdFn:
1625 case ZigTypeIdPromise:1628 case ZigTypeIdPromise:
1629 case ZigTypeIdVector:
1626 switch (type_requires_comptime(g, type_entry)) {1630 switch (type_requires_comptime(g, type_entry)) {
1627 case ReqCompTimeNo:1631 case ReqCompTimeNo:
1628 break;1632 break;
...@@ -1718,6 +1722,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc...@@ -1718,6 +1722,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
1718 case ZigTypeIdUnion:1722 case ZigTypeIdUnion:
1719 case ZigTypeIdFn:1723 case ZigTypeIdFn:
1720 case ZigTypeIdPromise:1724 case ZigTypeIdPromise:
1725 case ZigTypeIdVector:
1721 switch (type_requires_comptime(g, fn_type_id.return_type)) {1726 switch (type_requires_comptime(g, fn_type_id.return_type)) {
1722 case ReqCompTimeInvalid:1727 case ReqCompTimeInvalid:
1723 return g->builtin_types.entry_invalid;1728 return g->builtin_types.entry_invalid;
...@@ -2504,20 +2509,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {...@@ -2504,20 +2509,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
2504 // In this first pass we resolve explicit tag values.2509 // In this first pass we resolve explicit tag values.
2505 // In a second pass we will fill in the unspecified ones.2510 // In a second pass we will fill in the unspecified ones.
2506 if (tag_value != nullptr) {2511 if (tag_value != nullptr) {
2507 IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);2512 ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
2508 if (result_inst->value.type->id == ZigTypeIdInvalid) {2513 if (type_is_invalid(result->type)) {
2509 enum_type->data.enumeration.is_invalid = true;2514 enum_type->data.enumeration.is_invalid = true;
2510 continue;2515 continue;
2511 }2516 }
2512 assert(result_inst->value.special != ConstValSpecialRuntime);2517 assert(result->special != ConstValSpecialRuntime);
2513 assert(result_inst->value.type->id == ZigTypeIdInt ||2518 assert(result->type->id == ZigTypeIdInt ||
2514 result_inst->value.type->id == ZigTypeIdComptimeInt);2519 result->type->id == ZigTypeIdComptimeInt);
2515 auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);2520 auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
2516 if (entry == nullptr) {2521 if (entry == nullptr) {
2517 bigint_init_bigint(&type_enum_field->value, &result_inst->value.data.x_bigint);2522 bigint_init_bigint(&type_enum_field->value, &result->data.x_bigint);
2518 } else {2523 } else {
2519 Buf *val_buf = buf_alloc();2524 Buf *val_buf = buf_alloc();
2520 bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10);2525 bigint_append_buf(val_buf, &result->data.x_bigint, 10);
25212526
2522 ErrorMsg *msg = add_node_error(g, tag_value,2527 ErrorMsg *msg = add_node_error(g, tag_value,
2523 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));2528 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
...@@ -2944,19 +2949,19 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {...@@ -2944,19 +2949,19 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
2944 // In a second pass we will fill in the unspecified ones.2949 // In a second pass we will fill in the unspecified ones.
2945 if (tag_value != nullptr) {2950 if (tag_value != nullptr) {
2946 ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type;2951 ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type;
2947 IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);2952 ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
2948 if (result_inst->value.type->id == ZigTypeIdInvalid) {2953 if (type_is_invalid(result->type)) {
2949 union_type->data.unionation.is_invalid = true;2954 union_type->data.unionation.is_invalid = true;
2950 continue;2955 continue;
2951 }2956 }
2952 assert(result_inst->value.special != ConstValSpecialRuntime);2957 assert(result->special != ConstValSpecialRuntime);
2953 assert(result_inst->value.type->id == ZigTypeIdInt);2958 assert(result->type->id == ZigTypeIdInt);
2954 auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);2959 auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
2955 if (entry == nullptr) {2960 if (entry == nullptr) {
2956 bigint_init_bigint(&union_field->enum_field->value, &result_inst->value.data.x_bigint);2961 bigint_init_bigint(&union_field->enum_field->value, &result->data.x_bigint);
2957 } else {2962 } else {
2958 Buf *val_buf = buf_alloc();2963 Buf *val_buf = buf_alloc();
2959 bigint_append_buf(val_buf, &result_inst->value.data.x_bigint, 10);2964 bigint_append_buf(val_buf, &result->data.x_bigint, 10);
29602965
2961 ErrorMsg *msg = add_node_error(g, tag_value,2966 ErrorMsg *msg = add_node_error(g, tag_value,
2962 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));2967 buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf)));
...@@ -3419,7 +3424,8 @@ void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) {...@@ -3419,7 +3424,8 @@ void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) {
3419 resolve_top_level_decl(g, tld, false, tld->source_node);3424 resolve_top_level_decl(g, tld, false, tld->source_node);
3420 assert(tld->id == TldIdVar);3425 assert(tld->id == TldIdVar);
3421 TldVar *tld_var = (TldVar *)tld;3426 TldVar *tld_var = (TldVar *)tld;
3422 tld_var->var->value = value;3427 tld_var->var->const_value = value;
3428 tld_var->var->var_type = value->type;
3423 tld_var->var->align_bytes = get_abi_alignment(g, value->type);3429 tld_var->var->align_bytes = get_abi_alignment(g, value->type);
3424}3430}
34253431
...@@ -3513,7 +3519,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {...@@ -3513,7 +3519,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
3513 case NodeTypeArrayType:3519 case NodeTypeArrayType:
3514 case NodeTypeErrorType:3520 case NodeTypeErrorType:
3515 case NodeTypeIfErrorExpr:3521 case NodeTypeIfErrorExpr:
3516 case NodeTypeTestExpr:3522 case NodeTypeIfOptional:
3517 case NodeTypeErrorSetDecl:3523 case NodeTypeErrorSetDecl:
3518 case NodeTypeCancel:3524 case NodeTypeCancel:
3519 case NodeTypeResume:3525 case NodeTypeResume:
...@@ -3574,6 +3580,7 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry...@@ -3574,6 +3580,7 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
3574 case ZigTypeIdFn:3580 case ZigTypeIdFn:
3575 case ZigTypeIdBoundFn:3581 case ZigTypeIdBoundFn:
3576 case ZigTypeIdPromise:3582 case ZigTypeIdPromise:
3583 case ZigTypeIdVector:
3577 return type_entry;3584 return type_entry;
3578 }3585 }
3579 zig_unreachable();3586 zig_unreachable();
...@@ -3582,13 +3589,15 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry...@@ -3582,13 +3589,15 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
3582// Set name to nullptr to make the variable anonymous (not visible to programmer).3589// Set name to nullptr to make the variable anonymous (not visible to programmer).
3583// TODO merge with definition of add_local_var in ir.cpp3590// TODO merge with definition of add_local_var in ir.cpp
3584ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,3591ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
3585 bool is_const, ConstExprValue *value, Tld *src_tld)3592 bool is_const, ConstExprValue *const_value, Tld *src_tld, ZigType *var_type)
3586{3593{
3587 Error err;3594 Error err;
3588 assert(value);3595 assert(const_value != nullptr);
3596 assert(var_type != nullptr);
35893597
3590 ZigVar *variable_entry = allocate<ZigVar>(1);3598 ZigVar *variable_entry = allocate<ZigVar>(1);
3591 variable_entry->value = value;3599 variable_entry->const_value = const_value;
3600 variable_entry->var_type = var_type;
3592 variable_entry->parent_scope = parent_scope;3601 variable_entry->parent_scope = parent_scope;
3593 variable_entry->shadowable = false;3602 variable_entry->shadowable = false;
3594 variable_entry->mem_slot_index = SIZE_MAX;3603 variable_entry->mem_slot_index = SIZE_MAX;
...@@ -3597,23 +3606,23 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf...@@ -3597,23 +3606,23 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
3597 assert(name);3606 assert(name);
3598 buf_init_from_buf(&variable_entry->name, name);3607 buf_init_from_buf(&variable_entry->name, name);
35993608
3600 if ((err = type_resolve(g, value->type, ResolveStatusAlignmentKnown))) {3609 if ((err = type_resolve(g, var_type, ResolveStatusAlignmentKnown))) {
3601 variable_entry->value->type = g->builtin_types.entry_invalid;3610 variable_entry->var_type = g->builtin_types.entry_invalid;
3602 } else {3611 } else {
3603 variable_entry->align_bytes = get_abi_alignment(g, value->type);3612 variable_entry->align_bytes = get_abi_alignment(g, var_type);
36043613
3605 ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr);3614 ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr);
3606 if (existing_var && !existing_var->shadowable) {3615 if (existing_var && !existing_var->shadowable) {
3607 ErrorMsg *msg = add_node_error(g, source_node,3616 ErrorMsg *msg = add_node_error(g, source_node,
3608 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));3617 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
3609 add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));3618 add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
3610 variable_entry->value->type = g->builtin_types.entry_invalid;3619 variable_entry->var_type = g->builtin_types.entry_invalid;
3611 } else {3620 } else {
3612 ZigType *type;3621 ZigType *type;
3613 if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) {3622 if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) {
3614 add_node_error(g, source_node,3623 add_node_error(g, source_node,
3615 buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));3624 buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));
3616 variable_entry->value->type = g->builtin_types.entry_invalid;3625 variable_entry->var_type = g->builtin_types.entry_invalid;
3617 } else {3626 } else {
3618 Scope *search_scope = nullptr;3627 Scope *search_scope = nullptr;
3619 if (src_tld == nullptr) {3628 if (src_tld == nullptr) {
...@@ -3627,7 +3636,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf...@@ -3627,7 +3636,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
3627 ErrorMsg *msg = add_node_error(g, source_node,3636 ErrorMsg *msg = add_node_error(g, source_node,
3628 buf_sprintf("redefinition of '%s'", buf_ptr(name)));3637 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
3629 add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here"));3638 add_error_note(g, msg, tld->source_node, buf_sprintf("previous definition is here"));
3630 variable_entry->value->type = g->builtin_types.entry_invalid;3639 variable_entry->var_type = g->builtin_types.entry_invalid;
3631 }3640 }
3632 }3641 }
3633 }3642 }
...@@ -3677,7 +3686,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3677,7 +3686,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3677 linkage = VarLinkageInternal;3686 linkage = VarLinkageInternal;
3678 }3687 }
36793688
3680 IrInstruction *init_value = nullptr;3689 ConstExprValue *init_value = nullptr;
36813690
3682 // TODO more validation for types that can't be used for export/extern variables3691 // TODO more validation for types that can't be used for export/extern variables
3683 ZigType *implicit_type = nullptr;3692 ZigType *implicit_type = nullptr;
...@@ -3686,7 +3695,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3686,7 +3695,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3686 } else if (var_decl->expr) {3695 } else if (var_decl->expr) {
3687 init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol);3696 init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol);
3688 assert(init_value);3697 assert(init_value);
3689 implicit_type = init_value->value.type;3698 implicit_type = init_value->type;
36903699
3691 if (implicit_type->id == ZigTypeIdUnreachable) {3700 if (implicit_type->id == ZigTypeIdUnreachable) {
3692 add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));3701 add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));
...@@ -3704,7 +3713,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3704,7 +3713,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3704 add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant"));3713 add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant"));
3705 implicit_type = g->builtin_types.entry_invalid;3714 implicit_type = g->builtin_types.entry_invalid;
3706 }3715 }
3707 assert(implicit_type->id == ZigTypeIdInvalid || init_value->value.special != ConstValSpecialRuntime);3716 assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime);
3708 } else if (linkage != VarLinkageExternal) {3717 } else if (linkage != VarLinkageExternal) {
3709 add_node_error(g, source_node, buf_sprintf("variables must be initialized"));3718 add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
3710 implicit_type = g->builtin_types.entry_invalid;3719 implicit_type = g->builtin_types.entry_invalid;
...@@ -3713,19 +3722,19 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {...@@ -3713,19 +3722,19 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
3713 ZigType *type = explicit_type ? explicit_type : implicit_type;3722 ZigType *type = explicit_type ? explicit_type : implicit_type;
3714 assert(type != nullptr); // should have been caught by the parser3723 assert(type != nullptr); // should have been caught by the parser
37153724
3716 ConstExprValue *init_val = init_value ? &init_value->value : create_const_runtime(type);3725 ConstExprValue *init_val = (init_value != nullptr) ? init_value : create_const_runtime(type);
37173726
3718 tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol,3727 tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol,
3719 is_const, init_val, &tld_var->base);3728 is_const, init_val, &tld_var->base, type);
3720 tld_var->var->linkage = linkage;3729 tld_var->var->linkage = linkage;
37213730
3722 if (implicit_type != nullptr && type_is_invalid(implicit_type)) {3731 if (implicit_type != nullptr && type_is_invalid(implicit_type)) {
3723 tld_var->var->value->type = g->builtin_types.entry_invalid;3732 tld_var->var->var_type = g->builtin_types.entry_invalid;
3724 }3733 }
37253734
3726 if (var_decl->align_expr != nullptr) {3735 if (var_decl->align_expr != nullptr) {
3727 if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) {3736 if (!analyze_const_align(g, tld_var->base.parent_scope, var_decl->align_expr, &tld_var->var->align_bytes)) {
3728 tld_var->var->value->type = g->builtin_types.entry_invalid;3737 tld_var->var->var_type = g->builtin_types.entry_invalid;
3729 }3738 }
3730 }3739 }
37313740
...@@ -3938,6 +3947,7 @@ static bool is_container(ZigType *type_entry) {...@@ -3938,6 +3947,7 @@ static bool is_container(ZigType *type_entry) {
3938 case ZigTypeIdArgTuple:3947 case ZigTypeIdArgTuple:
3939 case ZigTypeIdOpaque:3948 case ZigTypeIdOpaque:
3940 case ZigTypeIdPromise:3949 case ZigTypeIdPromise:
3950 case ZigTypeIdVector:
3941 return false;3951 return false;
3942 }3952 }
3943 zig_unreachable();3953 zig_unreachable();
...@@ -3997,6 +4007,7 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) {...@@ -3997,6 +4007,7 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) {
3997 case ZigTypeIdArgTuple:4007 case ZigTypeIdArgTuple:
3998 case ZigTypeIdOpaque:4008 case ZigTypeIdOpaque:
3999 case ZigTypeIdPromise:4009 case ZigTypeIdPromise:
4010 case ZigTypeIdVector:
4000 zig_unreachable();4011 zig_unreachable();
4001 }4012 }
4002}4013}
...@@ -4090,7 +4101,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {...@@ -4090,7 +4101,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {
4090 }4101 }
40914102
4092 ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope,4103 ZigVar *var = add_variable(g, param_decl_node, fn_table_entry->child_scope,
4093 param_name, true, create_const_runtime(param_type), nullptr);4104 param_name, true, create_const_runtime(param_type), nullptr, param_type);
4094 var->src_arg_index = i;4105 var->src_arg_index = i;
4095 fn_table_entry->child_scope = var->child_scope;4106 fn_table_entry->child_scope = var->child_scope;
4096 var->shadowable = var->shadowable || is_var_args;4107 var->shadowable = var->shadowable || is_var_args;
...@@ -4228,18 +4239,17 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *...@@ -4228,18 +4239,17 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *
4228 preview_use_decl(g, src_use_node);4239 preview_use_decl(g, src_use_node);
4229 }4240 }
42304241
4231 IrInstruction *use_target_value = src_use_node->data.use.value;4242 ConstExprValue *use_target_value = src_use_node->data.use.value;
4232 if (use_target_value->value.type->id == ZigTypeIdInvalid) {4243 if (type_is_invalid(use_target_value->type)) {
4233 dst_use_node->owner->any_imports_failed = true;4244 dst_use_node->owner->any_imports_failed = true;
4234 return;4245 return;
4235 }4246 }
42364247
4237 dst_use_node->data.use.resolution = TldResolutionOk;4248 dst_use_node->data.use.resolution = TldResolutionOk;
42384249
4239 ConstExprValue *const_val = &use_target_value->value;4250 assert(use_target_value->special != ConstValSpecialRuntime);
4240 assert(const_val->special != ConstValSpecialRuntime);
42414251
4242 ImportTableEntry *target_import = const_val->data.x_import;4252 ImportTableEntry *target_import = use_target_value->data.x_import;
4243 assert(target_import);4253 assert(target_import);
42444254
4245 if (target_import->any_imports_failed) {4255 if (target_import->any_imports_failed) {
...@@ -4302,10 +4312,10 @@ void preview_use_decl(CodeGen *g, AstNode *node) {...@@ -4302,10 +4312,10 @@ void preview_use_decl(CodeGen *g, AstNode *node) {
4302 }4312 }
43034313
4304 node->data.use.resolution = TldResolutionResolving;4314 node->data.use.resolution = TldResolutionResolving;
4305 IrInstruction *result = analyze_const_value(g, &node->owner->decls_scope->base,4315 ConstExprValue *result = analyze_const_value(g, &node->owner->decls_scope->base,
4306 node->data.use.expr, g->builtin_types.entry_namespace, nullptr);4316 node->data.use.expr, g->builtin_types.entry_namespace, nullptr);
43074317
4308 if (result->value.type->id == ZigTypeIdInvalid)4318 if (type_is_invalid(result->type))
4309 node->owner->any_imports_failed = true;4319 node->owner->any_imports_failed = true;
43104320
4311 node->data.use.value = result;4321 node->data.use.value = result;
...@@ -4447,6 +4457,42 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {...@@ -4447,6 +4457,42 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
4447 return new_entry;4457 return new_entry;
4448}4458}
44494459
4460bool is_valid_vector_elem_type(ZigType *elem_type) {
4461 return elem_type->id == ZigTypeIdInt ||
4462 elem_type->id == ZigTypeIdFloat ||
4463 get_codegen_ptr_type(elem_type) != nullptr;
4464}
4465
4466ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) {
4467 assert(is_valid_vector_elem_type(elem_type));
4468
4469 TypeId type_id = {};
4470 type_id.id = ZigTypeIdVector;
4471 type_id.data.vector.len = len;
4472 type_id.data.vector.elem_type = elem_type;
4473
4474 {
4475 auto entry = g->type_table.maybe_get(type_id);
4476 if (entry)
4477 return entry->value;
4478 }
4479
4480 ZigType *entry = new_type_table_entry(ZigTypeIdVector);
4481 entry->zero_bits = (len == 0) || !type_has_bits(elem_type);
4482 entry->type_ref = entry->zero_bits ? LLVMVoidType() : LLVMVectorType(elem_type->type_ref, len);
4483 entry->data.vector.len = len;
4484 entry->data.vector.elem_type = elem_type;
4485
4486 buf_resize(&entry->name, 0);
4487 buf_appendf(&entry->name, "@Vector(%u, %s)", len, buf_ptr(&elem_type->name));
4488
4489 entry->di_type = ZigLLVMDIBuilderCreateVectorType(g->dbuilder, len,
4490 LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref), elem_type->di_type);
4491
4492 g->type_table.put(type_id, entry);
4493 return entry;
4494}
4495
4450ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) {4496ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) {
4451 return &g->builtin_types.entry_c_int[c_int_type];4497 return &g->builtin_types.entry_c_int[c_int_type];
4452}4498}
...@@ -4478,6 +4524,7 @@ bool handle_is_ptr(ZigType *type_entry) {...@@ -4478,6 +4524,7 @@ bool handle_is_ptr(ZigType *type_entry) {
4478 case ZigTypeIdFn:4524 case ZigTypeIdFn:
4479 case ZigTypeIdEnum:4525 case ZigTypeIdEnum:
4480 case ZigTypeIdPromise:4526 case ZigTypeIdPromise:
4527 case ZigTypeIdVector:
4481 return false;4528 return false;
4482 case ZigTypeIdArray:4529 case ZigTypeIdArray:
4483 case ZigTypeIdStruct:4530 case ZigTypeIdStruct:
...@@ -4486,7 +4533,8 @@ bool handle_is_ptr(ZigType *type_entry) {...@@ -4486,7 +4533,8 @@ bool handle_is_ptr(ZigType *type_entry) {
4486 return type_has_bits(type_entry->data.error_union.payload_type);4533 return type_has_bits(type_entry->data.error_union.payload_type);
4487 case ZigTypeIdOptional:4534 case ZigTypeIdOptional:
4488 return type_has_bits(type_entry->data.maybe.child_type) &&4535 return type_has_bits(type_entry->data.maybe.child_type) &&
4489 !type_is_codegen_pointer(type_entry->data.maybe.child_type);4536 !type_is_codegen_pointer(type_entry->data.maybe.child_type) &&
4537 type_entry->data.maybe.child_type->id != ZigTypeIdErrorSet;
4490 case ZigTypeIdUnion:4538 case ZigTypeIdUnion:
4491 assert(type_entry->data.unionation.zero_bits_known);4539 assert(type_entry->data.unionation.zero_bits_known);
4492 if (type_entry->data.unionation.gen_field_count == 0)4540 if (type_entry->data.unionation.gen_field_count == 0)
...@@ -4732,6 +4780,11 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {...@@ -4732,6 +4780,11 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {
4732 return true;4780 return true;
4733}4781}
47344782
4783static uint32_t hash_const_val_error_set(ConstExprValue *const_val) {
4784 assert(const_val->data.x_err_set != nullptr);
4785 return const_val->data.x_err_set->value ^ 2630160122;
4786}
4787
4735static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {4788static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
4736 uint32_t hash_val = 0;4789 uint32_t hash_val = 0;
4737 switch (const_val->data.x_ptr.mut) {4790 switch (const_val->data.x_ptr.mut) {
...@@ -4763,6 +4816,18 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {...@@ -4763,6 +4816,18 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
4763 hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val);4816 hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val);
4764 hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index);4817 hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index);
4765 return hash_val;4818 return hash_val;
4819 case ConstPtrSpecialBaseErrorUnionCode:
4820 hash_val += (uint32_t)2994743799;
4821 hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_code.err_union_val);
4822 return hash_val;
4823 case ConstPtrSpecialBaseErrorUnionPayload:
4824 hash_val += (uint32_t)3456080131;
4825 hash_val += hash_ptr(const_val->data.x_ptr.data.base_err_union_payload.err_union_val);
4826 return hash_val;
4827 case ConstPtrSpecialBaseOptionalPayload:
4828 hash_val += (uint32_t)3163140517;
4829 hash_val += hash_ptr(const_val->data.x_ptr.data.base_optional_payload.optional_val);
4830 return hash_val;
4766 case ConstPtrSpecialHardCodedAddr:4831 case ConstPtrSpecialHardCodedAddr:
4767 hash_val += (uint32_t)4048518294;4832 hash_val += (uint32_t)4048518294;
4768 hash_val += hash_size(const_val->data.x_ptr.data.hard_coded_addr.addr);4833 hash_val += hash_size(const_val->data.x_ptr.data.hard_coded_addr.addr);
...@@ -4774,6 +4839,9 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {...@@ -4774,6 +4839,9 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
4774 hash_val += (uint32_t)2590901619;4839 hash_val += (uint32_t)2590901619;
4775 hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry);4840 hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry);
4776 return hash_val;4841 return hash_val;
4842 case ConstPtrSpecialNull:
4843 hash_val += (uint32_t)1486246455;
4844 return hash_val;
4777 }4845 }
4778 zig_unreachable();4846 zig_unreachable();
4779}4847}
...@@ -4872,7 +4940,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {...@@ -4872,7 +4940,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
4872 return 2709806591;4940 return 2709806591;
4873 case ZigTypeIdOptional:4941 case ZigTypeIdOptional:
4874 if (get_codegen_ptr_type(const_val->type) != nullptr) {4942 if (get_codegen_ptr_type(const_val->type) != nullptr) {
4875 return hash_const_val(const_val) * 1992916303;4943 return hash_const_val_ptr(const_val) * 1992916303;
4944 } else if (const_val->type->data.maybe.child_type->id == ZigTypeIdErrorSet) {
4945 return hash_const_val_error_set(const_val) * 3147031929;
4876 } else {4946 } else {
4877 if (const_val->data.x_optional) {4947 if (const_val->data.x_optional) {
4878 return hash_const_val(const_val->data.x_optional) * 1992916303;4948 return hash_const_val(const_val->data.x_optional) * 1992916303;
...@@ -4884,10 +4954,12 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {...@@ -4884,10 +4954,12 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
4884 // TODO better hashing algorithm4954 // TODO better hashing algorithm
4885 return 3415065496;4955 return 3415065496;
4886 case ZigTypeIdErrorSet:4956 case ZigTypeIdErrorSet:
4887 assert(const_val->data.x_err_set != nullptr);4957 return hash_const_val_error_set(const_val);
4888 return const_val->data.x_err_set->value ^ 2630160122;
4889 case ZigTypeIdNamespace:4958 case ZigTypeIdNamespace:
4890 return hash_ptr(const_val->data.x_import);4959 return hash_ptr(const_val->data.x_import);
4960 case ZigTypeIdVector:
4961 // TODO better hashing algorithm
4962 return 3647867726;
4891 case ZigTypeIdBoundFn:4963 case ZigTypeIdBoundFn:
4892 case ZigTypeIdInvalid:4964 case ZigTypeIdInvalid:
4893 case ZigTypeIdUnreachable:4965 case ZigTypeIdUnreachable:
...@@ -4940,6 +5012,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {...@@ -4940,6 +5012,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
4940 case ZigTypeIdBool:5012 case ZigTypeIdBool:
4941 case ZigTypeIdUnreachable:5013 case ZigTypeIdUnreachable:
4942 case ZigTypeIdInt:5014 case ZigTypeIdInt:
5015 case ZigTypeIdVector:
4943 case ZigTypeIdFloat:5016 case ZigTypeIdFloat:
4944 case ZigTypeIdComptimeFloat:5017 case ZigTypeIdComptimeFloat:
4945 case ZigTypeIdComptimeInt:5018 case ZigTypeIdComptimeInt:
...@@ -4987,7 +5060,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {...@@ -4987,7 +5060,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
4987 return can_mutate_comptime_var_state(value->data.x_optional);5060 return can_mutate_comptime_var_state(value->data.x_optional);
49885061
4989 case ZigTypeIdErrorUnion:5062 case ZigTypeIdErrorUnion:
4990 if (value->data.x_err_union.err != nullptr)5063 if (value->data.x_err_union.error_set->data.x_err_set != nullptr)
4991 return false;5064 return false;
4992 assert(value->data.x_err_union.payload != nullptr);5065 assert(value->data.x_err_union.payload != nullptr);
4993 return can_mutate_comptime_var_state(value->data.x_err_union.payload);5066 return can_mutate_comptime_var_state(value->data.x_err_union.payload);
...@@ -5023,6 +5096,7 @@ static bool return_type_is_cacheable(ZigType *return_type) {...@@ -5023,6 +5096,7 @@ static bool return_type_is_cacheable(ZigType *return_type) {
5023 case ZigTypeIdErrorSet:5096 case ZigTypeIdErrorSet:
5024 case ZigTypeIdEnum:5097 case ZigTypeIdEnum:
5025 case ZigTypeIdPointer:5098 case ZigTypeIdPointer:
5099 case ZigTypeIdVector:
5026 return true;5100 return true;
50275101
5028 case ZigTypeIdArray:5102 case ZigTypeIdArray:
...@@ -5048,9 +5122,9 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) {...@@ -5048,9 +5122,9 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) {
5048 while (scope) {5122 while (scope) {
5049 if (scope->id == ScopeIdVarDecl) {5123 if (scope->id == ScopeIdVarDecl) {
5050 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;5124 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
5051 if (type_is_invalid(var_scope->var->value->type))5125 if (type_is_invalid(var_scope->var->var_type))
5052 return false;5126 return false;
5053 if (can_mutate_comptime_var_state(var_scope->var->value))5127 if (can_mutate_comptime_var_state(var_scope->var->const_value))
5054 return false;5128 return false;
5055 } else if (scope->id == ScopeIdFnDef) {5129 } else if (scope->id == ScopeIdFnDef) {
5056 return true;5130 return true;
...@@ -5068,7 +5142,7 @@ uint32_t fn_eval_hash(Scope* scope) {...@@ -5068,7 +5142,7 @@ uint32_t fn_eval_hash(Scope* scope) {
5068 while (scope) {5142 while (scope) {
5069 if (scope->id == ScopeIdVarDecl) {5143 if (scope->id == ScopeIdVarDecl) {
5070 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;5144 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
5071 result += hash_const_val(var_scope->var->value);5145 result += hash_const_val(var_scope->var->const_value);
5072 } else if (scope->id == ScopeIdFnDef) {5146 } else if (scope->id == ScopeIdFnDef) {
5073 ScopeFnDef *fn_scope = (ScopeFnDef *)scope;5147 ScopeFnDef *fn_scope = (ScopeFnDef *)scope;
5074 result += hash_ptr(fn_scope->fn_entry);5148 result += hash_ptr(fn_scope->fn_entry);
...@@ -5092,10 +5166,16 @@ bool fn_eval_eql(Scope *a, Scope *b) {...@@ -5092,10 +5166,16 @@ bool fn_eval_eql(Scope *a, Scope *b) {
5092 if (a->id == ScopeIdVarDecl) {5166 if (a->id == ScopeIdVarDecl) {
5093 ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a;5167 ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a;
5094 ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b;5168 ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b;
5095 if (a_var_scope->var->value->type != b_var_scope->var->value->type)5169 if (a_var_scope->var->var_type != b_var_scope->var->var_type)
5096 return false;
5097 if (!const_values_equal(a->codegen, a_var_scope->var->value, b_var_scope->var->value))
5098 return false;5170 return false;
5171 if (a_var_scope->var->var_type == a_var_scope->var->const_value->type &&
5172 b_var_scope->var->var_type == b_var_scope->var->const_value->type)
5173 {
5174 if (!const_values_equal(a->codegen, a_var_scope->var->const_value, b_var_scope->var->const_value))
5175 return false;
5176 } else {
5177 zig_panic("TODO comptime ptr reinterpret for fn_eval_eql");
5178 }
5099 } else if (a->id == ScopeIdFnDef) {5179 } else if (a->id == ScopeIdFnDef) {
5100 ScopeFnDef *a_fn_scope = (ScopeFnDef *)a;5180 ScopeFnDef *a_fn_scope = (ScopeFnDef *)a;
5101 ScopeFnDef *b_fn_scope = (ScopeFnDef *)b;5181 ScopeFnDef *b_fn_scope = (ScopeFnDef *)b;
...@@ -5113,6 +5193,7 @@ bool fn_eval_eql(Scope *a, Scope *b) {...@@ -5113,6 +5193,7 @@ bool fn_eval_eql(Scope *a, Scope *b) {
5113 return false;5193 return false;
5114}5194}
51155195
5196// Whether the type has bits at runtime.
5116bool type_has_bits(ZigType *type_entry) {5197bool type_has_bits(ZigType *type_entry) {
5117 assert(type_entry);5198 assert(type_entry);
5118 assert(!type_is_invalid(type_entry));5199 assert(!type_is_invalid(type_entry));
...@@ -5120,6 +5201,66 @@ bool type_has_bits(ZigType *type_entry) {...@@ -5120,6 +5201,66 @@ bool type_has_bits(ZigType *type_entry) {
5120 return !type_entry->zero_bits;5201 return !type_entry->zero_bits;
5121}5202}
51225203
5204// Whether you can infer the value based solely on the type.
5205OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
5206 assert(type_entry != nullptr);
5207 Error err;
5208 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
5209 return OnePossibleValueInvalid;
5210 switch (type_entry->id) {
5211 case ZigTypeIdInvalid:
5212 zig_unreachable();
5213 case ZigTypeIdOpaque:
5214 case ZigTypeIdComptimeFloat:
5215 case ZigTypeIdComptimeInt:
5216 case ZigTypeIdMetaType:
5217 case ZigTypeIdNamespace:
5218 case ZigTypeIdBoundFn:
5219 case ZigTypeIdArgTuple:
5220 case ZigTypeIdOptional:
5221 case ZigTypeIdFn:
5222 case ZigTypeIdBool:
5223 case ZigTypeIdFloat:
5224 case ZigTypeIdPromise:
5225 case ZigTypeIdErrorUnion:
5226 return OnePossibleValueNo;
5227 case ZigTypeIdUndefined:
5228 case ZigTypeIdNull:
5229 case ZigTypeIdVoid:
5230 case ZigTypeIdUnreachable:
5231 return OnePossibleValueYes;
5232 case ZigTypeIdArray:
5233 if (type_entry->data.array.len == 0)
5234 return OnePossibleValueYes;
5235 return type_has_one_possible_value(g, type_entry->data.array.child_type);
5236 case ZigTypeIdStruct:
5237 for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
5238 TypeStructField *field = &type_entry->data.structure.fields[i];
5239 switch (type_has_one_possible_value(g, field->type_entry)) {
5240 case OnePossibleValueInvalid:
5241 return OnePossibleValueInvalid;
5242 case OnePossibleValueNo:
5243 return OnePossibleValueNo;
5244 case OnePossibleValueYes:
5245 continue;
5246 }
5247 }
5248 return OnePossibleValueYes;
5249 case ZigTypeIdErrorSet:
5250 case ZigTypeIdEnum:
5251 case ZigTypeIdInt:
5252 case ZigTypeIdVector:
5253 return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes;
5254 case ZigTypeIdPointer:
5255 return type_has_one_possible_value(g, type_entry->data.pointer.child_type);
5256 case ZigTypeIdUnion:
5257 if (type_entry->data.unionation.src_field_count > 1)
5258 return OnePossibleValueNo;
5259 return type_has_one_possible_value(g, type_entry->data.unionation.fields[0].type_entry);
5260 }
5261 zig_unreachable();
5262}
5263
5123ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {5264ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
5124 Error err;5265 Error err;
5125 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))5266 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
...@@ -5159,6 +5300,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {...@@ -5159,6 +5300,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
5159 case ZigTypeIdErrorSet:5300 case ZigTypeIdErrorSet:
5160 case ZigTypeIdBool:5301 case ZigTypeIdBool:
5161 case ZigTypeIdInt:5302 case ZigTypeIdInt:
5303 case ZigTypeIdVector:
5162 case ZigTypeIdFloat:5304 case ZigTypeIdFloat:
5163 case ZigTypeIdVoid:5305 case ZigTypeIdVoid:
5164 case ZigTypeIdUnreachable:5306 case ZigTypeIdUnreachable:
...@@ -5574,6 +5716,33 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {...@@ -5574,6 +5716,33 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
5574 if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index)5716 if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index)
5575 return false;5717 return false;
5576 return true;5718 return true;
5719 case ConstPtrSpecialBaseErrorUnionCode:
5720 if (a->data.x_ptr.data.base_err_union_code.err_union_val !=
5721 b->data.x_ptr.data.base_err_union_code.err_union_val &&
5722 a->data.x_ptr.data.base_err_union_code.err_union_val->global_refs !=
5723 b->data.x_ptr.data.base_err_union_code.err_union_val->global_refs)
5724 {
5725 return false;
5726 }
5727 return true;
5728 case ConstPtrSpecialBaseErrorUnionPayload:
5729 if (a->data.x_ptr.data.base_err_union_payload.err_union_val !=
5730 b->data.x_ptr.data.base_err_union_payload.err_union_val &&
5731 a->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs !=
5732 b->data.x_ptr.data.base_err_union_payload.err_union_val->global_refs)
5733 {
5734 return false;
5735 }
5736 return true;
5737 case ConstPtrSpecialBaseOptionalPayload:
5738 if (a->data.x_ptr.data.base_optional_payload.optional_val !=
5739 b->data.x_ptr.data.base_optional_payload.optional_val &&
5740 a->data.x_ptr.data.base_optional_payload.optional_val->global_refs !=
5741 b->data.x_ptr.data.base_optional_payload.optional_val->global_refs)
5742 {
5743 return false;
5744 }
5745 return true;
5577 case ConstPtrSpecialHardCodedAddr:5746 case ConstPtrSpecialHardCodedAddr:
5578 if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr)5747 if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr)
5579 return false;5748 return false;
...@@ -5582,10 +5751,34 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {...@@ -5582,10 +5751,34 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
5582 return true;5751 return true;
5583 case ConstPtrSpecialFunction:5752 case ConstPtrSpecialFunction:
5584 return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry;5753 return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry;
5754 case ConstPtrSpecialNull:
5755 return true;
5585 }5756 }
5586 zig_unreachable();5757 zig_unreachable();
5587}5758}
55885759
5760static bool const_values_equal_array(CodeGen *g, ConstExprValue *a, ConstExprValue *b, size_t len) {
5761 assert(a->data.x_array.special != ConstArraySpecialUndef);
5762 assert(b->data.x_array.special != ConstArraySpecialUndef);
5763 if (a->data.x_array.special == ConstArraySpecialBuf &&
5764 b->data.x_array.special == ConstArraySpecialBuf)
5765 {
5766 return buf_eql_buf(a->data.x_array.data.s_buf, b->data.x_array.data.s_buf);
5767 }
5768 expand_undef_array(g, a);
5769 expand_undef_array(g, b);
5770
5771 ConstExprValue *a_elems = a->data.x_array.data.s_none.elements;
5772 ConstExprValue *b_elems = b->data.x_array.data.s_none.elements;
5773
5774 for (size_t i = 0; i < len; i += 1) {
5775 if (!const_values_equal(g, &a_elems[i], &b_elems[i]))
5776 return false;
5777 }
5778
5779 return true;
5780}
5781
5589bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {5782bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
5590 assert(a->type->id == b->type->id);5783 assert(a->type->id == b->type->id);
5591 assert(a->special == ConstValSpecialStatic);5784 assert(a->special == ConstValSpecialStatic);
...@@ -5640,28 +5833,12 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {...@@ -5640,28 +5833,12 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
5640 case ZigTypeIdPointer:5833 case ZigTypeIdPointer:
5641 case ZigTypeIdFn:5834 case ZigTypeIdFn:
5642 return const_values_equal_ptr(a, b);5835 return const_values_equal_ptr(a, b);
5836 case ZigTypeIdVector:
5837 assert(a->type->data.vector.len == b->type->data.vector.len);
5838 return const_values_equal_array(g, a, b, a->type->data.vector.len);
5643 case ZigTypeIdArray: {5839 case ZigTypeIdArray: {
5644 assert(a->type->data.array.len == b->type->data.array.len);5840 assert(a->type->data.array.len == b->type->data.array.len);
5645 assert(a->data.x_array.special != ConstArraySpecialUndef);5841 return const_values_equal_array(g, a, b, a->type->data.array.len);
5646 assert(b->data.x_array.special != ConstArraySpecialUndef);
5647 if (a->data.x_array.special == ConstArraySpecialBuf &&
5648 b->data.x_array.special == ConstArraySpecialBuf)
5649 {
5650 return buf_eql_buf(a->data.x_array.data.s_buf, b->data.x_array.data.s_buf);
5651 }
5652 expand_undef_array(g, a);
5653 expand_undef_array(g, b);
5654
5655 size_t len = a->type->data.array.len;
5656 ConstExprValue *a_elems = a->data.x_array.data.s_none.elements;
5657 ConstExprValue *b_elems = b->data.x_array.data.s_none.elements;
5658
5659 for (size_t i = 0; i < len; ++i) {
5660 if (!const_values_equal(g, &a_elems[i], &b_elems[i]))
5661 return false;
5662 }
5663
5664 return true;
5665 }5842 }
5666 case ZigTypeIdStruct:5843 case ZigTypeIdStruct:
5667 for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) {5844 for (size_t i = 0; i < a->type->data.structure.src_field_count; i += 1) {
...@@ -5750,7 +5927,7 @@ void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_v...@@ -5750,7 +5927,7 @@ void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_v
5750 }5927 }
5751}5928}
57525929
5753void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {5930static void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {
5754 assert(type_entry->id == ZigTypeIdPointer);5931 assert(type_entry->id == ZigTypeIdPointer);
57555932
5756 if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) {5933 if (type_entry->data.pointer.child_type->id == ZigTypeIdOpaque) {
...@@ -5763,6 +5940,9 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy...@@ -5763,6 +5940,9 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy
5763 zig_unreachable();5940 zig_unreachable();
5764 case ConstPtrSpecialRef:5941 case ConstPtrSpecialRef:
5765 case ConstPtrSpecialBaseStruct:5942 case ConstPtrSpecialBaseStruct:
5943 case ConstPtrSpecialBaseErrorUnionCode:
5944 case ConstPtrSpecialBaseErrorUnionPayload:
5945 case ConstPtrSpecialBaseOptionalPayload:
5766 buf_appendf(buf, "*");5946 buf_appendf(buf, "*");
5767 // TODO we need a source node for const_ptr_pointee because it can generate compile errors5947 // TODO we need a source node for const_ptr_pointee because it can generate compile errors
5768 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));5948 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
...@@ -5790,6 +5970,51 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy...@@ -5790,6 +5970,51 @@ void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigTy
5790 buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name));5970 buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name));
5791 return;5971 return;
5792 }5972 }
5973 case ConstPtrSpecialNull:
5974 buf_append_str(buf, "null");
5975 return;
5976 }
5977 zig_unreachable();
5978}
5979
5980static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const_val, ZigType *type_entry) {
5981 if (const_val->data.x_err_set == nullptr) {
5982 buf_append_str(buf, "null");
5983 } else {
5984 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name));
5985 }
5986}
5987
5988static void render_const_val_array(CodeGen *g, Buf *buf, ConstExprValue *const_val, size_t len) {
5989 switch (const_val->data.x_array.special) {
5990 case ConstArraySpecialUndef:
5991 buf_append_str(buf, "undefined");
5992 return;
5993 case ConstArraySpecialBuf: {
5994 Buf *array_buf = const_val->data.x_array.data.s_buf;
5995 buf_append_char(buf, '"');
5996 for (size_t i = 0; i < buf_len(array_buf); i += 1) {
5997 uint8_t c = buf_ptr(array_buf)[i];
5998 if (c == '"') {
5999 buf_append_str(buf, "\\\"");
6000 } else {
6001 buf_append_char(buf, c);
6002 }
6003 }
6004 buf_append_char(buf, '"');
6005 return;
6006 }
6007 case ConstArraySpecialNone: {
6008 buf_appendf(buf, "%s{", buf_ptr(&const_val->type->name));
6009 for (uint64_t i = 0; i < len; i += 1) {
6010 if (i != 0)
6011 buf_appendf(buf, ",");
6012 ConstExprValue *child_value = &const_val->data.x_array.data.s_none.elements[i];
6013 render_const_value(g, buf, child_value);
6014 }
6015 buf_appendf(buf, "}");
6016 return;
6017 }
5793 }6018 }
5794 zig_unreachable();6019 zig_unreachable();
5795}6020}
...@@ -5874,39 +6099,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -5874,39 +6099,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
5874 }6099 }
5875 case ZigTypeIdPointer:6100 case ZigTypeIdPointer:
5876 return render_const_val_ptr(g, buf, const_val, type_entry);6101 return render_const_val_ptr(g, buf, const_val, type_entry);
6102 case ZigTypeIdVector:
6103 return render_const_val_array(g, buf, const_val, type_entry->data.vector.len);
5877 case ZigTypeIdArray:6104 case ZigTypeIdArray:
5878 switch (const_val->data.x_array.special) {6105 return render_const_val_array(g, buf, const_val, type_entry->data.array.len);
5879 case ConstArraySpecialUndef:
5880 buf_append_str(buf, "undefined");
5881 return;
5882 case ConstArraySpecialBuf: {
5883 Buf *array_buf = const_val->data.x_array.data.s_buf;
5884 buf_append_char(buf, '"');
5885 for (size_t i = 0; i < buf_len(array_buf); i += 1) {
5886 uint8_t c = buf_ptr(array_buf)[i];
5887 if (c == '"') {
5888 buf_append_str(buf, "\\\"");
5889 } else {
5890 buf_append_char(buf, c);
5891 }
5892 }
5893 buf_append_char(buf, '"');
5894 return;
5895 }
5896 case ConstArraySpecialNone: {
5897 buf_appendf(buf, "%s{", buf_ptr(&type_entry->name));
5898 uint64_t len = type_entry->data.array.len;
5899 for (uint64_t i = 0; i < len; i += 1) {
5900 if (i != 0)
5901 buf_appendf(buf, ",");
5902 ConstExprValue *child_value = &const_val->data.x_array.data.s_none.elements[i];
5903 render_const_value(g, buf, child_value);
5904 }
5905 buf_appendf(buf, "}");
5906 return;
5907 }
5908 }
5909 zig_unreachable();
5910 case ZigTypeIdNull:6106 case ZigTypeIdNull:
5911 {6107 {
5912 buf_appendf(buf, "null");6108 buf_appendf(buf, "null");
...@@ -5921,6 +6117,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -5921,6 +6117,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
5921 {6117 {
5922 if (get_codegen_ptr_type(const_val->type) != nullptr)6118 if (get_codegen_ptr_type(const_val->type) != nullptr)
5923 return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type);6119 return render_const_val_ptr(g, buf, const_val, type_entry->data.maybe.child_type);
6120 if (type_entry->data.maybe.child_type->id == ZigTypeIdErrorSet)
6121 return render_const_val_err_set(g, buf, const_val, type_entry->data.maybe.child_type);
5924 if (const_val->data.x_optional) {6122 if (const_val->data.x_optional) {
5925 render_const_value(g, buf, const_val->data.x_optional);6123 render_const_value(g, buf, const_val->data.x_optional);
5926 } else {6124 } else {
...@@ -5958,11 +6156,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -5958,11 +6156,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
5958 case ZigTypeIdErrorUnion:6156 case ZigTypeIdErrorUnion:
5959 {6157 {
5960 buf_appendf(buf, "%s(", buf_ptr(&type_entry->name));6158 buf_appendf(buf, "%s(", buf_ptr(&type_entry->name));
5961 if (const_val->data.x_err_union.err == nullptr) {6159 ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
6160 if (err_set == nullptr) {
5962 render_const_value(g, buf, const_val->data.x_err_union.payload);6161 render_const_value(g, buf, const_val->data.x_err_union.payload);
5963 } else {6162 } else {
5964 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name),6163 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name),
5965 buf_ptr(&const_val->data.x_err_union.err->name));6164 buf_ptr(&err_set->name));
5966 }6165 }
5967 buf_appendf(buf, ")");6166 buf_appendf(buf, ")");
5968 return;6167 return;
...@@ -5977,10 +6176,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -5977,10 +6176,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
5977 return;6176 return;
5978 }6177 }
5979 case ZigTypeIdErrorSet:6178 case ZigTypeIdErrorSet:
5980 {6179 return render_const_val_err_set(g, buf, const_val, type_entry);
5981 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name));
5982 return;
5983 }
5984 case ZigTypeIdArgTuple:6180 case ZigTypeIdArgTuple:
5985 {6181 {
5986 buf_appendf(buf, "(args value)");6182 buf_appendf(buf, "(args value)");
...@@ -6065,6 +6261,8 @@ uint32_t type_id_hash(TypeId x) {...@@ -6065,6 +6261,8 @@ uint32_t type_id_hash(TypeId x) {
6065 case ZigTypeIdInt:6261 case ZigTypeIdInt:
6066 return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) +6262 return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) +
6067 (((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557);6263 (((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557);
6264 case ZigTypeIdVector:
6265 return hash_ptr(x.data.vector.elem_type) * (x.data.vector.len * 526582681);
6068 }6266 }
6069 zig_unreachable();6267 zig_unreachable();
6070}6268}
...@@ -6113,6 +6311,9 @@ bool type_id_eql(TypeId a, TypeId b) {...@@ -6113,6 +6311,9 @@ bool type_id_eql(TypeId a, TypeId b) {
6113 case ZigTypeIdInt:6311 case ZigTypeIdInt:
6114 return a.data.integer.is_signed == b.data.integer.is_signed &&6312 return a.data.integer.is_signed == b.data.integer.is_signed &&
6115 a.data.integer.bit_count == b.data.integer.bit_count;6313 a.data.integer.bit_count == b.data.integer.bit_count;
6314 case ZigTypeIdVector:
6315 return a.data.vector.elem_type == b.data.vector.elem_type &&
6316 a.data.vector.len == b.data.vector.len;
6116 }6317 }
6117 zig_unreachable();6318 zig_unreachable();
6118}6319}
...@@ -6171,24 +6372,34 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {...@@ -6171,24 +6372,34 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
61716372
6172// Canonicalize the array value as ConstArraySpecialNone6373// Canonicalize the array value as ConstArraySpecialNone
6173void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {6374void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
6174 assert(const_val->type->id == ZigTypeIdArray);6375 size_t elem_count;
6376 ZigType *elem_type;
6377 if (const_val->type->id == ZigTypeIdArray) {
6378 elem_count = const_val->type->data.array.len;
6379 elem_type = const_val->type->data.array.child_type;
6380 } else if (const_val->type->id == ZigTypeIdVector) {
6381 elem_count = const_val->type->data.vector.len;
6382 elem_type = const_val->type->data.vector.elem_type;
6383 } else {
6384 zig_unreachable();
6385 }
6386 if (const_val->special == ConstValSpecialUndef) {
6387 const_val->special = ConstValSpecialStatic;
6388 const_val->data.x_array.special = ConstArraySpecialUndef;
6389 }
6175 switch (const_val->data.x_array.special) {6390 switch (const_val->data.x_array.special) {
6176 case ConstArraySpecialNone:6391 case ConstArraySpecialNone:
6177 return;6392 return;
6178 case ConstArraySpecialUndef: {6393 case ConstArraySpecialUndef: {
6179 const_val->data.x_array.special = ConstArraySpecialNone;6394 const_val->data.x_array.special = ConstArraySpecialNone;
6180 size_t elem_count = const_val->type->data.array.len;
6181 const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count);6395 const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count);
6182 for (size_t i = 0; i < elem_count; i += 1) {6396 for (size_t i = 0; i < elem_count; i += 1) {
6183 ConstExprValue *element_val = &const_val->data.x_array.data.s_none.elements[i];6397 ConstExprValue *element_val = &const_val->data.x_array.data.s_none.elements[i];
6184 element_val->type = const_val->type->data.array.child_type;6398 element_val->type = elem_type;
6185 init_const_undefined(g, element_val);6399 init_const_undefined(g, element_val);
6186 ConstParent *parent = get_const_val_parent(g, element_val);6400 element_val->parent.id = ConstParentIdArray;
6187 if (parent != nullptr) {6401 element_val->parent.data.p_array.array_val = const_val;
6188 parent->id = ConstParentIdArray;6402 element_val->parent.data.p_array.elem_index = i;
6189 parent->data.p_array.array_val = const_val;
6190 parent->data.p_array.elem_index = i;
6191 }
6192 }6403 }
6193 return;6404 return;
6194 }6405 }
...@@ -6199,7 +6410,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {...@@ -6199,7 +6410,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
6199 g->string_literals_table.maybe_remove(buf);6410 g->string_literals_table.maybe_remove(buf);
62006411
6201 const_val->data.x_array.special = ConstArraySpecialNone;6412 const_val->data.x_array.special = ConstArraySpecialNone;
6202 size_t elem_count = const_val->type->data.array.len;
6203 assert(elem_count == buf_len(buf));6413 assert(elem_count == buf_len(buf));
6204 const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count);6414 const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count);
6205 for (size_t i = 0; i < elem_count; i += 1) {6415 for (size_t i = 0; i < elem_count; i += 1) {
...@@ -6207,6 +6417,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {...@@ -6207,6 +6417,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
6207 this_char->special = ConstValSpecialStatic;6417 this_char->special = ConstValSpecialStatic;
6208 this_char->type = g->builtin_types.entry_u8;6418 this_char->type = g->builtin_types.entry_u8;
6209 bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(buf)[i]);6419 bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(buf)[i]);
6420 this_char->parent.id = ConstParentIdArray;
6421 this_char->parent.data.p_array.array_val = const_val;
6422 this_char->parent.data.p_array.elem_index = i;
6210 }6423 }
6211 return;6424 return;
6212 }6425 }
...@@ -6214,18 +6427,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {...@@ -6214,18 +6427,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
6214 zig_unreachable();6427 zig_unreachable();
6215}6428}
62166429
6430// Deprecated. Reference the parent field directly.
6217ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {6431ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {
6218 assert(value->type);6432 return &value->parent;
6219 ZigType *type_entry = value->type;
6220 if (type_entry->id == ZigTypeIdArray) {
6221 expand_undef_array(g, value);
6222 return &value->data.x_array.data.s_none.parent;
6223 } else if (type_entry->id == ZigTypeIdStruct) {
6224 return &value->data.x_struct.parent;
6225 } else if (type_entry->id == ZigTypeIdUnion) {
6226 return &value->data.x_union.parent;
6227 }
6228 return nullptr;
6229}6433}
62306434
6231static const ZigTypeId all_type_ids[] = {6435static const ZigTypeId all_type_ids[] = {
...@@ -6253,6 +6457,7 @@ static const ZigTypeId all_type_ids[] = {...@@ -6253,6 +6457,7 @@ static const ZigTypeId all_type_ids[] = {
6253 ZigTypeIdArgTuple,6457 ZigTypeIdArgTuple,
6254 ZigTypeIdOpaque,6458 ZigTypeIdOpaque,
6255 ZigTypeIdPromise,6459 ZigTypeIdPromise,
6460 ZigTypeIdVector,
6256};6461};
62576462
6258ZigTypeId type_id_at_index(size_t index) {6463ZigTypeId type_id_at_index(size_t index) {
...@@ -6318,6 +6523,8 @@ size_t type_id_index(ZigType *entry) {...@@ -6318,6 +6523,8 @@ size_t type_id_index(ZigType *entry) {
6318 return 22;6523 return 22;
6319 case ZigTypeIdPromise:6524 case ZigTypeIdPromise:
6320 return 23;6525 return 23;
6526 case ZigTypeIdVector:
6527 return 24;
6321 }6528 }
6322 zig_unreachable();6529 zig_unreachable();
6323}6530}
...@@ -6374,6 +6581,8 @@ const char *type_id_name(ZigTypeId id) {...@@ -6374,6 +6581,8 @@ const char *type_id_name(ZigTypeId id) {
6374 return "Opaque";6581 return "Opaque";
6375 case ZigTypeIdPromise:6582 case ZigTypeIdPromise:
6376 return "Promise";6583 return "Promise";
6584 case ZigTypeIdVector:
6585 return "Vector";
6377 }6586 }
6378 zig_unreachable();6587 zig_unreachable();
6379}6588}
...@@ -6453,7 +6662,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {...@@ -6453,7 +6662,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
6453 resolve_top_level_decl(codegen, tld, false, nullptr);6662 resolve_top_level_decl(codegen, tld, false, nullptr);
6454 assert(tld->id == TldIdVar);6663 assert(tld->id == TldIdVar);
6455 TldVar *tld_var = (TldVar *)tld;6664 TldVar *tld_var = (TldVar *)tld;
6456 ConstExprValue *var_value = tld_var->var->value;6665 ConstExprValue *var_value = tld_var->var->const_value;
6457 assert(var_value != nullptr);6666 assert(var_value != nullptr);
6458 return var_value;6667 return var_value;
6459}6668}
...@@ -6529,6 +6738,7 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {...@@ -6529,6 +6738,7 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {
6529 case ZigTypeIdBool:6738 case ZigTypeIdBool:
6530 return X64CABIClass_INTEGER;6739 return X64CABIClass_INTEGER;
6531 case ZigTypeIdFloat:6740 case ZigTypeIdFloat:
6741 case ZigTypeIdVector:
6532 return X64CABIClass_SSE;6742 return X64CABIClass_SSE;
6533 case ZigTypeIdStruct: {6743 case ZigTypeIdStruct: {
6534 // "If the size of an object is larger than four eightbytes, or it contains unaligned6744 // "If the size of an object is larger than four eightbytes, or it contains unaligned
src/analyze.hpp+10-1
...@@ -20,6 +20,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -20,6 +20,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
20uint64_t type_size(CodeGen *g, ZigType *type_entry);20uint64_t type_size(CodeGen *g, ZigType *type_entry);
21uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);21uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);
22ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);22ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
23ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type);
23ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);24ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
24ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type);25ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type);
25ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);26ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
...@@ -73,6 +74,7 @@ TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag);...@@ -73,6 +74,7 @@ TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag);
73bool is_ref(ZigType *type_entry);74bool is_ref(ZigType *type_entry);
74bool is_array_ref(ZigType *type_entry);75bool is_array_ref(ZigType *type_entry);
75bool is_container_ref(ZigType *type_entry);76bool is_container_ref(ZigType *type_entry);
77bool is_valid_vector_elem_type(ZigType *elem_type);
76void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);78void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
77void scan_import(CodeGen *g, ImportTableEntry *import);79void scan_import(CodeGen *g, ImportTableEntry *import);
78void preview_use_decl(CodeGen *g, AstNode *node);80void preview_use_decl(CodeGen *g, AstNode *node);
...@@ -81,7 +83,7 @@ ZigFn *scope_fn_entry(Scope *scope);...@@ -81,7 +83,7 @@ ZigFn *scope_fn_entry(Scope *scope);
81ImportTableEntry *get_scope_import(Scope *scope);83ImportTableEntry *get_scope_import(Scope *scope);
82void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope);84void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope);
83ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,85ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
84 bool is_const, ConstExprValue *init_value, Tld *src_tld);86 bool is_const, ConstExprValue *init_value, Tld *src_tld, ZigType *var_type);
85ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);87ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);
86ZigFn *create_fn(CodeGen *g, AstNode *proto_node);88ZigFn *create_fn(CodeGen *g, AstNode *proto_node);
87ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);89ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);
...@@ -222,6 +224,13 @@ enum ReqCompTime {...@@ -222,6 +224,13 @@ enum ReqCompTime {
222};224};
223ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry);225ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry);
224226
227enum OnePossibleValue {
228 OnePossibleValueInvalid,
229 OnePossibleValueNo,
230 OnePossibleValueYes,
231};
232OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry);
233
225Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,234Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
226 ConstExprValue *const_val, ZigType *wanted_type);235 ConstExprValue *const_val, ZigType *wanted_type);
227236
src/ast_render.cpp+4-4
...@@ -233,8 +233,8 @@ static const char *node_type_str(NodeType node_type) {...@@ -233,8 +233,8 @@ static const char *node_type_str(NodeType node_type) {
233 return "ErrorType";233 return "ErrorType";
234 case NodeTypeIfErrorExpr:234 case NodeTypeIfErrorExpr:
235 return "IfErrorExpr";235 return "IfErrorExpr";
236 case NodeTypeTestExpr:236 case NodeTypeIfOptional:
237 return "TestExpr";237 return "IfOptional";
238 case NodeTypeErrorSetDecl:238 case NodeTypeErrorSetDecl:
239 return "ErrorSetDecl";239 return "ErrorSetDecl";
240 case NodeTypeCancel:240 case NodeTypeCancel:
...@@ -387,7 +387,7 @@ static bool statement_terminates_without_semicolon(AstNode *node) {...@@ -387,7 +387,7 @@ static bool statement_terminates_without_semicolon(AstNode *node) {
387 if (node->data.if_err_expr.else_node)387 if (node->data.if_err_expr.else_node)
388 return statement_terminates_without_semicolon(node->data.if_err_expr.else_node);388 return statement_terminates_without_semicolon(node->data.if_err_expr.else_node);
389 return node->data.if_err_expr.then_node->type == NodeTypeBlock;389 return node->data.if_err_expr.then_node->type == NodeTypeBlock;
390 case NodeTypeTestExpr:390 case NodeTypeIfOptional:
391 if (node->data.test_expr.else_node)391 if (node->data.test_expr.else_node)
392 return statement_terminates_without_semicolon(node->data.test_expr.else_node);392 return statement_terminates_without_semicolon(node->data.test_expr.else_node);
393 return node->data.test_expr.then_node->type == NodeTypeBlock;393 return node->data.test_expr.then_node->type == NodeTypeBlock;
...@@ -974,7 +974,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -974,7 +974,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
974 }974 }
975 break;975 break;
976 }976 }
977 case NodeTypeTestExpr:977 case NodeTypeIfOptional:
978 {978 {
979 fprintf(ar->f, "if (");979 fprintf(ar->f, "if (");
980 render_node_grouped(ar, node->data.test_expr.target_node);980 render_node_grouped(ar, node->data.test_expr.target_node);
src/cache_hash.cpp+3-13
...@@ -222,14 +222,9 @@ static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf, Buf *contents...@@ -222,14 +222,9 @@ static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf, Buf *contents
222 assert(chf->path != nullptr);222 assert(chf->path != nullptr);
223223
224 OsFile this_file;224 OsFile this_file;
225 if ((err = os_file_open_r(chf->path, &this_file)))225 if ((err = os_file_open_r(chf->path, &this_file, &chf->mtime)))
226 return err;226 return err;
227227
228 if ((err = os_file_mtime(this_file, &chf->mtime))) {
229 os_file_close(this_file);
230 return err;
231 }
232
233 if ((err = hash_file(chf->bin_digest, this_file, contents))) {228 if ((err = hash_file(chf->bin_digest, this_file, contents))) {
234 os_file_close(this_file);229 os_file_close(this_file);
235 return err;230 return err;
...@@ -351,17 +346,12 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {...@@ -351,17 +346,12 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
351346
352 // if the mtime matches we can trust the digest347 // if the mtime matches we can trust the digest
353 OsFile this_file;348 OsFile this_file;
354 if ((err = os_file_open_r(chf->path, &this_file))) {349 OsTimeStamp actual_mtime;
350 if ((err = os_file_open_r(chf->path, &this_file, &actual_mtime))) {
355 fprintf(stderr, "Unable to open %s\n: %s", buf_ptr(chf->path), err_str(err));351 fprintf(stderr, "Unable to open %s\n: %s", buf_ptr(chf->path), err_str(err));
356 os_file_close(ch->manifest_file);352 os_file_close(ch->manifest_file);
357 return ErrorCacheUnavailable;353 return ErrorCacheUnavailable;
358 }354 }
359 OsTimeStamp actual_mtime;
360 if ((err = os_file_mtime(this_file, &actual_mtime))) {
361 os_file_close(this_file);
362 os_file_close(ch->manifest_file);
363 return err;
364 }
365 if (chf->mtime.sec == actual_mtime.sec && chf->mtime.nsec == actual_mtime.nsec) {355 if (chf->mtime.sec == actual_mtime.sec && chf->mtime.nsec == actual_mtime.nsec) {
366 os_file_close(this_file);356 os_file_close(this_file);
367 } else {357 } else {
src/codegen.cpp+396-104
...@@ -118,6 +118,7 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out...@@ -118,6 +118,7 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
118 g->string_literals_table.init(16);118 g->string_literals_table.init(16);
119 g->type_info_cache.init(32);119 g->type_info_cache.init(32);
120 g->is_test_build = false;120 g->is_test_build = false;
121 g->is_single_threaded = false;
121 buf_resize(&g->global_asm, 0);122 buf_resize(&g->global_asm, 0);
122123
123 for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) {124 for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) {
...@@ -313,6 +314,8 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val, const char *...@@ -313,6 +314,8 @@ static void render_const_val(CodeGen *g, ConstExprValue *const_val, const char *
313static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name);314static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name);
314static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name);315static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name);
315static void generate_error_name_table(CodeGen *g);316static void generate_error_name_table(CodeGen *g);
317static bool value_is_all_undef(ConstExprValue *const_val);
318static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr);
316319
317static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) {320static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) {
318 unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));321 unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));
...@@ -461,6 +464,21 @@ static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkag...@@ -461,6 +464,21 @@ static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkag
461 }464 }
462}465}
463466
467static bool cc_want_sret_attr(CallingConvention cc) {
468 switch (cc) {
469 case CallingConventionNaked:
470 zig_unreachable();
471 case CallingConventionC:
472 case CallingConventionCold:
473 case CallingConventionStdcall:
474 return true;
475 case CallingConventionAsync:
476 case CallingConventionUnspecified:
477 return false;
478 }
479 zig_unreachable();
480}
481
464static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {482static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
465 if (fn_table_entry->llvm_value)483 if (fn_table_entry->llvm_value)
466 return fn_table_entry->llvm_value;484 return fn_table_entry->llvm_value;
...@@ -598,9 +616,9 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {...@@ -598,9 +616,9 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
598 } else if (type_is_codegen_pointer(return_type)) {616 } else if (type_is_codegen_pointer(return_type)) {
599 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");617 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
600 } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {618 } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {
601 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
602 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");619 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");
603 if (cc == CallingConventionC) {620 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
621 if (cc_want_sret_attr(cc)) {
604 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias");622 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias");
605 }623 }
606 init_gen_i = 1;624 init_gen_i = 1;
...@@ -1903,9 +1921,8 @@ static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) {...@@ -1903,9 +1921,8 @@ static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) {
1903}1921}
19041922
1905static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) {1923static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) {
1906 assert(alignment > 0);
1907 LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name);1924 LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name);
1908 LLVMSetAlignment(result, alignment);1925 LLVMSetAlignment(result, (alignment == 0) ? get_abi_alignment(g, type_entry) : alignment);
1909 return result;1926 return result;
1910}1927}
19111928
...@@ -1963,7 +1980,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_...@@ -1963,7 +1980,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
1963 break;1980 break;
1964 }1981 }
19651982
1966 if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat ||1983 if (type_is_c_abi_int(g, ty) || ty->id == ZigTypeIdFloat || ty->id == ZigTypeIdVector ||
1967 ty->id == ZigTypeIdInt // TODO investigate if we need to change this1984 ty->id == ZigTypeIdInt // TODO investigate if we need to change this
1968 ) {1985 ) {
1969 switch (fn_walk->id) {1986 switch (fn_walk->id) {
...@@ -2200,10 +2217,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {...@@ -2200,10 +2217,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
2200 assert(variable);2217 assert(variable);
2201 assert(variable->value_ref);2218 assert(variable->value_ref);
22022219
2203 if (!handle_is_ptr(variable->value->type)) {2220 if (!handle_is_ptr(variable->var_type)) {
2204 clear_debug_source_node(g);2221 clear_debug_source_node(g);
2205 gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index), variable->value_ref,2222 gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index),
2206 variable->align_bytes, false);2223 variable->value_ref, variable->align_bytes, false);
2207 }2224 }
22082225
2209 if (variable->decl_node) {2226 if (variable->decl_node) {
...@@ -2643,6 +2660,27 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,...@@ -2643,6 +2660,27 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
2643 } else {2660 } else {
2644 return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, "");2661 return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, "");
2645 }2662 }
2663 } else if (type_entry->id == ZigTypeIdVector) {
2664 ZigType *elem_type = type_entry->data.vector.elem_type;
2665 if (elem_type->id == ZigTypeIdFloat) {
2666 ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base));
2667 return LLVMBuildFAdd(g->builder, op1_value, op2_value, "");
2668 } else if (elem_type->id == ZigTypeIdPointer) {
2669 zig_panic("TODO codegen for pointers in vectors");
2670 } else if (elem_type->id == ZigTypeIdInt) {
2671 bool is_wrapping = (op_id == IrBinOpAddWrap);
2672 if (is_wrapping) {
2673 return LLVMBuildAdd(g->builder, op1_value, op2_value, "");
2674 } else if (want_runtime_safety) {
2675 zig_panic("TODO runtime safety for vector integer addition");
2676 } else if (elem_type->data.integral.is_signed) {
2677 return LLVMBuildNSWAdd(g->builder, op1_value, op2_value, "");
2678 } else {
2679 return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, "");
2680 }
2681 } else {
2682 zig_unreachable();
2683 }
2646 } else {2684 } else {
2647 zig_unreachable();2685 zig_unreachable();
2648 }2686 }
...@@ -2961,7 +2999,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -2961,7 +2999,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
2961}2999}
29623000
2963static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,3001static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
2964 IrInstructionPtrCast *instruction)3002 IrInstructionPtrCastGen *instruction)
2965{3003{
2966 ZigType *wanted_type = instruction->base.value.type;3004 ZigType *wanted_type = instruction->base.value.type;
2967 if (!type_has_bits(wanted_type)) {3005 if (!type_has_bits(wanted_type)) {
...@@ -3149,11 +3187,11 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI...@@ -3149,11 +3187,11 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI
3149}3187}
31503188
3151static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,3189static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
3152 IrInstructionDeclVar *decl_var_instruction)3190 IrInstructionDeclVarGen *decl_var_instruction)
3153{3191{
3154 ZigVar *var = decl_var_instruction->var;3192 ZigVar *var = decl_var_instruction->var;
31553193
3156 if (!type_has_bits(var->value->type))3194 if (!type_has_bits(var->var_type))
3157 return nullptr;3195 return nullptr;
31583196
3159 if (var->ref_count == 0 && g->build_mode != BuildModeDebug)3197 if (var->ref_count == 0 && g->build_mode != BuildModeDebug)
...@@ -3161,34 +3199,16 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,...@@ -3161,34 +3199,16 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
31613199
3162 IrInstruction *init_value = decl_var_instruction->init_value;3200 IrInstruction *init_value = decl_var_instruction->init_value;
31633201
3164 bool have_init_expr = false;3202 bool have_init_expr = !value_is_all_undef(&init_value->value);
3165
3166 ConstExprValue *const_val = &init_value->value;
3167 if (const_val->special == ConstValSpecialRuntime || const_val->special == ConstValSpecialStatic)
3168 have_init_expr = true;
31693203
3170 if (have_init_expr) {3204 if (have_init_expr) {
3171 assert(var->value->type == init_value->value.type);3205 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->var_type, false, false,
3172 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,
3173 PtrLenSingle, var->align_bytes, 0, 0);3206 PtrLenSingle, var->align_bytes, 0, 0);
3174 LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);3207 LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);
3175 gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);3208 gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);
3176 } else {3209 } else if (ir_want_runtime_safety(g, &decl_var_instruction->base)) {
3177 bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);3210 uint32_t align_bytes = (var->align_bytes == 0) ? get_abi_alignment(g, var->var_type) : var->align_bytes;
3178 if (want_safe) {3211 gen_undef_init(g, align_bytes, var->var_type, var->value_ref);
3179 ZigType *usize = g->builtin_types.entry_usize;
3180 uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, var->value->type->type_ref);
3181 assert(size_bytes > 0);
3182
3183 assert(var->align_bytes > 0);
3184
3185 // memset uninitialized memory to 0xa
3186 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
3187 LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
3188 LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, var->value_ref, ptr_u8, "");
3189 LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
3190 ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, var->align_bytes, false);
3191 }
3192 }3212 }
31933213
3194 gen_var_debug_decl(g, var);3214 gen_var_debug_decl(g, var);
...@@ -3225,21 +3245,81 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI...@@ -3225,21 +3245,81 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
3225 return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, "");3245 return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, "");
3226}3246}
32273247
3228static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {3248static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) {
3229 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);3249 switch (const_val->data.x_array.special) {
3230 LLVMValueRef value = ir_llvm_value(g, instruction->value);3250 case ConstArraySpecialUndef:
3251 return true;
3252 case ConstArraySpecialBuf:
3253 return false;
3254 case ConstArraySpecialNone:
3255 for (size_t i = 0; i < len; i += 1) {
3256 if (!value_is_all_undef(&const_val->data.x_array.data.s_none.elements[i]))
3257 return false;
3258 }
3259 return true;
3260 }
3261 zig_unreachable();
3262}
32313263
3232 assert(instruction->ptr->value.type->id == ZigTypeIdPointer);3264static bool value_is_all_undef(ConstExprValue *const_val) {
3233 ZigType *ptr_type = instruction->ptr->value.type;3265 switch (const_val->special) {
3266 case ConstValSpecialRuntime:
3267 return false;
3268 case ConstValSpecialUndef:
3269 return true;
3270 case ConstValSpecialStatic:
3271 if (const_val->type->id == ZigTypeIdStruct) {
3272 for (size_t i = 0; i < const_val->type->data.structure.src_field_count; i += 1) {
3273 if (!value_is_all_undef(&const_val->data.x_struct.fields[i]))
3274 return false;
3275 }
3276 return true;
3277 } else if (const_val->type->id == ZigTypeIdArray) {
3278 return value_is_all_undef_array(const_val, const_val->type->data.array.len);
3279 } else if (const_val->type->id == ZigTypeIdVector) {
3280 return value_is_all_undef_array(const_val, const_val->type->data.vector.len);
3281 } else {
3282 return false;
3283 }
3284 }
3285 zig_unreachable();
3286}
3287
3288static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) {
3289 assert(type_has_bits(value_type));
3290 uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, value_type->type_ref);
3291 assert(size_bytes > 0);
3292 assert(ptr_align_bytes > 0);
3293 // memset uninitialized memory to 0xaa
3294 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
3295 LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
3296 LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, ptr, ptr_u8, "");
3297 ZigType *usize = g->builtin_types.entry_usize;
3298 LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
3299 ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false);
3300}
32343301
3235 gen_assign_raw(g, ptr, ptr_type, value);3302static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {
3303 ZigType *ptr_type = instruction->ptr->value.type;
3304 assert(ptr_type->id == ZigTypeIdPointer);
3305 if (!type_has_bits(ptr_type))
3306 return nullptr;
32363307
3308 bool have_init_expr = !value_is_all_undef(&instruction->value->value);
3309 if (have_init_expr) {
3310 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
3311 LLVMValueRef value = ir_llvm_value(g, instruction->value);
3312 gen_assign_raw(g, ptr, ptr_type, value);
3313 } else if (ir_want_runtime_safety(g, &instruction->base)) {
3314 gen_undef_init(g, get_ptr_align(g, ptr_type), instruction->value->value.type,
3315 ir_llvm_value(g, instruction->ptr));
3316 }
3237 return nullptr;3317 return nullptr;
3238}3318}
32393319
3240static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {3320static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {
3241 ZigVar *var = instruction->var;3321 ZigVar *var = instruction->var;
3242 if (type_has_bits(var->value->type)) {3322 if (type_has_bits(var->var_type)) {
3243 assert(var->value_ref);3323 assert(var->value_ref);
3244 return var->value_ref;3324 return var->value_ref;
3245 } else {3325 } else {
...@@ -3553,7 +3633,8 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab...@@ -3553,7 +3633,8 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
3553 LLVMPositionBuilderAtEnd(g->builder, ok_block);3633 LLVMPositionBuilderAtEnd(g->builder, ok_block);
3554 }3634 }
35553635
3556 LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_union_index, "");3636 LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr,
3637 union_type->data.unionation.gen_union_index, "");
3557 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, "");3638 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, "");
3558 return bitcasted_union_field_ptr;3639 return bitcasted_union_field_ptr;
3559}3640}
...@@ -3715,8 +3796,8 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR...@@ -3715,8 +3796,8 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR
3715 if (child_type->zero_bits) {3796 if (child_type->zero_bits) {
3716 return maybe_handle;3797 return maybe_handle;
3717 } else {3798 } else {
3718 bool maybe_is_ptr = type_is_codegen_pointer(child_type);3799 bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet;
3719 if (maybe_is_ptr) {3800 if (is_scalar) {
3720 return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), "");3801 return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), "");
3721 } else {3802 } else {
3722 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, "");3803 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, "");
...@@ -3731,17 +3812,17 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable...@@ -3731,17 +3812,17 @@ static LLVMValueRef ir_render_test_non_null(CodeGen *g, IrExecutable *executable
3731 return gen_non_null_bit(g, instruction->value->value.type, ir_llvm_value(g, instruction->value));3812 return gen_non_null_bit(g, instruction->value->value.type, ir_llvm_value(g, instruction->value));
3732}3813}
37333814
3734static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,3815static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *executable,
3735 IrInstructionUnwrapOptional *instruction)3816 IrInstructionOptionalUnwrapPtr *instruction)
3736{3817{
3737 ZigType *ptr_type = instruction->value->value.type;3818 ZigType *ptr_type = instruction->base_ptr->value.type;
3738 assert(ptr_type->id == ZigTypeIdPointer);3819 assert(ptr_type->id == ZigTypeIdPointer);
3739 ZigType *maybe_type = ptr_type->data.pointer.child_type;3820 ZigType *maybe_type = ptr_type->data.pointer.child_type;
3740 assert(maybe_type->id == ZigTypeIdOptional);3821 assert(maybe_type->id == ZigTypeIdOptional);
3741 ZigType *child_type = maybe_type->data.maybe.child_type;3822 ZigType *child_type = maybe_type->data.maybe.child_type;
3742 LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value);3823 LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->base_ptr);
3743 LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
3744 if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) {3824 if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on) {
3825 LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
3745 LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);3826 LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);
3746 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");3827 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");
3747 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");3828 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");
...@@ -3755,8 +3836,8 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,...@@ -3755,8 +3836,8 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
3755 if (child_type->zero_bits) {3836 if (child_type->zero_bits) {
3756 return nullptr;3837 return nullptr;
3757 } else {3838 } else {
3758 bool maybe_is_ptr = type_is_codegen_pointer(child_type);3839 bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet;
3759 if (maybe_is_ptr) {3840 if (is_scalar) {
3760 return maybe_ptr;3841 return maybe_ptr;
3761 } else {3842 } else {
3762 LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);3843 LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
...@@ -4174,7 +4255,7 @@ static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed)...@@ -4174,7 +4255,7 @@ static LLVMAtomicRMWBinOp to_LLVMAtomicRMWBinOp(AtomicRmwOp op, bool is_signed)
4174 zig_unreachable();4255 zig_unreachable();
4175}4256}
41764257
4177static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchg *instruction) {4258static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchgGen *instruction) {
4178 LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr);4259 LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr);
4179 LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value);4260 LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value);
4180 LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value);4261 LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value);
...@@ -4189,18 +4270,18 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn...@@ -4189,18 +4270,18 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
4189 assert(maybe_type->id == ZigTypeIdOptional);4270 assert(maybe_type->id == ZigTypeIdOptional);
4190 ZigType *child_type = maybe_type->data.maybe.child_type;4271 ZigType *child_type = maybe_type->data.maybe.child_type;
41914272
4192 if (type_is_codegen_pointer(child_type)) {4273 if (!handle_is_ptr(maybe_type)) {
4193 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");4274 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
4194 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");4275 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
4195 return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(child_type->type_ref), payload_val, "");4276 return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(child_type->type_ref), payload_val, "");
4196 }4277 }
41974278
4198 assert(instruction->tmp_ptr != nullptr);4279 assert(instruction->tmp_ptr != nullptr);
4199 assert(type_has_bits(instruction->type));4280 assert(type_has_bits(child_type));
42004281
4201 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");4282 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
4202 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");4283 LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, maybe_child_index, "");
4203 gen_assign_raw(g, val_ptr, get_pointer_to_type(g, instruction->type, false), payload_val);4284 gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val);
42044285
4205 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");4286 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
4206 LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, "");4287 LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, "");
...@@ -4351,6 +4432,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst...@@ -4351,6 +4432,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
4351 assert(array_type->data.structure.is_slice);4432 assert(array_type->data.structure.is_slice);
4352 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);4433 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
4353 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);4434 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
4435 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind);
43544436
4355 size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index;4437 size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index;
4356 assert(ptr_index != SIZE_MAX);4438 assert(ptr_index != SIZE_MAX);
...@@ -4540,12 +4622,14 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI...@@ -4540,12 +4622,14 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI
4540 return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, "");4622 return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, "");
4541}4623}
45424624
4543static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) {4625static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable,
4544 ZigType *ptr_type = instruction->value->value.type;4626 IrInstructionUnwrapErrCode *instruction)
4627{
4628 ZigType *ptr_type = instruction->err_union->value.type;
4545 assert(ptr_type->id == ZigTypeIdPointer);4629 assert(ptr_type->id == ZigTypeIdPointer);
4546 ZigType *err_union_type = ptr_type->data.pointer.child_type;4630 ZigType *err_union_type = ptr_type->data.pointer.child_type;
4547 ZigType *payload_type = err_union_type->data.error_union.payload_type;4631 ZigType *payload_type = err_union_type->data.error_union.payload_type;
4548 LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->value);4632 LLVMValueRef err_union_ptr = ir_llvm_value(g, instruction->err_union);
4549 LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);4633 LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
45504634
4551 if (type_has_bits(payload_type)) {4635 if (type_has_bits(payload_type)) {
...@@ -4556,7 +4640,13 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab...@@ -4556,7 +4640,13 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab
4556 }4640 }
4557}4641}
45584642
4559static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrPayload *instruction) {4643static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *executable,
4644 IrInstructionUnwrapErrPayload *instruction)
4645{
4646 bool want_safety = ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on &&
4647 g->errors_by_index.length > 1;
4648 if (!want_safety && !type_has_bits(instruction->base.value.type))
4649 return nullptr;
4560 ZigType *ptr_type = instruction->value->value.type;4650 ZigType *ptr_type = instruction->value->value.type;
4561 assert(ptr_type->id == ZigTypeIdPointer);4651 assert(ptr_type->id == ZigTypeIdPointer);
4562 ZigType *err_union_type = ptr_type->data.pointer.child_type;4652 ZigType *err_union_type = ptr_type->data.pointer.child_type;
...@@ -4568,7 +4658,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu...@@ -4568,7 +4658,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu
4568 return err_union_handle;4658 return err_union_handle;
4569 }4659 }
45704660
4571 if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->errors_by_index.length > 1) {4661 if (want_safety) {
4572 LLVMValueRef err_val;4662 LLVMValueRef err_val;
4573 if (type_has_bits(payload_type)) {4663 if (type_has_bits(payload_type)) {
4574 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");4664 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, "");
...@@ -4607,7 +4697,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I...@@ -4607,7 +4697,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I
4607 }4697 }
46084698
4609 LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);4699 LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
4610 if (type_is_codegen_pointer(child_type)) {4700 if (type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet) {
4611 return payload_val;4701 return payload_val;
4612 }4702 }
46134703
...@@ -5109,6 +5199,32 @@ static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutable *executable,...@@ -5109,6 +5199,32 @@ static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutable *executable,
5109 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");5199 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
5110}5200}
51115201
5202static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executable,
5203 IrInstructionVectorToArray *instruction)
5204{
5205 ZigType *array_type = instruction->base.value.type;
5206 assert(array_type->id == ZigTypeIdArray);
5207 assert(handle_is_ptr(array_type));
5208 assert(instruction->tmp_ptr);
5209 LLVMValueRef vector = ir_llvm_value(g, instruction->vector);
5210 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr,
5211 LLVMPointerType(instruction->vector->value.type->type_ref, 0), "");
5212 gen_store_untyped(g, vector, casted_ptr, 0, false);
5213 return instruction->tmp_ptr;
5214}
5215
5216static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executable,
5217 IrInstructionArrayToVector *instruction)
5218{
5219 ZigType *vector_type = instruction->base.value.type;
5220 assert(vector_type->id == ZigTypeIdVector);
5221 assert(!handle_is_ptr(vector_type));
5222 LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array);
5223 LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr,
5224 LLVMPointerType(vector_type->type_ref, 0), "");
5225 return gen_load_untyped(g, casted_ptr, 0, false, "");
5226}
5227
5112static void set_debug_location(CodeGen *g, IrInstruction *instruction) {5228static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
5113 AstNode *source_node = instruction->source_node;5229 AstNode *source_node = instruction->source_node;
5114 Scope *scope = instruction->scope;5230 Scope *scope = instruction->scope;
...@@ -5148,6 +5264,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5148,6 +5264,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5148 case IrInstructionIdCUndef:5264 case IrInstructionIdCUndef:
5149 case IrInstructionIdEmbedFile:5265 case IrInstructionIdEmbedFile:
5150 case IrInstructionIdIntType:5266 case IrInstructionIdIntType:
5267 case IrInstructionIdVectorType:
5151 case IrInstructionIdMemberCount:5268 case IrInstructionIdMemberCount:
5152 case IrInstructionIdMemberType:5269 case IrInstructionIdMemberType:
5153 case IrInstructionIdMemberName:5270 case IrInstructionIdMemberName:
...@@ -5184,12 +5301,15 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5184,12 +5301,15 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5184 case IrInstructionIdToBytes:5301 case IrInstructionIdToBytes:
5185 case IrInstructionIdEnumToInt:5302 case IrInstructionIdEnumToInt:
5186 case IrInstructionIdCheckRuntimeScope:5303 case IrInstructionIdCheckRuntimeScope:
5304 case IrInstructionIdDeclVarSrc:
5305 case IrInstructionIdPtrCastSrc:
5306 case IrInstructionIdCmpxchgSrc:
5187 zig_unreachable();5307 zig_unreachable();
51885308
5309 case IrInstructionIdDeclVarGen:
5310 return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction);
5189 case IrInstructionIdReturn:5311 case IrInstructionIdReturn:
5190 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);5312 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
5191 case IrInstructionIdDeclVar:
5192 return ir_render_decl_var(g, executable, (IrInstructionDeclVar *)instruction);
5193 case IrInstructionIdBinOp:5313 case IrInstructionIdBinOp:
5194 return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);5314 return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);
5195 case IrInstructionIdCast:5315 case IrInstructionIdCast:
...@@ -5220,8 +5340,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5220,8 +5340,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5220 return ir_render_asm(g, executable, (IrInstructionAsm *)instruction);5340 return ir_render_asm(g, executable, (IrInstructionAsm *)instruction);
5221 case IrInstructionIdTestNonNull:5341 case IrInstructionIdTestNonNull:
5222 return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction);5342 return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction);
5223 case IrInstructionIdUnwrapOptional:5343 case IrInstructionIdOptionalUnwrapPtr:
5224 return ir_render_unwrap_maybe(g, executable, (IrInstructionUnwrapOptional *)instruction);5344 return ir_render_optional_unwrap_ptr(g, executable, (IrInstructionOptionalUnwrapPtr *)instruction);
5225 case IrInstructionIdClz:5345 case IrInstructionIdClz:
5226 return ir_render_clz(g, executable, (IrInstructionClz *)instruction);5346 return ir_render_clz(g, executable, (IrInstructionClz *)instruction);
5227 case IrInstructionIdCtz:5347 case IrInstructionIdCtz:
...@@ -5236,8 +5356,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5236,8 +5356,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5236 return ir_render_ref(g, executable, (IrInstructionRef *)instruction);5356 return ir_render_ref(g, executable, (IrInstructionRef *)instruction);
5237 case IrInstructionIdErrName:5357 case IrInstructionIdErrName:
5238 return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction);5358 return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction);
5239 case IrInstructionIdCmpxchg:5359 case IrInstructionIdCmpxchgGen:
5240 return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchg *)instruction);5360 return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchgGen *)instruction);
5241 case IrInstructionIdFence:5361 case IrInstructionIdFence:
5242 return ir_render_fence(g, executable, (IrInstructionFence *)instruction);5362 return ir_render_fence(g, executable, (IrInstructionFence *)instruction);
5243 case IrInstructionIdTruncate:5363 case IrInstructionIdTruncate:
...@@ -5278,8 +5398,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5278,8 +5398,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5278 return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);5398 return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
5279 case IrInstructionIdUnionInit:5399 case IrInstructionIdUnionInit:
5280 return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);5400 return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
5281 case IrInstructionIdPtrCast:5401 case IrInstructionIdPtrCastGen:
5282 return ir_render_ptr_cast(g, executable, (IrInstructionPtrCast *)instruction);5402 return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction);
5283 case IrInstructionIdBitCast:5403 case IrInstructionIdBitCast:
5284 return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction);5404 return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction);
5285 case IrInstructionIdWidenOrShorten:5405 case IrInstructionIdWidenOrShorten:
...@@ -5350,6 +5470,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5350,6 +5470,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5350 return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction);5470 return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction);
5351 case IrInstructionIdBitReverse:5471 case IrInstructionIdBitReverse:
5352 return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction);5472 return ir_render_bit_reverse(g, executable, (IrInstructionBitReverse *)instruction);
5473 case IrInstructionIdArrayToVector:
5474 return ir_render_array_to_vector(g, executable, (IrInstructionArrayToVector *)instruction);
5475 case IrInstructionIdVectorToArray:
5476 return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction);
5353 }5477 }
5354 zig_unreachable();5478 zig_unreachable();
5355}5479}
...@@ -5377,6 +5501,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {...@@ -5377,6 +5501,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
5377static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);5501static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);
5378static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);5502static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);
5379static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val);5503static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val);
5504static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val);
5505static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val);
5506static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val);
53805507
5381static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {5508static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {
5382 switch (parent->id) {5509 switch (parent->id) {
...@@ -5387,6 +5514,12 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent...@@ -5387,6 +5514,12 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
5387 case ConstParentIdStruct:5514 case ConstParentIdStruct:
5388 return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val,5515 return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val,
5389 parent->data.p_struct.field_index);5516 parent->data.p_struct.field_index);
5517 case ConstParentIdErrUnionCode:
5518 return gen_const_ptr_err_union_code_recursive(g, parent->data.p_err_union_code.err_union_val);
5519 case ConstParentIdErrUnionPayload:
5520 return gen_const_ptr_err_union_payload_recursive(g, parent->data.p_err_union_payload.err_union_val);
5521 case ConstParentIdOptionalPayload:
5522 return gen_const_ptr_optional_payload_recursive(g, parent->data.p_optional_payload.optional_val);
5390 case ConstParentIdArray:5523 case ConstParentIdArray:
5391 return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val,5524 return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val,
5392 parent->data.p_array.elem_index);5525 parent->data.p_array.elem_index);
...@@ -5402,7 +5535,7 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent...@@ -5402,7 +5535,7 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
54025535
5403static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) {5536static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) {
5404 expand_undef_array(g, array_const_val);5537 expand_undef_array(g, array_const_val);
5405 ConstParent *parent = &array_const_val->data.x_array.data.s_none.parent;5538 ConstParent *parent = &array_const_val->parent;
5406 LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);5539 LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);
54075540
5408 LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr)));5541 LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr)));
...@@ -5427,7 +5560,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar...@@ -5427,7 +5560,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
5427}5560}
54285561
5429static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) {5562static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) {
5430 ConstParent *parent = &struct_const_val->data.x_struct.parent;5563 ConstParent *parent = &struct_const_val->parent;
5431 LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent);5564 LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent);
54325565
5433 ZigType *u32 = g->builtin_types.entry_u32;5566 ZigType *u32 = g->builtin_types.entry_u32;
...@@ -5438,8 +5571,44 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s...@@ -5438,8 +5571,44 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s
5438 return LLVMConstInBoundsGEP(base_ptr, indices, 2);5571 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
5439}5572}
54405573
5574static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExprValue *err_union_const_val) {
5575 ConstParent *parent = &err_union_const_val->parent;
5576 LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent);
5577
5578 ZigType *u32 = g->builtin_types.entry_u32;
5579 LLVMValueRef indices[] = {
5580 LLVMConstNull(u32->type_ref),
5581 LLVMConstInt(u32->type_ref, err_union_err_index, false),
5582 };
5583 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
5584}
5585
5586static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstExprValue *err_union_const_val) {
5587 ConstParent *parent = &err_union_const_val->parent;
5588 LLVMValueRef base_ptr = gen_parent_ptr(g, err_union_const_val, parent);
5589
5590 ZigType *u32 = g->builtin_types.entry_u32;
5591 LLVMValueRef indices[] = {
5592 LLVMConstNull(u32->type_ref),
5593 LLVMConstInt(u32->type_ref, err_union_payload_index, false),
5594 };
5595 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
5596}
5597
5598static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstExprValue *optional_const_val) {
5599 ConstParent *parent = &optional_const_val->parent;
5600 LLVMValueRef base_ptr = gen_parent_ptr(g, optional_const_val, parent);
5601
5602 ZigType *u32 = g->builtin_types.entry_u32;
5603 LLVMValueRef indices[] = {
5604 LLVMConstNull(u32->type_ref),
5605 LLVMConstInt(u32->type_ref, maybe_child_index, false),
5606 };
5607 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
5608}
5609
5441static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val) {5610static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *union_const_val) {
5442 ConstParent *parent = &union_const_val->data.x_union.parent;5611 ConstParent *parent = &union_const_val->parent;
5443 LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent);5612 LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent);
54445613
5445 ZigType *u32 = g->builtin_types.entry_u32;5614 ZigType *u32 = g->builtin_types.entry_u32;
...@@ -5509,6 +5678,8 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con...@@ -5509,6 +5678,8 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
5509 }5678 }
5510 case ZigTypeIdArray:5679 case ZigTypeIdArray:
5511 zig_panic("TODO bit pack an array");5680 zig_panic("TODO bit pack an array");
5681 case ZigTypeIdVector:
5682 zig_panic("TODO bit pack a vector");
5512 case ZigTypeIdUnion:5683 case ZigTypeIdUnion:
5513 zig_panic("TODO bit pack a union");5684 zig_panic("TODO bit pack a union");
5514 case ZigTypeIdStruct:5685 case ZigTypeIdStruct:
...@@ -5609,6 +5780,63 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con...@@ -5609,6 +5780,63 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
5609 render_const_val_global(g, const_val, "");5780 render_const_val_global(g, const_val, "");
5610 return ptr_val;5781 return ptr_val;
5611 }5782 }
5783 case ConstPtrSpecialBaseErrorUnionCode:
5784 {
5785 render_const_val_global(g, const_val, name);
5786 ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_code.err_union_val;
5787 assert(err_union_const_val->type->id == ZigTypeIdErrorUnion);
5788 if (err_union_const_val->type->zero_bits) {
5789 // make this a null pointer
5790 ZigType *usize = g->builtin_types.entry_usize;
5791 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
5792 const_val->type->type_ref);
5793 render_const_val_global(g, const_val, "");
5794 return const_val->global_refs->llvm_value;
5795 }
5796 LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_code_recursive(g, err_union_const_val);
5797 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
5798 const_val->global_refs->llvm_value = ptr_val;
5799 render_const_val_global(g, const_val, "");
5800 return ptr_val;
5801 }
5802 case ConstPtrSpecialBaseErrorUnionPayload:
5803 {
5804 render_const_val_global(g, const_val, name);
5805 ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_payload.err_union_val;
5806 assert(err_union_const_val->type->id == ZigTypeIdErrorUnion);
5807 if (err_union_const_val->type->zero_bits) {
5808 // make this a null pointer
5809 ZigType *usize = g->builtin_types.entry_usize;
5810 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
5811 const_val->type->type_ref);
5812 render_const_val_global(g, const_val, "");
5813 return const_val->global_refs->llvm_value;
5814 }
5815 LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_payload_recursive(g, err_union_const_val);
5816 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
5817 const_val->global_refs->llvm_value = ptr_val;
5818 render_const_val_global(g, const_val, "");
5819 return ptr_val;
5820 }
5821 case ConstPtrSpecialBaseOptionalPayload:
5822 {
5823 render_const_val_global(g, const_val, name);
5824 ConstExprValue *optional_const_val = const_val->data.x_ptr.data.base_optional_payload.optional_val;
5825 assert(optional_const_val->type->id == ZigTypeIdOptional);
5826 if (optional_const_val->type->zero_bits) {
5827 // make this a null pointer
5828 ZigType *usize = g->builtin_types.entry_usize;
5829 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref),
5830 const_val->type->type_ref);
5831 render_const_val_global(g, const_val, "");
5832 return const_val->global_refs->llvm_value;
5833 }
5834 LLVMValueRef uncasted_ptr_val = gen_const_ptr_optional_payload_recursive(g, optional_const_val);
5835 LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref);
5836 const_val->global_refs->llvm_value = ptr_val;
5837 render_const_val_global(g, const_val, "");
5838 return ptr_val;
5839 }
5612 case ConstPtrSpecialHardCodedAddr:5840 case ConstPtrSpecialHardCodedAddr:
5613 {5841 {
5614 render_const_val_global(g, const_val, name);5842 render_const_val_global(g, const_val, name);
...@@ -5621,10 +5849,17 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con...@@ -5621,10 +5849,17 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
5621 }5849 }
5622 case ConstPtrSpecialFunction:5850 case ConstPtrSpecialFunction:
5623 return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref);5851 return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref);
5852 case ConstPtrSpecialNull:
5853 return LLVMConstNull(const_val->type->type_ref);
5624 }5854 }
5625 zig_unreachable();5855 zig_unreachable();
5626}5856}
56275857
5858static LLVMValueRef gen_const_val_err_set(CodeGen *g, ConstExprValue *const_val, const char *name) {
5859 uint64_t value = (const_val->data.x_err_set == nullptr) ? 0 : const_val->data.x_err_set->value;
5860 return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref, value, false);
5861}
5862
5628static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) {5863static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) {
5629 Error err;5864 Error err;
56305865
...@@ -5644,9 +5879,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5644,9 +5879,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5644 case ZigTypeIdInt:5879 case ZigTypeIdInt:
5645 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);5880 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);
5646 case ZigTypeIdErrorSet:5881 case ZigTypeIdErrorSet:
5647 assert(const_val->data.x_err_set != nullptr);5882 return gen_const_val_err_set(g, const_val, name);
5648 return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref,
5649 const_val->data.x_err_set->value, false);
5650 case ZigTypeIdFloat:5883 case ZigTypeIdFloat:
5651 switch (type_entry->data.floating.bit_count) {5884 switch (type_entry->data.floating.bit_count) {
5652 case 16:5885 case 16:
...@@ -5680,6 +5913,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5680,6 +5913,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5680 return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false);5913 return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false);
5681 } else if (type_is_codegen_pointer(child_type)) {5914 } else if (type_is_codegen_pointer(child_type)) {
5682 return gen_const_val_ptr(g, const_val, name);5915 return gen_const_val_ptr(g, const_val, name);
5916 } else if (child_type->id == ZigTypeIdErrorSet) {
5917 return gen_const_val_err_set(g, const_val, name);
5683 } else {5918 } else {
5684 LLVMValueRef child_val;5919 LLVMValueRef child_val;
5685 LLVMValueRef maybe_val;5920 LLVMValueRef maybe_val;
...@@ -5816,7 +6051,33 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5816,7 +6051,33 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5816 return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf), true);6051 return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf), true);
5817 }6052 }
5818 }6053 }
6054 zig_unreachable();
5819 }6055 }
6056 case ZigTypeIdVector: {
6057 uint32_t len = type_entry->data.vector.len;
6058 switch (const_val->data.x_array.special) {
6059 case ConstArraySpecialUndef:
6060 return LLVMGetUndef(type_entry->type_ref);
6061 case ConstArraySpecialNone: {
6062 LLVMValueRef *values = allocate<LLVMValueRef>(len);
6063 for (uint64_t i = 0; i < len; i += 1) {
6064 ConstExprValue *elem_value = &const_val->data.x_array.data.s_none.elements[i];
6065 values[i] = gen_const_val(g, elem_value, "");
6066 }
6067 return LLVMConstVector(values, len);
6068 }
6069 case ConstArraySpecialBuf: {
6070 Buf *buf = const_val->data.x_array.data.s_buf;
6071 assert(buf_len(buf) == len);
6072 LLVMValueRef *values = allocate<LLVMValueRef>(len);
6073 for (uint64_t i = 0; i < len; i += 1) {
6074 values[i] = LLVMConstInt(g->builtin_types.entry_u8->type_ref, buf_ptr(buf)[i], false);
6075 }
6076 return LLVMConstVector(values, len);
6077 }
6078 }
6079 zig_unreachable();
6080 }
5820 case ZigTypeIdUnion:6081 case ZigTypeIdUnion:
5821 {6082 {
5822 LLVMTypeRef union_type_ref = type_entry->data.unionation.union_type_ref;6083 LLVMTypeRef union_type_ref = type_entry->data.unionation.union_type_ref;
...@@ -5914,7 +6175,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5914,7 +6175,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5914 ZigType *err_set_type = type_entry->data.error_union.err_set_type;6175 ZigType *err_set_type = type_entry->data.error_union.err_set_type;
5915 if (!type_has_bits(payload_type)) {6176 if (!type_has_bits(payload_type)) {
5916 assert(type_has_bits(err_set_type));6177 assert(type_has_bits(err_set_type));
5917 uint64_t value = const_val->data.x_err_union.err ? const_val->data.x_err_union.err->value : 0;6178 ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
6179 uint64_t value = (err_set == nullptr) ? 0 : err_set->value;
5918 return LLVMConstInt(g->err_tag_type->type_ref, value, false);6180 return LLVMConstInt(g->err_tag_type->type_ref, value, false);
5919 } else if (!type_has_bits(err_set_type)) {6181 } else if (!type_has_bits(err_set_type)) {
5920 assert(type_has_bits(payload_type));6182 assert(type_has_bits(payload_type));
...@@ -5923,8 +6185,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5923,8 +6185,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5923 LLVMValueRef err_tag_value;6185 LLVMValueRef err_tag_value;
5924 LLVMValueRef err_payload_value;6186 LLVMValueRef err_payload_value;
5925 bool make_unnamed_struct;6187 bool make_unnamed_struct;
5926 if (const_val->data.x_err_union.err) {6188 ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
5927 err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false);6189 if (err_set != nullptr) {
6190 err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, err_set->value, false);
5928 err_payload_value = LLVMConstNull(payload_type->type_ref);6191 err_payload_value = LLVMConstNull(payload_type->type_ref);
5929 make_unnamed_struct = false;6192 make_unnamed_struct = false;
5930 } else {6193 } else {
...@@ -6130,10 +6393,13 @@ static void do_code_gen(CodeGen *g) {...@@ -6130,10 +6393,13 @@ static void do_code_gen(CodeGen *g) {
6130 TldVar *tld_var = g->global_vars.at(i);6393 TldVar *tld_var = g->global_vars.at(i);
6131 ZigVar *var = tld_var->var;6394 ZigVar *var = tld_var->var;
61326395
6133 if (var->value->type->id == ZigTypeIdComptimeFloat) {6396 if (var->var_type->id == ZigTypeIdComptimeFloat) {
6134 // Generate debug info for it but that's it.6397 // Generate debug info for it but that's it.
6135 ConstExprValue *const_val = var->value;6398 ConstExprValue *const_val = var->const_value;
6136 assert(const_val->special != ConstValSpecialRuntime);6399 assert(const_val->special != ConstValSpecialRuntime);
6400 if (const_val->type != var->var_type) {
6401 zig_panic("TODO debug info for var with ptr casted value");
6402 }
6137 ZigType *var_type = g->builtin_types.entry_f128;6403 ZigType *var_type = g->builtin_types.entry_f128;
6138 ConstExprValue coerced_value;6404 ConstExprValue coerced_value;
6139 coerced_value.special = ConstValSpecialStatic;6405 coerced_value.special = ConstValSpecialStatic;
...@@ -6144,10 +6410,13 @@ static void do_code_gen(CodeGen *g) {...@@ -6144,10 +6410,13 @@ static void do_code_gen(CodeGen *g) {
6144 continue;6410 continue;
6145 }6411 }
61466412
6147 if (var->value->type->id == ZigTypeIdComptimeInt) {6413 if (var->var_type->id == ZigTypeIdComptimeInt) {
6148 // Generate debug info for it but that's it.6414 // Generate debug info for it but that's it.
6149 ConstExprValue *const_val = var->value;6415 ConstExprValue *const_val = var->const_value;
6150 assert(const_val->special != ConstValSpecialRuntime);6416 assert(const_val->special != ConstValSpecialRuntime);
6417 if (const_val->type != var->var_type) {
6418 zig_panic("TODO debug info for var with ptr casted value");
6419 }
6151 size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint);6420 size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint);
6152 if (bits_needed < 8) {6421 if (bits_needed < 8) {
6153 bits_needed = 8;6422 bits_needed = 8;
...@@ -6158,7 +6427,7 @@ static void do_code_gen(CodeGen *g) {...@@ -6158,7 +6427,7 @@ static void do_code_gen(CodeGen *g) {
6158 continue;6427 continue;
6159 }6428 }
61606429
6161 if (!type_has_bits(var->value->type))6430 if (!type_has_bits(var->var_type))
6162 continue;6431 continue;
61636432
6164 assert(var->decl_node);6433 assert(var->decl_node);
...@@ -6167,9 +6436,9 @@ static void do_code_gen(CodeGen *g) {...@@ -6167,9 +6436,9 @@ static void do_code_gen(CodeGen *g) {
6167 if (var->linkage == VarLinkageExternal) {6436 if (var->linkage == VarLinkageExternal) {
6168 LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name));6437 LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name));
6169 if (existing_llvm_var) {6438 if (existing_llvm_var) {
6170 global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->value->type->type_ref, 0));6439 global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->var_type->type_ref, 0));
6171 } else {6440 } else {
6172 global_value = LLVMAddGlobal(g->module, var->value->type->type_ref, buf_ptr(&var->name));6441 global_value = LLVMAddGlobal(g->module, var->var_type->type_ref, buf_ptr(&var->name));
6173 // TODO debug info for the extern variable6442 // TODO debug info for the extern variable
61746443
6175 LLVMSetLinkage(global_value, LLVMExternalLinkage);6444 LLVMSetLinkage(global_value, LLVMExternalLinkage);
...@@ -6180,9 +6449,9 @@ static void do_code_gen(CodeGen *g) {...@@ -6180,9 +6449,9 @@ static void do_code_gen(CodeGen *g) {
6180 } else {6449 } else {
6181 bool exported = (var->linkage == VarLinkageExport);6450 bool exported = (var->linkage == VarLinkageExport);
6182 const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));6451 const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));
6183 render_const_val(g, var->value, mangled_name);6452 render_const_val(g, var->const_value, mangled_name);
6184 render_const_val_global(g, var->value, mangled_name);6453 render_const_val_global(g, var->const_value, mangled_name);
6185 global_value = var->value->global_refs->llvm_global;6454 global_value = var->const_value->global_refs->llvm_global;
61866455
6187 if (exported) {6456 if (exported) {
6188 LLVMSetLinkage(global_value, LLVMExternalLinkage);6457 LLVMSetLinkage(global_value, LLVMExternalLinkage);
...@@ -6194,8 +6463,10 @@ static void do_code_gen(CodeGen *g) {...@@ -6194,8 +6463,10 @@ static void do_code_gen(CodeGen *g) {
6194 LLVMSetAlignment(global_value, var->align_bytes);6463 LLVMSetAlignment(global_value, var->align_bytes);
61956464
6196 // TODO debug info for function pointers6465 // TODO debug info for function pointers
6197 if (var->gen_is_const && var->value->type->id != ZigTypeIdFn) {6466 // Here we use const_value->type because that's the type of the llvm global,
6198 gen_global_var(g, var, var->value->global_refs->llvm_value, var->value->type);6467 // which we const ptr cast upon use to whatever it needs to be.
6468 if (var->gen_is_const && var->const_value->type->id != ZigTypeIdFn) {
6469 gen_global_var(g, var, var->const_value->global_refs->llvm_value, var->const_value->type);
6199 }6470 }
62006471
6201 LLVMSetGlobalConstant(global_value, var->gen_is_const);6472 LLVMSetGlobalConstant(global_value, var->gen_is_const);
...@@ -6249,6 +6520,7 @@ static void do_code_gen(CodeGen *g) {...@@ -6249,6 +6520,7 @@ static void do_code_gen(CodeGen *g) {
6249 IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i);6520 IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i);
6250 LLVMValueRef *slot;6521 LLVMValueRef *slot;
6251 ZigType *slot_type = instruction->value.type;6522 ZigType *slot_type = instruction->value.type;
6523 uint32_t alignment_bytes = 0;
6252 if (instruction->id == IrInstructionIdCast) {6524 if (instruction->id == IrInstructionIdCast) {
6253 IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction;6525 IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction;
6254 slot = &cast_instruction->tmp_ptr;6526 slot = &cast_instruction->tmp_ptr;
...@@ -6281,13 +6553,17 @@ static void do_code_gen(CodeGen *g) {...@@ -6281,13 +6553,17 @@ static void do_code_gen(CodeGen *g) {
6281 } else if (instruction->id == IrInstructionIdErrWrapCode) {6553 } else if (instruction->id == IrInstructionIdErrWrapCode) {
6282 IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;6554 IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
6283 slot = &err_wrap_code_instruction->tmp_ptr;6555 slot = &err_wrap_code_instruction->tmp_ptr;
6284 } else if (instruction->id == IrInstructionIdCmpxchg) {6556 } else if (instruction->id == IrInstructionIdCmpxchgGen) {
6285 IrInstructionCmpxchg *cmpxchg_instruction = (IrInstructionCmpxchg *)instruction;6557 IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;
6286 slot = &cmpxchg_instruction->tmp_ptr;6558 slot = &cmpxchg_instruction->tmp_ptr;
6559 } else if (instruction->id == IrInstructionIdVectorToArray) {
6560 IrInstructionVectorToArray *vector_to_array_instruction = (IrInstructionVectorToArray *)instruction;
6561 alignment_bytes = get_abi_alignment(g, vector_to_array_instruction->vector->value.type);
6562 slot = &vector_to_array_instruction->tmp_ptr;
6287 } else {6563 } else {
6288 zig_unreachable();6564 zig_unreachable();
6289 }6565 }
6290 *slot = build_alloca(g, slot_type, "", get_abi_alignment(g, slot_type));6566 *slot = build_alloca(g, slot_type, "", alignment_bytes);
6291 }6567 }
62926568
6293 ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base);6569 ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base);
...@@ -6304,12 +6580,12 @@ static void do_code_gen(CodeGen *g) {...@@ -6304,12 +6580,12 @@ static void do_code_gen(CodeGen *g) {
6304 for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {6580 for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {
6305 ZigVar *var = fn_table_entry->variable_list.at(var_i);6581 ZigVar *var = fn_table_entry->variable_list.at(var_i);
63066582
6307 if (!type_has_bits(var->value->type)) {6583 if (!type_has_bits(var->var_type)) {
6308 continue;6584 continue;
6309 }6585 }
6310 if (ir_get_var_is_comptime(var))6586 if (ir_get_var_is_comptime(var))
6311 continue;6587 continue;
6312 switch (type_requires_comptime(g, var->value->type)) {6588 switch (type_requires_comptime(g, var->var_type)) {
6313 case ReqCompTimeInvalid:6589 case ReqCompTimeInvalid:
6314 zig_unreachable();6590 zig_unreachable();
6315 case ReqCompTimeYes:6591 case ReqCompTimeYes:
...@@ -6319,11 +6595,11 @@ static void do_code_gen(CodeGen *g) {...@@ -6319,11 +6595,11 @@ static void do_code_gen(CodeGen *g) {
6319 }6595 }
63206596
6321 if (var->src_arg_index == SIZE_MAX) {6597 if (var->src_arg_index == SIZE_MAX) {
6322 var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);6598 var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
63236599
6324 var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),6600 var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
6325 buf_ptr(&var->name), import->di_file, (unsigned)(var->decl_node->line + 1),6601 buf_ptr(&var->name), import->di_file, (unsigned)(var->decl_node->line + 1),
6326 var->value->type->di_type, !g->strip_debug_symbols, 0);6602 var->var_type->di_type, !g->strip_debug_symbols, 0);
63276603
6328 } else if (is_c_abi) {6604 } else if (is_c_abi) {
6329 fn_walk_var.data.vars.var = var;6605 fn_walk_var.data.vars.var = var;
...@@ -6333,16 +6609,16 @@ static void do_code_gen(CodeGen *g) {...@@ -6333,16 +6609,16 @@ static void do_code_gen(CodeGen *g) {
6333 ZigType *gen_type;6609 ZigType *gen_type;
6334 FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index];6610 FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index];
63356611
6336 if (handle_is_ptr(var->value->type)) {6612 if (handle_is_ptr(var->var_type)) {
6337 if (gen_info->is_byval) {6613 if (gen_info->is_byval) {
6338 gen_type = var->value->type;6614 gen_type = var->var_type;
6339 } else {6615 } else {
6340 gen_type = gen_info->type;6616 gen_type = gen_info->type;
6341 }6617 }
6342 var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index);6618 var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index);
6343 } else {6619 } else {
6344 gen_type = var->value->type;6620 gen_type = var->var_type;
6345 var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);6621 var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
6346 }6622 }
6347 if (var->decl_node) {6623 if (var->decl_node) {
6348 var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),6624 var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
...@@ -6742,6 +7018,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -6742,6 +7018,7 @@ static void define_builtin_fns(CodeGen *g) {
6742 create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);7018 create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
6743 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);7019 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
6744 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int7020 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
7021 create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);
6745 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);7022 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);
6746 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);7023 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);
6747 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);7024 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);
...@@ -6967,6 +7244,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -6967,6 +7244,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
6967 " ArgTuple: void,\n"7244 " ArgTuple: void,\n"
6968 " Opaque: void,\n"7245 " Opaque: void,\n"
6969 " Promise: Promise,\n"7246 " Promise: Promise,\n"
7247 " Vector: Vector,\n"
6970 "\n\n"7248 "\n\n"
6971 " pub const Int = struct {\n"7249 " pub const Int = struct {\n"
6972 " is_signed: bool,\n"7250 " is_signed: bool,\n"
...@@ -7085,6 +7363,11 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -7085,6 +7363,11 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
7085 " child: ?type,\n"7363 " child: ?type,\n"
7086 " };\n"7364 " };\n"
7087 "\n"7365 "\n"
7366 " pub const Vector = struct {\n"
7367 " len: u32,\n"
7368 " child: type,\n"
7369 " };\n"
7370 "\n"
7088 " pub const Definition = struct {\n"7371 " pub const Definition = struct {\n"
7089 " name: []const u8,\n"7372 " name: []const u8,\n"
7090 " is_pub: bool,\n"7373 " is_pub: bool,\n"
...@@ -7153,6 +7436,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -7153,6 +7436,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
7153 buf_appendf(contents, "pub const endian = %s;\n", endian_str);7436 buf_appendf(contents, "pub const endian = %s;\n", endian_str);
7154 }7437 }
7155 buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build));7438 buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build));
7439 buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));
7156 buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);7440 buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);
7157 buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);7441 buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);
7158 buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ);7442 buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ);
...@@ -7187,6 +7471,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {...@@ -7187,6 +7471,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
7187 cache_buf(&cache_hash, compiler_id);7471 cache_buf(&cache_hash, compiler_id);
7188 cache_int(&cache_hash, g->build_mode);7472 cache_int(&cache_hash, g->build_mode);
7189 cache_bool(&cache_hash, g->is_test_build);7473 cache_bool(&cache_hash, g->is_test_build);
7474 cache_bool(&cache_hash, g->is_single_threaded);
7190 cache_int(&cache_hash, g->zig_target.arch.arch);7475 cache_int(&cache_hash, g->zig_target.arch.arch);
7191 cache_int(&cache_hash, g->zig_target.arch.sub_arch);7476 cache_int(&cache_hash, g->zig_target.arch.sub_arch);
7192 cache_int(&cache_hash, g->zig_target.vendor);7477 cache_int(&cache_hash, g->zig_target.vendor);
...@@ -7458,9 +7743,9 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {...@@ -7458,9 +7743,9 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
7458 ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i];7743 ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i];
7459 this_val->special = ConstValSpecialStatic;7744 this_val->special = ConstValSpecialStatic;
7460 this_val->type = struct_type;7745 this_val->type = struct_type;
7461 this_val->data.x_struct.parent.id = ConstParentIdArray;7746 this_val->parent.id = ConstParentIdArray;
7462 this_val->data.x_struct.parent.data.p_array.array_val = test_fn_array;7747 this_val->parent.data.p_array.array_val = test_fn_array;
7463 this_val->data.x_struct.parent.data.p_array.elem_index = i;7748 this_val->parent.data.p_array.elem_index = i;
7464 this_val->data.x_struct.fields = create_const_vals(2);7749 this_val->data.x_struct.fields = create_const_vals(2);
74657750
7466 ConstExprValue *name_field = &this_val->data.x_struct.fields[0];7751 ConstExprValue *name_field = &this_val->data.x_struct.fields[0];
...@@ -7656,6 +7941,9 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e...@@ -7656,6 +7941,9 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e
7656 case ZigTypeIdArray:7941 case ZigTypeIdArray:
7657 prepend_c_type_to_decl_list(g, gen_h, type_entry->data.array.child_type);7942 prepend_c_type_to_decl_list(g, gen_h, type_entry->data.array.child_type);
7658 return;7943 return;
7944 case ZigTypeIdVector:
7945 prepend_c_type_to_decl_list(g, gen_h, type_entry->data.vector.elem_type);
7946 return;
7659 case ZigTypeIdOptional:7947 case ZigTypeIdOptional:
7660 prepend_c_type_to_decl_list(g, gen_h, type_entry->data.maybe.child_type);7948 prepend_c_type_to_decl_list(g, gen_h, type_entry->data.maybe.child_type);
7661 return;7949 return;
...@@ -7787,6 +8075,8 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu...@@ -7787,6 +8075,8 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu
7787 buf_appendf(out_buf, "%s", buf_ptr(child_buf));8075 buf_appendf(out_buf, "%s", buf_ptr(child_buf));
7788 return;8076 return;
7789 }8077 }
8078 case ZigTypeIdVector:
8079 zig_panic("TODO implement get_c_type for vector types");
7790 case ZigTypeIdErrorUnion:8080 case ZigTypeIdErrorUnion:
7791 case ZigTypeIdErrorSet:8081 case ZigTypeIdErrorSet:
7792 case ZigTypeIdFn:8082 case ZigTypeIdFn:
...@@ -7952,6 +8242,7 @@ static void gen_h_file(CodeGen *g) {...@@ -7952,6 +8242,7 @@ static void gen_h_file(CodeGen *g) {
7952 case ZigTypeIdOptional:8242 case ZigTypeIdOptional:
7953 case ZigTypeIdFn:8243 case ZigTypeIdFn:
7954 case ZigTypeIdPromise:8244 case ZigTypeIdPromise:
8245 case ZigTypeIdVector:
7955 zig_unreachable();8246 zig_unreachable();
7956 case ZigTypeIdEnum:8247 case ZigTypeIdEnum:
7957 if (type_entry->data.enumeration.layout == ContainerLayoutExtern) {8248 if (type_entry->data.enumeration.layout == ContainerLayoutExtern) {
...@@ -8099,6 +8390,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {...@@ -8099,6 +8390,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
8099 cache_bool(ch, g->is_static);8390 cache_bool(ch, g->is_static);
8100 cache_bool(ch, g->strip_debug_symbols);8391 cache_bool(ch, g->strip_debug_symbols);
8101 cache_bool(ch, g->is_test_build);8392 cache_bool(ch, g->is_test_build);
8393 cache_bool(ch, g->is_single_threaded);
8102 cache_bool(ch, g->is_native_target);8394 cache_bool(ch, g->is_native_target);
8103 cache_bool(ch, g->linker_rdynamic);8395 cache_bool(ch, g->linker_rdynamic);
8104 cache_bool(ch, g->no_rosegment_workaround);8396 cache_bool(ch, g->no_rosegment_workaround);
src/ir.cpp+1228-834
...@@ -167,6 +167,8 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -167,6 +167,8 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
167 ZigType *dest_type, IrInstruction *dest_type_src);167 ZigType *dest_type, IrInstruction *dest_type_src);
168static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);168static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
169static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);169static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
170static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
171static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry);
170172
171static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {173static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
172 assert(get_src_ptr_type(const_val->type) != nullptr);174 assert(get_src_ptr_type(const_val->type) != nullptr);
...@@ -178,15 +180,28 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c...@@ -178,15 +180,28 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
178 case ConstPtrSpecialRef:180 case ConstPtrSpecialRef:
179 result = const_val->data.x_ptr.data.ref.pointee;181 result = const_val->data.x_ptr.data.ref.pointee;
180 break;182 break;
181 case ConstPtrSpecialBaseArray:183 case ConstPtrSpecialBaseArray: {
182 expand_undef_array(g, const_val->data.x_ptr.data.base_array.array_val);184 ConstExprValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
183 result = &const_val->data.x_ptr.data.base_array.array_val->data.x_array.data.s_none.elements[185 expand_undef_array(g, array_val);
184 const_val->data.x_ptr.data.base_array.elem_index];186 result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];
185 break;187 break;
188 }
186 case ConstPtrSpecialBaseStruct:189 case ConstPtrSpecialBaseStruct:
187 result = &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[190 result = &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[
188 const_val->data.x_ptr.data.base_struct.field_index];191 const_val->data.x_ptr.data.base_struct.field_index];
189 break;192 break;
193 case ConstPtrSpecialBaseErrorUnionCode:
194 result = const_val->data.x_ptr.data.base_err_union_code.err_union_val->data.x_err_union.error_set;
195 break;
196 case ConstPtrSpecialBaseErrorUnionPayload:
197 result = const_val->data.x_ptr.data.base_err_union_payload.err_union_val->data.x_err_union.payload;
198 break;
199 case ConstPtrSpecialBaseOptionalPayload:
200 result = const_val->data.x_ptr.data.base_optional_payload.optional_val->data.x_optional;
201 break;
202 case ConstPtrSpecialNull:
203 result = const_val;
204 break;
190 case ConstPtrSpecialHardCodedAddr:205 case ConstPtrSpecialHardCodedAddr:
191 zig_unreachable();206 zig_unreachable();
192 case ConstPtrSpecialDiscard:207 case ConstPtrSpecialDiscard:
...@@ -198,6 +213,11 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c...@@ -198,6 +213,11 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
198 return result;213 return result;
199}214}
200215
216static bool is_opt_err_set(ZigType *ty) {
217 return ty->id == ZigTypeIdErrorSet ||
218 (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);
219}
220
201static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {221static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
202 if (a == b)222 if (a == b)
203 return true;223 return true;
...@@ -208,15 +228,10 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {...@@ -208,15 +228,10 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
208 if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr)228 if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr)
209 return true;229 return true;
210230
211 return false;231 if (is_opt_err_set(a) && is_opt_err_set(b))
212}232 return true;
213233
214ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {234 return false;
215 ConstExprValue *result = const_ptr_pointee_unchecked(g, const_val);
216 if (const_val->type->id == ZigTypeIdPointer) {
217 assert(types_have_same_zig_comptime_repr(const_val->type->data.pointer.child_type, result->type));
218 }
219 return result;
220}235}
221236
222static bool ir_should_inline(IrExecutable *exec, Scope *scope) {237static bool ir_should_inline(IrExecutable *exec, Scope *scope) {
...@@ -305,6 +320,14 @@ static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) {...@@ -305,6 +320,14 @@ static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) {
305 return new_bb;320 return new_bb;
306}321}
307322
323static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVarSrc *) {
324 return IrInstructionIdDeclVarSrc;
325}
326
327static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVarGen *) {
328 return IrInstructionIdDeclVarGen;
329}
330
308static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) {331static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) {
309 return IrInstructionIdCondBr;332 return IrInstructionIdCondBr;
310}333}
...@@ -337,10 +360,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) {...@@ -337,10 +360,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) {
337 return IrInstructionIdBinOp;360 return IrInstructionIdBinOp;
338}361}
339362
340static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVar *) {
341 return IrInstructionIdDeclVar;
342}
343
344static constexpr IrInstructionId ir_instruction_id(IrInstructionExport *) {363static constexpr IrInstructionId ir_instruction_id(IrInstructionExport *) {
345 return IrInstructionIdExport;364 return IrInstructionIdExport;
346}365}
...@@ -449,8 +468,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestNonNull *) {...@@ -449,8 +468,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestNonNull *) {
449 return IrInstructionIdTestNonNull;468 return IrInstructionIdTestNonNull;
450}469}
451470
452static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapOptional *) {471static constexpr IrInstructionId ir_instruction_id(IrInstructionOptionalUnwrapPtr *) {
453 return IrInstructionIdUnwrapOptional;472 return IrInstructionIdOptionalUnwrapPtr;
454}473}
455474
456static constexpr IrInstructionId ir_instruction_id(IrInstructionClz *) {475static constexpr IrInstructionId ir_instruction_id(IrInstructionClz *) {
...@@ -517,8 +536,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) {...@@ -517,8 +536,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) {
517 return IrInstructionIdEmbedFile;536 return IrInstructionIdEmbedFile;
518}537}
519538
520static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchg *) {539static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgSrc *) {
521 return IrInstructionIdCmpxchg;540 return IrInstructionIdCmpxchgSrc;
541}
542
543static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgGen *) {
544 return IrInstructionIdCmpxchgGen;
522}545}
523546
524static constexpr IrInstructionId ir_instruction_id(IrInstructionFence *) {547static constexpr IrInstructionId ir_instruction_id(IrInstructionFence *) {
...@@ -565,6 +588,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionIntType *) {...@@ -565,6 +588,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionIntType *) {
565 return IrInstructionIdIntType;588 return IrInstructionIdIntType;
566}589}
567590
591static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorType *) {
592 return IrInstructionIdVectorType;
593}
594
568static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) {595static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) {
569 return IrInstructionIdBoolNot;596 return IrInstructionIdBoolNot;
570}597}
...@@ -649,8 +676,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *)...@@ -649,8 +676,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *)
649 return IrInstructionIdTestComptime;676 return IrInstructionIdTestComptime;
650}677}
651678
652static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) {679static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastSrc *) {
653 return IrInstructionIdPtrCast;680 return IrInstructionIdPtrCastSrc;
681}
682
683static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastGen *) {
684 return IrInstructionIdPtrCastGen;
654}685}
655686
656static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {687static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {
...@@ -869,6 +900,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScop...@@ -869,6 +900,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScop
869 return IrInstructionIdCheckRuntimeScope;900 return IrInstructionIdCheckRuntimeScope;
870}901}
871902
903static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorToArray *) {
904 return IrInstructionIdVectorToArray;
905}
906
907static constexpr IrInstructionId ir_instruction_id(IrInstructionArrayToVector *) {
908 return IrInstructionIdArrayToVector;
909}
910
872template<typename T>911template<typename T>
873static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {912static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
874 T *special_instruction = allocate<T>(1);913 T *special_instruction = allocate<T>(1);
...@@ -915,7 +954,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so...@@ -915,7 +954,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so
915 ir_ref_instruction(condition, irb->current_basic_block);954 ir_ref_instruction(condition, irb->current_basic_block);
916 ir_ref_bb(then_block);955 ir_ref_bb(then_block);
917 ir_ref_bb(else_block);956 ir_ref_bb(else_block);
918 if (is_comptime) ir_ref_instruction(is_comptime, irb->current_basic_block);957 if (is_comptime != nullptr) ir_ref_instruction(is_comptime, irb->current_basic_block);
919958
920 return &cond_br_instruction->base;959 return &cond_br_instruction->base;
921}960}
...@@ -931,16 +970,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou...@@ -931,16 +970,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou
931 return &return_instruction->base;970 return &return_instruction->base;
932}971}
933972
934static IrInstruction *ir_create_const(IrBuilder *irb, Scope *scope, AstNode *source_node,
935 ZigType *type_entry)
936{
937 assert(type_entry);
938 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb, scope, source_node);
939 const_instruction->base.value.type = type_entry;
940 const_instruction->base.value.special = ConstValSpecialStatic;
941 return &const_instruction->base;
942}
943
944static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) {973static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) {
945 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);974 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
946 const_instruction->base.value.type = irb->codegen->builtin_types.entry_void;975 const_instruction->base.value.type = irb->codegen->builtin_types.entry_void;
...@@ -1188,14 +1217,11 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc...@@ -1188,14 +1217,11 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc
1188 call_instruction->async_allocator = async_allocator;1217 call_instruction->async_allocator = async_allocator;
1189 call_instruction->new_stack = new_stack;1218 call_instruction->new_stack = new_stack;
11901219
1191 if (fn_ref)1220 if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block);
1192 ir_ref_instruction(fn_ref, irb->current_basic_block);
1193 for (size_t i = 0; i < arg_count; i += 1)1221 for (size_t i = 0; i < arg_count; i += 1)
1194 ir_ref_instruction(args[i], irb->current_basic_block);1222 ir_ref_instruction(args[i], irb->current_basic_block);
1195 if (async_allocator)1223 if (async_allocator != nullptr) ir_ref_instruction(async_allocator, irb->current_basic_block);
1196 ir_ref_instruction(async_allocator, irb->current_basic_block);1224 if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block);
1197 if (new_stack != nullptr)
1198 ir_ref_instruction(new_stack, irb->current_basic_block);
11991225
1200 return &call_instruction->base;1226 return &call_instruction->base;
1201}1227}
...@@ -1280,7 +1306,7 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope,...@@ -1280,7 +1306,7 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope,
1280 container_init_list_instruction->item_count = item_count;1306 container_init_list_instruction->item_count = item_count;
1281 container_init_list_instruction->items = items;1307 container_init_list_instruction->items = items;
12821308
1283 ir_ref_instruction(container_type, irb->current_basic_block);1309 if (container_type != nullptr) ir_ref_instruction(container_type, irb->current_basic_block);
1284 for (size_t i = 0; i < item_count; i += 1) {1310 for (size_t i = 0; i < item_count; i += 1) {
1285 ir_ref_instruction(items[i], irb->current_basic_block);1311 ir_ref_instruction(items[i], irb->current_basic_block);
1286 }1312 }
...@@ -1355,10 +1381,10 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *...@@ -1355,10 +1381,10 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *
1355 return &instruction->base;1381 return &instruction->base;
1356}1382}
13571383
1358static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *source_node,1384static IrInstruction *ir_build_var_decl_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
1359 ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value)1385 ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value)
1360{1386{
1361 IrInstructionDeclVar *decl_var_instruction = ir_build_instruction<IrInstructionDeclVar>(irb, scope, source_node);1387 IrInstructionDeclVarSrc *decl_var_instruction = ir_build_instruction<IrInstructionDeclVarSrc>(irb, scope, source_node);
1362 decl_var_instruction->base.value.special = ConstValSpecialStatic;1388 decl_var_instruction->base.value.special = ConstValSpecialStatic;
1363 decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void;1389 decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void;
1364 decl_var_instruction->var = var;1390 decl_var_instruction->var = var;
...@@ -1366,13 +1392,28 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1366,13 +1392,28 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *s
1366 decl_var_instruction->align_value = align_value;1392 decl_var_instruction->align_value = align_value;
1367 decl_var_instruction->init_value = init_value;1393 decl_var_instruction->init_value = init_value;
13681394
1369 if (var_type) ir_ref_instruction(var_type, irb->current_basic_block);1395 if (var_type != nullptr) ir_ref_instruction(var_type, irb->current_basic_block);
1370 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);1396 if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block);
1371 ir_ref_instruction(init_value, irb->current_basic_block);1397 ir_ref_instruction(init_value, irb->current_basic_block);
13721398
1373 return &decl_var_instruction->base;1399 return &decl_var_instruction->base;
1374}1400}
13751401
1402static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *source_instruction,
1403 ZigVar *var, IrInstruction *init_value)
1404{
1405 IrInstructionDeclVarGen *decl_var_instruction = ir_build_instruction<IrInstructionDeclVarGen>(&ira->new_irb,
1406 source_instruction->scope, source_instruction->source_node);
1407 decl_var_instruction->base.value.special = ConstValSpecialStatic;
1408 decl_var_instruction->base.value.type = ira->codegen->builtin_types.entry_void;
1409 decl_var_instruction->var = var;
1410 decl_var_instruction->init_value = init_value;
1411
1412 ir_ref_instruction(init_value, ira->new_irb.current_basic_block);
1413
1414 return &decl_var_instruction->base;
1415}
1416
1376static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node,1417static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node,
1377 IrInstruction *name, IrInstruction *target, IrInstruction *linkage)1418 IrInstruction *name, IrInstruction *target, IrInstruction *linkage)
1378{1419{
...@@ -1542,14 +1583,14 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod...@@ -1542,14 +1583,14 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod
1542 return &instruction->base;1583 return &instruction->base;
1543}1584}
15441585
1545static IrInstruction *ir_build_unwrap_maybe(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value,1586static IrInstruction *ir_build_optional_unwrap_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
1546 bool safety_check_on)1587 IrInstruction *base_ptr, bool safety_check_on)
1547{1588{
1548 IrInstructionUnwrapOptional *instruction = ir_build_instruction<IrInstructionUnwrapOptional>(irb, scope, source_node);1589 IrInstructionOptionalUnwrapPtr *instruction = ir_build_instruction<IrInstructionOptionalUnwrapPtr>(irb, scope, source_node);
1549 instruction->value = value;1590 instruction->base_ptr = base_ptr;
1550 instruction->safety_check_on = safety_check_on;1591 instruction->safety_check_on = safety_check_on;
15511592
1552 ir_ref_instruction(value, irb->current_basic_block);1593 ir_ref_instruction(base_ptr, irb->current_basic_block);
15531594
1554 return &instruction->base;1595 return &instruction->base;
1555}1596}
...@@ -1765,13 +1806,12 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode...@@ -1765,13 +1806,12 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode
1765 return &instruction->base;1806 return &instruction->base;
1766}1807}
17671808
1768static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value,1809static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
1769 IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,1810 IrInstruction *type_value, IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
1770 IrInstruction *success_order_value, IrInstruction *failure_order_value,1811 IrInstruction *success_order_value, IrInstruction *failure_order_value,
1771 bool is_weak,1812 bool is_weak)
1772 ZigType *type, AtomicOrder success_order, AtomicOrder failure_order)
1773{1813{
1774 IrInstructionCmpxchg *instruction = ir_build_instruction<IrInstructionCmpxchg>(irb, scope, source_node);1814 IrInstructionCmpxchgSrc *instruction = ir_build_instruction<IrInstructionCmpxchgSrc>(irb, scope, source_node);
1775 instruction->type_value = type_value;1815 instruction->type_value = type_value;
1776 instruction->ptr = ptr;1816 instruction->ptr = ptr;
1777 instruction->cmp_value = cmp_value;1817 instruction->cmp_value = cmp_value;
...@@ -1779,16 +1819,33 @@ static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *so...@@ -1779,16 +1819,33 @@ static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *so
1779 instruction->success_order_value = success_order_value;1819 instruction->success_order_value = success_order_value;
1780 instruction->failure_order_value = failure_order_value;1820 instruction->failure_order_value = failure_order_value;
1781 instruction->is_weak = is_weak;1821 instruction->is_weak = is_weak;
1782 instruction->type = type;
1783 instruction->success_order = success_order;
1784 instruction->failure_order = failure_order;
17851822
1786 if (type_value != nullptr) ir_ref_instruction(type_value, irb->current_basic_block);1823 ir_ref_instruction(type_value, irb->current_basic_block);
1787 ir_ref_instruction(ptr, irb->current_basic_block);1824 ir_ref_instruction(ptr, irb->current_basic_block);
1788 ir_ref_instruction(cmp_value, irb->current_basic_block);1825 ir_ref_instruction(cmp_value, irb->current_basic_block);
1789 ir_ref_instruction(new_value, irb->current_basic_block);1826 ir_ref_instruction(new_value, irb->current_basic_block);
1790 if (type_value != nullptr) ir_ref_instruction(success_order_value, irb->current_basic_block);1827 ir_ref_instruction(success_order_value, irb->current_basic_block);
1791 if (type_value != nullptr) ir_ref_instruction(failure_order_value, irb->current_basic_block);1828 ir_ref_instruction(failure_order_value, irb->current_basic_block);
1829
1830 return &instruction->base;
1831}
1832
1833static IrInstruction *ir_build_cmpxchg_gen(IrAnalyze *ira, IrInstruction *source_instruction,
1834 IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
1835 AtomicOrder success_order, AtomicOrder failure_order, bool is_weak)
1836{
1837 IrInstructionCmpxchgGen *instruction = ir_build_instruction<IrInstructionCmpxchgGen>(&ira->new_irb,
1838 source_instruction->scope, source_instruction->source_node);
1839 instruction->ptr = ptr;
1840 instruction->cmp_value = cmp_value;
1841 instruction->new_value = new_value;
1842 instruction->success_order = success_order;
1843 instruction->failure_order = failure_order;
1844 instruction->is_weak = is_weak;
1845
1846 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
1847 ir_ref_instruction(cmp_value, ira->new_irb.current_basic_block);
1848 ir_ref_instruction(new_value, ira->new_irb.current_basic_block);
17921849
1793 return &instruction->base;1850 return &instruction->base;
1794}1851}
...@@ -1909,6 +1966,19 @@ static IrInstruction *ir_build_int_type(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1909,6 +1966,19 @@ static IrInstruction *ir_build_int_type(IrBuilder *irb, Scope *scope, AstNode *s
1909 return &instruction->base;1966 return &instruction->base;
1910}1967}
19111968
1969static IrInstruction *ir_build_vector_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *len,
1970 IrInstruction *elem_type)
1971{
1972 IrInstructionVectorType *instruction = ir_build_instruction<IrInstructionVectorType>(irb, scope, source_node);
1973 instruction->len = len;
1974 instruction->elem_type = elem_type;
1975
1976 ir_ref_instruction(len, irb->current_basic_block);
1977 ir_ref_instruction(elem_type, irb->current_basic_block);
1978
1979 return &instruction->base;
1980}
1981
1912static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {1982static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
1913 IrInstructionBoolNot *instruction = ir_build_instruction<IrInstructionBoolNot>(irb, scope, source_node);1983 IrInstructionBoolNot *instruction = ir_build_instruction<IrInstructionBoolNot>(irb, scope, source_node);
1914 instruction->value = value;1984 instruction->value = value;
...@@ -2060,12 +2130,12 @@ static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *s...@@ -2060,12 +2130,12 @@ static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *s
2060}2130}
20612131
2062static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node,2132static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node,
2063 IrInstruction *value)2133 IrInstruction *err_union)
2064{2134{
2065 IrInstructionUnwrapErrCode *instruction = ir_build_instruction<IrInstructionUnwrapErrCode>(irb, scope, source_node);2135 IrInstructionUnwrapErrCode *instruction = ir_build_instruction<IrInstructionUnwrapErrCode>(irb, scope, source_node);
2066 instruction->value = value;2136 instruction->err_union = err_union;
20672137
2068 ir_ref_instruction(value, irb->current_basic_block);2138 ir_ref_instruction(err_union, irb->current_basic_block);
20692139
2070 return &instruction->base;2140 return &instruction->base;
2071}2141}
...@@ -2115,20 +2185,33 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo...@@ -2115,20 +2185,33 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo
2115 return &instruction->base;2185 return &instruction->base;
2116}2186}
21172187
2118static IrInstruction *ir_build_ptr_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,2188static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
2119 IrInstruction *dest_type, IrInstruction *ptr)2189 IrInstruction *dest_type, IrInstruction *ptr)
2120{2190{
2121 IrInstructionPtrCast *instruction = ir_build_instruction<IrInstructionPtrCast>(2191 IrInstructionPtrCastSrc *instruction = ir_build_instruction<IrInstructionPtrCastSrc>(
2122 irb, scope, source_node);2192 irb, scope, source_node);
2123 instruction->dest_type = dest_type;2193 instruction->dest_type = dest_type;
2124 instruction->ptr = ptr;2194 instruction->ptr = ptr;
21252195
2126 if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block);2196 ir_ref_instruction(dest_type, irb->current_basic_block);
2127 ir_ref_instruction(ptr, irb->current_basic_block);2197 ir_ref_instruction(ptr, irb->current_basic_block);
21282198
2129 return &instruction->base;2199 return &instruction->base;
2130}2200}
21312201
2202static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction,
2203 ZigType *ptr_type, IrInstruction *ptr)
2204{
2205 IrInstructionPtrCastGen *instruction = ir_build_instruction<IrInstructionPtrCastGen>(
2206 &ira->new_irb, source_instruction->scope, source_instruction->source_node);
2207 instruction->base.value.type = ptr_type;
2208 instruction->ptr = ptr;
2209
2210 ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
2211
2212 return &instruction->base;
2213}
2214
2132static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,2215static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
2133 IrInstruction *dest_type, IrInstruction *value)2216 IrInstruction *dest_type, IrInstruction *value)
2134{2217{
...@@ -2747,6 +2830,34 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope,...@@ -2747,6 +2830,34 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope,
2747 return &instruction->base;2830 return &instruction->base;
2748}2831}
27492832
2833static IrInstruction *ir_build_vector_to_array(IrAnalyze *ira, IrInstruction *source_instruction,
2834 IrInstruction *vector, ZigType *result_type)
2835{
2836 IrInstructionVectorToArray *instruction = ir_build_instruction<IrInstructionVectorToArray>(&ira->new_irb,
2837 source_instruction->scope, source_instruction->source_node);
2838 instruction->base.value.type = result_type;
2839 instruction->vector = vector;
2840
2841 ir_ref_instruction(vector, ira->new_irb.current_basic_block);
2842
2843 ir_add_alloca(ira, &instruction->base, result_type);
2844
2845 return &instruction->base;
2846}
2847
2848static IrInstruction *ir_build_array_to_vector(IrAnalyze *ira, IrInstruction *source_instruction,
2849 IrInstruction *array, ZigType *result_type)
2850{
2851 IrInstructionArrayToVector *instruction = ir_build_instruction<IrInstructionArrayToVector>(&ira->new_irb,
2852 source_instruction->scope, source_instruction->source_node);
2853 instruction->base.value.type = result_type;
2854 instruction->array = array;
2855
2856 ir_ref_instruction(array, ira->new_irb.current_basic_block);
2857
2858 return &instruction->base;
2859}
2860
2750static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {2861static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
2751 results[ReturnKindUnconditional] = 0;2862 results[ReturnKindUnconditional] = 0;
2752 results[ReturnKindError] = 0;2863 results[ReturnKindError] = 0;
...@@ -2807,10 +2918,13 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o...@@ -2807,10 +2918,13 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o
2807 Scope *defer_expr_scope = defer_node->data.defer.expr_scope;2918 Scope *defer_expr_scope = defer_node->data.defer.expr_scope;
2808 IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);2919 IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);
2809 if (defer_expr_value != irb->codegen->invalid_instruction) {2920 if (defer_expr_value != irb->codegen->invalid_instruction) {
2810 if (defer_expr_value->value.type != nullptr && defer_expr_value->value.type->id == ZigTypeIdUnreachable) {2921 if (defer_expr_value->value.type != nullptr &&
2922 defer_expr_value->value.type->id == ZigTypeIdUnreachable)
2923 {
2811 is_noreturn = true;2924 is_noreturn = true;
2812 } else {2925 } else {
2813 ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, defer_expr_value));2926 ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node,
2927 defer_expr_value));
2814 }2928 }
2815 }2929 }
2816 }2930 }
...@@ -3065,7 +3179,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s...@@ -3065,7 +3179,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
3065 variable_entry->mem_slot_index = SIZE_MAX;3179 variable_entry->mem_slot_index = SIZE_MAX;
3066 variable_entry->is_comptime = is_comptime;3180 variable_entry->is_comptime = is_comptime;
3067 variable_entry->src_arg_index = SIZE_MAX;3181 variable_entry->src_arg_index = SIZE_MAX;
3068 variable_entry->value = create_const_vals(1);3182 variable_entry->const_value = create_const_vals(1);
30693183
3070 if (is_comptime != nullptr) {3184 if (is_comptime != nullptr) {
3071 is_comptime->ref_count += 1;3185 is_comptime->ref_count += 1;
...@@ -3080,20 +3194,20 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s...@@ -3080,20 +3194,20 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
3080 ErrorMsg *msg = add_node_error(codegen, node,3194 ErrorMsg *msg = add_node_error(codegen, node,
3081 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));3195 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
3082 add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));3196 add_error_note(codegen, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
3083 variable_entry->value->type = codegen->builtin_types.entry_invalid;3197 variable_entry->var_type = codegen->builtin_types.entry_invalid;
3084 } else {3198 } else {
3085 ZigType *type;3199 ZigType *type;
3086 if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) {3200 if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) {
3087 add_node_error(codegen, node,3201 add_node_error(codegen, node,
3088 buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));3202 buf_sprintf("variable shadows primitive type '%s'", buf_ptr(name)));
3089 variable_entry->value->type = codegen->builtin_types.entry_invalid;3203 variable_entry->var_type = codegen->builtin_types.entry_invalid;
3090 } else {3204 } else {
3091 Tld *tld = find_decl(codegen, parent_scope, name);3205 Tld *tld = find_decl(codegen, parent_scope, name);
3092 if (tld != nullptr) {3206 if (tld != nullptr) {
3093 ErrorMsg *msg = add_node_error(codegen, node,3207 ErrorMsg *msg = add_node_error(codegen, node,
3094 buf_sprintf("redefinition of '%s'", buf_ptr(name)));3208 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
3095 add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here"));3209 add_error_note(codegen, msg, tld->source_node, buf_sprintf("previous definition is here"));
3096 variable_entry->value->type = codegen->builtin_types.entry_invalid;3210 variable_entry->var_type = codegen->builtin_types.entry_invalid;
3097 }3211 }
3098 }3212 }
3099 }3213 }
...@@ -3156,7 +3270,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3156,7 +3270,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
3156 scope_block->incoming_blocks = &incoming_blocks;3270 scope_block->incoming_blocks = &incoming_blocks;
3157 scope_block->incoming_values = &incoming_values;3271 scope_block->incoming_values = &incoming_values;
3158 scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd");3272 scope_block->end_block = ir_create_basic_block(irb, parent_scope, "BlockEnd");
3159 scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node, ir_should_inline(irb->exec, parent_scope));3273 scope_block->is_comptime = ir_build_const_bool(irb, parent_scope, block_node,
3274 ir_should_inline(irb->exec, parent_scope));
3160 }3275 }
31613276
3162 bool is_continuation_unreachable = false;3277 bool is_continuation_unreachable = false;
...@@ -3174,9 +3289,9 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode...@@ -3174,9 +3289,9 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
3174 // defer starts a new scope3289 // defer starts a new scope
3175 child_scope = statement_node->data.defer.child_scope;3290 child_scope = statement_node->data.defer.child_scope;
3176 assert(child_scope);3291 assert(child_scope);
3177 } else if (statement_value->id == IrInstructionIdDeclVar) {3292 } else if (statement_value->id == IrInstructionIdDeclVarSrc) {
3178 // variable declarations start a new scope3293 // variable declarations start a new scope
3179 IrInstructionDeclVar *decl_var_instruction = (IrInstructionDeclVar *)statement_value;3294 IrInstructionDeclVarSrc *decl_var_instruction = (IrInstructionDeclVarSrc *)statement_value;
3180 child_scope = decl_var_instruction->var->child_scope;3295 child_scope = decl_var_instruction->var->child_scope;
3181 } else if (statement_value != irb->codegen->invalid_instruction && !is_continuation_unreachable) {3296 } else if (statement_value != irb->codegen->invalid_instruction && !is_continuation_unreachable) {
3182 // this statement's value must be void3297 // this statement's value must be void
...@@ -3331,7 +3446,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -3331,7 +3446,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod
3331 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);3446 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
3332}3447}
33333448
3334static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) {3449static IrInstruction *ir_gen_orelse(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
3335 assert(node->type == NodeTypeBinOpExpr);3450 assert(node->type == NodeTypeBinOpExpr);
33363451
3337 AstNode *op1_node = node->data.bin_op_expr.op1;3452 AstNode *op1_node = node->data.bin_op_expr.op1;
...@@ -3365,7 +3480,7 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As...@@ -3365,7 +3480,7 @@ static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, As
3365 ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));3480 ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));
33663481
3367 ir_set_cursor_at_end_and_append_block(irb, ok_block);3482 ir_set_cursor_at_end_and_append_block(irb, ok_block);
3368 IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, parent_scope, node, maybe_ptr, false);3483 IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, parent_scope, node, maybe_ptr, false);
3369 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);3484 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
3370 IrBasicBlock *after_ok_block = irb->current_basic_block;3485 IrBasicBlock *after_ok_block = irb->current_basic_block;
3371 ir_build_br(irb, parent_scope, node, end_block, is_comptime);3486 ir_build_br(irb, parent_scope, node, end_block, is_comptime);
...@@ -3483,7 +3598,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -3483,7 +3598,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node)
3483 case BinOpTypeMergeErrorSets:3598 case BinOpTypeMergeErrorSets:
3484 return ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets);3599 return ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets);
3485 case BinOpTypeUnwrapOptional:3600 case BinOpTypeUnwrapOptional:
3486 return ir_gen_maybe_ok_or(irb, scope, node);3601 return ir_gen_orelse(irb, scope, node);
3487 case BinOpTypeErrorUnion:3602 case BinOpTypeErrorUnion:
3488 return ir_gen_error_union(irb, scope, node);3603 return ir_gen_error_union(irb, scope, node);
3489 }3604 }
...@@ -3542,6 +3657,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,...@@ -3542,6 +3657,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
3542 buf_ptr(variable_name)));3657 buf_ptr(variable_name)));
3543 return irb->codegen->invalid_instruction;3658 return irb->codegen->invalid_instruction;
3544 }3659 }
3660 assert(err == ErrorPrimitiveTypeNotFound);
3545 } else {3661 } else {
3546 IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_type);3662 IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_type);
3547 if (lval == LValPtr) {3663 if (lval == LValPtr) {
...@@ -3904,9 +4020,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -3904,9 +4020,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
3904 if (arg5_value == irb->codegen->invalid_instruction)4020 if (arg5_value == irb->codegen->invalid_instruction)
3905 return arg5_value;4021 return arg5_value;
39064022
3907 IrInstruction *cmpxchg = ir_build_cmpxchg(irb, scope, node, arg0_value, arg1_value,4023 IrInstruction *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value,
3908 arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak),4024 arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak));
3909 nullptr, AtomicOrderUnordered, AtomicOrderUnordered);
3910 return ir_lval_wrap(irb, scope, cmpxchg, lval);4025 return ir_lval_wrap(irb, scope, cmpxchg, lval);
3911 }4026 }
3912 case BuiltinFnIdFence:4027 case BuiltinFnIdFence:
...@@ -4169,6 +4284,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4169,6 +4284,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4169 IrInstruction *int_type = ir_build_int_type(irb, scope, node, arg0_value, arg1_value);4284 IrInstruction *int_type = ir_build_int_type(irb, scope, node, arg0_value, arg1_value);
4170 return ir_lval_wrap(irb, scope, int_type, lval);4285 return ir_lval_wrap(irb, scope, int_type, lval);
4171 }4286 }
4287 case BuiltinFnIdVectorType:
4288 {
4289 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4290 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4291 if (arg0_value == irb->codegen->invalid_instruction)
4292 return arg0_value;
4293
4294 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4295 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
4296 if (arg1_value == irb->codegen->invalid_instruction)
4297 return arg1_value;
4298
4299 IrInstruction *vector_type = ir_build_vector_type(irb, scope, node, arg0_value, arg1_value);
4300 return ir_lval_wrap(irb, scope, vector_type, lval);
4301 }
4172 case BuiltinFnIdMemcpy:4302 case BuiltinFnIdMemcpy:
4173 {4303 {
4174 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);4304 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
...@@ -4346,7 +4476,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4346,7 +4476,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4346 if (arg1_value == irb->codegen->invalid_instruction)4476 if (arg1_value == irb->codegen->invalid_instruction)
4347 return arg1_value;4477 return arg1_value;
43484478
4349 IrInstruction *ptr_cast = ir_build_ptr_cast(irb, scope, node, arg0_value, arg1_value);4479 IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value);
4350 return ir_lval_wrap(irb, scope, ptr_cast, lval);4480 return ir_lval_wrap(irb, scope, ptr_cast, lval);
4351 }4481 }
4352 case BuiltinFnIdBitCast:4482 case BuiltinFnIdBitCast:
...@@ -4784,7 +4914,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node...@@ -4784,7 +4914,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
4784 }4914 }
4785 }4915 }
47864916
4787 IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto, is_async, async_allocator, nullptr);4917 IrInstruction *fn_call = ir_build_call(irb, scope, node, nullptr, fn_ref, arg_count, args, false, FnInlineAuto,
4918 is_async, async_allocator, nullptr);
4788 return ir_lval_wrap(irb, scope, fn_call, lval);4919 return ir_lval_wrap(irb, scope, fn_call, lval);
4789}4920}
47904921
...@@ -4793,7 +4924,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -4793,7 +4924,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
47934924
4794 IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope);4925 IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope);
4795 if (condition == irb->codegen->invalid_instruction)4926 if (condition == irb->codegen->invalid_instruction)
4796 return condition;4927 return irb->codegen->invalid_instruction;
47974928
4798 IrInstruction *is_comptime;4929 IrInstruction *is_comptime;
4799 if (ir_should_inline(irb->exec, scope)) {4930 if (ir_should_inline(irb->exec, scope)) {
...@@ -4816,7 +4947,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -4816,7 +4947,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
4816 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);4947 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
4817 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, subexpr_scope);4948 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, subexpr_scope);
4818 if (then_expr_result == irb->codegen->invalid_instruction)4949 if (then_expr_result == irb->codegen->invalid_instruction)
4819 return then_expr_result;4950 return irb->codegen->invalid_instruction;
4820 IrBasicBlock *after_then_block = irb->current_basic_block;4951 IrBasicBlock *after_then_block = irb->current_basic_block;
4821 if (!instr_is_unreachable(then_expr_result))4952 if (!instr_is_unreachable(then_expr_result))
4822 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));4953 ir_mark_gen(ir_build_br(irb, scope, node, endif_block, is_comptime));
...@@ -4826,7 +4957,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode...@@ -4826,7 +4957,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
4826 if (else_node) {4957 if (else_node) {
4827 else_expr_result = ir_gen_node(irb, else_node, subexpr_scope);4958 else_expr_result = ir_gen_node(irb, else_node, subexpr_scope);
4828 if (else_expr_result == irb->codegen->invalid_instruction)4959 if (else_expr_result == irb->codegen->invalid_instruction)
4829 return else_expr_result;4960 return irb->codegen->invalid_instruction;
4830 } else {4961 } else {
4831 else_expr_result = ir_build_const_void(irb, scope, node);4962 else_expr_result = ir_build_const_void(irb, scope, node);
4832 }4963 }
...@@ -4927,7 +5058,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode...@@ -4927,7 +5058,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
4927 ptr_len, align_value, bit_offset_start, host_int_bytes);5058 ptr_len, align_value, bit_offset_start, host_int_bytes);
4928}5059}
49295060
4930static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node,5061static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node, AstNode *expr_node,
4931 LVal lval)5062 LVal lval)
4932{5063{
4933 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);5064 IrInstruction *err_union_ptr = ir_gen_node_extra(irb, expr_node, scope, LValPtr);
...@@ -5053,11 +5184,11 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5053,11 +5184,11 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
5053 ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime);5184 ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime);
5054 ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol,5185 ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol,
5055 is_const, is_const, is_shadowable, is_comptime);5186 is_const, is_const, is_shadowable, is_comptime);
5056 // we detect IrInstructionIdDeclVar in gen_block to make sure the next node5187 // we detect IrInstructionIdDeclVarSrc in gen_block to make sure the next node
5057 // is inside var->child_scope5188 // is inside var->child_scope
50585189
5059 if (!is_extern && !variable_declaration->expr) {5190 if (!is_extern && !variable_declaration->expr) {
5060 var->value->type = irb->codegen->builtin_types.entry_invalid;5191 var->var_type = irb->codegen->builtin_types.entry_invalid;
5061 add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized"));5192 add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized"));
5062 return irb->codegen->invalid_instruction;5193 return irb->codegen->invalid_instruction;
5063 }5194 }
...@@ -5084,7 +5215,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5084,7 +5215,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
5084 if (init_value == irb->codegen->invalid_instruction)5215 if (init_value == irb->codegen->invalid_instruction)
5085 return init_value;5216 return init_value;
50865217
5087 return ir_build_var_decl(irb, scope, node, var, type_instruction, align_value, init_value);5218 return ir_build_var_decl_src(irb, scope, node, var, type_instruction, align_value, init_value);
5088}5219}
50895220
5090static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) {5221static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
...@@ -5140,7 +5271,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5140,7 +5271,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5140 err_val_ptr, false);5271 err_val_ptr, false);
5141 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?5272 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
5142 var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value);5273 var_ptr_value : ir_build_load_ptr(irb, payload_scope, symbol_node, var_ptr_value);
5143 ir_build_var_decl(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value);5274 ir_build_var_decl_src(irb, payload_scope, symbol_node, payload_var, nullptr, nullptr, var_value);
5144 }5275 }
51455276
5146 ZigList<IrInstruction *> incoming_values = {0};5277 ZigList<IrInstruction *> incoming_values = {0};
...@@ -5180,7 +5311,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5180,7 +5311,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5180 true, false, false, is_comptime);5311 true, false, false, is_comptime);
5181 Scope *err_scope = err_var->child_scope;5312 Scope *err_scope = err_var->child_scope;
5182 IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);5313 IrInstruction *err_var_value = ir_build_unwrap_err_code(irb, err_scope, err_symbol_node, err_val_ptr);
5183 ir_build_var_decl(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value);5314 ir_build_var_decl_src(irb, err_scope, symbol_node, err_var, nullptr, nullptr, err_var_value);
51845315
5185 IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope);5316 IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope);
5186 if (else_result == irb->codegen->invalid_instruction)5317 if (else_result == irb->codegen->invalid_instruction)
...@@ -5220,10 +5351,10 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -5220,10 +5351,10 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
5220 }5351 }
52215352
5222 ir_set_cursor_at_end_and_append_block(irb, body_block);5353 ir_set_cursor_at_end_and_append_block(irb, body_block);
5223 IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, child_scope, symbol_node, maybe_val_ptr, false);5354 IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, child_scope, symbol_node, maybe_val_ptr, false);
5224 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?5355 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
5225 var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value);5356 var_ptr_value : ir_build_load_ptr(irb, child_scope, symbol_node, var_ptr_value);
5226 ir_build_var_decl(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value);5357 ir_build_var_decl_src(irb, child_scope, symbol_node, payload_var, nullptr, nullptr, var_value);
52275358
5228 ZigList<IrInstruction *> incoming_values = {0};5359 ZigList<IrInstruction *> incoming_values = {0};
5229 ZigList<IrBasicBlock *> incoming_blocks = {0};5360 ZigList<IrBasicBlock *> incoming_blocks = {0};
...@@ -5380,7 +5511,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -5380,7 +5511,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
5380 Scope *child_scope = elem_var->child_scope;5511 Scope *child_scope = elem_var->child_scope;
53815512
5382 IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node);5513 IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node);
5383 ir_build_var_decl(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value);5514 ir_build_var_decl_src(irb, child_scope, elem_node, elem_var, elem_var_type, nullptr, undefined_value);
5384 IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var);5515 IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var);
53855516
5386 AstNode *index_var_source_node;5517 AstNode *index_var_source_node;
...@@ -5398,7 +5529,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo...@@ -5398,7 +5529,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
5398 IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize);5529 IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize);
5399 IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0);5530 IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0);
5400 IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1);5531 IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1);
5401 ir_build_var_decl(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero);5532 ir_build_var_decl_src(irb, child_scope, index_var_source_node, index_var, usize, nullptr, zero);
5402 IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var);5533 IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var);
54035534
54045535
...@@ -5622,8 +5753,8 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -5622,8 +5753,8 @@ static IrInstruction *ir_gen_asm_expr(IrBuilder *irb, Scope *scope, AstNode *nod
5622 return ir_build_asm(irb, scope, node, input_list, output_types, output_vars, return_count, is_volatile);5753 return ir_build_asm(irb, scope, node, input_list, output_types, output_vars, return_count, is_volatile);
5623}5754}
56245755
5625static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *node) {5756static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
5626 assert(node->type == NodeTypeTestExpr);5757 assert(node->type == NodeTypeIfOptional);
56275758
5628 Buf *var_symbol = node->data.test_expr.var_symbol;5759 Buf *var_symbol = node->data.test_expr.var_symbol;
5629 AstNode *expr_node = node->data.test_expr.target_node;5760 AstNode *expr_node = node->data.test_expr.target_node;
...@@ -5661,9 +5792,9 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no...@@ -5661,9 +5792,9 @@ static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *no
5661 ZigVar *var = ir_create_var(irb, node, subexpr_scope,5792 ZigVar *var = ir_create_var(irb, node, subexpr_scope,
5662 var_symbol, is_const, is_const, is_shadowable, is_comptime);5793 var_symbol, is_const, is_const, is_shadowable, is_comptime);
56635794
5664 IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, subexpr_scope, node, maybe_val_ptr, false);5795 IrInstruction *var_ptr_value = ir_build_optional_unwrap_ptr(irb, subexpr_scope, node, maybe_val_ptr, false);
5665 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);5796 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);
5666 ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value);5797 ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
5667 var_scope = var->child_scope;5798 var_scope = var->child_scope;
5668 } else {5799 } else {
5669 var_scope = subexpr_scope;5800 var_scope = subexpr_scope;
...@@ -5738,7 +5869,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -5738,7 +5869,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
57385869
5739 IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false);5870 IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false);
5740 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);5871 IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, subexpr_scope, node, var_ptr_value);
5741 ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value);5872 ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
5742 var_scope = var->child_scope;5873 var_scope = var->child_scope;
5743 } else {5874 } else {
5744 var_scope = subexpr_scope;5875 var_scope = subexpr_scope;
...@@ -5763,7 +5894,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *...@@ -5763,7 +5894,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
5763 err_symbol, is_const, is_const, is_shadowable, is_comptime);5894 err_symbol, is_const, is_const, is_shadowable, is_comptime);
57645895
5765 IrInstruction *var_value = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr);5896 IrInstruction *var_value = ir_build_unwrap_err_code(irb, subexpr_scope, node, err_val_ptr);
5766 ir_build_var_decl(irb, subexpr_scope, node, var, var_type, nullptr, var_value);5897 ir_build_var_decl_src(irb, subexpr_scope, node, var, var_type, nullptr, var_value);
5767 err_var_scope = var->child_scope;5898 err_var_scope = var->child_scope;
5768 } else {5899 } else {
5769 err_var_scope = subexpr_scope;5900 err_var_scope = subexpr_scope;
...@@ -5818,7 +5949,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit...@@ -5818,7 +5949,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
5818 var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr);5949 var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr);
5819 }5950 }
5820 IrInstruction *var_type = nullptr; // infer the type5951 IrInstruction *var_type = nullptr; // infer the type
5821 ir_build_var_decl(irb, scope, var_symbol_node, var, var_type, nullptr, var_value);5952 ir_build_var_decl_src(irb, scope, var_symbol_node, var, var_type, nullptr, var_value);
5822 } else {5953 } else {
5823 child_scope = scope;5954 child_scope = scope;
5824 }5955 }
...@@ -6228,7 +6359,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)...@@ -6228,7 +6359,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)
6228 return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true);6359 return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true);
6229}6360}
62306361
6231static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) {6362static IrInstruction *ir_gen_catch(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
6232 assert(node->type == NodeTypeUnwrapErrorExpr);6363 assert(node->type == NodeTypeUnwrapErrorExpr);
62336364
6234 AstNode *op1_node = node->data.unwrap_err_expr.op1;6365 AstNode *op1_node = node->data.unwrap_err_expr.op1;
...@@ -6242,7 +6373,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN...@@ -6242,7 +6373,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
6242 add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));6373 add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));
6243 return irb->codegen->invalid_instruction;6374 return irb->codegen->invalid_instruction;
6244 }6375 }
6245 return ir_gen_err_assert_ok(irb, parent_scope, node, op1_node, LValNone);6376 return ir_gen_catch_unreachable(irb, parent_scope, node, op1_node, LValNone);
6246 }6377 }
62476378
62486379
...@@ -6276,7 +6407,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN...@@ -6276,7 +6407,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
6276 is_const, is_const, is_shadowable, is_comptime);6407 is_const, is_const, is_shadowable, is_comptime);
6277 err_scope = var->child_scope;6408 err_scope = var->child_scope;
6278 IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);6409 IrInstruction *err_val = ir_build_unwrap_err_code(irb, err_scope, node, err_union_ptr);
6279 ir_build_var_decl(irb, err_scope, var_node, var, nullptr, nullptr, err_val);6410 ir_build_var_decl_src(irb, err_scope, var_node, var, nullptr, nullptr, err_val);
6280 } else {6411 } else {
6281 err_scope = parent_scope;6412 err_scope = parent_scope;
6282 }6413 }
...@@ -6312,7 +6443,8 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o...@@ -6312,7 +6443,8 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o
6312 ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope;6443 ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope;
6313 if (need_comma)6444 if (need_comma)
6314 buf_append_char(name, ',');6445 buf_append_char(name, ',');
6315 render_const_value(codegen, name, var_scope->var->value);6446 // TODO: const ptr reinterpret here to make the var type agree with the value?
6447 render_const_value(codegen, name, var_scope->var->const_value);
6316 return true;6448 return true;
6317}6449}
63186450
...@@ -6562,7 +6694,7 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode...@@ -6562,7 +6694,7 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
6562 IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b0106694 IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010
65636695
6564 // TODO relies on Zig not re-ordering fields6696 // TODO relies on Zig not re-ordering fields
6565 IrInstruction *casted_target_inst = ir_build_ptr_cast(irb, scope, node, promise_T_type_val, target_inst);6697 IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst);
6566 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);6698 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
6567 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);6699 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
6568 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,6700 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
...@@ -6640,7 +6772,7 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode...@@ -6640,7 +6772,7 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode
6640 get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));6772 get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));
66416773
6642 // TODO relies on Zig not re-ordering fields6774 // TODO relies on Zig not re-ordering fields
6643 IrInstruction *casted_target_inst = ir_build_ptr_cast(irb, scope, node, promise_T_type_val, target_inst);6775 IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst);
6644 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);6776 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
6645 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);6777 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
6646 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,6778 IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
...@@ -6756,7 +6888,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6756,7 +6888,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
6756 IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst);6888 IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst);
6757 IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type);6889 IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type);
6758 ir_build_await_bookkeeping(irb, scope, node, promise_result_type);6890 ir_build_await_bookkeeping(irb, scope, node, promise_result_type);
6759 ir_build_var_decl(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value);6891 ir_build_var_decl_src(irb, scope, node, result_var, promise_result_type, nullptr, undefined_value);
6760 IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var);6892 IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var);
6761 ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr);6893 ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr);
6762 IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle);6894 IrInstruction *save_token = ir_build_coro_save(irb, scope, node, irb->exec->coro_handle);
...@@ -7050,7 +7182,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -7050,7 +7182,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
7050 if (maybe_ptr == irb->codegen->invalid_instruction)7182 if (maybe_ptr == irb->codegen->invalid_instruction)
7051 return irb->codegen->invalid_instruction;7183 return irb->codegen->invalid_instruction;
70527184
7053 IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, scope, node, maybe_ptr, true);7185 IrInstruction *unwrapped_ptr = ir_build_optional_unwrap_ptr(irb, scope, node, maybe_ptr, true);
7054 if (lval == LValPtr)7186 if (lval == LValPtr)
7055 return unwrapped_ptr;7187 return unwrapped_ptr;
70567188
...@@ -7074,8 +7206,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -7074,8 +7206,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
7074 return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);7206 return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);
7075 case NodeTypeIfErrorExpr:7207 case NodeTypeIfErrorExpr:
7076 return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval);7208 return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval);
7077 case NodeTypeTestExpr:7209 case NodeTypeIfOptional:
7078 return ir_lval_wrap(irb, scope, ir_gen_test_expr(irb, scope, node), lval);7210 return ir_lval_wrap(irb, scope, ir_gen_if_optional_expr(irb, scope, node), lval);
7079 case NodeTypeSwitchExpr:7211 case NodeTypeSwitchExpr:
7080 return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);7212 return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);
7081 case NodeTypeCompTime:7213 case NodeTypeCompTime:
...@@ -7093,7 +7225,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -7093,7 +7225,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
7093 case NodeTypeSliceExpr:7225 case NodeTypeSliceExpr:
7094 return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval);7226 return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval);
7095 case NodeTypeUnwrapErrorExpr:7227 case NodeTypeUnwrapErrorExpr:
7096 return ir_lval_wrap(irb, scope, ir_gen_err_ok_or(irb, scope, node), lval);7228 return ir_lval_wrap(irb, scope, ir_gen_catch(irb, scope, node), lval);
7097 case NodeTypeContainerDecl:7229 case NodeTypeContainerDecl:
7098 return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval);7230 return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval);
7099 case NodeTypeFnProto:7231 case NodeTypeFnProto:
...@@ -7152,6 +7284,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7152,6 +7284,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7152 ir_ref_bb(irb->current_basic_block);7284 ir_ref_bb(irb->current_basic_block);
71537285
7154 ZigFn *fn_entry = exec_fn_entry(irb->exec);7286 ZigFn *fn_entry = exec_fn_entry(irb->exec);
7287
7155 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;7288 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
7156 IrInstruction *coro_id;7289 IrInstruction *coro_id;
7157 IrInstruction *u8_ptr_type;7290 IrInstruction *u8_ptr_type;
...@@ -7172,27 +7305,27 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7172,27 +7305,27 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7172 ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);7305 ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);
7173 IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);7306 IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);
7174 // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa7307 // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa
7175 ir_build_var_decl(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef);7308 ir_build_var_decl_src(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef);
7176 coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var);7309 coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var);
71777310
7178 ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);7311 ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
7179 IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);7312 IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);
7180 IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,7313 IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,
7181 get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise));7314 get_optional_type(irb->codegen, irb->codegen->builtin_types.entry_promise));
7182 ir_build_var_decl(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);7315 ir_build_var_decl_src(irb, coro_scope, node, await_handle_var, await_handle_type_val, nullptr, null_value);
7183 irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var);7316 irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var);
71847317
7185 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,7318 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
7186 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));7319 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));
7187 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr);7320 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr);
7188 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);7321 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);
7189 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);7322 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
7190 IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);7323 IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);
7191 ir_build_var_decl(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size);7324 ir_build_var_decl_src(irb, coro_scope, node, coro_size_var, nullptr, nullptr, coro_size);
7192 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node,7325 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node,
7193 ImplicitAllocatorIdArg);7326 ImplicitAllocatorIdArg);
7194 irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false);7327 irb->exec->coro_allocator_var = ir_create_var(irb, node, coro_scope, nullptr, true, true, true, const_bool_false);
7195 ir_build_var_decl(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);7328 ir_build_var_decl_src(irb, coro_scope, node, irb->exec->coro_allocator_var, nullptr, nullptr, implicit_allocator_ptr);
7196 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);7329 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
7197 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, alloc_field_name);7330 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, alloc_field_name);
7198 IrInstruction *alloc_fn = ir_build_load_ptr(irb, coro_scope, node, alloc_fn_ptr);7331 IrInstruction *alloc_fn = ir_build_load_ptr(irb, coro_scope, node, alloc_fn_ptr);
...@@ -7208,7 +7341,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7208,7 +7341,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7208 ir_build_return(irb, coro_scope, node, undef);7341 ir_build_return(irb, coro_scope, node, undef);
72097342
7210 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);7343 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);
7211 IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr);7344 IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr);
7212 irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);7345 irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);
72137346
7214 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);7347 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
...@@ -7286,8 +7419,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7286,8 +7419,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7286 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,7419 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
7287 false, false, PtrLenUnknown, 0, 0, 0));7420 false, false, PtrLenUnknown, 0, 0, 0));
7288 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);7421 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
7289 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, result_ptr);7422 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, result_ptr);
7290 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len,7423 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
7291 irb->exec->coro_result_field_ptr);7424 irb->exec->coro_result_field_ptr);
7292 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,7425 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,
7293 fn_entry->type_entry->data.fn.fn_type_id.return_type);7426 fn_entry->type_entry->data.fn.fn_type_id.return_type);
...@@ -7303,7 +7436,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7303,7 +7436,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7303 // Before we destroy the coroutine frame, we need to load the target promise into7436 // Before we destroy the coroutine frame, we need to load the target promise into
7304 // a register or local variable which does not get spilled into the frame,7437 // a register or local variable which does not get spilled into the frame,
7305 // otherwise llvm tries to access memory inside the destroyed frame.7438 // otherwise llvm tries to access memory inside the destroyed frame.
7306 IrInstruction *unwrapped_await_handle_ptr = ir_build_unwrap_maybe(irb, scope, node,7439 IrInstruction *unwrapped_await_handle_ptr = ir_build_optional_unwrap_ptr(irb, scope, node,
7307 irb->exec->await_handle_var_ptr, false);7440 irb->exec->await_handle_var_ptr, false);
7308 IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);7441 IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);
7309 ir_build_br(irb, scope, node, check_free_block, const_bool_false);7442 ir_build_br(irb, scope, node, check_free_block, const_bool_false);
...@@ -7338,7 +7471,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -7338,7 +7471,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
7338 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,7471 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
7339 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,7472 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
7340 false, false, PtrLenUnknown, 0, 0, 0));7473 false, false, PtrLenUnknown, 0, 0, 0));
7341 IrInstruction *coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe);7474 IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe);
7342 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);7475 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
7343 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);7476 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
7344 IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);7477 IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);
...@@ -7435,7 +7568,7 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal...@@ -7435,7 +7568,7 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal
7435 return val;7568 return val;
7436}7569}
74377570
7438static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) {7571static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) {
7439 IrBasicBlock *bb = exec->basic_block_list.at(0);7572 IrBasicBlock *bb = exec->basic_block_list.at(0);
7440 for (size_t i = 0; i < bb->instruction_list.length; i += 1) {7573 for (size_t i = 0; i < bb->instruction_list.length; i += 1) {
7441 IrInstruction *instruction = bb->instruction_list.at(i);7574 IrInstruction *instruction = bb->instruction_list.at(i);
...@@ -7445,16 +7578,16 @@ static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec)...@@ -7445,16 +7578,16 @@ static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec)
7445 if (value->value.special == ConstValSpecialRuntime) {7578 if (value->value.special == ConstValSpecialRuntime) {
7446 exec_add_error_node(codegen, exec, value->source_node,7579 exec_add_error_node(codegen, exec, value->source_node,
7447 buf_sprintf("unable to evaluate constant expression"));7580 buf_sprintf("unable to evaluate constant expression"));
7448 return codegen->invalid_instruction;7581 return &codegen->invalid_instruction->value;
7449 }7582 }
7450 return value;7583 return &value->value;
7451 } else if (ir_has_side_effects(instruction)) {7584 } else if (ir_has_side_effects(instruction)) {
7452 exec_add_error_node(codegen, exec, instruction->source_node,7585 exec_add_error_node(codegen, exec, instruction->source_node,
7453 buf_sprintf("unable to evaluate constant expression"));7586 buf_sprintf("unable to evaluate constant expression"));
7454 return codegen->invalid_instruction;7587 return &codegen->invalid_instruction->value;
7455 }7588 }
7456 }7589 }
7457 return codegen->invalid_instruction;7590 return &codegen->invalid_instruction->value;
7458}7591}
74597592
7460static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) {7593static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) {
...@@ -8174,6 +8307,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc...@@ -8174,6 +8307,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
81748307
8175 bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt);8308 bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt);
8176 bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || const_val->type->id == ZigTypeIdComptimeFloat);8309 bool const_val_is_float = (const_val->type->id == ZigTypeIdFloat || const_val->type->id == ZigTypeIdComptimeFloat);
8310 assert(const_val_is_int || const_val_is_float);
81778311
8178 if (other_type->id == ZigTypeIdFloat) {8312 if (other_type->id == ZigTypeIdFloat) {
8179 if (const_val->type->id == ZigTypeIdComptimeInt || const_val->type->id == ZigTypeIdComptimeFloat) {8313 if (const_val->type->id == ZigTypeIdComptimeInt || const_val->type->id == ZigTypeIdComptimeFloat) {
...@@ -8768,13 +8902,13 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -8768,13 +8902,13 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
8768 size_t errors_count = 0;8902 size_t errors_count = 0;
8769 ZigType *err_set_type = nullptr;8903 ZigType *err_set_type = nullptr;
8770 if (prev_inst->value.type->id == ZigTypeIdErrorSet) {8904 if (prev_inst->value.type->id == ZigTypeIdErrorSet) {
8905 if (!resolve_inferred_error_set(ira->codegen, prev_inst->value.type, prev_inst->source_node)) {
8906 return ira->codegen->builtin_types.entry_invalid;
8907 }
8771 if (type_is_global_error_set(prev_inst->value.type)) {8908 if (type_is_global_error_set(prev_inst->value.type)) {
8772 err_set_type = ira->codegen->builtin_types.entry_global_error_set;8909 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
8773 } else {8910 } else {
8774 err_set_type = prev_inst->value.type;8911 err_set_type = prev_inst->value.type;
8775 if (!resolve_inferred_error_set(ira->codegen, err_set_type, prev_inst->source_node)) {
8776 return ira->codegen->builtin_types.entry_invalid;
8777 }
8778 update_errors_helper(ira->codegen, &errors, &errors_count);8912 update_errors_helper(ira->codegen, &errors, &errors_count);
87798913
8780 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {8914 for (uint32_t i = 0; i < err_set_type->data.error_set.err_count; i += 1) {
...@@ -8933,6 +9067,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -8933,6 +9067,9 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
8933 if (prev_type->id == ZigTypeIdArray) {9067 if (prev_type->id == ZigTypeIdArray) {
8934 convert_to_const_slice = true;9068 convert_to_const_slice = true;
8935 }9069 }
9070 if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
9071 return ira->codegen->builtin_types.entry_invalid;
9072 }
8936 if (type_is_global_error_set(cur_type)) {9073 if (type_is_global_error_set(cur_type)) {
8937 err_set_type = ira->codegen->builtin_types.entry_global_error_set;9074 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
8938 continue;9075 continue;
...@@ -8940,9 +9077,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -8940,9 +9077,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
8940 if (err_set_type != nullptr && type_is_global_error_set(err_set_type)) {9077 if (err_set_type != nullptr && type_is_global_error_set(err_set_type)) {
8941 continue;9078 continue;
8942 }9079 }
8943 if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
8944 return ira->codegen->builtin_types.entry_invalid;
8945 }
89469080
8947 update_errors_helper(ira->codegen, &errors, &errors_count);9081 update_errors_helper(ira->codegen, &errors, &errors_count);
89489082
...@@ -9432,14 +9566,23 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_...@@ -9432,14 +9566,23 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
9432 }9566 }
9433 return true;9567 return true;
9434}9568}
9569
9570static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) {
9571 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
9572 old_instruction->scope, old_instruction->source_node);
9573 IrInstruction *new_instruction = &const_instruction->base;
9574 new_instruction->value.type = ty;
9575 new_instruction->value.special = ConstValSpecialStatic;
9576 return new_instruction;
9577}
9578
9435static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,9579static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
9436 ZigType *wanted_type, CastOp cast_op, bool need_alloca)9580 ZigType *wanted_type, CastOp cast_op, bool need_alloca)
9437{9581{
9438 if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) &&9582 if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) &&
9439 cast_op != CastOpResizeSlice)9583 cast_op != CastOpResizeSlice)
9440 {9584 {
9441 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,9585 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
9442 source_instr->source_node, wanted_type);
9443 if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type,9586 if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type,
9444 &result->value, wanted_type))9587 &result->value, wanted_type))
9445 {9588 {
...@@ -9476,9 +9619,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,...@@ -9476,9 +9619,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
9476 if (pointee == nullptr)9619 if (pointee == nullptr)
9477 return ira->codegen->invalid_instruction;9620 return ira->codegen->invalid_instruction;
9478 if (pointee->special != ConstValSpecialRuntime) {9621 if (pointee->special != ConstValSpecialRuntime) {
9479 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,9622 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
9480 source_instr->source_node, wanted_type);
9481 result->value.type = wanted_type;
9482 result->value.data.x_ptr.special = ConstPtrSpecialBaseArray;9623 result->value.data.x_ptr.special = ConstPtrSpecialBaseArray;
9483 result->value.data.x_ptr.mut = value->value.data.x_ptr.mut;9624 result->value.data.x_ptr.mut = value->value.data.x_ptr.mut;
9484 result->value.data.x_ptr.data.base_array.array_val = pointee;9625 result->value.data.x_ptr.data.base_array.array_val = pointee;
...@@ -9517,8 +9658,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc...@@ -9517,8 +9658,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
9517 assert(is_slice(wanted_type));9658 assert(is_slice(wanted_type));
9518 bool is_const = wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;9659 bool is_const = wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const;
95199660
9520 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,9661 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
9521 source_instr->source_node, wanted_type);
9522 init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const);9662 init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const);
9523 result->value.data.x_struct.fields[slice_ptr_index].data.x_ptr.mut =9663 result->value.data.x_struct.fields[slice_ptr_index].data.x_ptr.mut =
9524 value->value.data.x_ptr.mut;9664 value->value.data.x_ptr.mut;
...@@ -9653,15 +9793,6 @@ static IrInstruction *ir_finish_anal(IrAnalyze *ira, IrInstruction *instruction)...@@ -9653,15 +9793,6 @@ static IrInstruction *ir_finish_anal(IrAnalyze *ira, IrInstruction *instruction)
9653 return instruction;9793 return instruction;
9654}9794}
96559795
9656static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, ZigType *ty) {
9657 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
9658 old_instruction->scope, old_instruction->source_node);
9659 IrInstruction *new_instruction = &const_instruction->base;
9660 new_instruction->value.type = ty;
9661 new_instruction->value.special = ConstValSpecialStatic;
9662 return new_instruction;
9663}
9664
9665static IrInstruction *ir_const_type(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) {9796static IrInstruction *ir_const_type(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) {
9666 IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_type);9797 IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_type);
9667 result->value.data.x_type = ty;9798 result->value.data.x_type = ty;
...@@ -9719,13 +9850,13 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un...@@ -9719,13 +9850,13 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
9719 zig_unreachable();9850 zig_unreachable();
9720}9851}
97219852
9722IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,9853ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
9723 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,9854 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
9724 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,9855 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
9725 IrExecutable *parent_exec)9856 IrExecutable *parent_exec)
9726{9857{
9727 if (expected_type != nullptr && type_is_invalid(expected_type))9858 if (expected_type != nullptr && type_is_invalid(expected_type))
9728 return codegen->invalid_instruction;9859 return &codegen->invalid_instruction->value;
97299860
9730 IrExecutable *ir_executable = allocate<IrExecutable>(1);9861 IrExecutable *ir_executable = allocate<IrExecutable>(1);
9731 ir_executable->source_node = source_node;9862 ir_executable->source_node = source_node;
...@@ -9738,13 +9869,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node...@@ -9738,13 +9869,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node
9738 ir_gen(codegen, node, scope, ir_executable);9869 ir_gen(codegen, node, scope, ir_executable);
97399870
9740 if (ir_executable->invalid)9871 if (ir_executable->invalid)
9741 return codegen->invalid_instruction;9872 return &codegen->invalid_instruction->value;
97429873
9743 if (codegen->verbose_ir) {9874 if (codegen->verbose_ir) {
9744 fprintf(stderr, "\nSource: ");9875 fprintf(stderr, "\nSource: ");
9745 ast_render(codegen, stderr, node, 4);9876 ast_render(codegen, stderr, node, 4);
9746 fprintf(stderr, "\n{ // (IR)\n");9877 fprintf(stderr, "\n{ // (IR)\n");
9747 ir_print(codegen, stderr, ir_executable, 4);9878 ir_print(codegen, stderr, ir_executable, 2);
9748 fprintf(stderr, "}\n");9879 fprintf(stderr, "}\n");
9749 }9880 }
9750 IrExecutable *analyzed_executable = allocate<IrExecutable>(1);9881 IrExecutable *analyzed_executable = allocate<IrExecutable>(1);
...@@ -9760,11 +9891,11 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node...@@ -9760,11 +9891,11 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node
9760 analyzed_executable->begin_scope = scope;9891 analyzed_executable->begin_scope = scope;
9761 ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, node);9892 ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, node);
9762 if (type_is_invalid(result_type))9893 if (type_is_invalid(result_type))
9763 return codegen->invalid_instruction;9894 return &codegen->invalid_instruction->value;
97649895
9765 if (codegen->verbose_ir) {9896 if (codegen->verbose_ir) {
9766 fprintf(stderr, "{ // (analyzed)\n");9897 fprintf(stderr, "{ // (analyzed)\n");
9767 ir_print(codegen, stderr, analyzed_executable, 4);9898 ir_print(codegen, stderr, analyzed_executable, 2);
9768 fprintf(stderr, "}\n");9899 fprintf(stderr, "}\n");
9769 }9900 }
97709901
...@@ -9789,6 +9920,34 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {...@@ -9789,6 +9920,34 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {
9789 return const_val->data.x_type;9920 return const_val->data.x_type;
9790}9921}
97919922
9923static ZigType *ir_resolve_error_set_type(IrAnalyze *ira, IrInstruction *op_source, IrInstruction *type_value) {
9924 if (type_is_invalid(type_value->value.type))
9925 return ira->codegen->builtin_types.entry_invalid;
9926
9927 if (type_value->value.type->id != ZigTypeIdMetaType) {
9928 ErrorMsg *msg = ir_add_error(ira, type_value,
9929 buf_sprintf("expected error set type, found '%s'", buf_ptr(&type_value->value.type->name)));
9930 add_error_note(ira->codegen, msg, op_source->source_node,
9931 buf_sprintf("`||` merges error sets; `or` performs boolean OR"));
9932 return ira->codegen->builtin_types.entry_invalid;
9933 }
9934
9935 ConstExprValue *const_val = ir_resolve_const(ira, type_value, UndefBad);
9936 if (!const_val)
9937 return ira->codegen->builtin_types.entry_invalid;
9938
9939 assert(const_val->data.x_type != nullptr);
9940 ZigType *result_type = const_val->data.x_type;
9941 if (result_type->id != ZigTypeIdErrorSet) {
9942 ErrorMsg *msg = ir_add_error(ira, type_value,
9943 buf_sprintf("expected error set type, found type '%s'", buf_ptr(&result_type->name)));
9944 add_error_note(ira->codegen, msg, op_source->source_node,
9945 buf_sprintf("`||` merges error sets; `or` performs boolean OR"));
9946 return ira->codegen->builtin_types.entry_invalid;
9947 }
9948 return result_type;
9949}
9950
9792static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {9951static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
9793 if (fn_value == ira->codegen->invalid_instruction)9952 if (fn_value == ira->codegen->invalid_instruction)
9794 return nullptr;9953 return nullptr;
...@@ -9810,7 +9969,9 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {...@@ -9810,7 +9969,9 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
9810 return const_val->data.x_ptr.data.fn.fn_entry;9969 return const_val->data.x_ptr.data.fn.fn_entry;
9811}9970}
98129971
9813static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *wanted_type) {9972static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
9973 ZigType *wanted_type)
9974{
9814 assert(wanted_type->id == ZigTypeIdOptional);9975 assert(wanted_type->id == ZigTypeIdOptional);
98159976
9816 if (instr_is_comptime(value)) {9977 if (instr_is_comptime(value)) {
...@@ -9826,7 +9987,7 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc...@@ -9826,7 +9987,7 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc
9826 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,9987 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
9827 source_instr->scope, source_instr->source_node);9988 source_instr->scope, source_instr->source_node);
9828 const_instruction->base.value.special = ConstValSpecialStatic;9989 const_instruction->base.value.special = ConstValSpecialStatic;
9829 if (get_codegen_ptr_type(wanted_type) != nullptr) {9990 if (types_have_same_zig_comptime_repr(wanted_type, payload_type)) {
9830 copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst);9991 copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst);
9831 } else {9992 } else {
9832 const_instruction->base.value.data.x_optional = val;9993 const_instruction->base.value.data.x_optional = val;
...@@ -9857,11 +10018,16 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction...@@ -9857,11 +10018,16 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
9857 if (!val)10018 if (!val)
9858 return ira->codegen->invalid_instruction;10019 return ira->codegen->invalid_instruction;
985910020
10021 ConstExprValue *err_set_val = create_const_vals(1);
10022 err_set_val->type = wanted_type->data.error_union.err_set_type;
10023 err_set_val->special = ConstValSpecialStatic;
10024 err_set_val->data.x_err_set = nullptr;
10025
9860 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,10026 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
9861 source_instr->scope, source_instr->source_node);10027 source_instr->scope, source_instr->source_node);
9862 const_instruction->base.value.type = wanted_type;10028 const_instruction->base.value.type = wanted_type;
9863 const_instruction->base.value.special = ConstValSpecialStatic;10029 const_instruction->base.value.special = ConstValSpecialStatic;
9864 const_instruction->base.value.data.x_err_union.err = nullptr;10030 const_instruction->base.value.data.x_err_union.error_set = err_set_val;
9865 const_instruction->base.value.data.x_err_union.payload = val;10031 const_instruction->base.value.data.x_err_union.payload = val;
9866 return &const_instruction->base;10032 return &const_instruction->base;
9867 }10033 }
...@@ -9926,11 +10092,16 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so...@@ -9926,11 +10092,16 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so
9926 if (!val)10092 if (!val)
9927 return ira->codegen->invalid_instruction;10093 return ira->codegen->invalid_instruction;
992810094
10095 ConstExprValue *err_set_val = create_const_vals(1);
10096 err_set_val->special = ConstValSpecialStatic;
10097 err_set_val->type = wanted_type->data.error_union.err_set_type;
10098 err_set_val->data.x_err_set = val->data.x_err_set;
10099
9929 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,10100 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
9930 source_instr->scope, source_instr->source_node);10101 source_instr->scope, source_instr->source_node);
9931 const_instruction->base.value.type = wanted_type;10102 const_instruction->base.value.type = wanted_type;
9932 const_instruction->base.value.special = ConstValSpecialStatic;10103 const_instruction->base.value.special = ConstValSpecialStatic;
9933 const_instruction->base.value.data.x_err_union.err = val->data.x_err_set;10104 const_instruction->base.value.data.x_err_union.error_set = err_set_val;
9934 const_instruction->base.value.data.x_err_union.payload = nullptr;10105 const_instruction->base.value.data.x_err_union.payload = nullptr;
9935 return &const_instruction->base;10106 return &const_instruction->base;
9936 }10107 }
...@@ -9952,8 +10123,9 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so...@@ -9952,8 +10123,9 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so
9952 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, source_instr->scope, source_instr->source_node);10123 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, source_instr->scope, source_instr->source_node);
9953 const_instruction->base.value.special = ConstValSpecialStatic;10124 const_instruction->base.value.special = ConstValSpecialStatic;
9954 if (get_codegen_ptr_type(wanted_type) != nullptr) {10125 if (get_codegen_ptr_type(wanted_type) != nullptr) {
9955 const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;10126 const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialNull;
9956 const_instruction->base.value.data.x_ptr.data.hard_coded_addr.addr = 0;10127 } else if (is_opt_err_set(wanted_type)) {
10128 const_instruction->base.value.data.x_err_set = nullptr;
9957 } else {10129 } else {
9958 const_instruction->base.value.data.x_optional = nullptr;10130 const_instruction->base.value.data.x_optional = nullptr;
9959 }10131 }
...@@ -9986,7 +10158,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi...@@ -9986,7 +10158,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
9986 source_instruction->source_node, value, is_const, is_volatile);10158 source_instruction->source_node, value, is_const, is_volatile);
9987 new_instruction->value.type = ptr_type;10159 new_instruction->value.type = ptr_type;
9988 new_instruction->value.data.rh_ptr = RuntimeHintPtrStack;10160 new_instruction->value.data.rh_ptr = RuntimeHintPtrStack;
9989 if (type_has_bits(ptr_type)) {10161 if (type_has_bits(ptr_type) && !handle_is_ptr(value->value.type)) {
9990 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);10162 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
9991 assert(fn_entry);10163 assert(fn_entry);
9992 fn_entry->alloca_list.append(new_instruction);10164 fn_entry->alloca_list.append(new_instruction);
...@@ -10012,20 +10184,17 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s...@@ -10012,20 +10184,17 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
10012 ZigType *array_type = array->value.type;10184 ZigType *array_type = array->value.type;
10013 assert(array_type->id == ZigTypeIdArray);10185 assert(array_type->id == ZigTypeIdArray);
1001410186
10015 if (instr_is_comptime(array)) {10187 if (instr_is_comptime(array) || array_type->data.array.len == 0) {
10016 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10188 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10017 source_instr->source_node, wanted_type);
10018 init_const_slice(ira->codegen, &result->value, &array->value, 0, array_type->data.array.len, true);10189 init_const_slice(ira->codegen, &result->value, &array->value, 0, array_type->data.array.len, true);
10019 result->value.type = wanted_type;10190 result->value.type = wanted_type;
10020 return result;10191 return result;
10021 }10192 }
1002210193
10023 IrInstruction *start = ir_create_const(&ira->new_irb, source_instr->scope,10194 IrInstruction *start = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize);
10024 source_instr->source_node, ira->codegen->builtin_types.entry_usize);
10025 init_const_usize(ira->codegen, &start->value, 0);10195 init_const_usize(ira->codegen, &start->value, 0);
1002610196
10027 IrInstruction *end = ir_create_const(&ira->new_irb, source_instr->scope,10197 IrInstruction *end = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize);
10028 source_instr->source_node, ira->codegen->builtin_types.entry_usize);
10029 init_const_usize(ira->codegen, &end->value, array_type->data.array.len);10198 init_const_usize(ira->codegen, &end->value, array_type->data.array.len);
1003010199
10031 if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false);10200 if (!array_ptr) array_ptr = ir_get_ref(ira, source_instr, array, true, false);
...@@ -10064,8 +10233,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour...@@ -10064,8 +10233,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
10064 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);10233 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
10065 if (!val)10234 if (!val)
10066 return ira->codegen->invalid_instruction;10235 return ira->codegen->invalid_instruction;
10067 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10236 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10068 source_instr->source_node, wanted_type);
10069 init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag);10237 init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag);
10070 return result;10238 return result;
10071 }10239 }
...@@ -10075,8 +10243,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour...@@ -10075,8 +10243,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
10075 actual_type->data.enumeration.src_field_count == 1)10243 actual_type->data.enumeration.src_field_count == 1)
10076 {10244 {
10077 assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int);10245 assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int);
10078 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10246 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10079 source_instr->source_node, wanted_type);
10080 init_const_bigint(&result->value, wanted_type,10247 init_const_bigint(&result->value, wanted_type,
10081 &actual_type->data.enumeration.fields[0].value);10248 &actual_type->data.enumeration.fields[0].value);
10082 return result;10249 return result;
...@@ -10099,8 +10266,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou...@@ -10099,8 +10266,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
10099 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);10266 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
10100 if (!val)10267 if (!val)
10101 return ira->codegen->invalid_instruction;10268 return ira->codegen->invalid_instruction;
10102 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10269 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10103 source_instr->source_node, wanted_type);
10104 result->value.special = ConstValSpecialStatic;10270 result->value.special = ConstValSpecialStatic;
10105 result->value.type = wanted_type;10271 result->value.type = wanted_type;
10106 bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_union.tag);10272 bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_union.tag);
...@@ -10111,8 +10277,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou...@@ -10111,8 +10277,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
10111 if (wanted_type->data.enumeration.layout == ContainerLayoutAuto &&10277 if (wanted_type->data.enumeration.layout == ContainerLayoutAuto &&
10112 wanted_type->data.enumeration.src_field_count == 1)10278 wanted_type->data.enumeration.src_field_count == 1)
10113 {10279 {
10114 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10280 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10115 source_instr->source_node, wanted_type);
10116 result->value.special = ConstValSpecialStatic;10281 result->value.special = ConstValSpecialStatic;
10117 result->value.type = wanted_type;10282 result->value.type = wanted_type;
10118 TypeEnumField *enum_field = target->value.type->data.unionation.fields[0].enum_field;10283 TypeEnumField *enum_field = target->value.type->data.unionation.fields[0].enum_field;
...@@ -10129,8 +10294,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou...@@ -10129,8 +10294,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
10129static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr,10294static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr,
10130 IrInstruction *target, ZigType *wanted_type)10295 IrInstruction *target, ZigType *wanted_type)
10131{10296{
10132 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10297 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10133 source_instr->source_node, wanted_type);
10134 init_const_undefined(ira->codegen, &result->value);10298 init_const_undefined(ira->codegen, &result->value);
10135 return result;10299 return result;
10136}10300}
...@@ -10162,8 +10326,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so...@@ -10162,8 +10326,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so
10162 buf_sprintf("field '%s' declared here", buf_ptr(union_field->name)));10326 buf_sprintf("field '%s' declared here", buf_ptr(union_field->name)));
10163 return ira->codegen->invalid_instruction;10327 return ira->codegen->invalid_instruction;
10164 }10328 }
10165 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10329 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10166 source_instr->source_node, wanted_type);
10167 result->value.special = ConstValSpecialStatic;10330 result->value.special = ConstValSpecialStatic;
10168 result->value.type = wanted_type;10331 result->value.type = wanted_type;
10169 bigint_init_bigint(&result->value.data.x_union.tag, &val->data.x_enum_tag);10332 bigint_init_bigint(&result->value.data.x_union.tag, &val->data.x_enum_tag);
...@@ -10218,8 +10381,7 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction...@@ -10218,8 +10381,7 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction
10218 return ira->codegen->invalid_instruction;10381 return ira->codegen->invalid_instruction;
10219 }10382 }
10220 }10383 }
10221 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10384 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10222 source_instr->source_node, wanted_type);
10223 result->value.type = wanted_type;10385 result->value.type = wanted_type;
10224 if (wanted_type->id == ZigTypeIdInt) {10386 if (wanted_type->id == ZigTypeIdInt) {
10225 bigint_init_bigint(&result->value.data.x_bigint, &val->data.x_bigint);10387 bigint_init_bigint(&result->value.data.x_bigint, &val->data.x_bigint);
...@@ -10273,8 +10435,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour...@@ -10273,8 +10435,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
10273 return ira->codegen->invalid_instruction;10435 return ira->codegen->invalid_instruction;
10274 }10436 }
1027510437
10276 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10438 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10277 source_instr->source_node, wanted_type);
10278 bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_bigint);10439 bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_bigint);
10279 return result;10440 return result;
10280 }10441 }
...@@ -10292,8 +10453,7 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction...@@ -10292,8 +10453,7 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction
10292 if (!val)10453 if (!val)
10293 return ira->codegen->invalid_instruction;10454 return ira->codegen->invalid_instruction;
1029410455
10295 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10456 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10296 source_instr->source_node, wanted_type);
10297 if (wanted_type->id == ZigTypeIdComptimeFloat) {10457 if (wanted_type->id == ZigTypeIdComptimeFloat) {
10298 float_init_float(&result->value, val);10458 float_init_float(&result->value, val);
10299 } else if (wanted_type->id == ZigTypeIdComptimeInt) {10459 } else if (wanted_type->id == ZigTypeIdComptimeInt) {
...@@ -10316,8 +10476,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc...@@ -10316,8 +10476,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc
10316 if (!val)10476 if (!val)
10317 return ira->codegen->invalid_instruction;10477 return ira->codegen->invalid_instruction;
1031810478
10319 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10479 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10320 source_instr->source_node, wanted_type);
1032110480
10322 if (!resolve_inferred_error_set(ira->codegen, wanted_type, source_instr->source_node)) {10481 if (!resolve_inferred_error_set(ira->codegen, wanted_type, source_instr->source_node)) {
10323 return ira->codegen->invalid_instruction;10482 return ira->codegen->invalid_instruction;
...@@ -10381,12 +10540,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc...@@ -10381,12 +10540,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
10381 if (!val)10540 if (!val)
10382 return ira->codegen->invalid_instruction;10541 return ira->codegen->invalid_instruction;
1038310542
10384 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10543 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10385 source_instr->source_node, wanted_type);
1038610544
10387 ErrorTableEntry *err;10545 ErrorTableEntry *err;
10388 if (err_type->id == ZigTypeIdErrorUnion) {10546 if (err_type->id == ZigTypeIdErrorUnion) {
10389 err = val->data.x_err_union.err;10547 err = val->data.x_err_union.error_set->data.x_err_set;
10390 } else if (err_type->id == ZigTypeIdErrorSet) {10548 } else if (err_type->id == ZigTypeIdErrorSet) {
10391 err = val->data.x_err_set;10549 err = val->data.x_err_set;
10392 } else {10550 } else {
...@@ -10421,15 +10579,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc...@@ -10421,15 +10579,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
10421 return ira->codegen->invalid_instruction;10579 return ira->codegen->invalid_instruction;
10422 }10580 }
10423 if (err_set_type->data.error_set.err_count == 0) {10581 if (err_set_type->data.error_set.err_count == 0) {
10424 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10582 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10425 source_instr->source_node, wanted_type);
10426 result->value.type = wanted_type;
10427 bigint_init_unsigned(&result->value.data.x_bigint, 0);10583 bigint_init_unsigned(&result->value.data.x_bigint, 0);
10428 return result;10584 return result;
10429 } else if (err_set_type->data.error_set.err_count == 1) {10585 } else if (err_set_type->data.error_set.err_count == 1) {
10430 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,10586 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10431 source_instr->source_node, wanted_type);
10432 result->value.type = wanted_type;
10433 ErrorTableEntry *err = err_set_type->data.error_set.errors[0];10587 ErrorTableEntry *err = err_set_type->data.error_set.errors[0];
10434 bigint_init_unsigned(&result->value.data.x_bigint, err->value);10588 bigint_init_unsigned(&result->value.data.x_bigint, err->value);
10435 return result;10589 return result;
...@@ -10476,8 +10630,8 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou...@@ -10476,8 +10630,8 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou
10476 array_val->type = array_type;10630 array_val->type = array_type;
10477 array_val->data.x_array.special = ConstArraySpecialNone;10631 array_val->data.x_array.special = ConstArraySpecialNone;
10478 array_val->data.x_array.data.s_none.elements = pointee;10632 array_val->data.x_array.data.s_none.elements = pointee;
10479 array_val->data.x_array.data.s_none.parent.id = ConstParentIdScalar;10633 array_val->parent.id = ConstParentIdScalar;
10480 array_val->data.x_array.data.s_none.parent.data.p_scalar.scalar_val = pointee;10634 array_val->parent.data.p_scalar.scalar_val = pointee;
1048110635
10482 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,10636 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
10483 source_instr->scope, source_instr->source_node);10637 source_instr->scope, source_instr->source_node);
...@@ -10598,6 +10752,32 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa...@@ -10598,6 +10752,32 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
10598 }10752 }
10599}10753}
1060010754
10755static IrInstruction *ir_analyze_array_to_vector(IrAnalyze *ira, IrInstruction *source_instr,
10756 IrInstruction *array, ZigType *vector_type)
10757{
10758 if (instr_is_comptime(array)) {
10759 // arrays and vectors have the same ConstExprValue representation
10760 IrInstruction *result = ir_const(ira, source_instr, vector_type);
10761 copy_const_val(&result->value, &array->value, false);
10762 result->value.type = vector_type;
10763 return result;
10764 }
10765 return ir_build_array_to_vector(ira, source_instr, array, vector_type);
10766}
10767
10768static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *source_instr,
10769 IrInstruction *vector, ZigType *array_type)
10770{
10771 if (instr_is_comptime(vector)) {
10772 // arrays and vectors have the same ConstExprValue representation
10773 IrInstruction *result = ir_const(ira, source_instr, array_type);
10774 copy_const_val(&result->value, &vector->value, false);
10775 result->value.type = array_type;
10776 return result;
10777 }
10778 return ir_build_vector_to_array(ira, source_instr, vector, array_type);
10779}
10780
10601static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,10781static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
10602 ZigType *wanted_type, IrInstruction *value)10782 ZigType *wanted_type, IrInstruction *value)
10603{10783{
...@@ -10625,12 +10805,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10625,12 +10805,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10625 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,10805 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,
10626 false).id == ConstCastResultIdOk)10806 false).id == ConstCastResultIdOk)
10627 {10807 {
10628 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);10808 return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type);
10629 } else if (actual_type->id == ZigTypeIdComptimeInt ||10809 } else if (actual_type->id == ZigTypeIdComptimeInt ||
10630 actual_type->id == ZigTypeIdComptimeFloat)10810 actual_type->id == ZigTypeIdComptimeFloat)
10631 {10811 {
10632 if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {10812 if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {
10633 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);10813 return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type);
10634 } else {10814 } else {
10635 return ira->codegen->invalid_instruction;10815 return ira->codegen->invalid_instruction;
10636 }10816 }
...@@ -10654,7 +10834,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10654,7 +10834,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10654 wanted_child_type);10834 wanted_child_type);
10655 if (type_is_invalid(cast1->value.type))10835 if (type_is_invalid(cast1->value.type))
10656 return ira->codegen->invalid_instruction;10836 return ira->codegen->invalid_instruction;
10657 return ir_analyze_maybe_wrap(ira, source_instr, cast1, wanted_type);10837 return ir_analyze_optional_wrap(ira, source_instr, cast1, wanted_type);
10658 }10838 }
10659 }10839 }
10660 }10840 }
...@@ -10707,6 +10887,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10707,6 +10887,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10707 (wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt ||10887 (wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt ||
10708 wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat))10888 wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat))
10709 {10889 {
10890 if (value->value.special == ConstValSpecialUndef) {
10891 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10892 result->value.special = ConstValSpecialUndef;
10893 return result;
10894 }
10710 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {10895 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {
10711 if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) {10896 if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) {
10712 IrInstruction *result = ir_const(ira, source_instr, wanted_type);10897 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
...@@ -10760,6 +10945,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10760,6 +10945,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1076010945
1076110946
10762 // cast from [N]T to []const T10947 // cast from [N]T to []const T
10948 // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
10763 if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) {10949 if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) {
10764 ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;10950 ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
10765 assert(ptr_type->id == ZigTypeIdPointer);10951 assert(ptr_type->id == ZigTypeIdPointer);
...@@ -10772,6 +10958,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10772,6 +10958,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10772 }10958 }
1077310959
10774 // cast from [N]T to ?[]const T10960 // cast from [N]T to ?[]const T
10961 // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
10775 if (wanted_type->id == ZigTypeIdOptional &&10962 if (wanted_type->id == ZigTypeIdOptional &&
10776 is_slice(wanted_type->data.maybe.child_type) &&10963 is_slice(wanted_type->data.maybe.child_type) &&
10777 actual_type->id == ZigTypeIdArray)10964 actual_type->id == ZigTypeIdArray)
...@@ -10866,7 +11053,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10866,7 +11053,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10866 }11053 }
10867 }11054 }
1086811055
10869 // cast from error set to error union type11056 // cast from E to E!T
10870 if (wanted_type->id == ZigTypeIdErrorUnion &&11057 if (wanted_type->id == ZigTypeIdErrorUnion &&
10871 actual_type->id == ZigTypeIdErrorSet)11058 actual_type->id == ZigTypeIdErrorSet)
10872 {11059 {
...@@ -10979,6 +11166,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10979,6 +11166,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10979 }11166 }
10980 }11167 }
1098111168
11169 // cast from @Vector(N, T) to [N]T
11170 if (wanted_type->id == ZigTypeIdArray && actual_type->id == ZigTypeIdVector &&
11171 wanted_type->data.array.len == actual_type->data.vector.len &&
11172 types_match_const_cast_only(ira, wanted_type->data.array.child_type,
11173 actual_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk)
11174 {
11175 return ir_analyze_vector_to_array(ira, source_instr, value, wanted_type);
11176 }
11177
11178 // cast from [N]T to @Vector(N, T)
11179 if (actual_type->id == ZigTypeIdArray && wanted_type->id == ZigTypeIdVector &&
11180 actual_type->data.array.len == wanted_type->data.vector.len &&
11181 types_match_const_cast_only(ira, actual_type->data.array.child_type,
11182 wanted_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk)
11183 {
11184 return ir_analyze_array_to_vector(ira, source_instr, value, wanted_type);
11185 }
1098211186
10983 // cast from undefined to anything11187 // cast from undefined to anything
10984 if (actual_type->id == ZigTypeIdUndefined) {11188 if (actual_type->id == ZigTypeIdUndefined) {
...@@ -11018,8 +11222,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -11018,8 +11222,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
11018 ZigType *child_type = type_entry->data.pointer.child_type;11222 ZigType *child_type = type_entry->data.pointer.child_type;
11019 // dereferencing a *u0 is comptime known to be 011223 // dereferencing a *u0 is comptime known to be 0
11020 if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) {11224 if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) {
11021 IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,11225 IrInstruction *result = ir_const(ira, source_instruction, child_type);
11022 source_instruction->source_node, child_type);
11023 init_const_unsigned_negative(&result->value, child_type, 0, false);11226 init_const_unsigned_negative(&result->value, child_type, 0, false);
11024 return result;11227 return result;
11025 }11228 }
...@@ -11033,8 +11236,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -11033,8 +11236,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
11033 {11236 {
11034 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);11237 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
11035 if (pointee->special != ConstValSpecialRuntime) {11238 if (pointee->special != ConstValSpecialRuntime) {
11036 IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,11239 IrInstruction *result = ir_const(ira, source_instruction, child_type);
11037 source_instruction->source_node, child_type);
1103811240
11039 if ((err = ir_read_const_ptr(ira, ira->codegen, source_instruction->source_node, &result->value,11241 if ((err = ir_read_const_ptr(ira, ira->codegen, source_instruction->source_node, &result->value,
11040 &ptr->value)))11242 &ptr->value)))
...@@ -11046,7 +11248,11 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc...@@ -11046,7 +11248,11 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
11046 }11248 }
11047 }11249 }
11048 }11250 }
11049 // TODO if the instruction is a const ref instruction we can skip it11251 // if the instruction is a const ref instruction we can skip it
11252 if (ptr->id == IrInstructionIdRef) {
11253 IrInstructionRef *ref_inst = reinterpret_cast<IrInstructionRef *>(ptr);
11254 return ref_inst->value;
11255 }
11050 IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,11256 IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,
11051 source_instruction->source_node, ptr);11257 source_instruction->source_node, ptr);
11052 load_ptr_instruction->value.type = child_type;11258 load_ptr_instruction->value.type = child_type;
...@@ -11293,8 +11499,7 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio...@@ -11293,8 +11499,7 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio
1129311499
11294static IrInstruction *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *instruction) {11500static IrInstruction *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *instruction) {
11295 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);11501 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
11296 // TODO determine if we need to use copy_const_val here11502 copy_const_val(&result->value, &instruction->base.value, true);
11297 result->value = instruction->base.value;
11298 return result;11503 return result;
11299}11504}
1130011505
...@@ -11369,6 +11574,8 @@ static bool optional_value_is_null(ConstExprValue *val) {...@@ -11369,6 +11574,8 @@ static bool optional_value_is_null(ConstExprValue *val) {
11369 if (get_codegen_ptr_type(val->type) != nullptr) {11574 if (get_codegen_ptr_type(val->type) != nullptr) {
11370 return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&11575 return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
11371 val->data.x_ptr.data.hard_coded_addr.addr == 0;11576 val->data.x_ptr.data.hard_coded_addr.addr == 0;
11577 } else if (is_opt_err_set(val->type)) {
11578 return val->data.x_err_set == nullptr;
11372 } else {11579 } else {
11373 return val->data.x_optional == nullptr;11580 return val->data.x_optional == nullptr;
11374 }11581 }
...@@ -11523,6 +11730,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11523,6 +11730,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11523 case ZigTypeIdComptimeInt:11730 case ZigTypeIdComptimeInt:
11524 case ZigTypeIdInt:11731 case ZigTypeIdInt:
11525 case ZigTypeIdFloat:11732 case ZigTypeIdFloat:
11733 case ZigTypeIdVector:
11526 operator_allowed = true;11734 operator_allowed = true;
11527 break;11735 break;
1152811736
...@@ -11568,19 +11776,18 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11568,19 +11776,18 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11568 if (casted_op2 == ira->codegen->invalid_instruction)11776 if (casted_op2 == ira->codegen->invalid_instruction)
11569 return ira->codegen->invalid_instruction;11777 return ira->codegen->invalid_instruction;
1157011778
11571 bool requires_comptime;11779 bool one_possible_value;
11572 switch (type_requires_comptime(ira->codegen, resolved_type)) {11780 switch (type_has_one_possible_value(ira->codegen, resolved_type)) {
11573 case ReqCompTimeYes:11781 case OnePossibleValueInvalid:
11574 requires_comptime = true;11782 return ira->codegen->invalid_instruction;
11783 case OnePossibleValueYes:
11784 one_possible_value = true;
11575 break;11785 break;
11576 case ReqCompTimeNo:11786 case OnePossibleValueNo:
11577 requires_comptime = false;11787 one_possible_value = false;
11578 break;11788 break;
11579 case ReqCompTimeInvalid:
11580 return ira->codegen->invalid_instruction;
11581 }11789 }
1158211790
11583 bool one_possible_value = !requires_comptime && !type_has_bits(resolved_type);
11584 if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {11791 if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {
11585 ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad);11792 ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad);
11586 if (op1_val == nullptr)11793 if (op1_val == nullptr)
...@@ -11654,8 +11861,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *...@@ -11654,8 +11861,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
11654 return result;11861 return result;
11655}11862}
1165611863
11657static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,11864static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, IrInstruction *source_instr, ZigType *type_entry,
11658 IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val)11865 ConstExprValue *op1_val, IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val)
11659{11866{
11660 bool is_int;11867 bool is_int;
11661 bool is_float;11868 bool is_float;
...@@ -11677,10 +11884,10 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,...@@ -11677,10 +11884,10 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
11677 if ((op_id == IrBinOpDivUnspecified || op_id == IrBinOpRemRem || op_id == IrBinOpRemMod ||11884 if ((op_id == IrBinOpDivUnspecified || op_id == IrBinOpRemRem || op_id == IrBinOpRemMod ||
11678 op_id == IrBinOpDivTrunc || op_id == IrBinOpDivFloor) && op2_zcmp == CmpEQ)11885 op_id == IrBinOpDivTrunc || op_id == IrBinOpDivFloor) && op2_zcmp == CmpEQ)
11679 {11886 {
11680 return ErrorDivByZero;11887 return ir_add_error(ira, source_instr, buf_sprintf("division by zero"));
11681 }11888 }
11682 if ((op_id == IrBinOpRemRem || op_id == IrBinOpRemMod) && op2_zcmp == CmpLT) {11889 if ((op_id == IrBinOpRemRem || op_id == IrBinOpRemMod) && op2_zcmp == CmpLT) {
11683 return ErrorNegativeDenominator;11890 return ir_add_error(ira, source_instr, buf_sprintf("negative denominator"));
11684 }11891 }
1168511892
11686 switch (op_id) {11893 switch (op_id) {
...@@ -11726,7 +11933,7 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,...@@ -11726,7 +11933,7 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
11726 BigInt orig_bigint;11933 BigInt orig_bigint;
11727 bigint_shl(&orig_bigint, &out_val->data.x_bigint, &op2_val->data.x_bigint);11934 bigint_shl(&orig_bigint, &out_val->data.x_bigint, &op2_val->data.x_bigint);
11728 if (bigint_cmp(&op1_val->data.x_bigint, &orig_bigint) != CmpEQ) {11935 if (bigint_cmp(&op1_val->data.x_bigint, &orig_bigint) != CmpEQ) {
11729 return ErrorShiftedOutOneBits;11936 return ir_add_error(ira, source_instr, buf_sprintf("exact shift shifted out 1 bits"));
11730 }11937 }
11731 break;11938 break;
11732 }11939 }
...@@ -11794,14 +12001,14 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,...@@ -11794,14 +12001,14 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
11794 BigInt remainder;12001 BigInt remainder;
11795 bigint_rem(&remainder, &op1_val->data.x_bigint, &op2_val->data.x_bigint);12002 bigint_rem(&remainder, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
11796 if (bigint_cmp_zero(&remainder) != CmpEQ) {12003 if (bigint_cmp_zero(&remainder) != CmpEQ) {
11797 return ErrorExactDivRemainder;12004 return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder"));
11798 }12005 }
11799 } else {12006 } else {
11800 float_div_trunc(out_val, op1_val, op2_val);12007 float_div_trunc(out_val, op1_val, op2_val);
11801 ConstExprValue remainder;12008 ConstExprValue remainder;
11802 float_rem(&remainder, op1_val, op2_val);12009 float_rem(&remainder, op1_val, op2_val);
11803 if (float_cmp_zero(&remainder) != CmpEQ) {12010 if (float_cmp_zero(&remainder) != CmpEQ) {
11804 return ErrorExactDivRemainder;12011 return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder"));
11805 }12012 }
11806 }12013 }
11807 break;12014 break;
...@@ -11825,13 +12032,51 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,...@@ -11825,13 +12032,51 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
11825 if (!bigint_fits_in_bits(&out_val->data.x_bigint, type_entry->data.integral.bit_count,12032 if (!bigint_fits_in_bits(&out_val->data.x_bigint, type_entry->data.integral.bit_count,
11826 type_entry->data.integral.is_signed))12033 type_entry->data.integral.is_signed))
11827 {12034 {
11828 return ErrorOverflow;12035 return ir_add_error(ira, source_instr, buf_sprintf("operation caused overflow"));
11829 }12036 }
11830 }12037 }
1183112038
11832 out_val->type = type_entry;12039 out_val->type = type_entry;
11833 out_val->special = ConstValSpecialStatic;12040 out_val->special = ConstValSpecialStatic;
11834 return 0;12041 return nullptr;
12042}
12043
12044// This works on operands that have already been checked to be comptime known.
12045static IrInstruction *ir_analyze_math_op(IrAnalyze *ira, IrInstruction *source_instr,
12046 ZigType *type_entry, ConstExprValue *op1_val, IrBinOp op_id, ConstExprValue *op2_val)
12047{
12048 IrInstruction *result_instruction = ir_const(ira, source_instr, type_entry);
12049 ConstExprValue *out_val = &result_instruction->value;
12050 if (type_entry->id == ZigTypeIdVector) {
12051 expand_undef_array(ira->codegen, op1_val);
12052 expand_undef_array(ira->codegen, op2_val);
12053 out_val->special = ConstValSpecialUndef;
12054 expand_undef_array(ira->codegen, out_val);
12055 size_t len = type_entry->data.vector.len;
12056 ZigType *scalar_type = type_entry->data.vector.elem_type;
12057 for (size_t i = 0; i < len; i += 1) {
12058 ConstExprValue *scalar_op1_val = &op1_val->data.x_array.data.s_none.elements[i];
12059 ConstExprValue *scalar_op2_val = &op2_val->data.x_array.data.s_none.elements[i];
12060 ConstExprValue *scalar_out_val = &out_val->data.x_array.data.s_none.elements[i];
12061 assert(scalar_op1_val->type == scalar_type);
12062 assert(scalar_op2_val->type == scalar_type);
12063 assert(scalar_out_val->type == scalar_type);
12064 ErrorMsg *msg = ir_eval_math_op_scalar(ira, source_instr, scalar_type,
12065 scalar_op1_val, op_id, scalar_op2_val, scalar_out_val);
12066 if (msg != nullptr) {
12067 add_error_note(ira->codegen, msg, source_instr->source_node,
12068 buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i));
12069 return ira->codegen->invalid_instruction;
12070 }
12071 }
12072 out_val->type = type_entry;
12073 out_val->special = ConstValSpecialStatic;
12074 } else {
12075 if (ir_eval_math_op_scalar(ira, source_instr, type_entry, op1_val, op_id, op2_val, out_val) != nullptr) {
12076 return ira->codegen->invalid_instruction;
12077 }
12078 }
12079 return ir_implicit_cast(ira, result_instruction, type_entry);
11835}12080}
1183612081
11837static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {12082static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
...@@ -11903,24 +12148,7 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b...@@ -11903,24 +12148,7 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b
11903 if (op2_val == nullptr)12148 if (op2_val == nullptr)
11904 return ira->codegen->invalid_instruction;12149 return ira->codegen->invalid_instruction;
1190512150
11906 IrInstruction *result_instruction = ir_const(ira, &bin_op_instruction->base, op1->value.type);12151 return ir_analyze_math_op(ira, &bin_op_instruction->base, op1->value.type, op1_val, op_id, op2_val);
11907
11908 int err;
11909 if ((err = ir_eval_math_op(op1->value.type, op1_val, op_id, op2_val, &result_instruction->value))) {
11910 if (err == ErrorOverflow) {
11911 ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("operation caused overflow"));
11912 return ira->codegen->invalid_instruction;
11913 } else if (err == ErrorShiftedOutOneBits) {
11914 ir_add_error(ira, &bin_op_instruction->base, buf_sprintf("exact shift shifted out 1 bits"));
11915 return ira->codegen->invalid_instruction;
11916 } else {
11917 zig_unreachable();
11918 }
11919 return ira->codegen->invalid_instruction;
11920 }
11921
11922 ir_num_lit_fits_in_other_type(ira, result_instruction, op1->value.type, false);
11923 return result_instruction;
11924 } else if (op1->value.type->id == ZigTypeIdComptimeInt) {12152 } else if (op1->value.type->id == ZigTypeIdComptimeInt) {
11925 ir_add_error(ira, &bin_op_instruction->base,12153 ir_add_error(ira, &bin_op_instruction->base,
11926 buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known"));12154 buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known"));
...@@ -11939,32 +12167,74 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b...@@ -11939,32 +12167,74 @@ static IrInstruction *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *b
11939 return result;12167 return result;
11940}12168}
1194112169
11942static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {12170static bool ok_float_op(IrBinOp op) {
11943 IrInstruction *op1 = instruction->op1->child;12171 switch (op) {
11944 if (type_is_invalid(op1->value.type))12172 case IrBinOpInvalid:
11945 return ira->codegen->invalid_instruction;12173 zig_unreachable();
1194612174 case IrBinOpAdd:
11947 IrInstruction *op2 = instruction->op2->child;12175 case IrBinOpSub:
11948 if (type_is_invalid(op2->value.type))12176 case IrBinOpMult:
11949 return ira->codegen->invalid_instruction;12177 case IrBinOpDivUnspecified:
1195012178 case IrBinOpDivTrunc:
11951 IrBinOp op_id = instruction->op_id;12179 case IrBinOpDivFloor:
1195212180 case IrBinOpDivExact:
11953 // look for pointer math12181 case IrBinOpRemRem:
11954 if (op1->value.type->id == ZigTypeIdPointer && op1->value.type->data.pointer.ptr_len == PtrLenUnknown &&12182 case IrBinOpRemMod:
11955 (op_id == IrBinOpAdd || op_id == IrBinOpSub))12183 return true;
11956 {
11957 IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize);
11958 if (casted_op2 == ira->codegen->invalid_instruction)
11959 return ira->codegen->invalid_instruction;
11960
11961 IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
11962 instruction->base.source_node, op_id, op1, casted_op2, true);
11963 result->value.type = op1->value.type;
11964 return result;
11965 }
1196612184
11967 IrInstruction *instructions[] = {op1, op2};12185 case IrBinOpBoolOr:
12186 case IrBinOpBoolAnd:
12187 case IrBinOpCmpEq:
12188 case IrBinOpCmpNotEq:
12189 case IrBinOpCmpLessThan:
12190 case IrBinOpCmpGreaterThan:
12191 case IrBinOpCmpLessOrEq:
12192 case IrBinOpCmpGreaterOrEq:
12193 case IrBinOpBinOr:
12194 case IrBinOpBinXor:
12195 case IrBinOpBinAnd:
12196 case IrBinOpBitShiftLeftLossy:
12197 case IrBinOpBitShiftLeftExact:
12198 case IrBinOpBitShiftRightLossy:
12199 case IrBinOpBitShiftRightExact:
12200 case IrBinOpAddWrap:
12201 case IrBinOpSubWrap:
12202 case IrBinOpMultWrap:
12203 case IrBinOpRemUnspecified:
12204 case IrBinOpArrayCat:
12205 case IrBinOpArrayMult:
12206 case IrBinOpMergeErrorSets:
12207 return false;
12208 }
12209 zig_unreachable();
12210}
12211
12212static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {
12213 IrInstruction *op1 = instruction->op1->child;
12214 if (type_is_invalid(op1->value.type))
12215 return ira->codegen->invalid_instruction;
12216
12217 IrInstruction *op2 = instruction->op2->child;
12218 if (type_is_invalid(op2->value.type))
12219 return ira->codegen->invalid_instruction;
12220
12221 IrBinOp op_id = instruction->op_id;
12222
12223 // look for pointer math
12224 if (op1->value.type->id == ZigTypeIdPointer && op1->value.type->data.pointer.ptr_len == PtrLenUnknown &&
12225 (op_id == IrBinOpAdd || op_id == IrBinOpSub))
12226 {
12227 IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize);
12228 if (casted_op2 == ira->codegen->invalid_instruction)
12229 return ira->codegen->invalid_instruction;
12230
12231 IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
12232 instruction->base.source_node, op_id, op1, casted_op2, true);
12233 result->value.type = op1->value.type;
12234 return result;
12235 }
12236
12237 IrInstruction *instructions[] = {op1, op2};
11968 ZigType *resolved_type = ir_resolve_peer_types(ira, instruction->base.source_node, nullptr, instructions, 2);12238 ZigType *resolved_type = ir_resolve_peer_types(ira, instruction->base.source_node, nullptr, instructions, 2);
11969 if (type_is_invalid(resolved_type))12239 if (type_is_invalid(resolved_type))
11970 return ira->codegen->invalid_instruction;12240 return ira->codegen->invalid_instruction;
...@@ -12076,21 +12346,20 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -12076,21 +12346,20 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
12076 op_id = IrBinOpRemRem;12346 op_id = IrBinOpRemRem;
12077 }12347 }
1207812348
12349 bool ok = false;
12079 if (is_int) {12350 if (is_int) {
12080 // int12351 ok = true;
12081 } else if (is_float &&12352 } else if (is_float && ok_float_op(op_id)) {
12082 (op_id == IrBinOpAdd ||12353 ok = true;
12083 op_id == IrBinOpSub ||12354 } else if (resolved_type->id == ZigTypeIdVector) {
12084 op_id == IrBinOpMult ||12355 ZigType *elem_type = resolved_type->data.vector.elem_type;
12085 op_id == IrBinOpDivUnspecified ||12356 if (elem_type->id == ZigTypeIdInt || elem_type->id == ZigTypeIdComptimeInt) {
12086 op_id == IrBinOpDivTrunc ||12357 ok = true;
12087 op_id == IrBinOpDivFloor ||12358 } else if ((elem_type->id == ZigTypeIdFloat || elem_type->id == ZigTypeIdComptimeFloat) && ok_float_op(op_id)) {
12088 op_id == IrBinOpDivExact ||12359 ok = true;
12089 op_id == IrBinOpRemRem ||12360 }
12090 op_id == IrBinOpRemMod))12361 }
12091 {12362 if (!ok) {
12092 // float
12093 } else {
12094 AstNode *source_node = instruction->base.source_node;12363 AstNode *source_node = instruction->base.source_node;
12095 ir_add_error_node(ira, source_node,12364 ir_add_error_node(ira, source_node,
12096 buf_sprintf("invalid operands to binary expression: '%s' and '%s'",12365 buf_sprintf("invalid operands to binary expression: '%s' and '%s'",
...@@ -12125,30 +12394,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -12125,30 +12394,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
12125 if (op2_val == nullptr)12394 if (op2_val == nullptr)
12126 return ira->codegen->invalid_instruction;12395 return ira->codegen->invalid_instruction;
1212712396
12128 IrInstruction *result_instruction = ir_const(ira, &instruction->base, resolved_type);12397 return ir_analyze_math_op(ira, &instruction->base, resolved_type, op1_val, op_id, op2_val);
12129
12130 int err;
12131 if ((err = ir_eval_math_op(resolved_type, op1_val, op_id, op2_val, &result_instruction->value))) {
12132 if (err == ErrorDivByZero) {
12133 ir_add_error(ira, &instruction->base, buf_sprintf("division by zero"));
12134 return ira->codegen->invalid_instruction;
12135 } else if (err == ErrorOverflow) {
12136 ir_add_error(ira, &instruction->base, buf_sprintf("operation caused overflow"));
12137 return ira->codegen->invalid_instruction;
12138 } else if (err == ErrorExactDivRemainder) {
12139 ir_add_error(ira, &instruction->base, buf_sprintf("exact division had a remainder"));
12140 return ira->codegen->invalid_instruction;
12141 } else if (err == ErrorNegativeDenominator) {
12142 ir_add_error(ira, &instruction->base, buf_sprintf("negative denominator"));
12143 return ira->codegen->invalid_instruction;
12144 } else {
12145 zig_unreachable();
12146 }
12147 return ira->codegen->invalid_instruction;
12148 }
12149
12150 ir_num_lit_fits_in_other_type(ira, result_instruction, resolved_type, false);
12151 return result_instruction;
12152 }12398 }
1215312399
12154 IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,12400 IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
...@@ -12202,7 +12448,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -12202,7 +12448,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
12202 op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val;12448 op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
12203 op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;12449 op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
12204 ConstExprValue *len_val = &op1_val->data.x_struct.fields[slice_len_index];12450 ConstExprValue *len_val = &op1_val->data.x_struct.fields[slice_len_index];
12205 op1_array_end = bigint_as_unsigned(&len_val->data.x_bigint);12451 op1_array_end = op1_array_index + bigint_as_unsigned(&len_val->data.x_bigint);
12206 } else {12452 } else {
12207 ir_add_error(ira, op1,12453 ir_add_error(ira, op1,
12208 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name)));12454 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name)));
...@@ -12212,13 +12458,9 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -12212,13 +12458,9 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
12212 ConstExprValue *op2_array_val;12458 ConstExprValue *op2_array_val;
12213 size_t op2_array_index;12459 size_t op2_array_index;
12214 size_t op2_array_end;12460 size_t op2_array_end;
12461 bool op2_type_valid;
12215 if (op2_type->id == ZigTypeIdArray) {12462 if (op2_type->id == ZigTypeIdArray) {
12216 if (op2_type->data.array.child_type != child_type) {12463 op2_type_valid = op2_type->data.array.child_type == child_type;
12217 ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
12218 buf_ptr(&child_type->name),
12219 buf_ptr(&op2->value.type->name)));
12220 return ira->codegen->invalid_instruction;
12221 }
12222 op2_array_val = op2_val;12464 op2_array_val = op2_val;
12223 op2_array_index = 0;12465 op2_array_index = 0;
12224 op2_array_end = op2_array_val->type->data.array.len;12466 op2_array_end = op2_array_val->type->data.array.len;
...@@ -12227,35 +12469,30 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -12227,35 +12469,30 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
12227 op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray &&12469 op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray &&
12228 op2_val->data.x_ptr.data.base_array.is_cstr)12470 op2_val->data.x_ptr.data.base_array.is_cstr)
12229 {12471 {
12230 if (child_type != ira->codegen->builtin_types.entry_u8) {12472 op2_type_valid = child_type == ira->codegen->builtin_types.entry_u8;
12231 ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
12232 buf_ptr(&child_type->name),
12233 buf_ptr(&op2->value.type->name)));
12234 return ira->codegen->invalid_instruction;
12235 }
12236 op2_array_val = op2_val->data.x_ptr.data.base_array.array_val;12473 op2_array_val = op2_val->data.x_ptr.data.base_array.array_val;
12237 op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index;12474 op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index;
12238 op2_array_end = op2_array_val->type->data.array.len - 1;12475 op2_array_end = op2_array_val->type->data.array.len - 1;
12239 } else if (is_slice(op2_type)) {12476 } else if (is_slice(op2_type)) {
12240 ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index].type_entry;12477 ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index].type_entry;
12241 if (ptr_type->data.pointer.child_type != child_type) {12478 op2_type_valid = ptr_type->data.pointer.child_type == child_type;
12242 ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
12243 buf_ptr(&child_type->name),
12244 buf_ptr(&op2->value.type->name)));
12245 return ira->codegen->invalid_instruction;
12246 }
12247 ConstExprValue *ptr_val = &op2_val->data.x_struct.fields[slice_ptr_index];12479 ConstExprValue *ptr_val = &op2_val->data.x_struct.fields[slice_ptr_index];
12248 assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);12480 assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
12249 op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val;12481 op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
12250 op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;12482 op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
12251 op2_array_end = op2_array_val->type->data.array.len;
12252 ConstExprValue *len_val = &op2_val->data.x_struct.fields[slice_len_index];12483 ConstExprValue *len_val = &op2_val->data.x_struct.fields[slice_len_index];
12253 op2_array_end = bigint_as_unsigned(&len_val->data.x_bigint);12484 op2_array_end = op2_array_index + bigint_as_unsigned(&len_val->data.x_bigint);
12254 } else {12485 } else {
12255 ir_add_error(ira, op2,12486 ir_add_error(ira, op2,
12256 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));12487 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));
12257 return ira->codegen->invalid_instruction;12488 return ira->codegen->invalid_instruction;
12258 }12489 }
12490 if (!op2_type_valid) {
12491 ir_add_error(ira, op2, buf_sprintf("expected array of type '%s', found '%s'",
12492 buf_ptr(&child_type->name),
12493 buf_ptr(&op2->value.type->name)));
12494 return ira->codegen->invalid_instruction;
12495 }
1225912496
12260 // The type of result is populated in the following if blocks12497 // The type of result is populated in the following if blocks
12261 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);12498 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
...@@ -12388,26 +12625,14 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *...@@ -12388,26 +12625,14 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
12388}12625}
1238912626
12390static IrInstruction *ir_analyze_merge_error_sets(IrAnalyze *ira, IrInstructionBinOp *instruction) {12627static IrInstruction *ir_analyze_merge_error_sets(IrAnalyze *ira, IrInstructionBinOp *instruction) {
12391 ZigType *op1_type = ir_resolve_type(ira, instruction->op1->child);12628 ZigType *op1_type = ir_resolve_error_set_type(ira, &instruction->base, instruction->op1->child);
12392 if (type_is_invalid(op1_type))12629 if (type_is_invalid(op1_type))
12393 return ira->codegen->invalid_instruction;12630 return ira->codegen->invalid_instruction;
1239412631
12395 if (op1_type->id != ZigTypeIdErrorSet) {12632 ZigType *op2_type = ir_resolve_error_set_type(ira, &instruction->base, instruction->op2->child);
12396 ir_add_error(ira, instruction->op1,
12397 buf_sprintf("expected error set type, found '%s'", buf_ptr(&op1_type->name)));
12398 return ira->codegen->invalid_instruction;
12399 }
12400
12401 ZigType *op2_type = ir_resolve_type(ira, instruction->op2->child);
12402 if (type_is_invalid(op2_type))12633 if (type_is_invalid(op2_type))
12403 return ira->codegen->invalid_instruction;12634 return ira->codegen->invalid_instruction;
1240412635
12405 if (op2_type->id != ZigTypeIdErrorSet) {
12406 ir_add_error(ira, instruction->op2,
12407 buf_sprintf("expected error set type, found '%s'", buf_ptr(&op2_type->name)));
12408 return ira->codegen->invalid_instruction;
12409 }
12410
12411 if (type_is_global_error_set(op1_type) ||12636 if (type_is_global_error_set(op1_type) ||
12412 type_is_global_error_set(op2_type))12637 type_is_global_error_set(op2_type))
12413 {12638 {
...@@ -12481,13 +12706,15 @@ static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructio...@@ -12481,13 +12706,15 @@ static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructio
12481 zig_unreachable();12706 zig_unreachable();
12482}12707}
1248312708
12484static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDeclVar *decl_var_instruction) {12709static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
12710 IrInstructionDeclVarSrc *decl_var_instruction)
12711{
12485 Error err;12712 Error err;
12486 ZigVar *var = decl_var_instruction->var;12713 ZigVar *var = decl_var_instruction->var;
1248712714
12488 IrInstruction *init_value = decl_var_instruction->init_value->child;12715 IrInstruction *init_value = decl_var_instruction->init_value->child;
12489 if (type_is_invalid(init_value->value.type)) {12716 if (type_is_invalid(init_value->value.type)) {
12490 var->value->type = ira->codegen->builtin_types.entry_invalid;12717 var->var_type = ira->codegen->builtin_types.entry_invalid;
12491 return ira->codegen->invalid_instruction;12718 return ira->codegen->invalid_instruction;
12492 }12719 }
1249312720
...@@ -12498,7 +12725,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12498,7 +12725,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12498 ZigType *proposed_type = ir_resolve_type(ira, var_type);12725 ZigType *proposed_type = ir_resolve_type(ira, var_type);
12499 explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type);12726 explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type);
12500 if (type_is_invalid(explicit_type)) {12727 if (type_is_invalid(explicit_type)) {
12501 var->value->type = ira->codegen->builtin_types.entry_invalid;12728 var->var_type = ira->codegen->builtin_types.entry_invalid;
12502 return ira->codegen->invalid_instruction;12729 return ira->codegen->invalid_instruction;
12503 }12730 }
12504 }12731 }
...@@ -12523,7 +12750,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12523,7 +12750,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12523 case ReqCompTimeInvalid:12750 case ReqCompTimeInvalid:
12524 result_type = ira->codegen->builtin_types.entry_invalid;12751 result_type = ira->codegen->builtin_types.entry_invalid;
12525 break;12752 break;
12526 case ReqCompTimeYes: {12753 case ReqCompTimeYes:
12527 var_class_requires_const = true;12754 var_class_requires_const = true;
12528 if (!var->gen_is_const && !is_comptime_var) {12755 if (!var->gen_is_const && !is_comptime_var) {
12529 ir_add_error_node(ira, source_node,12756 ir_add_error_node(ira, source_node,
...@@ -12532,7 +12759,6 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12532,7 +12759,6 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12532 result_type = ira->codegen->builtin_types.entry_invalid;12759 result_type = ira->codegen->builtin_types.entry_invalid;
12533 }12760 }
12534 break;12761 break;
12535 }
12536 case ReqCompTimeNo:12762 case ReqCompTimeNo:
12537 if (casted_init_value->value.special == ConstValSpecialStatic &&12763 if (casted_init_value->value.special == ConstValSpecialStatic &&
12538 casted_init_value->value.type->id == ZigTypeIdFn &&12764 casted_init_value->value.type->id == ZigTypeIdFn &&
...@@ -12551,7 +12777,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12551,7 +12777,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12551 break;12777 break;
12552 }12778 }
1255312779
12554 if (var->value->type != nullptr && !is_comptime_var) {12780 if (var->var_type != nullptr && !is_comptime_var) {
12555 // This is at least the second time we've seen this variable declaration during analysis.12781 // This is at least the second time we've seen this variable declaration during analysis.
12556 // This means that this is actually a different variable due to, e.g. an inline while loop.12782 // This means that this is actually a different variable due to, e.g. an inline while loop.
12557 // We make a new variable so that it can hold a different type, and so the debug info can12783 // We make a new variable so that it can hold a different type, and so the debug info can
...@@ -12573,8 +12799,8 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12573,8 +12799,8 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12573 // This must be done after possibly creating a new variable above12799 // This must be done after possibly creating a new variable above
12574 var->ref_count = 0;12800 var->ref_count = 0;
1257512801
12576 var->value->type = result_type;12802 var->var_type = result_type;
12577 assert(var->value->type);12803 assert(var->var_type);
1257812804
12579 if (type_is_invalid(result_type)) {12805 if (type_is_invalid(result_type)) {
12580 return ir_const_void(ira, &decl_var_instruction->base);12806 return ir_const_void(ira, &decl_var_instruction->base);
...@@ -12582,13 +12808,13 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12582,13 +12808,13 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1258212808
12583 if (decl_var_instruction->align_value == nullptr) {12809 if (decl_var_instruction->align_value == nullptr) {
12584 if ((err = type_resolve(ira->codegen, result_type, ResolveStatusAlignmentKnown))) {12810 if ((err = type_resolve(ira->codegen, result_type, ResolveStatusAlignmentKnown))) {
12585 var->value->type = ira->codegen->builtin_types.entry_invalid;12811 var->var_type = ira->codegen->builtin_types.entry_invalid;
12586 return ir_const_void(ira, &decl_var_instruction->base);12812 return ir_const_void(ira, &decl_var_instruction->base);
12587 }12813 }
12588 var->align_bytes = get_abi_alignment(ira->codegen, result_type);12814 var->align_bytes = get_abi_alignment(ira->codegen, result_type);
12589 } else {12815 } else {
12590 if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, &var->align_bytes)) {12816 if (!ir_resolve_align(ira, decl_var_instruction->align_value->child, &var->align_bytes)) {
12591 var->value->type = ira->codegen->builtin_types.entry_invalid;12817 var->var_type = ira->codegen->builtin_types.entry_invalid;
12592 }12818 }
12593 }12819 }
1259412820
...@@ -12605,7 +12831,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12605,7 +12831,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12605 } else if (is_comptime_var) {12831 } else if (is_comptime_var) {
12606 ir_add_error(ira, &decl_var_instruction->base,12832 ir_add_error(ira, &decl_var_instruction->base,
12607 buf_sprintf("cannot store runtime value in compile time variable"));12833 buf_sprintf("cannot store runtime value in compile time variable"));
12608 var->value->type = ira->codegen->builtin_types.entry_invalid;12834 var->var_type = ira->codegen->builtin_types.entry_invalid;
12609 return ira->codegen->invalid_instruction;12835 return ira->codegen->invalid_instruction;
12610 }12836 }
1261112837
...@@ -12613,11 +12839,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct...@@ -12613,11 +12839,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
12613 if (fn_entry)12839 if (fn_entry)
12614 fn_entry->variable_list.append(var);12840 fn_entry->variable_list.append(var);
1261512841
12616 IrInstruction *result = ir_build_var_decl(&ira->new_irb,12842 return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value);
12617 decl_var_instruction->base.scope, decl_var_instruction->base.source_node,
12618 var, var_type, nullptr, casted_init_value);
12619 result->value.type = ira->codegen->builtin_types.entry_void;
12620 return result;
12621}12843}
1262212844
12623static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {12845static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {
...@@ -12739,6 +12961,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio...@@ -12739,6 +12961,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
12739 case ZigTypeIdPointer:12961 case ZigTypeIdPointer:
12740 case ZigTypeIdArray:12962 case ZigTypeIdArray:
12741 case ZigTypeIdBool:12963 case ZigTypeIdBool:
12964 case ZigTypeIdVector:
12742 break;12965 break;
12743 case ZigTypeIdMetaType:12966 case ZigTypeIdMetaType:
12744 case ZigTypeIdVoid:12967 case ZigTypeIdVoid:
...@@ -12773,6 +12996,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio...@@ -12773,6 +12996,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
12773 case ZigTypeIdOptional:12996 case ZigTypeIdOptional:
12774 case ZigTypeIdErrorUnion:12997 case ZigTypeIdErrorUnion:
12775 case ZigTypeIdErrorSet:12998 case ZigTypeIdErrorSet:
12999 case ZigTypeIdVector:
12776 zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name));13000 zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name));
12777 case ZigTypeIdNamespace:13001 case ZigTypeIdNamespace:
12778 case ZigTypeIdBoundFn:13002 case ZigTypeIdBoundFn:
...@@ -12947,7 +13171,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node...@@ -12947,7 +13171,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node
1294713171
12948 Buf *param_name = param_decl_node->data.param_decl.name;13172 Buf *param_name = param_decl_node->data.param_decl.name;
12949 ZigVar *var = add_variable(ira->codegen, param_decl_node,13173 ZigVar *var = add_variable(ira->codegen, param_decl_node,
12950 *exec_scope, param_name, true, arg_val, nullptr);13174 *exec_scope, param_name, true, arg_val, nullptr, arg_val->type);
12951 *exec_scope = var->child_scope;13175 *exec_scope = var->child_scope;
12952 *next_proto_i += 1;13176 *next_proto_i += 1;
1295313177
...@@ -13005,7 +13229,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod...@@ -13005,7 +13229,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
13005 if (!param_name) return false;13229 if (!param_name) return false;
13006 if (!is_var_args) {13230 if (!is_var_args) {
13007 ZigVar *var = add_variable(ira->codegen, param_decl_node,13231 ZigVar *var = add_variable(ira->codegen, param_decl_node,
13008 *child_scope, param_name, true, arg_val, nullptr);13232 *child_scope, param_name, true, arg_val, nullptr, arg_val->type);
13009 *child_scope = var->child_scope;13233 *child_scope = var->child_scope;
13010 var->shadowable = !comptime_arg;13234 var->shadowable = !comptime_arg;
1301113235
...@@ -13059,9 +13283,7 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) {...@@ -13059,9 +13283,7 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) {
13059 return fn_entry->variable_list.at(next_var_i);13283 return fn_entry->variable_list.at(next_var_i);
13060}13284}
1306113285
13062static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,13286static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var) {
13063 ZigVar *var)
13064{
13065 while (var->next_var != nullptr) {13287 while (var->next_var != nullptr) {
13066 var = var->next_var;13288 var = var->next_var;
13067 }13289 }
...@@ -13070,14 +13292,14 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,...@@ -13070,14 +13292,14 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
13070 assert(ira->codegen->errors.length != 0);13292 assert(ira->codegen->errors.length != 0);
13071 return ira->codegen->invalid_instruction;13293 return ira->codegen->invalid_instruction;
13072 }13294 }
13073 if (var->value->type == nullptr || type_is_invalid(var->value->type))13295 if (var->var_type == nullptr || type_is_invalid(var->var_type))
13074 return ira->codegen->invalid_instruction;13296 return ira->codegen->invalid_instruction;
1307513297
13076 bool comptime_var_mem = ir_get_var_is_comptime(var);13298 bool comptime_var_mem = ir_get_var_is_comptime(var);
1307713299
13078 ConstExprValue *mem_slot = nullptr;13300 ConstExprValue *mem_slot = nullptr;
13079 if (var->value->special == ConstValSpecialStatic) {13301 if (var->const_value->special == ConstValSpecialStatic) {
13080 mem_slot = var->value;13302 mem_slot = var->const_value;
13081 } else {13303 } else {
13082 if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) {13304 if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) {
13083 // find the relevant exec_context13305 // find the relevant exec_context
...@@ -13106,7 +13328,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,...@@ -13106,7 +13328,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
13106 assert(!comptime_var_mem);13328 assert(!comptime_var_mem);
13107 ptr_mut = ConstPtrMutRuntimeVar;13329 ptr_mut = ConstPtrMutRuntimeVar;
13108 }13330 }
13109 return ir_get_const_ptr(ira, instruction, mem_slot, var->value->type,13331 return ir_get_const_ptr(ira, instruction, mem_slot, var->var_type,
13110 ptr_mut, is_const, is_volatile, var->align_bytes);13332 ptr_mut, is_const, is_volatile, var->align_bytes);
13111 }13333 }
13112 }13334 }
...@@ -13117,7 +13339,7 @@ no_mem_slot:...@@ -13117,7 +13339,7 @@ no_mem_slot:
1311713339
13118 IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb,13340 IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb,
13119 instruction->scope, instruction->source_node, var);13341 instruction->scope, instruction->source_node, var);
13120 var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->value->type,13342 var_ptr_instruction->value.type = get_pointer_to_type_extra(ira->codegen, var->var_type,
13121 var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0);13343 var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0);
1312213344
13123 bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);13345 bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);
...@@ -13126,6 +13348,96 @@ no_mem_slot:...@@ -13126,6 +13348,96 @@ no_mem_slot:
13126 return var_ptr_instruction;13348 return var_ptr_instruction;
13127}13349}
1312813350
13351static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
13352 IrInstruction *ptr, IrInstruction *uncasted_value)
13353{
13354 if (ptr->value.type->id != ZigTypeIdPointer) {
13355 ir_add_error(ira, ptr,
13356 buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name)));
13357 return ira->codegen->invalid_instruction;
13358 }
13359
13360 if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) {
13361 return ir_const_void(ira, source_instr);
13362 }
13363
13364 if (ptr->value.type->data.pointer.is_const && !source_instr->is_gen) {
13365 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
13366 return ira->codegen->invalid_instruction;
13367 }
13368
13369 ZigType *child_type = ptr->value.type->data.pointer.child_type;
13370 IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type);
13371 if (value == ira->codegen->invalid_instruction)
13372 return ira->codegen->invalid_instruction;
13373
13374 if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
13375 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {
13376 ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
13377 return ira->codegen->invalid_instruction;
13378 }
13379 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) {
13380 if (instr_is_comptime(value)) {
13381 ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, source_instr->source_node);
13382 if (dest_val == nullptr)
13383 return ira->codegen->invalid_instruction;
13384 if (dest_val->special != ConstValSpecialRuntime) {
13385 // TODO this allows a value stored to have the original value modified and then
13386 // have that affect what should be a copy. We need some kind of advanced copy-on-write
13387 // system to make these two tests pass at the same time:
13388 // * "string literal used as comptime slice is memoized"
13389 // * "comptime modification of const struct field" - except modified to avoid
13390 // ConstPtrMutComptimeVar, thus defeating the logic below.
13391 bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar;
13392 copy_const_val(dest_val, &value->value, same_global_refs);
13393 if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
13394 switch (type_has_one_possible_value(ira->codegen, child_type)) {
13395 case OnePossibleValueInvalid:
13396 return ira->codegen->invalid_instruction;
13397 case OnePossibleValueNo:
13398 ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
13399 break;
13400 case OnePossibleValueYes:
13401 break;
13402 }
13403 }
13404 return ir_const_void(ira, source_instr);
13405 }
13406 }
13407 ir_add_error(ira, source_instr,
13408 buf_sprintf("cannot store runtime value in compile time variable"));
13409 ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
13410 dest_val->type = ira->codegen->builtin_types.entry_invalid;
13411
13412 return ira->codegen->invalid_instruction;
13413 }
13414 }
13415
13416 switch (type_requires_comptime(ira->codegen, child_type)) {
13417 case ReqCompTimeInvalid:
13418 return ira->codegen->invalid_instruction;
13419 case ReqCompTimeYes:
13420 switch (type_has_one_possible_value(ira->codegen, ptr->value.type)) {
13421 case OnePossibleValueInvalid:
13422 return ira->codegen->invalid_instruction;
13423 case OnePossibleValueNo:
13424 ir_add_error(ira, source_instr,
13425 buf_sprintf("cannot store runtime value in type '%s'", buf_ptr(&child_type->name)));
13426 return ira->codegen->invalid_instruction;
13427 case OnePossibleValueYes:
13428 return ir_const_void(ira, source_instr);
13429 }
13430 zig_unreachable();
13431 case ReqCompTimeNo:
13432 break;
13433 }
13434
13435 IrInstruction *result = ir_build_store_ptr(&ira->new_irb, source_instr->scope, source_instr->source_node,
13436 ptr, value);
13437 result->value.type = ira->codegen->builtin_types.entry_void;
13438 return result;
13439}
13440
13129static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction,13441static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction,
13130 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,13442 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
13131 IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)13443 IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)
...@@ -13270,7 +13582,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13270,7 +13582,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13270 }13582 }
1327113583
13272 bool cacheable = fn_eval_cacheable(exec_scope, return_type);13584 bool cacheable = fn_eval_cacheable(exec_scope, return_type);
13273 IrInstruction *result = nullptr;13585 ConstExprValue *result = nullptr;
13274 if (cacheable) {13586 if (cacheable) {
13275 auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope);13587 auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope);
13276 if (entry)13588 if (entry)
...@@ -13286,18 +13598,19 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13286,18 +13598,19 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1328613598
13287 if (inferred_err_set_type != nullptr) {13599 if (inferred_err_set_type != nullptr) {
13288 inferred_err_set_type->data.error_set.infer_fn = nullptr;13600 inferred_err_set_type->data.error_set.infer_fn = nullptr;
13289 if (result->value.type->id == ZigTypeIdErrorUnion) {13601 if (result->type->id == ZigTypeIdErrorUnion) {
13290 if (result->value.data.x_err_union.err != nullptr) {13602 ErrorTableEntry *err = result->data.x_err_union.error_set->data.x_err_set;
13603 if (err != nullptr) {
13291 inferred_err_set_type->data.error_set.err_count = 1;13604 inferred_err_set_type->data.error_set.err_count = 1;
13292 inferred_err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(1);13605 inferred_err_set_type->data.error_set.errors = allocate<ErrorTableEntry *>(1);
13293 inferred_err_set_type->data.error_set.errors[0] = result->value.data.x_err_union.err;13606 inferred_err_set_type->data.error_set.errors[0] = err;
13294 }13607 }
13295 ZigType *fn_inferred_err_set_type = result->value.type->data.error_union.err_set_type;13608 ZigType *fn_inferred_err_set_type = result->type->data.error_union.err_set_type;
13296 inferred_err_set_type->data.error_set.err_count = fn_inferred_err_set_type->data.error_set.err_count;13609 inferred_err_set_type->data.error_set.err_count = fn_inferred_err_set_type->data.error_set.err_count;
13297 inferred_err_set_type->data.error_set.errors = fn_inferred_err_set_type->data.error_set.errors;13610 inferred_err_set_type->data.error_set.errors = fn_inferred_err_set_type->data.error_set.errors;
13298 } else if (result->value.type->id == ZigTypeIdErrorSet) {13611 } else if (result->type->id == ZigTypeIdErrorSet) {
13299 inferred_err_set_type->data.error_set.err_count = result->value.type->data.error_set.err_count;13612 inferred_err_set_type->data.error_set.err_count = result->type->data.error_set.err_count;
13300 inferred_err_set_type->data.error_set.errors = result->value.type->data.error_set.errors;13613 inferred_err_set_type->data.error_set.errors = result->type->data.error_set.errors;
13301 }13614 }
13302 }13615 }
1330313616
...@@ -13305,13 +13618,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13305,13 +13618,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13305 ira->codegen->memoized_fn_eval_table.put(exec_scope, result);13618 ira->codegen->memoized_fn_eval_table.put(exec_scope, result);
13306 }13619 }
1330713620
13308 if (type_is_invalid(result->value.type))13621 if (type_is_invalid(result->type))
13309 return ira->codegen->invalid_instruction;13622 return ira->codegen->invalid_instruction;
13310 }13623 }
1331113624
13312 IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->value.type);13625 IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->type);
13313 // TODO should we use copy_const_val?13626 copy_const_val(&new_instruction->value, result, true);
13314 new_instruction->value = result->value;
13315 new_instruction->value.type = return_type;13627 new_instruction->value.type = return_type;
13316 return ir_finish_anal(ira, new_instruction);13628 return ir_finish_anal(ira, new_instruction);
13317 }13629 }
...@@ -13470,18 +13782,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13470,18 +13782,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13470 ConstExprValue *var_args_val = create_const_arg_tuple(ira->codegen,13782 ConstExprValue *var_args_val = create_const_arg_tuple(ira->codegen,
13471 first_var_arg, inst_fn_type_id.param_count);13783 first_var_arg, inst_fn_type_id.param_count);
13472 ZigVar *var = add_variable(ira->codegen, param_decl_node,13784 ZigVar *var = add_variable(ira->codegen, param_decl_node,
13473 impl_fn->child_scope, param_name, true, var_args_val, nullptr);13785 impl_fn->child_scope, param_name, true, var_args_val, nullptr, var_args_val->type);
13474 impl_fn->child_scope = var->child_scope;13786 impl_fn->child_scope = var->child_scope;
13475 }13787 }
1347613788
13477 if (fn_proto_node->data.fn_proto.align_expr != nullptr) {13789 if (fn_proto_node->data.fn_proto.align_expr != nullptr) {
13478 IrInstruction *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,13790 ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,
13479 fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),13791 fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),
13480 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota,13792 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota,
13481 nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec);13793 nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec);
13794 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
13795 impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
13796 const_instruction->base.value = *align_result;
1348213797
13483 uint32_t align_bytes = 0;13798 uint32_t align_bytes = 0;
13484 ir_resolve_align(ira, align_result, &align_bytes);13799 ir_resolve_align(ira, &const_instruction->base, &align_bytes);
13485 impl_fn->align_bytes = align_bytes;13800 impl_fn->align_bytes = align_bytes;
13486 inst_fn_type_id.alignment = align_bytes;13801 inst_fn_type_id.alignment = align_bytes;
13487 }13802 }
...@@ -13559,12 +13874,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13559,12 +13874,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13559 ira->codegen->fn_defs.append(impl_fn);13874 ira->codegen->fn_defs.append(impl_fn);
13560 }13875 }
1356113876
13562 ZigType *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type;13877 FnTypeId *impl_fn_type_id = &impl_fn->type_entry->data.fn.fn_type_id;
13563 if (fn_type_can_fail(&impl_fn->type_entry->data.fn.fn_type_id)) {13878 if (fn_type_can_fail(impl_fn_type_id)) {
13564 parent_fn_entry->calls_or_awaits_errorable_fn = true;13879 parent_fn_entry->calls_or_awaits_errorable_fn = true;
13565 }13880 }
1356613881
13567 size_t impl_param_count = impl_fn->type_entry->data.fn.fn_type_id.param_count;13882 size_t impl_param_count = impl_fn_type_id->param_count;
13568 if (call_instruction->is_async) {13883 if (call_instruction->is_async) {
13569 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,13884 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,
13570 fn_ref, casted_args, impl_param_count, async_allocator_inst);13885 fn_ref, casted_args, impl_param_count, async_allocator_inst);
...@@ -13577,9 +13892,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call...@@ -13577,9 +13892,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
13577 call_instruction->base.scope, call_instruction->base.source_node,13892 call_instruction->base.scope, call_instruction->base.source_node,
13578 impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline,13893 impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline,
13579 call_instruction->is_async, nullptr, casted_new_stack);13894 call_instruction->is_async, nullptr, casted_new_stack);
13580 new_call_instruction->value.type = return_type;13895 new_call_instruction->value.type = impl_fn_type_id->return_type;
1358113896
13582 ir_add_alloca(ira, new_call_instruction, return_type);13897 ir_add_alloca(ira, new_call_instruction, impl_fn_type_id->return_type);
1358313898
13584 return ir_finish_anal(ira, new_call_instruction);13899 return ir_finish_anal(ira, new_call_instruction);
13585 }13900 }
...@@ -13774,6 +14089,13 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source...@@ -13774,6 +14089,13 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
13774 switch (ptr_val->data.x_ptr.special) {14089 switch (ptr_val->data.x_ptr.special) {
13775 case ConstPtrSpecialInvalid:14090 case ConstPtrSpecialInvalid:
13776 zig_unreachable();14091 zig_unreachable();
14092 case ConstPtrSpecialNull:
14093 if (dst_size == 0)
14094 return ErrorNone;
14095 opt_ir_add_error_node(ira, codegen, source_node,
14096 buf_sprintf("attempt to read %zu bytes from null pointer",
14097 dst_size));
14098 return ErrorSemanticAnalyzeFail;
13777 case ConstPtrSpecialRef: {14099 case ConstPtrSpecialRef: {
13778 opt_ir_add_error_node(ira, codegen, source_node,14100 opt_ir_add_error_node(ira, codegen, source_node,
13779 buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",14101 buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",
...@@ -13806,6 +14128,9 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source...@@ -13806,6 +14128,9 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
13806 return ErrorNone;14128 return ErrorNone;
13807 }14129 }
13808 case ConstPtrSpecialBaseStruct:14130 case ConstPtrSpecialBaseStruct:
14131 case ConstPtrSpecialBaseErrorUnionCode:
14132 case ConstPtrSpecialBaseErrorUnionPayload:
14133 case ConstPtrSpecialBaseOptionalPayload:
13809 case ConstPtrSpecialDiscard:14134 case ConstPtrSpecialDiscard:
13810 case ConstPtrSpecialHardCodedAddr:14135 case ConstPtrSpecialHardCodedAddr:
13811 case ConstPtrSpecialFunction:14136 case ConstPtrSpecialFunction:
...@@ -13830,6 +14155,7 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_...@@ -13830,6 +14155,7 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_
13830 case ZigTypeIdVoid:14155 case ZigTypeIdVoid:
13831 case ZigTypeIdBool:14156 case ZigTypeIdBool:
13832 case ZigTypeIdInt:14157 case ZigTypeIdInt:
14158 case ZigTypeIdVector:
13833 case ZigTypeIdFloat:14159 case ZigTypeIdFloat:
13834 case ZigTypeIdPointer:14160 case ZigTypeIdPointer:
13835 case ZigTypeIdArray:14161 case ZigTypeIdArray:
...@@ -14001,9 +14327,14 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi...@@ -14001,9 +14327,14 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi
14001 if (!ir_resolve_comptime(ira, cond_br_instruction->is_comptime->child, &is_comptime))14327 if (!ir_resolve_comptime(ira, cond_br_instruction->is_comptime->child, &is_comptime))
14002 return ir_unreach_error(ira);14328 return ir_unreach_error(ira);
1400314329
14004 if (is_comptime || instr_is_comptime(condition)) {14330 ZigType *bool_type = ira->codegen->builtin_types.entry_bool;
14331 IrInstruction *casted_condition = ir_implicit_cast(ira, condition, bool_type);
14332 if (type_is_invalid(casted_condition->value.type))
14333 return ir_unreach_error(ira);
14334
14335 if (is_comptime || instr_is_comptime(casted_condition)) {
14005 bool cond_is_true;14336 bool cond_is_true;
14006 if (!ir_resolve_bool(ira, condition, &cond_is_true))14337 if (!ir_resolve_bool(ira, casted_condition, &cond_is_true))
14007 return ir_unreach_error(ira);14338 return ir_unreach_error(ira);
1400814339
14009 IrBasicBlock *old_dest_block = cond_is_true ?14340 IrBasicBlock *old_dest_block = cond_is_true ?
...@@ -14022,11 +14353,6 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi...@@ -14022,11 +14353,6 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi
14022 return ir_finish_anal(ira, result);14353 return ir_finish_anal(ira, result);
14023 }14354 }
1402414355
14025 ZigType *bool_type = ira->codegen->builtin_types.entry_bool;
14026 IrInstruction *casted_condition = ir_implicit_cast(ira, condition, bool_type);
14027 if (casted_condition == ira->codegen->invalid_instruction)
14028 return ir_unreach_error(ira);
14029
14030 assert(cond_br_instruction->then_block != cond_br_instruction->else_block);14356 assert(cond_br_instruction->then_block != cond_br_instruction->else_block);
14031 IrBasicBlock *new_then_block = ir_get_new_bb_runtime(ira, cond_br_instruction->then_block, &cond_br_instruction->base);14357 IrBasicBlock *new_then_block = ir_get_new_bb_runtime(ira, cond_br_instruction->then_block, &cond_br_instruction->base);
14032 if (new_then_block == nullptr)14358 if (new_then_block == nullptr)
...@@ -14065,8 +14391,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh...@@ -14065,8 +14391,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
1406514391
14066 if (value->value.special != ConstValSpecialRuntime) {14392 if (value->value.special != ConstValSpecialRuntime) {
14067 IrInstruction *result = ir_const(ira, &phi_instruction->base, nullptr);14393 IrInstruction *result = ir_const(ira, &phi_instruction->base, nullptr);
14068 // TODO use copy_const_val?14394 copy_const_val(&result->value, &value->value, true);
14069 result->value = value->value;
14070 return result;14395 return result;
14071 } else {14396 } else {
14072 return value;14397 return value;
...@@ -14115,14 +14440,24 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh...@@ -14115,14 +14440,24 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
14115 if (type_is_invalid(resolved_type))14440 if (type_is_invalid(resolved_type))
14116 return ira->codegen->invalid_instruction;14441 return ira->codegen->invalid_instruction;
1411714442
14118 if (resolved_type->id == ZigTypeIdComptimeFloat ||14443 switch (type_has_one_possible_value(ira->codegen, resolved_type)) {
14119 resolved_type->id == ZigTypeIdComptimeInt ||14444 case OnePossibleValueInvalid:
14120 resolved_type->id == ZigTypeIdNull ||14445 return ira->codegen->invalid_instruction;
14121 resolved_type->id == ZigTypeIdUndefined)14446 case OnePossibleValueYes:
14122 {14447 return ir_const(ira, &phi_instruction->base, resolved_type);
14448 case OnePossibleValueNo:
14449 break;
14450 }
14451
14452 switch (type_requires_comptime(ira->codegen, resolved_type)) {
14453 case ReqCompTimeInvalid:
14454 return ira->codegen->invalid_instruction;
14455 case ReqCompTimeYes:
14123 ir_add_error_node(ira, phi_instruction->base.source_node,14456 ir_add_error_node(ira, phi_instruction->base.source_node,
14124 buf_sprintf("unable to infer expression type"));14457 buf_sprintf("values of type '%s' must be comptime known", buf_ptr(&resolved_type->name)));
14125 return ira->codegen->invalid_instruction;14458 return ira->codegen->invalid_instruction;
14459 case ReqCompTimeNo:
14460 break;
14126 }14461 }
1412714462
14128 bool all_stack_ptrs = (resolved_type->id == ZigTypeIdPointer);14463 bool all_stack_ptrs = (resolved_type->id == ZigTypeIdPointer);
...@@ -14412,10 +14747,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -14412,10 +14747,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
14412 }14747 }
14413 case ConstPtrSpecialBaseStruct:14748 case ConstPtrSpecialBaseStruct:
14414 zig_panic("TODO elem ptr on a const inner struct");14749 zig_panic("TODO elem ptr on a const inner struct");
14750 case ConstPtrSpecialBaseErrorUnionCode:
14751 zig_panic("TODO elem ptr on a const inner error union code");
14752 case ConstPtrSpecialBaseErrorUnionPayload:
14753 zig_panic("TODO elem ptr on a const inner error union payload");
14754 case ConstPtrSpecialBaseOptionalPayload:
14755 zig_panic("TODO elem ptr on a const inner optional payload");
14415 case ConstPtrSpecialHardCodedAddr:14756 case ConstPtrSpecialHardCodedAddr:
14416 zig_unreachable();14757 zig_unreachable();
14417 case ConstPtrSpecialFunction:14758 case ConstPtrSpecialFunction:
14418 zig_panic("TODO element ptr of a function casted to a ptr");14759 zig_panic("TODO element ptr of a function casted to a ptr");
14760 case ConstPtrSpecialNull:
14761 zig_panic("TODO elem ptr on a null pointer");
14419 }14762 }
14420 if (new_index >= mem_size) {14763 if (new_index >= mem_size) {
14421 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,14764 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
...@@ -14465,10 +14808,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -14465,10 +14808,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
14465 }14808 }
14466 case ConstPtrSpecialBaseStruct:14809 case ConstPtrSpecialBaseStruct:
14467 zig_panic("TODO elem ptr on a slice backed by const inner struct");14810 zig_panic("TODO elem ptr on a slice backed by const inner struct");
14811 case ConstPtrSpecialBaseErrorUnionCode:
14812 zig_panic("TODO elem ptr on a slice backed by const inner error union code");
14813 case ConstPtrSpecialBaseErrorUnionPayload:
14814 zig_panic("TODO elem ptr on a slice backed by const inner error union payload");
14815 case ConstPtrSpecialBaseOptionalPayload:
14816 zig_panic("TODO elem ptr on a slice backed by const optional payload");
14468 case ConstPtrSpecialHardCodedAddr:14817 case ConstPtrSpecialHardCodedAddr:
14469 zig_unreachable();14818 zig_unreachable();
14470 case ConstPtrSpecialFunction:14819 case ConstPtrSpecialFunction:
14471 zig_panic("TODO elem ptr on a slice that was ptrcast from a function");14820 zig_panic("TODO elem ptr on a slice that was ptrcast from a function");
14821 case ConstPtrSpecialNull:
14822 zig_panic("TODO elem ptr on a slice has a null pointer");
14472 }14823 }
14473 return result;14824 return result;
14474 } else if (array_type->id == ZigTypeIdArray) {14825 } else if (array_type->id == ZigTypeIdArray) {
...@@ -15155,74 +15506,23 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc...@@ -15155,74 +15506,23 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
15155 }15506 }
15156}15507}
1515715508
15158static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) {15509static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *instruction) {
15159 IrInstruction *ptr = load_ptr_instruction->ptr->child;15510 IrInstruction *ptr = instruction->ptr->child;
15160 if (type_is_invalid(ptr->value.type))
15161 return ira->codegen->invalid_instruction;
15162 return ir_get_deref(ira, &load_ptr_instruction->base, ptr);
15163}
15164
15165static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *store_ptr_instruction) {
15166 IrInstruction *ptr = store_ptr_instruction->ptr->child;
15167 if (type_is_invalid(ptr->value.type))15511 if (type_is_invalid(ptr->value.type))
15168 return ira->codegen->invalid_instruction;15512 return ira->codegen->invalid_instruction;
1516915513
15170 IrInstruction *value = store_ptr_instruction->value->child;15514 IrInstruction *value = instruction->value->child;
15171 if (type_is_invalid(value->value.type))15515 if (type_is_invalid(value->value.type))
15172 return ira->codegen->invalid_instruction;15516 return ira->codegen->invalid_instruction;
1517315517
15174 if (ptr->value.type->id != ZigTypeIdPointer) {15518 return ir_analyze_store_ptr(ira, &instruction->base, ptr, value);
15175 ir_add_error(ira, ptr,15519}
15176 buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name)));
15177 return ira->codegen->invalid_instruction;
15178 }
15179
15180 if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) {
15181 return ir_const_void(ira, &store_ptr_instruction->base);
15182 }
15183
15184 if (ptr->value.type->data.pointer.is_const && !store_ptr_instruction->base.is_gen) {
15185 ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant"));
15186 return ira->codegen->invalid_instruction;
15187 }
1518815520
15189 ZigType *child_type = ptr->value.type->data.pointer.child_type;15521static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *instruction) {
15190 IrInstruction *casted_value = ir_implicit_cast(ira, value, child_type);15522 IrInstruction *ptr = instruction->ptr->child;
15191 if (casted_value == ira->codegen->invalid_instruction)15523 if (type_is_invalid(ptr->value.type))
15192 return ira->codegen->invalid_instruction;15524 return ira->codegen->invalid_instruction;
1519315525 return ir_get_deref(ira, &instruction->base, ptr);
15194 if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
15195 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {
15196 ir_add_error(ira, &store_ptr_instruction->base, buf_sprintf("cannot assign to constant"));
15197 return ira->codegen->invalid_instruction;
15198 }
15199 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) {
15200 if (instr_is_comptime(casted_value)) {
15201 ConstExprValue *dest_val = const_ptr_pointee(ira, ira->codegen, &ptr->value, store_ptr_instruction->base.source_node);
15202 if (dest_val == nullptr)
15203 return ira->codegen->invalid_instruction;
15204 if (dest_val->special != ConstValSpecialRuntime) {
15205 *dest_val = casted_value->value;
15206 if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
15207 ira->new_irb.current_basic_block->must_be_comptime_source_instr = &store_ptr_instruction->base;
15208 }
15209 return ir_const_void(ira, &store_ptr_instruction->base);
15210 }
15211 }
15212 ir_add_error(ira, &store_ptr_instruction->base,
15213 buf_sprintf("cannot store runtime value in compile time variable"));
15214 ConstExprValue *dest_val = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
15215 dest_val->type = ira->codegen->builtin_types.entry_invalid;
15216
15217 return ira->codegen->invalid_instruction;
15218 }
15219 }
15220
15221 IrInstruction *result = ir_build_store_ptr(&ira->new_irb,
15222 store_ptr_instruction->base.scope, store_ptr_instruction->base.source_node,
15223 ptr, casted_value);
15224 result->value.type = ira->codegen->builtin_types.entry_void;
15225 return result;
15226}15526}
1522715527
15228static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) {15528static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) {
...@@ -15230,37 +15530,7 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio...@@ -15230,37 +15530,7 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio
15230 ZigType *type_entry = expr_value->value.type;15530 ZigType *type_entry = expr_value->value.type;
15231 if (type_is_invalid(type_entry))15531 if (type_is_invalid(type_entry))
15232 return ira->codegen->invalid_instruction;15532 return ira->codegen->invalid_instruction;
15233 switch (type_entry->id) {15533 return ir_const_type(ira, &typeof_instruction->base, type_entry);
15234 case ZigTypeIdInvalid:
15235 zig_unreachable(); // handled above
15236 case ZigTypeIdComptimeFloat:
15237 case ZigTypeIdComptimeInt:
15238 case ZigTypeIdUndefined:
15239 case ZigTypeIdNull:
15240 case ZigTypeIdNamespace:
15241 case ZigTypeIdBoundFn:
15242 case ZigTypeIdMetaType:
15243 case ZigTypeIdVoid:
15244 case ZigTypeIdBool:
15245 case ZigTypeIdUnreachable:
15246 case ZigTypeIdInt:
15247 case ZigTypeIdFloat:
15248 case ZigTypeIdPointer:
15249 case ZigTypeIdArray:
15250 case ZigTypeIdStruct:
15251 case ZigTypeIdOptional:
15252 case ZigTypeIdErrorUnion:
15253 case ZigTypeIdErrorSet:
15254 case ZigTypeIdEnum:
15255 case ZigTypeIdUnion:
15256 case ZigTypeIdFn:
15257 case ZigTypeIdArgTuple:
15258 case ZigTypeIdOpaque:
15259 case ZigTypeIdPromise:
15260 return ir_const_type(ira, &typeof_instruction->base, type_entry);
15261 }
15262
15263 zig_unreachable();
15264}15534}
1526515535
15266static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,15536static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
...@@ -15499,6 +15769,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,...@@ -15499,6 +15769,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
15499 case ZigTypeIdNamespace:15769 case ZigTypeIdNamespace:
15500 case ZigTypeIdBoundFn:15770 case ZigTypeIdBoundFn:
15501 case ZigTypeIdPromise:15771 case ZigTypeIdPromise:
15772 case ZigTypeIdVector:
15502 {15773 {
15503 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))15774 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
15504 return ira->codegen->invalid_instruction;15775 return ira->codegen->invalid_instruction;
...@@ -15619,6 +15890,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,...@@ -15619,6 +15890,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
15619 case ZigTypeIdNamespace:15890 case ZigTypeIdNamespace:
15620 case ZigTypeIdBoundFn:15891 case ZigTypeIdBoundFn:
15621 case ZigTypeIdPromise:15892 case ZigTypeIdPromise:
15893 case ZigTypeIdVector:
15622 {15894 {
15623 if ((err = ensure_complete_type(ira->codegen, child_type)))15895 if ((err = ensure_complete_type(ira->codegen, child_type)))
15624 return ira->codegen->invalid_instruction;15896 return ira->codegen->invalid_instruction;
...@@ -15685,6 +15957,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,...@@ -15685,6 +15957,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
15685 case ZigTypeIdUnion:15957 case ZigTypeIdUnion:
15686 case ZigTypeIdFn:15958 case ZigTypeIdFn:
15687 case ZigTypeIdPromise:15959 case ZigTypeIdPromise:
15960 case ZigTypeIdVector:
15688 {15961 {
15689 uint64_t size_in_bytes = type_size(ira->codegen, type_entry);15962 uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
15690 return ir_const_unsigned(ira, &size_of_instruction->base, size_in_bytes);15963 return ir_const_unsigned(ira, &size_of_instruction->base, size_in_bytes);
...@@ -15693,11 +15966,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,...@@ -15693,11 +15966,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
15693 zig_unreachable();15966 zig_unreachable();
15694}15967}
1569515968
15696static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) {15969static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value) {
15697 IrInstruction *value = instruction->value->child;
15698 if (type_is_invalid(value->value.type))
15699 return ira->codegen->invalid_instruction;
15700
15701 ZigType *type_entry = value->value.type;15970 ZigType *type_entry = value->value.type;
1570215971
15703 if (type_entry->id == ZigTypeIdOptional) {15972 if (type_entry->id == ZigTypeIdOptional) {
...@@ -15706,60 +15975,66 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns...@@ -15706,60 +15975,66 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns
15706 if (!maybe_val)15975 if (!maybe_val)
15707 return ira->codegen->invalid_instruction;15976 return ira->codegen->invalid_instruction;
1570815977
15709 return ir_const_bool(ira, &instruction->base, !optional_value_is_null(maybe_val));15978 return ir_const_bool(ira, source_inst, !optional_value_is_null(maybe_val));
15710 }15979 }
1571115980
15712 IrInstruction *result = ir_build_test_nonnull(&ira->new_irb,15981 IrInstruction *result = ir_build_test_nonnull(&ira->new_irb,
15713 instruction->base.scope, instruction->base.source_node, value);15982 source_inst->scope, source_inst->source_node, value);
15714 result->value.type = ira->codegen->builtin_types.entry_bool;15983 result->value.type = ira->codegen->builtin_types.entry_bool;
15715 return result;15984 return result;
15716 } else if (type_entry->id == ZigTypeIdNull) {15985 } else if (type_entry->id == ZigTypeIdNull) {
15717 return ir_const_bool(ira, &instruction->base, false);15986 return ir_const_bool(ira, source_inst, false);
15718 } else {15987 } else {
15719 return ir_const_bool(ira, &instruction->base, true);15988 return ir_const_bool(ira, source_inst, true);
15720 }15989 }
15721}15990}
1572215991
15723static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,15992static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) {
15724 IrInstructionUnwrapOptional *unwrap_maybe_instruction)15993 IrInstruction *value = instruction->value->child;
15725{
15726 IrInstruction *value = unwrap_maybe_instruction->value->child;
15727 if (type_is_invalid(value->value.type))15994 if (type_is_invalid(value->value.type))
15728 return ira->codegen->invalid_instruction;15995 return ira->codegen->invalid_instruction;
1572915996
15730 ZigType *ptr_type = value->value.type;15997 return ir_analyze_test_non_null(ira, &instruction->base, value);
15998}
15999
16000static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
16001 IrInstruction *base_ptr, bool safety_check_on)
16002{
16003 ZigType *ptr_type = base_ptr->value.type;
15731 assert(ptr_type->id == ZigTypeIdPointer);16004 assert(ptr_type->id == ZigTypeIdPointer);
1573216005
15733 ZigType *type_entry = ptr_type->data.pointer.child_type;16006 ZigType *type_entry = ptr_type->data.pointer.child_type;
15734 if (type_is_invalid(type_entry)) {16007 if (type_is_invalid(type_entry))
15735 return ira->codegen->invalid_instruction;16008 return ira->codegen->invalid_instruction;
15736 } else if (type_entry->id != ZigTypeIdOptional) {16009
15737 ir_add_error_node(ira, unwrap_maybe_instruction->value->source_node,16010 if (type_entry->id != ZigTypeIdOptional) {
16011 ir_add_error_node(ira, base_ptr->source_node,
15738 buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name)));16012 buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name)));
15739 return ira->codegen->invalid_instruction;16013 return ira->codegen->invalid_instruction;
15740 }16014 }
16015
15741 ZigType *child_type = type_entry->data.maybe.child_type;16016 ZigType *child_type = type_entry->data.maybe.child_type;
15742 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,16017 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
15743 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0);16018 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0);
1574416019
15745 if (instr_is_comptime(value)) {16020 if (instr_is_comptime(base_ptr)) {
15746 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);16021 ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad);
15747 if (!val)16022 if (!val)
15748 return ira->codegen->invalid_instruction;16023 return ira->codegen->invalid_instruction;
15749 ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, unwrap_maybe_instruction->base.source_node);16024 ConstExprValue *maybe_val = const_ptr_pointee(ira, ira->codegen, val, source_instr->source_node);
15750 if (maybe_val == nullptr)16025 if (maybe_val == nullptr)
15751 return ira->codegen->invalid_instruction;16026 return ira->codegen->invalid_instruction;
1575216027
15753 if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {16028 if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
15754 if (optional_value_is_null(maybe_val)) {16029 if (optional_value_is_null(maybe_val)) {
15755 ir_add_error(ira, &unwrap_maybe_instruction->base, buf_sprintf("unable to unwrap null"));16030 ir_add_error(ira, source_instr, buf_sprintf("unable to unwrap null"));
15756 return ira->codegen->invalid_instruction;16031 return ira->codegen->invalid_instruction;
15757 }16032 }
15758 IrInstruction *result = ir_const(ira, &unwrap_maybe_instruction->base, result_type);16033 IrInstruction *result = ir_const(ira, source_instr, result_type);
15759 ConstExprValue *out_val = &result->value;16034 ConstExprValue *out_val = &result->value;
15760 out_val->data.x_ptr.special = ConstPtrSpecialRef;16035 out_val->data.x_ptr.special = ConstPtrSpecialRef;
15761 out_val->data.x_ptr.mut = val->data.x_ptr.mut;16036 out_val->data.x_ptr.mut = val->data.x_ptr.mut;
15762 if (type_is_codegen_pointer(child_type)) {16037 if (types_have_same_zig_comptime_repr(type_entry, child_type)) {
15763 out_val->data.x_ptr.data.ref.pointee = maybe_val;16038 out_val->data.x_ptr.data.ref.pointee = maybe_val;
15764 } else {16039 } else {
15765 out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_optional;16040 out_val->data.x_ptr.data.ref.pointee = maybe_val->data.x_optional;
...@@ -15768,13 +16043,22 @@ static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,...@@ -15768,13 +16043,22 @@ static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
15768 }16043 }
15769 }16044 }
1577016045
15771 IrInstruction *result = ir_build_unwrap_maybe(&ira->new_irb,16046 IrInstruction *result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope,
15772 unwrap_maybe_instruction->base.scope, unwrap_maybe_instruction->base.source_node,16047 source_instr->source_node, base_ptr, safety_check_on);
15773 value, unwrap_maybe_instruction->safety_check_on);
15774 result->value.type = result_type;16048 result->value.type = result_type;
15775 return result;16049 return result;
15776}16050}
1577716051
16052static IrInstruction *ir_analyze_instruction_optional_unwrap_ptr(IrAnalyze *ira,
16053 IrInstructionOptionalUnwrapPtr *instruction)
16054{
16055 IrInstruction *base_ptr = instruction->base_ptr->child;
16056 if (type_is_invalid(base_ptr->value.type))
16057 return ira->codegen->invalid_instruction;
16058
16059 return ir_analyze_unwrap_optional_payload(ira, &instruction->base, base_ptr, instruction->safety_check_on);
16060}
16061
15778static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) {16062static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) {
15779 IrInstruction *value = ctz_instruction->value->child;16063 IrInstruction *value = ctz_instruction->value->child;
15780 if (type_is_invalid(value->value.type)) {16064 if (type_is_invalid(value->value.type)) {
...@@ -16075,9 +16359,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -16075,9 +16359,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
16075 return result;16359 return result;
16076 }16360 }
1607716361
16078 IrInstruction *result = ir_build_load_ptr(&ira->new_irb,16362 IrInstruction *result = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
16079 switch_target_instruction->base.scope, switch_target_instruction->base.source_node,
16080 target_value_ptr);
16081 result->value.type = target_type;16363 result->value.type = target_type;
16082 return result;16364 return result;
16083 }16365 }
...@@ -16107,8 +16389,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -16107,8 +16389,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
16107 return result;16389 return result;
16108 }16390 }
1610916391
16110 IrInstruction *union_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,16392 IrInstruction *union_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
16111 switch_target_instruction->base.source_node, target_value_ptr);
16112 union_value->value.type = target_type;16393 union_value->value.type = target_type;
1611316394
16114 IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope,16395 IrInstruction *union_tag_inst = ir_build_union_tag(&ira->new_irb, switch_target_instruction->base.scope,
...@@ -16132,8 +16413,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -16132,8 +16413,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
16132 return result;16413 return result;
16133 }16414 }
1613416415
16135 IrInstruction *enum_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,16416 IrInstruction *enum_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
16136 switch_target_instruction->base.source_node, target_value_ptr);
16137 enum_value->value.type = target_type;16417 enum_value->value.type = target_type;
16138 return enum_value;16418 return enum_value;
16139 }16419 }
...@@ -16147,6 +16427,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,...@@ -16147,6 +16427,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
16147 case ZigTypeIdBoundFn:16427 case ZigTypeIdBoundFn:
16148 case ZigTypeIdArgTuple:16428 case ZigTypeIdArgTuple:
16149 case ZigTypeIdOpaque:16429 case ZigTypeIdOpaque:
16430 case ZigTypeIdVector:
16150 ir_add_error(ira, &switch_target_instruction->base,16431 ir_add_error(ira, &switch_target_instruction->base,
16151 buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name)));16432 buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name)));
16152 return ira->codegen->invalid_instruction;16433 return ira->codegen->invalid_instruction;
...@@ -16290,7 +16571,7 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI...@@ -16290,7 +16571,7 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
16290 Error err;16571 Error err;
16291 assert(container_type->id == ZigTypeIdUnion);16572 assert(container_type->id == ZigTypeIdUnion);
1629216573
16293 if ((err = ensure_complete_type(ira->codegen, container_type)))16574 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
16294 return ira->codegen->invalid_instruction;16575 return ira->codegen->invalid_instruction;
1629516576
16296 if (instr_field_count != 1) {16577 if (instr_field_count != 1) {
...@@ -16322,7 +16603,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI...@@ -16322,7 +16603,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
16322 if ((err = type_resolve(ira->codegen, casted_field_value->value.type, ResolveStatusZeroBitsKnown)))16603 if ((err = type_resolve(ira->codegen, casted_field_value->value.type, ResolveStatusZeroBitsKnown)))
16323 return ira->codegen->invalid_instruction;16604 return ira->codegen->invalid_instruction;
1632416605
16325 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope);16606 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
16607 || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
16326 if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime ||16608 if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime ||
16327 !type_has_bits(casted_field_value->value.type))16609 !type_has_bits(casted_field_value->value.type))
16328 {16610 {
...@@ -16334,12 +16616,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI...@@ -16334,12 +16616,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
16334 ConstExprValue *out_val = &result->value;16616 ConstExprValue *out_val = &result->value;
16335 out_val->data.x_union.payload = field_val;16617 out_val->data.x_union.payload = field_val;
16336 out_val->data.x_union.tag = type_field->enum_field->value;16618 out_val->data.x_union.tag = type_field->enum_field->value;
1633716619 out_val->parent.id = ConstParentIdUnion;
16338 ConstParent *parent = get_const_val_parent(ira->codegen, field_val);16620 out_val->parent.data.p_union.union_val = out_val;
16339 if (parent != nullptr) {
16340 parent->id = ConstParentIdUnion;
16341 parent->data.p_union.union_val = out_val;
16342 }
1634316621
16344 return result;16622 return result;
16345 }16623 }
...@@ -16366,7 +16644,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -16366,7 +16644,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
16366 return ira->codegen->invalid_instruction;16644 return ira->codegen->invalid_instruction;
16367 }16645 }
1636816646
16369 if ((err = ensure_complete_type(ira->codegen, container_type)))16647 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
16370 return ira->codegen->invalid_instruction;16648 return ira->codegen->invalid_instruction;
1637116649
16372 size_t actual_field_count = container_type->data.structure.src_field_count;16650 size_t actual_field_count = container_type->data.structure.src_field_count;
...@@ -16377,7 +16655,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -16377,7 +16655,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1637716655
16378 IrInstructionStructInitField *new_fields = allocate<IrInstructionStructInitField>(actual_field_count);16656 IrInstructionStructInitField *new_fields = allocate<IrInstructionStructInitField>(actual_field_count);
1637916657
16380 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope);16658 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->scope)
16659 || type_requires_comptime(ira->codegen, container_type) == ReqCompTimeYes;
1638116660
16382 ConstExprValue const_val = {};16661 ConstExprValue const_val = {};
16383 const_val.special = ConstValSpecialStatic;16662 const_val.special = ConstValSpecialStatic;
...@@ -16445,9 +16724,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -16445,9 +16724,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
16445 if (const_val.special == ConstValSpecialStatic) {16724 if (const_val.special == ConstValSpecialStatic) {
16446 IrInstruction *result = ir_const(ira, instruction, nullptr);16725 IrInstruction *result = ir_const(ira, instruction, nullptr);
16447 ConstExprValue *out_val = &result->value;16726 ConstExprValue *out_val = &result->value;
16448 // TODO copy_const_val?16727 copy_const_val(out_val, &const_val, true);
16449 *out_val = const_val;16728 out_val->type = container_type;
16450 result->value.type = container_type;
1645116729
16452 for (size_t i = 0; i < instr_field_count; i += 1) {16730 for (size_t i = 0; i < instr_field_count; i += 1) {
16453 ConstExprValue *field_val = &out_val->data.x_struct.fields[i];16731 ConstExprValue *field_val = &out_val->data.x_struct.fields[i];
...@@ -16479,127 +16757,119 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -16479,127 +16757,119 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
16479static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,16757static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
16480 IrInstructionContainerInitList *instruction)16758 IrInstructionContainerInitList *instruction)
16481{16759{
16482 IrInstruction *container_type_value = instruction->container_type->child;16760 ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
16483 if (type_is_invalid(container_type_value->value.type))16761 if (type_is_invalid(container_type))
16484 return ira->codegen->invalid_instruction;16762 return ira->codegen->invalid_instruction;
1648516763
16486 size_t elem_count = instruction->item_count;16764 size_t elem_count = instruction->item_count;
16487 if (container_type_value->value.type->id == ZigTypeIdMetaType) {
16488 ZigType *container_type = ir_resolve_type(ira, container_type_value);
16489 if (type_is_invalid(container_type))
16490 return ira->codegen->invalid_instruction;
1649116765
16492 if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {16766 if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {
16493 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,16767 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
16494 0, nullptr);16768 0, nullptr);
16495 } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) {16769 } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) {
16496 // array is same as slice init but we make a compile error if the length is wrong16770 // array is same as slice init but we make a compile error if the length is wrong
16497 ZigType *child_type;16771 ZigType *child_type;
16498 if (container_type->id == ZigTypeIdArray) {16772 if (container_type->id == ZigTypeIdArray) {
16499 child_type = container_type->data.array.child_type;16773 child_type = container_type->data.array.child_type;
16500 if (container_type->data.array.len != elem_count) {16774 if (container_type->data.array.len != elem_count) {
16501 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);16775 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
1650216776
16503 ir_add_error(ira, &instruction->base,16777 ir_add_error(ira, &instruction->base,
16504 buf_sprintf("expected %s literal, found %s literal",16778 buf_sprintf("expected %s literal, found %s literal",
16505 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));16779 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
16506 return ira->codegen->invalid_instruction;16780 return ira->codegen->invalid_instruction;
16507 }
16508 } else {
16509 ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry;
16510 assert(pointer_type->id == ZigTypeIdPointer);
16511 child_type = pointer_type->data.pointer.child_type;
16512 }16781 }
16782 } else {
16783 ZigType *pointer_type = container_type->data.structure.fields[slice_ptr_index].type_entry;
16784 assert(pointer_type->id == ZigTypeIdPointer);
16785 child_type = pointer_type->data.pointer.child_type;
16786 }
1651316787
16514 ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count);16788 ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count);
1651516789
16516 ConstExprValue const_val = {};16790 ConstExprValue const_val = {};
16517 const_val.special = ConstValSpecialStatic;16791 const_val.special = ConstValSpecialStatic;
16518 const_val.type = fixed_size_array_type;16792 const_val.type = fixed_size_array_type;
16519 const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);16793 const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);
1652016794
16521 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);16795 bool is_comptime = ir_should_inline(ira->new_irb.exec, instruction->base.scope);
1652216796
16523 IrInstruction **new_items = allocate<IrInstruction *>(elem_count);16797 IrInstruction **new_items = allocate<IrInstruction *>(elem_count);
1652416798
16525 IrInstruction *first_non_const_instruction = nullptr;16799 IrInstruction *first_non_const_instruction = nullptr;
1652616800
16527 for (size_t i = 0; i < elem_count; i += 1) {16801 for (size_t i = 0; i < elem_count; i += 1) {
16528 IrInstruction *arg_value = instruction->items[i]->child;16802 IrInstruction *arg_value = instruction->items[i]->child;
16529 if (type_is_invalid(arg_value->value.type))16803 if (type_is_invalid(arg_value->value.type))
16530 return ira->codegen->invalid_instruction;16804 return ira->codegen->invalid_instruction;
1653116805
16532 IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);16806 IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);
16533 if (casted_arg == ira->codegen->invalid_instruction)16807 if (casted_arg == ira->codegen->invalid_instruction)
16534 return ira->codegen->invalid_instruction;16808 return ira->codegen->invalid_instruction;
1653516809
16536 new_items[i] = casted_arg;16810 new_items[i] = casted_arg;
1653716811
16538 if (const_val.special == ConstValSpecialStatic) {16812 if (const_val.special == ConstValSpecialStatic) {
16539 if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {16813 if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {
16540 ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);16814 ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);
16541 if (!elem_val)16815 if (!elem_val)
16542 return ira->codegen->invalid_instruction;16816 return ira->codegen->invalid_instruction;
1654316817
16544 copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);16818 copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);
16545 } else {16819 } else {
16546 first_non_const_instruction = casted_arg;16820 first_non_const_instruction = casted_arg;
16547 const_val.special = ConstValSpecialRuntime;16821 const_val.special = ConstValSpecialRuntime;
16548 }
16549 }16822 }
16550 }16823 }
16824 }
1655116825
16552 if (const_val.special == ConstValSpecialStatic) {16826 if (const_val.special == ConstValSpecialStatic) {
16553 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);16827 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
16554 ConstExprValue *out_val = &result->value;16828 ConstExprValue *out_val = &result->value;
16555 // TODO copy_const_val?16829 copy_const_val(out_val, &const_val, true);
16556 *out_val = const_val;16830 result->value.type = fixed_size_array_type;
16557 result->value.type = fixed_size_array_type;16831 for (size_t i = 0; i < elem_count; i += 1) {
16558 for (size_t i = 0; i < elem_count; i += 1) {16832 ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];
16559 ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];16833 ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);
16560 ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);16834 if (parent != nullptr) {
16561 if (parent != nullptr) {16835 parent->id = ConstParentIdArray;
16562 parent->id = ConstParentIdArray;16836 parent->data.p_array.array_val = out_val;
16563 parent->data.p_array.array_val = out_val;16837 parent->data.p_array.elem_index = i;
16564 parent->data.p_array.elem_index = i;
16565 }
16566 }16838 }
16567 return result;
16568 }16839 }
16840 return result;
16841 }
1656916842
16570 if (is_comptime) {16843 if (is_comptime) {
16571 ir_add_error_node(ira, first_non_const_instruction->source_node,16844 ir_add_error_node(ira, first_non_const_instruction->source_node,
16572 buf_sprintf("unable to evaluate constant expression"));16845 buf_sprintf("unable to evaluate constant expression"));
16573 return ira->codegen->invalid_instruction;16846 return ira->codegen->invalid_instruction;
16574 }16847 }
1657516848
16576 IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,16849 IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,
16577 instruction->base.scope, instruction->base.source_node,16850 instruction->base.scope, instruction->base.source_node,
16578 container_type_value, elem_count, new_items);16851 nullptr, elem_count, new_items);
16579 new_instruction->value.type = fixed_size_array_type;16852 new_instruction->value.type = fixed_size_array_type;
16580 ir_add_alloca(ira, new_instruction, fixed_size_array_type);16853 ir_add_alloca(ira, new_instruction, fixed_size_array_type);
16581 return new_instruction;16854 return new_instruction;
16582 } else if (container_type->id == ZigTypeIdVoid) {16855 } else if (container_type->id == ZigTypeIdVoid) {
16583 if (elem_count != 0) {16856 if (elem_count != 0) {
16584 ir_add_error_node(ira, instruction->base.source_node,
16585 buf_sprintf("void expression expects no arguments"));
16586 return ira->codegen->invalid_instruction;
16587 }
16588 return ir_const_void(ira, &instruction->base);
16589 } else {
16590 ir_add_error_node(ira, instruction->base.source_node,16857 ir_add_error_node(ira, instruction->base.source_node,
16591 buf_sprintf("type '%s' does not support array initialization",16858 buf_sprintf("void expression expects no arguments"));
16592 buf_ptr(&container_type->name)));
16593 return ira->codegen->invalid_instruction;16859 return ira->codegen->invalid_instruction;
16594 }16860 }
16861 return ir_const_void(ira, &instruction->base);
16595 } else {16862 } else {
16596 ir_add_error(ira, container_type_value,16863 ir_add_error_node(ira, instruction->base.source_node,
16597 buf_sprintf("expected type, found '%s' value", buf_ptr(&container_type_value->value.type->name)));16864 buf_sprintf("type '%s' does not support array initialization",
16865 buf_ptr(&container_type->name)));
16598 return ira->codegen->invalid_instruction;16866 return ira->codegen->invalid_instruction;
16599 }16867 }
16600}16868}
1660116869
16602static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira, IrInstructionContainerInitFields *instruction) {16870static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira,
16871 IrInstructionContainerInitFields *instruction)
16872{
16603 IrInstruction *container_type_value = instruction->container_type->child;16873 IrInstruction *container_type_value = instruction->container_type->child;
16604 ZigType *container_type = ir_resolve_type(ira, container_type_value);16874 ZigType *container_type = ir_resolve_type(ira, container_type_value);
16605 if (type_is_invalid(container_type))16875 if (type_is_invalid(container_type))
...@@ -16659,7 +16929,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct...@@ -16659,7 +16929,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct
16659 if (type_is_invalid(value->value.type))16929 if (type_is_invalid(value->value.type))
16660 return ira->codegen->invalid_instruction;16930 return ira->codegen->invalid_instruction;
1666116931
16662 IrInstruction *casted_value = ir_implicit_cast(ira, value, value->value.type);16932 IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->codegen->builtin_types.entry_global_error_set);
16663 if (type_is_invalid(casted_value->value.type))16933 if (type_is_invalid(casted_value->value.type))
16664 return ira->codegen->invalid_instruction;16934 return ira->codegen->invalid_instruction;
1666516935
...@@ -16920,10 +17190,11 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig...@@ -16920,10 +17190,11 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig
1692017190
16921 ZigVar *var = tld->var;17191 ZigVar *var = tld->var;
1692217192
16923 if ((err = ensure_complete_type(ira->codegen, var->value->type)))17193 if ((err = ensure_complete_type(ira->codegen, var->const_value->type)))
16924 return ira->codegen->builtin_types.entry_invalid;17194 return ira->codegen->builtin_types.entry_invalid;
16925 assert(var->value->type->id == ZigTypeIdMetaType);17195
16926 return var->value->data.x_type;17196 assert(var->const_value->type->id == ZigTypeIdMetaType);
17197 return var->const_value->data.x_type;
16927}17198}
1692817199
16929static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, ScopeDecls *decls_scope) {17200static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, ScopeDecls *decls_scope) {
...@@ -16978,7 +17249,6 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco...@@ -16978,7 +17249,6 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
16978 definition_array->special = ConstValSpecialStatic;17249 definition_array->special = ConstValSpecialStatic;
16979 definition_array->type = get_array_type(ira->codegen, type_info_definition_type, definition_count);17250 definition_array->type = get_array_type(ira->codegen, type_info_definition_type, definition_count);
16980 definition_array->data.x_array.special = ConstArraySpecialNone;17251 definition_array->data.x_array.special = ConstArraySpecialNone;
16981 definition_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
16982 definition_array->data.x_array.data.s_none.elements = create_const_vals(definition_count);17252 definition_array->data.x_array.data.s_none.elements = create_const_vals(definition_count);
16983 init_const_slice(ira->codegen, out_val, definition_array, 0, definition_count, false);17253 init_const_slice(ira->codegen, out_val, definition_array, 0, definition_count, false);
1698417254
...@@ -17009,33 +17279,30 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco...@@ -17009,33 +17279,30 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
17009 inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub;17279 inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub;
17010 inner_fields[2].special = ConstValSpecialStatic;17280 inner_fields[2].special = ConstValSpecialStatic;
17011 inner_fields[2].type = type_info_definition_data_type;17281 inner_fields[2].type = type_info_definition_data_type;
17012 inner_fields[2].data.x_union.parent.id = ConstParentIdStruct;17282 inner_fields[2].parent.id = ConstParentIdStruct;
17013 inner_fields[2].data.x_union.parent.data.p_struct.struct_val = definition_val;17283 inner_fields[2].parent.data.p_struct.struct_val = definition_val;
17014 inner_fields[2].data.x_union.parent.data.p_struct.field_index = 1;17284 inner_fields[2].parent.data.p_struct.field_index = 1;
1701517285
17016 switch (curr_entry->value->id) {17286 switch (curr_entry->value->id) {
17017 case TldIdVar:17287 case TldIdVar:
17018 {17288 {
17019 ZigVar *var = ((TldVar *)curr_entry->value)->var;17289 ZigVar *var = ((TldVar *)curr_entry->value)->var;
17020 if ((err = ensure_complete_type(ira->codegen, var->value->type)))17290 if ((err = ensure_complete_type(ira->codegen, var->const_value->type)))
17021 return ErrorSemanticAnalyzeFail;17291 return ErrorSemanticAnalyzeFail;
1702217292
17023 if (var->value->type->id == ZigTypeIdMetaType)17293 if (var->const_value->type->id == ZigTypeIdMetaType) {
17024 {
17025 // We have a variable of type 'type', so it's actually a type definition.17294 // We have a variable of type 'type', so it's actually a type definition.
17026 // 0: Data.Type: type17295 // 0: Data.Type: type
17027 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0);17296 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0);
17028 inner_fields[2].data.x_union.payload = var->value;17297 inner_fields[2].data.x_union.payload = var->const_value;
17029 }17298 } else {
17030 else
17031 {
17032 // We have a variable of another type, so we store the type of the variable.17299 // We have a variable of another type, so we store the type of the variable.
17033 // 1: Data.Var: type17300 // 1: Data.Var: type
17034 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 1);17301 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 1);
1703517302
17036 ConstExprValue *payload = create_const_vals(1);17303 ConstExprValue *payload = create_const_vals(1);
17037 payload->type = ira->codegen->builtin_types.entry_type;17304 payload->type = ira->codegen->builtin_types.entry_type;
17038 payload->data.x_type = var->value->type;17305 payload->data.x_type = var->const_value->type;
1703917306
17040 inner_fields[2].data.x_union.payload = payload;17307 inner_fields[2].data.x_union.payload = payload;
17041 }17308 }
...@@ -17055,8 +17322,8 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco...@@ -17055,8 +17322,8 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
17055 ConstExprValue *fn_def_val = create_const_vals(1);17322 ConstExprValue *fn_def_val = create_const_vals(1);
17056 fn_def_val->special = ConstValSpecialStatic;17323 fn_def_val->special = ConstValSpecialStatic;
17057 fn_def_val->type = type_info_fn_def_type;17324 fn_def_val->type = type_info_fn_def_type;
17058 fn_def_val->data.x_struct.parent.id = ConstParentIdUnion;17325 fn_def_val->parent.id = ConstParentIdUnion;
17059 fn_def_val->data.x_struct.parent.data.p_union.union_val = &inner_fields[2];17326 fn_def_val->parent.data.p_union.union_val = &inner_fields[2];
1706017327
17061 ConstExprValue *fn_def_fields = create_const_vals(9);17328 ConstExprValue *fn_def_fields = create_const_vals(9);
17062 fn_def_val->data.x_struct.fields = fn_def_fields;17329 fn_def_val->data.x_struct.fields = fn_def_fields;
...@@ -17120,20 +17387,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco...@@ -17120,20 +17387,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
17120 fn_arg_name_array->type = get_array_type(ira->codegen,17387 fn_arg_name_array->type = get_array_type(ira->codegen,
17121 get_slice_type(ira->codegen, u8_ptr), fn_arg_count);17388 get_slice_type(ira->codegen, u8_ptr), fn_arg_count);
17122 fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;17389 fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;
17123 fn_arg_name_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
17124 fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);17390 fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
1712517391
17126 init_const_slice(ira->codegen, &fn_def_fields[8], fn_arg_name_array, 0, fn_arg_count, false);17392 init_const_slice(ira->codegen, &fn_def_fields[8], fn_arg_name_array, 0, fn_arg_count, false);
1712717393
17128 for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++)17394 for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) {
17129 {
17130 ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index);17395 ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index);
17131 ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index];17396 ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index];
17132 ConstExprValue *arg_name = create_const_str_lit(ira->codegen, &arg_var->name);17397 ConstExprValue *arg_name = create_const_str_lit(ira->codegen, &arg_var->name);
17133 init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, buf_len(&arg_var->name), true);17398 init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, buf_len(&arg_var->name), true);
17134 fn_arg_name_val->data.x_struct.parent.id = ConstParentIdArray;17399 fn_arg_name_val->parent.id = ConstParentIdArray;
17135 fn_arg_name_val->data.x_struct.parent.data.p_array.array_val = fn_arg_name_array;17400 fn_arg_name_val->parent.data.p_array.array_val = fn_arg_name_array;
17136 fn_arg_name_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index;17401 fn_arg_name_val->parent.data.p_array.elem_index = fn_arg_index;
17137 }17402 }
1713817403
17139 inner_fields[2].data.x_union.payload = fn_def_val;17404 inner_fields[2].data.x_union.payload = fn_def_val;
...@@ -17354,6 +17619,27 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17354,6 +17619,27 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1735417619
17355 break;17620 break;
17356 }17621 }
17622 case ZigTypeIdVector: {
17623 result = create_const_vals(1);
17624 result->special = ConstValSpecialStatic;
17625 result->type = ir_type_info_get_type(ira, "Vector", nullptr);
17626
17627 ConstExprValue *fields = create_const_vals(2);
17628 result->data.x_struct.fields = fields;
17629
17630 // len: usize
17631 ensure_field_index(result->type, "len", 0);
17632 fields[0].special = ConstValSpecialStatic;
17633 fields[0].type = ira->codegen->builtin_types.entry_u32;
17634 bigint_init_unsigned(&fields[0].data.x_bigint, type_entry->data.vector.len);
17635 // child: type
17636 ensure_field_index(result->type, "child", 1);
17637 fields[1].special = ConstValSpecialStatic;
17638 fields[1].type = ira->codegen->builtin_types.entry_type;
17639 fields[1].data.x_type = type_entry->data.vector.elem_type;
17640
17641 break;
17642 }
17357 case ZigTypeIdOptional:17643 case ZigTypeIdOptional:
17358 {17644 {
17359 result = create_const_vals(1);17645 result = create_const_vals(1);
...@@ -17426,7 +17712,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17426,7 +17712,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17426 enum_field_array->special = ConstValSpecialStatic;17712 enum_field_array->special = ConstValSpecialStatic;
17427 enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count);17713 enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count);
17428 enum_field_array->data.x_array.special = ConstArraySpecialNone;17714 enum_field_array->data.x_array.special = ConstArraySpecialNone;
17429 enum_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
17430 enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count);17715 enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count);
1743117716
17432 init_const_slice(ira->codegen, &fields[2], enum_field_array, 0, enum_field_count, false);17717 init_const_slice(ira->codegen, &fields[2], enum_field_array, 0, enum_field_count, false);
...@@ -17436,9 +17721,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17436,9 +17721,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17436 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index];17721 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index];
17437 ConstExprValue *enum_field_val = &enum_field_array->data.x_array.data.s_none.elements[enum_field_index];17722 ConstExprValue *enum_field_val = &enum_field_array->data.x_array.data.s_none.elements[enum_field_index];
17438 make_enum_field_val(ira, enum_field_val, enum_field, type_info_enum_field_type);17723 make_enum_field_val(ira, enum_field_val, enum_field, type_info_enum_field_type);
17439 enum_field_val->data.x_struct.parent.id = ConstParentIdArray;17724 enum_field_val->parent.id = ConstParentIdArray;
17440 enum_field_val->data.x_struct.parent.data.p_array.array_val = enum_field_array;17725 enum_field_val->parent.data.p_array.array_val = enum_field_array;
17441 enum_field_val->data.x_struct.parent.data.p_array.elem_index = enum_field_index;17726 enum_field_val->parent.data.p_array.elem_index = enum_field_index;
17442 }17727 }
17443 // defs: []TypeInfo.Definition17728 // defs: []TypeInfo.Definition
17444 ensure_field_index(result->type, "defs", 3);17729 ensure_field_index(result->type, "defs", 3);
...@@ -17465,7 +17750,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17465,7 +17750,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17465 error_array->special = ConstValSpecialStatic;17750 error_array->special = ConstValSpecialStatic;
17466 error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count);17751 error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count);
17467 error_array->data.x_array.special = ConstArraySpecialNone;17752 error_array->data.x_array.special = ConstArraySpecialNone;
17468 error_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
17469 error_array->data.x_array.data.s_none.elements = create_const_vals(error_count);17753 error_array->data.x_array.data.s_none.elements = create_const_vals(error_count);
1747017754
17471 init_const_slice(ira->codegen, &fields[0], error_array, 0, error_count, false);17755 init_const_slice(ira->codegen, &fields[0], error_array, 0, error_count, false);
...@@ -17489,9 +17773,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17489,9 +17773,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17489 bigint_init_unsigned(&inner_fields[1].data.x_bigint, error->value);17773 bigint_init_unsigned(&inner_fields[1].data.x_bigint, error->value);
1749017774
17491 error_val->data.x_struct.fields = inner_fields;17775 error_val->data.x_struct.fields = inner_fields;
17492 error_val->data.x_struct.parent.id = ConstParentIdArray;17776 error_val->parent.id = ConstParentIdArray;
17493 error_val->data.x_struct.parent.data.p_array.array_val = error_array;17777 error_val->parent.data.p_array.array_val = error_array;
17494 error_val->data.x_struct.parent.data.p_array.elem_index = error_index;17778 error_val->parent.data.p_array.elem_index = error_index;
17495 }17779 }
1749617780
17497 break;17781 break;
...@@ -17560,7 +17844,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17560,7 +17844,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17560 union_field_array->special = ConstValSpecialStatic;17844 union_field_array->special = ConstValSpecialStatic;
17561 union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count);17845 union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count);
17562 union_field_array->data.x_array.special = ConstArraySpecialNone;17846 union_field_array->data.x_array.special = ConstArraySpecialNone;
17563 union_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
17564 union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count);17847 union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count);
1756517848
17566 init_const_slice(ira->codegen, &fields[2], union_field_array, 0, union_field_count, false);17849 init_const_slice(ira->codegen, &fields[2], union_field_array, 0, union_field_count, false);
...@@ -17593,9 +17876,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17593,9 +17876,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17593 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true);17876 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true);
1759417877
17595 union_field_val->data.x_struct.fields = inner_fields;17878 union_field_val->data.x_struct.fields = inner_fields;
17596 union_field_val->data.x_struct.parent.id = ConstParentIdArray;17879 union_field_val->parent.id = ConstParentIdArray;
17597 union_field_val->data.x_struct.parent.data.p_array.array_val = union_field_array;17880 union_field_val->parent.data.p_array.array_val = union_field_array;
17598 union_field_val->data.x_struct.parent.data.p_array.elem_index = union_field_index;17881 union_field_val->parent.data.p_array.elem_index = union_field_index;
17599 }17882 }
17600 // defs: []TypeInfo.Definition17883 // defs: []TypeInfo.Definition
17601 ensure_field_index(result->type, "defs", 3);17884 ensure_field_index(result->type, "defs", 3);
...@@ -17635,7 +17918,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17635,7 +17918,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17635 struct_field_array->special = ConstValSpecialStatic;17918 struct_field_array->special = ConstValSpecialStatic;
17636 struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count);17919 struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count);
17637 struct_field_array->data.x_array.special = ConstArraySpecialNone;17920 struct_field_array->data.x_array.special = ConstArraySpecialNone;
17638 struct_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
17639 struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count);17921 struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count);
1764017922
17641 init_const_slice(ira->codegen, &fields[1], struct_field_array, 0, struct_field_count, false);17923 init_const_slice(ira->codegen, &fields[1], struct_field_array, 0, struct_field_count, false);
...@@ -17669,9 +17951,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17669,9 +17951,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17669 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(struct_field->name), true);17951 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(struct_field->name), true);
1767017952
17671 struct_field_val->data.x_struct.fields = inner_fields;17953 struct_field_val->data.x_struct.fields = inner_fields;
17672 struct_field_val->data.x_struct.parent.id = ConstParentIdArray;17954 struct_field_val->parent.id = ConstParentIdArray;
17673 struct_field_val->data.x_struct.parent.data.p_array.array_val = struct_field_array;17955 struct_field_val->parent.data.p_array.array_val = struct_field_array;
17674 struct_field_val->data.x_struct.parent.data.p_array.elem_index = struct_field_index;17956 struct_field_val->parent.data.p_array.elem_index = struct_field_index;
17675 }17957 }
17676 // defs: []TypeInfo.Definition17958 // defs: []TypeInfo.Definition
17677 ensure_field_index(result->type, "defs", 2);17959 ensure_field_index(result->type, "defs", 2);
...@@ -17741,7 +18023,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17741,7 +18023,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17741 fn_arg_array->special = ConstValSpecialStatic;18023 fn_arg_array->special = ConstValSpecialStatic;
17742 fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count);18024 fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count);
17743 fn_arg_array->data.x_array.special = ConstArraySpecialNone;18025 fn_arg_array->data.x_array.special = ConstArraySpecialNone;
17744 fn_arg_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
17745 fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);18026 fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
1774618027
17747 init_const_slice(ira->codegen, &fields[5], fn_arg_array, 0, fn_arg_count, false);18028 init_const_slice(ira->codegen, &fields[5], fn_arg_array, 0, fn_arg_count, false);
...@@ -17778,9 +18059,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE...@@ -17778,9 +18059,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
17778 }18059 }
1777918060
17780 fn_arg_val->data.x_struct.fields = inner_fields;18061 fn_arg_val->data.x_struct.fields = inner_fields;
17781 fn_arg_val->data.x_struct.parent.id = ConstParentIdArray;18062 fn_arg_val->parent.id = ConstParentIdArray;
17782 fn_arg_val->data.x_struct.parent.data.p_array.array_val = fn_arg_array;18063 fn_arg_val->parent.data.p_array.array_val = fn_arg_array;
17783 fn_arg_val->data.x_struct.parent.data.p_array.elem_index = fn_arg_index;18064 fn_arg_val->parent.data.p_array.elem_index = fn_arg_index;
17784 }18065 }
1778518066
17786 break;18067 break;
...@@ -17824,8 +18105,8 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira,...@@ -17824,8 +18105,8 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira,
1782418105
17825 if (payload != nullptr) {18106 if (payload != nullptr) {
17826 assert(payload->type->id == ZigTypeIdStruct);18107 assert(payload->type->id == ZigTypeIdStruct);
17827 payload->data.x_struct.parent.id = ConstParentIdUnion;18108 payload->parent.id = ConstParentIdUnion;
17828 payload->data.x_struct.parent.data.p_union.union_val = out_val;18109 payload->parent.data.p_union.union_val = out_val;
17829 }18110 }
1783018111
17831 return result;18112 return result;
...@@ -17897,10 +18178,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct...@@ -17897,10 +18178,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
1789718178
17898 // Execute the C import block like an inline function18179 // Execute the C import block like an inline function
17899 ZigType *void_type = ira->codegen->builtin_types.entry_void;18180 ZigType *void_type = ira->codegen->builtin_types.entry_void;
17900 IrInstruction *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,18181 ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
17901 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,18182 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,
17902 &cimport_scope->buf, block_node, nullptr, nullptr);18183 &cimport_scope->buf, block_node, nullptr, nullptr);
17903 if (type_is_invalid(cimport_result->value.type))18184 if (type_is_invalid(cimport_result->type))
17904 return ira->codegen->invalid_instruction;18185 return ira->codegen->invalid_instruction;
1790518186
17906 find_libc_include_path(ira->codegen);18187 find_libc_include_path(ira->codegen);
...@@ -18050,7 +18331,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru...@@ -18050,7 +18331,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru
18050 return result;18331 return result;
18051}18332}
1805218333
18053static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchg *instruction) {18334static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchgSrc *instruction) {
18054 ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child);18335 ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child);
18055 if (type_is_invalid(operand_type))18336 if (type_is_invalid(operand_type))
18056 return ira->codegen->invalid_instruction;18337 return ira->codegen->invalid_instruction;
...@@ -18122,9 +18403,9 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi...@@ -18122,9 +18403,9 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi
18122 zig_panic("TODO compile-time execution of cmpxchg");18403 zig_panic("TODO compile-time execution of cmpxchg");
18123 }18404 }
1812418405
18125 IrInstruction *result = ir_build_cmpxchg(&ira->new_irb, instruction->base.scope, instruction->base.source_node,18406 IrInstruction *result = ir_build_cmpxchg_gen(ira, &instruction->base,
18126 nullptr, casted_ptr, casted_cmp_value, casted_new_value, nullptr, nullptr, instruction->is_weak,18407 casted_ptr, casted_cmp_value, casted_new_value,
18127 operand_type, success_order, failure_order);18408 success_order, failure_order, instruction->is_weak);
18128 result->value.type = get_optional_type(ira->codegen, operand_type);18409 result->value.type = get_optional_type(ira->codegen, operand_type);
18129 ir_add_alloca(ira, result, result->value.type);18410 ir_add_alloca(ira, result, result->value.type);
18130 return result;18411 return result;
...@@ -18296,18 +18577,6 @@ static IrInstruction *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInst...@@ -18296,18 +18577,6 @@ static IrInstruction *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInst
18296 return ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type);18577 return ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type);
18297}18578}
1829818579
18299static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
18300 Error err;
18301
18302 if (ty->id == ZigTypeIdPointer) {
18303 if ((err = type_resolve(ira->codegen, ty->data.pointer.child_type, ResolveStatusAlignmentKnown)))
18304 return err;
18305 }
18306
18307 *result_align = get_ptr_align(ira->codegen, ty);
18308 return ErrorNone;
18309}
18310
18311static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {18580static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {
18312 Error err;18581 Error err;
1831318582
...@@ -18426,6 +18695,20 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct...@@ -18426,6 +18695,20 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct
18426 return ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);18695 return ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);
18427}18696}
1842818697
18698static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
18699 Error err;
18700
18701 ZigType *ptr_type = get_src_ptr_type(ty);
18702 assert(ptr_type != nullptr);
18703 if (ptr_type->id == ZigTypeIdPointer) {
18704 if ((err = type_resolve(ira->codegen, ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
18705 return err;
18706 }
18707
18708 *result_align = get_ptr_align(ira->codegen, ty);
18709 return ErrorNone;
18710}
18711
18429static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) {18712static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) {
18430 ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);18713 ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
18431 if (type_is_invalid(dest_type))18714 if (type_is_invalid(dest_type))
...@@ -18532,6 +18815,27 @@ static IrInstruction *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstruct...@@ -18532,6 +18815,27 @@ static IrInstruction *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstruct
18532 return ir_const_type(ira, &instruction->base, get_int_type(ira->codegen, is_signed, (uint32_t)bit_count));18815 return ir_const_type(ira, &instruction->base, get_int_type(ira->codegen, is_signed, (uint32_t)bit_count));
18533}18816}
1853418817
18818static IrInstruction *ir_analyze_instruction_vector_type(IrAnalyze *ira, IrInstructionVectorType *instruction) {
18819 uint64_t len;
18820 if (!ir_resolve_unsigned(ira, instruction->len->child, ira->codegen->builtin_types.entry_u32, &len))
18821 return ira->codegen->invalid_instruction;
18822
18823 ZigType *elem_type = ir_resolve_type(ira, instruction->elem_type->child);
18824 if (type_is_invalid(elem_type))
18825 return ira->codegen->invalid_instruction;
18826
18827 if (!is_valid_vector_elem_type(elem_type)) {
18828 ir_add_error(ira, instruction->elem_type,
18829 buf_sprintf("vector element type must be integer, float, or pointer; '%s' is invalid",
18830 buf_ptr(&elem_type->name)));
18831 return ira->codegen->invalid_instruction;
18832 }
18833
18834 ZigType *vector_type = get_vector_type(ira->codegen, len, elem_type);
18835
18836 return ir_const_type(ira, &instruction->base, vector_type);
18837}
18838
18535static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {18839static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {
18536 IrInstruction *value = instruction->value->child;18840 IrInstruction *value = instruction->value->child;
18537 if (type_is_invalid(value->value.type))18841 if (type_is_invalid(value->value.type))
...@@ -18630,10 +18934,18 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio...@@ -18630,10 +18934,18 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio
18630 }18934 }
18631 case ConstPtrSpecialBaseStruct:18935 case ConstPtrSpecialBaseStruct:
18632 zig_panic("TODO memset on const inner struct");18936 zig_panic("TODO memset on const inner struct");
18937 case ConstPtrSpecialBaseErrorUnionCode:
18938 zig_panic("TODO memset on const inner error union code");
18939 case ConstPtrSpecialBaseErrorUnionPayload:
18940 zig_panic("TODO memset on const inner error union payload");
18941 case ConstPtrSpecialBaseOptionalPayload:
18942 zig_panic("TODO memset on const inner optional payload");
18633 case ConstPtrSpecialHardCodedAddr:18943 case ConstPtrSpecialHardCodedAddr:
18634 zig_unreachable();18944 zig_unreachable();
18635 case ConstPtrSpecialFunction:18945 case ConstPtrSpecialFunction:
18636 zig_panic("TODO memset on ptr cast from function");18946 zig_panic("TODO memset on ptr cast from function");
18947 case ConstPtrSpecialNull:
18948 zig_panic("TODO memset on null ptr");
18637 }18949 }
1863818950
18639 size_t count = bigint_as_unsigned(&casted_count->value.data.x_bigint);18951 size_t count = bigint_as_unsigned(&casted_count->value.data.x_bigint);
...@@ -18745,10 +19057,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio...@@ -18745,10 +19057,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
18745 }19057 }
18746 case ConstPtrSpecialBaseStruct:19058 case ConstPtrSpecialBaseStruct:
18747 zig_panic("TODO memcpy on const inner struct");19059 zig_panic("TODO memcpy on const inner struct");
19060 case ConstPtrSpecialBaseErrorUnionCode:
19061 zig_panic("TODO memcpy on const inner error union code");
19062 case ConstPtrSpecialBaseErrorUnionPayload:
19063 zig_panic("TODO memcpy on const inner error union payload");
19064 case ConstPtrSpecialBaseOptionalPayload:
19065 zig_panic("TODO memcpy on const inner optional payload");
18748 case ConstPtrSpecialHardCodedAddr:19066 case ConstPtrSpecialHardCodedAddr:
18749 zig_unreachable();19067 zig_unreachable();
18750 case ConstPtrSpecialFunction:19068 case ConstPtrSpecialFunction:
18751 zig_panic("TODO memcpy on ptr cast from function");19069 zig_panic("TODO memcpy on ptr cast from function");
19070 case ConstPtrSpecialNull:
19071 zig_panic("TODO memcpy on null ptr");
18752 }19072 }
1875319073
18754 if (dest_start + count > dest_end) {19074 if (dest_start + count > dest_end) {
...@@ -18781,10 +19101,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio...@@ -18781,10 +19101,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
18781 }19101 }
18782 case ConstPtrSpecialBaseStruct:19102 case ConstPtrSpecialBaseStruct:
18783 zig_panic("TODO memcpy on const inner struct");19103 zig_panic("TODO memcpy on const inner struct");
19104 case ConstPtrSpecialBaseErrorUnionCode:
19105 zig_panic("TODO memcpy on const inner error union code");
19106 case ConstPtrSpecialBaseErrorUnionPayload:
19107 zig_panic("TODO memcpy on const inner error union payload");
19108 case ConstPtrSpecialBaseOptionalPayload:
19109 zig_panic("TODO memcpy on const inner optional payload");
18784 case ConstPtrSpecialHardCodedAddr:19110 case ConstPtrSpecialHardCodedAddr:
18785 zig_unreachable();19111 zig_unreachable();
18786 case ConstPtrSpecialFunction:19112 case ConstPtrSpecialFunction:
18787 zig_panic("TODO memcpy on ptr cast from function");19113 zig_panic("TODO memcpy on ptr cast from function");
19114 case ConstPtrSpecialNull:
19115 zig_panic("TODO memcpy on null ptr");
18788 }19116 }
1878919117
18790 if (src_start + count > src_end) {19118 if (src_start + count > src_end) {
...@@ -18812,9 +19140,9 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18812,9 +19140,9 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18812 if (type_is_invalid(ptr_ptr->value.type))19140 if (type_is_invalid(ptr_ptr->value.type))
18813 return ira->codegen->invalid_instruction;19141 return ira->codegen->invalid_instruction;
1881419142
18815 ZigType *ptr_type = ptr_ptr->value.type;19143 ZigType *ptr_ptr_type = ptr_ptr->value.type;
18816 assert(ptr_type->id == ZigTypeIdPointer);19144 assert(ptr_ptr_type->id == ZigTypeIdPointer);
18817 ZigType *array_type = ptr_type->data.pointer.child_type;19145 ZigType *array_type = ptr_ptr_type->data.pointer.child_type;
1881819146
18819 IrInstruction *start = instruction->start->child;19147 IrInstruction *start = instruction->start->child;
18820 if (type_is_invalid(start->value.type))19148 if (type_is_invalid(start->value.type))
...@@ -18843,10 +19171,10 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18843,10 +19171,10 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18843 bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic &&19171 bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic &&
18844 ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst;19172 ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst;
18845 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type,19173 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, array_type->data.array.child_type,
18846 ptr_type->data.pointer.is_const || is_comptime_const,19174 ptr_ptr_type->data.pointer.is_const || is_comptime_const,
18847 ptr_type->data.pointer.is_volatile,19175 ptr_ptr_type->data.pointer.is_volatile,
18848 PtrLenUnknown,19176 PtrLenUnknown,
18849 ptr_type->data.pointer.explicit_alignment, 0, 0);19177 ptr_ptr_type->data.pointer.explicit_alignment, 0, 0);
18850 return_type = get_slice_type(ira->codegen, slice_ptr_type);19178 return_type = get_slice_type(ira->codegen, slice_ptr_type);
18851 } else if (array_type->id == ZigTypeIdPointer) {19179 } else if (array_type->id == ZigTypeIdPointer) {
18852 if (array_type->data.pointer.ptr_len == PtrLenSingle) {19180 if (array_type->data.pointer.ptr_len == PtrLenSingle) {
...@@ -18944,6 +19272,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18944,6 +19272,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18944 break;19272 break;
18945 case ConstPtrSpecialBaseStruct:19273 case ConstPtrSpecialBaseStruct:
18946 zig_panic("TODO slice const inner struct");19274 zig_panic("TODO slice const inner struct");
19275 case ConstPtrSpecialBaseErrorUnionCode:
19276 zig_panic("TODO slice const inner error union code");
19277 case ConstPtrSpecialBaseErrorUnionPayload:
19278 zig_panic("TODO slice const inner error union payload");
19279 case ConstPtrSpecialBaseOptionalPayload:
19280 zig_panic("TODO slice const inner optional payload");
18947 case ConstPtrSpecialHardCodedAddr:19281 case ConstPtrSpecialHardCodedAddr:
18948 array_val = nullptr;19282 array_val = nullptr;
18949 abs_offset = 0;19283 abs_offset = 0;
...@@ -18951,6 +19285,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18951,6 +19285,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18951 break;19285 break;
18952 case ConstPtrSpecialFunction:19286 case ConstPtrSpecialFunction:
18953 zig_panic("TODO slice of ptr cast from function");19287 zig_panic("TODO slice of ptr cast from function");
19288 case ConstPtrSpecialNull:
19289 zig_panic("TODO slice of null ptr");
18954 }19290 }
18955 } else if (is_slice(array_type)) {19291 } else if (is_slice(array_type)) {
18956 ConstExprValue *slice_ptr = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node);19292 ConstExprValue *slice_ptr = const_ptr_pointee(ira, ira->codegen, &ptr_ptr->value, instruction->base.source_node);
...@@ -18981,6 +19317,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18981,6 +19317,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18981 break;19317 break;
18982 case ConstPtrSpecialBaseStruct:19318 case ConstPtrSpecialBaseStruct:
18983 zig_panic("TODO slice const inner struct");19319 zig_panic("TODO slice const inner struct");
19320 case ConstPtrSpecialBaseErrorUnionCode:
19321 zig_panic("TODO slice const inner error union code");
19322 case ConstPtrSpecialBaseErrorUnionPayload:
19323 zig_panic("TODO slice const inner error union payload");
19324 case ConstPtrSpecialBaseOptionalPayload:
19325 zig_panic("TODO slice const inner optional payload");
18984 case ConstPtrSpecialHardCodedAddr:19326 case ConstPtrSpecialHardCodedAddr:
18985 array_val = nullptr;19327 array_val = nullptr;
18986 abs_offset = 0;19328 abs_offset = 0;
...@@ -18988,6 +19330,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -18988,6 +19330,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
18988 break;19330 break;
18989 case ConstPtrSpecialFunction:19331 case ConstPtrSpecialFunction:
18990 zig_panic("TODO slice of slice cast from function");19332 zig_panic("TODO slice of slice cast from function");
19333 case ConstPtrSpecialNull:
19334 zig_panic("TODO slice of null");
18991 }19335 }
18992 } else {19336 } else {
18993 zig_unreachable();19337 zig_unreachable();
...@@ -19053,6 +19397,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -19053,6 +19397,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
19053 zig_unreachable();19397 zig_unreachable();
19054 case ConstPtrSpecialBaseStruct:19398 case ConstPtrSpecialBaseStruct:
19055 zig_panic("TODO");19399 zig_panic("TODO");
19400 case ConstPtrSpecialBaseErrorUnionCode:
19401 zig_panic("TODO");
19402 case ConstPtrSpecialBaseErrorUnionPayload:
19403 zig_panic("TODO");
19404 case ConstPtrSpecialBaseOptionalPayload:
19405 zig_panic("TODO");
19056 case ConstPtrSpecialHardCodedAddr:19406 case ConstPtrSpecialHardCodedAddr:
19057 init_const_ptr_hard_coded_addr(ira->codegen, ptr_val,19407 init_const_ptr_hard_coded_addr(ira->codegen, ptr_val,
19058 parent_ptr->type->data.pointer.child_type,19408 parent_ptr->type->data.pointer.child_type,
...@@ -19061,6 +19411,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction...@@ -19061,6 +19411,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
19061 break;19411 break;
19062 case ConstPtrSpecialFunction:19412 case ConstPtrSpecialFunction:
19063 zig_panic("TODO");19413 zig_panic("TODO");
19414 case ConstPtrSpecialNull:
19415 zig_panic("TODO");
19064 }19416 }
1906519417
19066 ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index];19418 ConstExprValue *len_val = &out_val->data.x_struct.fields[slice_len_index];
...@@ -19287,6 +19639,7 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct...@@ -19287,6 +19639,7 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct
19287 case ZigTypeIdEnum:19639 case ZigTypeIdEnum:
19288 case ZigTypeIdUnion:19640 case ZigTypeIdUnion:
19289 case ZigTypeIdFn:19641 case ZigTypeIdFn:
19642 case ZigTypeIdVector:
19290 {19643 {
19291 uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry);19644 uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry);
19292 return ir_const_unsigned(ira, &instruction->base, align_in_bytes);19645 return ir_const_unsigned(ira, &instruction->base, align_in_bytes);
...@@ -19416,7 +19769,8 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct...@@ -19416,7 +19769,8 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
19416 return ira->codegen->invalid_instruction;19769 return ira->codegen->invalid_instruction;
1941719770
19418 if (err_union_val->special != ConstValSpecialRuntime) {19771 if (err_union_val->special != ConstValSpecialRuntime) {
19419 return ir_const_bool(ira, &instruction->base, (err_union_val->data.x_err_union.err != nullptr));19772 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
19773 return ir_const_bool(ira, &instruction->base, (err != nullptr));
19420 }19774 }
19421 }19775 }
1942219776
...@@ -19442,48 +19796,47 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct...@@ -19442,48 +19796,47 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
19442 }19796 }
19443}19797}
1944419798
19445static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,19799static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrInstructionUnwrapErrCode *instruction) {
19446 IrInstructionUnwrapErrCode *instruction)19800 IrInstruction *base_ptr = instruction->err_union->child;
19447{19801 if (type_is_invalid(base_ptr->value.type))
19448 IrInstruction *value = instruction->value->child;
19449 if (type_is_invalid(value->value.type))
19450 return ira->codegen->invalid_instruction;19802 return ira->codegen->invalid_instruction;
19451 ZigType *ptr_type = value->value.type;19803 ZigType *ptr_type = base_ptr->value.type;
1945219804
19453 // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.19805 // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
19454 assert(ptr_type->id == ZigTypeIdPointer);19806 assert(ptr_type->id == ZigTypeIdPointer);
1945519807
19456 ZigType *type_entry = ptr_type->data.pointer.child_type;19808 ZigType *type_entry = ptr_type->data.pointer.child_type;
19457 if (type_is_invalid(type_entry)) {19809 if (type_is_invalid(type_entry))
19458 return ira->codegen->invalid_instruction;19810 return ira->codegen->invalid_instruction;
19459 } else if (type_entry->id == ZigTypeIdErrorUnion) {
19460 if (instr_is_comptime(value)) {
19461 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
19462 if (!ptr_val)
19463 return ira->codegen->invalid_instruction;
19464 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
19465 if (err_union_val == nullptr)
19466 return ira->codegen->invalid_instruction;
19467 if (err_union_val->special != ConstValSpecialRuntime) {
19468 ErrorTableEntry *err = err_union_val->data.x_err_union.err;
19469 assert(err);
1947019811
19471 IrInstruction *result = ir_const(ira, &instruction->base,19812 if (type_entry->id != ZigTypeIdErrorUnion) {
19472 type_entry->data.error_union.err_set_type);19813 ir_add_error(ira, base_ptr,
19473 result->value.data.x_err_set = err;
19474 return result;
19475 }
19476 }
19477
19478 IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb,
19479 instruction->base.scope, instruction->base.source_node, value);
19480 result->value.type = type_entry->data.error_union.err_set_type;
19481 return result;
19482 } else {
19483 ir_add_error(ira, value,
19484 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));19814 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
19485 return ira->codegen->invalid_instruction;19815 return ira->codegen->invalid_instruction;
19486 }19816 }
19817
19818 if (instr_is_comptime(base_ptr)) {
19819 ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
19820 if (!ptr_val)
19821 return ira->codegen->invalid_instruction;
19822 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
19823 if (err_union_val == nullptr)
19824 return ira->codegen->invalid_instruction;
19825 if (err_union_val->special != ConstValSpecialRuntime) {
19826 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
19827 assert(err);
19828
19829 IrInstruction *result = ir_const(ira, &instruction->base,
19830 type_entry->data.error_union.err_set_type);
19831 result->value.data.x_err_set = err;
19832 return result;
19833 }
19834 }
19835
19836 IrInstruction *result = ir_build_unwrap_err_code(&ira->new_irb,
19837 instruction->base.scope, instruction->base.source_node, base_ptr);
19838 result->value.type = type_entry->data.error_union.err_set_type;
19839 return result;
19487}19840}
1948819841
19489static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,19842static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
...@@ -19499,48 +19852,48 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,...@@ -19499,48 +19852,48 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
19499 assert(ptr_type->id == ZigTypeIdPointer);19852 assert(ptr_type->id == ZigTypeIdPointer);
1950019853
19501 ZigType *type_entry = ptr_type->data.pointer.child_type;19854 ZigType *type_entry = ptr_type->data.pointer.child_type;
19502 if (type_is_invalid(type_entry)) {19855 if (type_is_invalid(type_entry))
19503 return ira->codegen->invalid_instruction;19856 return ira->codegen->invalid_instruction;
19504 } else if (type_entry->id == ZigTypeIdErrorUnion) {
19505 ZigType *payload_type = type_entry->data.error_union.payload_type;
19506 if (type_is_invalid(payload_type)) {
19507 return ira->codegen->invalid_instruction;
19508 }
19509 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
19510 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
19511 PtrLenSingle, 0, 0, 0);
19512 if (instr_is_comptime(value)) {
19513 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
19514 if (!ptr_val)
19515 return ira->codegen->invalid_instruction;
19516 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
19517 if (err_union_val == nullptr)
19518 return ira->codegen->invalid_instruction;
19519 if (err_union_val->special != ConstValSpecialRuntime) {
19520 ErrorTableEntry *err = err_union_val->data.x_err_union.err;
19521 if (err != nullptr) {
19522 ir_add_error(ira, &instruction->base,
19523 buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name)));
19524 return ira->codegen->invalid_instruction;
19525 }
1952619857
19527 IrInstruction *result = ir_const(ira, &instruction->base, result_type);19858 if (type_entry->id != ZigTypeIdErrorUnion) {
19528 result->value.data.x_ptr.special = ConstPtrSpecialRef;
19529 result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;
19530 return result;
19531 }
19532 }
19533
19534 IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb,
19535 instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on);
19536 result->value.type = result_type;
19537 return result;
19538 } else {
19539 ir_add_error(ira, value,19859 ir_add_error(ira, value,
19540 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));19860 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
19541 return ira->codegen->invalid_instruction;19861 return ira->codegen->invalid_instruction;
19542 }19862 }
1954319863
19864 ZigType *payload_type = type_entry->data.error_union.payload_type;
19865 if (type_is_invalid(payload_type))
19866 return ira->codegen->invalid_instruction;
19867
19868 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, payload_type,
19869 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
19870 PtrLenSingle, 0, 0, 0);
19871 if (instr_is_comptime(value)) {
19872 ConstExprValue *ptr_val = ir_resolve_const(ira, value, UndefBad);
19873 if (!ptr_val)
19874 return ira->codegen->invalid_instruction;
19875 ConstExprValue *err_union_val = const_ptr_pointee(ira, ira->codegen, ptr_val, instruction->base.source_node);
19876 if (err_union_val == nullptr)
19877 return ira->codegen->invalid_instruction;
19878 if (err_union_val->special != ConstValSpecialRuntime) {
19879 ErrorTableEntry *err = err_union_val->data.x_err_union.error_set->data.x_err_set;
19880 if (err != nullptr) {
19881 ir_add_error(ira, &instruction->base,
19882 buf_sprintf("caught unexpected error '%s'", buf_ptr(&err->name)));
19883 return ira->codegen->invalid_instruction;
19884 }
19885
19886 IrInstruction *result = ir_const(ira, &instruction->base, result_type);
19887 result->value.data.x_ptr.special = ConstPtrSpecialRef;
19888 result->value.data.x_ptr.data.ref.pointee = err_union_val->data.x_err_union.payload;
19889 return result;
19890 }
19891 }
19892
19893 IrInstruction *result = ir_build_unwrap_err_payload(&ira->new_irb,
19894 instruction->base.scope, instruction->base.source_node, value, instruction->safety_check_on);
19895 result->value.type = result_type;
19896 return result;
19544}19897}
1954519898
19546static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {19899static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {
...@@ -19957,7 +20310,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3...@@ -19957,7 +20310,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
19957 return ira->codegen->invalid_instruction;20310 return ira->codegen->invalid_instruction;
19958 }20311 }
1995920312
19960 IrInstruction *result = ir_create_const(&ira->new_irb, target->scope, target->source_node, result_type);20313 IrInstruction *result = ir_const(ira, target, result_type);
19961 copy_const_val(&result->value, val, false);20314 copy_const_val(&result->value, val, false);
19962 result->value.type = result_type;20315 result->value.type = result_type;
19963 return result;20316 return result;
...@@ -20005,8 +20358,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -20005,8 +20358,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
20005 if (!val)20358 if (!val)
20006 return ira->codegen->invalid_instruction;20359 return ira->codegen->invalid_instruction;
2000720360
20008 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, source_instr->source_node,20361 IrInstruction *result = ir_const(ira, source_instr, dest_type);
20009 dest_type);
20010 copy_const_val(&result->value, val, false);20362 copy_const_val(&result->value, val, false);
20011 result->value.type = dest_type;20363 result->value.type = dest_type;
20012 return result;20364 return result;
...@@ -20029,9 +20381,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -20029,9 +20381,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
20029 return ira->codegen->invalid_instruction;20381 return ira->codegen->invalid_instruction;
20030 }20382 }
2003120383
20032 IrInstruction *casted_ptr = ir_build_ptr_cast(&ira->new_irb, source_instr->scope,20384 IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr);
20033 source_instr->source_node, nullptr, ptr);
20034 casted_ptr->value.type = dest_type;
2003520385
20036 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {20386 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
20037 ErrorMsg *msg = ir_add_error(ira, source_instr,20387 ErrorMsg *msg = ir_add_error(ira, source_instr,
...@@ -20057,7 +20407,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_...@@ -20057,7 +20407,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
20057 return result;20407 return result;
20058}20408}
2005920409
20060static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCast *instruction) {20410static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCastSrc *instruction) {
20061 IrInstruction *dest_type_value = instruction->dest_type->child;20411 IrInstruction *dest_type_value = instruction->dest_type->child;
20062 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);20412 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
20063 if (type_is_invalid(dest_type))20413 if (type_is_invalid(dest_type))
...@@ -20071,6 +20421,17 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct...@@ -20071,6 +20421,17 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct
20071 return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value);20421 return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value);
20072}20422}
2007320423
20424static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ConstExprValue *val, size_t len) {
20425 size_t buf_i = 0;
20426 // TODO optimize the buf case
20427 expand_undef_array(codegen, val);
20428 for (size_t elem_i = 0; elem_i < val->type->data.array.len; elem_i += 1) {
20429 ConstExprValue *elem = &val->data.x_array.data.s_none.elements[elem_i];
20430 buf_write_value_bytes(codegen, &buf[buf_i], elem);
20431 buf_i += type_size(codegen, elem->type);
20432 }
20433}
20434
20074static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {20435static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {
20075 if (val->special == ConstValSpecialUndef)20436 if (val->special == ConstValSpecialUndef)
20076 val->special = ConstValSpecialStatic;20437 val->special = ConstValSpecialStatic;
...@@ -20116,17 +20477,9 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -20116,17 +20477,9 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
20116 zig_unreachable();20477 zig_unreachable();
20117 }20478 }
20118 case ZigTypeIdArray:20479 case ZigTypeIdArray:
20119 {20480 return buf_write_value_bytes_array(codegen, buf, val, val->type->data.array.len);
20120 size_t buf_i = 0;20481 case ZigTypeIdVector:
20121 // TODO optimize the buf case20482 return buf_write_value_bytes_array(codegen, buf, val, val->type->data.vector.len);
20122 expand_undef_array(codegen, val);
20123 for (size_t elem_i = 0; elem_i < val->type->data.array.len; elem_i += 1) {
20124 ConstExprValue *elem = &val->data.x_array.data.s_none.elements[elem_i];
20125 buf_write_value_bytes(codegen, &buf[buf_i], elem);
20126 buf_i += type_size(codegen, elem->type);
20127 }
20128 }
20129 return;
20130 case ZigTypeIdStruct:20483 case ZigTypeIdStruct:
20131 zig_panic("TODO buf_write_value_bytes struct type");20484 zig_panic("TODO buf_write_value_bytes struct type");
20132 case ZigTypeIdOptional:20485 case ZigTypeIdOptional:
...@@ -20143,6 +20496,31 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue...@@ -20143,6 +20496,31 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
20143 zig_unreachable();20496 zig_unreachable();
20144}20497}
2014520498
20499static Error buf_read_value_bytes_array(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf,
20500 ConstExprValue *val, ZigType *elem_type, size_t len)
20501{
20502 Error err;
20503 uint64_t elem_size = type_size(codegen, elem_type);
20504
20505 switch (val->data.x_array.special) {
20506 case ConstArraySpecialNone:
20507 val->data.x_array.data.s_none.elements = create_const_vals(len);
20508 for (size_t i = 0; i < len; i++) {
20509 ConstExprValue *elem = &val->data.x_array.data.s_none.elements[i];
20510 elem->special = ConstValSpecialStatic;
20511 elem->type = elem_type;
20512 if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem)))
20513 return err;
20514 }
20515 return ErrorNone;
20516 case ConstArraySpecialUndef:
20517 zig_panic("TODO buf_read_value_bytes ConstArraySpecialUndef array type");
20518 case ConstArraySpecialBuf:
20519 zig_panic("TODO buf_read_value_bytes ConstArraySpecialBuf array type");
20520 }
20521 zig_unreachable();
20522}
20523
20146static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val) {20524static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val) {
20147 Error err;20525 Error err;
20148 assert(val->special == ConstValSpecialStatic);20526 assert(val->special == ConstValSpecialStatic);
...@@ -20181,29 +20559,27 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou...@@ -20181,29 +20559,27 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
20181 val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);20559 val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);
20182 return ErrorNone;20560 return ErrorNone;
20183 }20561 }
20184 case ZigTypeIdArray: {20562 case ZigTypeIdArray:
20185 uint64_t elem_size = type_size(codegen, val->type->data.array.child_type);20563 return buf_read_value_bytes_array(ira, codegen, source_node, buf, val, val->type->data.array.child_type,
20186 size_t len = val->type->data.array.len;20564 val->type->data.array.len);
2018720565 case ZigTypeIdVector:
20188 switch (val->data.x_array.special) {20566 return buf_read_value_bytes_array(ira, codegen, source_node, buf, val, val->type->data.vector.elem_type,
20189 case ConstArraySpecialNone:20567 val->type->data.vector.len);
20190 val->data.x_array.data.s_none.elements = create_const_vals(len);20568 case ZigTypeIdEnum:
20191 for (size_t i = 0; i < len; i++) {20569 switch (val->type->data.enumeration.layout) {
20192 ConstExprValue *elem = &val->data.x_array.data.s_none.elements[i];20570 case ContainerLayoutAuto:
20193 elem->special = ConstValSpecialStatic;20571 zig_panic("TODO buf_read_value_bytes enum auto");
20194 elem->type = val->type->data.array.child_type;20572 case ContainerLayoutPacked:
20195 if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem)))20573 zig_panic("TODO buf_read_value_bytes enum packed");
20196 return err;20574 case ContainerLayoutExtern: {
20197 }20575 ZigType *tag_int_type = val->type->data.enumeration.tag_int_type;
20198 break;20576 assert(tag_int_type->id == ZigTypeIdInt);
20199 case ConstArraySpecialUndef:20577 bigint_read_twos_complement(&val->data.x_enum_tag, buf, tag_int_type->data.integral.bit_count,
20200 zig_panic("TODO buf_read_value_bytes ConstArraySpecialUndef array type");20578 codegen->is_big_endian, tag_int_type->data.integral.is_signed);
20201 case ConstArraySpecialBuf:20579 return ErrorNone;
20202 zig_panic("TODO buf_read_value_bytes ConstArraySpecialBuf array type");20580 }
20203 }20581 }
2020420582 zig_unreachable();
20205 return ErrorNone;
20206 }
20207 case ZigTypeIdStruct:20583 case ZigTypeIdStruct:
20208 switch (val->type->data.structure.layout) {20584 switch (val->type->data.structure.layout) {
20209 case ContainerLayoutAuto: {20585 case ContainerLayoutAuto: {
...@@ -20242,8 +20618,6 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou...@@ -20242,8 +20618,6 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
20242 zig_panic("TODO buf_read_value_bytes error union");20618 zig_panic("TODO buf_read_value_bytes error union");
20243 case ZigTypeIdErrorSet:20619 case ZigTypeIdErrorSet:
20244 zig_panic("TODO buf_read_value_bytes pure error type");20620 zig_panic("TODO buf_read_value_bytes pure error type");
20245 case ZigTypeIdEnum:
20246 zig_panic("TODO buf_read_value_bytes enum type");
20247 case ZigTypeIdFn:20621 case ZigTypeIdFn:
20248 zig_panic("TODO buf_read_value_bytes fn type");20622 zig_panic("TODO buf_read_value_bytes fn type");
20249 case ZigTypeIdUnion:20623 case ZigTypeIdUnion:
...@@ -20264,10 +20638,10 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct...@@ -20264,10 +20638,10 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
20264 if (type_is_invalid(src_type))20638 if (type_is_invalid(src_type))
20265 return ira->codegen->invalid_instruction;20639 return ira->codegen->invalid_instruction;
2026620640
20267 if ((err = ensure_complete_type(ira->codegen, dest_type)))20641 if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown)))
20268 return ira->codegen->invalid_instruction;20642 return ira->codegen->invalid_instruction;
2026920643
20270 if ((err = ensure_complete_type(ira->codegen, src_type)))20644 if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown)))
20271 return ira->codegen->invalid_instruction;20645 return ira->codegen->invalid_instruction;
2027220646
20273 if (get_codegen_ptr_type(src_type) != nullptr) {20647 if (get_codegen_ptr_type(src_type) != nullptr) {
...@@ -20330,6 +20704,16 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct...@@ -20330,6 +20704,16 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
20330 return ira->codegen->invalid_instruction;20704 return ira->codegen->invalid_instruction;
20331 }20705 }
2033220706
20707 uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);
20708 uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);
20709 if (dest_size_bits != src_size_bits) {
20710 ir_add_error(ira, &instruction->base,
20711 buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits",
20712 buf_ptr(&dest_type->name), dest_size_bits,
20713 buf_ptr(&src_type->name), src_size_bits));
20714 return ira->codegen->invalid_instruction;
20715 }
20716
20333 if (instr_is_comptime(value)) {20717 if (instr_is_comptime(value)) {
20334 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);20718 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
20335 if (!val)20719 if (!val)
...@@ -20410,8 +20794,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,...@@ -20410,8 +20794,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
20410 case TldIdContainer:20794 case TldIdContainer:
20411 case TldIdCompTime:20795 case TldIdCompTime:
20412 zig_unreachable();20796 zig_unreachable();
20413 case TldIdVar:20797 case TldIdVar: {
20414 {
20415 TldVar *tld_var = (TldVar *)tld;20798 TldVar *tld_var = (TldVar *)tld;
20416 ZigVar *var = tld_var->var;20799 ZigVar *var = tld_var->var;
2041720800
...@@ -20429,8 +20812,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,...@@ -20429,8 +20812,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
20429 return ir_get_deref(ira, &instruction->base, var_ptr);20812 return ir_get_deref(ira, &instruction->base, var_ptr);
20430 }20813 }
20431 }20814 }
20432 case TldIdFn:20815 case TldIdFn: {
20433 {
20434 TldFn *tld_fn = (TldFn *)tld;20816 TldFn *tld_fn = (TldFn *)tld;
20435 ZigFn *fn_entry = tld_fn->fn_entry;20817 ZigFn *fn_entry = tld_fn->fn_entry;
20436 assert(fn_entry->type_entry);20818 assert(fn_entry->type_entry);
...@@ -20476,8 +20858,7 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru...@@ -20476,8 +20858,7 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru
20476 if (!val)20858 if (!val)
20477 return ira->codegen->invalid_instruction;20859 return ira->codegen->invalid_instruction;
20478 if (val->type->id == ZigTypeIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {20860 if (val->type->id == ZigTypeIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
20479 IrInstruction *result = ir_create_const(&ira->new_irb, instruction->base.scope,20861 IrInstruction *result = ir_const(ira, &instruction->base, usize);
20480 instruction->base.source_node, usize);
20481 bigint_init_unsigned(&result->value.data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr);20862 bigint_init_unsigned(&result->value.data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr);
20482 result->value.type = usize;20863 result->value.type = usize;
20483 return result;20864 return result;
...@@ -21315,6 +21696,11 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -21315,6 +21696,11 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21315 case IrInstructionIdErrWrapCode:21696 case IrInstructionIdErrWrapCode:
21316 case IrInstructionIdErrWrapPayload:21697 case IrInstructionIdErrWrapPayload:
21317 case IrInstructionIdCast:21698 case IrInstructionIdCast:
21699 case IrInstructionIdDeclVarGen:
21700 case IrInstructionIdPtrCastGen:
21701 case IrInstructionIdCmpxchgGen:
21702 case IrInstructionIdArrayToVector:
21703 case IrInstructionIdVectorToArray:
21318 zig_unreachable();21704 zig_unreachable();
2131921705
21320 case IrInstructionIdReturn:21706 case IrInstructionIdReturn:
...@@ -21325,8 +21711,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -21325,8 +21711,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21325 return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction);21711 return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction);
21326 case IrInstructionIdBinOp:21712 case IrInstructionIdBinOp:
21327 return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction);21713 return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction);
21328 case IrInstructionIdDeclVar:21714 case IrInstructionIdDeclVarSrc:
21329 return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVar *)instruction);21715 return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVarSrc *)instruction);
21330 case IrInstructionIdLoadPtr:21716 case IrInstructionIdLoadPtr:
21331 return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction);21717 return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction);
21332 case IrInstructionIdStorePtr:21718 case IrInstructionIdStorePtr:
...@@ -21371,8 +21757,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -21371,8 +21757,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21371 return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction);21757 return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction);
21372 case IrInstructionIdTestNonNull:21758 case IrInstructionIdTestNonNull:
21373 return ir_analyze_instruction_test_non_null(ira, (IrInstructionTestNonNull *)instruction);21759 return ir_analyze_instruction_test_non_null(ira, (IrInstructionTestNonNull *)instruction);
21374 case IrInstructionIdUnwrapOptional:21760 case IrInstructionIdOptionalUnwrapPtr:
21375 return ir_analyze_instruction_unwrap_maybe(ira, (IrInstructionUnwrapOptional *)instruction);21761 return ir_analyze_instruction_optional_unwrap_ptr(ira, (IrInstructionOptionalUnwrapPtr *)instruction);
21376 case IrInstructionIdClz:21762 case IrInstructionIdClz:
21377 return ir_analyze_instruction_clz(ira, (IrInstructionClz *)instruction);21763 return ir_analyze_instruction_clz(ira, (IrInstructionClz *)instruction);
21378 case IrInstructionIdCtz:21764 case IrInstructionIdCtz:
...@@ -21413,8 +21799,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -21413,8 +21799,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21413 return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction);21799 return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction);
21414 case IrInstructionIdEmbedFile:21800 case IrInstructionIdEmbedFile:
21415 return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction);21801 return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction);
21416 case IrInstructionIdCmpxchg:21802 case IrInstructionIdCmpxchgSrc:
21417 return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchg *)instruction);21803 return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchgSrc *)instruction);
21418 case IrInstructionIdFence:21804 case IrInstructionIdFence:
21419 return ir_analyze_instruction_fence(ira, (IrInstructionFence *)instruction);21805 return ir_analyze_instruction_fence(ira, (IrInstructionFence *)instruction);
21420 case IrInstructionIdTruncate:21806 case IrInstructionIdTruncate:
...@@ -21437,6 +21823,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -21437,6 +21823,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21437 return ir_analyze_instruction_bool_to_int(ira, (IrInstructionBoolToInt *)instruction);21823 return ir_analyze_instruction_bool_to_int(ira, (IrInstructionBoolToInt *)instruction);
21438 case IrInstructionIdIntType:21824 case IrInstructionIdIntType:
21439 return ir_analyze_instruction_int_type(ira, (IrInstructionIntType *)instruction);21825 return ir_analyze_instruction_int_type(ira, (IrInstructionIntType *)instruction);
21826 case IrInstructionIdVectorType:
21827 return ir_analyze_instruction_vector_type(ira, (IrInstructionVectorType *)instruction);
21440 case IrInstructionIdBoolNot:21828 case IrInstructionIdBoolNot:
21441 return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction);21829 return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction);
21442 case IrInstructionIdMemset:21830 case IrInstructionIdMemset:
...@@ -21481,8 +21869,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio...@@ -21481,8 +21869,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
21481 return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction);21869 return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction);
21482 case IrInstructionIdPanic:21870 case IrInstructionIdPanic:
21483 return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);21871 return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);
21484 case IrInstructionIdPtrCast:21872 case IrInstructionIdPtrCastSrc:
21485 return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCast *)instruction);21873 return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCastSrc *)instruction);
21486 case IrInstructionIdBitCast:21874 case IrInstructionIdBitCast:
21487 return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction);21875 return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction);
21488 case IrInstructionIdIntToPtr:21876 case IrInstructionIdIntToPtr:
...@@ -21666,7 +22054,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21666,7 +22054,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21666 case IrInstructionIdBr:22054 case IrInstructionIdBr:
21667 case IrInstructionIdCondBr:22055 case IrInstructionIdCondBr:
21668 case IrInstructionIdSwitchBr:22056 case IrInstructionIdSwitchBr:
21669 case IrInstructionIdDeclVar:22057 case IrInstructionIdDeclVarSrc:
22058 case IrInstructionIdDeclVarGen:
21670 case IrInstructionIdStorePtr:22059 case IrInstructionIdStorePtr:
21671 case IrInstructionIdCall:22060 case IrInstructionIdCall:
21672 case IrInstructionIdReturn:22061 case IrInstructionIdReturn:
...@@ -21681,7 +22070,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21681,7 +22070,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21681 case IrInstructionIdCInclude:22070 case IrInstructionIdCInclude:
21682 case IrInstructionIdCDefine:22071 case IrInstructionIdCDefine:
21683 case IrInstructionIdCUndef:22072 case IrInstructionIdCUndef:
21684 case IrInstructionIdCmpxchg:
21685 case IrInstructionIdFence:22073 case IrInstructionIdFence:
21686 case IrInstructionIdMemset:22074 case IrInstructionIdMemset:
21687 case IrInstructionIdMemcpy:22075 case IrInstructionIdMemcpy:
...@@ -21709,6 +22097,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21709,6 +22097,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21709 case IrInstructionIdMergeErrRetTraces:22097 case IrInstructionIdMergeErrRetTraces:
21710 case IrInstructionIdMarkErrRetTracePtr:22098 case IrInstructionIdMarkErrRetTracePtr:
21711 case IrInstructionIdAtomicRmw:22099 case IrInstructionIdAtomicRmw:
22100 case IrInstructionIdCmpxchgGen:
22101 case IrInstructionIdCmpxchgSrc:
21712 return true;22102 return true;
2171322103
21714 case IrInstructionIdPhi:22104 case IrInstructionIdPhi:
...@@ -21734,7 +22124,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21734,7 +22124,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21734 case IrInstructionIdSliceType:22124 case IrInstructionIdSliceType:
21735 case IrInstructionIdSizeOf:22125 case IrInstructionIdSizeOf:
21736 case IrInstructionIdTestNonNull:22126 case IrInstructionIdTestNonNull:
21737 case IrInstructionIdUnwrapOptional:22127 case IrInstructionIdOptionalUnwrapPtr:
21738 case IrInstructionIdClz:22128 case IrInstructionIdClz:
21739 case IrInstructionIdCtz:22129 case IrInstructionIdCtz:
21740 case IrInstructionIdPopCount:22130 case IrInstructionIdPopCount:
...@@ -21745,6 +22135,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21745,6 +22135,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21745 case IrInstructionIdEmbedFile:22135 case IrInstructionIdEmbedFile:
21746 case IrInstructionIdTruncate:22136 case IrInstructionIdTruncate:
21747 case IrInstructionIdIntType:22137 case IrInstructionIdIntType:
22138 case IrInstructionIdVectorType:
21748 case IrInstructionIdBoolNot:22139 case IrInstructionIdBoolNot:
21749 case IrInstructionIdSlice:22140 case IrInstructionIdSlice:
21750 case IrInstructionIdMemberCount:22141 case IrInstructionIdMemberCount:
...@@ -21761,7 +22152,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21761,7 +22152,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21761 case IrInstructionIdErrWrapPayload:22152 case IrInstructionIdErrWrapPayload:
21762 case IrInstructionIdFnProto:22153 case IrInstructionIdFnProto:
21763 case IrInstructionIdTestComptime:22154 case IrInstructionIdTestComptime:
21764 case IrInstructionIdPtrCast:22155 case IrInstructionIdPtrCastSrc:
22156 case IrInstructionIdPtrCastGen:
21765 case IrInstructionIdBitCast:22157 case IrInstructionIdBitCast:
21766 case IrInstructionIdWidenOrShorten:22158 case IrInstructionIdWidenOrShorten:
21767 case IrInstructionIdPtrToInt:22159 case IrInstructionIdPtrToInt:
...@@ -21804,6 +22196,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -21804,6 +22196,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
21804 case IrInstructionIdFromBytes:22196 case IrInstructionIdFromBytes:
21805 case IrInstructionIdToBytes:22197 case IrInstructionIdToBytes:
21806 case IrInstructionIdEnumToInt:22198 case IrInstructionIdEnumToInt:
22199 case IrInstructionIdVectorToArray:
22200 case IrInstructionIdArrayToVector:
21807 return false;22201 return false;
2180822202
21809 case IrInstructionIdAsm:22203 case IrInstructionIdAsm:
src/ir.hpp+1-1
...@@ -13,7 +13,7 @@...@@ -13,7 +13,7 @@
13bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable);13bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable);
14bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);14bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
1515
16IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,16ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
17 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,17 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
18 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,18 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
19 IrExecutable *parent_exec);19 IrExecutable *parent_exec);
src/ir_print.cpp+90-22
...@@ -172,7 +172,7 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction...@@ -172,7 +172,7 @@ static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction
172 }172 }
173}173}
174174
175static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instruction) {175static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_var_instruction) {
176 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";176 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
177 const char *name = buf_ptr(&decl_var_instruction->var->name);177 const char *name = buf_ptr(&decl_var_instruction->var->name);
178 if (decl_var_instruction->var_type) {178 if (decl_var_instruction->var_type) {
...@@ -332,8 +332,8 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {...@@ -332,8 +332,8 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {
332}332}
333333
334static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {334static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
335 fprintf(irp->f, "*");
336 ir_print_other_instruction(irp, instruction->ptr);335 ir_print_other_instruction(irp, instruction->ptr);
336 fprintf(irp->f, ".*");
337}337}
338338
339static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {339static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {
...@@ -479,15 +479,15 @@ static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) {...@@ -479,15 +479,15 @@ static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) {
479 fprintf(irp->f, ")");479 fprintf(irp->f, ")");
480}480}
481481
482static void ir_print_test_null(IrPrint *irp, IrInstructionTestNonNull *instruction) {482static void ir_print_test_non_null(IrPrint *irp, IrInstructionTestNonNull *instruction) {
483 fprintf(irp->f, "*");
484 ir_print_other_instruction(irp, instruction->value);483 ir_print_other_instruction(irp, instruction->value);
485 fprintf(irp->f, " != null");484 fprintf(irp->f, " != null");
486}485}
487486
488static void ir_print_unwrap_maybe(IrPrint *irp, IrInstructionUnwrapOptional *instruction) {487static void ir_print_optional_unwrap_ptr(IrPrint *irp, IrInstructionOptionalUnwrapPtr *instruction) {
489 fprintf(irp->f, "&??*");488 fprintf(irp->f, "&");
490 ir_print_other_instruction(irp, instruction->value);489 ir_print_other_instruction(irp, instruction->base_ptr);
490 fprintf(irp->f, ".*.?");
491 if (!instruction->safety_check_on) {491 if (!instruction->safety_check_on) {
492 fprintf(irp->f, " // no safety");492 fprintf(irp->f, " // no safety");
493 }493 }
...@@ -613,7 +613,7 @@ static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instructio...@@ -613,7 +613,7 @@ static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instructio
613 fprintf(irp->f, ")");613 fprintf(irp->f, ")");
614}614}
615615
616static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {616static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruction) {
617 fprintf(irp->f, "@cmpxchg(");617 fprintf(irp->f, "@cmpxchg(");
618 ir_print_other_instruction(irp, instruction->ptr);618 ir_print_other_instruction(irp, instruction->ptr);
619 fprintf(irp->f, ", ");619 fprintf(irp->f, ", ");
...@@ -627,6 +627,16 @@ static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {...@@ -627,6 +627,16 @@ static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {
627 fprintf(irp->f, ")");627 fprintf(irp->f, ")");
628}628}
629629
630static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruction) {
631 fprintf(irp->f, "@cmpxchg(");
632 ir_print_other_instruction(irp, instruction->ptr);
633 fprintf(irp->f, ", ");
634 ir_print_other_instruction(irp, instruction->cmp_value);
635 fprintf(irp->f, ", ");
636 ir_print_other_instruction(irp, instruction->new_value);
637 fprintf(irp->f, ", TODO print atomic orders)");
638}
639
630static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) {640static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) {
631 fprintf(irp->f, "@fence(");641 fprintf(irp->f, "@fence(");
632 ir_print_other_instruction(irp, instruction->order_value);642 ir_print_other_instruction(irp, instruction->order_value);
...@@ -709,6 +719,14 @@ static void ir_print_int_type(IrPrint *irp, IrInstructionIntType *instruction) {...@@ -709,6 +719,14 @@ static void ir_print_int_type(IrPrint *irp, IrInstructionIntType *instruction) {
709 fprintf(irp->f, ")");719 fprintf(irp->f, ")");
710}720}
711721
722static void ir_print_vector_type(IrPrint *irp, IrInstructionVectorType *instruction) {
723 fprintf(irp->f, "@Vector(");
724 ir_print_other_instruction(irp, instruction->len);
725 fprintf(irp->f, ", ");
726 ir_print_other_instruction(irp, instruction->elem_type);
727 fprintf(irp->f, ")");
728}
729
712static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) {730static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) {
713 fprintf(irp->f, "! ");731 fprintf(irp->f, "! ");
714 ir_print_other_instruction(irp, instruction->value);732 ir_print_other_instruction(irp, instruction->value);
...@@ -820,13 +838,13 @@ static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) {...@@ -820,13 +838,13 @@ static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) {
820}838}
821839
822static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) {840static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) {
823 fprintf(irp->f, "@unwrapErrorCode(");841 fprintf(irp->f, "UnwrapErrorCode(");
824 ir_print_other_instruction(irp, instruction->value);842 ir_print_other_instruction(irp, instruction->err_union);
825 fprintf(irp->f, ")");843 fprintf(irp->f, ")");
826}844}
827845
828static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) {846static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) {
829 fprintf(irp->f, "@unwrapErrorPayload(");847 fprintf(irp->f, "ErrorUnionFieldPayload(");
830 ir_print_other_instruction(irp, instruction->value);848 ir_print_other_instruction(irp, instruction->value);
831 fprintf(irp->f, ")");849 fprintf(irp->f, ")");
832 if (!instruction->safety_check_on) {850 if (!instruction->safety_check_on) {
...@@ -879,7 +897,7 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst...@@ -879,7 +897,7 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst
879 fprintf(irp->f, ")");897 fprintf(irp->f, ")");
880}898}
881899
882static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {900static void ir_print_ptr_cast_src(IrPrint *irp, IrInstructionPtrCastSrc *instruction) {
883 fprintf(irp->f, "@ptrCast(");901 fprintf(irp->f, "@ptrCast(");
884 if (instruction->dest_type) {902 if (instruction->dest_type) {
885 ir_print_other_instruction(irp, instruction->dest_type);903 ir_print_other_instruction(irp, instruction->dest_type);
...@@ -889,6 +907,12 @@ static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {...@@ -889,6 +907,12 @@ static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {
889 fprintf(irp->f, ")");907 fprintf(irp->f, ")");
890}908}
891909
910static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruction) {
911 fprintf(irp->f, "@ptrCast(");
912 ir_print_other_instruction(irp, instruction->ptr);
913 fprintf(irp->f, ")");
914}
915
892static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {916static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
893 fprintf(irp->f, "@bitCast(");917 fprintf(irp->f, "@bitCast(");
894 if (instruction->dest_type) {918 if (instruction->dest_type) {
...@@ -900,7 +924,7 @@ static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {...@@ -900,7 +924,7 @@ static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
900}924}
901925
902static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) {926static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) {
903 fprintf(irp->f, "@widenOrShorten(");927 fprintf(irp->f, "WidenOrShorten(");
904 ir_print_other_instruction(irp, instruction->target);928 ir_print_other_instruction(irp, instruction->target);
905 fprintf(irp->f, ")");929 fprintf(irp->f, ")");
906}930}
...@@ -948,6 +972,18 @@ static void ir_print_check_runtime_scope(IrPrint *irp, IrInstructionCheckRuntime...@@ -948,6 +972,18 @@ static void ir_print_check_runtime_scope(IrPrint *irp, IrInstructionCheckRuntime
948 fprintf(irp->f, ")");972 fprintf(irp->f, ")");
949}973}
950974
975static void ir_print_array_to_vector(IrPrint *irp, IrInstructionArrayToVector *instruction) {
976 fprintf(irp->f, "ArrayToVector(");
977 ir_print_other_instruction(irp, instruction->array);
978 fprintf(irp->f, ")");
979}
980
981static void ir_print_vector_to_array(IrPrint *irp, IrInstructionVectorToArray *instruction) {
982 fprintf(irp->f, "VectorToArray(");
983 ir_print_other_instruction(irp, instruction->vector);
984 fprintf(irp->f, ")");
985}
986
951static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {987static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {
952 fprintf(irp->f, "inttoerr ");988 fprintf(irp->f, "inttoerr ");
953 ir_print_other_instruction(irp, instruction->target);989 ir_print_other_instruction(irp, instruction->target);
...@@ -1323,6 +1359,20 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) {...@@ -1323,6 +1359,20 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) {
1323 fprintf(irp->f, ")");1359 fprintf(irp->f, ")");
1324}1360}
13251361
1362static void ir_print_decl_var_gen(IrPrint *irp, IrInstructionDeclVarGen *decl_var_instruction) {
1363 ZigVar *var = decl_var_instruction->var;
1364 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
1365 const char *name = buf_ptr(&decl_var_instruction->var->name);
1366 fprintf(irp->f, "%s %s: %s align(%u) = ", var_or_const, name, buf_ptr(&var->var_type->name),
1367 var->align_bytes);
1368
1369 ir_print_other_instruction(irp, decl_var_instruction->init_value);
1370 if (decl_var_instruction->var->is_comptime != nullptr) {
1371 fprintf(irp->f, " // comptime = ");
1372 ir_print_other_instruction(irp, decl_var_instruction->var->is_comptime);
1373 }
1374}
1375
1326static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) {1376static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) {
1327 fprintf(irp->f, "@bswap(");1377 fprintf(irp->f, "@bswap(");
1328 if (instruction->type != nullptr) {1378 if (instruction->type != nullptr) {
...@@ -1361,8 +1411,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1361,8 +1411,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1361 case IrInstructionIdBinOp:1411 case IrInstructionIdBinOp:
1362 ir_print_bin_op(irp, (IrInstructionBinOp *)instruction);1412 ir_print_bin_op(irp, (IrInstructionBinOp *)instruction);
1363 break;1413 break;
1364 case IrInstructionIdDeclVar:1414 case IrInstructionIdDeclVarSrc:
1365 ir_print_decl_var(irp, (IrInstructionDeclVar *)instruction);1415 ir_print_decl_var_src(irp, (IrInstructionDeclVarSrc *)instruction);
1366 break;1416 break;
1367 case IrInstructionIdCast:1417 case IrInstructionIdCast:
1368 ir_print_cast(irp, (IrInstructionCast *)instruction);1418 ir_print_cast(irp, (IrInstructionCast *)instruction);
...@@ -1452,10 +1502,10 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1452,10 +1502,10 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1452 ir_print_size_of(irp, (IrInstructionSizeOf *)instruction);1502 ir_print_size_of(irp, (IrInstructionSizeOf *)instruction);
1453 break;1503 break;
1454 case IrInstructionIdTestNonNull:1504 case IrInstructionIdTestNonNull:
1455 ir_print_test_null(irp, (IrInstructionTestNonNull *)instruction);1505 ir_print_test_non_null(irp, (IrInstructionTestNonNull *)instruction);
1456 break;1506 break;
1457 case IrInstructionIdUnwrapOptional:1507 case IrInstructionIdOptionalUnwrapPtr:
1458 ir_print_unwrap_maybe(irp, (IrInstructionUnwrapOptional *)instruction);1508 ir_print_optional_unwrap_ptr(irp, (IrInstructionOptionalUnwrapPtr *)instruction);
1459 break;1509 break;
1460 case IrInstructionIdCtz:1510 case IrInstructionIdCtz:
1461 ir_print_ctz(irp, (IrInstructionCtz *)instruction);1511 ir_print_ctz(irp, (IrInstructionCtz *)instruction);
...@@ -1508,8 +1558,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1508,8 +1558,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1508 case IrInstructionIdEmbedFile:1558 case IrInstructionIdEmbedFile:
1509 ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction);1559 ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction);
1510 break;1560 break;
1511 case IrInstructionIdCmpxchg:1561 case IrInstructionIdCmpxchgSrc:
1512 ir_print_cmpxchg(irp, (IrInstructionCmpxchg *)instruction);1562 ir_print_cmpxchg_src(irp, (IrInstructionCmpxchgSrc *)instruction);
1563 break;
1564 case IrInstructionIdCmpxchgGen:
1565 ir_print_cmpxchg_gen(irp, (IrInstructionCmpxchgGen *)instruction);
1513 break;1566 break;
1514 case IrInstructionIdFence:1567 case IrInstructionIdFence:
1515 ir_print_fence(irp, (IrInstructionFence *)instruction);1568 ir_print_fence(irp, (IrInstructionFence *)instruction);
...@@ -1544,6 +1597,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1544,6 +1597,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1544 case IrInstructionIdIntType:1597 case IrInstructionIdIntType:
1545 ir_print_int_type(irp, (IrInstructionIntType *)instruction);1598 ir_print_int_type(irp, (IrInstructionIntType *)instruction);
1546 break;1599 break;
1600 case IrInstructionIdVectorType:
1601 ir_print_vector_type(irp, (IrInstructionVectorType *)instruction);
1602 break;
1547 case IrInstructionIdBoolNot:1603 case IrInstructionIdBoolNot:
1548 ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction);1604 ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction);
1549 break;1605 break;
...@@ -1607,8 +1663,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1607,8 +1663,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1607 case IrInstructionIdTestComptime:1663 case IrInstructionIdTestComptime:
1608 ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction);1664 ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction);
1609 break;1665 break;
1610 case IrInstructionIdPtrCast:1666 case IrInstructionIdPtrCastSrc:
1611 ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction);1667 ir_print_ptr_cast_src(irp, (IrInstructionPtrCastSrc *)instruction);
1668 break;
1669 case IrInstructionIdPtrCastGen:
1670 ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction);
1612 break;1671 break;
1613 case IrInstructionIdBitCast:1672 case IrInstructionIdBitCast:
1614 ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);1673 ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);
...@@ -1775,6 +1834,15 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1775,6 +1834,15 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1775 case IrInstructionIdCheckRuntimeScope:1834 case IrInstructionIdCheckRuntimeScope:
1776 ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction);1835 ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction);
1777 break;1836 break;
1837 case IrInstructionIdDeclVarGen:
1838 ir_print_decl_var_gen(irp, (IrInstructionDeclVarGen *)instruction);
1839 break;
1840 case IrInstructionIdArrayToVector:
1841 ir_print_array_to_vector(irp, (IrInstructionArrayToVector *)instruction);
1842 break;
1843 case IrInstructionIdVectorToArray:
1844 ir_print_vector_to_array(irp, (IrInstructionVectorToArray *)instruction);
1845 break;
1778 }1846 }
1779 fprintf(irp->f, "\n");1847 fprintf(irp->f, "\n");
1780}1848}
src/main.cpp+6
...@@ -59,6 +59,7 @@ static int print_full_usage(const char *arg0) {...@@ -59,6 +59,7 @@ static int print_full_usage(const char *arg0) {
59 " --release-fast build with optimizations on and safety off\n"59 " --release-fast build with optimizations on and safety off\n"
60 " --release-safe build with optimizations on and safety on\n"60 " --release-safe build with optimizations on and safety on\n"
61 " --release-small build with size optimizations on and safety off\n"61 " --release-small build with size optimizations on and safety off\n"
62 " --single-threaded source may assume it is only used single-threaded\n"
62 " --static output will be statically linked\n"63 " --static output will be statically linked\n"
63 " --strip exclude debug symbols\n"64 " --strip exclude debug symbols\n"
64 " --target-arch [name] specify target architecture\n"65 " --target-arch [name] specify target architecture\n"
...@@ -393,6 +394,7 @@ int main(int argc, char **argv) {...@@ -393,6 +394,7 @@ int main(int argc, char **argv) {
393 bool no_rosegment_workaround = false;394 bool no_rosegment_workaround = false;
394 bool system_linker_hack = false;395 bool system_linker_hack = false;
395 TargetSubsystem subsystem = TargetSubsystemAuto;396 TargetSubsystem subsystem = TargetSubsystemAuto;
397 bool is_single_threaded = false;
396398
397 if (argc >= 2 && strcmp(argv[1], "build") == 0) {399 if (argc >= 2 && strcmp(argv[1], "build") == 0) {
398 Buf zig_exe_path_buf = BUF_INIT;400 Buf zig_exe_path_buf = BUF_INIT;
...@@ -550,6 +552,8 @@ int main(int argc, char **argv) {...@@ -550,6 +552,8 @@ int main(int argc, char **argv) {
550 disable_pic = true;552 disable_pic = true;
551 } else if (strcmp(arg, "--system-linker-hack") == 0) {553 } else if (strcmp(arg, "--system-linker-hack") == 0) {
552 system_linker_hack = true;554 system_linker_hack = true;
555 } else if (strcmp(arg, "--single-threaded") == 0) {
556 is_single_threaded = true;
553 } else if (strcmp(arg, "--test-cmd-bin") == 0) {557 } else if (strcmp(arg, "--test-cmd-bin") == 0) {
554 test_exec_args.append(nullptr);558 test_exec_args.append(nullptr);
555 } else if (arg[1] == 'L' && arg[2] != 0) {559 } else if (arg[1] == 'L' && arg[2] != 0) {
...@@ -816,6 +820,7 @@ int main(int argc, char **argv) {...@@ -816,6 +820,7 @@ int main(int argc, char **argv) {
816 switch (cmd) {820 switch (cmd) {
817 case CmdBuiltin: {821 case CmdBuiltin: {
818 CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, get_zig_lib_dir());822 CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, get_zig_lib_dir());
823 g->is_single_threaded = is_single_threaded;
819 Buf *builtin_source = codegen_generate_builtin_source(g);824 Buf *builtin_source = codegen_generate_builtin_source(g);
820 if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {825 if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {
821 fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));826 fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));
...@@ -889,6 +894,7 @@ int main(int argc, char **argv) {...@@ -889,6 +894,7 @@ int main(int argc, char **argv) {
889 codegen_set_out_name(g, buf_out_name);894 codegen_set_out_name(g, buf_out_name);
890 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);895 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
891 codegen_set_is_test(g, cmd == CmdTest);896 codegen_set_is_test(g, cmd == CmdTest);
897 g->is_single_threaded = is_single_threaded;
892 codegen_set_linker_script(g, linker_script);898 codegen_set_linker_script(g, linker_script);
893 if (each_lib_rpath)899 if (each_lib_rpath)
894 codegen_set_each_lib_rpath(g, each_lib_rpath);900 codegen_set_each_lib_rpath(g, each_lib_rpath);
src/os.cpp+31-31
...@@ -1808,7 +1808,7 @@ Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {...@@ -1808,7 +1808,7 @@ Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {
1808#endif1808#endif
1809}1809}
18101810
1811Error os_file_open_r(Buf *full_path, OsFile *out_file) {1811Error os_file_open_r(Buf *full_path, OsFile *out_file, OsTimeStamp *mtime) {
1812#if defined(ZIG_OS_WINDOWS)1812#if defined(ZIG_OS_WINDOWS)
1813 // TODO use CreateFileW1813 // TODO use CreateFileW
1814 HANDLE result = CreateFileA(buf_ptr(full_path), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);1814 HANDLE result = CreateFileA(buf_ptr(full_path), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
...@@ -1834,8 +1834,18 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) {...@@ -1834,8 +1834,18 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) {
1834 return ErrorUnexpected;1834 return ErrorUnexpected;
1835 }1835 }
1836 }1836 }
1837
1838 *out_file = result;1837 *out_file = result;
1838
1839 if (mtime != nullptr) {
1840 FILETIME last_write_time;
1841 if (!GetFileTime(result, nullptr, nullptr, &last_write_time)) {
1842 CloseHandle(result);
1843 return ErrorUnexpected;
1844 }
1845 mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime;
1846 mtime->nsec = 0;
1847 }
1848
1839 return ErrorNone;1849 return ErrorNone;
1840#else1850#else
1841 for (;;) {1851 for (;;) {
...@@ -1858,7 +1868,26 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) {...@@ -1858,7 +1868,26 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) {
1858 return ErrorFileSystem;1868 return ErrorFileSystem;
1859 }1869 }
1860 }1870 }
1871 struct stat statbuf;
1872 if (fstat(fd, &statbuf) == -1) {
1873 close(fd);
1874 return ErrorFileSystem;
1875 }
1876 if (S_ISDIR(statbuf.st_mode)) {
1877 close(fd);
1878 return ErrorIsDir;
1879 }
1861 *out_file = fd;1880 *out_file = fd;
1881
1882 if (mtime != nullptr) {
1883#if defined(ZIG_OS_DARWIN)
1884 mtime->sec = statbuf.st_mtimespec.tv_sec;
1885 mtime->nsec = statbuf.st_mtimespec.tv_nsec;
1886#else
1887 mtime->sec = statbuf.st_mtim.tv_sec;
1888 mtime->nsec = statbuf.st_mtim.tv_nsec;
1889#endif
1890 }
1862 return ErrorNone;1891 return ErrorNone;
1863 }1892 }
1864#endif1893#endif
...@@ -1948,35 +1977,6 @@ Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {...@@ -1948,35 +1977,6 @@ Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {
1948#endif1977#endif
1949}1978}
19501979
1951Error os_file_mtime(OsFile file, OsTimeStamp *mtime) {
1952#if defined(ZIG_OS_WINDOWS)
1953 FILETIME last_write_time;
1954 if (!GetFileTime(file, nullptr, nullptr, &last_write_time))
1955 return ErrorUnexpected;
1956 mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime;
1957 mtime->nsec = 0;
1958 return ErrorNone;
1959#elif defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD)
1960 struct stat statbuf;
1961 if (fstat(file, &statbuf) == -1)
1962 return ErrorFileSystem;
1963
1964 mtime->sec = statbuf.st_mtim.tv_sec;
1965 mtime->nsec = statbuf.st_mtim.tv_nsec;
1966 return ErrorNone;
1967#elif defined(ZIG_OS_DARWIN)
1968 struct stat statbuf;
1969 if (fstat(file, &statbuf) == -1)
1970 return ErrorFileSystem;
1971
1972 mtime->sec = statbuf.st_mtimespec.tv_sec;
1973 mtime->nsec = statbuf.st_mtimespec.tv_nsec;
1974 return ErrorNone;
1975#else
1976#error unimplemented
1977#endif
1978}
1979
1980Error os_file_read(OsFile file, void *ptr, size_t *len) {1980Error os_file_read(OsFile file, void *ptr, size_t *len) {
1981#if defined(ZIG_OS_WINDOWS)1981#if defined(ZIG_OS_WINDOWS)
1982 DWORD amt_read;1982 DWORD amt_read;
src/os.hpp+1-2
...@@ -101,9 +101,8 @@ bool os_path_is_absolute(Buf *path);...@@ -101,9 +101,8 @@ bool os_path_is_absolute(Buf *path);
101Error ATTRIBUTE_MUST_USE os_make_path(Buf *path);101Error ATTRIBUTE_MUST_USE os_make_path(Buf *path);
102Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path);102Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path);
103103
104Error ATTRIBUTE_MUST_USE os_file_open_r(Buf *full_path, OsFile *out_file);104Error ATTRIBUTE_MUST_USE os_file_open_r(Buf *full_path, OsFile *out_file, OsTimeStamp *mtime);
105Error ATTRIBUTE_MUST_USE os_file_open_lock_rw(Buf *full_path, OsFile *out_file);105Error ATTRIBUTE_MUST_USE os_file_open_lock_rw(Buf *full_path, OsFile *out_file);
106Error ATTRIBUTE_MUST_USE os_file_mtime(OsFile file, OsTimeStamp *mtime);
107Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len);106Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len);
108Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents);107Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents);
109Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents);108Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents);
src/parser.cpp+4-4
...@@ -381,7 +381,7 @@ static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parse...@@ -381,7 +381,7 @@ static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parse
381 else_body = ast_expect(pc, body_parser);381 else_body = ast_expect(pc, body_parser);
382 }382 }
383383
384 assert(res->type == NodeTypeTestExpr);384 assert(res->type == NodeTypeIfOptional);
385 if (err_payload != nullptr) {385 if (err_payload != nullptr) {
386 AstNodeTestExpr old = res->data.test_expr;386 AstNodeTestExpr old = res->data.test_expr;
387 res->type = NodeTypeIfErrorExpr;387 res->type = NodeTypeIfErrorExpr;
...@@ -990,7 +990,7 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) {...@@ -990,7 +990,7 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) {
990 if (requires_semi && else_body == nullptr)990 if (requires_semi && else_body == nullptr)
991 expect_token(pc, TokenIdSemicolon);991 expect_token(pc, TokenIdSemicolon);
992992
993 assert(res->type == NodeTypeTestExpr);993 assert(res->type == NodeTypeIfOptional);
994 if (err_payload != nullptr) {994 if (err_payload != nullptr) {
995 AstNodeTestExpr old = res->data.test_expr;995 AstNodeTestExpr old = res->data.test_expr;
996 res->type = NodeTypeIfErrorExpr;996 res->type = NodeTypeIfErrorExpr;
...@@ -2204,7 +2204,7 @@ static AstNode *ast_parse_if_prefix(ParseContext *pc) {...@@ -2204,7 +2204,7 @@ static AstNode *ast_parse_if_prefix(ParseContext *pc) {
2204 Optional<PtrPayload> opt_payload = ast_parse_ptr_payload(pc);2204 Optional<PtrPayload> opt_payload = ast_parse_ptr_payload(pc);
22052205
2206 PtrPayload payload;2206 PtrPayload payload;
2207 AstNode *res = ast_create_node(pc, NodeTypeTestExpr, first);2207 AstNode *res = ast_create_node(pc, NodeTypeIfOptional, first);
2208 res->data.test_expr.target_node = condition;2208 res->data.test_expr.target_node = condition;
2209 if (opt_payload.unwrap(&payload)) {2209 if (opt_payload.unwrap(&payload)) {
2210 res->data.test_expr.var_symbol = token_buf(payload.payload);2210 res->data.test_expr.var_symbol = token_buf(payload.payload);
...@@ -2999,7 +2999,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -2999,7 +2999,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
2999 visit_field(&node->data.if_err_expr.then_node, visit, context);2999 visit_field(&node->data.if_err_expr.then_node, visit, context);
3000 visit_field(&node->data.if_err_expr.else_node, visit, context);3000 visit_field(&node->data.if_err_expr.else_node, visit, context);
3001 break;3001 break;
3002 case NodeTypeTestExpr:3002 case NodeTypeIfOptional:
3003 visit_field(&node->data.test_expr.target_node, visit, context);3003 visit_field(&node->data.test_expr.target_node, visit, context);
3004 visit_field(&node->data.test_expr.then_node, visit, context);3004 visit_field(&node->data.test_expr.then_node, visit, context);
3005 visit_field(&node->data.test_expr.else_node, visit, context);3005 visit_field(&node->data.test_expr.else_node, visit, context);
src/tokenizer.cpp+5-7
...@@ -248,13 +248,8 @@ ATTRIBUTE_PRINTF(2, 3)...@@ -248,13 +248,8 @@ ATTRIBUTE_PRINTF(2, 3)
248static void tokenize_error(Tokenize *t, const char *format, ...) {248static void tokenize_error(Tokenize *t, const char *format, ...) {
249 t->state = TokenizeStateError;249 t->state = TokenizeStateError;
250250
251 if (t->cur_tok) {251 t->out->err_line = t->line;
252 t->out->err_line = t->cur_tok->start_line;252 t->out->err_column = t->column;
253 t->out->err_column = t->cur_tok->start_column;
254 } else {
255 t->out->err_line = t->line;
256 t->out->err_column = t->column;
257 }
258253
259 va_list ap;254 va_list ap;
260 va_start(ap, format);255 va_start(ap, format);
...@@ -886,6 +881,9 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -886,6 +881,9 @@ void tokenize(Buf *buf, Tokenization *out) {
886 break;881 break;
887 case TokenizeStateSawAmpersand:882 case TokenizeStateSawAmpersand:
888 switch (c) {883 switch (c) {
884 case '&':
885 tokenize_error(&t, "`&&` is invalid. Note that `and` is boolean AND.");
886 break;
889 case '=':887 case '=':
890 set_token_id(&t, t.cur_tok, TokenIdBitAndEq);888 set_token_id(&t, t.cur_tok, TokenIdBitAndEq);
891 end_token(&t);889 end_token(&t);
src/zig_llvm.cpp+13
...@@ -263,6 +263,19 @@ ZigLLVMDIType *ZigLLVMCreateDebugBasicType(ZigLLVMDIBuilder *dibuilder, const ch...@@ -263,6 +263,19 @@ ZigLLVMDIType *ZigLLVMCreateDebugBasicType(ZigLLVMDIBuilder *dibuilder, const ch
263 return reinterpret_cast<ZigLLVMDIType*>(di_type);263 return reinterpret_cast<ZigLLVMDIType*>(di_type);
264}264}
265265
266struct ZigLLVMDIType *ZigLLVMDIBuilderCreateVectorType(struct ZigLLVMDIBuilder *dibuilder,
267 uint64_t Size, uint32_t AlignInBits, struct ZigLLVMDIType *Ty)
268{
269 SmallVector<Metadata *, 1> subrange;
270 subrange.push_back(reinterpret_cast<DIBuilder*>(dibuilder)->getOrCreateSubrange(0, Size));
271 DIType *di_type = reinterpret_cast<DIBuilder*>(dibuilder)->createVectorType(
272 Size,
273 AlignInBits,
274 reinterpret_cast<DIType*>(Ty),
275 reinterpret_cast<DIBuilder*>(dibuilder)->getOrCreateArray(subrange));
276 return reinterpret_cast<ZigLLVMDIType*>(di_type);
277}
278
266ZigLLVMDIType *ZigLLVMCreateDebugArrayType(ZigLLVMDIBuilder *dibuilder, uint64_t size_in_bits,279ZigLLVMDIType *ZigLLVMCreateDebugArrayType(ZigLLVMDIBuilder *dibuilder, uint64_t size_in_bits,
267 uint64_t align_in_bits, ZigLLVMDIType *elem_type, int elem_count)280 uint64_t align_in_bits, ZigLLVMDIType *elem_type, int elem_count)
268{281{
src/zig_llvm.h+2
...@@ -191,6 +191,8 @@ ZIG_EXTERN_C struct ZigLLVMDISubprogram *ZigLLVMCreateFunction(struct ZigLLVMDIB...@@ -191,6 +191,8 @@ ZIG_EXTERN_C struct ZigLLVMDISubprogram *ZigLLVMCreateFunction(struct ZigLLVMDIB
191 unsigned lineno, struct ZigLLVMDIType *fn_di_type, bool is_local_to_unit, bool is_definition,191 unsigned lineno, struct ZigLLVMDIType *fn_di_type, bool is_local_to_unit, bool is_definition,
192 unsigned scope_line, unsigned flags, bool is_optimized, struct ZigLLVMDISubprogram *decl_subprogram);192 unsigned scope_line, unsigned flags, bool is_optimized, struct ZigLLVMDISubprogram *decl_subprogram);
193193
194ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMDIBuilderCreateVectorType(struct ZigLLVMDIBuilder *dibuilder,
195 uint64_t Size, uint32_t AlignInBits, struct ZigLLVMDIType *Ty);
194196
195ZIG_EXTERN_C void ZigLLVMFnSetSubprogram(LLVMValueRef fn, struct ZigLLVMDISubprogram *subprogram);197ZIG_EXTERN_C void ZigLLVMFnSetSubprogram(LLVMValueRef fn, struct ZigLLVMDISubprogram *subprogram);
196198
std/atomic/queue.zig+32-15
...@@ -170,20 +170,36 @@ test "std.atomic.Queue" {...@@ -170,20 +170,36 @@ test "std.atomic.Queue" {
170 .get_count = 0,170 .get_count = 0,
171 };171 };
172172
173 var putters: [put_thread_count]*std.os.Thread = undefined;173 if (builtin.single_threaded) {
174 for (putters) |*t| {174 {
175 t.* = try std.os.spawnThread(&context, startPuts);175 var i: usize = 0;
176 }176 while (i < put_thread_count) : (i += 1) {
177 var getters: [put_thread_count]*std.os.Thread = undefined;177 std.debug.assertOrPanic(startPuts(&context) == 0);
178 for (getters) |*t| {178 }
179 t.* = try std.os.spawnThread(&context, startGets);179 }
180 }180 context.puts_done = 1;
181 {
182 var i: usize = 0;
183 while (i < put_thread_count) : (i += 1) {
184 std.debug.assertOrPanic(startGets(&context) == 0);
185 }
186 }
187 } else {
188 var putters: [put_thread_count]*std.os.Thread = undefined;
189 for (putters) |*t| {
190 t.* = try std.os.spawnThread(&context, startPuts);
191 }
192 var getters: [put_thread_count]*std.os.Thread = undefined;
193 for (getters) |*t| {
194 t.* = try std.os.spawnThread(&context, startGets);
195 }
181196
182 for (putters) |t|197 for (putters) |t|
183 t.wait();198 t.wait();
184 _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);199 _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
185 for (getters) |t|200 for (getters) |t|
186 t.wait();201 t.wait();
202 }
187203
188 if (context.put_sum != context.get_sum) {204 if (context.put_sum != context.get_sum) {
189 std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum);205 std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum);
...@@ -205,11 +221,12 @@ fn startPuts(ctx: *Context) u8 {...@@ -205,11 +221,12 @@ fn startPuts(ctx: *Context) u8 {
205 while (put_count != 0) : (put_count -= 1) {221 while (put_count != 0) : (put_count -= 1) {
206 std.os.time.sleep(1); // let the os scheduler be our fuzz222 std.os.time.sleep(1); // let the os scheduler be our fuzz
207 const x = @bitCast(i32, r.random.scalar(u32));223 const x = @bitCast(i32, r.random.scalar(u32));
208 const node = ctx.allocator.create(Queue(i32).Node{224 const node = ctx.allocator.create(Queue(i32).Node) catch unreachable;
225 node.* = Queue(i32).Node{
209 .prev = undefined,226 .prev = undefined,
210 .next = undefined,227 .next = undefined,
211 .data = x,228 .data = x,
212 }) catch unreachable;229 };
213 ctx.queue.put(node);230 ctx.queue.put(node);
214 _ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst);231 _ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst);
215 }232 }
std/atomic/stack.zig+59-28
...@@ -4,10 +4,13 @@ const AtomicOrder = builtin.AtomicOrder;...@@ -4,10 +4,13 @@ const AtomicOrder = builtin.AtomicOrder;
44
5/// Many reader, many writer, non-allocating, thread-safe5/// Many reader, many writer, non-allocating, thread-safe
6/// Uses a spinlock to protect push() and pop()6/// Uses a spinlock to protect push() and pop()
7/// When building in single threaded mode, this is a simple linked list.
7pub fn Stack(comptime T: type) type {8pub fn Stack(comptime T: type) type {
8 return struct {9 return struct {
9 root: ?*Node,10 root: ?*Node,
10 lock: u8,11 lock: @typeOf(lock_init),
12
13 const lock_init = if (builtin.single_threaded) {} else u8(0);
1114
12 pub const Self = @This();15 pub const Self = @This();
1316
...@@ -19,7 +22,7 @@ pub fn Stack(comptime T: type) type {...@@ -19,7 +22,7 @@ pub fn Stack(comptime T: type) type {
19 pub fn init() Self {22 pub fn init() Self {
20 return Self{23 return Self{
21 .root = null,24 .root = null,
22 .lock = 0,25 .lock = lock_init,
23 };26 };
24 }27 }
2528
...@@ -31,20 +34,31 @@ pub fn Stack(comptime T: type) type {...@@ -31,20 +34,31 @@ pub fn Stack(comptime T: type) type {
31 }34 }
3235
33 pub fn push(self: *Self, node: *Node) void {36 pub fn push(self: *Self, node: *Node) void {
34 while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}37 if (builtin.single_threaded) {
35 defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);38 node.next = self.root;
3639 self.root = node;
37 node.next = self.root;40 } else {
38 self.root = node;41 while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
42 defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
43
44 node.next = self.root;
45 self.root = node;
46 }
39 }47 }
4048
41 pub fn pop(self: *Self) ?*Node {49 pub fn pop(self: *Self) ?*Node {
42 while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}50 if (builtin.single_threaded) {
43 defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);51 const root = self.root orelse return null;
4452 self.root = root.next;
45 const root = self.root orelse return null;53 return root;
46 self.root = root.next;54 } else {
47 return root;55 while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
56 defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
57
58 const root = self.root orelse return null;
59 self.root = root.next;
60 return root;
61 }
48 }62 }
4963
50 pub fn isEmpty(self: *Self) bool {64 pub fn isEmpty(self: *Self) bool {
...@@ -90,20 +104,36 @@ test "std.atomic.stack" {...@@ -90,20 +104,36 @@ test "std.atomic.stack" {
90 .get_count = 0,104 .get_count = 0,
91 };105 };
92106
93 var putters: [put_thread_count]*std.os.Thread = undefined;107 if (builtin.single_threaded) {
94 for (putters) |*t| {108 {
95 t.* = try std.os.spawnThread(&context, startPuts);109 var i: usize = 0;
96 }110 while (i < put_thread_count) : (i += 1) {
97 var getters: [put_thread_count]*std.os.Thread = undefined;111 std.debug.assertOrPanic(startPuts(&context) == 0);
98 for (getters) |*t| {112 }
99 t.* = try std.os.spawnThread(&context, startGets);113 }
100 }114 context.puts_done = 1;
115 {
116 var i: usize = 0;
117 while (i < put_thread_count) : (i += 1) {
118 std.debug.assertOrPanic(startGets(&context) == 0);
119 }
120 }
121 } else {
122 var putters: [put_thread_count]*std.os.Thread = undefined;
123 for (putters) |*t| {
124 t.* = try std.os.spawnThread(&context, startPuts);
125 }
126 var getters: [put_thread_count]*std.os.Thread = undefined;
127 for (getters) |*t| {
128 t.* = try std.os.spawnThread(&context, startGets);
129 }
101130
102 for (putters) |t|131 for (putters) |t|
103 t.wait();132 t.wait();
104 _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);133 _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
105 for (getters) |t|134 for (getters) |t|
106 t.wait();135 t.wait();
136 }
107137
108 if (context.put_sum != context.get_sum) {138 if (context.put_sum != context.get_sum) {
109 std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum);139 std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum);
...@@ -125,10 +155,11 @@ fn startPuts(ctx: *Context) u8 {...@@ -125,10 +155,11 @@ fn startPuts(ctx: *Context) u8 {
125 while (put_count != 0) : (put_count -= 1) {155 while (put_count != 0) : (put_count -= 1) {
126 std.os.time.sleep(1); // let the os scheduler be our fuzz156 std.os.time.sleep(1); // let the os scheduler be our fuzz
127 const x = @bitCast(i32, r.random.scalar(u32));157 const x = @bitCast(i32, r.random.scalar(u32));
128 const node = ctx.allocator.create(Stack(i32).Node{158 const node = ctx.allocator.create(Stack(i32).Node) catch unreachable;
159 node.* = Stack(i32).Node{
129 .next = undefined,160 .next = undefined,
130 .data = x,161 .data = x,
131 }) catch unreachable;162 };
132 ctx.stack.push(node);163 ctx.stack.push(node);
133 _ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst);164 _ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst);
134 }165 }
std/build.zig+39-23
...@@ -89,7 +89,7 @@ pub const Builder = struct {...@@ -89,7 +89,7 @@ pub const Builder = struct {
89 };89 };
9090
91 pub fn init(allocator: *Allocator, zig_exe: []const u8, build_root: []const u8, cache_root: []const u8) Builder {91 pub fn init(allocator: *Allocator, zig_exe: []const u8, build_root: []const u8, cache_root: []const u8) Builder {
92 const env_map = allocator.createOne(BufMap) catch unreachable;92 const env_map = allocator.create(BufMap) catch unreachable;
93 env_map.* = os.getEnvMap(allocator) catch unreachable;93 env_map.* = os.getEnvMap(allocator) catch unreachable;
94 var self = Builder{94 var self = Builder{
95 .zig_exe = zig_exe,95 .zig_exe = zig_exe,
...@@ -170,7 +170,8 @@ pub const Builder = struct {...@@ -170,7 +170,8 @@ pub const Builder = struct {
170 }170 }
171171
172 pub fn addTest(self: *Builder, root_src: []const u8) *TestStep {172 pub fn addTest(self: *Builder, root_src: []const u8) *TestStep {
173 const test_step = self.allocator.create(TestStep.init(self, root_src)) catch unreachable;173 const test_step = self.allocator.create(TestStep) catch unreachable;
174 test_step.* = TestStep.init(self, root_src);
174 return test_step;175 return test_step;
175 }176 }
176177
...@@ -202,18 +203,21 @@ pub const Builder = struct {...@@ -202,18 +203,21 @@ pub const Builder = struct {
202 }203 }
203204
204 pub fn addWriteFile(self: *Builder, file_path: []const u8, data: []const u8) *WriteFileStep {205 pub fn addWriteFile(self: *Builder, file_path: []const u8, data: []const u8) *WriteFileStep {
205 const write_file_step = self.allocator.create(WriteFileStep.init(self, file_path, data)) catch unreachable;206 const write_file_step = self.allocator.create(WriteFileStep) catch unreachable;
207 write_file_step.* = WriteFileStep.init(self, file_path, data);
206 return write_file_step;208 return write_file_step;
207 }209 }
208210
209 pub fn addLog(self: *Builder, comptime format: []const u8, args: ...) *LogStep {211 pub fn addLog(self: *Builder, comptime format: []const u8, args: ...) *LogStep {
210 const data = self.fmt(format, args);212 const data = self.fmt(format, args);
211 const log_step = self.allocator.create(LogStep.init(self, data)) catch unreachable;213 const log_step = self.allocator.create(LogStep) catch unreachable;
214 log_step.* = LogStep.init(self, data);
212 return log_step;215 return log_step;
213 }216 }
214217
215 pub fn addRemoveDirTree(self: *Builder, dir_path: []const u8) *RemoveDirStep {218 pub fn addRemoveDirTree(self: *Builder, dir_path: []const u8) *RemoveDirStep {
216 const remove_dir_step = self.allocator.create(RemoveDirStep.init(self, dir_path)) catch unreachable;219 const remove_dir_step = self.allocator.create(RemoveDirStep) catch unreachable;
220 remove_dir_step.* = RemoveDirStep.init(self, dir_path);
217 return remove_dir_step;221 return remove_dir_step;
218 }222 }
219223
...@@ -320,7 +324,7 @@ pub const Builder = struct {...@@ -320,7 +324,7 @@ pub const Builder = struct {
320324
321 fn processNixOSEnvVars(self: *Builder) void {325 fn processNixOSEnvVars(self: *Builder) void {
322 if (os.getEnvVarOwned(self.allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {326 if (os.getEnvVarOwned(self.allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {
323 var it = mem.split(nix_cflags_compile, " ");327 var it = mem.tokenize(nix_cflags_compile, " ");
324 while (true) {328 while (true) {
325 const word = it.next() orelse break;329 const word = it.next() orelse break;
326 if (mem.eql(u8, word, "-isystem")) {330 if (mem.eql(u8, word, "-isystem")) {
...@@ -338,7 +342,7 @@ pub const Builder = struct {...@@ -338,7 +342,7 @@ pub const Builder = struct {
338 assert(err == error.EnvironmentVariableNotFound);342 assert(err == error.EnvironmentVariableNotFound);
339 }343 }
340 if (os.getEnvVarOwned(self.allocator, "NIX_LDFLAGS")) |nix_ldflags| {344 if (os.getEnvVarOwned(self.allocator, "NIX_LDFLAGS")) |nix_ldflags| {
341 var it = mem.split(nix_ldflags, " ");345 var it = mem.tokenize(nix_ldflags, " ");
342 while (true) {346 while (true) {
343 const word = it.next() orelse break;347 const word = it.next() orelse break;
344 if (mem.eql(u8, word, "-rpath")) {348 if (mem.eql(u8, word, "-rpath")) {
...@@ -414,10 +418,11 @@ pub const Builder = struct {...@@ -414,10 +418,11 @@ pub const Builder = struct {
414 }418 }
415419
416 pub fn step(self: *Builder, name: []const u8, description: []const u8) *Step {420 pub fn step(self: *Builder, name: []const u8, description: []const u8) *Step {
417 const step_info = self.allocator.create(TopLevelStep{421 const step_info = self.allocator.create(TopLevelStep) catch unreachable;
422 step_info.* = TopLevelStep{
418 .step = Step.initNoOp(name, self.allocator),423 .step = Step.initNoOp(name, self.allocator),
419 .description = description,424 .description = description,
420 }) catch unreachable;425 };
421 self.top_level_steps.append(step_info) catch unreachable;426 self.top_level_steps.append(step_info) catch unreachable;
422 return &step_info.step;427 return &step_info.step;
423 }428 }
...@@ -616,7 +621,8 @@ pub const Builder = struct {...@@ -616,7 +621,8 @@ pub const Builder = struct {
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(self.allocator, self.prefix, dest_rel_path) catch unreachable;
617 self.pushInstalledFile(full_dest_path);622 self.pushInstalledFile(full_dest_path);
618623
619 const install_step = self.allocator.create(InstallFileStep.init(self, src_path, full_dest_path)) catch unreachable;624 const install_step = self.allocator.create(InstallFileStep) catch unreachable;
625 install_step.* = InstallFileStep.init(self, src_path, full_dest_path);
620 return install_step;626 return install_step;
621 }627 }
622628
...@@ -683,7 +689,7 @@ pub const Builder = struct {...@@ -683,7 +689,7 @@ pub const Builder = struct {
683 if (os.path.isAbsolute(name)) {689 if (os.path.isAbsolute(name)) {
684 return name;690 return name;
685 }691 }
686 var it = mem.split(PATH, []u8{os.path.delimiter});692 var it = mem.tokenize(PATH, []u8{os.path.delimiter});
687 while (it.next()) |path| {693 while (it.next()) |path| {
688 const full_path = try os.path.join(self.allocator, path, self.fmt("{}{}", name, exe_extension));694 const full_path = try os.path.join(self.allocator, path, self.fmt("{}{}", name, exe_extension));
689 if (os.path.real(self.allocator, full_path)) |real_path| {695 if (os.path.real(self.allocator, full_path)) |real_path| {
...@@ -865,43 +871,51 @@ pub const LibExeObjStep = struct {...@@ -865,43 +871,51 @@ pub const LibExeObjStep = struct {
865 };871 };
866872
867 pub fn createSharedLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8, ver: Version) *LibExeObjStep {873 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;874 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
875 self.* = initExtraArgs(builder, name, root_src, Kind.Lib, false, ver);
869 return self;876 return self;
870 }877 }
871878
872 pub fn createCSharedLibrary(builder: *Builder, name: []const u8, version: Version) *LibExeObjStep {879 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;880 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
881 self.* = initC(builder, name, Kind.Lib, version, false);
874 return self;882 return self;
875 }883 }
876884
877 pub fn createStaticLibrary(builder: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {885 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;886 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
887 self.* = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0));
879 return self;888 return self;
880 }889 }
881890
882 pub fn createCStaticLibrary(builder: *Builder, name: []const u8) *LibExeObjStep {891 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;892 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
893 self.* = initC(builder, name, Kind.Lib, builder.version(0, 0, 0), true);
884 return self;894 return self;
885 }895 }
886896
887 pub fn createObject(builder: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep {897 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;898 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
899 self.* = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0));
889 return self;900 return self;
890 }901 }
891902
892 pub fn createCObject(builder: *Builder, name: []const u8, src: []const u8) *LibExeObjStep {903 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;904 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
905 self.* = initC(builder, name, Kind.Obj, builder.version(0, 0, 0), false);
894 self.object_src = src;906 self.object_src = src;
895 return self;907 return self;
896 }908 }
897909
898 pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?[]const u8, static: bool) *LibExeObjStep {910 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;911 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
912 self.* = initExtraArgs(builder, name, root_src, Kind.Exe, static, builder.version(0, 0, 0));
900 return self;913 return self;
901 }914 }
902915
903 pub fn createCExecutable(builder: *Builder, name: []const u8) *LibExeObjStep {916 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;917 const self = builder.allocator.create(LibExeObjStep) catch unreachable;
918 self.* = initC(builder, name, Kind.Exe, builder.version(0, 0, 0), false);
905 return self;919 return self;
906 }920 }
907921
...@@ -1914,13 +1928,14 @@ pub const CommandStep = struct {...@@ -1914,13 +1928,14 @@ pub const CommandStep = struct {
19141928
1915 /// ::argv is copied.1929 /// ::argv is copied.
1916 pub fn create(builder: *Builder, cwd: ?[]const u8, env_map: *const BufMap, argv: []const []const u8) *CommandStep {1930 pub fn create(builder: *Builder, cwd: ?[]const u8, env_map: *const BufMap, argv: []const []const u8) *CommandStep {
1917 const self = builder.allocator.create(CommandStep{1931 const self = builder.allocator.create(CommandStep) catch unreachable;
1932 self.* = CommandStep{
1918 .builder = builder,1933 .builder = builder,
1919 .step = Step.init(argv[0], builder.allocator, make),1934 .step = Step.init(argv[0], builder.allocator, make),
1920 .argv = builder.allocator.alloc([]u8, argv.len) catch unreachable,1935 .argv = builder.allocator.alloc([]u8, argv.len) catch unreachable,
1921 .cwd = cwd,1936 .cwd = cwd,
1922 .env_map = env_map,1937 .env_map = env_map,
1923 }) catch unreachable;1938 };
19241939
1925 mem.copy([]const u8, self.argv, argv);1940 mem.copy([]const u8, self.argv, argv);
1926 self.step.name = self.argv[0];1941 self.step.name = self.argv[0];
...@@ -1949,12 +1964,13 @@ const InstallArtifactStep = struct {...@@ -1949,12 +1964,13 @@ const InstallArtifactStep = struct {
1949 LibExeObjStep.Kind.Exe => builder.exe_dir,1964 LibExeObjStep.Kind.Exe => builder.exe_dir,
1950 LibExeObjStep.Kind.Lib => builder.lib_dir,1965 LibExeObjStep.Kind.Lib => builder.lib_dir,
1951 };1966 };
1952 const self = builder.allocator.create(Self{1967 const self = builder.allocator.create(Self) catch unreachable;
1968 self.* = Self{
1953 .builder = builder,1969 .builder = builder,
1954 .step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make),1970 .step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make),
1955 .artifact = artifact,1971 .artifact = artifact,
1956 .dest_file = os.path.join(builder.allocator, dest_dir, artifact.out_filename) catch unreachable,1972 .dest_file = os.path.join(builder.allocator, dest_dir, artifact.out_filename) catch unreachable,
1957 }) catch unreachable;1973 };
1958 self.step.dependOn(&artifact.step);1974 self.step.dependOn(&artifact.step);
1959 builder.pushInstalledFile(self.dest_file);1975 builder.pushInstalledFile(self.dest_file);
1960 if (self.artifact.kind == LibExeObjStep.Kind.Lib and !self.artifact.static) {1976 if (self.artifact.kind == LibExeObjStep.Kind.Lib and !self.artifact.static) {
std/c/darwin.zig+20-2
...@@ -73,8 +73,8 @@ pub const sockaddr_in6 = extern struct {...@@ -73,8 +73,8 @@ pub const sockaddr_in6 = extern struct {
73};73};
7474
75pub const timeval = extern struct {75pub const timeval = extern struct {
76 tv_sec: isize,76 tv_sec: c_long,
77 tv_usec: isize,77 tv_usec: i32,
78};78};
7979
80pub const timezone = extern struct {80pub const timezone = extern struct {
...@@ -176,6 +176,24 @@ pub const kevent64_s = extern struct {...@@ -176,6 +176,24 @@ pub const kevent64_s = extern struct {
176 ext: [2]u64,176 ext: [2]u64,
177};177};
178178
179pub const mach_port_t = c_uint;
180pub const clock_serv_t = mach_port_t;
181pub const clock_res_t = c_int;
182pub const mach_port_name_t = natural_t;
183pub const natural_t = c_uint;
184pub const mach_timespec_t = extern struct {
185 tv_sec: c_uint,
186 tv_nsec: clock_res_t,
187};
188pub const kern_return_t = c_int;
189pub const host_t = mach_port_t;
190pub const CALENDAR_CLOCK = 1;
191
192pub extern fn mach_host_self() mach_port_t;
193pub extern fn clock_get_time(clock_serv: clock_serv_t, cur_time: *mach_timespec_t) kern_return_t;
194pub extern fn host_get_clock_service(host: host_t, clock_id: clock_id_t, clock_serv: ?[*]clock_serv_t) kern_return_t;
195pub extern fn mach_port_deallocate(task: ipc_space_t, name: mach_port_name_t) kern_return_t;
196
179// sys/types.h on macos uses #pragma pack() so these checks are197// sys/types.h on macos uses #pragma pack() so these checks are
180// to make sure the struct is laid out the same. These values were198// to make sure the struct is laid out the same. These values were
181// produced from C code using the offsetof macro.199// produced from C code using the offsetof macro.
std/c/index.zig+1-1
...@@ -44,7 +44,7 @@ pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) c_int;...@@ -44,7 +44,7 @@ pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) c_int;
44pub extern "c" fn readlink(noalias path: [*]const u8, noalias buf: [*]u8, bufsize: usize) isize;44pub extern "c" fn readlink(noalias path: [*]const u8, noalias buf: [*]u8, bufsize: usize) isize;
45pub extern "c" fn realpath(noalias file_name: [*]const u8, noalias resolved_name: [*]u8) ?[*]u8;45pub extern "c" fn realpath(noalias file_name: [*]const u8, noalias resolved_name: [*]u8) ?[*]u8;
46pub extern "c" fn sigprocmask(how: c_int, noalias set: *const sigset_t, noalias oset: ?*sigset_t) c_int;46pub extern "c" fn sigprocmask(how: c_int, noalias set: *const sigset_t, noalias oset: ?*sigset_t) c_int;
47pub extern "c" fn gettimeofday(tv: ?*timeval, tz: ?*timezone) c_int;47pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int;
48pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int;48pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int;
49pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int;49pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int;
50pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int;50pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int;
std/debug/index.zig+4-3
...@@ -751,7 +751,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {...@@ -751,7 +751,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
751 const self_file = try os.openSelfExe();751 const self_file = try os.openSelfExe();
752 defer self_file.close();752 defer self_file.close();
753753
754 const coff_obj = try allocator.createOne(coff.Coff);754 const coff_obj = try allocator.create(coff.Coff);
755 coff_obj.* = coff.Coff{755 coff_obj.* = coff.Coff{
756 .in_file = self_file,756 .in_file = self_file,
757 .allocator = allocator,757 .allocator = allocator,
...@@ -1036,7 +1036,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {...@@ -1036,7 +1036,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
1036 }1036 }
1037 }1037 }
1038 }1038 }
1039 const sentinel = try allocator.createOne(macho.nlist_64);1039 const sentinel = try allocator.create(macho.nlist_64);
1040 sentinel.* = macho.nlist_64{1040 sentinel.* = macho.nlist_64{
1041 .n_strx = 0,1041 .n_strx = 0,
1042 .n_type = 36,1042 .n_type = 36,
...@@ -1949,7 +1949,8 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void {...@@ -1949,7 +1949,8 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void {
19491949
1950 try di.dwarf_seekable_stream.seekTo(compile_unit_pos);1950 try di.dwarf_seekable_stream.seekTo(compile_unit_pos);
19511951
1952 const compile_unit_die = try di.allocator().create(try parseDie(di, abbrev_table, is_64));1952 const compile_unit_die = try di.allocator().create(Die);
1953 compile_unit_die.* = try parseDie(di, abbrev_table, is_64);
19531954
1954 if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo;1955 if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo;
19551956
std/event/channel.zig+6-2
...@@ -54,7 +54,8 @@ pub fn Channel(comptime T: type) type {...@@ -54,7 +54,8 @@ pub fn Channel(comptime T: type) type {
54 const buffer_nodes = try loop.allocator.alloc(T, capacity);54 const buffer_nodes = try loop.allocator.alloc(T, capacity);
55 errdefer loop.allocator.free(buffer_nodes);55 errdefer loop.allocator.free(buffer_nodes);
5656
57 const self = try loop.allocator.create(SelfChannel{57 const self = try loop.allocator.create(SelfChannel);
58 self.* = SelfChannel{
58 .loop = loop,59 .loop = loop,
59 .buffer_len = 0,60 .buffer_len = 0,
60 .buffer_nodes = buffer_nodes,61 .buffer_nodes = buffer_nodes,
...@@ -66,7 +67,7 @@ pub fn Channel(comptime T: type) type {...@@ -66,7 +67,7 @@ pub fn Channel(comptime T: type) type {
66 .or_null_queue = std.atomic.Queue(*std.atomic.Queue(GetNode).Node).init(),67 .or_null_queue = std.atomic.Queue(*std.atomic.Queue(GetNode).Node).init(),
67 .get_count = 0,68 .get_count = 0,
68 .put_count = 0,69 .put_count = 0,
69 });70 };
70 errdefer loop.allocator.destroy(self);71 errdefer loop.allocator.destroy(self);
7172
72 return self;73 return self;
...@@ -319,6 +320,9 @@ pub fn Channel(comptime T: type) type {...@@ -319,6 +320,9 @@ pub fn Channel(comptime T: type) type {
319}320}
320321
321test "std.event.Channel" {322test "std.event.Channel" {
323 // https://github.com/ziglang/zig/issues/1908
324 if (builtin.single_threaded) return error.SkipZigTest;
325
322 var da = std.heap.DirectAllocator.init();326 var da = std.heap.DirectAllocator.init();
323 defer da.deinit();327 defer da.deinit();
324328
std/event/fs.zig+27-30
...@@ -495,7 +495,7 @@ pub const CloseOperation = struct {...@@ -495,7 +495,7 @@ pub const CloseOperation = struct {
495 };495 };
496496
497 pub fn start(loop: *Loop) (error{OutOfMemory}!*CloseOperation) {497 pub fn start(loop: *Loop) (error{OutOfMemory}!*CloseOperation) {
498 const self = try loop.allocator.createOne(CloseOperation);498 const self = try loop.allocator.create(CloseOperation);
499 self.* = CloseOperation{499 self.* = CloseOperation{
500 .loop = loop,500 .loop = loop,
501 .os_data = switch (builtin.os) {501 .os_data = switch (builtin.os) {
...@@ -787,7 +787,7 @@ pub fn Watch(comptime V: type) type {...@@ -787,7 +787,7 @@ pub fn Watch(comptime V: type) type {
787 },787 },
788788
789 builtin.Os.windows => {789 builtin.Os.windows => {
790 const self = try loop.allocator.createOne(Self);790 const self = try loop.allocator.create(Self);
791 errdefer loop.allocator.destroy(self);791 errdefer loop.allocator.destroy(self);
792 self.* = Self{792 self.* = Self{
793 .channel = channel,793 .channel = channel,
...@@ -802,7 +802,7 @@ pub fn Watch(comptime V: type) type {...@@ -802,7 +802,7 @@ pub fn Watch(comptime V: type) type {
802 },802 },
803803
804 builtin.Os.macosx, builtin.Os.freebsd => {804 builtin.Os.macosx, builtin.Os.freebsd => {
805 const self = try loop.allocator.createOne(Self);805 const self = try loop.allocator.create(Self);
806 errdefer loop.allocator.destroy(self);806 errdefer loop.allocator.destroy(self);
807807
808 self.* = Self{808 self.* = Self{
...@@ -1068,7 +1068,7 @@ pub fn Watch(comptime V: type) type {...@@ -1068,7 +1068,7 @@ pub fn Watch(comptime V: type) type {
1068 }1068 }
1069 } else {1069 } else {
1070 errdefer _ = self.os_data.dir_table.remove(dirname);1070 errdefer _ = self.os_data.dir_table.remove(dirname);
1071 const dir = try self.channel.loop.allocator.createOne(OsData.Dir);1071 const dir = try self.channel.loop.allocator.create(OsData.Dir);
1072 errdefer self.channel.loop.allocator.destroy(dir);1072 errdefer self.channel.loop.allocator.destroy(dir);
10731073
1074 dir.* = OsData.Dir{1074 dir.* = OsData.Dir{
...@@ -1307,32 +1307,29 @@ pub fn Watch(comptime V: type) type {...@@ -1307,32 +1307,29 @@ pub fn Watch(comptime V: type) type {
13071307
1308const test_tmp_dir = "std_event_fs_test";1308const test_tmp_dir = "std_event_fs_test";
13091309
1310test "write a file, watch it, write it again" {1310// TODO this test is disabled until the coroutine rewrite is finished.
1311 if (builtin.os == builtin.Os.windows) {1311//test "write a file, watch it, write it again" {
1312 // TODO this test is disabled on windows until the coroutine rewrite is finished.1312// return error.SkipZigTest;
1313 // https://github.com/ziglang/zig/issues/13631313// var da = std.heap.DirectAllocator.init();
1314 return error.SkipZigTest;1314// defer da.deinit();
1315 }1315//
1316 var da = std.heap.DirectAllocator.init();1316// const allocator = &da.allocator;
1317 defer da.deinit();1317//
13181318// // TODO move this into event loop too
1319 const allocator = &da.allocator;1319// try os.makePath(allocator, test_tmp_dir);
13201320// defer os.deleteTree(allocator, test_tmp_dir) catch {};
1321 // TODO move this into event loop too1321//
1322 try os.makePath(allocator, test_tmp_dir);1322// var loop: Loop = undefined;
1323 defer os.deleteTree(allocator, test_tmp_dir) catch {};1323// try loop.initMultiThreaded(allocator);
13241324// defer loop.deinit();
1325 var loop: Loop = undefined;1325//
1326 try loop.initMultiThreaded(allocator);1326// var result: anyerror!void = error.ResultNeverWritten;
1327 defer loop.deinit();1327// const handle = try async<allocator> testFsWatchCantFail(&loop, &result);
13281328// defer cancel handle;
1329 var result: anyerror!void = error.ResultNeverWritten;1329//
1330 const handle = try async<allocator> testFsWatchCantFail(&loop, &result);1330// loop.run();
1331 defer cancel handle;1331// return result;
13321332//}
1333 loop.run();
1334 return result;
1335}
13361333
1337async fn testFsWatchCantFail(loop: *Loop, result: *(anyerror!void)) void {1334async fn testFsWatchCantFail(loop: *Loop, result: *(anyerror!void)) void {
1338 result.* = await (async testFsWatch(loop) catch unreachable);1335 result.* = await (async testFsWatch(loop) catch unreachable);
std/event/future.zig+3
...@@ -84,6 +84,9 @@ pub fn Future(comptime T: type) type {...@@ -84,6 +84,9 @@ pub fn Future(comptime T: type) type {
84}84}
8585
86test "std.event.Future" {86test "std.event.Future" {
87 // https://github.com/ziglang/zig/issues/1908
88 if (builtin.single_threaded) return error.SkipZigTest;
89
87 var da = std.heap.DirectAllocator.init();90 var da = std.heap.DirectAllocator.init();
88 defer da.deinit();91 defer da.deinit();
8992
std/event/group.zig+6-2
...@@ -42,10 +42,11 @@ pub fn Group(comptime ReturnType: type) type {...@@ -42,10 +42,11 @@ pub fn Group(comptime ReturnType: type) type {
4242
43 /// Add a promise to the group. Thread-safe.43 /// Add a promise to the group. Thread-safe.
44 pub fn add(self: *Self, handle: promise->ReturnType) (error{OutOfMemory}!void) {44 pub fn add(self: *Self, handle: promise->ReturnType) (error{OutOfMemory}!void) {
45 const node = try self.lock.loop.allocator.create(Stack.Node{45 const node = try self.lock.loop.allocator.create(Stack.Node);
46 node.* = Stack.Node{
46 .next = undefined,47 .next = undefined,
47 .data = handle,48 .data = handle,
48 });49 };
49 self.alloc_stack.push(node);50 self.alloc_stack.push(node);
50 }51 }
5152
...@@ -121,6 +122,9 @@ pub fn Group(comptime ReturnType: type) type {...@@ -121,6 +122,9 @@ pub fn Group(comptime ReturnType: type) type {
121}122}
122123
123test "std.event.Group" {124test "std.event.Group" {
125 // https://github.com/ziglang/zig/issues/1908
126 if (builtin.single_threaded) return error.SkipZigTest;
127
124 var da = std.heap.DirectAllocator.init();128 var da = std.heap.DirectAllocator.init();
125 defer da.deinit();129 defer da.deinit();
126130
std/event/lock.zig+3
...@@ -122,6 +122,9 @@ pub const Lock = struct {...@@ -122,6 +122,9 @@ pub const Lock = struct {
122};122};
123123
124test "std.event.Lock" {124test "std.event.Lock" {
125 // https://github.com/ziglang/zig/issues/1908
126 if (builtin.single_threaded) return error.SkipZigTest;
127
125 var da = std.heap.DirectAllocator.init();128 var da = std.heap.DirectAllocator.init();
126 defer da.deinit();129 defer da.deinit();
127130
std/event/loop.zig+22
...@@ -97,6 +97,7 @@ pub const Loop = struct {...@@ -97,6 +97,7 @@ pub const Loop = struct {
97 /// TODO copy elision / named return values so that the threads referencing *Loop97 /// TODO copy elision / named return values so that the threads referencing *Loop
98 /// have the correct pointer value.98 /// have the correct pointer value.
99 pub fn initMultiThreaded(self: *Loop, allocator: *mem.Allocator) !void {99 pub fn initMultiThreaded(self: *Loop, allocator: *mem.Allocator) !void {
100 if (builtin.single_threaded) @compileError("initMultiThreaded unavailable when building in single-threaded mode");
100 const core_count = try os.cpuCount(allocator);101 const core_count = try os.cpuCount(allocator);
101 return self.initInternal(allocator, core_count);102 return self.initInternal(allocator, core_count);
102 }103 }
...@@ -201,6 +202,11 @@ pub const Loop = struct {...@@ -201,6 +202,11 @@ pub const Loop = struct {
201 self.os_data.fs_thread.wait();202 self.os_data.fs_thread.wait();
202 }203 }
203204
205 if (builtin.single_threaded) {
206 assert(extra_thread_count == 0);
207 return;
208 }
209
204 var extra_thread_index: usize = 0;210 var extra_thread_index: usize = 0;
205 errdefer {211 errdefer {
206 // writing 8 bytes to an eventfd cannot fail212 // writing 8 bytes to an eventfd cannot fail
...@@ -301,6 +307,11 @@ pub const Loop = struct {...@@ -301,6 +307,11 @@ pub const Loop = struct {
301 self.os_data.fs_thread.wait();307 self.os_data.fs_thread.wait();
302 }308 }
303309
310 if (builtin.single_threaded) {
311 assert(extra_thread_count == 0);
312 return;
313 }
314
304 var extra_thread_index: usize = 0;315 var extra_thread_index: usize = 0;
305 errdefer {316 errdefer {
306 _ = os.bsdKEvent(self.os_data.kqfd, final_kev_arr, empty_kevs, null) catch unreachable;317 _ = os.bsdKEvent(self.os_data.kqfd, final_kev_arr, empty_kevs, null) catch unreachable;
...@@ -338,6 +349,11 @@ pub const Loop = struct {...@@ -338,6 +349,11 @@ pub const Loop = struct {
338 self.available_eventfd_resume_nodes.push(eventfd_node);349 self.available_eventfd_resume_nodes.push(eventfd_node);
339 }350 }
340351
352 if (builtin.single_threaded) {
353 assert(extra_thread_count == 0);
354 return;
355 }
356
341 var extra_thread_index: usize = 0;357 var extra_thread_index: usize = 0;
342 errdefer {358 errdefer {
343 var i: usize = 0;359 var i: usize = 0;
...@@ -845,6 +861,9 @@ pub const Loop = struct {...@@ -845,6 +861,9 @@ pub const Loop = struct {
845};861};
846862
847test "std.event.Loop - basic" {863test "std.event.Loop - basic" {
864 // https://github.com/ziglang/zig/issues/1908
865 if (builtin.single_threaded) return error.SkipZigTest;
866
848 var da = std.heap.DirectAllocator.init();867 var da = std.heap.DirectAllocator.init();
849 defer da.deinit();868 defer da.deinit();
850869
...@@ -858,6 +877,9 @@ test "std.event.Loop - basic" {...@@ -858,6 +877,9 @@ test "std.event.Loop - basic" {
858}877}
859878
860test "std.event.Loop - call" {879test "std.event.Loop - call" {
880 // https://github.com/ziglang/zig/issues/1908
881 if (builtin.single_threaded) return error.SkipZigTest;
882
861 var da = std.heap.DirectAllocator.init();883 var da = std.heap.DirectAllocator.init();
862 defer da.deinit();884 defer da.deinit();
863885
std/event/net.zig+3
...@@ -269,6 +269,9 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !os.File {...@@ -269,6 +269,9 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !os.File {
269}269}
270270
271test "listen on a port, send bytes, receive bytes" {271test "listen on a port, send bytes, receive bytes" {
272 // https://github.com/ziglang/zig/issues/1908
273 if (builtin.single_threaded) return error.SkipZigTest;
274
272 if (builtin.os != builtin.Os.linux) {275 if (builtin.os != builtin.Os.linux) {
273 // TODO build abstractions for other operating systems276 // TODO build abstractions for other operating systems
274 return error.SkipZigTest;277 return error.SkipZigTest;
std/event/rwlock.zig+3
...@@ -211,6 +211,9 @@ pub const RwLock = struct {...@@ -211,6 +211,9 @@ pub const RwLock = struct {
211};211};
212212
213test "std.event.RwLock" {213test "std.event.RwLock" {
214 // https://github.com/ziglang/zig/issues/1908
215 if (builtin.single_threaded) return error.SkipZigTest;
216
214 var da = std.heap.DirectAllocator.init();217 var da = std.heap.DirectAllocator.init();
215 defer da.deinit();218 defer da.deinit();
216219
std/fmt/index.zig-2
...@@ -982,13 +982,11 @@ test "fmt.format" {...@@ -982,13 +982,11 @@ test "fmt.format" {
982 context = BufPrintContext{ .remaining = buf1[0..] };982 context = BufPrintContext{ .remaining = buf1[0..] };
983 try formatType('a', "c", &context, error{BufferTooSmall}, bufPrintWrite);983 try formatType('a', "c", &context, error{BufferTooSmall}, bufPrintWrite);
984 res = buf1[0 .. buf1.len - context.remaining.len];984 res = buf1[0 .. buf1.len - context.remaining.len];
985 debug.warn("{}\n", res);
986 assert(mem.eql(u8, res, "a"));985 assert(mem.eql(u8, res, "a"));
987986
988 context = BufPrintContext{ .remaining = buf1[0..] };987 context = BufPrintContext{ .remaining = buf1[0..] };
989 try formatType(0b1100, "b", &context, error{BufferTooSmall}, bufPrintWrite);988 try formatType(0b1100, "b", &context, error{BufferTooSmall}, bufPrintWrite);
990 res = buf1[0 .. buf1.len - context.remaining.len];989 res = buf1[0 .. buf1.len - context.remaining.len];
991 debug.warn("{}\n", res);
992 assert(mem.eql(u8, res, "1100"));990 assert(mem.eql(u8, res, "1100"));
993 }991 }
994 {992 {
std/hash_map.zig+2
...@@ -508,6 +508,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type...@@ -508,6 +508,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type
508508
509 builtin.TypeId.Optional => @compileError("TODO auto hash for optionals"),509 builtin.TypeId.Optional => @compileError("TODO auto hash for optionals"),
510 builtin.TypeId.Array => @compileError("TODO auto hash for arrays"),510 builtin.TypeId.Array => @compileError("TODO auto hash for arrays"),
511 builtin.TypeId.Vector => @compileError("TODO auto hash for vectors"),
511 builtin.TypeId.Struct => @compileError("TODO auto hash for structs"),512 builtin.TypeId.Struct => @compileError("TODO auto hash for structs"),
512 builtin.TypeId.Union => @compileError("TODO auto hash for unions"),513 builtin.TypeId.Union => @compileError("TODO auto hash for unions"),
513 builtin.TypeId.ErrorUnion => @compileError("TODO auto hash for unions"),514 builtin.TypeId.ErrorUnion => @compileError("TODO auto hash for unions"),
...@@ -555,5 +556,6 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {...@@ -555,5 +556,6 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {
555 builtin.TypeId.Struct => @compileError("TODO auto eql for structs"),556 builtin.TypeId.Struct => @compileError("TODO auto eql for structs"),
556 builtin.TypeId.Union => @compileError("TODO auto eql for unions"),557 builtin.TypeId.Union => @compileError("TODO auto eql for unions"),
557 builtin.TypeId.ErrorUnion => @compileError("TODO auto eql for unions"),558 builtin.TypeId.ErrorUnion => @compileError("TODO auto eql for unions"),
559 builtin.TypeId.Vector => @compileError("TODO auto eql for vectors"),
558 }560 }
559}561}
std/heap.zig+2-1
...@@ -518,7 +518,8 @@ fn testAllocator(allocator: *mem.Allocator) !void {...@@ -518,7 +518,8 @@ fn testAllocator(allocator: *mem.Allocator) !void {
518 var slice = try allocator.alloc(*i32, 100);518 var slice = try allocator.alloc(*i32, 100);
519 assert(slice.len == 100);519 assert(slice.len == 100);
520 for (slice) |*item, i| {520 for (slice) |*item, i| {
521 item.* = try allocator.create(@intCast(i32, i));521 item.* = try allocator.create(i32);
522 item.*.* = @intCast(i32, i);
522 }523 }
523524
524 slice = try allocator.realloc(*i32, slice, 20000);525 slice = try allocator.realloc(*i32, slice, 20000);
std/index.zig+2
...@@ -9,6 +9,7 @@ pub const DynLib = @import("dynamic_library.zig").DynLib;...@@ -9,6 +9,7 @@ pub const DynLib = @import("dynamic_library.zig").DynLib;
9pub const HashMap = @import("hash_map.zig").HashMap;9pub const HashMap = @import("hash_map.zig").HashMap;
10pub const LinkedList = @import("linked_list.zig").LinkedList;10pub const LinkedList = @import("linked_list.zig").LinkedList;
11pub const Mutex = @import("mutex.zig").Mutex;11pub const Mutex = @import("mutex.zig").Mutex;
12pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex;
12pub const SegmentedList = @import("segmented_list.zig").SegmentedList;13pub const SegmentedList = @import("segmented_list.zig").SegmentedList;
13pub const SpinLock = @import("spinlock.zig").SpinLock;14pub const SpinLock = @import("spinlock.zig").SpinLock;
1415
...@@ -55,6 +56,7 @@ test "std" {...@@ -55,6 +56,7 @@ test "std" {
55 _ = @import("hash_map.zig");56 _ = @import("hash_map.zig");
56 _ = @import("linked_list.zig");57 _ = @import("linked_list.zig");
57 _ = @import("mutex.zig");58 _ = @import("mutex.zig");
59 _ = @import("statically_initialized_mutex.zig");
58 _ = @import("segmented_list.zig");60 _ = @import("segmented_list.zig");
59 _ = @import("spinlock.zig");61 _ = @import("spinlock.zig");
60 62
std/io.zig+654-13
...@@ -8,6 +8,8 @@ const debug = std.debug;...@@ -8,6 +8,8 @@ const debug = std.debug;
8const assert = debug.assert;8const assert = debug.assert;
9const os = std.os;9const os = std.os;
10const mem = std.mem;10const mem = std.mem;
11const meta = std.meta;
12const trait = meta.trait;
11const Buffer = std.Buffer;13const Buffer = std.Buffer;
12const fmt = std.fmt;14const fmt = std.fmt;
13const File = std.os.File;15const File = std.os.File;
...@@ -463,6 +465,153 @@ pub const SliceInStream = struct {...@@ -463,6 +465,153 @@ pub const SliceInStream = struct {
463 }465 }
464};466};
465467
468/// Creates a stream which allows for reading bit fields from another stream
469pub fn BitInStream(endian: builtin.Endian, comptime Error: type) type {
470 return struct {
471 const Self = @This();
472
473 in_stream: *Stream,
474 bit_buffer: u7,
475 bit_count: u3,
476 stream: Stream,
477
478 pub const Stream = InStream(Error);
479 const u8_bit_count = comptime meta.bitCount(u8);
480 const u7_bit_count = comptime meta.bitCount(u7);
481 const u4_bit_count = comptime meta.bitCount(u4);
482
483 pub fn init(in_stream: *Stream) Self {
484 return Self{
485 .in_stream = in_stream,
486 .bit_buffer = 0,
487 .bit_count = 0,
488 .stream = Stream{ .readFn = read },
489 };
490 }
491
492 /// Reads `bits` bits from the stream and returns a specified unsigned int type
493 /// containing them in the least significant end, returning an error if the
494 /// specified number of bits could not be read.
495 pub fn readBitsNoEof(self: *Self, comptime U: type, bits: usize) !U {
496 var n: usize = undefined;
497 const result = try self.readBits(U, bits, &n);
498 if (n < bits) return error.EndOfStream;
499 return result;
500 }
501
502 /// Reads `bits` bits from the stream and returns a specified unsigned int type
503 /// containing them in the least significant end. The number of bits successfully
504 /// read is placed in `out_bits`, as reaching the end of the stream is not an error.
505 pub fn readBits(self: *Self, comptime U: type, bits: usize, out_bits: *usize) Error!U {
506 comptime assert(trait.isUnsignedInt(U));
507
508 //by extending the buffer to a minimum of u8 we can cover a number of edge cases
509 // related to shifting and casting.
510 const u_bit_count = comptime meta.bitCount(U);
511 const buf_bit_count = bc: {
512 assert(u_bit_count >= bits);
513 break :bc if (u_bit_count <= u8_bit_count) u8_bit_count else u_bit_count;
514 };
515 const Buf = @IntType(false, buf_bit_count);
516 const BufShift = math.Log2Int(Buf);
517
518 out_bits.* = usize(0);
519 if (U == u0 or bits == 0) return 0;
520 var out_buffer = Buf(0);
521
522 if (self.bit_count > 0) {
523 const n = if (self.bit_count >= bits) @intCast(u3, bits) else self.bit_count;
524 const shift = u7_bit_count - n;
525 switch (endian) {
526 builtin.Endian.Big => {
527 out_buffer = Buf(self.bit_buffer >> shift);
528 self.bit_buffer <<= n;
529 },
530 builtin.Endian.Little => {
531 const value = (self.bit_buffer << shift) >> shift;
532 out_buffer = Buf(value);
533 self.bit_buffer >>= n;
534 },
535 }
536 self.bit_count -= n;
537 out_bits.* = n;
538 }
539 //at this point we know bit_buffer is empty
540
541 //copy bytes until we have enough bits, then leave the rest in bit_buffer
542 while (out_bits.* < bits) {
543 const n = bits - out_bits.*;
544 const next_byte = self.in_stream.readByte() catch |err| {
545 if (err == error.EndOfStream) {
546 return @intCast(U, out_buffer);
547 }
548 //@BUG: See #1810. Not sure if the bug is that I have to do this for some
549 // streams, or that I don't for streams with emtpy errorsets.
550 return @errSetCast(Error, err);
551 };
552
553 switch (endian) {
554 builtin.Endian.Big => {
555 if (n >= u8_bit_count) {
556 out_buffer <<= @intCast(u3, u8_bit_count - 1);
557 out_buffer <<= 1;
558 out_buffer |= Buf(next_byte);
559 out_bits.* += u8_bit_count;
560 continue;
561 }
562
563 const shift = @intCast(u3, u8_bit_count - n);
564 out_buffer <<= @intCast(BufShift, n);
565 out_buffer |= Buf(next_byte >> shift);
566 out_bits.* += n;
567 self.bit_buffer = @truncate(u7, next_byte << @intCast(u3, n - 1));
568 self.bit_count = shift;
569 },
570 builtin.Endian.Little => {
571 if (n >= u8_bit_count) {
572 out_buffer |= Buf(next_byte) << @intCast(BufShift, out_bits.*);
573 out_bits.* += u8_bit_count;
574 continue;
575 }
576
577 const shift = @intCast(u3, u8_bit_count - n);
578 const value = (next_byte << shift) >> shift;
579 out_buffer |= Buf(value) << @intCast(BufShift, out_bits.*);
580 out_bits.* += n;
581 self.bit_buffer = @truncate(u7, next_byte >> @intCast(u3, n));
582 self.bit_count = shift;
583 },
584 }
585 }
586
587 return @intCast(U, out_buffer);
588 }
589
590 pub fn alignToByte(self: *Self) void {
591 self.bit_buffer = 0;
592 self.bit_count = 0;
593 }
594
595 pub fn read(self_stream: *Stream, buffer: []u8) Error!usize {
596 var self = @fieldParentPtr(Self, "stream", self_stream);
597
598 var out_bits: usize = undefined;
599 var out_bits_total = usize(0);
600 //@NOTE: I'm not sure this is a good idea, maybe alignToByte should be forced
601 if (self.bit_count > 0) {
602 for (buffer) |*b, i| {
603 b.* = try self.readBits(u8, u8_bit_count, &out_bits);
604 out_bits_total += out_bits;
605 }
606 const incomplete_byte = @boolToInt(out_bits_total % u8_bit_count > 0);
607 return (out_bits_total / u8_bit_count) + incomplete_byte;
608 }
609
610 return self.in_stream.read(buffer);
611 }
612 };
613}
614
466/// This is a simple OutStream that writes to a slice, and returns an error615/// This is a simple OutStream that writes to a slice, and returns an error
467/// when it runs out of space.616/// when it runs out of space.
468pub const SliceOutStream = struct {617pub const SliceOutStream = struct {
...@@ -515,7 +664,7 @@ test "io.SliceOutStream" {...@@ -515,7 +664,7 @@ test "io.SliceOutStream" {
515 const stream = &slice_stream.stream;664 const stream = &slice_stream.stream;
516665
517 try stream.print("{}{}!", "Hello", "World");666 try stream.print("{}{}!", "Hello", "World");
518 debug.assert(mem.eql(u8, "HelloWorld!", slice_stream.getWritten()));667 debug.assertOrPanic(mem.eql(u8, "HelloWorld!", slice_stream.getWritten()));
519}668}
520669
521var null_out_stream_state = NullOutStream.init();670var null_out_stream_state = NullOutStream.init();
...@@ -577,7 +726,7 @@ test "io.CountingOutStream" {...@@ -577,7 +726,7 @@ test "io.CountingOutStream" {
577726
578 const bytes = "yay" ** 10000;727 const bytes = "yay" ** 10000;
579 stream.write(bytes) catch unreachable;728 stream.write(bytes) catch unreachable;
580 debug.assert(counting_stream.bytes_written == bytes.len);729 debug.assertOrPanic(counting_stream.bytes_written == bytes.len);
581}730}
582731
583pub fn BufferedOutStream(comptime Error: type) type {732pub fn BufferedOutStream(comptime Error: type) type {
...@@ -656,6 +805,137 @@ pub const BufferOutStream = struct {...@@ -656,6 +805,137 @@ pub const BufferOutStream = struct {
656 }805 }
657};806};
658807
808/// Creates a stream which allows for writing bit fields to another stream
809pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type {
810 return struct {
811 const Self = @This();
812
813 out_stream: *Stream,
814 bit_buffer: u8,
815 bit_count: u4,
816 stream: Stream,
817
818 pub const Stream = OutStream(Error);
819 const u8_bit_count = comptime meta.bitCount(u8);
820 const u4_bit_count = comptime meta.bitCount(u4);
821
822 pub fn init(out_stream: *Stream) Self {
823 return Self{
824 .out_stream = out_stream,
825 .bit_buffer = 0,
826 .bit_count = 0,
827 .stream = Stream{ .writeFn = write },
828 };
829 }
830
831 /// Write the specified number of bits to the stream from the least significant bits of
832 /// the specified unsigned int value. Bits will only be written to the stream when there
833 /// are enough to fill a byte.
834 pub fn writeBits(self: *Self, value: var, bits: usize) Error!void {
835 if (bits == 0) return;
836
837 const U = @typeOf(value);
838 comptime assert(trait.isUnsignedInt(U));
839
840 //by extending the buffer to a minimum of u8 we can cover a number of edge cases
841 // related to shifting and casting.
842 const u_bit_count = comptime meta.bitCount(U);
843 const buf_bit_count = bc: {
844 assert(u_bit_count >= bits);
845 break :bc if (u_bit_count <= u8_bit_count) u8_bit_count else u_bit_count;
846 };
847 const Buf = @IntType(false, buf_bit_count);
848 const BufShift = math.Log2Int(Buf);
849
850 const buf_value = @intCast(Buf, value);
851
852 const high_byte_shift = @intCast(BufShift, buf_bit_count - u8_bit_count);
853 var in_buffer = switch (endian) {
854 builtin.Endian.Big => buf_value << @intCast(BufShift, buf_bit_count - bits),
855 builtin.Endian.Little => buf_value,
856 };
857 var in_bits = bits;
858
859 if (self.bit_count > 0) {
860 const bits_remaining = u8_bit_count - self.bit_count;
861 const n = @intCast(u3, if (bits_remaining > bits) bits else bits_remaining);
862 switch (endian) {
863 builtin.Endian.Big => {
864 const shift = @intCast(BufShift, high_byte_shift + self.bit_count);
865 const v = @intCast(u8, in_buffer >> shift);
866 self.bit_buffer |= v;
867 in_buffer <<= n;
868 },
869 builtin.Endian.Little => {
870 const v = @truncate(u8, in_buffer) << @intCast(u3, self.bit_count);
871 self.bit_buffer |= v;
872 in_buffer >>= n;
873 },
874 }
875 self.bit_count += n;
876 in_bits -= n;
877
878 //if we didn't fill the buffer, it's because bits < bits_remaining;
879 if (self.bit_count != u8_bit_count) return;
880 try self.out_stream.writeByte(self.bit_buffer);
881 self.bit_buffer = 0;
882 self.bit_count = 0;
883 }
884 //at this point we know bit_buffer is empty
885
886 //copy bytes until we can't fill one anymore, then leave the rest in bit_buffer
887 while (in_bits >= u8_bit_count) {
888 switch (endian) {
889 builtin.Endian.Big => {
890 const v = @intCast(u8, in_buffer >> high_byte_shift);
891 try self.out_stream.writeByte(v);
892 in_buffer <<= @intCast(u3, u8_bit_count - 1);
893 in_buffer <<= 1;
894 },
895 builtin.Endian.Little => {
896 const v = @truncate(u8, in_buffer);
897 try self.out_stream.writeByte(v);
898 in_buffer >>= @intCast(u3, u8_bit_count - 1);
899 in_buffer >>= 1;
900 },
901 }
902 in_bits -= u8_bit_count;
903 }
904
905 if (in_bits > 0) {
906 self.bit_count = @intCast(u4, in_bits);
907 self.bit_buffer = switch (endian) {
908 builtin.Endian.Big => @truncate(u8, in_buffer >> high_byte_shift),
909 builtin.Endian.Little => @truncate(u8, in_buffer),
910 };
911 }
912 }
913
914 /// Flush any remaining bits to the stream.
915 pub fn flushBits(self: *Self) !void {
916 if (self.bit_count == 0) return;
917 try self.out_stream.writeByte(self.bit_buffer);
918 self.bit_buffer = 0;
919 self.bit_count = 0;
920 }
921
922 pub fn write(self_stream: *Stream, buffer: []const u8) Error!void {
923 var self = @fieldParentPtr(Self, "stream", self_stream);
924
925 //@NOTE: I'm not sure this is a good idea, maybe flushBits should be forced
926 if (self.bit_count > 0) {
927 for (buffer) |b, i|
928 try self.writeBits(b, u8_bit_count);
929 return;
930 }
931
932 return self.out_stream.write(buffer);
933 }
934 };
935}
936
937
938
659pub const BufferedAtomicFile = struct {939pub const BufferedAtomicFile = struct {
660 atomic_file: os.AtomicFile,940 atomic_file: os.AtomicFile,
661 file_stream: os.File.OutStream,941 file_stream: os.File.OutStream,
...@@ -664,12 +944,13 @@ pub const BufferedAtomicFile = struct {...@@ -664,12 +944,13 @@ pub const BufferedAtomicFile = struct {
664944
665 pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile {945 pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile {
666 // TODO with well defined copy elision we don't need this allocation946 // TODO with well defined copy elision we don't need this allocation
667 var self = try allocator.create(BufferedAtomicFile{947 var self = try allocator.create(BufferedAtomicFile);
948 self.* = BufferedAtomicFile{
668 .atomic_file = undefined,949 .atomic_file = undefined,
669 .file_stream = undefined,950 .file_stream = undefined,
670 .buffered_stream = undefined,951 .buffered_stream = undefined,
671 .allocator = allocator,952 .allocator = allocator,
672 });953 };
673 errdefer allocator.destroy(self);954 errdefer allocator.destroy(self);
674955
675 self.atomic_file = try os.AtomicFile.init(dest_path, os.File.default_mode);956 self.atomic_file = try os.AtomicFile.init(dest_path, os.File.default_mode);
...@@ -696,11 +977,6 @@ pub const BufferedAtomicFile = struct {...@@ -696,11 +977,6 @@ pub const BufferedAtomicFile = struct {
696 }977 }
697};978};
698979
699test "import io tests" {
700 comptime {
701 _ = @import("io_test.zig");
702 }
703}
704980
705pub fn readLine(buf: *std.Buffer) ![]u8 {981pub fn readLine(buf: *std.Buffer) ![]u8 {
706 var stdin = try getStdIn();982 var stdin = try getStdIn();
...@@ -738,10 +1014,10 @@ test "io.readLineFrom" {...@@ -738,10 +1014,10 @@ test "io.readLineFrom" {
738 );1014 );
739 const stream = &mem_stream.stream;1015 const stream = &mem_stream.stream;
7401016
741 debug.assert(mem.eql(u8, "Line 1", try readLineFrom(stream, &buf)));1017 debug.assertOrPanic(mem.eql(u8, "Line 1", try readLineFrom(stream, &buf)));
742 debug.assert(mem.eql(u8, "Line 22", try readLineFrom(stream, &buf)));1018 debug.assertOrPanic(mem.eql(u8, "Line 22", try readLineFrom(stream, &buf)));
743 debug.assertError(readLineFrom(stream, &buf), error.EndOfStream);1019 debug.assertError(readLineFrom(stream, &buf), error.EndOfStream);
744 debug.assert(mem.eql(u8, buf.toSlice(), "Line 1Line 22Line 333"));1020 debug.assertOrPanic(mem.eql(u8, buf.toSlice(), "Line 1Line 22Line 333"));
745}1021}
7461022
747pub fn readLineSlice(slice: []u8) ![]u8 {1023pub fn readLineSlice(slice: []u8) ![]u8 {
...@@ -769,6 +1045,371 @@ test "io.readLineSliceFrom" {...@@ -769,6 +1045,371 @@ test "io.readLineSliceFrom" {
769 );1045 );
770 const stream = &mem_stream.stream;1046 const stream = &mem_stream.stream;
7711047
772 debug.assert(mem.eql(u8, "Line 1", try readLineSliceFrom(stream, buf[0..])));1048 debug.assertOrPanic(mem.eql(u8, "Line 1", try readLineSliceFrom(stream, buf[0..])));
773 debug.assertError(readLineSliceFrom(stream, buf[0..]), error.OutOfMemory);1049 debug.assertError(readLineSliceFrom(stream, buf[0..]), error.OutOfMemory);
774}1050}
1051
1052/// Creates a deserializer that deserializes types from any stream.
1053/// If `is_packed` is true, the data stream is treated as bit-packed,
1054/// otherwise data is expected to be packed to the smallest byte.
1055/// Types may implement a custom deserialization routine with a
1056/// function named `deserialize` in the form of:
1057/// pub fn deserialize(self: *Self, deserializer: var) !void
1058/// which will be called when the deserializer is used to deserialize
1059/// that type. It will pass a pointer to the type instance to deserialize
1060/// into and a pointer to the deserializer struct.
1061pub fn Deserializer(comptime endian: builtin.Endian, is_packed: bool, comptime Error: type) type {
1062 return struct {
1063 const Self = @This();
1064
1065 in_stream: if (is_packed) BitInStream(endian, Stream.Error) else *Stream,
1066
1067 pub const Stream = InStream(Error);
1068
1069 pub fn init(in_stream: *Stream) Self {
1070 return Self{ .in_stream = switch (is_packed) {
1071 true => BitInStream(endian, Stream.Error).init(in_stream),
1072 else => in_stream,
1073 } };
1074 }
1075
1076 pub fn alignToByte(self: *Self) void {
1077 if(!is_packed) return;
1078 self.in_stream.alignToByte();
1079 }
1080
1081 //@BUG: inferred error issue. See: #1386
1082 fn deserializeInt(self: *Self, comptime T: type) (Stream.Error || error{EndOfStream})!T {
1083 comptime assert(trait.is(builtin.TypeId.Int)(T) or trait.is(builtin.TypeId.Float)(T));
1084
1085 const u8_bit_count = 8;
1086 const t_bit_count = comptime meta.bitCount(T);
1087
1088 const U = @IntType(false, t_bit_count);
1089 const Log2U = math.Log2Int(U);
1090 const int_size = @sizeOf(U);
1091
1092 if (is_packed) {
1093 const result = try self.in_stream.readBitsNoEof(U, t_bit_count);
1094 return @bitCast(T, result);
1095 }
1096
1097 var buffer: [int_size]u8 = undefined;
1098 const read_size = try self.in_stream.read(buffer[0..]);
1099 if (read_size < int_size) return error.EndOfStream;
1100
1101 if (int_size == 1) {
1102 if (t_bit_count == 8) return @bitCast(T, buffer[0]);
1103 const PossiblySignedByte = @IntType(T.is_signed, 8);
1104 return @truncate(T, @bitCast(PossiblySignedByte, buffer[0]));
1105 }
1106
1107 var result = U(0);
1108 for (buffer) |byte, i| {
1109 switch (endian) {
1110 builtin.Endian.Big => {
1111 result = (result << u8_bit_count) | byte;
1112 },
1113 builtin.Endian.Little => {
1114 result |= U(byte) << @intCast(Log2U, u8_bit_count * i);
1115 },
1116 }
1117 }
1118
1119 return @bitCast(T, result);
1120 }
1121
1122 //@TODO: Replace this with @unionInit or whatever when it is added
1123 // see: #1315
1124 fn setTag(ptr: var, tag: var) void {
1125 const T = @typeOf(ptr);
1126 comptime assert(trait.isPtrTo(builtin.TypeId.Union)(T));
1127 const U = meta.Child(T);
1128
1129 const info = @typeInfo(U).Union;
1130 if (info.tag_type) |TagType| {
1131 comptime assert(TagType == @typeOf(tag));
1132
1133 var ptr_tag = ptr: {
1134 if (@alignOf(TagType) >= @alignOf(U)) break :ptr @ptrCast(*TagType, ptr);
1135 const offset = comptime max: {
1136 var max_field_size: comptime_int = 0;
1137 for (info.fields) |field_info| {
1138 const field_size = @sizeOf(field_info.field_type);
1139 max_field_size = math.max(max_field_size, field_size);
1140 }
1141 break :max math.max(max_field_size, @alignOf(U));
1142 };
1143 break :ptr @intToPtr(*TagType, @ptrToInt(ptr) + offset);
1144 };
1145 ptr_tag.* = tag;
1146 }
1147 }
1148
1149 /// Deserializes and returns data of the specified type from the stream
1150 pub fn deserialize(self: *Self, comptime T: type) !T {
1151 var value: T = undefined;
1152 try self.deserializeInto(&value);
1153 return value;
1154 }
1155
1156 /// Deserializes data into the type pointed to by `ptr`
1157 pub fn deserializeInto(self: *Self, ptr: var) !void {
1158 const T = @typeOf(ptr);
1159 comptime assert(trait.is(builtin.TypeId.Pointer)(T));
1160
1161 if (comptime trait.isSlice(T) or comptime trait.isPtrTo(builtin.TypeId.Array)(T)) {
1162 for (ptr) |*v|
1163 try self.deserializeInto(v);
1164 return;
1165 }
1166
1167 comptime assert(trait.isSingleItemPtr(T));
1168
1169 const C = comptime meta.Child(T);
1170 const child_type_id = @typeId(C);
1171
1172 //custom deserializer: fn(self: *Self, deserializer: var) !void
1173 if (comptime trait.hasFn("deserialize")(C)) return C.deserialize(ptr, self);
1174
1175 if (comptime trait.isPacked(C) and !is_packed) {
1176 var packed_deserializer = Deserializer(endian, true, Error).init(self.in_stream);
1177 return packed_deserializer.deserializeInto(ptr);
1178 }
1179
1180 switch (child_type_id) {
1181 builtin.TypeId.Void => return,
1182 builtin.TypeId.Bool => ptr.* = (try self.deserializeInt(u1)) > 0,
1183 builtin.TypeId.Float, builtin.TypeId.Int => ptr.* = try self.deserializeInt(C),
1184 builtin.TypeId.Struct => {
1185 const info = @typeInfo(C).Struct;
1186
1187 inline for (info.fields) |*field_info| {
1188 const name = field_info.name;
1189 const FieldType = field_info.field_type;
1190
1191 if (FieldType == void or FieldType == u0) continue;
1192
1193 //it doesn't make any sense to read pointers
1194 if (comptime trait.is(builtin.TypeId.Pointer)(FieldType)) {
1195 @compileError("Will not " ++ "read field " ++ name ++ " of struct " ++
1196 @typeName(C) ++ " because it " ++ "is of pointer-type " ++
1197 @typeName(FieldType) ++ ".");
1198 }
1199
1200 try self.deserializeInto(&@field(ptr, name));
1201 }
1202 },
1203 builtin.TypeId.Union => {
1204 const info = @typeInfo(C).Union;
1205 if (info.tag_type) |TagType| {
1206 //we avoid duplicate iteration over the enum tags
1207 // by getting the int directly and casting it without
1208 // safety. If it is bad, it will be caught anyway.
1209 const TagInt = @TagType(TagType);
1210 const tag = try self.deserializeInt(TagInt);
1211
1212 {
1213 @setRuntimeSafety(false);
1214 //See: #1315
1215 setTag(ptr, @intToEnum(TagType, tag));
1216 }
1217
1218 inline for (info.fields) |field_info| {
1219 if (field_info.enum_field.?.value == tag) {
1220 const name = field_info.name;
1221 const FieldType = field_info.field_type;
1222 @field(ptr, name) = FieldType(undefined);
1223 try self.deserializeInto(&@field(ptr, name));
1224 return;
1225 }
1226 }
1227 //This is reachable if the enum data is bad
1228 return error.InvalidEnumTag;
1229 }
1230 @compileError("Cannot meaningfully deserialize " ++ @typeName(C) ++
1231 " because it is an untagged union Use a custom deserialize().");
1232 },
1233 builtin.TypeId.Optional => {
1234 const OC = comptime meta.Child(C);
1235 const exists = (try self.deserializeInt(u1)) > 0;
1236 if (!exists) {
1237 ptr.* = null;
1238 return;
1239 }
1240
1241 //The way non-pointer optionals are implemented ensures a pointer to them
1242 // will point to the value. The flag is stored at the end of that data.
1243 var val_ptr = @ptrCast(*OC, ptr);
1244 try self.deserializeInto(val_ptr);
1245 //This bit ensures the null flag isn't set. Any actual copying should be
1246 // optimized out... I hope.
1247 ptr.* = val_ptr.*;
1248 },
1249 builtin.TypeId.Enum => {
1250 var value = try self.deserializeInt(@TagType(C));
1251 ptr.* = try meta.intToEnum(C, value);
1252 },
1253 else => {
1254 @compileError("Cannot deserialize " ++ @tagName(child_type_id) ++ " types (unimplemented).");
1255 },
1256 }
1257 }
1258 };
1259}
1260
1261/// Creates a serializer that serializes types to any stream.
1262/// If `is_packed` is true, the data will be bit-packed into the stream.
1263/// Note that the you must call `serializer.flush()` when you are done
1264/// writing bit-packed data in order ensure any unwritten bits are committed.
1265/// If `is_packed` is false, data is packed to the smallest byte. In the case
1266/// of packed structs, the struct will written bit-packed and with the specified
1267/// endianess, after which data will resume being written at the next byte boundary.
1268/// Types may implement a custom serialization routine with a
1269/// function named `serialize` in the form of:
1270/// pub fn serialize(self: Self, serializer: var) !void
1271/// which will be called when the serializer is used to serialize that type. It will
1272/// pass a const pointer to the type instance to be serialized and a pointer
1273/// to the serializer struct.
1274pub fn Serializer(comptime endian: builtin.Endian, comptime is_packed: bool, comptime Error: type) type {
1275 return struct {
1276 const Self = @This();
1277
1278 out_stream: if (is_packed) BitOutStream(endian, Stream.Error) else *Stream,
1279
1280 pub const Stream = OutStream(Error);
1281
1282 pub fn init(out_stream: *Stream) Self {
1283 return Self{ .out_stream = switch (is_packed) {
1284 true => BitOutStream(endian, Stream.Error).init(out_stream),
1285 else => out_stream,
1286 } };
1287 }
1288
1289 /// Flushes any unwritten bits to the stream
1290 pub fn flush(self: *Self) Stream.Error!void {
1291 if (is_packed) return self.out_stream.flushBits();
1292 }
1293
1294 fn serializeInt(self: *Self, value: var) !void {
1295 const T = @typeOf(value);
1296 comptime assert(trait.is(builtin.TypeId.Int)(T) or trait.is(builtin.TypeId.Float)(T));
1297
1298 const t_bit_count = comptime meta.bitCount(T);
1299 const u8_bit_count = comptime meta.bitCount(u8);
1300
1301 const U = @IntType(false, t_bit_count);
1302 const Log2U = math.Log2Int(U);
1303 const int_size = @sizeOf(U);
1304
1305 const u_value = @bitCast(U, value);
1306
1307 if (is_packed) return self.out_stream.writeBits(u_value, t_bit_count);
1308
1309 var buffer: [int_size]u8 = undefined;
1310 if (int_size == 1) buffer[0] = u_value;
1311
1312 for (buffer) |*byte, i| {
1313 const idx = switch (endian) {
1314 builtin.Endian.Big => int_size - i - 1,
1315 builtin.Endian.Little => i,
1316 };
1317 const shift = @intCast(Log2U, idx * u8_bit_count);
1318 const v = u_value >> shift;
1319 byte.* = if (t_bit_count < u8_bit_count) v else @truncate(u8, v);
1320 }
1321
1322 try self.out_stream.write(buffer);
1323 }
1324
1325 /// Serializes the passed value into the stream
1326 pub fn serialize(self: *Self, value: var) !void {
1327 const T = comptime @typeOf(value);
1328
1329 if (comptime trait.isIndexable(T)) {
1330 for (value) |v|
1331 try self.serialize(v);
1332 return;
1333 }
1334
1335 //custom serializer: fn(self: Self, serializer: var) !void
1336 if (comptime trait.hasFn("serialize")(T)) return T.serialize(value, self);
1337
1338 if (comptime trait.isPacked(T) and !is_packed) {
1339 var packed_serializer = Serializer(endian, true, Error).init(self.out_stream);
1340 try packed_serializer.serialize(value);
1341 try packed_serializer.flush();
1342 return;
1343 }
1344
1345 switch (@typeId(T)) {
1346 builtin.TypeId.Void => return,
1347 builtin.TypeId.Bool => try self.serializeInt(u1(@boolToInt(value))),
1348 builtin.TypeId.Float, builtin.TypeId.Int => try self.serializeInt(value),
1349 builtin.TypeId.Struct => {
1350 const info = @typeInfo(T);
1351
1352 inline for (info.Struct.fields) |*field_info| {
1353 const name = field_info.name;
1354 const FieldType = field_info.field_type;
1355
1356 if (FieldType == void or FieldType == u0) continue;
1357
1358 //It doesn't make sense to write pointers
1359 if (comptime trait.is(builtin.TypeId.Pointer)(FieldType)) {
1360 @compileError("Will not " ++ "serialize field " ++ name ++
1361 " of struct " ++ @typeName(T) ++ " because it " ++
1362 "is of pointer-type " ++ @typeName(FieldType) ++ ".");
1363 }
1364 try self.serialize(@field(value, name));
1365 }
1366 },
1367 builtin.TypeId.Union => {
1368 const info = @typeInfo(T).Union;
1369 if (info.tag_type) |TagType| {
1370 const active_tag = meta.activeTag(value);
1371 try self.serialize(active_tag);
1372 //This inline loop is necessary because active_tag is a runtime
1373 // value, but @field requires a comptime value. Our alternative
1374 // is to check each field for a match
1375 inline for (info.fields) |field_info| {
1376 if (field_info.enum_field.?.value == @enumToInt(active_tag)) {
1377 const name = field_info.name;
1378 const FieldType = field_info.field_type;
1379 try self.serialize(@field(value, name));
1380 return;
1381 }
1382 }
1383 unreachable;
1384 }
1385 @compileError("Cannot meaningfully serialize " ++ @typeName(T) ++
1386 " because it is an untagged union Use a custom serialize().");
1387 },
1388 builtin.TypeId.Optional => {
1389 if (value == null) {
1390 try self.serializeInt(u1(@boolToInt(false)));
1391 return;
1392 }
1393 try self.serializeInt(u1(@boolToInt(true)));
1394
1395 const OC = comptime meta.Child(T);
1396
1397 //The way non-pointer optionals are implemented ensures a pointer to them
1398 // will point to the value. The flag is stored at the end of that data.
1399 var val_ptr = @ptrCast(*const OC, &value);
1400 try self.serialize(val_ptr.*);
1401 },
1402 builtin.TypeId.Enum => {
1403 try self.serializeInt(@enumToInt(value));
1404 },
1405 else => @compileError("Cannot serialize " ++ @tagName(@typeId(T)) ++ " types (unimplemented)."),
1406 }
1407 }
1408 };
1409}
1410
1411test "import io tests" {
1412 comptime {
1413 _ = @import("io_test.zig");
1414 }
1415}
std/io_test.zig+437
...@@ -1,5 +1,7 @@...@@ -1,5 +1,7 @@
1const std = @import("index.zig");1const std = @import("index.zig");
2const io = std.io;2const io = std.io;
3const meta = std.meta;
4const trait = std.trait;
3const DefaultPrng = std.rand.DefaultPrng;5const DefaultPrng = std.rand.DefaultPrng;
4const assert = std.debug.assert;6const assert = std.debug.assert;
5const assertError = std.debug.assertError;7const assertError = std.debug.assertError;
...@@ -132,3 +134,438 @@ test "SliceOutStream" {...@@ -132,3 +134,438 @@ test "SliceOutStream" {
132 assertError(ss.stream.write("Hello world!"), error.OutOfSpace);134 assertError(ss.stream.write("Hello world!"), error.OutOfSpace);
133 assert(mem.eql(u8, ss.getWritten(), "Hello worl"));135 assert(mem.eql(u8, ss.getWritten(), "Hello worl"));
134}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 assert(1 == try bit_stream_be.readBits(u2, 1, &out_bits));
149 assert(out_bits == 1);
150 assert(2 == try bit_stream_be.readBits(u5, 2, &out_bits));
151 assert(out_bits == 2);
152 assert(3 == try bit_stream_be.readBits(u128, 3, &out_bits));
153 assert(out_bits == 3);
154 assert(4 == try bit_stream_be.readBits(u8, 4, &out_bits));
155 assert(out_bits == 4);
156 assert(5 == try bit_stream_be.readBits(u9, 5, &out_bits));
157 assert(out_bits == 5);
158 assert(1 == try bit_stream_be.readBits(u1, 1, &out_bits));
159 assert(out_bits == 1);
160
161 mem_in_be.pos = 0;
162 bit_stream_be.bit_count = 0;
163 assert(0b110011010000101 == try bit_stream_be.readBits(u15, 15, &out_bits));
164 assert(out_bits == 15);
165
166 mem_in_be.pos = 0;
167 bit_stream_be.bit_count = 0;
168 assert(0b1100110100001011 == try bit_stream_be.readBits(u16, 16, &out_bits));
169 assert(out_bits == 16);
170
171 _ = try bit_stream_be.readBits(u0, 0, &out_bits);
172
173 assert(0 == try bit_stream_be.readBits(u1, 1, &out_bits));
174 assert(out_bits == 0);
175 assertError(bit_stream_be.readBitsNoEof(u1, 1), error.EndOfStream);
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 assert(1 == try bit_stream_le.readBits(u2, 1, &out_bits));
181 assert(out_bits == 1);
182 assert(2 == try bit_stream_le.readBits(u5, 2, &out_bits));
183 assert(out_bits == 2);
184 assert(3 == try bit_stream_le.readBits(u128, 3, &out_bits));
185 assert(out_bits == 3);
186 assert(4 == try bit_stream_le.readBits(u8, 4, &out_bits));
187 assert(out_bits == 4);
188 assert(5 == try bit_stream_le.readBits(u9, 5, &out_bits));
189 assert(out_bits == 5);
190 assert(1 == try bit_stream_le.readBits(u1, 1, &out_bits));
191 assert(out_bits == 1);
192
193 mem_in_le.pos = 0;
194 bit_stream_le.bit_count = 0;
195 assert(0b001010100011101 == try bit_stream_le.readBits(u15, 15, &out_bits));
196 assert(out_bits == 15);
197
198 mem_in_le.pos = 0;
199 bit_stream_le.bit_count = 0;
200 assert(0b1001010100011101 == try bit_stream_le.readBits(u16, 16, &out_bits));
201 assert(out_bits == 16);
202
203 _ = try bit_stream_le.readBits(u0, 0, &out_bits);
204
205 assert(0 == try bit_stream_le.readBits(u1, 1, &out_bits));
206 assert(out_bits == 0);
207 assertError(bit_stream_le.readBitsNoEof(u1, 1), error.EndOfStream);
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 assert(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 assert(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 assert(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 assert(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 assert(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 assert(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 assert(1 == try bit_stream.readBits(u2, 1, &out_bits));
294 assert(out_bits == 1);
295 assert(2 == try bit_stream.readBits(u5, 2, &out_bits));
296 assert(out_bits == 2);
297 assert(3 == try bit_stream.readBits(u128, 3, &out_bits));
298 assert(out_bits == 3);
299 assert(4 == try bit_stream.readBits(u8, 4, &out_bits));
300 assert(out_bits == 4);
301 assert(5 == try bit_stream.readBits(u9, 5, &out_bits));
302 assert(out_bits == 5);
303 assert(1 == try bit_stream.readBits(u1, 1, &out_bits));
304 assert(out_bits == 1);
305
306 assertError(bit_stream.readBitsNoEof(u1, 1), error.EndOfStream);
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 assert(x == U(i));
349 if (i != 0) assert(y == S(-1)) else assert(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 assert(in.pos == if (is_packed) total_packed_bytes else total_bytes);
360}
361
362test "Serializer/Deserializer Int" {
363 try testIntSerializerDeserializer(builtin.Endian.Big, false);
364 try testIntSerializerDeserializer(builtin.Endian.Little, false);
365 try testIntSerializerDeserializer(builtin.Endian.Big, true);
366 try testIntSerializerDeserializer(builtin.Endian.Little, true);
367}
368
369fn testIntSerializerDeserializerInfNaN(comptime endian: builtin.Endian,
370 comptime is_packed: bool) !void
371{
372 const mem_size = (16*2 + 32*2 + 64*2 + 128*2) / comptime meta.bitCount(u8);
373 var data_mem: [mem_size]u8 = undefined;
374
375 var out = io.SliceOutStream.init(data_mem[0..]);
376 const OutError = io.SliceOutStream.Error;
377 var out_stream = &out.stream;
378 var serializer = io.Serializer(endian, is_packed, OutError).init(out_stream);
379
380 var in = io.SliceInStream.init(data_mem[0..]);
381 const InError = io.SliceInStream.Error;
382 var in_stream = &in.stream;
383 var deserializer = io.Deserializer(endian, is_packed, InError).init(in_stream);
384
385 //@TODO: isInf/isNan not currently implemented for f128.
386 try serializer.serialize(std.math.nan(f16));
387 try serializer.serialize(std.math.inf(f16));
388 try serializer.serialize(std.math.nan(f32));
389 try serializer.serialize(std.math.inf(f32));
390 try serializer.serialize(std.math.nan(f64));
391 try serializer.serialize(std.math.inf(f64));
392 //try serializer.serialize(std.math.nan(f128));
393 //try serializer.serialize(std.math.inf(f128));
394 const nan_check_f16 = try deserializer.deserialize(f16);
395 const inf_check_f16 = try deserializer.deserialize(f16);
396 const nan_check_f32 = try deserializer.deserialize(f32);
397 const inf_check_f32 = try deserializer.deserialize(f32);
398 const nan_check_f64 = try deserializer.deserialize(f64);
399 const inf_check_f64 = try deserializer.deserialize(f64);
400 //const nan_check_f128 = try deserializer.deserialize(f128);
401 //const inf_check_f128 = try deserializer.deserialize(f128);
402 assert(std.math.isNan(nan_check_f16));
403 assert(std.math.isInf(inf_check_f16));
404 assert(std.math.isNan(nan_check_f32));
405 assert(std.math.isInf(inf_check_f32));
406 assert(std.math.isNan(nan_check_f64));
407 assert(std.math.isInf(inf_check_f64));
408 //assert(std.math.isNan(nan_check_f128));
409 //assert(std.math.isInf(inf_check_f128));
410}
411
412test "Serializer/Deserializer Int: Inf/NaN" {
413 try testIntSerializerDeserializerInfNaN(builtin.Endian.Big, false);
414 try testIntSerializerDeserializerInfNaN(builtin.Endian.Little, false);
415 try testIntSerializerDeserializerInfNaN(builtin.Endian.Big, true);
416 try testIntSerializerDeserializerInfNaN(builtin.Endian.Little, true);
417}
418
419fn testAlternateSerializer(self: var, serializer: var) !void {
420 try serializer.serialize(self.f_f16);
421}
422
423fn testSerializerDeserializer(comptime endian: builtin.Endian, comptime is_packed: bool) !void {
424 const ColorType = enum(u4) {
425 RGB8 = 1,
426 RA16 = 2,
427 R32 = 3,
428 };
429
430 const TagAlign = union(enum(u32)) {
431 A: u8,
432 B: u8,
433 C: u8,
434 };
435
436 const Color = union(ColorType) {
437 RGB8: struct {
438 r: u8,
439 g: u8,
440 b: u8,
441 a: u8,
442 },
443 RA16: struct {
444 r: u16,
445 a: u16,
446 },
447 R32: u32,
448 };
449
450 const PackedStruct = packed struct {
451 f_i3: i3,
452 f_u2: u2,
453 };
454
455
456
457 //to test custom serialization
458 const Custom = struct {
459 f_f16: f16,
460 f_unused_u32: u32,
461
462 pub fn deserialize(self: *@This(), deserializer: var) !void {
463 try deserializer.deserializeInto(&self.f_f16);
464 self.f_unused_u32 = 47;
465 }
466
467 pub const serialize = testAlternateSerializer;
468 };
469
470 const MyStruct = struct {
471 f_i3: i3,
472 f_u8: u8,
473 f_tag_align: TagAlign,
474 f_u24: u24,
475 f_i19: i19,
476 f_void: void,
477 f_f32: f32,
478 f_f128: f128,
479 f_packed_0: PackedStruct,
480 f_i7arr: [10]i7,
481 f_of64n: ?f64,
482 f_of64v: ?f64,
483 f_color_type: ColorType,
484 f_packed_1: PackedStruct,
485 f_custom: Custom,
486 f_color: Color,
487 };
488
489 const my_inst = MyStruct{
490 .f_i3 = -1,
491 .f_u8 = 8,
492 .f_tag_align = TagAlign{ .B = 148 },
493 .f_u24 = 24,
494 .f_i19 = 19,
495 .f_void = {},
496 .f_f32 = 32.32,
497 .f_f128 = 128.128,
498 .f_packed_0 = PackedStruct{ .f_i3 = -1, .f_u2 = 2 },
499 .f_i7arr = [10]i7{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
500 .f_of64n = null,
501 .f_of64v = 64.64,
502 .f_color_type = ColorType.R32,
503 .f_packed_1 = PackedStruct{ .f_i3 = 1, .f_u2 = 1 },
504 .f_custom = Custom{ .f_f16 = 38.63, .f_unused_u32 = 47 },
505 .f_color = Color{ .R32 = 123822 },
506 };
507
508 var data_mem: [@sizeOf(MyStruct)]u8 = undefined;
509 var out = io.SliceOutStream.init(data_mem[0..]);
510 const OutError = io.SliceOutStream.Error;
511 var out_stream = &out.stream;
512 var serializer = io.Serializer(endian, is_packed, OutError).init(out_stream);
513
514 var in = io.SliceInStream.init(data_mem[0..]);
515 const InError = io.SliceInStream.Error;
516 var in_stream = &in.stream;
517 var deserializer = io.Deserializer(endian, is_packed, InError).init(in_stream);
518
519 try serializer.serialize(my_inst);
520
521 const my_copy = try deserializer.deserialize(MyStruct);
522 assert(meta.eql(my_copy, my_inst));
523}
524
525test "Serializer/Deserializer generic" {
526 try testSerializerDeserializer(builtin.Endian.Big, false);
527 try testSerializerDeserializer(builtin.Endian.Little, false);
528 try testSerializerDeserializer(builtin.Endian.Big, true);
529 try testSerializerDeserializer(builtin.Endian.Little, true);
530}
531
532fn testBadData(comptime endian: builtin.Endian, comptime is_packed: bool) !void {
533 const E = enum(u14) {
534 One = 1,
535 Two = 2,
536 };
537
538 const A = struct {
539 e: E,
540 };
541
542 const C = union(E) {
543 One: u14,
544 Two: f16,
545 };
546
547 var data_mem: [4]u8 = undefined;
548 var out = io.SliceOutStream.init(data_mem[0..]);
549 const OutError = io.SliceOutStream.Error;
550 var out_stream = &out.stream;
551 var serializer = io.Serializer(endian, is_packed, OutError).init(out_stream);
552
553 var in = io.SliceInStream.init(data_mem[0..]);
554 const InError = io.SliceInStream.Error;
555 var in_stream = &in.stream;
556 var deserializer = io.Deserializer(endian, is_packed, InError).init(in_stream);
557
558 try serializer.serialize(u14(3));
559 assertError(deserializer.deserialize(A), error.InvalidEnumTag);
560 out.pos = 0;
561 try serializer.serialize(u14(3));
562 try serializer.serialize(u14(88));
563 assertError(deserializer.deserialize(C), error.InvalidEnumTag);
564}
565
566test "Deserializer bad data" {
567 try testBadData(builtin.Endian.Big, false);
568 try testBadData(builtin.Endian.Little, false);
569 try testBadData(builtin.Endian.Big, true);
570 try testBadData(builtin.Endian.Little, true);
571}
\ No newline at end of file
std/linked_list.zig+1-1
...@@ -190,7 +190,7 @@ pub fn LinkedList(comptime T: type) type {...@@ -190,7 +190,7 @@ pub fn LinkedList(comptime T: type) type {
190 /// Returns:190 /// Returns:
191 /// A pointer to the new node.191 /// A pointer to the new node.
192 pub fn allocateNode(list: *Self, allocator: *Allocator) !*Node {192 pub fn allocateNode(list: *Self, allocator: *Allocator) !*Node {
193 return allocator.create(Node(undefined));193 return allocator.create(Node);
194 }194 }
195195
196 /// Deallocate a node.196 /// Deallocate a node.
std/mem.zig+132-25
...@@ -36,20 +36,9 @@ pub const Allocator = struct {...@@ -36,20 +36,9 @@ pub const Allocator = struct {
36 /// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn`36 /// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn`
37 freeFn: fn (self: *Allocator, old_mem: []u8) void,37 freeFn: fn (self: *Allocator, old_mem: []u8) void,
3838
39 /// Call `destroy` with the result
40 /// TODO this is deprecated. use createOne instead
41 pub fn create(self: *Allocator, init: var) Error!*@typeOf(init) {
42 const T = @typeOf(init);
43 if (@sizeOf(T) == 0) return &(T{});
44 const slice = try self.alloc(T, 1);
45 const ptr = &slice[0];
46 ptr.* = init;
47 return ptr;
48 }
49
50 /// Call `destroy` with the result.39 /// Call `destroy` with the result.
51 /// Returns undefined memory.40 /// Returns undefined memory.
52 pub fn createOne(self: *Allocator, comptime T: type) Error!*T {41 pub fn create(self: *Allocator, comptime T: type) Error!*T {
53 if (@sizeOf(T) == 0) return &(T{});42 if (@sizeOf(T) == 0) return &(T{});
54 const slice = try self.alloc(T, 1);43 const slice = try self.alloc(T, 1);
55 return &slice[0];44 return &slice[0];
...@@ -700,23 +689,114 @@ pub fn eql_slice_u8(a: []const u8, b: []const u8) bool {...@@ -700,23 +689,114 @@ pub fn eql_slice_u8(a: []const u8, b: []const u8) bool {
700}689}
701690
702/// Returns an iterator that iterates over the slices of `buffer` that are not691/// Returns an iterator that iterates over the slices of `buffer` that are not
703/// any of the bytes in `split_bytes`.692/// any of the bytes in `delimiter_bytes`.
704/// split(" abc def ghi ", " ")693/// tokenize(" abc def ghi ", " ")
705/// Will return slices for "abc", "def", "ghi", null, in that order.694/// Will return slices for "abc", "def", "ghi", null, in that order.
706pub fn split(buffer: []const u8, split_bytes: []const u8) SplitIterator {695/// If `buffer` is empty, the iterator will return null.
696/// If `delimiter_bytes` does not exist in buffer,
697/// the iterator will return `buffer`, null, in that order.
698/// See also the related function `separate`.
699pub fn tokenize(buffer: []const u8, delimiter_bytes: []const u8) TokenIterator {
700 return TokenIterator{
701 .index = 0,
702 .buffer = buffer,
703 .delimiter_bytes = delimiter_bytes,
704 };
705}
706
707test "mem.tokenize" {
708 var it = tokenize(" abc def ghi ", " ");
709 assert(eql(u8, it.next().?, "abc"));
710 assert(eql(u8, it.next().?, "def"));
711 assert(eql(u8, it.next().?, "ghi"));
712 assert(it.next() == null);
713
714 it = tokenize("..\\bob", "\\");
715 assert(eql(u8, it.next().?, ".."));
716 assert(eql(u8, "..", "..\\bob"[0..it.index]));
717 assert(eql(u8, it.next().?, "bob"));
718 assert(it.next() == null);
719
720 it = tokenize("//a/b", "/");
721 assert(eql(u8, it.next().?, "a"));
722 assert(eql(u8, it.next().?, "b"));
723 assert(eql(u8, "//a/b", "//a/b"[0..it.index]));
724 assert(it.next() == null);
725
726 it = tokenize("|", "|");
727 assert(it.next() == null);
728
729 it = tokenize("", "|");
730 assert(it.next() == null);
731
732 it = tokenize("hello", "");
733 assert(eql(u8, it.next().?, "hello"));
734 assert(it.next() == null);
735
736 it = tokenize("hello", " ");
737 assert(eql(u8, it.next().?, "hello"));
738 assert(it.next() == null);
739}
740
741test "mem.tokenize (multibyte)" {
742 var it = tokenize("a|b,c/d e", " /,|");
743 assert(eql(u8, it.next().?, "a"));
744 assert(eql(u8, it.next().?, "b"));
745 assert(eql(u8, it.next().?, "c"));
746 assert(eql(u8, it.next().?, "d"));
747 assert(eql(u8, it.next().?, "e"));
748 assert(it.next() == null);
749}
750
751/// Returns an iterator that iterates over the slices of `buffer` that
752/// are separated by bytes in `delimiter`.
753/// separate("abc|def||ghi", "|")
754/// will return slices for "abc", "def", "", "ghi", null, in that order.
755/// If `delimiter` does not exist in buffer,
756/// the iterator will return `buffer`, null, in that order.
757/// The delimiter length must not be zero.
758/// See also the related function `tokenize`.
759/// It is planned to rename this function to `split` before 1.0.0, like this:
760/// pub fn split(buffer: []const u8, delimiter: []const u8) SplitIterator {
761pub fn separate(buffer: []const u8, delimiter: []const u8) SplitIterator {
762 assert(delimiter.len != 0);
707 return SplitIterator{763 return SplitIterator{
708 .index = 0,764 .index = 0,
709 .buffer = buffer,765 .buffer = buffer,
710 .split_bytes = split_bytes,766 .delimiter = delimiter,
711 };767 };
712}768}
713769
714test "mem.split" {770test "mem.separate" {
715 var it = split(" abc def ghi ", " ");771 var it = separate("abc|def||ghi", "|");
716 assert(eql(u8, it.next().?, "abc"));772 assert(eql(u8, it.next().?, "abc"));
717 assert(eql(u8, it.next().?, "def"));773 assert(eql(u8, it.next().?, "def"));
774 assert(eql(u8, it.next().?, ""));
718 assert(eql(u8, it.next().?, "ghi"));775 assert(eql(u8, it.next().?, "ghi"));
719 assert(it.next() == null);776 assert(it.next() == null);
777
778 it = separate("", "|");
779 assert(eql(u8, it.next().?, ""));
780 assert(it.next() == null);
781
782 it = separate("|", "|");
783 assert(eql(u8, it.next().?, ""));
784 assert(eql(u8, it.next().?, ""));
785 assert(it.next() == null);
786
787 it = separate("hello", " ");
788 assert(eql(u8, it.next().?, "hello"));
789 assert(it.next() == null);
790}
791
792test "mem.separate (multibyte)" {
793 var it = separate("a, b ,, c, d, e", ", ");
794 assert(eql(u8, it.next().?, "a"));
795 assert(eql(u8, it.next().?, "b ,"));
796 assert(eql(u8, it.next().?, "c"));
797 assert(eql(u8, it.next().?, "d"));
798 assert(eql(u8, it.next().?, "e"));
799 assert(it.next() == null);
720}800}
721801
722pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool {802pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool {
...@@ -737,12 +817,13 @@ test "mem.endsWith" {...@@ -737,12 +817,13 @@ test "mem.endsWith" {
737 assert(!endsWith(u8, "Bob", "Bo"));817 assert(!endsWith(u8, "Bob", "Bo"));
738}818}
739819
740pub const SplitIterator = struct {820pub const TokenIterator = struct {
741 buffer: []const u8,821 buffer: []const u8,
742 split_bytes: []const u8,822 delimiter_bytes: []const u8,
743 index: usize,823 index: usize,
744824
745 pub fn next(self: *SplitIterator) ?[]const u8 {825 /// Returns a slice of the next token, or null if tokenization is complete.
826 pub fn next(self: *TokenIterator) ?[]const u8 {
746 // move to beginning of token827 // move to beginning of token
747 while (self.index < self.buffer.len and self.isSplitByte(self.buffer[self.index])) : (self.index += 1) {}828 while (self.index < self.buffer.len and self.isSplitByte(self.buffer[self.index])) : (self.index += 1) {}
748 const start = self.index;829 const start = self.index;
...@@ -758,16 +839,16 @@ pub const SplitIterator = struct {...@@ -758,16 +839,16 @@ pub const SplitIterator = struct {
758 }839 }
759840
760 /// Returns a slice of the remaining bytes. Does not affect iterator state.841 /// Returns a slice of the remaining bytes. Does not affect iterator state.
761 pub fn rest(self: *const SplitIterator) []const u8 {842 pub fn rest(self: TokenIterator) []const u8 {
762 // move to beginning of token843 // move to beginning of token
763 var index: usize = self.index;844 var index: usize = self.index;
764 while (index < self.buffer.len and self.isSplitByte(self.buffer[index])) : (index += 1) {}845 while (index < self.buffer.len and self.isSplitByte(self.buffer[index])) : (index += 1) {}
765 return self.buffer[index..];846 return self.buffer[index..];
766 }847 }
767848
768 fn isSplitByte(self: *const SplitIterator, byte: u8) bool {849 fn isSplitByte(self: TokenIterator, byte: u8) bool {
769 for (self.split_bytes) |split_byte| {850 for (self.delimiter_bytes) |delimiter_byte| {
770 if (byte == split_byte) {851 if (byte == delimiter_byte) {
771 return true;852 return true;
772 }853 }
773 }854 }
...@@ -775,6 +856,32 @@ pub const SplitIterator = struct {...@@ -775,6 +856,32 @@ pub const SplitIterator = struct {
775 }856 }
776};857};
777858
859pub const SplitIterator = struct {
860 buffer: []const u8,
861 index: ?usize,
862 delimiter: []const u8,
863
864 /// Returns a slice of the next field, or null if splitting is complete.
865 pub fn next(self: *SplitIterator) ?[]const u8 {
866 const start = self.index orelse return null;
867 const end = if (indexOfPos(u8, self.buffer, start, self.delimiter)) |delim_start| blk: {
868 self.index = delim_start + self.delimiter.len;
869 break :blk delim_start;
870 } else blk: {
871 self.index = null;
872 break :blk self.buffer.len;
873 };
874 return self.buffer[start..end];
875 }
876
877 /// Returns a slice of the remaining bytes. Does not affect iterator state.
878 pub fn rest(self: SplitIterator) []const u8 {
879 const end = self.buffer.len;
880 const start = self.index orelse end;
881 return self.buffer[start..end];
882 }
883};
884
778/// Naively combines a series of strings with a separator.885/// Naively combines a series of strings with a separator.
779/// Allocates memory for the result, which must be freed by the caller.886/// Allocates memory for the result, which must be freed by the caller.
780pub fn join(allocator: *Allocator, sep: u8, strings: ...) ![]u8 {887pub fn join(allocator: *Allocator, sep: u8, strings: ...) ![]u8 {
std/meta/index.zig+35-3
...@@ -95,7 +95,7 @@ test "std.meta.stringToEnum" {...@@ -95,7 +95,7 @@ test "std.meta.stringToEnum" {
95 debug.assert(null == stringToEnum(E1, "C"));95 debug.assert(null == stringToEnum(E1, "C"));
96}96}
9797
98pub fn bitCount(comptime T: type) u32 {98pub fn bitCount(comptime T: type) comptime_int {
99 return switch (@typeInfo(T)) {99 return switch (@typeInfo(T)) {
100 TypeId.Int => |info| info.bits,100 TypeId.Int => |info| info.bits,
101 TypeId.Float => |info| info.bits,101 TypeId.Float => |info| info.bits,
...@@ -108,7 +108,7 @@ test "std.meta.bitCount" {...@@ -108,7 +108,7 @@ test "std.meta.bitCount" {
108 debug.assert(bitCount(f32) == 32);108 debug.assert(bitCount(f32) == 32);
109}109}
110110
111pub fn alignment(comptime T: type) u29 {111pub fn alignment(comptime T: type) comptime_int {
112 //@alignOf works on non-pointer types112 //@alignOf works on non-pointer types
113 const P = if (comptime trait.is(TypeId.Pointer)(T)) T else *T;113 const P = if (comptime trait.is(TypeId.Pointer)(T)) T else *T;
114 return @typeInfo(P).Pointer.alignment;114 return @typeInfo(P).Pointer.alignment;
...@@ -386,6 +386,33 @@ test "std.meta.activeTag" {...@@ -386,6 +386,33 @@ test "std.meta.activeTag" {
386 debug.assert(activeTag(u) == UE.Float);386 debug.assert(activeTag(u) == UE.Float);
387}387}
388388
389///Given a tagged union type, and an enum, return the type of the union
390/// field corresponding to the enum tag.
391pub fn TagPayloadType(comptime U: type, tag: var) type {
392 const Tag = @typeOf(tag);
393 debug.assert(trait.is(builtin.TypeId.Union)(U));
394 debug.assert(trait.is(builtin.TypeId.Enum)(Tag));
395
396 const info = @typeInfo(U).Union;
397
398 inline for (info.fields) |field_info| {
399 if (field_info.enum_field.?.value == @enumToInt(tag)) return field_info.field_type;
400 }
401 unreachable;
402}
403
404test "std.meta.TagPayloadType" {
405 const Event = union(enum) {
406 Moved: struct {
407 from: i32,
408 to: i32,
409 },
410 };
411 const MovedEvent = TagPayloadType(Event, Event.Moved);
412 var e: Event = undefined;
413 debug.assert(MovedEvent == @typeOf(e.Moved));
414}
415
389///Compares two of any type for equality. Containers are compared on a field-by-field basis,416///Compares two of any type for equality. Containers are compared on a field-by-field basis,
390/// where possible. Pointers are not followed.417/// where possible. Pointers are not followed.
391pub fn eql(a: var, b: @typeOf(a)) bool {418pub fn eql(a: var, b: @typeOf(a)) bool {
...@@ -439,6 +466,11 @@ pub fn eql(a: var, b: @typeOf(a)) bool {...@@ -439,6 +466,11 @@ pub fn eql(a: var, b: @typeOf(a)) bool {
439 builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len,466 builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len,
440 }467 }
441 },468 },
469 builtin.TypeId.Optional => {
470 if(a == null and b == null) return true;
471 if(a == null or b == null) return false;
472 return eql(a.?, b.?);
473 },
442 else => return a == b,474 else => return a == b,
443 }475 }
444}476}
...@@ -452,7 +484,7 @@ test "std.meta.eql" {...@@ -452,7 +484,7 @@ test "std.meta.eql" {
452484
453 const U = union(enum) {485 const U = union(enum) {
454 s: S,486 s: S,
455 f: f32,487 f: ?f32,
456 };488 };
457489
458 const s_1 = S{490 const s_1 = S{
std/meta/trait.zig+31
...@@ -231,6 +231,37 @@ test "std.meta.trait.isPacked" {...@@ -231,6 +231,37 @@ test "std.meta.trait.isPacked" {
231 debug.assert(!isPacked(u8));231 debug.assert(!isPacked(u8));
232}232}
233233
234///
235pub fn isUnsignedInt(comptime T: type) bool {
236 return switch (@typeId(T)) {
237 builtin.TypeId.Int => !@typeInfo(T).Int.is_signed,
238 else => false,
239 };
240}
241
242test "isUnsignedInt" {
243 debug.assert(isUnsignedInt(u32) == true);
244 debug.assert(isUnsignedInt(comptime_int) == false);
245 debug.assert(isUnsignedInt(i64) == false);
246 debug.assert(isUnsignedInt(f64) == false);
247}
248
249///
250pub fn isSignedInt(comptime T: type) bool {
251 return switch (@typeId(T)) {
252 builtin.TypeId.ComptimeInt => true,
253 builtin.TypeId.Int => @typeInfo(T).Int.is_signed,
254 else => false,
255 };
256}
257
258test "isSignedInt" {
259 debug.assert(isSignedInt(u32) == false);
260 debug.assert(isSignedInt(comptime_int) == true);
261 debug.assert(isSignedInt(i64) == true);
262 debug.assert(isSignedInt(f64) == false);
263}
264
234///265///
235pub fn isSingleItemPtr(comptime T: type) bool {266pub fn isSingleItemPtr(comptime T: type) bool {
236 if (comptime is(builtin.TypeId.Pointer)(T)) {267 if (comptime is(builtin.TypeId.Pointer)(T)) {
std/mutex.zig+104-47
...@@ -5,74 +5,124 @@ const AtomicRmwOp = builtin.AtomicRmwOp;...@@ -5,74 +5,124 @@ const AtomicRmwOp = builtin.AtomicRmwOp;
5const assert = std.debug.assert;5const assert = std.debug.assert;
6const SpinLock = std.SpinLock;6const SpinLock = std.SpinLock;
7const linux = std.os.linux;7const linux = std.os.linux;
8const windows = std.os.windows;
89
9/// Lock may be held only once. If the same thread10/// Lock may be held only once. If the same thread
10/// tries to acquire the same mutex twice, it deadlocks.11/// tries to acquire the same mutex twice, it deadlocks.
12/// This type must be initialized at runtime, and then deinitialized when no
13/// longer needed, to free resources.
14/// If you need static initialization, use std.StaticallyInitializedMutex.
11/// The Linux implementation is based on mutex3 from15/// The Linux implementation is based on mutex3 from
12/// https://www.akkadia.org/drepper/futex.pdf16/// https://www.akkadia.org/drepper/futex.pdf
13pub const Mutex = struct {17/// When an application is built in single threaded release mode, all the functions are
14 /// 0: unlocked18/// no-ops. In single threaded debug mode, there is deadlock detection.
15 /// 1: locked, no waiters19pub const Mutex = if (builtin.single_threaded)
16 /// 2: locked, one or more waiters20 struct {
17 linux_lock: @typeOf(linux_lock_init),21 lock: @typeOf(lock_init),
1822
19 /// TODO better implementation than spin lock23 const lock_init = if (std.debug.runtime_safety) false else {};
20 spin_lock: @typeOf(spin_lock_init),
2124
22 const linux_lock_init = if (builtin.os == builtin.Os.linux) i32(0) else {};25 pub const Held = struct {
23 const spin_lock_init = if (builtin.os != builtin.Os.linux) SpinLock.init() else {};26 mutex: *Mutex,
2427
25 pub const Held = struct {28 pub fn release(self: Held) void {
26 mutex: *Mutex,29 if (std.debug.runtime_safety) {
30 self.mutex.lock = false;
31 }
32 }
33 };
34 pub fn init() Mutex {
35 return Mutex{ .lock = lock_init };
36 }
37 pub fn deinit(self: *Mutex) void {}
2738
28 pub fn release(self: Held) void {39 pub fn acquire(self: *Mutex) Held {
29 if (builtin.os == builtin.Os.linux) {40 if (std.debug.runtime_safety and self.lock) {
30 const c = @atomicRmw(i32, &self.mutex.linux_lock, AtomicRmwOp.Sub, 1, AtomicOrder.Release);41 @panic("deadlock detected");
42 }
43 return Held{ .mutex = self };
44 }
45 }
46else switch (builtin.os) {
47 builtin.Os.linux => struct {
48 /// 0: unlocked
49 /// 1: locked, no waiters
50 /// 2: locked, one or more waiters
51 lock: i32,
52
53 pub const Held = struct {
54 mutex: *Mutex,
55
56 pub fn release(self: Held) void {
57 const c = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Sub, 1, AtomicOrder.Release);
31 if (c != 1) {58 if (c != 1) {
32 _ = @atomicRmw(i32, &self.mutex.linux_lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release);59 _ = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release);
33 const rc = linux.futex_wake(&self.mutex.linux_lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1);60 const rc = linux.futex_wake(&self.mutex.lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1);
34 switch (linux.getErrno(rc)) {61 switch (linux.getErrno(rc)) {
35 0 => {},62 0 => {},
36 linux.EINVAL => unreachable,63 linux.EINVAL => unreachable,
37 else => unreachable,64 else => unreachable,
38 }65 }
39 }66 }
40 } else {
41 SpinLock.Held.release(SpinLock.Held{ .spinlock = &self.mutex.spin_lock });
42 }67 }
68 };
69
70 pub fn init() Mutex {
71 return Mutex{ .lock = 0 };
43 }72 }
44 };
4573
46 pub fn init() Mutex {74 pub fn deinit(self: *Mutex) void {}
47 return Mutex{
48 .linux_lock = linux_lock_init,
49 .spin_lock = spin_lock_init,
50 };
51 }
5275
53 pub fn acquire(self: *Mutex) Held {76 pub fn acquire(self: *Mutex) Held {
54 if (builtin.os == builtin.Os.linux) {77 var c = @cmpxchgWeak(i32, &self.lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse
55 var c = @cmpxchgWeak(i32, &self.linux_lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse
56 return Held{ .mutex = self };78 return Held{ .mutex = self };
57 if (c != 2)79 if (c != 2)
58 c = @atomicRmw(i32, &self.linux_lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);80 c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
59 while (c != 0) {81 while (c != 0) {
60 const rc = linux.futex_wait(&self.linux_lock, linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG, 2, null);82 const rc = linux.futex_wait(&self.lock, linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG, 2, null);
61 switch (linux.getErrno(rc)) {83 switch (linux.getErrno(rc)) {
62 0, linux.EINTR, linux.EAGAIN => {},84 0, linux.EINTR, linux.EAGAIN => {},
63 linux.EINVAL => unreachable,85 linux.EINVAL => unreachable,
64 else => unreachable,86 else => unreachable,
65 }87 }
66 c = @atomicRmw(i32, &self.linux_lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);88 c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
67 }89 }
68 } else {90 return Held{ .mutex = self };
69 _ = self.spin_lock.acquire();
70 }91 }
71 return Held{ .mutex = self };92 },
72 }93 // TODO once https://github.com/ziglang/zig/issues/287 (copy elision) is solved, we can make a
94 // better implementation of this. The problem is we need the init() function to have access to
95 // the address of the CRITICAL_SECTION, and then have it not move.
96 builtin.Os.windows => std.StaticallyInitializedMutex,
97 else => struct {
98 /// TODO better implementation than spin lock.
99 /// When changing this, one must also change the corresponding
100 /// std.StaticallyInitializedMutex code, since it aliases this type,
101 /// under the assumption that it works both statically and at runtime.
102 lock: SpinLock,
103
104 pub const Held = struct {
105 mutex: *Mutex,
106
107 pub fn release(self: Held) void {
108 SpinLock.Held.release(SpinLock.Held{ .spinlock = &self.mutex.lock });
109 }
110 };
111
112 pub fn init() Mutex {
113 return Mutex{ .lock = SpinLock.init() };
114 }
115
116 pub fn deinit(self: *Mutex) void {}
117
118 pub fn acquire(self: *Mutex) Held {
119 _ = self.lock.acquire();
120 return Held{ .mutex = self };
121 }
122 },
73};123};
74124
75const Context = struct {125const TestContext = struct {
76 mutex: *Mutex,126 mutex: *Mutex,
77 data: i128,127 data: i128,
78128
...@@ -90,25 +140,32 @@ test "std.Mutex" {...@@ -90,25 +140,32 @@ test "std.Mutex" {
90 var a = &fixed_buffer_allocator.allocator;140 var a = &fixed_buffer_allocator.allocator;
91141
92 var mutex = Mutex.init();142 var mutex = Mutex.init();
93 var context = Context{143 defer mutex.deinit();
144
145 var context = TestContext{
94 .mutex = &mutex,146 .mutex = &mutex,
95 .data = 0,147 .data = 0,
96 };148 };
97149
98 const thread_count = 10;150 if (builtin.single_threaded) {
99 var threads: [thread_count]*std.os.Thread = undefined;151 worker(&context);
100 for (threads) |*t| {152 std.debug.assertOrPanic(context.data == TestContext.incr_count);
101 t.* = try std.os.spawnThread(&context, worker);153 } else {
102 }154 const thread_count = 10;
103 for (threads) |t|155 var threads: [thread_count]*std.os.Thread = undefined;
104 t.wait();156 for (threads) |*t| {
157 t.* = try std.os.spawnThread(&context, worker);
158 }
159 for (threads) |t|
160 t.wait();
105161
106 std.debug.assertOrPanic(context.data == thread_count * Context.incr_count);162 std.debug.assertOrPanic(context.data == thread_count * TestContext.incr_count);
163 }
107}164}
108165
109fn worker(ctx: *Context) void {166fn worker(ctx: *TestContext) void {
110 var i: usize = 0;167 var i: usize = 0;
111 while (i != Context.incr_count) : (i += 1) {168 while (i != TestContext.incr_count) : (i += 1) {
112 const held = ctx.mutex.acquire();169 const held = ctx.mutex.acquire();
113 defer held.release();170 defer held.release();
114171
std/os/child_process.zig+4-3
...@@ -88,7 +88,8 @@ pub const ChildProcess = struct {...@@ -88,7 +88,8 @@ pub const ChildProcess = struct {
88 /// First argument in argv is the executable.88 /// First argument in argv is the executable.
89 /// On success must call deinit.89 /// On success must call deinit.
90 pub fn init(argv: []const []const u8, allocator: *mem.Allocator) !*ChildProcess {90 pub fn init(argv: []const []const u8, allocator: *mem.Allocator) !*ChildProcess {
91 const child = try allocator.create(ChildProcess{91 const child = try allocator.create(ChildProcess);
92 child.* = ChildProcess{
92 .allocator = allocator,93 .allocator = allocator,
93 .argv = argv,94 .argv = argv,
94 .pid = undefined,95 .pid = undefined,
...@@ -109,7 +110,7 @@ pub const ChildProcess = struct {...@@ -109,7 +110,7 @@ pub const ChildProcess = struct {
109 .stdin_behavior = StdIo.Inherit,110 .stdin_behavior = StdIo.Inherit,
110 .stdout_behavior = StdIo.Inherit,111 .stdout_behavior = StdIo.Inherit,
111 .stderr_behavior = StdIo.Inherit,112 .stderr_behavior = StdIo.Inherit,
112 });113 };
113 errdefer allocator.destroy(child);114 errdefer allocator.destroy(child);
114 return child;115 return child;
115 }116 }
...@@ -594,7 +595,7 @@ pub const ChildProcess = struct {...@@ -594,7 +595,7 @@ pub const ChildProcess = struct {
594 const PATH = try os.getEnvVarOwned(self.allocator, "PATH");595 const PATH = try os.getEnvVarOwned(self.allocator, "PATH");
595 defer self.allocator.free(PATH);596 defer self.allocator.free(PATH);
596597
597 var it = mem.split(PATH, ";");598 var it = mem.tokenize(PATH, ";");
598 while (it.next()) |search_path| {599 while (it.next()) |search_path| {
599 const joined_path = try os.path.join(self.allocator, search_path, app_name);600 const joined_path = try os.path.join(self.allocator, search_path, app_name);
600 defer self.allocator.free(joined_path);601 defer self.allocator.free(joined_path);
std/os/index.zig+5-3
...@@ -608,7 +608,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: *const BufMap, allocator:...@@ -608,7 +608,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: *const BufMap, allocator:
608 // +1 for the null terminating byte608 // +1 for the null terminating byte
609 const path_buf = try allocator.alloc(u8, PATH.len + exe_path.len + 2);609 const path_buf = try allocator.alloc(u8, PATH.len + exe_path.len + 2);
610 defer allocator.free(path_buf);610 defer allocator.free(path_buf);
611 var it = mem.split(PATH, ":");611 var it = mem.tokenize(PATH, ":");
612 var seen_eacces = false;612 var seen_eacces = false;
613 var err: usize = undefined;613 var err: usize = undefined;
614 while (it.next()) |search_path| {614 while (it.next()) |search_path| {
...@@ -3013,6 +3013,7 @@ pub const SpawnThreadError = error{...@@ -3013,6 +3013,7 @@ pub const SpawnThreadError = error{
3013/// where T is u8, noreturn, void, or !void3013/// where T is u8, noreturn, void, or !void
3014/// caller must call wait on the returned thread3014/// caller must call wait on the returned thread
3015pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread {3015pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread {
3016 if (builtin.single_threaded) @compileError("cannot spawn thread when building in single-threaded mode");
3016 // TODO compile-time call graph analysis to determine stack upper bound3017 // TODO compile-time call graph analysis to determine stack upper bound
3017 // https://github.com/ziglang/zig/issues/1573018 // https://github.com/ziglang/zig/issues/157
3018 const default_stack_size = 8 * 1024 * 1024;3019 const default_stack_size = 8 * 1024 * 1024;
...@@ -3046,7 +3047,8 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread...@@ -3046,7 +3047,8 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
3046 const bytes_ptr = windows.HeapAlloc(heap_handle, 0, byte_count) orelse return SpawnThreadError.OutOfMemory;3047 const bytes_ptr = windows.HeapAlloc(heap_handle, 0, byte_count) orelse return SpawnThreadError.OutOfMemory;
3047 errdefer assert(windows.HeapFree(heap_handle, 0, bytes_ptr) != 0);3048 errdefer assert(windows.HeapFree(heap_handle, 0, bytes_ptr) != 0);
3048 const bytes = @ptrCast([*]u8, bytes_ptr)[0..byte_count];3049 const bytes = @ptrCast([*]u8, bytes_ptr)[0..byte_count];
3049 const outer_context = std.heap.FixedBufferAllocator.init(bytes).allocator.create(WinThread.OuterContext{3050 const outer_context = std.heap.FixedBufferAllocator.init(bytes).allocator.create(WinThread.OuterContext) catch unreachable;
3051 outer_context.* = WinThread.OuterContext{
3050 .thread = Thread{3052 .thread = Thread{
3051 .data = Thread.Data{3053 .data = Thread.Data{
3052 .heap_handle = heap_handle,3054 .heap_handle = heap_handle,
...@@ -3055,7 +3057,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread...@@ -3055,7 +3057,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
3055 },3057 },
3056 },3058 },
3057 .inner = context,3059 .inner = context,
3058 }) catch unreachable;3060 };
30593061
3060 const parameter = if (@sizeOf(Context) == 0) null else @ptrCast(*c_void, &outer_context.inner);3062 const parameter = if (@sizeOf(Context) == 0) null else @ptrCast(*c_void, &outer_context.inner);
3061 outer_context.thread.data.handle = windows.CreateThread(null, default_stack_size, WinThread.threadMain, parameter, 0, null) orelse {3063 outer_context.thread.data.handle = windows.CreateThread(null, default_stack_size, WinThread.threadMain, parameter, 0, null) orelse {
std/os/path.zig+18-14
...@@ -184,7 +184,7 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {...@@ -184,7 +184,7 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {
184 return relative_path;184 return relative_path;
185 }185 }
186186
187 var it = mem.split(path, []u8{this_sep});187 var it = mem.tokenize(path, []u8{this_sep});
188 _ = (it.next() orelse return relative_path);188 _ = (it.next() orelse return relative_path);
189 _ = (it.next() orelse return relative_path);189 _ = (it.next() orelse return relative_path);
190 return WindowsPath{190 return WindowsPath{
...@@ -202,7 +202,7 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {...@@ -202,7 +202,7 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {
202 return relative_path;202 return relative_path;
203 }203 }
204204
205 var it = mem.split(path, []u8{this_sep});205 var it = mem.tokenize(path, []u8{this_sep});
206 _ = (it.next() orelse return relative_path);206 _ = (it.next() orelse return relative_path);
207 _ = (it.next() orelse return relative_path);207 _ = (it.next() orelse return relative_path);
208 return WindowsPath{208 return WindowsPath{
...@@ -264,8 +264,8 @@ fn networkShareServersEql(ns1: []const u8, ns2: []const u8) bool {...@@ -264,8 +264,8 @@ fn networkShareServersEql(ns1: []const u8, ns2: []const u8) bool {
264 const sep1 = ns1[0];264 const sep1 = ns1[0];
265 const sep2 = ns2[0];265 const sep2 = ns2[0];
266266
267 var it1 = mem.split(ns1, []u8{sep1});267 var it1 = mem.tokenize(ns1, []u8{sep1});
268 var it2 = mem.split(ns2, []u8{sep2});268 var it2 = mem.tokenize(ns2, []u8{sep2});
269269
270 // TODO ASCII is wrong, we actually need full unicode support to compare paths.270 // TODO ASCII is wrong, we actually need full unicode support to compare paths.
271 return asciiEqlIgnoreCase(it1.next().?, it2.next().?);271 return asciiEqlIgnoreCase(it1.next().?, it2.next().?);
...@@ -285,8 +285,8 @@ fn compareDiskDesignators(kind: WindowsPath.Kind, p1: []const u8, p2: []const u8...@@ -285,8 +285,8 @@ fn compareDiskDesignators(kind: WindowsPath.Kind, p1: []const u8, p2: []const u8
285 const sep1 = p1[0];285 const sep1 = p1[0];
286 const sep2 = p2[0];286 const sep2 = p2[0];
287287
288 var it1 = mem.split(p1, []u8{sep1});288 var it1 = mem.tokenize(p1, []u8{sep1});
289 var it2 = mem.split(p2, []u8{sep2});289 var it2 = mem.tokenize(p2, []u8{sep2});
290290
291 // TODO ASCII is wrong, we actually need full unicode support to compare paths.291 // TODO ASCII is wrong, we actually need full unicode support to compare paths.
292 return asciiEqlIgnoreCase(it1.next().?, it2.next().?) and asciiEqlIgnoreCase(it1.next().?, it2.next().?);292 return asciiEqlIgnoreCase(it1.next().?, it2.next().?) and asciiEqlIgnoreCase(it1.next().?, it2.next().?);
...@@ -337,6 +337,8 @@ pub fn resolveSlice(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -337,6 +337,8 @@ pub fn resolveSlice(allocator: *Allocator, paths: []const []const u8) ![]u8 {
337/// If all paths are relative it uses the current working directory as a starting point.337/// If all paths are relative it uses the current working directory as a starting point.
338/// Each drive has its own current working directory.338/// Each drive has its own current working directory.
339/// Path separators are canonicalized to '\\' and drives are canonicalized to capital letters.339/// Path separators are canonicalized to '\\' and drives are canonicalized to capital letters.
340/// Note: all usage of this function should be audited due to the existence of symlinks.
341/// Without performing actual syscalls, resolving `..` could be incorrect.
340pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {342pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
341 if (paths.len == 0) {343 if (paths.len == 0) {
342 assert(is_windows); // resolveWindows called on non windows can't use getCwd344 assert(is_windows); // resolveWindows called on non windows can't use getCwd
...@@ -416,7 +418,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -416,7 +418,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
416 },418 },
417 WindowsPath.Kind.NetworkShare => {419 WindowsPath.Kind.NetworkShare => {
418 result = try allocator.alloc(u8, max_size);420 result = try allocator.alloc(u8, max_size);
419 var it = mem.split(paths[first_index], "/\\");421 var it = mem.tokenize(paths[first_index], "/\\");
420 const server_name = it.next().?;422 const server_name = it.next().?;
421 const other_name = it.next().?;423 const other_name = it.next().?;
422424
...@@ -483,7 +485,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -483,7 +485,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
483 if (!correct_disk_designator) {485 if (!correct_disk_designator) {
484 continue;486 continue;
485 }487 }
486 var it = mem.split(p[parsed.disk_designator.len..], "/\\");488 var it = mem.tokenize(p[parsed.disk_designator.len..], "/\\");
487 while (it.next()) |component| {489 while (it.next()) |component| {
488 if (mem.eql(u8, component, ".")) {490 if (mem.eql(u8, component, ".")) {
489 continue;491 continue;
...@@ -516,6 +518,8 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -516,6 +518,8 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
516/// It resolves "." and "..".518/// It resolves "." and "..".
517/// The result does not have a trailing path separator.519/// The result does not have a trailing path separator.
518/// If all paths are relative it uses the current working directory as a starting point.520/// If all paths are relative it uses the current working directory as a starting point.
521/// Note: all usage of this function should be audited due to the existence of symlinks.
522/// Without performing actual syscalls, resolving `..` could be incorrect.
519pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {523pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
520 if (paths.len == 0) {524 if (paths.len == 0) {
521 assert(!is_windows); // resolvePosix called on windows can't use getCwd525 assert(!is_windows); // resolvePosix called on windows can't use getCwd
...@@ -550,7 +554,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -550,7 +554,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
550 errdefer allocator.free(result);554 errdefer allocator.free(result);
551555
552 for (paths[first_index..]) |p, i| {556 for (paths[first_index..]) |p, i| {
553 var it = mem.split(p, "/");557 var it = mem.tokenize(p, "/");
554 while (it.next()) |component| {558 while (it.next()) |component| {
555 if (mem.eql(u8, component, ".")) {559 if (mem.eql(u8, component, ".")) {
556 continue;560 continue;
...@@ -937,8 +941,8 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8)...@@ -937,8 +941,8 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8)
937 return resolved_to;941 return resolved_to;
938 }942 }
939943
940 var from_it = mem.split(resolved_from, "/\\");944 var from_it = mem.tokenize(resolved_from, "/\\");
941 var to_it = mem.split(resolved_to, "/\\");945 var to_it = mem.tokenize(resolved_to, "/\\");
942 while (true) {946 while (true) {
943 const from_component = from_it.next() orelse return mem.dupe(allocator, u8, to_it.rest());947 const from_component = from_it.next() orelse return mem.dupe(allocator, u8, to_it.rest());
944 const to_rest = to_it.rest();948 const to_rest = to_it.rest();
...@@ -967,7 +971,7 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8)...@@ -967,7 +971,7 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8)
967 // shave off the trailing slash971 // shave off the trailing slash
968 result_index -= 1;972 result_index -= 1;
969973
970 var rest_it = mem.split(to_rest, "/\\");974 var rest_it = mem.tokenize(to_rest, "/\\");
971 while (rest_it.next()) |to_component| {975 while (rest_it.next()) |to_component| {
972 result[result_index] = '\\';976 result[result_index] = '\\';
973 result_index += 1;977 result_index += 1;
...@@ -988,8 +992,8 @@ pub fn relativePosix(allocator: *Allocator, from: []const u8, to: []const u8) ![...@@ -988,8 +992,8 @@ pub fn relativePosix(allocator: *Allocator, from: []const u8, to: []const u8) ![
988 const resolved_to = try resolvePosix(allocator, [][]const u8{to});992 const resolved_to = try resolvePosix(allocator, [][]const u8{to});
989 defer allocator.free(resolved_to);993 defer allocator.free(resolved_to);
990994
991 var from_it = mem.split(resolved_from, "/");995 var from_it = mem.tokenize(resolved_from, "/");
992 var to_it = mem.split(resolved_to, "/");996 var to_it = mem.tokenize(resolved_to, "/");
993 while (true) {997 while (true) {
994 const from_component = from_it.next() orelse return mem.dupe(allocator, u8, to_it.rest());998 const from_component = from_it.next() orelse return mem.dupe(allocator, u8, to_it.rest());
995 const to_rest = to_it.rest();999 const to_rest = to_it.rest();
std/os/test.zig+4
...@@ -40,6 +40,8 @@ fn testThreadIdFn(thread_id: *os.Thread.Id) void {...@@ -40,6 +40,8 @@ fn testThreadIdFn(thread_id: *os.Thread.Id) void {
40}40}
4141
42test "std.os.Thread.getCurrentId" {42test "std.os.Thread.getCurrentId" {
43 if (builtin.single_threaded) return error.SkipZigTest;
44
43 var thread_current_id: os.Thread.Id = undefined;45 var thread_current_id: os.Thread.Id = undefined;
44 const thread = try os.spawnThread(&thread_current_id, testThreadIdFn);46 const thread = try os.spawnThread(&thread_current_id, testThreadIdFn);
45 const thread_id = thread.handle();47 const thread_id = thread.handle();
...@@ -53,6 +55,8 @@ test "std.os.Thread.getCurrentId" {...@@ -53,6 +55,8 @@ test "std.os.Thread.getCurrentId" {
53}55}
5456
55test "spawn threads" {57test "spawn threads" {
58 if (builtin.single_threaded) return error.SkipZigTest;
59
56 var shared_ctx: i32 = 1;60 var shared_ctx: i32 = 1;
5761
58 const thread1 = try std.os.spawnThread({}, start1);62 const thread1 = try std.os.spawnThread({}, start1);
std/os/time.zig+3-5
...@@ -79,14 +79,12 @@ fn milliTimestampWindows() u64 {...@@ -79,14 +79,12 @@ fn milliTimestampWindows() u64 {
79}79}
8080
81fn milliTimestampDarwin() u64 {81fn milliTimestampDarwin() u64 {
82 //Sources suggest MacOS 10.12 has support for
83 // posix clock_gettime.
84 var tv: darwin.timeval = undefined;82 var tv: darwin.timeval = undefined;
85 var err = darwin.gettimeofday(&tv, null);83 var err = darwin.gettimeofday(&tv, null);
86 debug.assert(err == 0);84 debug.assert(err == 0);
87 const sec_ms = @intCast(u64, tv.tv_sec) * ms_per_s;85 const sec_ms = tv.tv_sec * ms_per_s;
88 const usec_ms = @divFloor(@intCast(u64, tv.tv_usec), us_per_s / ms_per_s);86 const usec_ms = @divFloor(tv.tv_usec, us_per_s / ms_per_s);
89 return u64(sec_ms) + u64(usec_ms);87 return @intCast(u64, sec_ms + usec_ms);
90}88}
9189
92fn milliTimestampPosix() u64 {90fn milliTimestampPosix() u64 {
std/os/windows/index.zig+1
...@@ -49,6 +49,7 @@ pub const UNICODE = false;...@@ -49,6 +49,7 @@ pub const UNICODE = false;
49pub const WCHAR = u16;49pub const WCHAR = u16;
50pub const WORD = u16;50pub const WORD = u16;
51pub const LARGE_INTEGER = i64;51pub const LARGE_INTEGER = i64;
52pub const LONG = c_long;
5253
53pub const TRUE = 1;54pub const TRUE = 1;
54pub const FALSE = 0;55pub const FALSE = 0;
std/os/windows/kernel32.zig+47
...@@ -220,3 +220,50 @@ pub const FOREGROUND_BLUE = 1;...@@ -220,3 +220,50 @@ pub const FOREGROUND_BLUE = 1;
220pub const FOREGROUND_GREEN = 2;220pub const FOREGROUND_GREEN = 2;
221pub const FOREGROUND_RED = 4;221pub const FOREGROUND_RED = 4;
222pub const FOREGROUND_INTENSITY = 8;222pub const FOREGROUND_INTENSITY = 8;
223
224pub extern "kernel32" stdcallcc fn InitializeCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
225pub extern "kernel32" stdcallcc fn EnterCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
226pub extern "kernel32" stdcallcc fn LeaveCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
227pub extern "kernel32" stdcallcc fn DeleteCriticalSection(lpCriticalSection: *CRITICAL_SECTION) void;
228
229pub const LIST_ENTRY = extern struct {
230 Flink: *LIST_ENTRY,
231 Blink: *LIST_ENTRY,
232};
233
234pub const RTL_CRITICAL_SECTION_DEBUG = extern struct {
235 Type: WORD,
236 CreatorBackTraceIndex: WORD,
237 CriticalSection: *RTL_CRITICAL_SECTION,
238 ProcessLocksList: LIST_ENTRY,
239 EntryCount: DWORD,
240 ContentionCount: DWORD,
241 Flags: DWORD,
242 CreatorBackTraceIndexHigh: WORD,
243 SpareWORD: WORD,
244};
245
246pub const RTL_CRITICAL_SECTION = extern struct {
247 DebugInfo: *RTL_CRITICAL_SECTION_DEBUG,
248 LockCount: LONG,
249 RecursionCount: LONG,
250 OwningThread: HANDLE,
251 LockSemaphore: HANDLE,
252 SpinCount: ULONG_PTR,
253};
254
255pub const CRITICAL_SECTION = RTL_CRITICAL_SECTION;
256pub const INIT_ONCE = RTL_RUN_ONCE;
257pub const INIT_ONCE_STATIC_INIT = RTL_RUN_ONCE_INIT;
258
259pub extern "kernel32" stdcallcc fn InitOnceExecuteOnce(InitOnce: *INIT_ONCE, InitFn: INIT_ONCE_FN, Parameter: ?*c_void, Context: ?*c_void) BOOL;
260
261pub const INIT_ONCE_FN = extern fn(InitOnce: *INIT_ONCE, Parameter: ?*c_void, Context: ?*c_void) BOOL;
262
263pub const RTL_RUN_ONCE = extern struct {
264 Ptr: ?*c_void,
265};
266
267pub const RTL_RUN_ONCE_INIT = RTL_RUN_ONCE {
268 .Ptr = null,
269};
std/statically_initialized_mutex.zig created+110
...@@ -0,0 +1,110 @@
1const std = @import("index.zig");
2const builtin = @import("builtin");
3const AtomicOrder = builtin.AtomicOrder;
4const AtomicRmwOp = builtin.AtomicRmwOp;
5const assert = std.debug.assert;
6const windows = std.os.windows;
7
8/// Lock may be held only once. If the same thread
9/// tries to acquire the same mutex twice, it deadlocks.
10/// This type is intended to be initialized statically. If you don't
11/// require static initialization, use std.Mutex.
12/// On Windows, this mutex allocates resources when it is
13/// first used, and the resources cannot be freed.
14/// On Linux, this is an alias of std.Mutex.
15pub const StaticallyInitializedMutex = switch(builtin.os) {
16 builtin.Os.linux => std.Mutex,
17 builtin.Os.windows => struct {
18 lock: windows.CRITICAL_SECTION,
19 init_once: windows.RTL_RUN_ONCE,
20
21 pub const Held = struct {
22 mutex: *StaticallyInitializedMutex,
23
24 pub fn release(self: Held) void {
25 windows.LeaveCriticalSection(&self.mutex.lock);
26 }
27 };
28
29 pub fn init() StaticallyInitializedMutex {
30 return StaticallyInitializedMutex {
31 .lock = undefined,
32 .init_once = windows.INIT_ONCE_STATIC_INIT,
33 };
34 }
35
36 extern fn initCriticalSection(
37 InitOnce: *windows.RTL_RUN_ONCE,
38 Parameter: ?*c_void,
39 Context: ?*c_void,
40 ) windows.BOOL {
41 const lock = @ptrCast(*windows.CRITICAL_SECTION, @alignCast(@alignOf(windows.CRITICAL_SECTION), Parameter));
42 windows.InitializeCriticalSection(lock);
43 return windows.TRUE;
44 }
45
46 /// TODO: once https://github.com/ziglang/zig/issues/287 is solved and std.Mutex has a better
47 /// implementation of a runtime initialized mutex, remove this function.
48 pub fn deinit(self: *StaticallyInitializedMutex) void {
49 assert(windows.InitOnceExecuteOnce(&self.init_once, initCriticalSection, &self.lock, null) != 0);
50 windows.DeleteCriticalSection(&self.lock);
51 }
52
53 pub fn acquire(self: *StaticallyInitializedMutex) Held {
54 assert(windows.InitOnceExecuteOnce(&self.init_once, initCriticalSection, &self.lock, null) != 0);
55 windows.EnterCriticalSection(&self.lock);
56 return Held { .mutex = self };
57 }
58 },
59 else => std.Mutex,
60};
61
62test "std.StaticallyInitializedMutex" {
63 const TestContext = struct {
64 data: i128,
65
66 const TestContext = @This();
67 const incr_count = 10000;
68
69 var mutex = StaticallyInitializedMutex.init();
70
71 fn worker(ctx: *TestContext) void {
72 var i: usize = 0;
73 while (i != TestContext.incr_count) : (i += 1) {
74 const held = mutex.acquire();
75 defer held.release();
76
77 ctx.data += 1;
78 }
79 }
80 };
81
82 var direct_allocator = std.heap.DirectAllocator.init();
83 defer direct_allocator.deinit();
84
85 var plenty_of_memory = try direct_allocator.allocator.alloc(u8, 300 * 1024);
86 defer direct_allocator.allocator.free(plenty_of_memory);
87
88 var fixed_buffer_allocator = std.heap.ThreadSafeFixedBufferAllocator.init(plenty_of_memory);
89 var a = &fixed_buffer_allocator.allocator;
90
91
92 var context = TestContext{
93 .data = 0,
94 };
95
96 if (builtin.single_threaded) {
97 TestContext.worker(&context);
98 std.debug.assertOrPanic(context.data == TestContext.incr_count);
99 } else {
100 const thread_count = 10;
101 var threads: [thread_count]*std.os.Thread = undefined;
102 for (threads) |*t| {
103 t.* = try std.os.spawnThread(&context, TestContext.worker);
104 }
105 for (threads) |t|
106 t.wait();
107
108 std.debug.assertOrPanic(context.data == thread_count * TestContext.incr_count);
109 }
110}
std/zig/parse.zig+226-150
...@@ -17,14 +17,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -17,14 +17,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
17 defer stack.deinit();17 defer stack.deinit();
1818
19 const arena = &tree_arena.allocator;19 const arena = &tree_arena.allocator;
20 const root_node = try arena.create(ast.Node.Root{20 const root_node = try arena.create(ast.Node.Root);
21 root_node.* = ast.Node.Root{
21 .base = ast.Node{ .id = ast.Node.Id.Root },22 .base = ast.Node{ .id = ast.Node.Id.Root },
22 .decls = ast.Node.Root.DeclList.init(arena),23 .decls = ast.Node.Root.DeclList.init(arena),
23 .doc_comments = null,24 .doc_comments = null,
24 .shebang = null,25 .shebang = null,
25 // initialized when we get the eof token26 // initialized when we get the eof token
26 .eof_token = undefined,27 .eof_token = undefined,
27 });28 };
2829
29 var tree = ast.Tree{30 var tree = ast.Tree{
30 .source = source,31 .source = source,
...@@ -75,20 +76,22 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -75,20 +76,22 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
75 Token.Id.Keyword_test => {76 Token.Id.Keyword_test => {
76 stack.append(State.TopLevel) catch unreachable;77 stack.append(State.TopLevel) catch unreachable;
7778
78 const block = try arena.create(ast.Node.Block{79 const block = try arena.create(ast.Node.Block);
80 block.* = ast.Node.Block{
79 .base = ast.Node{ .id = ast.Node.Id.Block },81 .base = ast.Node{ .id = ast.Node.Id.Block },
80 .label = null,82 .label = null,
81 .lbrace = undefined,83 .lbrace = undefined,
82 .statements = ast.Node.Block.StatementList.init(arena),84 .statements = ast.Node.Block.StatementList.init(arena),
83 .rbrace = undefined,85 .rbrace = undefined,
84 });86 };
85 const test_node = try arena.create(ast.Node.TestDecl{87 const test_node = try arena.create(ast.Node.TestDecl);
88 test_node.* = ast.Node.TestDecl{
86 .base = ast.Node{ .id = ast.Node.Id.TestDecl },89 .base = ast.Node{ .id = ast.Node.Id.TestDecl },
87 .doc_comments = comments,90 .doc_comments = comments,
88 .test_token = token_index,91 .test_token = token_index,
89 .name = undefined,92 .name = undefined,
90 .body_node = &block.base,93 .body_node = &block.base,
91 });94 };
92 try root_node.decls.push(&test_node.base);95 try root_node.decls.push(&test_node.base);
93 try stack.append(State{ .Block = block });96 try stack.append(State{ .Block = block });
94 try stack.append(State{97 try stack.append(State{
...@@ -119,19 +122,21 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -119,19 +122,21 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
119 continue;122 continue;
120 },123 },
121 Token.Id.Keyword_comptime => {124 Token.Id.Keyword_comptime => {
122 const block = try arena.create(ast.Node.Block{125 const block = try arena.create(ast.Node.Block);
126 block.* = ast.Node.Block{
123 .base = ast.Node{ .id = ast.Node.Id.Block },127 .base = ast.Node{ .id = ast.Node.Id.Block },
124 .label = null,128 .label = null,
125 .lbrace = undefined,129 .lbrace = undefined,
126 .statements = ast.Node.Block.StatementList.init(arena),130 .statements = ast.Node.Block.StatementList.init(arena),
127 .rbrace = undefined,131 .rbrace = undefined,
128 });132 };
129 const node = try arena.create(ast.Node.Comptime{133 const node = try arena.create(ast.Node.Comptime);
134 node.* = ast.Node.Comptime{
130 .base = ast.Node{ .id = ast.Node.Id.Comptime },135 .base = ast.Node{ .id = ast.Node.Id.Comptime },
131 .comptime_token = token_index,136 .comptime_token = token_index,
132 .expr = &block.base,137 .expr = &block.base,
133 .doc_comments = comments,138 .doc_comments = comments,
134 });139 };
135 try root_node.decls.push(&node.base);140 try root_node.decls.push(&node.base);
136141
137 stack.append(State.TopLevel) catch unreachable;142 stack.append(State.TopLevel) catch unreachable;
...@@ -235,14 +240,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -235,14 +240,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
235 return tree;240 return tree;
236 }241 }
237242
238 const node = try arena.create(ast.Node.Use{243 const node = try arena.create(ast.Node.Use);
244 node.* = ast.Node.Use{
239 .base = ast.Node{ .id = ast.Node.Id.Use },245 .base = ast.Node{ .id = ast.Node.Id.Use },
240 .use_token = token_index,246 .use_token = token_index,
241 .visib_token = ctx.visib_token,247 .visib_token = ctx.visib_token,
242 .expr = undefined,248 .expr = undefined,
243 .semicolon_token = undefined,249 .semicolon_token = undefined,
244 .doc_comments = ctx.comments,250 .doc_comments = ctx.comments,
245 });251 };
246 try ctx.decls.push(&node.base);252 try ctx.decls.push(&node.base);
247253
248 stack.append(State{254 stack.append(State{
...@@ -276,7 +282,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -276,7 +282,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
276 continue;282 continue;
277 },283 },
278 Token.Id.Keyword_fn, Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc, Token.Id.Keyword_async => {284 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{285 const fn_proto = try arena.create(ast.Node.FnProto);
286 fn_proto.* = ast.Node.FnProto{
280 .base = ast.Node{ .id = ast.Node.Id.FnProto },287 .base = ast.Node{ .id = ast.Node.Id.FnProto },
281 .doc_comments = ctx.comments,288 .doc_comments = ctx.comments,
282 .visib_token = ctx.visib_token,289 .visib_token = ctx.visib_token,
...@@ -292,7 +299,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -292,7 +299,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
292 .lib_name = ctx.lib_name,299 .lib_name = ctx.lib_name,
293 .align_expr = null,300 .align_expr = null,
294 .section_expr = null,301 .section_expr = null,
295 });302 };
296 try ctx.decls.push(&fn_proto.base);303 try ctx.decls.push(&fn_proto.base);
297 stack.append(State{ .FnDef = fn_proto }) catch unreachable;304 stack.append(State{ .FnDef = fn_proto }) catch unreachable;
298 try stack.append(State{ .FnProto = fn_proto });305 try stack.append(State{ .FnProto = fn_proto });
...@@ -309,12 +316,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -309,12 +316,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
309 continue;316 continue;
310 },317 },
311 Token.Id.Keyword_async => {318 Token.Id.Keyword_async => {
312 const async_node = try arena.create(ast.Node.AsyncAttribute{319 const async_node = try arena.create(ast.Node.AsyncAttribute);
320 async_node.* = ast.Node.AsyncAttribute{
313 .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },321 .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },
314 .async_token = token_index,322 .async_token = token_index,
315 .allocator_type = null,323 .allocator_type = null,
316 .rangle_bracket = null,324 .rangle_bracket = null,
317 });325 };
318 fn_proto.async_attr = async_node;326 fn_proto.async_attr = async_node;
319327
320 try stack.append(State{328 try stack.append(State{
...@@ -341,13 +349,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -341,13 +349,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
341 },349 },
342 State.TopLevelExternOrField => |ctx| {350 State.TopLevelExternOrField => |ctx| {
343 if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |identifier| {351 if (eatToken(&tok_it, &tree, Token.Id.Identifier)) |identifier| {
344 const node = try arena.create(ast.Node.StructField{352 const node = try arena.create(ast.Node.StructField);
353 node.* = ast.Node.StructField{
345 .base = ast.Node{ .id = ast.Node.Id.StructField },354 .base = ast.Node{ .id = ast.Node.Id.StructField },
346 .doc_comments = ctx.comments,355 .doc_comments = ctx.comments,
347 .visib_token = ctx.visib_token,356 .visib_token = ctx.visib_token,
348 .name_token = identifier,357 .name_token = identifier,
349 .type_expr = undefined,358 .type_expr = undefined,
350 });359 };
351 const node_ptr = try ctx.container_decl.fields_and_decls.addOne();360 const node_ptr = try ctx.container_decl.fields_and_decls.addOne();
352 node_ptr.* = &node.base;361 node_ptr.* = &node.base;
353362
...@@ -391,7 +400,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -391,7 +400,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
391 const token = nextToken(&tok_it, &tree);400 const token = nextToken(&tok_it, &tree);
392 const token_index = token.index;401 const token_index = token.index;
393 const token_ptr = token.ptr;402 const token_ptr = token.ptr;
394 const node = try arena.create(ast.Node.ContainerDecl{403 const node = try arena.create(ast.Node.ContainerDecl);
404 node.* = ast.Node.ContainerDecl{
395 .base = ast.Node{ .id = ast.Node.Id.ContainerDecl },405 .base = ast.Node{ .id = ast.Node.Id.ContainerDecl },
396 .layout_token = ctx.layout_token,406 .layout_token = ctx.layout_token,
397 .kind_token = switch (token_ptr.id) {407 .kind_token = switch (token_ptr.id) {
...@@ -405,7 +415,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -405,7 +415,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
405 .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(arena),415 .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(arena),
406 .lbrace_token = undefined,416 .lbrace_token = undefined,
407 .rbrace_token = undefined,417 .rbrace_token = undefined,
408 });418 };
409 ctx.opt_ctx.store(&node.base);419 ctx.opt_ctx.store(&node.base);
410420
411 stack.append(State{ .ContainerDecl = node }) catch unreachable;421 stack.append(State{ .ContainerDecl = node }) catch unreachable;
...@@ -464,13 +474,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -464,13 +474,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
464 Token.Id.Identifier => {474 Token.Id.Identifier => {
465 switch (tree.tokens.at(container_decl.kind_token).id) {475 switch (tree.tokens.at(container_decl.kind_token).id) {
466 Token.Id.Keyword_struct => {476 Token.Id.Keyword_struct => {
467 const node = try arena.create(ast.Node.StructField{477 const node = try arena.create(ast.Node.StructField);
478 node.* = ast.Node.StructField{
468 .base = ast.Node{ .id = ast.Node.Id.StructField },479 .base = ast.Node{ .id = ast.Node.Id.StructField },
469 .doc_comments = comments,480 .doc_comments = comments,
470 .visib_token = null,481 .visib_token = null,
471 .name_token = token_index,482 .name_token = token_index,
472 .type_expr = undefined,483 .type_expr = undefined,
473 });484 };
474 const node_ptr = try container_decl.fields_and_decls.addOne();485 const node_ptr = try container_decl.fields_and_decls.addOne();
475 node_ptr.* = &node.base;486 node_ptr.* = &node.base;
476487
...@@ -485,13 +496,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -485,13 +496,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
485 continue;496 continue;
486 },497 },
487 Token.Id.Keyword_union => {498 Token.Id.Keyword_union => {
488 const node = try arena.create(ast.Node.UnionTag{499 const node = try arena.create(ast.Node.UnionTag);
500 node.* = ast.Node.UnionTag{
489 .base = ast.Node{ .id = ast.Node.Id.UnionTag },501 .base = ast.Node{ .id = ast.Node.Id.UnionTag },
490 .name_token = token_index,502 .name_token = token_index,
491 .type_expr = null,503 .type_expr = null,
492 .value_expr = null,504 .value_expr = null,
493 .doc_comments = comments,505 .doc_comments = comments,
494 });506 };
495 try container_decl.fields_and_decls.push(&node.base);507 try container_decl.fields_and_decls.push(&node.base);
496508
497 try stack.append(State{509 try stack.append(State{
...@@ -506,12 +518,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -506,12 +518,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
506 continue;518 continue;
507 },519 },
508 Token.Id.Keyword_enum => {520 Token.Id.Keyword_enum => {
509 const node = try arena.create(ast.Node.EnumTag{521 const node = try arena.create(ast.Node.EnumTag);
522 node.* = ast.Node.EnumTag{
510 .base = ast.Node{ .id = ast.Node.Id.EnumTag },523 .base = ast.Node{ .id = ast.Node.Id.EnumTag },
511 .name_token = token_index,524 .name_token = token_index,
512 .value = null,525 .value = null,
513 .doc_comments = comments,526 .doc_comments = comments,
514 });527 };
515 try container_decl.fields_and_decls.push(&node.base);528 try container_decl.fields_and_decls.push(&node.base);
516529
517 try stack.append(State{530 try stack.append(State{
...@@ -593,7 +606,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -593,7 +606,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
593 },606 },
594607
595 State.VarDecl => |ctx| {608 State.VarDecl => |ctx| {
596 const var_decl = try arena.create(ast.Node.VarDecl{609 const var_decl = try arena.create(ast.Node.VarDecl);
610 var_decl.* = ast.Node.VarDecl{
597 .base = ast.Node{ .id = ast.Node.Id.VarDecl },611 .base = ast.Node{ .id = ast.Node.Id.VarDecl },
598 .doc_comments = ctx.comments,612 .doc_comments = ctx.comments,
599 .visib_token = ctx.visib_token,613 .visib_token = ctx.visib_token,
...@@ -609,7 +623,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -609,7 +623,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
609 .name_token = undefined,623 .name_token = undefined,
610 .eq_token = undefined,624 .eq_token = undefined,
611 .semicolon_token = undefined,625 .semicolon_token = undefined,
612 });626 };
613 try ctx.list.push(&var_decl.base);627 try ctx.list.push(&var_decl.base);
614628
615 try stack.append(State{ .VarDeclAlign = var_decl });629 try stack.append(State{ .VarDeclAlign = var_decl });
...@@ -708,13 +722,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -708,13 +722,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
708 const token_ptr = token.ptr;722 const token_ptr = token.ptr;
709 switch (token_ptr.id) {723 switch (token_ptr.id) {
710 Token.Id.LBrace => {724 Token.Id.LBrace => {
711 const block = try arena.create(ast.Node.Block{725 const block = try arena.create(ast.Node.Block);
726 block.* = ast.Node.Block{
712 .base = ast.Node{ .id = ast.Node.Id.Block },727 .base = ast.Node{ .id = ast.Node.Id.Block },
713 .label = null,728 .label = null,
714 .lbrace = token_index,729 .lbrace = token_index,
715 .statements = ast.Node.Block.StatementList.init(arena),730 .statements = ast.Node.Block.StatementList.init(arena),
716 .rbrace = undefined,731 .rbrace = undefined,
717 });732 };
718 fn_proto.body_node = &block.base;733 fn_proto.body_node = &block.base;
719 stack.append(State{ .Block = block }) catch unreachable;734 stack.append(State{ .Block = block }) catch unreachable;
720 continue;735 continue;
...@@ -770,10 +785,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -770,10 +785,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
770 // TODO: this is a special case. Remove this when #760 is fixed785 // TODO: this is a special case. Remove this when #760 is fixed
771 if (token_ptr.id == Token.Id.Keyword_anyerror) {786 if (token_ptr.id == Token.Id.Keyword_anyerror) {
772 if (tok_it.peek().?.id == Token.Id.LBrace) {787 if (tok_it.peek().?.id == Token.Id.LBrace) {
773 const error_type_node = try arena.create(ast.Node.ErrorType{788 const error_type_node = try arena.create(ast.Node.ErrorType);
789 error_type_node.* = ast.Node.ErrorType{
774 .base = ast.Node{ .id = ast.Node.Id.ErrorType },790 .base = ast.Node{ .id = ast.Node.Id.ErrorType },
775 .token = token_index,791 .token = token_index,
776 });792 };
777 fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = &error_type_node.base };793 fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = &error_type_node.base };
778 continue;794 continue;
779 }795 }
...@@ -791,14 +807,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -791,14 +807,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
791 if (eatToken(&tok_it, &tree, Token.Id.RParen)) |_| {807 if (eatToken(&tok_it, &tree, Token.Id.RParen)) |_| {
792 continue;808 continue;
793 }809 }
794 const param_decl = try arena.create(ast.Node.ParamDecl{810 const param_decl = try arena.create(ast.Node.ParamDecl);
811 param_decl.* = ast.Node.ParamDecl{
795 .base = ast.Node{ .id = ast.Node.Id.ParamDecl },812 .base = ast.Node{ .id = ast.Node.Id.ParamDecl },
796 .comptime_token = null,813 .comptime_token = null,
797 .noalias_token = null,814 .noalias_token = null,
798 .name_token = null,815 .name_token = null,
799 .type_node = undefined,816 .type_node = undefined,
800 .var_args_token = null,817 .var_args_token = null,
801 });818 };
802 try fn_proto.params.push(&param_decl.base);819 try fn_proto.params.push(&param_decl.base);
803820
804 stack.append(State{821 stack.append(State{
...@@ -877,13 +894,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -877,13 +894,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
877 const token_ptr = token.ptr;894 const token_ptr = token.ptr;
878 switch (token_ptr.id) {895 switch (token_ptr.id) {
879 Token.Id.LBrace => {896 Token.Id.LBrace => {
880 const block = try arena.create(ast.Node.Block{897 const block = try arena.create(ast.Node.Block);
898 block.* = ast.Node.Block{
881 .base = ast.Node{ .id = ast.Node.Id.Block },899 .base = ast.Node{ .id = ast.Node.Id.Block },
882 .label = ctx.label,900 .label = ctx.label,
883 .lbrace = token_index,901 .lbrace = token_index,
884 .statements = ast.Node.Block.StatementList.init(arena),902 .statements = ast.Node.Block.StatementList.init(arena),
885 .rbrace = undefined,903 .rbrace = undefined,
886 });904 };
887 ctx.opt_ctx.store(&block.base);905 ctx.opt_ctx.store(&block.base);
888 stack.append(State{ .Block = block }) catch unreachable;906 stack.append(State{ .Block = block }) catch unreachable;
889 continue;907 continue;
...@@ -970,7 +988,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -970,7 +988,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
970 }988 }
971 },989 },
972 State.While => |ctx| {990 State.While => |ctx| {
973 const node = try arena.create(ast.Node.While{991 const node = try arena.create(ast.Node.While);
992 node.* = ast.Node.While{
974 .base = ast.Node{ .id = ast.Node.Id.While },993 .base = ast.Node{ .id = ast.Node.Id.While },
975 .label = ctx.label,994 .label = ctx.label,
976 .inline_token = ctx.inline_token,995 .inline_token = ctx.inline_token,
...@@ -980,7 +999,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -980,7 +999,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
980 .continue_expr = null,999 .continue_expr = null,
981 .body = undefined,1000 .body = undefined,
982 .@"else" = null,1001 .@"else" = null,
983 });1002 };
984 ctx.opt_ctx.store(&node.base);1003 ctx.opt_ctx.store(&node.base);
985 stack.append(State{ .Else = &node.@"else" }) catch unreachable;1004 stack.append(State{ .Else = &node.@"else" }) catch unreachable;
986 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } });1005 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } });
...@@ -999,7 +1018,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -999,7 +1018,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
999 continue;1018 continue;
1000 },1019 },
1001 State.For => |ctx| {1020 State.For => |ctx| {
1002 const node = try arena.create(ast.Node.For{1021 const node = try arena.create(ast.Node.For);
1022 node.* = ast.Node.For{
1003 .base = ast.Node{ .id = ast.Node.Id.For },1023 .base = ast.Node{ .id = ast.Node.Id.For },
1004 .label = ctx.label,1024 .label = ctx.label,
1005 .inline_token = ctx.inline_token,1025 .inline_token = ctx.inline_token,
...@@ -1008,7 +1028,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1008,7 +1028,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1008 .payload = null,1028 .payload = null,
1009 .body = undefined,1029 .body = undefined,
1010 .@"else" = null,1030 .@"else" = null,
1011 });1031 };
1012 ctx.opt_ctx.store(&node.base);1032 ctx.opt_ctx.store(&node.base);
1013 stack.append(State{ .Else = &node.@"else" }) catch unreachable;1033 stack.append(State{ .Else = &node.@"else" }) catch unreachable;
1014 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } });1034 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } });
...@@ -1020,12 +1040,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1020,12 +1040,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1020 },1040 },
1021 State.Else => |dest| {1041 State.Else => |dest| {
1022 if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| {1042 if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| {
1023 const node = try arena.create(ast.Node.Else{1043 const node = try arena.create(ast.Node.Else);
1044 node.* = ast.Node.Else{
1024 .base = ast.Node{ .id = ast.Node.Id.Else },1045 .base = ast.Node{ .id = ast.Node.Id.Else },
1025 .else_token = else_token,1046 .else_token = else_token,
1026 .payload = null,1047 .payload = null,
1027 .body = undefined,1048 .body = undefined,
1028 });1049 };
1029 dest.* = node;1050 dest.* = node;
10301051
1031 stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }) catch unreachable;1052 stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } }) catch unreachable;
...@@ -1083,11 +1104,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1083,11 +1104,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1083 continue;1104 continue;
1084 },1105 },
1085 Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => {1106 Token.Id.Keyword_defer, Token.Id.Keyword_errdefer => {
1086 const node = try arena.create(ast.Node.Defer{1107 const node = try arena.create(ast.Node.Defer);
1108 node.* = ast.Node.Defer{
1087 .base = ast.Node{ .id = ast.Node.Id.Defer },1109 .base = ast.Node{ .id = ast.Node.Id.Defer },
1088 .defer_token = token_index,1110 .defer_token = token_index,
1089 .expr = undefined,1111 .expr = undefined,
1090 });1112 };
1091 const node_ptr = try block.statements.addOne();1113 const node_ptr = try block.statements.addOne();
1092 node_ptr.* = &node.base;1114 node_ptr.* = &node.base;
10931115
...@@ -1096,13 +1118,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1096,13 +1118,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1096 continue;1118 continue;
1097 },1119 },
1098 Token.Id.LBrace => {1120 Token.Id.LBrace => {
1099 const inner_block = try arena.create(ast.Node.Block{1121 const inner_block = try arena.create(ast.Node.Block);
1122 inner_block.* = ast.Node.Block{
1100 .base = ast.Node{ .id = ast.Node.Id.Block },1123 .base = ast.Node{ .id = ast.Node.Id.Block },
1101 .label = null,1124 .label = null,
1102 .lbrace = token_index,1125 .lbrace = token_index,
1103 .statements = ast.Node.Block.StatementList.init(arena),1126 .statements = ast.Node.Block.StatementList.init(arena),
1104 .rbrace = undefined,1127 .rbrace = undefined,
1105 });1128 };
1106 try block.statements.push(&inner_block.base);1129 try block.statements.push(&inner_block.base);
11071130
1108 stack.append(State{ .Block = inner_block }) catch unreachable;1131 stack.append(State{ .Block = inner_block }) catch unreachable;
...@@ -1164,14 +1187,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1164,14 +1187,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1164 continue;1187 continue;
1165 }1188 }
11661189
1167 const node = try arena.create(ast.Node.AsmOutput{1190 const node = try arena.create(ast.Node.AsmOutput);
1191 node.* = ast.Node.AsmOutput{
1168 .base = ast.Node{ .id = ast.Node.Id.AsmOutput },1192 .base = ast.Node{ .id = ast.Node.Id.AsmOutput },
1169 .lbracket = lbracket_index,1193 .lbracket = lbracket_index,
1170 .symbolic_name = undefined,1194 .symbolic_name = undefined,
1171 .constraint = undefined,1195 .constraint = undefined,
1172 .kind = undefined,1196 .kind = undefined,
1173 .rparen = undefined,1197 .rparen = undefined,
1174 });1198 };
1175 try items.push(node);1199 try items.push(node);
11761200
1177 stack.append(State{ .AsmOutputItems = items }) catch unreachable;1201 stack.append(State{ .AsmOutputItems = items }) catch unreachable;
...@@ -1218,14 +1242,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1218,14 +1242,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1218 continue;1242 continue;
1219 }1243 }
12201244
1221 const node = try arena.create(ast.Node.AsmInput{1245 const node = try arena.create(ast.Node.AsmInput);
1246 node.* = ast.Node.AsmInput{
1222 .base = ast.Node{ .id = ast.Node.Id.AsmInput },1247 .base = ast.Node{ .id = ast.Node.Id.AsmInput },
1223 .lbracket = lbracket_index,1248 .lbracket = lbracket_index,
1224 .symbolic_name = undefined,1249 .symbolic_name = undefined,
1225 .constraint = undefined,1250 .constraint = undefined,
1226 .expr = undefined,1251 .expr = undefined,
1227 .rparen = undefined,1252 .rparen = undefined,
1228 });1253 };
1229 try items.push(node);1254 try items.push(node);
12301255
1231 stack.append(State{ .AsmInputItems = items }) catch unreachable;1256 stack.append(State{ .AsmInputItems = items }) catch unreachable;
...@@ -1283,12 +1308,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1283,12 +1308,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1283 continue;1308 continue;
1284 }1309 }
12851310
1286 const node = try arena.create(ast.Node.FieldInitializer{1311 const node = try arena.create(ast.Node.FieldInitializer);
1312 node.* = ast.Node.FieldInitializer{
1287 .base = ast.Node{ .id = ast.Node.Id.FieldInitializer },1313 .base = ast.Node{ .id = ast.Node.Id.FieldInitializer },
1288 .period_token = undefined,1314 .period_token = undefined,
1289 .name_token = undefined,1315 .name_token = undefined,
1290 .expr = undefined,1316 .expr = undefined,
1291 });1317 };
1292 try list_state.list.push(&node.base);1318 try list_state.list.push(&node.base);
12931319
1294 stack.append(State{ .FieldInitListCommaOrEnd = list_state }) catch unreachable;1320 stack.append(State{ .FieldInitListCommaOrEnd = list_state }) catch unreachable;
...@@ -1390,13 +1416,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1390,13 +1416,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1390 }1416 }
13911417
1392 const comments = try eatDocComments(arena, &tok_it, &tree);1418 const comments = try eatDocComments(arena, &tok_it, &tree);
1393 const node = try arena.create(ast.Node.SwitchCase{1419 const node = try arena.create(ast.Node.SwitchCase);
1420 node.* = ast.Node.SwitchCase{
1394 .base = ast.Node{ .id = ast.Node.Id.SwitchCase },1421 .base = ast.Node{ .id = ast.Node.Id.SwitchCase },
1395 .items = ast.Node.SwitchCase.ItemList.init(arena),1422 .items = ast.Node.SwitchCase.ItemList.init(arena),
1396 .payload = null,1423 .payload = null,
1397 .expr = undefined,1424 .expr = undefined,
1398 .arrow_token = undefined,1425 .arrow_token = undefined,
1399 });1426 };
1400 try list_state.list.push(&node.base);1427 try list_state.list.push(&node.base);
1401 try stack.append(State{ .SwitchCaseCommaOrEnd = list_state });1428 try stack.append(State{ .SwitchCaseCommaOrEnd = list_state });
1402 try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } });1429 try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } });
...@@ -1427,10 +1454,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1427,10 +1454,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1427 const token_index = token.index;1454 const token_index = token.index;
1428 const token_ptr = token.ptr;1455 const token_ptr = token.ptr;
1429 if (token_ptr.id == Token.Id.Keyword_else) {1456 if (token_ptr.id == Token.Id.Keyword_else) {
1430 const else_node = try arena.create(ast.Node.SwitchElse{1457 const else_node = try arena.create(ast.Node.SwitchElse);
1458 else_node.* = ast.Node.SwitchElse{
1431 .base = ast.Node{ .id = ast.Node.Id.SwitchElse },1459 .base = ast.Node{ .id = ast.Node.Id.SwitchElse },
1432 .token = token_index,1460 .token = token_index,
1433 });1461 };
1434 try switch_case.items.push(&else_node.base);1462 try switch_case.items.push(&else_node.base);
14351463
1436 try stack.append(State{1464 try stack.append(State{
...@@ -1537,7 +1565,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1537,7 +1565,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
15371565
1538 State.ExternType => |ctx| {1566 State.ExternType => |ctx| {
1539 if (eatToken(&tok_it, &tree, Token.Id.Keyword_fn)) |fn_token| {1567 if (eatToken(&tok_it, &tree, Token.Id.Keyword_fn)) |fn_token| {
1540 const fn_proto = try arena.create(ast.Node.FnProto{1568 const fn_proto = try arena.create(ast.Node.FnProto);
1569 fn_proto.* = ast.Node.FnProto{
1541 .base = ast.Node{ .id = ast.Node.Id.FnProto },1570 .base = ast.Node{ .id = ast.Node.Id.FnProto },
1542 .doc_comments = ctx.comments,1571 .doc_comments = ctx.comments,
1543 .visib_token = null,1572 .visib_token = null,
...@@ -1553,7 +1582,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1553,7 +1582,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1553 .lib_name = null,1582 .lib_name = null,
1554 .align_expr = null,1583 .align_expr = null,
1555 .section_expr = null,1584 .section_expr = null,
1556 });1585 };
1557 ctx.opt_ctx.store(&fn_proto.base);1586 ctx.opt_ctx.store(&fn_proto.base);
1558 stack.append(State{ .FnProto = fn_proto }) catch unreachable;1587 stack.append(State{ .FnProto = fn_proto }) catch unreachable;
1559 continue;1588 continue;
...@@ -1711,12 +1740,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1711,12 +1740,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1711 continue;1740 continue;
1712 }1741 }
17131742
1714 const node = try arena.create(ast.Node.Payload{1743 const node = try arena.create(ast.Node.Payload);
1744 node.* = ast.Node.Payload{
1715 .base = ast.Node{ .id = ast.Node.Id.Payload },1745 .base = ast.Node{ .id = ast.Node.Id.Payload },
1716 .lpipe = token_index,1746 .lpipe = token_index,
1717 .error_symbol = undefined,1747 .error_symbol = undefined,
1718 .rpipe = undefined,1748 .rpipe = undefined,
1719 });1749 };
1720 opt_ctx.store(&node.base);1750 opt_ctx.store(&node.base);
17211751
1722 stack.append(State{1752 stack.append(State{
...@@ -1747,13 +1777,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1747,13 +1777,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1747 continue;1777 continue;
1748 }1778 }
17491779
1750 const node = try arena.create(ast.Node.PointerPayload{1780 const node = try arena.create(ast.Node.PointerPayload);
1781 node.* = ast.Node.PointerPayload{
1751 .base = ast.Node{ .id = ast.Node.Id.PointerPayload },1782 .base = ast.Node{ .id = ast.Node.Id.PointerPayload },
1752 .lpipe = token_index,1783 .lpipe = token_index,
1753 .ptr_token = null,1784 .ptr_token = null,
1754 .value_symbol = undefined,1785 .value_symbol = undefined,
1755 .rpipe = undefined,1786 .rpipe = undefined,
1756 });1787 };
1757 opt_ctx.store(&node.base);1788 opt_ctx.store(&node.base);
17581789
1759 try stack.append(State{1790 try stack.append(State{
...@@ -1790,14 +1821,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1790,14 +1821,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1790 continue;1821 continue;
1791 }1822 }
17921823
1793 const node = try arena.create(ast.Node.PointerIndexPayload{1824 const node = try arena.create(ast.Node.PointerIndexPayload);
1825 node.* = ast.Node.PointerIndexPayload{
1794 .base = ast.Node{ .id = ast.Node.Id.PointerIndexPayload },1826 .base = ast.Node{ .id = ast.Node.Id.PointerIndexPayload },
1795 .lpipe = token_index,1827 .lpipe = token_index,
1796 .ptr_token = null,1828 .ptr_token = null,
1797 .value_symbol = undefined,1829 .value_symbol = undefined,
1798 .index_symbol = null,1830 .index_symbol = null,
1799 .rpipe = undefined,1831 .rpipe = undefined,
1800 });1832 };
1801 opt_ctx.store(&node.base);1833 opt_ctx.store(&node.base);
18021834
1803 stack.append(State{1835 stack.append(State{
...@@ -1824,12 +1856,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1824,12 +1856,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1824 const token_ptr = token.ptr;1856 const token_ptr = token.ptr;
1825 switch (token_ptr.id) {1857 switch (token_ptr.id) {
1826 Token.Id.Keyword_return, Token.Id.Keyword_break, Token.Id.Keyword_continue => {1858 Token.Id.Keyword_return, Token.Id.Keyword_break, Token.Id.Keyword_continue => {
1827 const node = try arena.create(ast.Node.ControlFlowExpression{1859 const node = try arena.create(ast.Node.ControlFlowExpression);
1860 node.* = ast.Node.ControlFlowExpression{
1828 .base = ast.Node{ .id = ast.Node.Id.ControlFlowExpression },1861 .base = ast.Node{ .id = ast.Node.Id.ControlFlowExpression },
1829 .ltoken = token_index,1862 .ltoken = token_index,
1830 .kind = undefined,1863 .kind = undefined,
1831 .rhs = null,1864 .rhs = null,
1832 });1865 };
1833 opt_ctx.store(&node.base);1866 opt_ctx.store(&node.base);
18341867
1835 stack.append(State{ .Expression = OptionalCtx{ .Optional = &node.rhs } }) catch unreachable;1868 stack.append(State{ .Expression = OptionalCtx{ .Optional = &node.rhs } }) catch unreachable;
...@@ -1853,7 +1886,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1853,7 +1886,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1853 continue;1886 continue;
1854 },1887 },
1855 Token.Id.Keyword_try, Token.Id.Keyword_cancel, Token.Id.Keyword_resume => {1888 Token.Id.Keyword_try, Token.Id.Keyword_cancel, Token.Id.Keyword_resume => {
1856 const node = try arena.create(ast.Node.PrefixOp{1889 const node = try arena.create(ast.Node.PrefixOp);
1890 node.* = ast.Node.PrefixOp{
1857 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },1891 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
1858 .op_token = token_index,1892 .op_token = token_index,
1859 .op = switch (token_ptr.id) {1893 .op = switch (token_ptr.id) {
...@@ -1863,7 +1897,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1863,7 +1897,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1863 else => unreachable,1897 else => unreachable,
1864 },1898 },
1865 .rhs = undefined,1899 .rhs = undefined,
1866 });1900 };
1867 opt_ctx.store(&node.base);1901 opt_ctx.store(&node.base);
18681902
1869 stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;1903 stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
...@@ -1887,13 +1921,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1887,13 +1921,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1887 const lhs = opt_ctx.get() orelse continue;1921 const lhs = opt_ctx.get() orelse continue;
18881922
1889 if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| {1923 if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| {
1890 const node = try arena.create(ast.Node.InfixOp{1924 const node = try arena.create(ast.Node.InfixOp);
1925 node.* = ast.Node.InfixOp{
1891 .base = ast.Node{ .id = ast.Node.Id.InfixOp },1926 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
1892 .lhs = lhs,1927 .lhs = lhs,
1893 .op_token = ellipsis3,1928 .op_token = ellipsis3,
1894 .op = ast.Node.InfixOp.Op.Range,1929 .op = ast.Node.InfixOp.Op.Range,
1895 .rhs = undefined,1930 .rhs = undefined,
1896 });1931 };
1897 opt_ctx.store(&node.base);1932 opt_ctx.store(&node.base);
1898 stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;1933 stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
1899 continue;1934 continue;
...@@ -1912,13 +1947,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1912,13 +1947,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1912 const token_index = token.index;1947 const token_index = token.index;
1913 const token_ptr = token.ptr;1948 const token_ptr = token.ptr;
1914 if (tokenIdToAssignment(token_ptr.id)) |ass_id| {1949 if (tokenIdToAssignment(token_ptr.id)) |ass_id| {
1915 const node = try arena.create(ast.Node.InfixOp{1950 const node = try arena.create(ast.Node.InfixOp);
1951 node.* = ast.Node.InfixOp{
1916 .base = ast.Node{ .id = ast.Node.Id.InfixOp },1952 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
1917 .lhs = lhs,1953 .lhs = lhs,
1918 .op_token = token_index,1954 .op_token = token_index,
1919 .op = ass_id,1955 .op = ass_id,
1920 .rhs = undefined,1956 .rhs = undefined,
1921 });1957 };
1922 opt_ctx.store(&node.base);1958 opt_ctx.store(&node.base);
1923 stack.append(State{ .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable;1959 stack.append(State{ .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1924 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } });1960 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } });
...@@ -1942,13 +1978,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1942,13 +1978,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1942 const token_index = token.index;1978 const token_index = token.index;
1943 const token_ptr = token.ptr;1979 const token_ptr = token.ptr;
1944 if (tokenIdToUnwrapExpr(token_ptr.id)) |unwrap_id| {1980 if (tokenIdToUnwrapExpr(token_ptr.id)) |unwrap_id| {
1945 const node = try arena.create(ast.Node.InfixOp{1981 const node = try arena.create(ast.Node.InfixOp);
1982 node.* = ast.Node.InfixOp{
1946 .base = ast.Node{ .id = ast.Node.Id.InfixOp },1983 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
1947 .lhs = lhs,1984 .lhs = lhs,
1948 .op_token = token_index,1985 .op_token = token_index,
1949 .op = unwrap_id,1986 .op = unwrap_id,
1950 .rhs = undefined,1987 .rhs = undefined,
1951 });1988 };
1952 opt_ctx.store(&node.base);1989 opt_ctx.store(&node.base);
19531990
1954 stack.append(State{ .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable;1991 stack.append(State{ .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
...@@ -1974,13 +2011,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1974,13 +2011,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1974 const lhs = opt_ctx.get() orelse continue;2011 const lhs = opt_ctx.get() orelse continue;
19752012
1976 if (eatToken(&tok_it, &tree, Token.Id.Keyword_or)) |or_token| {2013 if (eatToken(&tok_it, &tree, Token.Id.Keyword_or)) |or_token| {
1977 const node = try arena.create(ast.Node.InfixOp{2014 const node = try arena.create(ast.Node.InfixOp);
2015 node.* = ast.Node.InfixOp{
1978 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2016 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
1979 .lhs = lhs,2017 .lhs = lhs,
1980 .op_token = or_token,2018 .op_token = or_token,
1981 .op = ast.Node.InfixOp.Op.BoolOr,2019 .op = ast.Node.InfixOp.Op.BoolOr,
1982 .rhs = undefined,2020 .rhs = undefined,
1983 });2021 };
1984 opt_ctx.store(&node.base);2022 opt_ctx.store(&node.base);
1985 stack.append(State{ .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2023 stack.append(State{ .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
1986 try stack.append(State{ .BoolAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2024 try stack.append(State{ .BoolAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
...@@ -1998,13 +2036,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -1998,13 +2036,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
1998 const lhs = opt_ctx.get() orelse continue;2036 const lhs = opt_ctx.get() orelse continue;
19992037
2000 if (eatToken(&tok_it, &tree, Token.Id.Keyword_and)) |and_token| {2038 if (eatToken(&tok_it, &tree, Token.Id.Keyword_and)) |and_token| {
2001 const node = try arena.create(ast.Node.InfixOp{2039 const node = try arena.create(ast.Node.InfixOp);
2040 node.* = ast.Node.InfixOp{
2002 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2041 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2003 .lhs = lhs,2042 .lhs = lhs,
2004 .op_token = and_token,2043 .op_token = and_token,
2005 .op = ast.Node.InfixOp.Op.BoolAnd,2044 .op = ast.Node.InfixOp.Op.BoolAnd,
2006 .rhs = undefined,2045 .rhs = undefined,
2007 });2046 };
2008 opt_ctx.store(&node.base);2047 opt_ctx.store(&node.base);
2009 stack.append(State{ .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2048 stack.append(State{ .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2010 try stack.append(State{ .ComparisonExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2049 try stack.append(State{ .ComparisonExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
...@@ -2025,13 +2064,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2025,13 +2064,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2025 const token_index = token.index;2064 const token_index = token.index;
2026 const token_ptr = token.ptr;2065 const token_ptr = token.ptr;
2027 if (tokenIdToComparison(token_ptr.id)) |comp_id| {2066 if (tokenIdToComparison(token_ptr.id)) |comp_id| {
2028 const node = try arena.create(ast.Node.InfixOp{2067 const node = try arena.create(ast.Node.InfixOp);
2068 node.* = ast.Node.InfixOp{
2029 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2069 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2030 .lhs = lhs,2070 .lhs = lhs,
2031 .op_token = token_index,2071 .op_token = token_index,
2032 .op = comp_id,2072 .op = comp_id,
2033 .rhs = undefined,2073 .rhs = undefined,
2034 });2074 };
2035 opt_ctx.store(&node.base);2075 opt_ctx.store(&node.base);
2036 stack.append(State{ .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2076 stack.append(State{ .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2037 try stack.append(State{ .BinaryOrExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2077 try stack.append(State{ .BinaryOrExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
...@@ -2052,13 +2092,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2052,13 +2092,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2052 const lhs = opt_ctx.get() orelse continue;2092 const lhs = opt_ctx.get() orelse continue;
20532093
2054 if (eatToken(&tok_it, &tree, Token.Id.Pipe)) |pipe| {2094 if (eatToken(&tok_it, &tree, Token.Id.Pipe)) |pipe| {
2055 const node = try arena.create(ast.Node.InfixOp{2095 const node = try arena.create(ast.Node.InfixOp);
2096 node.* = ast.Node.InfixOp{
2056 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2097 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2057 .lhs = lhs,2098 .lhs = lhs,
2058 .op_token = pipe,2099 .op_token = pipe,
2059 .op = ast.Node.InfixOp.Op.BitOr,2100 .op = ast.Node.InfixOp.Op.BitOr,
2060 .rhs = undefined,2101 .rhs = undefined,
2061 });2102 };
2062 opt_ctx.store(&node.base);2103 opt_ctx.store(&node.base);
2063 stack.append(State{ .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2104 stack.append(State{ .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2064 try stack.append(State{ .BinaryXorExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2105 try stack.append(State{ .BinaryXorExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
...@@ -2076,13 +2117,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2076,13 +2117,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2076 const lhs = opt_ctx.get() orelse continue;2117 const lhs = opt_ctx.get() orelse continue;
20772118
2078 if (eatToken(&tok_it, &tree, Token.Id.Caret)) |caret| {2119 if (eatToken(&tok_it, &tree, Token.Id.Caret)) |caret| {
2079 const node = try arena.create(ast.Node.InfixOp{2120 const node = try arena.create(ast.Node.InfixOp);
2121 node.* = ast.Node.InfixOp{
2080 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2122 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2081 .lhs = lhs,2123 .lhs = lhs,
2082 .op_token = caret,2124 .op_token = caret,
2083 .op = ast.Node.InfixOp.Op.BitXor,2125 .op = ast.Node.InfixOp.Op.BitXor,
2084 .rhs = undefined,2126 .rhs = undefined,
2085 });2127 };
2086 opt_ctx.store(&node.base);2128 opt_ctx.store(&node.base);
2087 stack.append(State{ .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2129 stack.append(State{ .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2088 try stack.append(State{ .BinaryAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2130 try stack.append(State{ .BinaryAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
...@@ -2100,13 +2142,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2100,13 +2142,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2100 const lhs = opt_ctx.get() orelse continue;2142 const lhs = opt_ctx.get() orelse continue;
21012143
2102 if (eatToken(&tok_it, &tree, Token.Id.Ampersand)) |ampersand| {2144 if (eatToken(&tok_it, &tree, Token.Id.Ampersand)) |ampersand| {
2103 const node = try arena.create(ast.Node.InfixOp{2145 const node = try arena.create(ast.Node.InfixOp);
2146 node.* = ast.Node.InfixOp{
2104 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2147 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2105 .lhs = lhs,2148 .lhs = lhs,
2106 .op_token = ampersand,2149 .op_token = ampersand,
2107 .op = ast.Node.InfixOp.Op.BitAnd,2150 .op = ast.Node.InfixOp.Op.BitAnd,
2108 .rhs = undefined,2151 .rhs = undefined,
2109 });2152 };
2110 opt_ctx.store(&node.base);2153 opt_ctx.store(&node.base);
2111 stack.append(State{ .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2154 stack.append(State{ .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2112 try stack.append(State{ .BitShiftExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2155 try stack.append(State{ .BitShiftExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
...@@ -2127,13 +2170,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2127,13 +2170,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2127 const token_index = token.index;2170 const token_index = token.index;
2128 const token_ptr = token.ptr;2171 const token_ptr = token.ptr;
2129 if (tokenIdToBitShift(token_ptr.id)) |bitshift_id| {2172 if (tokenIdToBitShift(token_ptr.id)) |bitshift_id| {
2130 const node = try arena.create(ast.Node.InfixOp{2173 const node = try arena.create(ast.Node.InfixOp);
2174 node.* = ast.Node.InfixOp{
2131 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2175 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2132 .lhs = lhs,2176 .lhs = lhs,
2133 .op_token = token_index,2177 .op_token = token_index,
2134 .op = bitshift_id,2178 .op = bitshift_id,
2135 .rhs = undefined,2179 .rhs = undefined,
2136 });2180 };
2137 opt_ctx.store(&node.base);2181 opt_ctx.store(&node.base);
2138 stack.append(State{ .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2182 stack.append(State{ .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2139 try stack.append(State{ .AdditionExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2183 try stack.append(State{ .AdditionExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
...@@ -2157,13 +2201,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2157,13 +2201,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2157 const token_index = token.index;2201 const token_index = token.index;
2158 const token_ptr = token.ptr;2202 const token_ptr = token.ptr;
2159 if (tokenIdToAddition(token_ptr.id)) |add_id| {2203 if (tokenIdToAddition(token_ptr.id)) |add_id| {
2160 const node = try arena.create(ast.Node.InfixOp{2204 const node = try arena.create(ast.Node.InfixOp);
2205 node.* = ast.Node.InfixOp{
2161 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2206 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2162 .lhs = lhs,2207 .lhs = lhs,
2163 .op_token = token_index,2208 .op_token = token_index,
2164 .op = add_id,2209 .op = add_id,
2165 .rhs = undefined,2210 .rhs = undefined,
2166 });2211 };
2167 opt_ctx.store(&node.base);2212 opt_ctx.store(&node.base);
2168 stack.append(State{ .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2213 stack.append(State{ .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2169 try stack.append(State{ .MultiplyExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2214 try stack.append(State{ .MultiplyExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
...@@ -2187,13 +2232,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2187,13 +2232,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2187 const token_index = token.index;2232 const token_index = token.index;
2188 const token_ptr = token.ptr;2233 const token_ptr = token.ptr;
2189 if (tokenIdToMultiply(token_ptr.id)) |mult_id| {2234 if (tokenIdToMultiply(token_ptr.id)) |mult_id| {
2190 const node = try arena.create(ast.Node.InfixOp{2235 const node = try arena.create(ast.Node.InfixOp);
2236 node.* = ast.Node.InfixOp{
2191 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2237 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2192 .lhs = lhs,2238 .lhs = lhs,
2193 .op_token = token_index,2239 .op_token = token_index,
2194 .op = mult_id,2240 .op = mult_id,
2195 .rhs = undefined,2241 .rhs = undefined,
2196 });2242 };
2197 opt_ctx.store(&node.base);2243 opt_ctx.store(&node.base);
2198 stack.append(State{ .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2244 stack.append(State{ .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2199 try stack.append(State{ .CurlySuffixExpressionBegin = OptionalCtx{ .Required = &node.rhs } });2245 try stack.append(State{ .CurlySuffixExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
...@@ -2215,12 +2261,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2215,12 +2261,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2215 const lhs = opt_ctx.get() orelse continue;2261 const lhs = opt_ctx.get() orelse continue;
22162262
2217 if (tok_it.peek().?.id == Token.Id.Period) {2263 if (tok_it.peek().?.id == Token.Id.Period) {
2218 const node = try arena.create(ast.Node.SuffixOp{2264 const node = try arena.create(ast.Node.SuffixOp);
2265 node.* = ast.Node.SuffixOp{
2219 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },2266 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
2220 .lhs = lhs,2267 .lhs = lhs,
2221 .op = ast.Node.SuffixOp.Op{ .StructInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) },2268 .op = ast.Node.SuffixOp.Op{ .StructInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) },
2222 .rtoken = undefined,2269 .rtoken = undefined,
2223 });2270 };
2224 opt_ctx.store(&node.base);2271 opt_ctx.store(&node.base);
22252272
2226 stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2273 stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
...@@ -2234,12 +2281,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2234,12 +2281,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2234 continue;2281 continue;
2235 }2282 }
22362283
2237 const node = try arena.create(ast.Node.SuffixOp{2284 const node = try arena.create(ast.Node.SuffixOp);
2285 node.* = ast.Node.SuffixOp{
2238 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },2286 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
2239 .lhs = lhs,2287 .lhs = lhs,
2240 .op = ast.Node.SuffixOp.Op{ .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) },2288 .op = ast.Node.SuffixOp.Op{ .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) },
2241 .rtoken = undefined,2289 .rtoken = undefined,
2242 });2290 };
2243 opt_ctx.store(&node.base);2291 opt_ctx.store(&node.base);
2244 stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2292 stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2245 try stack.append(State{ .IfToken = Token.Id.LBrace });2293 try stack.append(State{ .IfToken = Token.Id.LBrace });
...@@ -2263,13 +2311,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2263,13 +2311,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2263 const lhs = opt_ctx.get() orelse continue;2311 const lhs = opt_ctx.get() orelse continue;
22642312
2265 if (eatToken(&tok_it, &tree, Token.Id.Bang)) |bang| {2313 if (eatToken(&tok_it, &tree, Token.Id.Bang)) |bang| {
2266 const node = try arena.create(ast.Node.InfixOp{2314 const node = try arena.create(ast.Node.InfixOp);
2315 node.* = ast.Node.InfixOp{
2267 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2316 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2268 .lhs = lhs,2317 .lhs = lhs,
2269 .op_token = bang,2318 .op_token = bang,
2270 .op = ast.Node.InfixOp.Op.ErrorUnion,2319 .op = ast.Node.InfixOp.Op.ErrorUnion,
2271 .rhs = undefined,2320 .rhs = undefined,
2272 });2321 };
2273 opt_ctx.store(&node.base);2322 opt_ctx.store(&node.base);
2274 stack.append(State{ .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable;2323 stack.append(State{ .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable;
2275 try stack.append(State{ .PrefixOpExpression = OptionalCtx{ .Required = &node.rhs } });2324 try stack.append(State{ .PrefixOpExpression = OptionalCtx{ .Required = &node.rhs } });
...@@ -2282,22 +2331,24 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2282,22 +2331,24 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2282 const token_index = token.index;2331 const token_index = token.index;
2283 const token_ptr = token.ptr;2332 const token_ptr = token.ptr;
2284 if (tokenIdToPrefixOp(token_ptr.id)) |prefix_id| {2333 if (tokenIdToPrefixOp(token_ptr.id)) |prefix_id| {
2285 var node = try arena.create(ast.Node.PrefixOp{2334 var node = try arena.create(ast.Node.PrefixOp);
2335 node.* = ast.Node.PrefixOp{
2286 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },2336 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
2287 .op_token = token_index,2337 .op_token = token_index,
2288 .op = prefix_id,2338 .op = prefix_id,
2289 .rhs = undefined,2339 .rhs = undefined,
2290 });2340 };
2291 opt_ctx.store(&node.base);2341 opt_ctx.store(&node.base);
22922342
2293 // Treat '**' token as two pointer types2343 // Treat '**' token as two pointer types
2294 if (token_ptr.id == Token.Id.AsteriskAsterisk) {2344 if (token_ptr.id == Token.Id.AsteriskAsterisk) {
2295 const child = try arena.create(ast.Node.PrefixOp{2345 const child = try arena.create(ast.Node.PrefixOp);
2346 child.* = ast.Node.PrefixOp{
2296 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },2347 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
2297 .op_token = token_index,2348 .op_token = token_index,
2298 .op = prefix_id,2349 .op = prefix_id,
2299 .rhs = undefined,2350 .rhs = undefined,
2300 });2351 };
2301 node.rhs = &child.base;2352 node.rhs = &child.base;
2302 node = child;2353 node = child;
2303 }2354 }
...@@ -2316,12 +2367,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2316,12 +2367,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
23162367
2317 State.SuffixOpExpressionBegin => |opt_ctx| {2368 State.SuffixOpExpressionBegin => |opt_ctx| {
2318 if (eatToken(&tok_it, &tree, Token.Id.Keyword_async)) |async_token| {2369 if (eatToken(&tok_it, &tree, Token.Id.Keyword_async)) |async_token| {
2319 const async_node = try arena.create(ast.Node.AsyncAttribute{2370 const async_node = try arena.create(ast.Node.AsyncAttribute);
2371 async_node.* = ast.Node.AsyncAttribute{
2320 .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },2372 .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },
2321 .async_token = async_token,2373 .async_token = async_token,
2322 .allocator_type = null,2374 .allocator_type = null,
2323 .rangle_bracket = null,2375 .rangle_bracket = null,
2324 });2376 };
2325 stack.append(State{2377 stack.append(State{
2326 .AsyncEnd = AsyncEndCtx{2378 .AsyncEnd = AsyncEndCtx{
2327 .ctx = opt_ctx,2379 .ctx = opt_ctx,
...@@ -2347,7 +2399,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2347,7 +2399,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2347 const token_ptr = token.ptr;2399 const token_ptr = token.ptr;
2348 switch (token_ptr.id) {2400 switch (token_ptr.id) {
2349 Token.Id.LParen => {2401 Token.Id.LParen => {
2350 const node = try arena.create(ast.Node.SuffixOp{2402 const node = try arena.create(ast.Node.SuffixOp);
2403 node.* = ast.Node.SuffixOp{
2351 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },2404 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
2352 .lhs = lhs,2405 .lhs = lhs,
2353 .op = ast.Node.SuffixOp.Op{2406 .op = ast.Node.SuffixOp.Op{
...@@ -2357,7 +2410,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2357,7 +2410,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2357 },2410 },
2358 },2411 },
2359 .rtoken = undefined,2412 .rtoken = undefined,
2360 });2413 };
2361 opt_ctx.store(&node.base);2414 opt_ctx.store(&node.base);
23622415
2363 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2416 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
...@@ -2371,12 +2424,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2371,12 +2424,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2371 continue;2424 continue;
2372 },2425 },
2373 Token.Id.LBracket => {2426 Token.Id.LBracket => {
2374 const node = try arena.create(ast.Node.SuffixOp{2427 const node = try arena.create(ast.Node.SuffixOp);
2428 node.* = ast.Node.SuffixOp{
2375 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },2429 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
2376 .lhs = lhs,2430 .lhs = lhs,
2377 .op = ast.Node.SuffixOp.Op{ .ArrayAccess = undefined },2431 .op = ast.Node.SuffixOp.Op{ .ArrayAccess = undefined },
2378 .rtoken = undefined,2432 .rtoken = undefined,
2379 });2433 };
2380 opt_ctx.store(&node.base);2434 opt_ctx.store(&node.base);
23812435
2382 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2436 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
...@@ -2386,34 +2440,37 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2386,34 +2440,37 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2386 },2440 },
2387 Token.Id.Period => {2441 Token.Id.Period => {
2388 if (eatToken(&tok_it, &tree, Token.Id.Asterisk)) |asterisk_token| {2442 if (eatToken(&tok_it, &tree, Token.Id.Asterisk)) |asterisk_token| {
2389 const node = try arena.create(ast.Node.SuffixOp{2443 const node = try arena.create(ast.Node.SuffixOp);
2444 node.* = ast.Node.SuffixOp{
2390 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },2445 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
2391 .lhs = lhs,2446 .lhs = lhs,
2392 .op = ast.Node.SuffixOp.Op.Deref,2447 .op = ast.Node.SuffixOp.Op.Deref,
2393 .rtoken = asterisk_token,2448 .rtoken = asterisk_token,
2394 });2449 };
2395 opt_ctx.store(&node.base);2450 opt_ctx.store(&node.base);
2396 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2451 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2397 continue;2452 continue;
2398 }2453 }
2399 if (eatToken(&tok_it, &tree, Token.Id.QuestionMark)) |question_token| {2454 if (eatToken(&tok_it, &tree, Token.Id.QuestionMark)) |question_token| {
2400 const node = try arena.create(ast.Node.SuffixOp{2455 const node = try arena.create(ast.Node.SuffixOp);
2456 node.* = ast.Node.SuffixOp{
2401 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },2457 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
2402 .lhs = lhs,2458 .lhs = lhs,
2403 .op = ast.Node.SuffixOp.Op.UnwrapOptional,2459 .op = ast.Node.SuffixOp.Op.UnwrapOptional,
2404 .rtoken = question_token,2460 .rtoken = question_token,
2405 });2461 };
2406 opt_ctx.store(&node.base);2462 opt_ctx.store(&node.base);
2407 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2463 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
2408 continue;2464 continue;
2409 }2465 }
2410 const node = try arena.create(ast.Node.InfixOp{2466 const node = try arena.create(ast.Node.InfixOp);
2467 node.* = ast.Node.InfixOp{
2411 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2468 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2412 .lhs = lhs,2469 .lhs = lhs,
2413 .op_token = token_index,2470 .op_token = token_index,
2414 .op = ast.Node.InfixOp.Op.Period,2471 .op = ast.Node.InfixOp.Op.Period,
2415 .rhs = undefined,2472 .rhs = undefined,
2416 });2473 };
2417 opt_ctx.store(&node.base);2474 opt_ctx.store(&node.base);
24182475
2419 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;2476 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
...@@ -2467,11 +2524,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2467,11 +2524,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2467 continue;2524 continue;
2468 },2525 },
2469 Token.Id.Keyword_promise => {2526 Token.Id.Keyword_promise => {
2470 const node = try arena.create(ast.Node.PromiseType{2527 const node = try arena.create(ast.Node.PromiseType);
2528 node.* = ast.Node.PromiseType{
2471 .base = ast.Node{ .id = ast.Node.Id.PromiseType },2529 .base = ast.Node{ .id = ast.Node.Id.PromiseType },
2472 .promise_token = token.index,2530 .promise_token = token.index,
2473 .result = null,2531 .result = null,
2474 });2532 };
2475 opt_ctx.store(&node.base);2533 opt_ctx.store(&node.base);
2476 const next_token = nextToken(&tok_it, &tree);2534 const next_token = nextToken(&tok_it, &tree);
2477 const next_token_index = next_token.index;2535 const next_token_index = next_token.index;
...@@ -2493,12 +2551,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2493,12 +2551,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2493 continue;2551 continue;
2494 },2552 },
2495 Token.Id.LParen => {2553 Token.Id.LParen => {
2496 const node = try arena.create(ast.Node.GroupedExpression{2554 const node = try arena.create(ast.Node.GroupedExpression);
2555 node.* = ast.Node.GroupedExpression{
2497 .base = ast.Node{ .id = ast.Node.Id.GroupedExpression },2556 .base = ast.Node{ .id = ast.Node.Id.GroupedExpression },
2498 .lparen = token.index,2557 .lparen = token.index,
2499 .expr = undefined,2558 .expr = undefined,
2500 .rparen = undefined,2559 .rparen = undefined,
2501 });2560 };
2502 opt_ctx.store(&node.base);2561 opt_ctx.store(&node.base);
25032562
2504 stack.append(State{2563 stack.append(State{
...@@ -2511,12 +2570,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2511,12 +2570,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2511 continue;2570 continue;
2512 },2571 },
2513 Token.Id.Builtin => {2572 Token.Id.Builtin => {
2514 const node = try arena.create(ast.Node.BuiltinCall{2573 const node = try arena.create(ast.Node.BuiltinCall);
2574 node.* = ast.Node.BuiltinCall{
2515 .base = ast.Node{ .id = ast.Node.Id.BuiltinCall },2575 .base = ast.Node{ .id = ast.Node.Id.BuiltinCall },
2516 .builtin_token = token.index,2576 .builtin_token = token.index,
2517 .params = ast.Node.BuiltinCall.ParamList.init(arena),2577 .params = ast.Node.BuiltinCall.ParamList.init(arena),
2518 .rparen_token = undefined,2578 .rparen_token = undefined,
2519 });2579 };
2520 opt_ctx.store(&node.base);2580 opt_ctx.store(&node.base);
25212581
2522 stack.append(State{2582 stack.append(State{
...@@ -2530,12 +2590,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2530,12 +2590,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2530 continue;2590 continue;
2531 },2591 },
2532 Token.Id.LBracket => {2592 Token.Id.LBracket => {
2533 const node = try arena.create(ast.Node.PrefixOp{2593 const node = try arena.create(ast.Node.PrefixOp);
2594 node.* = ast.Node.PrefixOp{
2534 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },2595 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
2535 .op_token = token.index,2596 .op_token = token.index,
2536 .op = undefined,2597 .op = undefined,
2537 .rhs = undefined,2598 .rhs = undefined,
2538 });2599 };
2539 opt_ctx.store(&node.base);2600 opt_ctx.store(&node.base);
25402601
2541 stack.append(State{ .SliceOrArrayType = node }) catch unreachable;2602 stack.append(State{ .SliceOrArrayType = node }) catch unreachable;
...@@ -2593,7 +2654,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2593,7 +2654,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2593 continue;2654 continue;
2594 },2655 },
2595 Token.Id.Keyword_fn => {2656 Token.Id.Keyword_fn => {
2596 const fn_proto = try arena.create(ast.Node.FnProto{2657 const fn_proto = try arena.create(ast.Node.FnProto);
2658 fn_proto.* = ast.Node.FnProto{
2597 .base = ast.Node{ .id = ast.Node.Id.FnProto },2659 .base = ast.Node{ .id = ast.Node.Id.FnProto },
2598 .doc_comments = null,2660 .doc_comments = null,
2599 .visib_token = null,2661 .visib_token = null,
...@@ -2609,13 +2671,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2609,13 +2671,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2609 .lib_name = null,2671 .lib_name = null,
2610 .align_expr = null,2672 .align_expr = null,
2611 .section_expr = null,2673 .section_expr = null,
2612 });2674 };
2613 opt_ctx.store(&fn_proto.base);2675 opt_ctx.store(&fn_proto.base);
2614 stack.append(State{ .FnProto = fn_proto }) catch unreachable;2676 stack.append(State{ .FnProto = fn_proto }) catch unreachable;
2615 continue;2677 continue;
2616 },2678 },
2617 Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {2679 Token.Id.Keyword_nakedcc, Token.Id.Keyword_stdcallcc => {
2618 const fn_proto = try arena.create(ast.Node.FnProto{2680 const fn_proto = try arena.create(ast.Node.FnProto);
2681 fn_proto.* = ast.Node.FnProto{
2619 .base = ast.Node{ .id = ast.Node.Id.FnProto },2682 .base = ast.Node{ .id = ast.Node.Id.FnProto },
2620 .doc_comments = null,2683 .doc_comments = null,
2621 .visib_token = null,2684 .visib_token = null,
...@@ -2631,7 +2694,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2631,7 +2694,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2631 .lib_name = null,2694 .lib_name = null,
2632 .align_expr = null,2695 .align_expr = null,
2633 .section_expr = null,2696 .section_expr = null,
2634 });2697 };
2635 opt_ctx.store(&fn_proto.base);2698 opt_ctx.store(&fn_proto.base);
2636 stack.append(State{ .FnProto = fn_proto }) catch unreachable;2699 stack.append(State{ .FnProto = fn_proto }) catch unreachable;
2637 try stack.append(State{2700 try stack.append(State{
...@@ -2643,7 +2706,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2643,7 +2706,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2643 continue;2706 continue;
2644 },2707 },
2645 Token.Id.Keyword_asm => {2708 Token.Id.Keyword_asm => {
2646 const node = try arena.create(ast.Node.Asm{2709 const node = try arena.create(ast.Node.Asm);
2710 node.* = ast.Node.Asm{
2647 .base = ast.Node{ .id = ast.Node.Id.Asm },2711 .base = ast.Node{ .id = ast.Node.Id.Asm },
2648 .asm_token = token.index,2712 .asm_token = token.index,
2649 .volatile_token = null,2713 .volatile_token = null,
...@@ -2652,7 +2716,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2652,7 +2716,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2652 .inputs = ast.Node.Asm.InputList.init(arena),2716 .inputs = ast.Node.Asm.InputList.init(arena),
2653 .clobbers = ast.Node.Asm.ClobberList.init(arena),2717 .clobbers = ast.Node.Asm.ClobberList.init(arena),
2654 .rparen = undefined,2718 .rparen = undefined,
2655 });2719 };
2656 opt_ctx.store(&node.base);2720 opt_ctx.store(&node.base);
26572721
2658 stack.append(State{2722 stack.append(State{
...@@ -2701,13 +2765,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2701,13 +2765,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
27012765
2702 State.ErrorTypeOrSetDecl => |ctx| {2766 State.ErrorTypeOrSetDecl => |ctx| {
2703 if (eatToken(&tok_it, &tree, Token.Id.LBrace) == null) {2767 if (eatToken(&tok_it, &tree, Token.Id.LBrace) == null) {
2704 const node = try arena.create(ast.Node.InfixOp{2768 const node = try arena.create(ast.Node.InfixOp);
2769 node.* = ast.Node.InfixOp{
2705 .base = ast.Node{ .id = ast.Node.Id.InfixOp },2770 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
2706 .lhs = &(try createLiteral(arena, ast.Node.ErrorType, ctx.error_token)).base,2771 .lhs = &(try createLiteral(arena, ast.Node.ErrorType, ctx.error_token)).base,
2707 .op_token = undefined,2772 .op_token = undefined,
2708 .op = ast.Node.InfixOp.Op.Period,2773 .op = ast.Node.InfixOp.Op.Period,
2709 .rhs = undefined,2774 .rhs = undefined,
2710 });2775 };
2711 ctx.opt_ctx.store(&node.base);2776 ctx.opt_ctx.store(&node.base);
2712 stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;2777 stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
2713 try stack.append(State{2778 try stack.append(State{
...@@ -2719,12 +2784,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2719,12 +2784,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2719 continue;2784 continue;
2720 }2785 }
27212786
2722 const node = try arena.create(ast.Node.ErrorSetDecl{2787 const node = try arena.create(ast.Node.ErrorSetDecl);
2788 node.* = ast.Node.ErrorSetDecl{
2723 .base = ast.Node{ .id = ast.Node.Id.ErrorSetDecl },2789 .base = ast.Node{ .id = ast.Node.Id.ErrorSetDecl },
2724 .error_token = ctx.error_token,2790 .error_token = ctx.error_token,
2725 .decls = ast.Node.ErrorSetDecl.DeclList.init(arena),2791 .decls = ast.Node.ErrorSetDecl.DeclList.init(arena),
2726 .rbrace_token = undefined,2792 .rbrace_token = undefined,
2727 });2793 };
2728 ctx.opt_ctx.store(&node.base);2794 ctx.opt_ctx.store(&node.base);
27292795
2730 stack.append(State{2796 stack.append(State{
...@@ -2785,11 +2851,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {...@@ -2785,11 +2851,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
2785 return tree;2851 return tree;
2786 }2852 }
27872853
2788 const node = try arena.create(ast.Node.ErrorTag{2854 const node = try arena.create(ast.Node.ErrorTag);
2855 node.* = ast.Node.ErrorTag{
2789 .base = ast.Node{ .id = ast.Node.Id.ErrorTag },2856 .base = ast.Node{ .id = ast.Node.Id.ErrorTag },
2790 .doc_comments = comments,2857 .doc_comments = comments,
2791 .name_token = ident_token_index,2858 .name_token = ident_token_index,
2792 });2859 };
2793 node_ptr.* = &node.base;2860 node_ptr.* = &node.base;
2794 continue;2861 continue;
2795 },2862 },
...@@ -3129,10 +3196,11 @@ fn pushDocComment(arena: *mem.Allocator, line_comment: TokenIndex, result: *?*as...@@ -3129,10 +3196,11 @@ fn pushDocComment(arena: *mem.Allocator, line_comment: TokenIndex, result: *?*as
3129 if (result.*) |comment_node| {3196 if (result.*) |comment_node| {
3130 break :blk comment_node;3197 break :blk comment_node;
3131 } else {3198 } else {
3132 const comment_node = try arena.create(ast.Node.DocComment{3199 const comment_node = try arena.create(ast.Node.DocComment);
3200 comment_node.* = ast.Node.DocComment{
3133 .base = ast.Node{ .id = ast.Node.Id.DocComment },3201 .base = ast.Node{ .id = ast.Node.Id.DocComment },
3134 .lines = ast.Node.DocComment.LineList.init(arena),3202 .lines = ast.Node.DocComment.LineList.init(arena),
3135 });3203 };
3136 result.* = comment_node;3204 result.* = comment_node;
3137 break :blk comment_node;3205 break :blk comment_node;
3138 }3206 }
...@@ -3158,10 +3226,11 @@ fn parseStringLiteral(arena: *mem.Allocator, tok_it: *ast.Tree.TokenList.Iterato...@@ -3158,10 +3226,11 @@ fn parseStringLiteral(arena: *mem.Allocator, tok_it: *ast.Tree.TokenList.Iterato
3158 return &(try createLiteral(arena, ast.Node.StringLiteral, token_index)).base;3226 return &(try createLiteral(arena, ast.Node.StringLiteral, token_index)).base;
3159 },3227 },
3160 Token.Id.MultilineStringLiteralLine => {3228 Token.Id.MultilineStringLiteralLine => {
3161 const node = try arena.create(ast.Node.MultilineStringLiteral{3229 const node = try arena.create(ast.Node.MultilineStringLiteral);
3230 node.* = ast.Node.MultilineStringLiteral{
3162 .base = ast.Node{ .id = ast.Node.Id.MultilineStringLiteral },3231 .base = ast.Node{ .id = ast.Node.Id.MultilineStringLiteral },
3163 .lines = ast.Node.MultilineStringLiteral.LineList.init(arena),3232 .lines = ast.Node.MultilineStringLiteral.LineList.init(arena),
3164 });3233 };
3165 try node.lines.push(token_index);3234 try node.lines.push(token_index);
3166 while (true) {3235 while (true) {
3167 const multiline_str = nextToken(tok_it, tree);3236 const multiline_str = nextToken(tok_it, tree);
...@@ -3186,25 +3255,27 @@ fn parseStringLiteral(arena: *mem.Allocator, tok_it: *ast.Tree.TokenList.Iterato...@@ -3186,25 +3255,27 @@ fn parseStringLiteral(arena: *mem.Allocator, tok_it: *ast.Tree.TokenList.Iterato
3186fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: OptionalCtx, token_ptr: Token, token_index: TokenIndex) !bool {3255fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: OptionalCtx, token_ptr: Token, token_index: TokenIndex) !bool {
3187 switch (token_ptr.id) {3256 switch (token_ptr.id) {
3188 Token.Id.Keyword_suspend => {3257 Token.Id.Keyword_suspend => {
3189 const node = try arena.create(ast.Node.Suspend{3258 const node = try arena.create(ast.Node.Suspend);
3259 node.* = ast.Node.Suspend{
3190 .base = ast.Node{ .id = ast.Node.Id.Suspend },3260 .base = ast.Node{ .id = ast.Node.Id.Suspend },
3191 .suspend_token = token_index,3261 .suspend_token = token_index,
3192 .body = null,3262 .body = null,
3193 });3263 };
3194 ctx.store(&node.base);3264 ctx.store(&node.base);
31953265
3196 stack.append(State{ .SuspendBody = node }) catch unreachable;3266 stack.append(State{ .SuspendBody = node }) catch unreachable;
3197 return true;3267 return true;
3198 },3268 },
3199 Token.Id.Keyword_if => {3269 Token.Id.Keyword_if => {
3200 const node = try arena.create(ast.Node.If{3270 const node = try arena.create(ast.Node.If);
3271 node.* = ast.Node.If{
3201 .base = ast.Node{ .id = ast.Node.Id.If },3272 .base = ast.Node{ .id = ast.Node.Id.If },
3202 .if_token = token_index,3273 .if_token = token_index,
3203 .condition = undefined,3274 .condition = undefined,
3204 .payload = null,3275 .payload = null,
3205 .body = undefined,3276 .body = undefined,
3206 .@"else" = null,3277 .@"else" = null,
3207 });3278 };
3208 ctx.store(&node.base);3279 ctx.store(&node.base);
32093280
3210 stack.append(State{ .Else = &node.@"else" }) catch unreachable;3281 stack.append(State{ .Else = &node.@"else" }) catch unreachable;
...@@ -3238,13 +3309,14 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: Opti...@@ -3238,13 +3309,14 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: Opti
3238 return true;3309 return true;
3239 },3310 },
3240 Token.Id.Keyword_switch => {3311 Token.Id.Keyword_switch => {
3241 const node = try arena.create(ast.Node.Switch{3312 const node = try arena.create(ast.Node.Switch);
3313 node.* = ast.Node.Switch{
3242 .base = ast.Node{ .id = ast.Node.Id.Switch },3314 .base = ast.Node{ .id = ast.Node.Id.Switch },
3243 .switch_token = token_index,3315 .switch_token = token_index,
3244 .expr = undefined,3316 .expr = undefined,
3245 .cases = ast.Node.Switch.CaseList.init(arena),3317 .cases = ast.Node.Switch.CaseList.init(arena),
3246 .rbrace = undefined,3318 .rbrace = undefined,
3247 });3319 };
3248 ctx.store(&node.base);3320 ctx.store(&node.base);
32493321
3250 stack.append(State{3322 stack.append(State{
...@@ -3260,25 +3332,27 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: Opti...@@ -3260,25 +3332,27 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: Opti
3260 return true;3332 return true;
3261 },3333 },
3262 Token.Id.Keyword_comptime => {3334 Token.Id.Keyword_comptime => {
3263 const node = try arena.create(ast.Node.Comptime{3335 const node = try arena.create(ast.Node.Comptime);
3336 node.* = ast.Node.Comptime{
3264 .base = ast.Node{ .id = ast.Node.Id.Comptime },3337 .base = ast.Node{ .id = ast.Node.Id.Comptime },
3265 .comptime_token = token_index,3338 .comptime_token = token_index,
3266 .expr = undefined,3339 .expr = undefined,
3267 .doc_comments = null,3340 .doc_comments = null,
3268 });3341 };
3269 ctx.store(&node.base);3342 ctx.store(&node.base);
32703343
3271 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } });3344 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } });
3272 return true;3345 return true;
3273 },3346 },
3274 Token.Id.LBrace => {3347 Token.Id.LBrace => {
3275 const block = try arena.create(ast.Node.Block{3348 const block = try arena.create(ast.Node.Block);
3349 block.* = ast.Node.Block{
3276 .base = ast.Node{ .id = ast.Node.Id.Block },3350 .base = ast.Node{ .id = ast.Node.Id.Block },
3277 .label = null,3351 .label = null,
3278 .lbrace = token_index,3352 .lbrace = token_index,
3279 .statements = ast.Node.Block.StatementList.init(arena),3353 .statements = ast.Node.Block.StatementList.init(arena),
3280 .rbrace = undefined,3354 .rbrace = undefined,
3281 });3355 };
3282 ctx.store(&block.base);3356 ctx.store(&block.base);
3283 stack.append(State{ .Block = block }) catch unreachable;3357 stack.append(State{ .Block = block }) catch unreachable;
3284 return true;3358 return true;
...@@ -3412,10 +3486,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {...@@ -3412,10 +3486,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {
3412}3486}
34133487
3414fn createLiteral(arena: *mem.Allocator, comptime T: type, token_index: TokenIndex) !*T {3488fn createLiteral(arena: *mem.Allocator, comptime T: type, token_index: TokenIndex) !*T {
3415 return arena.create(T{3489 const result = try arena.create(T);
3490 result.* = T{
3416 .base = ast.Node{ .id = ast.Node.typeToId(T) },3491 .base = ast.Node{ .id = ast.Node.typeToId(T) },
3417 .token = token_index,3492 .token = token_index,
3418 });3493 };
3494 return result;
3419}3495}
34203496
3421fn createToCtxLiteral(arena: *mem.Allocator, opt_ctx: OptionalCtx, comptime T: type, token_index: TokenIndex) !*T {3497fn createToCtxLiteral(arena: *mem.Allocator, opt_ctx: OptionalCtx, comptime T: type, token_index: TokenIndex) !*T {
test/behavior.zig deleted-82
...@@ -1,82 +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/bswap.zig");
12 _ = @import("cases/bitreverse.zig");
13 _ = @import("cases/bugs/1076.zig");
14 _ = @import("cases/bugs/1111.zig");
15 _ = @import("cases/bugs/1277.zig");
16 _ = @import("cases/bugs/1322.zig");
17 _ = @import("cases/bugs/1381.zig");
18 _ = @import("cases/bugs/1421.zig");
19 _ = @import("cases/bugs/1442.zig");
20 _ = @import("cases/bugs/1486.zig");
21 _ = @import("cases/bugs/394.zig");
22 _ = @import("cases/bugs/655.zig");
23 _ = @import("cases/bugs/656.zig");
24 _ = @import("cases/bugs/726.zig");
25 _ = @import("cases/bugs/828.zig");
26 _ = @import("cases/bugs/920.zig");
27 _ = @import("cases/byval_arg_var.zig");
28 _ = @import("cases/cancel.zig");
29 _ = @import("cases/cast.zig");
30 _ = @import("cases/const_slice_child.zig");
31 _ = @import("cases/coroutine_await_struct.zig");
32 _ = @import("cases/coroutines.zig");
33 _ = @import("cases/defer.zig");
34 _ = @import("cases/enum.zig");
35 _ = @import("cases/enum_with_members.zig");
36 _ = @import("cases/error.zig");
37 _ = @import("cases/eval.zig");
38 _ = @import("cases/field_parent_ptr.zig");
39 _ = @import("cases/fn.zig");
40 _ = @import("cases/fn_in_struct_in_comptime.zig");
41 _ = @import("cases/for.zig");
42 _ = @import("cases/generics.zig");
43 _ = @import("cases/if.zig");
44 _ = @import("cases/import.zig");
45 _ = @import("cases/incomplete_struct_param_tld.zig");
46 _ = @import("cases/inttoptr.zig");
47 _ = @import("cases/ir_block_deps.zig");
48 _ = @import("cases/math.zig");
49 _ = @import("cases/merge_error_sets.zig");
50 _ = @import("cases/misc.zig");
51 _ = @import("cases/namespace_depends_on_compile_var/index.zig");
52 _ = @import("cases/new_stack_call.zig");
53 _ = @import("cases/null.zig");
54 _ = @import("cases/optional.zig");
55 _ = @import("cases/pointers.zig");
56 _ = @import("cases/popcount.zig");
57 _ = @import("cases/ptrcast.zig");
58 _ = @import("cases/pub_enum/index.zig");
59 _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig");
60 _ = @import("cases/reflection.zig");
61 _ = @import("cases/sizeof_and_typeof.zig");
62 _ = @import("cases/slice.zig");
63 _ = @import("cases/struct.zig");
64 _ = @import("cases/struct_contains_null_ptr_itself.zig");
65 _ = @import("cases/struct_contains_slice_of_itself.zig");
66 _ = @import("cases/switch.zig");
67 _ = @import("cases/switch_prong_err_enum.zig");
68 _ = @import("cases/switch_prong_implicit_cast.zig");
69 _ = @import("cases/syntax.zig");
70 _ = @import("cases/this.zig");
71 _ = @import("cases/truncate.zig");
72 _ = @import("cases/try.zig");
73 _ = @import("cases/type_info.zig");
74 _ = @import("cases/undefined.zig");
75 _ = @import("cases/underscore.zig");
76 _ = @import("cases/union.zig");
77 _ = @import("cases/var_args.zig");
78 _ = @import("cases/void.zig");
79 _ = @import("cases/while.zig");
80 _ = @import("cases/widening.zig");
81 _ = @import("cases/bit_shifting.zig");
82}
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/bitreverse.zig deleted-81
...@@ -1,81 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const minInt = std.math.minInt;
4
5test "@bitreverse" {
6 comptime testBitReverse();
7 testBitReverse();
8}
9
10fn testBitReverse() void {
11 // using comptime_ints, unsigned
12 assert(@bitreverse(u0, 0) == 0);
13 assert(@bitreverse(u5, 0x12) == 0x9);
14 assert(@bitreverse(u8, 0x12) == 0x48);
15 assert(@bitreverse(u16, 0x1234) == 0x2c48);
16 assert(@bitreverse(u24, 0x123456) == 0x6a2c48);
17 assert(@bitreverse(u32, 0x12345678) == 0x1e6a2c48);
18 assert(@bitreverse(u40, 0x123456789a) == 0x591e6a2c48);
19 assert(@bitreverse(u48, 0x123456789abc) == 0x3d591e6a2c48);
20 assert(@bitreverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48);
21 assert(@bitreverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48);
22 assert(@bitreverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48);
23
24 // using runtime uints, unsigned
25 var num0: u0 = 0;
26 assert(@bitreverse(u0, num0) == 0);
27 var num5: u5 = 0x12;
28 assert(@bitreverse(u5, num5) == 0x9);
29 var num8: u8 = 0x12;
30 assert(@bitreverse(u8, num8) == 0x48);
31 var num16: u16 = 0x1234;
32 assert(@bitreverse(u16, num16) == 0x2c48);
33 var num24: u24 = 0x123456;
34 assert(@bitreverse(u24, num24) == 0x6a2c48);
35 var num32: u32 = 0x12345678;
36 assert(@bitreverse(u32, num32) == 0x1e6a2c48);
37 var num40: u40 = 0x123456789a;
38 assert(@bitreverse(u40, num40) == 0x591e6a2c48);
39 var num48: u48 = 0x123456789abc;
40 assert(@bitreverse(u48, num48) == 0x3d591e6a2c48);
41 var num56: u56 = 0x123456789abcde;
42 assert(@bitreverse(u56, num56) == 0x7b3d591e6a2c48);
43 var num64: u64 = 0x123456789abcdef1;
44 assert(@bitreverse(u64, num64) == 0x8f7b3d591e6a2c48);
45 var num128: u128 = 0x123456789abcdef11121314151617181;
46 assert(@bitreverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48);
47
48 // using comptime_ints, signed, positive
49 assert(@bitreverse(i0, 0) == 0);
50 assert(@bitreverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8( 0x49)));
51 assert(@bitreverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16( 0x2c48)));
52 assert(@bitreverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24( 0x6a2c48)));
53 assert(@bitreverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32( 0x1e6a2c48)));
54 assert(@bitreverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40( 0x591e6a2c48)));
55 assert(@bitreverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48( 0x3d591e6a2c48)));
56 assert(@bitreverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56( 0x7b3d591e6a2c48)));
57 assert(@bitreverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64,u64(0x8f7b3d591e6a2c48)));
58 assert(@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 assert(@bitreverse(i5, minInt(i5) + 1) == @bitreverse(i5, neg5));
63 var neg8: i8 = -18;
64 assert(@bitreverse(i8, -18) == @bitreverse(i8, neg8));
65 var neg16: i16 = -32694;
66 assert(@bitreverse(i16, -32694) == @bitreverse(i16, neg16));
67 var neg24: i24 = -6773785;
68 assert(@bitreverse(i24, -6773785) == @bitreverse(i24, neg24));
69 var neg32: i32 = -16773785;
70 assert(@bitreverse(i32, -16773785) == @bitreverse(i32, neg32));
71 var neg40: i40 = minInt(i40) + 12345;
72 assert(@bitreverse(i40, minInt(i40) + 12345) == @bitreverse(i40, neg40));
73 var neg48: i48 = minInt(i48) + 12345;
74 assert(@bitreverse(i48, minInt(i48) + 12345) == @bitreverse(i48, neg48));
75 var neg56: i56 = minInt(i56) + 12345;
76 assert(@bitreverse(i56, minInt(i56) + 12345) == @bitreverse(i56, neg56));
77 var neg64: i64 = minInt(i64) + 12345;
78 assert(@bitreverse(i64, minInt(i64) + 12345) == @bitreverse(i64, neg64));
79 var neg128: i128 = minInt(i128) + 12345;
80 assert(@bitreverse(i128, minInt(i128) + 12345) == @bitreverse(i128, neg128));
81}
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/bswap.zig deleted-32
...@@ -1,32 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4test "@bswap" {
5 comptime testByteSwap();
6 testByteSwap();
7}
8
9fn testByteSwap() void {
10 assert(@bswap(u0, 0) == 0);
11 assert(@bswap(u8, 0x12) == 0x12);
12 assert(@bswap(u16, 0x1234) == 0x3412);
13 assert(@bswap(u24, 0x123456) == 0x563412);
14 assert(@bswap(u32, 0x12345678) == 0x78563412);
15 assert(@bswap(u40, 0x123456789a) == 0x9a78563412);
16 assert(@bswap(u48, 0x123456789abc) == 0xbc9a78563412);
17 assert(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412);
18 assert(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412);
19 assert(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412);
20
21 assert(@bswap(i0, 0) == 0);
22 assert(@bswap(i8, -50) == -50);
23 assert(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412)));
24 assert(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412)));
25 assert(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412)));
26 assert(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412)));
27 assert(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412)));
28 assert(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412)));
29 assert(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412)));
30 assert(@bswap(i128, @bitCast(i128, u128(0x123456789abcdef11121314151617181))) ==
31 @bitCast(i128, u128(0x8171615141312111f1debc9a78563412)));
32}
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/inttoptr.zig deleted-27
...@@ -1,27 +0,0 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const assertOrPanic = std.debug.assertOrPanic;
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}
27
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/ptrcast.zig deleted-52
...@@ -1,52 +0,0 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic(@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 assertOrPanic(val == 5);
36}
37
38test "reinterpret struct field at comptime" {
39 const numLittle = comptime Bytes.init(0x12345678);
40 assertOrPanic(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/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-85
...@@ -1,85 +0,0 @@
1const assert = @import("std").debug.assert;
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 assert(root.payload == 1234);
43 assert(root.children[0].payload == 1);
44 assert(root.children[1].payload == 2);
45 assert(root.children[2].payload == 3);
46 assert(root.children[2].children[0].payload == 31);
47 assert(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 assert(root.payload == 1234);
80 assert(root.children[0].payload == 1);
81 assert(root.children[1].payload == 2);
82 assert(root.children[2].payload == 3);
83 assert(root.children[2].children[0].payload == 31);
84 assert(root.children[2].children[1].payload == 32);
85}
test/cases/switch.zig deleted-271
...@@ -1,271 +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}
235
236test "switching on booleans" {
237 testSwitchOnBools();
238 comptime testSwitchOnBools();
239}
240
241fn testSwitchOnBools() void {
242 assert(testSwitchOnBoolsTrueAndFalse(true) == false);
243 assert(testSwitchOnBoolsTrueAndFalse(false) == true);
244
245 assert(testSwitchOnBoolsTrueWithElse(true) == false);
246 assert(testSwitchOnBoolsTrueWithElse(false) == true);
247
248 assert(testSwitchOnBoolsFalseWithElse(true) == false);
249 assert(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/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/truncate.zig deleted-8
...@@ -1,8 +0,0 @@
1const std = @import("std");
2const assert = std.debug.assert;
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 assert(y == 0);
8}
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-264
...@@ -1,264 +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 = enum {
148 Windows,
149 Macos,
150 Linux,
151 FreeBSD,
152 };
153
154 const os_info = @typeInfo(Os);
155 assert(TypeId(os_info) == TypeId.Enum);
156 assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
157 assert(os_info.Enum.fields.len == 4);
158 assert(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
159 assert(os_info.Enum.fields[3].value == 3);
160 assert(os_info.Enum.tag_type == u2);
161 assert(os_info.Enum.defs.len == 0);
162}
163
164test "type info: union info" {
165 testUnion();
166 comptime testUnion();
167}
168
169fn testUnion() void {
170 const typeinfo_info = @typeInfo(TypeInfo);
171 assert(TypeId(typeinfo_info) == TypeId.Union);
172 assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
173 assert(typeinfo_info.Union.tag_type.? == TypeId);
174 assert(typeinfo_info.Union.fields.len == 24);
175 assert(typeinfo_info.Union.fields[4].enum_field != null);
176 assert(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
177 assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
178 assert(typeinfo_info.Union.defs.len == 20);
179
180 const TestNoTagUnion = union {
181 Foo: void,
182 Bar: u32,
183 };
184
185 const notag_union_info = @typeInfo(TestNoTagUnion);
186 assert(TypeId(notag_union_info) == TypeId.Union);
187 assert(notag_union_info.Union.tag_type == null);
188 assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
189 assert(notag_union_info.Union.fields.len == 2);
190 assert(notag_union_info.Union.fields[0].enum_field == null);
191 assert(notag_union_info.Union.fields[1].field_type == u32);
192
193 const TestExternUnion = extern union {
194 foo: *c_void,
195 };
196
197 const extern_union_info = @typeInfo(TestExternUnion);
198 assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
199 assert(extern_union_info.Union.tag_type == null);
200 assert(extern_union_info.Union.fields[0].enum_field == null);
201 assert(extern_union_info.Union.fields[0].field_type == *c_void);
202}
203
204test "type info: struct info" {
205 testStruct();
206 comptime testStruct();
207}
208
209fn testStruct() void {
210 const struct_info = @typeInfo(TestStruct);
211 assert(TypeId(struct_info) == TypeId.Struct);
212 assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
213 assert(struct_info.Struct.fields.len == 3);
214 assert(struct_info.Struct.fields[1].offset == null);
215 assert(struct_info.Struct.fields[2].field_type == *TestStruct);
216 assert(struct_info.Struct.defs.len == 2);
217 assert(struct_info.Struct.defs[0].is_pub);
218 assert(!struct_info.Struct.defs[0].data.Fn.is_extern);
219 assert(struct_info.Struct.defs[0].data.Fn.lib_name == null);
220 assert(struct_info.Struct.defs[0].data.Fn.return_type == void);
221 assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void);
222}
223
224const TestStruct = packed struct {
225 const Self = @This();
226
227 fieldA: usize,
228 fieldB: void,
229 fieldC: *Self,
230
231 pub fn foo(self: *const Self) void {}
232};
233
234test "type info: function type info" {
235 testFunction();
236 comptime testFunction();
237}
238
239fn testFunction() void {
240 const fn_info = @typeInfo(@typeOf(foo));
241 assert(TypeId(fn_info) == TypeId.Fn);
242 assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
243 assert(fn_info.Fn.is_generic);
244 assert(fn_info.Fn.args.len == 2);
245 assert(fn_info.Fn.is_var_args);
246 assert(fn_info.Fn.return_type == null);
247 assert(fn_info.Fn.async_allocator_type == null);
248
249 const test_instance: TestStruct = undefined;
250 const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
251 assert(TypeId(bound_fn_info) == TypeId.BoundFn);
252 assert(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
253}
254
255fn foo(comptime a: usize, b: bool, args: ...) usize {
256 return 0;
257}
258
259test "typeInfo with comptime parameter in struct fn def" {
260 const S = struct {
261 pub fn func(comptime x: f32) void {}
262 };
263 comptime var info = @typeInfo(S);
264}
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/compile_errors.zig+69-5
...@@ -1,6 +1,40 @@...@@ -1,6 +1,40 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
22
3pub fn addCases(cases: *tests.CompileErrorContext) void {3pub fn addCases(cases: *tests.CompileErrorContext) void {
4 cases.add(
5 "@bitCast same size but bit count mismatch",
6 \\export fn entry(byte: u8) void {
7 \\ var oops = @bitCast(u7, byte);
8 \\}
9 ,
10 ".tmp_source.zig:2:16: error: destination type 'u7' has 7 bits but source type 'u8' has 8 bits",
11 );
12
13 cases.add(
14 "attempted `&&`",
15 \\export fn entry(a: bool, b: bool) i32 {
16 \\ if (a && b) {
17 \\ return 1234;
18 \\ }
19 \\ return 5678;
20 \\}
21 ,
22 ".tmp_source.zig:2:12: error: `&&` is invalid. Note that `and` is boolean AND.",
23 );
24
25 cases.add(
26 "attempted `||` on boolean values",
27 \\export fn entry(a: bool, b: bool) i32 {
28 \\ if (a || b) {
29 \\ return 1234;
30 \\ }
31 \\ return 5678;
32 \\}
33 ,
34 ".tmp_source.zig:2:9: error: expected error set type, found 'bool'",
35 ".tmp_source.zig:2:11: note: `||` merges error sets; `or` performs boolean OR",
36 );
37
4 cases.add(38 cases.add(
5 "compile log a pointer to an opaque value",39 "compile log a pointer to an opaque value",
6 \\export fn entry() void {40 \\export fn entry() void {
...@@ -267,8 +301,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -267,8 +301,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
267 \\ const Errors = error{} || u16;301 \\ const Errors = error{} || u16;
268 \\}302 \\}
269 ,303 ,
270 ".tmp_source.zig:2:20: error: expected error set type, found 'u8'",304 ".tmp_source.zig:2:20: error: expected error set type, found type 'u8'",
271 ".tmp_source.zig:5:31: error: expected error set type, found 'u16'",305 ".tmp_source.zig:2:23: note: `||` merges error sets; `or` performs boolean OR",
306 ".tmp_source.zig:5:31: error: expected error set type, found type 'u16'",
307 ".tmp_source.zig:5:28: note: `||` merges error sets; `or` performs boolean OR",
272 );308 );
273309
274 cases.add(310 cases.add(
...@@ -2618,7 +2654,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2618,7 +2654,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2618 \\2654 \\
2619 \\export fn entry() usize { return @sizeOf(@typeOf(foo)); }2655 \\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
2620 ,2656 ,
2621 ".tmp_source.zig:1:13: error: newline not allowed in string literal",2657 ".tmp_source.zig:1:15: error: newline not allowed in string literal",
2622 );2658 );
26232659
2624 cases.add(2660 cases.add(
...@@ -3193,7 +3229,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3193,7 +3229,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3193 \\ return 2;3229 \\ return 2;
3194 \\}3230 \\}
3195 ,3231 ,
3196 ".tmp_source.zig:2:15: error: unable to infer expression type",3232 ".tmp_source.zig:2:15: error: values of type 'comptime_int' must be comptime known",
3197 );3233 );
31983234
3199 cases.add(3235 cases.add(
...@@ -3539,7 +3575,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3539,7 +3575,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3539 \\3575 \\
3540 \\export fn entry() usize { return @sizeOf(@typeOf(a)); }3576 \\export fn entry() usize { return @sizeOf(@typeOf(a)); }
3541 ,3577 ,
3542 ".tmp_source.zig:2:11: error: expected type, found 'i32'",3578 ".tmp_source.zig:2:11: error: expected type 'type', found 'i32'",
3543 );3579 );
35443580
3545 cases.add(3581 cases.add(
...@@ -5331,4 +5367,32 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -5331,4 +5367,32 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
5331 ,5367 ,
5332 ".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_float",5368 ".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_float",
5333 );5369 );
5370
5371 cases.add(
5372 "runtime assignment to comptime struct type",
5373 \\const Foo = struct {
5374 \\ Bar: u8,
5375 \\ Baz: type,
5376 \\};
5377 \\export fn f() void {
5378 \\ var x: u8 = 0;
5379 \\ const foo = Foo { .Bar = x, .Baz = u8 };
5380 \\}
5381 ,
5382 ".tmp_source.zig:7:30: error: unable to evaluate constant expression",
5383 );
5384
5385 cases.add(
5386 "runtime assignment to comptime union type",
5387 \\const Foo = union {
5388 \\ Bar: u8,
5389 \\ Baz: type,
5390 \\};
5391 \\export fn f() void {
5392 \\ var x: u8 = 0;
5393 \\ const foo = Foo { .Bar = x };
5394 \\}
5395 ,
5396 ".tmp_source.zig:7:30: error: unable to evaluate constant expression",
5397 );
5334}5398}
test/stage1/behavior.zig created+81
...@@ -0,0 +1,81 @@
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/394.zig");
21 _ = @import("behavior/bugs/655.zig");
22 _ = @import("behavior/bugs/656.zig");
23 _ = @import("behavior/bugs/726.zig");
24 _ = @import("behavior/bugs/828.zig");
25 _ = @import("behavior/bugs/920.zig");
26 _ = @import("behavior/byval_arg_var.zig");
27 _ = @import("behavior/cancel.zig");
28 _ = @import("behavior/cast.zig");
29 _ = @import("behavior/const_slice_child.zig");
30 _ = @import("behavior/coroutine_await_struct.zig");
31 _ = @import("behavior/coroutines.zig");
32 _ = @import("behavior/defer.zig");
33 _ = @import("behavior/enum.zig");
34 _ = @import("behavior/enum_with_members.zig");
35 _ = @import("behavior/error.zig");
36 _ = @import("behavior/eval.zig");
37 _ = @import("behavior/field_parent_ptr.zig");
38 _ = @import("behavior/fn.zig");
39 _ = @import("behavior/fn_in_struct_in_comptime.zig");
40 _ = @import("behavior/for.zig");
41 _ = @import("behavior/generics.zig");
42 _ = @import("behavior/if.zig");
43 _ = @import("behavior/import.zig");
44 _ = @import("behavior/incomplete_struct_param_tld.zig");
45 _ = @import("behavior/inttoptr.zig");
46 _ = @import("behavior/ir_block_deps.zig");
47 _ = @import("behavior/math.zig");
48 _ = @import("behavior/merge_error_sets.zig");
49 _ = @import("behavior/misc.zig");
50 _ = @import("behavior/namespace_depends_on_compile_var/index.zig");
51 _ = @import("behavior/new_stack_call.zig");
52 _ = @import("behavior/null.zig");
53 _ = @import("behavior/optional.zig");
54 _ = @import("behavior/pointers.zig");
55 _ = @import("behavior/popcount.zig");
56 _ = @import("behavior/ptrcast.zig");
57 _ = @import("behavior/pub_enum/index.zig");
58 _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
59 _ = @import("behavior/reflection.zig");
60 _ = @import("behavior/sizeof_and_typeof.zig");
61 _ = @import("behavior/slice.zig");
62 _ = @import("behavior/struct.zig");
63 _ = @import("behavior/struct_contains_null_ptr_itself.zig");
64 _ = @import("behavior/struct_contains_slice_of_itself.zig");
65 _ = @import("behavior/switch.zig");
66 _ = @import("behavior/switch_prong_err_enum.zig");
67 _ = @import("behavior/switch_prong_implicit_cast.zig");
68 _ = @import("behavior/syntax.zig");
69 _ = @import("behavior/this.zig");
70 _ = @import("behavior/truncate.zig");
71 _ = @import("behavior/try.zig");
72 _ = @import("behavior/type_info.zig");
73 _ = @import("behavior/undefined.zig");
74 _ = @import("behavior/underscore.zig");
75 _ = @import("behavior/union.zig");
76 _ = @import("behavior/var_args.zig");
77 _ = @import("behavior/vector.zig");
78 _ = @import("behavior/void.zig");
79 _ = @import("behavior/while.zig");
80 _ = @import("behavior/widening.zig");
81}
test/stage1/behavior/align.zig created+230
...@@ -0,0 +1,230 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const builtin = @import("builtin");
3
4var foo: u8 align(4) = 100;
5
6test "global variable alignment" {
7 assertOrPanic(@typeOf(&foo).alignment == 4);
8 assertOrPanic(@typeOf(&foo) == *align(4) u8);
9 const slice = (*[1]u8)(&foo)[0..];
10 assertOrPanic(@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 assertOrPanic(derp() == 1234);
21 assertOrPanic(@typeOf(noop1) == fn () align(1) void);
22 assertOrPanic(@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 assertOrPanic(@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 assertOrPanic(@typeOf(&blah.b) == *align(1:3:1) const u3);
44}
45
46test "default alignment allows unspecified in type syntax" {
47 assertOrPanic(*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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(slice[0] == 0x33333333);
95}
96
97test "@alignCast pointers" {
98 var x: u32 align(4) = 1;
99 expectsOnly1(&x);
100 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(whyWouldYouEverDoThis(1) == 0x1);
156 assertOrPanic(whyWouldYouEverDoThis(4) == 0x1);
157 assertOrPanic(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 assertOrPanic(@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 assertOrPanic(@typeOf(&array[0]) == *align(4) u8);
174 assertOrPanic(@typeOf(&array[1]) == *u8);
175 assertOrPanic(@typeOf(&array[2]) == *align(2) u8);
176 assertOrPanic(@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 assertOrPanic(@typeOf(&bigger[0]) == *align(2) u64);
181 assertOrPanic(@typeOf(&bigger[1]) == *align(2) u64);
182 assertOrPanic(@typeOf(&bigger[2]) == *align(2) u64);
183 assertOrPanic(@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 assertOrPanic(@typeOf(smaller[0..]) == []align(2) u32);
188 comptime assertOrPanic(@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 assertOrPanic(@typeOf(&smaller[index]) == T);
202}
203fn testIndex2(ptr: [*]align(4) u8, index: usize, comptime T: type) void {
204 comptime assertOrPanic(@typeOf(&ptr[index]) == T);
205}
206
207test "alignstack" {
208 assertOrPanic(fnWithAlignedStack() == 1234);
209}
210
211fn fnWithAlignedStack() i32 {
212 @setAlignStack(256);
213 return 1234;
214}
215
216test "alignment of structs" {
217 assertOrPanic(@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 assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic(@alignOf(Foo) != maxInt(usize));
14 if (builtin.arch == builtin.Arch.x86_64) {
15 comptime assertOrPanic(@alignOf(Foo) == 4);
16 }
17}
18
test/stage1/behavior/array.zig created+270
...@@ -0,0 +1,270 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(accumulator == 15);
22 assertOrPanic(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 assertOrPanic(@sizeOf(@typeOf(array)) == 0);
33 assertOrPanic(array.len == 4);
34}
35
36test "array literal" {
37 const hex_mult = []u16{
38 4096,
39 256,
40 16,
41 1,
42 };
43
44 assertOrPanic(hex_mult.len == 4);
45 assertOrPanic(hex_mult[1] == 256);
46}
47
48test "array dot len const expr" {
49 assertOrPanic(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) assertOrPanic(mem.eql(u8, s, "hello"));
74 if (i == 1) assertOrPanic(mem.eql(u8, s, "this"));
75 if (i == 2) assertOrPanic(mem.eql(u8, s, "is"));
76 if (i == 3) assertOrPanic(mem.eql(u8, s, "my"));
77 if (i == 4) assertOrPanic(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 assertOrPanic(s_array[0].b == 1);
96 assertOrPanic(s_array[1].b == 2);
97 assertOrPanic(s_array[2].b == 3);
98}
99
100test "array literal with specified size" {
101 var array = [2]u8{
102 1,
103 2,
104 };
105 assertOrPanic(array[0] == 1);
106 assertOrPanic(array[1] == 2);
107}
108
109test "array child property" {
110 var x: [5]i32 = undefined;
111 assertOrPanic(@typeOf(x).Child == i32);
112}
113
114test "array len property" {
115 var x: [5]i32 = undefined;
116 assertOrPanic(@typeOf(x).len == 5);
117}
118
119test "array len field" {
120 var arr = [4]u8{ 0, 0, 0, 0 };
121 var ptr = &arr;
122 assertOrPanic(arr.len == 4);
123 comptime assertOrPanic(arr.len == 4);
124 assertOrPanic(ptr.len == 4);
125 comptime assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(x[0] == 1);
201 assertOrPanic(x[1] == 2);
202 assertOrPanic(x[2] == 3);
203 }
204 fn foo2(trash: bool, x: []const i32) void {
205 assertOrPanic(trash);
206 assertOrPanic(x[0] == 1);
207 assertOrPanic(x[1] == 2);
208 assertOrPanic(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 assertOrPanic(cases2.len == 2);
233 assertOrPanic(cases2[0].len == 1);
234 assertOrPanic(cases2[0][0] == 1);
235 assertOrPanic(cases2[1].len == 2);
236 assertOrPanic(cases2[1][0] == 2);
237 assertOrPanic(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 assertOrPanic(cases.len == 3);
252 assertOrPanic(cases[0].len == 1);
253 assertOrPanic(cases[0][0].len == 1);
254 assertOrPanic(cases[0][0][0] == 1);
255 assertOrPanic(cases[1].len == 1);
256 assertOrPanic(cases[1][0].len == 2);
257 assertOrPanic(cases[1][0][0] == 2);
258 assertOrPanic(cases[1][0][1] == 3);
259 assertOrPanic(cases[2].len == 2);
260 assertOrPanic(cases[2][0].len == 1);
261 assertOrPanic(cases[2][0][0] == 4);
262 assertOrPanic(cases[2][1].len == 3);
263 assertOrPanic(cases[2][1][0] == 5);
264 assertOrPanic(cases[2][1][1] == 6);
265 assertOrPanic(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 assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(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 assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic(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 assertOrPanic(x1 == 1234);
17 }
18 assertOrPanic(x == 5678);
19
20 assertOrPanic(@cmpxchgStrong(i32, &x, 5678, 42, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
21 assertOrPanic(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 assertOrPanic(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 assertOrPanic(prev_value == 200);
40 comptime {
41 var x: i32 = 1234;
42 const y: i32 = 12345;
43 assertOrPanic(@atomicLoad(i32, &x, AtomicOrder.SeqCst) == 1234);
44 assertOrPanic(@atomicLoad(i32, &y, AtomicOrder.SeqCst) == 12345);
45 }
46}
47
48fn testAtomicLoad(ptr: *u8) void {
49 const x = @atomicLoad(u8, ptr, AtomicOrder.SeqCst);
50 assertOrPanic(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 assertOrPanic(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 assertOrPanic(x1 == &data1);
66 }
67 assertOrPanic(x == &data3);
68
69 assertOrPanic(@cmpxchgStrong(*i32, &x, &data3, &data2, AtomicOrder.SeqCst, AtomicOrder.SeqCst) == null);
70 assertOrPanic(x == &data2);
71}
test/stage1/behavior/bit_shifting.zig created+88
...@@ -0,0 +1,88 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type {
5 assertOrPanic(Key == @IntType(false, Key.bit_count));
6 assertOrPanic(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 assertOrPanic(table.get(key) == null);
81 node.init(key, {});
82 table.put(node);
83 }
84
85 for (node_buffer) |*node, i| {
86 assertOrPanic(table.get(@intCast(Key, i)) == node);
87 }
88}
test/stage1/behavior/bitcast.zig created+36
...@@ -0,0 +1,36 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic(conv(-1) == maxInt(u32));
12 assertOrPanic(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 assertOrPanic(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 assertOrPanic = std.debug.assertOrPanic;
3const minInt = std.math.minInt;
4
5test "@bitreverse" {
6 comptime testBitReverse();
7 testBitReverse();
8}
9
10fn testBitReverse() void {
11 // using comptime_ints, unsigned
12 assertOrPanic(@bitreverse(u0, 0) == 0);
13 assertOrPanic(@bitreverse(u5, 0x12) == 0x9);
14 assertOrPanic(@bitreverse(u8, 0x12) == 0x48);
15 assertOrPanic(@bitreverse(u16, 0x1234) == 0x2c48);
16 assertOrPanic(@bitreverse(u24, 0x123456) == 0x6a2c48);
17 assertOrPanic(@bitreverse(u32, 0x12345678) == 0x1e6a2c48);
18 assertOrPanic(@bitreverse(u40, 0x123456789a) == 0x591e6a2c48);
19 assertOrPanic(@bitreverse(u48, 0x123456789abc) == 0x3d591e6a2c48);
20 assertOrPanic(@bitreverse(u56, 0x123456789abcde) == 0x7b3d591e6a2c48);
21 assertOrPanic(@bitreverse(u64, 0x123456789abcdef1) == 0x8f7b3d591e6a2c48);
22 assertOrPanic(@bitreverse(u128, 0x123456789abcdef11121314151617181) == 0x818e868a828c84888f7b3d591e6a2c48);
23
24 // using runtime uints, unsigned
25 var num0: u0 = 0;
26 assertOrPanic(@bitreverse(u0, num0) == 0);
27 var num5: u5 = 0x12;
28 assertOrPanic(@bitreverse(u5, num5) == 0x9);
29 var num8: u8 = 0x12;
30 assertOrPanic(@bitreverse(u8, num8) == 0x48);
31 var num16: u16 = 0x1234;
32 assertOrPanic(@bitreverse(u16, num16) == 0x2c48);
33 var num24: u24 = 0x123456;
34 assertOrPanic(@bitreverse(u24, num24) == 0x6a2c48);
35 var num32: u32 = 0x12345678;
36 assertOrPanic(@bitreverse(u32, num32) == 0x1e6a2c48);
37 var num40: u40 = 0x123456789a;
38 assertOrPanic(@bitreverse(u40, num40) == 0x591e6a2c48);
39 var num48: u48 = 0x123456789abc;
40 assertOrPanic(@bitreverse(u48, num48) == 0x3d591e6a2c48);
41 var num56: u56 = 0x123456789abcde;
42 assertOrPanic(@bitreverse(u56, num56) == 0x7b3d591e6a2c48);
43 var num64: u64 = 0x123456789abcdef1;
44 assertOrPanic(@bitreverse(u64, num64) == 0x8f7b3d591e6a2c48);
45 var num128: u128 = 0x123456789abcdef11121314151617181;
46 assertOrPanic(@bitreverse(u128, num128) == 0x818e868a828c84888f7b3d591e6a2c48);
47
48 // using comptime_ints, signed, positive
49 assertOrPanic(@bitreverse(i0, 0) == 0);
50 assertOrPanic(@bitreverse(i8, @bitCast(i8, u8(0x92))) == @bitCast(i8, u8(0x49)));
51 assertOrPanic(@bitreverse(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x2c48)));
52 assertOrPanic(@bitreverse(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x6a2c48)));
53 assertOrPanic(@bitreverse(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x1e6a2c48)));
54 assertOrPanic(@bitreverse(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x591e6a2c48)));
55 assertOrPanic(@bitreverse(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0x3d591e6a2c48)));
56 assertOrPanic(@bitreverse(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0x7b3d591e6a2c48)));
57 assertOrPanic(@bitreverse(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0x8f7b3d591e6a2c48)));
58 assertOrPanic(@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 assertOrPanic(@bitreverse(i5, minInt(i5) + 1) == @bitreverse(i5, neg5));
63 var neg8: i8 = -18;
64 assertOrPanic(@bitreverse(i8, -18) == @bitreverse(i8, neg8));
65 var neg16: i16 = -32694;
66 assertOrPanic(@bitreverse(i16, -32694) == @bitreverse(i16, neg16));
67 var neg24: i24 = -6773785;
68 assertOrPanic(@bitreverse(i24, -6773785) == @bitreverse(i24, neg24));
69 var neg32: i32 = -16773785;
70 assertOrPanic(@bitreverse(i32, -16773785) == @bitreverse(i32, neg32));
71 var neg40: i40 = minInt(i40) + 12345;
72 assertOrPanic(@bitreverse(i40, minInt(i40) + 12345) == @bitreverse(i40, neg40));
73 var neg48: i48 = minInt(i48) + 12345;
74 assertOrPanic(@bitreverse(i48, minInt(i48) + 12345) == @bitreverse(i48, neg48));
75 var neg56: i56 = minInt(i56) + 12345;
76 assertOrPanic(@bitreverse(i56, minInt(i56) + 12345) == @bitreverse(i56, neg56));
77 var neg64: i64 = minInt(i64) + 12345;
78 assertOrPanic(@bitreverse(i64, minInt(i64) + 12345) == @bitreverse(i64, neg64));
79 var neg128: i128 = minInt(i128) + 12345;
80 assertOrPanic(@bitreverse(i128, minInt(i128) + 12345) == @bitreverse(i128, neg128));
81}
test/stage1/behavior/bool.zig created+35
...@@ -0,0 +1,35 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "bool literals" {
4 assertOrPanic(true);
5 assertOrPanic(!false);
6}
7
8test "cast bool to int" {
9 const t = true;
10 const f = false;
11 assertOrPanic(@boolToInt(t) == u32(1));
12 assertOrPanic(@boolToInt(f) == u32(0));
13 nonConstCastBoolToInt(t, f);
14}
15
16fn nonConstCastBoolToInt(t: bool, f: bool) void {
17 assertOrPanic(@boolToInt(t) == u32(1));
18 assertOrPanic(@boolToInt(f) == u32(0));
19}
20
21test "bool cmp" {
22 assertOrPanic(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 assertOrPanic(not_global_f);
34 assertOrPanic(!not_global_t);
35}
test/stage1/behavior/bswap.zig created+32
...@@ -0,0 +1,32 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4test "@bswap" {
5 comptime testByteSwap();
6 testByteSwap();
7}
8
9fn testByteSwap() void {
10 assertOrPanic(@bswap(u0, 0) == 0);
11 assertOrPanic(@bswap(u8, 0x12) == 0x12);
12 assertOrPanic(@bswap(u16, 0x1234) == 0x3412);
13 assertOrPanic(@bswap(u24, 0x123456) == 0x563412);
14 assertOrPanic(@bswap(u32, 0x12345678) == 0x78563412);
15 assertOrPanic(@bswap(u40, 0x123456789a) == 0x9a78563412);
16 assertOrPanic(@bswap(u48, 0x123456789abc) == 0xbc9a78563412);
17 assertOrPanic(@bswap(u56, 0x123456789abcde) == 0xdebc9a78563412);
18 assertOrPanic(@bswap(u64, 0x123456789abcdef1) == 0xf1debc9a78563412);
19 assertOrPanic(@bswap(u128, 0x123456789abcdef11121314151617181) == 0x8171615141312111f1debc9a78563412);
20
21 assertOrPanic(@bswap(i0, 0) == 0);
22 assertOrPanic(@bswap(i8, -50) == -50);
23 assertOrPanic(@bswap(i16, @bitCast(i16, u16(0x1234))) == @bitCast(i16, u16(0x3412)));
24 assertOrPanic(@bswap(i24, @bitCast(i24, u24(0x123456))) == @bitCast(i24, u24(0x563412)));
25 assertOrPanic(@bswap(i32, @bitCast(i32, u32(0x12345678))) == @bitCast(i32, u32(0x78563412)));
26 assertOrPanic(@bswap(i40, @bitCast(i40, u40(0x123456789a))) == @bitCast(i40, u40(0x9a78563412)));
27 assertOrPanic(@bswap(i48, @bitCast(i48, u48(0x123456789abc))) == @bitCast(i48, u48(0xbc9a78563412)));
28 assertOrPanic(@bswap(i56, @bitCast(i56, u56(0x123456789abcde))) == @bitCast(i56, u56(0xdebc9a78563412)));
29 assertOrPanic(@bswap(i64, @bitCast(i64, u64(0x123456789abcdef1))) == @bitCast(i64, u64(0xf1debc9a78563412)));
30 assertOrPanic(@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 assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic(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.debug.assertOrPanic(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.debug.assertOrPanic(@TagType(B)(a.b) == @TagType(B).c);
17 a = A{ .b = B.None };
18 std.debug.assertOrPanic(@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.debug.assertOrPanic(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 assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic(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.debug.assertOrPanic((union_or_err catch unreachable).Color == 1234);
11}
test/stage1/behavior/bugs/1486.zig created+11
...@@ -0,0 +1,11 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3const ptr = &global;
4var global: u64 = 123;
5
6test "constant pointer to global variable causes runtime load" {
7 global = 1234;
8 assertOrPanic(&global == ptr);
9 assertOrPanic(ptr.* == 1234);
10}
11
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 assertOrPanic = @import("std").debug.assertOrPanic;
11
12test "bug 394 fixed" {
13 const x = S{
14 .x = 3,
15 .y = E{ .B = 1 },
16 };
17 assertOrPanic(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.debug.assertOrPanic(@typeOf(&x) == *const other_file.Integer);
7 foo(&x);
8}
9
10fn foo(x: *const other_file.Integer) void {
11 std.debug.assertOrPanic(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 assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(align_expr == 1234);
26 }
27 },
28 PrefixOp.Return => {},
29 }
30 }
31}
test/stage1/behavior/bugs/726.zig created+16
...@@ -0,0 +1,16 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "@ptrCast from const to nullable" {
4 const c: u8 = 4;
5 var x: ?*const u8 = @ptrCast(?*const u8, &c);
6 assertOrPanic(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 assertOrPanic(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.debug.assertOrPanic(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.debug.assertOrPanic(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.debug.assertOrPanic(defer_f1);
14 std.debug.assertOrPanic(defer_f2);
15 std.debug.assertOrPanic(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.assertOrPanic(defer_b1);
51 std.debug.assertOrPanic(defer_b2);
52 std.debug.assertOrPanic(defer_b3);
53 std.debug.assertOrPanic(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+473
...@@ -0,0 +1,473 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic(z == 13);
11}
12
13test "integer literal to pointer cast" {
14 const vga_mem = @intToPtr(*u16, 0xB8000);
15 assertOrPanic(@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 assertOrPanic(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 assertOrPanic(42 == S.constConst(q));
48 assertOrPanic(42 == S.maybeConstConst(q));
49 assertOrPanic(42 == S.constConstConst(r));
50 assertOrPanic(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 assertOrPanic(error.ItBroke == y);
61}
62
63test "peer resolve arrays of different size to const slice" {
64 assertOrPanic(mem.eql(u8, boolToStr(true), "true"));
65 assertOrPanic(mem.eql(u8, boolToStr(false), "false"));
66 comptime assertOrPanic(mem.eql(u8, boolToStr(true), "true"));
67 comptime assertOrPanic(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 assertOrPanic(mem.eql(u8, value1, "aoeu"));
81 assertOrPanic(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 assertOrPanic((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 assertOrPanic((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 assertOrPanic((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 assertOrPanic(peerTypeTAndOptionalT(true, false).? == 0);
129 assertOrPanic(peerTypeTAndOptionalT(false, false).? == 3);
130 comptime {
131 assertOrPanic(peerTypeTAndOptionalT(true, false).? == 0);
132 assertOrPanic(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 assertOrPanic(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
145 assertOrPanic(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
146 comptime {
147 assertOrPanic(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
148 assertOrPanic(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 assertOrPanic(mem.eql(u8, castToOptionalSlice().?, "hi"));
161 comptime assertOrPanic(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 assertOrPanic((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 assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
186 assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
187 }
188 comptime {
189 var data = "hi";
190 const slice = data[0..];
191 assertOrPanic((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
192 assertOrPanic((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 assertOrPanic(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 assertOrPanic(@typeOf(const_array_ref) == *const [4]u8);
223 const slice: []const u8 = const_array_ref;
224 assertOrPanic(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 //assertOrPanic(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
230 //comptime assertOrPanic(mem.eql(u8, try testPeerErrorAndArray(0), "OK"));
231 assertOrPanic(mem.eql(u8, try testPeerErrorAndArray2(1), "OKK"));
232 comptime assertOrPanic(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 assertOrPanic(x == 10000);
257 const y = @floatToInt(i32, f32(1e4));
258 assertOrPanic(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 assertOrPanic(@floatToInt(I, f) == i);
270}
271
272test "cast u128 to f128 and back" {
273 comptime testCast128();
274 testCast128();
275}
276
277fn testCast128() void {
278 assertOrPanic(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 assertOrPanic(u32_value == 0x12121212);
299
300 assertOrPanic(@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 assertOrPanic(mem.eql(u8, array[0..], "boeu"));
313 const y: []u8 = &array;
314 y[0] += 1;
315 assertOrPanic(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 assertOrPanic(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name"));
322}
323
324test "@intCast comptime_int" {
325 const result = @intCast(i32, 1234);
326 assertOrPanic(@typeOf(result) == i32);
327 assertOrPanic(result == 1234);
328}
329
330test "@floatCast comptime_int and comptime_float" {
331 {
332 const result = @floatCast(f16, 1234);
333 assertOrPanic(@typeOf(result) == f16);
334 assertOrPanic(result == 1234.0);
335 }
336 {
337 const result = @floatCast(f16, 1234.0);
338 assertOrPanic(@typeOf(result) == f16);
339 assertOrPanic(result == 1234.0);
340 }
341 {
342 const result = @floatCast(f32, 1234);
343 assertOrPanic(@typeOf(result) == f32);
344 assertOrPanic(result == 1234.0);
345 }
346 {
347 const result = @floatCast(f32, 1234.0);
348 assertOrPanic(@typeOf(result) == f32);
349 assertOrPanic(result == 1234.0);
350 }
351}
352
353test "comptime_int @intToFloat" {
354 {
355 const result = @intToFloat(f16, 1234);
356 assertOrPanic(@typeOf(result) == f16);
357 assertOrPanic(result == 1234.0);
358 }
359 {
360 const result = @intToFloat(f32, 1234);
361 assertOrPanic(@typeOf(result) == f32);
362 assertOrPanic(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 assertOrPanic(@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 assertOrPanic(z == 0xff);
377}
378
379test "implicit cast undefined to optional" {
380 assertOrPanic(MakeType(void).getNull() == null);
381 assertOrPanic(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 assertOrPanic(std.mem.eql(u16, x.?[0..4], y[0..4]));
402 x.?[0] = 8;
403 y[3] = 6;
404 assertOrPanic(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.debug.assertOrPanic(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 assertOrPanic(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.debug.assertOrPanic(@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 assertOrPanic(b.* == 1);
452 var ptr2: ?*c_void = &a;
453 var c: *u32 = @ptrCast(*u32, ptr2.?);
454 assertOrPanic(c.* == 1);
455}
456
457test "@intCast to comptime_int" {
458 assertOrPanic(@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 assertOrPanic(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 assertOrPanic(x == E.A);
473}
test/stage1/behavior/const_slice_child.zig created+45
...@@ -0,0 +1,45 @@
1const debug = @import("std").debug;
2const assertOrPanic = debug.assertOrPanic;
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 assertOrPanic(args.len == 3);
19 assertOrPanic(streql(args[0], "one"));
20 assertOrPanic(streql(args[1], "two"));
21 assertOrPanic(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/stage1/behavior/coroutine_await_struct.zig created+47
...@@ -0,0 +1,47 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic(await_final_result.x == 1234);
22 assertOrPanic(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 assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic(@typeOf(p) == promise->void);
13 cancel p;
14 assertOrPanic(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 assertOrPanic(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.assertOrPanic(!result);
57 resume a_promise;
58 std.debug.assertOrPanic(result);
59 cancel p;
60}
61
62var a_promise: promise = undefined;
63var result = false;
64async fn testSuspendBlock() void {
65 suspend {
66 comptime assertOrPanic(@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 assertOrPanic(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 assertOrPanic(await_final_result == 1234);
90 assertOrPanic(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 assertOrPanic(early_final_result == 1234);
127 assertOrPanic(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 assertOrPanic(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 assertOrPanic(data == 2);
186 cancel p;
187 assertOrPanic(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.debug.assertOrPanic(e == error.Fail);
234 if (@errorReturnTrace()) |trace| {
235 assertOrPanic(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.assertOrPanic(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 assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(runSomeErrorDefers(true) catch unreachable);
25 assertOrPanic(result[0] == 'c');
26 assertOrPanic(result[1] == 'a');
27
28 const ok = runSomeErrorDefers(false) catch |err| x: {
29 assertOrPanic(err == error.FalseNotAllowed);
30 break :x true;
31 };
32 assertOrPanic(ok);
33 assertOrPanic(result[0] == 'c');
34 assertOrPanic(result[1] == 'b');
35 assertOrPanic(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 assertOrPanic(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 assertOrPanic(i == 1);
63}
64
65test "errdefer does not apply to fn inside fn" {
66 if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| assertOrPanic(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 assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(bar == Bar.B);
15 assertOrPanic(@memberCount(Foo) == 3);
16 assertOrPanic(@memberCount(Bar) == 4);
17 assertOrPanic(@sizeOf(Foo) == @sizeOf(FooNoVoid));
18 assertOrPanic(@sizeOf(Bar) == 1);
19}
20
21test "enum as return value" {
22 switch (returnAnInt(13)) {
23 Foo.One => |value| assertOrPanic(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 assertOrPanic(@enumToInt(n) == expected);
96}
97
98test "int to enum" {
99 testIntToEnumEval(3);
100}
101fn testIntToEnumEval(x: i32) void {
102 assertOrPanic(@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 assertOrPanic(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
114 comptime assertOrPanic(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 assertOrPanic(@alignOf(AlignTestEnum) >= @alignOf([9]u8));
130 assertOrPanic(@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 assertOrPanic(@sizeOf(ValueCount1) == 0);
667 assertOrPanic(@sizeOf(ValueCount2) == 1);
668 assertOrPanic(@sizeOf(ValueCount256) == 1);
669 assertOrPanic(@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 assertOrPanic(@TagType(Small) == u2);
689 }
690 {
691 var x = Small2.One;
692 x = Small2.Two;
693 comptime assertOrPanic(@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 assertOrPanic(getA(&data) == A.Two);
741 assertOrPanic(getB(&data) == B.Three3);
742 assertOrPanic(getC(&data) == C.Four4);
743 comptime assertOrPanic(@sizeOf(BitFieldOfEnums) == 1);
744
745 data.b = B.Four3;
746 assertOrPanic(data.b == B.Four3);
747
748 data.a = A.Three;
749 assertOrPanic(data.a == A.Three);
750 assertOrPanic(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 assertOrPanic(@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 assertOrPanic(@enumToInt(x) == 60);
788 assertOrPanic(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 assertOrPanic(@enumToInt(x) == 1000);
815 assertOrPanic(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 assertOrPanic(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
830 assertOrPanic(@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 assertOrPanic(@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.assertOrPanic(@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 assertOrPanic(@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 assertOrPanic(mem.eql(u8, @tagName(b), "B"));
894}
test/stage1/behavior/enum_with_members.zig created+27
...@@ -0,0 +1,27 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic((a.print(buf[0..]) catch unreachable) == 3);
23 assertOrPanic(mem.eql(u8, buf[0..3], "-42"));
24
25 assertOrPanic((b.print(buf[0..]) catch unreachable) == 2);
26 assertOrPanic(mem.eql(u8, buf[0..2], "42"));
27}
test/stage1/behavior/error.zig created+332
...@@ -0,0 +1,332 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const assertError = std.debug.assertError;
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 assertOrPanic((baz() catch unreachable) == 15);
23}
24
25fn gimmeItBroke() []const u8 {
26 return @errorName(error.ItBroke);
27}
28
29test "@errorName" {
30 assertOrPanic(mem.eql(u8, @errorName(error.AnError), "AnError"));
31 assertOrPanic(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 assertOrPanic(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 assertOrPanic(a == 3);
51 assertOrPanic(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 assertOrPanic(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| assertOrPanic(value == 1234) else |_| unreachable;
86 assertOrPanic(@typeId(@typeOf(x)) == builtin.TypeId.ErrorUnion);
87 assertOrPanic(@typeId(@typeOf(x).ErrorSet) == builtin.TypeId.ErrorSet);
88 assertOrPanic(@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 assertOrPanic(@memberCount(MyErrSet) == 2);
103
104 const a: MyErrSet!i32 = 5678;
105 const b: MyErrSet!i32 = MyErrSet.OutOfMemory;
106
107 if (a) |value| assertOrPanic(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 assertOrPanic(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| assertOrPanic(v == 1234) else |err| @compileError("bad");
142}
143
144test "syntax: optional operator in front of error union operator" {
145 comptime {
146 assertOrPanic(?(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 assertOrPanic(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 assertOrPanic((try S.errorable()) == 1234);
286 assertError(S.errorable2(), error.Failure);
287 assertError(S.errorable3(), error.Other);
288 comptime {
289 assertOrPanic((try S.errorable()) == 1234);
290 assertError(S.errorable2(), error.Failure);
291 assertError(S.errorable3(), error.Other);
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 assertOrPanic((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 assertError(S.errorable(), error.Failure);
320 comptime assertError(S.errorable(), error.Failure);
321}
322
323test "optional error set is the same size as error set" {
324 comptime assertOrPanic(@sizeOf(?anyerror) == @sizeOf(anyerror));
325 const S = struct {
326 fn returnsOptErrSet() ?anyerror {
327 return null;
328 }
329 };
330 assertOrPanic(S.returnsOptErrSet() == null);
331 comptime assertOrPanic(S.returnsOptErrSet() == null);
332}
test/stage1/behavior/eval.zig created+784
...@@ -0,0 +1,784 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const builtin = @import("builtin");
4
5test "compile time recursion" {
6 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(gimme1or2(true) == 1);
38 assertOrPanic(gimme1or2(false) == 2);
39}
40
41test "static function evaluation" {
42 assertOrPanic(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 assertOrPanic(constExprEvalOnSingleExprBlocksFn(1, true) == 3);
51 comptime assertOrPanic(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 assertOrPanic(static_point_list[0].x == 1);
68 assertOrPanic(static_point_list[0].y == 2);
69 assertOrPanic(static_point_list[1].x == 3);
70 assertOrPanic(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 assertOrPanic(static_vec3.data[2] == 1.0);
89 assertOrPanic(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 assertOrPanic(@sizeOf(@typeOf(array)) == 20);
106}
107const array_size: u8 = 20;
108
109test "constant struct with negation" {
110 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(a.len == 10);
171 const b = a[1..2];
172 assertOrPanic(b.len == 1);
173 assertOrPanic(b[0] == '2');
174 }
175}
176
177test "try to trick eval with runtime if" {
178 assertOrPanic(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 assertOrPanic(letsTryToCompareBools(true, true));
205 assertOrPanic(letsTryToCompareBools(true, false));
206 assertOrPanic(letsTryToCompareBools(false, true));
207 assertOrPanic(!letsTryToCompareBools(false, false));
208
209 comptime {
210 assertOrPanic(letsTryToCompareBools(true, true));
211 assertOrPanic(letsTryToCompareBools(true, false));
212 assertOrPanic(letsTryToCompareBools(false, true));
213 assertOrPanic(!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 assertOrPanic(performFn('t', 1) == 6);
259 assertOrPanic(performFn('o', 0) == 1);
260 assertOrPanic(performFn('w', 99) == 99);
261}
262
263test "eval @setRuntimeSafety at compile-time" {
264 const result = comptime fnWithSetRuntimeSafety();
265 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(bytes[0] == 'a');
304 assertOrPanic(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 assertOrPanic(foo_ref.name[0] == 'a');
333 foo_ref.name = "b";
334 assertOrPanic(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 assertOrPanic(global_array[5] == 5 * 5);
346 assertOrPanic(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 assertOrPanic(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 assertOrPanic(&hi1[0] == &hi2[0]);
370}
371fn assertEqualPtrs(ptr1: *const u8, ptr2: *const u8) void {
372 assertOrPanic(ptr1 == ptr2);
373}
374
375test "@setEvalBranchQuota" {
376 comptime {
377 // 1001 for the loop and then 1 more for the assertOrPanic fn call
378 @setEvalBranchQuota(1002);
379 var i = 0;
380 var sum = 0;
381 while (i < 1001) : (i += 1) {
382 sum += i;
383 }
384 assertOrPanic(sum == 500500);
385 }
386}
387
388// TODO test "float literal at compile time not lossy" {
389// TODO assertOrPanic(16777216.0 + 1.0 == 16777217.0);
390// TODO assertOrPanic(9007199254740992.0 + 1.0 == 9007199254740993.0);
391// TODO }
392
393test "f32 at compile time is lossy" {
394 assertOrPanic(f32(1 << 24) + 1 == 1 << 24);
395}
396
397test "f64 at compile time is lossy" {
398 assertOrPanic(f64(1 << 53) + 1 == 1 << 53);
399}
400
401test "f128 at compile time is lossy" {
402 assertOrPanic(f128(10384593717069655257060992658440192.0) + 1 == 10384593717069655257060992658440192.0);
403}
404
405comptime {
406 assertOrPanic(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 assertOrPanic(TypeWithCompTimeSlice(a).Node == TypeWithCompTimeSlice(b).Node);
419 comptime assertOrPanic(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 assertOrPanic(slice1.len == 0);
425 const slice2 = ([*]i32)(undefined)[100..100];
426 assertOrPanic(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 assertOrPanic(s[0] == 0x1020304);
449 assertOrPanic(s[1] == 0x5060708);
450 assertOrPanic(s[2] == 0x90a0b0c);
451 assertOrPanic(s[3] == 0xd0e0f10);
452}
453
454test "comptime function with the same args is memoized" {
455 comptime {
456 assertOrPanic(MakeType(i32) == MakeType(i32));
457 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(foo.read_x() == 1);
530 foo.x = 2;
531 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(diamond_info.version == 0);
578 assertOrPanic(res.version == 1);
579 }
580}
581
582test "pointer to type" {
583 comptime {
584 var T: type = i32;
585 assertOrPanic(T == i32);
586 var ptr = &T;
587 assertOrPanic(@typeOf(ptr) == *type);
588 ptr.* = f32;
589 assertOrPanic(T == f32);
590 assertOrPanic(*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 => assertOrPanic(T == i32),
600 1 => assertOrPanic(T == f64),
601 2 => assertOrPanic(T == type),
602 else => unreachable,
603 }
604 }
605 for (types_array[0..]) |T, i| {
606 switch (i) {
607 0 => assertOrPanic(T == i32),
608 1 => assertOrPanic(T == f64),
609 2 => assertOrPanic(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 assertOrPanic(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 assertOrPanic(b == 2);
641}
642
643test "@tagName of @typeId" {
644 const str = @tagName(@typeId(u8));
645 assertOrPanic(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) assertOrPanic(x);
667 if (i == 1) assertOrPanic(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 assertOrPanic(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 assertOrPanic(zero_u1 == 0);
692}
693
694test "bit shift a u1" {
695 var x: u1 = 1;
696 var y = x << 0;
697 assertOrPanic(y == 1);
698}
699
700test "@intCast to a u0" {
701 var x: u8 = 0;
702 var y: u0 = @intCast(u0, x);
703 assertOrPanic(y == 0);
704}
705
706test "@bytesToslice on a packed struct" {
707 const F = packed struct {
708 a: u8,
709 };
710
711 var b = [1]u8{9};
712 var f = @bytesToSlice(F, b);
713 assertOrPanic(f[0].a == 9);
714}
715
716test "comptime pointer cast array and then slice" {
717 const array = []u8{ 1, 2, 3, 4, 5, 6, 7, 8 };
718
719 const ptrA: [*]const u8 = @ptrCast([*]const u8, &array);
720 const sliceA: []const u8 = ptrA[0..2];
721
722 const ptrB: [*]const u8 = &array;
723 const sliceB: []const u8 = ptrB[0..2];
724
725 assertOrPanic(sliceA[1] == 2);
726 assertOrPanic(sliceB[1] == 2);
727}
728
729test "slice bounds in comptime concatenation" {
730 const bs = comptime blk: {
731 const b = c"........1........";
732 break :blk b[8..9];
733 };
734 const str = "" ++ bs;
735 assertOrPanic(str.len == 1);
736 assertOrPanic(std.mem.eql(u8, str, "1"));
737
738 const str2 = bs ++ "";
739 assertOrPanic(str2.len == 1);
740 assertOrPanic(std.mem.eql(u8, str2, "1"));
741}
742
743test "comptime bitwise operators" {
744 comptime {
745 assertOrPanic(3 & 1 == 1);
746 assertOrPanic(3 & -1 == 3);
747 assertOrPanic(-3 & -1 == -3);
748 assertOrPanic(3 | -1 == -1);
749 assertOrPanic(-3 | -1 == -1);
750 assertOrPanic(3 ^ -1 == -4);
751 assertOrPanic(-3 ^ -1 == 2);
752 assertOrPanic(~i8(-1) == 0);
753 assertOrPanic(~i128(-1) == 0);
754 assertOrPanic(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
755 assertOrPanic(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
756 assertOrPanic(~u128(0) == 0xffffffffffffffffffffffffffffffff);
757 }
758}
759
760test "*align(1) u16 is the same as *align(1:0:2) u16" {
761 comptime {
762 assertOrPanic(*align(1:0:2) u16 == *align(1) u16);
763 // TODO add parsing support for this syntax
764 //assertOrPanic(*align(:0:2) u16 == *u16);
765 }
766}
767
768test "array concatenation forces comptime" {
769 var a = oneItem(3) ++ oneItem(4);
770 assertOrPanic(std.mem.eql(i32, a, []i32{ 3, 4 }));
771}
772
773test "array multiplication forces comptime" {
774 var a = oneItem(3) ** scalar(2);
775 assertOrPanic(std.mem.eql(i32, a, []i32{ 3, 3 }));
776}
777
778fn oneItem(x: i32) [1]i32 {
779 return []i32{x};
780}
781
782fn scalar(x: u32) u32 {
783 return x;
784}
test/stage1/behavior/field_parent_ptr.zig created+41
...@@ -0,0 +1,41 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(c == &foo.c);
29
30 const base = @fieldParentPtr(Foo, "c", c);
31 assertOrPanic(base == &foo);
32 assertOrPanic(&base.c == c);
33}
34
35fn testParentFieldPtrFirst(a: *const bool) void {
36 assertOrPanic(a == &foo.a);
37
38 const base = @fieldParentPtr(Foo, "a", a);
39 assertOrPanic(base == &foo);
40 assertOrPanic(&base.a == a);
41}
test/stage1/behavior/fn.zig created+208
...@@ -0,0 +1,208 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "params" {
4 assertOrPanic(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 assertOrPanic(a + c == 3);
25 return vv;
26}
27
28test "mutable local variables" {
29 var zero: i32 = 0;
30 assertOrPanic(zero == 0);
31
32 var i = i32(0);
33 while (i != 3) {
34 i += 1;
35 }
36 assertOrPanic(i == 3);
37}
38
39test "separate block scopes" {
40 {
41 const no_conflict: i32 = 5;
42 assertOrPanic(no_conflict == 5);
43 }
44
45 const c = x: {
46 const no_conflict = i32(10);
47 break :x no_conflict;
48 };
49 assertOrPanic(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 assertOrPanic(@"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 assertOrPanic(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 assertOrPanic(@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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(addPointCoordsVar(Point{ .x = 1, .y = 2 }) == 3);
138}
139
140fn addPointCoordsVar(pt: var) i32 {
141 comptime assertOrPanic(@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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(s.ptr() == 1234);
207}
208
test/stage1/behavior/fn_in_struct_in_comptime.zig created+17
...@@ -0,0 +1,17 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(foo(@intToPtr(*u8, 12345)) == 12345);
17}
test/stage1/behavior/for.zig created+106
...@@ -0,0 +1,106 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(counter == array.len);
106}
test/stage1/behavior/generics.zig created+151
...@@ -0,0 +1,151 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "simple generic fn" {
4 assertOrPanic(max(i32, 3, -1) == 3);
5 assertOrPanic(max(f32, 0.123, 0.456) == 0.456);
6 assertOrPanic(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 assertOrPanic(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 assertOrPanic(gimmeTheBigOne(1234, 5678) == 5678);
36 assertOrPanic(shouldCallSameInstance(34, 12) == 34);
37 assertOrPanic(sameButWithFloats(0.43, 0.49) == 0.49);
38}
39
40test "var params" {
41 assertOrPanic(max_i32(12, 34) == 34);
42 assertOrPanic(max_f64(1.2, 3.4) == 3.4);
43}
44
45comptime {
46 assertOrPanic(max_i32(12, 34) == 34);
47 assertOrPanic(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 assertOrPanic(list.prealloc_items.len == 8);
80 assertOrPanic(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 assertOrPanic(a1.value == 13);
93 assertOrPanic(a1.value == a1.getVal());
94 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(getFirstByte(u8, []u8{13}) == 13);
124 assertOrPanic(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 assertOrPanic(foos[0](true));
150 assertOrPanic(!foos[1](true));
151}
test/stage1/behavior/if.zig created+37
...@@ -0,0 +1,37 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(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 assertOrPanic = @import("std").debug.assertOrPanic;
2const a_namespace = @import("import/a_namespace.zig");
3
4test "call fn via namespace lookup" {
5 assertOrPanic(a_namespace.foo() == 1234);
6}
7
8test "importing the same thing gives the same import" {
9 assertOrPanic(@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 assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(foo(a) == 13);
30}
test/stage1/behavior/inttoptr.zig created+26
...@@ -0,0 +1,26 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic((foo(1) catch unreachable) == 0);
20 assertOrPanic((foo(2) catch unreachable) == 0);
21}
test/stage1/behavior/math.zig created+500
...@@ -0,0 +1,500 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3const maxInt = std.math.maxInt;
4const minInt = std.math.minInt;
5
6test "division" {
7 testDivision();
8 comptime testDivision();
9}
10fn testDivision() void {
11 assertOrPanic(div(u32, 13, 3) == 4);
12 assertOrPanic(div(f16, 1.0, 2.0) == 0.5);
13 assertOrPanic(div(f32, 1.0, 2.0) == 0.5);
14
15 assertOrPanic(divExact(u32, 55, 11) == 5);
16 assertOrPanic(divExact(i32, -55, 11) == -5);
17 assertOrPanic(divExact(f16, 55.0, 11.0) == 5.0);
18 assertOrPanic(divExact(f16, -55.0, 11.0) == -5.0);
19 assertOrPanic(divExact(f32, 55.0, 11.0) == 5.0);
20 assertOrPanic(divExact(f32, -55.0, 11.0) == -5.0);
21
22 assertOrPanic(divFloor(i32, 5, 3) == 1);
23 assertOrPanic(divFloor(i32, -5, 3) == -2);
24 assertOrPanic(divFloor(f16, 5.0, 3.0) == 1.0);
25 assertOrPanic(divFloor(f16, -5.0, 3.0) == -2.0);
26 assertOrPanic(divFloor(f32, 5.0, 3.0) == 1.0);
27 assertOrPanic(divFloor(f32, -5.0, 3.0) == -2.0);
28 assertOrPanic(divFloor(i32, -0x80000000, -2) == 0x40000000);
29 assertOrPanic(divFloor(i32, 0, -0x80000000) == 0);
30 assertOrPanic(divFloor(i32, -0x40000001, 0x40000000) == -2);
31 assertOrPanic(divFloor(i32, -0x80000000, 1) == -0x80000000);
32
33 assertOrPanic(divTrunc(i32, 5, 3) == 1);
34 assertOrPanic(divTrunc(i32, -5, 3) == -1);
35 assertOrPanic(divTrunc(f16, 5.0, 3.0) == 1.0);
36 assertOrPanic(divTrunc(f16, -5.0, 3.0) == -1.0);
37 assertOrPanic(divTrunc(f32, 5.0, 3.0) == 1.0);
38 assertOrPanic(divTrunc(f32, -5.0, 3.0) == -1.0);
39 assertOrPanic(divTrunc(f64, 5.0, 3.0) == 1.0);
40 assertOrPanic(divTrunc(f64, -5.0, 3.0) == -1.0);
41
42 comptime {
43 assertOrPanic(
44 1194735857077236777412821811143690633098347576 % 508740759824825164163191790951174292733114988 == 177254337427586449086438229241342047632117600,
45 );
46 assertOrPanic(
47 @rem(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -177254337427586449086438229241342047632117600,
48 );
49 assertOrPanic(
50 1194735857077236777412821811143690633098347576 / 508740759824825164163191790951174292733114988 == 2,
51 );
52 assertOrPanic(
53 @divTrunc(-1194735857077236777412821811143690633098347576, 508740759824825164163191790951174292733114988) == -2,
54 );
55 assertOrPanic(
56 @divTrunc(1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == -2,
57 );
58 assertOrPanic(
59 @divTrunc(-1194735857077236777412821811143690633098347576, -508740759824825164163191790951174292733114988) == 2,
60 );
61 assertOrPanic(
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 assertOrPanic(@addWithOverflow(u8, 250, 100, &result));
82 assertOrPanic(!@addWithOverflow(u8, 100, 150, &result));
83 assertOrPanic(result == 250);
84}
85
86// TODO test mulWithOverflow
87// TODO test subWithOverflow
88
89test "@shlWithOverflow" {
90 var result: u16 = undefined;
91 assertOrPanic(@shlWithOverflow(u16, 0b0010111111111111, 3, &result));
92 assertOrPanic(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result));
93 assertOrPanic(result == 0b1011111111111100);
94}
95
96test "@clz" {
97 testClz();
98 comptime testClz();
99}
100
101fn testClz() void {
102 assertOrPanic(clz(u8(0b00001010)) == 4);
103 assertOrPanic(clz(u8(0b10001010)) == 0);
104 assertOrPanic(clz(u8(0b00000000)) == 8);
105 assertOrPanic(clz(u128(0xffffffffffffffff)) == 64);
106 assertOrPanic(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 assertOrPanic(ctz(u8(0b10100000)) == 5);
120 assertOrPanic(ctz(u8(0b10001010)) == 1);
121 assertOrPanic(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 assertOrPanic(i == 5);
132 i -= 2;
133 assertOrPanic(i == 3);
134 i *= 20;
135 assertOrPanic(i == 60);
136 i /= 3;
137 assertOrPanic(i == 20);
138 i %= 11;
139 assertOrPanic(i == 9);
140 i <<= 1;
141 assertOrPanic(i == 18);
142 i >>= 2;
143 assertOrPanic(i == 4);
144 i = 6;
145 i &= 5;
146 assertOrPanic(i == 4);
147 i ^= 6;
148 assertOrPanic(i == 2);
149 i = 6;
150 i |= 3;
151 assertOrPanic(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 assertOrPanic(!b);
174}
175
176test "const number literal" {
177 const one = 1;
178 const eleven = ten + one;
179
180 assertOrPanic(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 assertOrPanic(zero == 0);
191 const orig = zero -% 1;
192 assertOrPanic(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 assertOrPanic(min_val == minInt(i32));
202 const max_val = min_val -% 1;
203 assertOrPanic(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 assertOrPanic(x == -32768);
212 const neg = -%x;
213 assertOrPanic(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 assertOrPanic(result.quotient == 33554432);
223 assertOrPanic(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 assertOrPanic(comptime x: {
238 break :x ~u16(0b1010101010101010) == 0b0101010101010101;
239 });
240 assertOrPanic(comptime x: {
241 break :x ~u64(2147483647) == 18446744071562067968;
242 });
243 testBinaryNot(0b1010101010101010);
244}
245
246fn testBinaryNot(x: u16) void {
247 assertOrPanic(~x == 0b0101010101010101);
248}
249
250test "small int addition" {
251 var x: @IntType(false, 2) = 0;
252 assertOrPanic(x == 0);
253
254 x += 1;
255 assertOrPanic(x == 1);
256
257 x += 1;
258 assertOrPanic(x == 2);
259
260 x += 1;
261 assertOrPanic(x == 3);
262
263 var result: @typeOf(x) = 3;
264 assertOrPanic(@addWithOverflow(@typeOf(x), x, 1, &result));
265
266 assertOrPanic(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 assertOrPanic(y == y2);
280}
281
282test "allow signed integer division/remainder when values are comptime known and positive or exact" {
283 assertOrPanic(5 / 3 == 1);
284 assertOrPanic(-5 / -3 == 1);
285 assertOrPanic(-6 / 3 == -2);
286
287 assertOrPanic(5 % 3 == 2);
288 assertOrPanic(-6 % 3 == 0);
289}
290
291test "hex float literal parsing" {
292 comptime assertOrPanic(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 assertOrPanic(@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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(shifted == 0b00101101);
350}
351
352test "comptime_int addition" {
353 comptime {
354 assertOrPanic(35361831660712422535336160538497375248 + 101752735581729509668353361206450473702 == 137114567242441932203689521744947848950);
355 assertOrPanic(594491908217841670578297176641415611445982232488944558774612 + 390603545391089362063884922208143568023166603618446395589768 == 985095453608931032642182098849559179469148836107390954364380);
356 }
357}
358
359test "comptime_int multiplication" {
360 comptime {
361 assertOrPanic(
362 45960427431263824329884196484953148229 * 128339149605334697009938835852565949723 == 5898522172026096622534201617172456926982464453350084962781392314016180490567,
363 );
364 assertOrPanic(
365 594491908217841670578297176641415611445982232488944558774612 * 390603545391089362063884922208143568023166603618446395589768 == 232210647056203049913662402532976186578842425262306016094292237500303028346593132411865381225871291702600263463125370016,
366 );
367 }
368}
369
370test "comptime_int shifting" {
371 comptime {
372 assertOrPanic((u128(1) << 127) == 0x80000000000000000000000000000000);
373 }
374}
375
376test "comptime_int multi-limb shift and mask" {
377 comptime {
378 var a = 0xefffffffa0000001eeeeeeefaaaaaaab;
379
380 assertOrPanic(u32(a & 0xffffffff) == 0xaaaaaaab);
381 a >>= 32;
382 assertOrPanic(u32(a & 0xffffffff) == 0xeeeeeeef);
383 a >>= 32;
384 assertOrPanic(u32(a & 0xffffffff) == 0xa0000001);
385 a >>= 32;
386 assertOrPanic(u32(a & 0xffffffff) == 0xefffffff);
387 a >>= 32;
388
389 assertOrPanic(a == 0);
390 }
391}
392
393test "comptime_int multi-limb partial shift right" {
394 comptime {
395 var a = 0x1ffffffffeeeeeeee;
396 a >>= 16;
397 assertOrPanic(a == 0x1ffffffffeeee);
398 }
399}
400
401test "xor" {
402 test_xor();
403 comptime test_xor();
404}
405
406fn test_xor() void {
407 assertOrPanic(0xFF ^ 0x00 == 0xFF);
408 assertOrPanic(0xF0 ^ 0x0F == 0xFF);
409 assertOrPanic(0xFF ^ 0xF0 == 0x0F);
410 assertOrPanic(0xFF ^ 0x0F == 0xF0);
411 assertOrPanic(0xFF ^ 0xFF == 0x00);
412}
413
414test "comptime_int xor" {
415 comptime {
416 assertOrPanic(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0x00000000000000000000000000000000 == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
417 assertOrPanic(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0x0000000000000000FFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
418 assertOrPanic(0xFFFFFFFFFFFFFFFF0000000000000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x0000000000000000FFFFFFFFFFFFFFFF);
419 assertOrPanic(0x0000000000000000FFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFFFF0000000000000000);
420 assertOrPanic(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000000000000000000000000000);
421 assertOrPanic(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0x00000000FFFFFFFF00000000FFFFFFFF == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
422 assertOrPanic(0xFFFFFFFF00000000FFFFFFFF00000000 ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0x00000000FFFFFFFF00000000FFFFFFFF);
423 assertOrPanic(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 assertOrPanic(@sizeOf(f128) == 16);
438 assertOrPanic(make_f128(1.0) == 1.0);
439 assertOrPanic(make_f128(1.0) != 1.1);
440 assertOrPanic(make_f128(1.0) > 0.9);
441 assertOrPanic(make_f128(1.0) >= 0.9);
442 assertOrPanic(make_f128(1.0) >= 1.0);
443 should_not_be_zero(1.0);
444}
445
446fn should_not_be_zero(x: f128) void {
447 assertOrPanic(x != 0.0);
448}
449
450test "comptime float rem int" {
451 comptime {
452 var x = f32(1) % 2;
453 assertOrPanic(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 assertOrPanic(T(1) == T(1) % T(2));
469 assertOrPanic(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 assertOrPanic(z == x);
484}
485
486fn testSqrt(comptime T: type, x: T) void {
487 assertOrPanic(@sqrt(T, x * x) == x);
488}
489
490test "comptime_int param and return" {
491 const a = comptimeAdd(35361831660712422535336160538497375248, 101752735581729509668353361206450473702);
492 assertOrPanic(a == 137114567242441932203689521744947848950);
493
494 const b = comptimeAdd(594491908217841670578297176641415611445982232488944558774612, 390603545391089362063884922208143568023166603618446395589768);
495 assertOrPanic(b == 985095453608931032642182098849559179469148836107390954364380);
496}
497
498fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int {
499 return a + b;
500}
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+687
...@@ -0,0 +1,687 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic(@IntType(true, 8) == i8);
30 assertOrPanic(@IntType(true, 16) == i16);
31 assertOrPanic(@IntType(true, 32) == i32);
32 assertOrPanic(@IntType(true, 64) == i64);
33
34 assertOrPanic(@IntType(false, 8) == u8);
35 assertOrPanic(@IntType(false, 16) == u16);
36 assertOrPanic(@IntType(false, 32) == u32);
37 assertOrPanic(@IntType(false, 64) == u64);
38
39 assertOrPanic(i8.bit_count == 8);
40 assertOrPanic(i16.bit_count == 16);
41 assertOrPanic(i32.bit_count == 32);
42 assertOrPanic(i64.bit_count == 64);
43
44 assertOrPanic(i8.is_signed);
45 assertOrPanic(i16.is_signed);
46 assertOrPanic(i32.is_signed);
47 assertOrPanic(i64.is_signed);
48 assertOrPanic(isize.is_signed);
49
50 assertOrPanic(!u8.is_signed);
51 assertOrPanic(!u16.is_signed);
52 assertOrPanic(!u32.is_signed);
53 assertOrPanic(!u64.is_signed);
54 assertOrPanic(!usize.is_signed);
55}
56
57test "floating point primitive bit counts" {
58 assertOrPanic(f16.bit_count == 16);
59 assertOrPanic(f32.bit_count == 32);
60 assertOrPanic(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 assertOrPanic(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 assertOrPanic(f);
85 }
86
87 if (t and x: {
88 hit_3 = t;
89 break :x f;
90 }) {
91 assertOrPanic(f);
92 }
93 if (f and x: {
94 assertOrPanic(f);
95 break :x f;
96 }) {
97 assertOrPanic(f);
98 } else {
99 hit_4 = t;
100 }
101 assertOrPanic(hit_1);
102 assertOrPanic(hit_2);
103 assertOrPanic(hit_3);
104 assertOrPanic(hit_4);
105}
106
107test "truncate" {
108 assertOrPanic(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 assertOrPanic(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
120}
121
122const g1: i32 = 1233 + 1;
123var g2: i32 = 0;
124
125test "global variables" {
126 assertOrPanic(g2 == 0);
127 g2 = g1;
128 assertOrPanic(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 assertOrPanic(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 assertOrPanic(comptime x: {
167 break :x emptyFn == alias;
168 });
169}
170
171fn emptyFn() void {}
172
173test "hex escape" {
174 assertOrPanic(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
175}
176
177test "string concatenation" {
178 assertOrPanic(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
179}
180
181test "array mult operator" {
182 assertOrPanic(mem.eql(u8, "ab" ** 5, "ababababab"));
183}
184
185test "string escapes" {
186 assertOrPanic(mem.eql(u8, "\"", "\x22"));
187 assertOrPanic(mem.eql(u8, "\'", "\x27"));
188 assertOrPanic(mem.eql(u8, "\n", "\x0a"));
189 assertOrPanic(mem.eql(u8, "\r", "\x0d"));
190 assertOrPanic(mem.eql(u8, "\t", "\x09"));
191 assertOrPanic(mem.eql(u8, "\\", "\x5c"));
192 assertOrPanic(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 assertOrPanic(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 assertOrPanic(cstr.cmp(s1, s2) == 0);
213}
214
215test "type equality" {
216 assertOrPanic(*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 assertOrPanic(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 assertOrPanic(castSmallUnsignedToLargerSigned1(200) == i16(200));
251 assertOrPanic(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 assertOrPanic(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 assertOrPanic(x == 4);
277 assertOrPanic(y.* == 4);
278}
279
280test "call result of if else expression" {
281 assertOrPanic(mem.eql(u8, f2(true), "a"));
282 assertOrPanic(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 assertOrPanic(pt.x == 3);
325 assertOrPanic(pt.y == 4);
326 },
327 else => unreachable,
328 }
329}
330fn test3_2(f: Test3Foo) void {
331 switch (f) {
332 Test3Foo.Two => |x| {
333 assertOrPanic(x == 13);
334 },
335 else => unreachable,
336 }
337}
338
339test "character literals" {
340 assertOrPanic('\'' == 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 assertOrPanic(f_ptr.* == 12.34);
350}
351
352test "pointer comparison" {
353 const a = ([]const u8)("a");
354 const b = &a;
355 assertOrPanic(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 assertOrPanic(a[i] == b[i]);
371 }
372 }
373 assertOrPanic(a[len] == 0);
374 assertOrPanic(b[len] == 0);
375}
376
377test "cast slice to u8 slice" {
378 assertOrPanic(@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 assertOrPanic(bytes.len == 4 * 4);
383 bytes[4] = 0;
384 bytes[5] = 0;
385 bytes[6] = 0;
386 bytes[7] = 0;
387 assertOrPanic(big_thing_slice[1] == 0);
388 const big_thing_again = @bytesToSlice(i32, bytes);
389 assertOrPanic(big_thing_again[2] == 3);
390 big_thing_again[2] = -1;
391 assertOrPanic(bytes[8] == maxInt(u8));
392 assertOrPanic(bytes[9] == maxInt(u8));
393 assertOrPanic(bytes[10] == maxInt(u8));
394 assertOrPanic(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 assertOrPanic(?*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 assertOrPanic(ptr2[0] == 1.0);
425 assertOrPanic(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 assertOrPanic(@typeId(type) == Tid.Type);
448 assertOrPanic(@typeId(void) == Tid.Void);
449 assertOrPanic(@typeId(bool) == Tid.Bool);
450 assertOrPanic(@typeId(noreturn) == Tid.NoReturn);
451 assertOrPanic(@typeId(i8) == Tid.Int);
452 assertOrPanic(@typeId(u8) == Tid.Int);
453 assertOrPanic(@typeId(i64) == Tid.Int);
454 assertOrPanic(@typeId(u64) == Tid.Int);
455 assertOrPanic(@typeId(f32) == Tid.Float);
456 assertOrPanic(@typeId(f64) == Tid.Float);
457 assertOrPanic(@typeId(*f32) == Tid.Pointer);
458 assertOrPanic(@typeId([2]u8) == Tid.Array);
459 assertOrPanic(@typeId(AStruct) == Tid.Struct);
460 assertOrPanic(@typeId(@typeOf(1)) == Tid.ComptimeInt);
461 assertOrPanic(@typeId(@typeOf(1.0)) == Tid.ComptimeFloat);
462 assertOrPanic(@typeId(@typeOf(undefined)) == Tid.Undefined);
463 assertOrPanic(@typeId(@typeOf(null)) == Tid.Null);
464 assertOrPanic(@typeId(?i32) == Tid.Optional);
465 assertOrPanic(@typeId(anyerror!i32) == Tid.ErrorUnion);
466 assertOrPanic(@typeId(anyerror) == Tid.ErrorSet);
467 assertOrPanic(@typeId(AnEnum) == Tid.Enum);
468 assertOrPanic(@typeId(@typeOf(AUnionEnum.One)) == Tid.Enum);
469 assertOrPanic(@typeId(AUnionEnum) == Tid.Union);
470 assertOrPanic(@typeId(AUnion) == Tid.Union);
471 assertOrPanic(@typeId(fn () void) == Tid.Fn);
472 assertOrPanic(@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 assertOrPanic(mem.eql(u8, @typeName(i64), "i64"));
489 assertOrPanic(mem.eql(u8, @typeName(*usize), "*usize"));
490 // https://github.com/ziglang/zig/issues/675
491 assertOrPanic(mem.eql(u8, @typeName(TypeFromFn(u8)), "TypeFromFn(u8)"));
492 assertOrPanic(mem.eql(u8, @typeName(Struct), "Struct"));
493 assertOrPanic(mem.eql(u8, @typeName(Union), "Union"));
494 assertOrPanic(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 assertOrPanic(x == 9);
505}
506fn nine() u8 {
507 return 9;
508}
509
510test "global variable initialized to global variable array element" {
511 assertOrPanic(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 assertOrPanic(*OpaqueA != *OpaqueB);
533 assertOrPanic(mem.eql(u8, @typeName(OpaqueA), "OpaqueA"));
534 assertOrPanic(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 assertOrPanic(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 assertOrPanic(s1.len == 0);
612 assertOrPanic(s2.len == 0);
613 assertOrPanic(mem.eql(u8, s1, ""));
614 assertOrPanic(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 assertOrPanic(addr1 == addr2);
621}
622
623test "equality compare fn ptrs" {
624 var a = emptyFn;
625 assertOrPanic(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 assertOrPanic(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 assertOrPanic(ptr.* == 1235);
648}
649
650test "slice string literal has type []const u8" {
651 comptime {
652 assertOrPanic(@typeOf("aoeu"[0..]) == []const u8);
653 const array = []i32{ 1, 2, 3, 4 };
654 assertOrPanic(@typeOf(array[0..]) == []const i32);
655 }
656}
657
658test "pointer child field" {
659 assertOrPanic((*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 assertOrPanic(block.kind == 1235);
679}
680
681test "fn call returning scalar optional in equality expression" {
682 assertOrPanic(getNull() == null);
683}
684
685fn getNull() ?*i32 {
686 return null;
687}
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 assertOrPanic = @import("std").debug.assertOrPanic;
3
4test "namespace depends on compile var" {
5 if (some_namespace.a_bool) {
6 assertOrPanic(some_namespace.a_bool);
7 } else {
8 assertOrPanic(!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 assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic(arg == 1234);
14 assertOrPanic(a < b);
15}
16
17fn targetFunction(x: i32) usize {
18 assertOrPanic(x == 1234);
19
20 var local_variable: i32 = 42;
21 const ptr = &local_variable;
22 ptr.* += 1;
23
24 assertOrPanic(local_variable == 43);
25 return @ptrToInt(ptr);
26}
test/stage1/behavior/null.zig created+162
...@@ -0,0 +1,162 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(z == 1234);
21
22 const final_x: ?i32 = 13;
23
24 const num = final_x orelse unreachable;
25
26 assertOrPanic(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 assertOrPanic(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 assertOrPanic(foo(1235).?);
51 if (foo(null) != null) unreachable;
52 assertOrPanic(!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 assertOrPanic(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 assertOrPanic(is_null);
88
89 const is_non_null = here_is_a_null_literal.context != null;
90 assertOrPanic(!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 assertOrPanic(x == null);
102 assertOrPanic(!(x != null));
103}
104
105test "optional void" {
106 optionalVoidImpl();
107 comptime optionalVoidImpl();
108}
109
110fn optionalVoidImpl() void {
111 assertOrPanic(bar(null) == null);
112 assertOrPanic(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 assertOrPanic(payload == 1234);
137 } else {
138 unreachable;
139 }
140}
141
142test "null with default unwrap" {
143 const x: i32 = null orelse 1;
144 assertOrPanic(x == 1);
145}
146
147test "optional types" {
148 comptime {
149 const opt_type_struct = StructWithOptionalType{ .t = u8 };
150 assertOrPanic(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 assertOrPanic(x == null);
162}
test/stage1/behavior/optional.zig created+81
...@@ -0,0 +1,81 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3pub const EmptyStruct = struct {};
4
5test "optional pointer to size zero struct" {
6 var e = EmptyStruct{};
7 var o: ?*EmptyStruct = &e;
8 assertOrPanic(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 assertOrPanic(x == y);
22 y = &number;
23 assertOrPanic(x != y);
24 assertOrPanic(x != &number);
25 assertOrPanic(&number != x);
26 x = &number;
27 assertOrPanic(x == y);
28 assertOrPanic(x == &number);
29 assertOrPanic(&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 assertOrPanic(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 assertOrPanic(S.entry());
61 comptime assertOrPanic(S.entry());
62}
63
64test "unwrap function call with optional pointer return value" {
65 const S = struct {
66 fn entry() void {
67 assertOrPanic(foo().?.* == 1234);
68 assertOrPanic(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+44
...@@ -0,0 +1,44 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic(x == 1235);
14}
15
16test "pointer arithmetic" {
17 var ptr = c"abcd";
18
19 assertOrPanic(ptr[0] == 'a');
20 ptr += 1;
21 assertOrPanic(ptr[0] == 'b');
22 ptr += 1;
23 assertOrPanic(ptr[0] == 'c');
24 ptr += 1;
25 assertOrPanic(ptr[0] == 'd');
26 ptr += 1;
27 assertOrPanic(ptr[0] == 0);
28 ptr -= 1;
29 assertOrPanic(ptr[0] == 'd');
30 ptr -= 1;
31 assertOrPanic(ptr[0] == 'c');
32 ptr -= 1;
33 assertOrPanic(ptr[0] == 'b');
34 ptr -= 1;
35 assertOrPanic(ptr[0] == 'a');
36}
37
38test "double pointer parsing" {
39 comptime assertOrPanic(PtrOf(PtrOf(i32)) == **i32);
40}
41
42fn PtrOf(comptime T: type) type {
43 return *T;
44}
test/stage1/behavior/popcount.zig created+25
...@@ -0,0 +1,25 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "@popCount" {
4 comptime testPopCount();
5 testPopCount();
6}
7
8fn testPopCount() void {
9 {
10 var x: u32 = 0xaa;
11 assertOrPanic(@popCount(x) == 4);
12 }
13 {
14 var x: u32 = 0xaaaaaaaa;
15 assertOrPanic(@popCount(x) == 16);
16 }
17 {
18 var x: i16 = -1;
19 assertOrPanic(@popCount(x) == 16);
20 }
21 comptime {
22 assertOrPanic(@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 assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic(@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 assertOrPanic(val == 5);
36}
37
38test "reinterpret struct field at comptime" {
39 const numLittle = comptime Bytes.init(0x12345678);
40 assertOrPanic(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 assertOrPanic = @import("std").debug.assertOrPanic;
3
4test "pub enum" {
5 pubEnumTest(other.APubEnum.Two);
6}
7fn pubEnumTest(foo: other.APubEnum) void {
8 assertOrPanic(foo == other.APubEnum.Two);
9}
10
11test "cast with imported symbol" {
12 assertOrPanic(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 assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(!ok);
8 foo(false, Num.One, false, "aoeu");
9 assertOrPanic(!ok);
10 foo(true, Num.One, false, "aoeu");
11 assertOrPanic(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 assertOrPanic(mem.eql(u8, x, "aoeu"));
36 ok = true;
37}
test/stage1/behavior/reflection.zig created+96
...@@ -0,0 +1,96 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2const mem = @import("std").mem;
3const reflection = @This();
4
5test "reflection: array, pointer, optional, error union type child" {
6 comptime {
7 assertOrPanic(([10]u8).Child == u8);
8 assertOrPanic((*u8).Child == u8);
9 assertOrPanic((anyerror!u8).Payload == u8);
10 assertOrPanic((?u8).Child == u8);
11 }
12}
13
14test "reflection: function return type, var args, and param types" {
15 comptime {
16 assertOrPanic(@typeOf(dummy).ReturnType == i32);
17 assertOrPanic(!@typeOf(dummy).is_var_args);
18 assertOrPanic(@typeOf(dummy_varargs).is_var_args);
19 assertOrPanic(@typeOf(dummy).arg_count == 3);
20 assertOrPanic(@ArgType(@typeOf(dummy), 0) == bool);
21 assertOrPanic(@ArgType(@typeOf(dummy), 1) == i32);
22 assertOrPanic(@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 assertOrPanic(@memberCount(Foo) == 3);
34
35 assertOrPanic(@memberType(Foo, 0) == i32);
36 assertOrPanic(@memberType(Foo, 1) == bool);
37 assertOrPanic(@memberType(Foo, 2) == void);
38
39 assertOrPanic(mem.eql(u8, @memberName(Foo, 0), "one"));
40 assertOrPanic(mem.eql(u8, @memberName(Foo, 1), "two"));
41 assertOrPanic(mem.eql(u8, @memberName(Foo, 2), "three"));
42 }
43}
44
45test "reflection: enum member types and names" {
46 comptime {
47 assertOrPanic(@memberCount(Bar) == 4);
48
49 assertOrPanic(@memberType(Bar, 0) == void);
50 assertOrPanic(@memberType(Bar, 1) == i32);
51 assertOrPanic(@memberType(Bar, 2) == bool);
52 assertOrPanic(@memberType(Bar, 3) == f64);
53
54 assertOrPanic(mem.eql(u8, @memberName(Bar, 0), "One"));
55 assertOrPanic(mem.eql(u8, @memberName(Bar, 1), "Two"));
56 assertOrPanic(mem.eql(u8, @memberName(Bar, 2), "Three"));
57 assertOrPanic(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 assertOrPanic(f.one == f.one);
69 assertOrPanic(@field(f, "o" ++ "ne") == f.one);
70 assertOrPanic(@field(f, "t" ++ "wo") == f.two);
71 assertOrPanic(@field(f, "th" ++ "ree") == f.three);
72 assertOrPanic(@field(Foo, "const" ++ "ant") == Foo.constant);
73 assertOrPanic(@field(Bar, "O" ++ "ne") == Bar.One);
74 assertOrPanic(@field(Bar, "T" ++ "wo") == Bar.Two);
75 assertOrPanic(@field(Bar, "Th" ++ "ree") == Bar.Three);
76 assertOrPanic(@field(Bar, "F" ++ "our") == Bar.Four);
77 assertOrPanic(@field(reflection, "dum" ++ "my")(true, 1, 2) == dummy(true, 1, 2));
78 @field(f, "o" ++ "ne") = 4;
79 assertOrPanic(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 assertOrPanic = @import("std").debug.assertOrPanic;
3
4test "@sizeOf and @typeOf" {
5 const y: @typeOf(x) = 120;
6 assertOrPanic(@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 assertOrPanic(@byteOffsetOf(P, "a") == 0);
34 assertOrPanic(@byteOffsetOf(P, "b") == 1);
35 assertOrPanic(@byteOffsetOf(P, "c") == 5);
36 assertOrPanic(@byteOffsetOf(P, "d") == 6);
37 assertOrPanic(@byteOffsetOf(P, "e") == 6);
38 assertOrPanic(@byteOffsetOf(P, "f") == 7);
39 assertOrPanic(@byteOffsetOf(P, "g") == 9);
40
41 // Normal struct fields can be moved/padded
42 var a: A = undefined;
43 assertOrPanic(@ptrToInt(&a.a) - @ptrToInt(&a) == @byteOffsetOf(A, "a"));
44 assertOrPanic(@ptrToInt(&a.b) - @ptrToInt(&a) == @byteOffsetOf(A, "b"));
45 assertOrPanic(@ptrToInt(&a.c) - @ptrToInt(&a) == @byteOffsetOf(A, "c"));
46 assertOrPanic(@ptrToInt(&a.d) - @ptrToInt(&a) == @byteOffsetOf(A, "d"));
47 assertOrPanic(@ptrToInt(&a.e) - @ptrToInt(&a) == @byteOffsetOf(A, "e"));
48 assertOrPanic(@ptrToInt(&a.f) - @ptrToInt(&a) == @byteOffsetOf(A, "f"));
49 assertOrPanic(@ptrToInt(&a.g) - @ptrToInt(&a) == @byteOffsetOf(A, "g"));
50}
51
52test "@bitOffsetOf" {
53 // Packed structs have fixed memory layout
54 assertOrPanic(@bitOffsetOf(P, "a") == 0);
55 assertOrPanic(@bitOffsetOf(P, "b") == 8);
56 assertOrPanic(@bitOffsetOf(P, "c") == 40);
57 assertOrPanic(@bitOffsetOf(P, "d") == 48);
58 assertOrPanic(@bitOffsetOf(P, "e") == 51);
59 assertOrPanic(@bitOffsetOf(P, "f") == 56);
60 assertOrPanic(@bitOffsetOf(P, "g") == 72);
61
62 assertOrPanic(@byteOffsetOf(A, "a") * 8 == @bitOffsetOf(A, "a"));
63 assertOrPanic(@byteOffsetOf(A, "b") * 8 == @bitOffsetOf(A, "b"));
64 assertOrPanic(@byteOffsetOf(A, "c") * 8 == @bitOffsetOf(A, "c"));
65 assertOrPanic(@byteOffsetOf(A, "d") * 8 == @bitOffsetOf(A, "d"));
66 assertOrPanic(@byteOffsetOf(A, "e") * 8 == @bitOffsetOf(A, "e"));
67 assertOrPanic(@byteOffsetOf(A, "f") * 8 == @bitOffsetOf(A, "f"));
68 assertOrPanic(@byteOffsetOf(A, "g") * 8 == @bitOffsetOf(A, "g"));
69}
test/stage1/behavior/slice.zig created+40
...@@ -0,0 +1,40 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(@ptrToInt(x.ptr) == 0x1000);
8 assertOrPanic(x.len == 0x500);
9
10 assertOrPanic(@ptrToInt(y.ptr) == 0x1100);
11 assertOrPanic(y.len == 0x400);
12}
13
14test "slice child property" {
15 var array: [5]i32 = undefined;
16 var slice = array[0..];
17 assertOrPanic(@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 assertOrPanic(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 assertOrPanic(msg.len == 0);
40}
test/stage1/behavior/struct.zig created+470
...@@ -0,0 +1,470 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(foo.b == 1);
38 assertOrPanic(@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 assertOrPanic(foo.c == 100);
54}
55const StructFoo = struct {
56 a: i32,
57 b: bool,
58 c: f32,
59};
60fn testFoo(foo: StructFoo) void {
61 assertOrPanic(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 assertOrPanic(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 assertOrPanic(foo2.a == 0);
96 foo2 = foo1;
97 assertOrPanic(foo2.a == 1234);
98}
99
100fn structInitializer() void {
101 const val = Val{ .x = 42 };
102 assertOrPanic(val.x == 42);
103}
104
105test "fn call of struct field" {
106 assertOrPanic(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 assertOrPanic(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 assertOrPanic(result == 1234);
138}
139
140test "member functions" {
141 const r = MemberFnRand{ .seed = 1234 };
142 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(getA(&data) == 1);
221 assertOrPanic(getB(&data) == 2);
222 assertOrPanic(getC(&data) == 3);
223 comptime assertOrPanic(@sizeOf(BitField1) == 1);
224
225 data.b += 1;
226 assertOrPanic(data.b == 3);
227
228 data.a += 1;
229 assertOrPanic(data.a == 2);
230 assertOrPanic(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 assertOrPanic(@sizeOf(Foo24Bits) == 3);
258 assertOrPanic(@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 assertOrPanic(value.a == 1);
269 assertOrPanic(value.b == 0);
270 assertOrPanic(value.c == 0);
271 assertOrPanic(value.d == 0);
272
273 value.b += 1;
274 assertOrPanic(value.a == 1);
275 assertOrPanic(value.b == 1);
276 assertOrPanic(value.c == 0);
277 assertOrPanic(value.d == 0);
278
279 value.c += 1;
280 assertOrPanic(value.a == 1);
281 assertOrPanic(value.b == 1);
282 assertOrPanic(value.c == 1);
283 assertOrPanic(value.d == 0);
284
285 value.d += 1;
286 assertOrPanic(value.a == 1);
287 assertOrPanic(value.b == 1);
288 assertOrPanic(value.c == 1);
289 assertOrPanic(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 assertOrPanic(@sizeOf([9]Foo24Bits) == 9 * 3);
301 assertOrPanic(@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 assertOrPanic(ptr.a == 0);
308 assertOrPanic(ptr.b[0].field == 0);
309 assertOrPanic(ptr.b[1].field == 0);
310 assertOrPanic(ptr.c == 0);
311
312 ptr.a = maxInt(u16);
313 assertOrPanic(ptr.a == maxInt(u16));
314 assertOrPanic(ptr.b[0].field == 0);
315 assertOrPanic(ptr.b[1].field == 0);
316 assertOrPanic(ptr.c == 0);
317
318 ptr.b[0].field = maxInt(u24);
319 assertOrPanic(ptr.a == maxInt(u16));
320 assertOrPanic(ptr.b[0].field == maxInt(u24));
321 assertOrPanic(ptr.b[1].field == 0);
322 assertOrPanic(ptr.c == 0);
323
324 ptr.b[1].field = maxInt(u24);
325 assertOrPanic(ptr.a == maxInt(u16));
326 assertOrPanic(ptr.b[0].field == maxInt(u24));
327 assertOrPanic(ptr.b[1].field == maxInt(u24));
328 assertOrPanic(ptr.c == 0);
329
330 ptr.c = maxInt(u16);
331 assertOrPanic(ptr.a == maxInt(u16));
332 assertOrPanic(ptr.b[0].field == maxInt(u24));
333 assertOrPanic(ptr.b[1].field == maxInt(u24));
334 assertOrPanic(ptr.c == maxInt(u16));
335
336 assertOrPanic(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 assertOrPanic(@sizeOf(FooStructAligned) == 2);
351 assertOrPanic(@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 assertOrPanic(ptr.a[0].a == 0xbb);
358 assertOrPanic(ptr.a[0].b == 0xbb);
359 assertOrPanic(ptr.a[1].a == 0xbb);
360 assertOrPanic(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 assertOrPanic(s1.x == x1);
374 assertOrPanic(s1.y == x1);
375 assertOrPanic(s2.x == @intCast(u4, x2));
376 assertOrPanic(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 assertOrPanic(bitfields.f1 == 0x1111);
404 assertOrPanic(bitfields.f2 == 0x2222);
405 assertOrPanic(bitfields.f3 == 0x33);
406 assertOrPanic(bitfields.f4 == 0x44);
407 assertOrPanic(bitfields.f5 == 0x5);
408 assertOrPanic(bitfields.f6 == 0x6);
409 assertOrPanic(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 assertOrPanic(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 assertOrPanic(S.doC(&s));
438 assertOrPanic(s.doC());
439 assertOrPanic(S.do(&s));
440 assertOrPanic(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 assertOrPanic(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 assertOrPanic(s.b == 0);
468 b_ptr.* = 2;
469 assertOrPanic(s.b == 2);
470}
test/stage1/behavior/struct_contains_null_ptr_itself.zig created+21
...@@ -0,0 +1,21 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4test "struct contains null pointer which contains original struct" {
5 var x: ?*NodeLineComment = null;
6 assertOrPanic(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 assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(root.payload == 1234);
43 assertOrPanic(root.children[0].payload == 1);
44 assertOrPanic(root.children[1].payload == 2);
45 assertOrPanic(root.children[2].payload == 3);
46 assertOrPanic(root.children[2].children[0].payload == 31);
47 assertOrPanic(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 assertOrPanic(root.payload == 1234);
80 assertOrPanic(root.children[0].payload == 1);
81 assertOrPanic(root.children[1].payload == 2);
82 assertOrPanic(root.children[2].payload == 3);
83 assertOrPanic(root.children[2].children[0].payload == 31);
84 assertOrPanic(root.children[2].children[1].payload == 32);
85}
test/stage1/behavior/switch.zig created+271
...@@ -0,0 +1,271 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(result);
14}
15
16test "switch with all ranges" {
17 assertOrPanic(testSwitchWithAllRanges(50, 3) == 1);
18 assertOrPanic(testSwitchWithAllRanges(101, 0) == 2);
19 assertOrPanic(testSwitchWithAllRanges(300, 5) == 3);
20 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(x == 13);
97 },
98 SwitchProngWithVarEnum.Two => |x| {
99 assertOrPanic(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| assertOrPanic(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 assertOrPanic(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 assertOrPanic(!returnsFalse());
153}
154
155test "switch on type" {
156 assertOrPanic(trueIfBoolFalseOtherwise(bool));
157 assertOrPanic(!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 assertOrPanic(testSwitchHandleAllCasesExhaustive(0) == 3);
174 assertOrPanic(testSwitchHandleAllCasesExhaustive(1) == 2);
175 assertOrPanic(testSwitchHandleAllCasesExhaustive(2) == 1);
176 assertOrPanic(testSwitchHandleAllCasesExhaustive(3) == 0);
177
178 assertOrPanic(testSwitchHandleAllCasesRange(100) == 0);
179 assertOrPanic(testSwitchHandleAllCasesRange(200) == 1);
180 assertOrPanic(testSwitchHandleAllCasesRange(201) == 2);
181 assertOrPanic(testSwitchHandleAllCasesRange(202) == 4);
182 assertOrPanic(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 assertOrPanic(switchWithUnreachable(1) == 2);
211 assertOrPanic(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 assertOrPanic(x == 1);
234}
235
236test "switching on booleans" {
237 testSwitchOnBools();
238 comptime testSwitchOnBools();
239}
240
241fn testSwitchOnBools() void {
242 assertOrPanic(testSwitchOnBoolsTrueAndFalse(true) == false);
243 assertOrPanic(testSwitchOnBoolsTrueAndFalse(false) == true);
244
245 assertOrPanic(testSwitchOnBoolsTrueWithElse(true) == false);
246 assertOrPanic(testSwitchOnBoolsTrueWithElse(false) == true);
247
248 assertOrPanic(testSwitchOnBoolsFalseWithElse(true) == false);
249 assertOrPanic(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 assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(payload == 1);
26 },
27 else => unreachable,
28 }
29 assertOrPanic(read_count == 1);
30}
test/stage1/behavior/switch_prong_implicit_cast.zig created+22
...@@ -0,0 +1,22 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(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 assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(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 assertOrPanic(pt.x == 13);
33 assertOrPanic(pt.y == 35);
34}
35
test/stage1/behavior/truncate.zig created+8
...@@ -0,0 +1,8 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic(y == 0);
8}
test/stage1/behavior/try.zig created+43
...@@ -0,0 +1,43 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(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 assertOrPanic(result1 == 2);
24
25 const result2 = if (failIfTrue(false)) 1 else |_| i32(2);
26 assertOrPanic(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 assertOrPanic(err == error.ItBroke);
42 }
43}
test/stage1/behavior/type_info.zig created+276
...@@ -0,0 +1,276 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(@TagType(TypeInfo) == TypeId);
13 const void_info = @typeInfo(void);
14 assertOrPanic(TypeId(void_info) == TypeId.Void);
15 assertOrPanic(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 assertOrPanic(TypeId(u8_info) == TypeId.Int);
26 assertOrPanic(!u8_info.Int.is_signed);
27 assertOrPanic(u8_info.Int.bits == 8);
28
29 const f64_info = @typeInfo(f64);
30 assertOrPanic(TypeId(f64_info) == TypeId.Float);
31 assertOrPanic(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 assertOrPanic(TypeId(u32_ptr_info) == TypeId.Pointer);
42 assertOrPanic(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.One);
43 assertOrPanic(u32_ptr_info.Pointer.is_const == false);
44 assertOrPanic(u32_ptr_info.Pointer.is_volatile == false);
45 assertOrPanic(u32_ptr_info.Pointer.alignment == @alignOf(u32));
46 assertOrPanic(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 assertOrPanic(TypeId(u32_ptr_info) == TypeId.Pointer);
57 assertOrPanic(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
58 assertOrPanic(u32_ptr_info.Pointer.is_const == true);
59 assertOrPanic(u32_ptr_info.Pointer.is_volatile == true);
60 assertOrPanic(u32_ptr_info.Pointer.alignment == @alignOf(f64));
61 assertOrPanic(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 assertOrPanic(TypeId(u32_slice_info) == TypeId.Pointer);
72 assertOrPanic(u32_slice_info.Pointer.size == TypeInfo.Pointer.Size.Slice);
73 assertOrPanic(u32_slice_info.Pointer.is_const == false);
74 assertOrPanic(u32_slice_info.Pointer.is_volatile == false);
75 assertOrPanic(u32_slice_info.Pointer.alignment == 4);
76 assertOrPanic(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 assertOrPanic(TypeId(arr_info) == TypeId.Array);
87 assertOrPanic(arr_info.Array.len == 42);
88 assertOrPanic(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 assertOrPanic(TypeId(null_info) == TypeId.Optional);
99 assertOrPanic(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 assertOrPanic(TypeId(null_promise_info) == TypeId.Promise);
110 assertOrPanic(null_promise_info.Promise.child == null);
111
112 const promise_info = @typeInfo(promise->usize);
113 assertOrPanic(TypeId(promise_info) == TypeId.Promise);
114 assertOrPanic(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 assertOrPanic(TypeId(error_set_info) == TypeId.ErrorSet);
131 assertOrPanic(error_set_info.ErrorSet.errors.len == 3);
132 assertOrPanic(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
133 assertOrPanic(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third));
134
135 const error_union_info = @typeInfo(TestErrorSet!usize);
136 assertOrPanic(TypeId(error_union_info) == TypeId.ErrorUnion);
137 assertOrPanic(error_union_info.ErrorUnion.error_set == TestErrorSet);
138 assertOrPanic(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 = enum {
148 Windows,
149 Macos,
150 Linux,
151 FreeBSD,
152 };
153
154 const os_info = @typeInfo(Os);
155 assertOrPanic(TypeId(os_info) == TypeId.Enum);
156 assertOrPanic(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
157 assertOrPanic(os_info.Enum.fields.len == 4);
158 assertOrPanic(mem.eql(u8, os_info.Enum.fields[1].name, "Macos"));
159 assertOrPanic(os_info.Enum.fields[3].value == 3);
160 assertOrPanic(os_info.Enum.tag_type == u2);
161 assertOrPanic(os_info.Enum.defs.len == 0);
162}
163
164test "type info: union info" {
165 testUnion();
166 comptime testUnion();
167}
168
169fn testUnion() void {
170 const typeinfo_info = @typeInfo(TypeInfo);
171 assertOrPanic(TypeId(typeinfo_info) == TypeId.Union);
172 assertOrPanic(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
173 assertOrPanic(typeinfo_info.Union.tag_type.? == TypeId);
174 assertOrPanic(typeinfo_info.Union.fields.len == 25);
175 assertOrPanic(typeinfo_info.Union.fields[4].enum_field != null);
176 assertOrPanic(typeinfo_info.Union.fields[4].enum_field.?.value == 4);
177 assertOrPanic(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
178 assertOrPanic(typeinfo_info.Union.defs.len == 21);
179
180 const TestNoTagUnion = union {
181 Foo: void,
182 Bar: u32,
183 };
184
185 const notag_union_info = @typeInfo(TestNoTagUnion);
186 assertOrPanic(TypeId(notag_union_info) == TypeId.Union);
187 assertOrPanic(notag_union_info.Union.tag_type == null);
188 assertOrPanic(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
189 assertOrPanic(notag_union_info.Union.fields.len == 2);
190 assertOrPanic(notag_union_info.Union.fields[0].enum_field == null);
191 assertOrPanic(notag_union_info.Union.fields[1].field_type == u32);
192
193 const TestExternUnion = extern union {
194 foo: *c_void,
195 };
196
197 const extern_union_info = @typeInfo(TestExternUnion);
198 assertOrPanic(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
199 assertOrPanic(extern_union_info.Union.tag_type == null);
200 assertOrPanic(extern_union_info.Union.fields[0].enum_field == null);
201 assertOrPanic(extern_union_info.Union.fields[0].field_type == *c_void);
202}
203
204test "type info: struct info" {
205 testStruct();
206 comptime testStruct();
207}
208
209fn testStruct() void {
210 const struct_info = @typeInfo(TestStruct);
211 assertOrPanic(TypeId(struct_info) == TypeId.Struct);
212 assertOrPanic(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
213 assertOrPanic(struct_info.Struct.fields.len == 3);
214 assertOrPanic(struct_info.Struct.fields[1].offset == null);
215 assertOrPanic(struct_info.Struct.fields[2].field_type == *TestStruct);
216 assertOrPanic(struct_info.Struct.defs.len == 2);
217 assertOrPanic(struct_info.Struct.defs[0].is_pub);
218 assertOrPanic(!struct_info.Struct.defs[0].data.Fn.is_extern);
219 assertOrPanic(struct_info.Struct.defs[0].data.Fn.lib_name == null);
220 assertOrPanic(struct_info.Struct.defs[0].data.Fn.return_type == void);
221 assertOrPanic(struct_info.Struct.defs[0].data.Fn.fn_type == fn (*const TestStruct) void);
222}
223
224const TestStruct = packed struct {
225 const Self = @This();
226
227 fieldA: usize,
228 fieldB: void,
229 fieldC: *Self,
230
231 pub fn foo(self: *const Self) void {}
232};
233
234test "type info: function type info" {
235 testFunction();
236 comptime testFunction();
237}
238
239fn testFunction() void {
240 const fn_info = @typeInfo(@typeOf(foo));
241 assertOrPanic(TypeId(fn_info) == TypeId.Fn);
242 assertOrPanic(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
243 assertOrPanic(fn_info.Fn.is_generic);
244 assertOrPanic(fn_info.Fn.args.len == 2);
245 assertOrPanic(fn_info.Fn.is_var_args);
246 assertOrPanic(fn_info.Fn.return_type == null);
247 assertOrPanic(fn_info.Fn.async_allocator_type == null);
248
249 const test_instance: TestStruct = undefined;
250 const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
251 assertOrPanic(TypeId(bound_fn_info) == TypeId.BoundFn);
252 assertOrPanic(bound_fn_info.BoundFn.args[0].arg_type.? == *const TestStruct);
253}
254
255fn foo(comptime a: usize, b: bool, args: ...) usize {
256 return 0;
257}
258
259test "typeInfo with comptime parameter in struct fn def" {
260 const S = struct {
261 pub fn func(comptime x: f32) void {}
262 };
263 comptime var info = @typeInfo(S);
264}
265
266test "type info: vectors" {
267 testVector();
268 comptime testVector();
269}
270
271fn testVector() void {
272 const vec_info = @typeInfo(@Vector(4, i32));
273 assertOrPanic(TypeId(vec_info) == TypeId.Vector);
274 assertOrPanic(vec_info.Vector.len == 4);
275 assertOrPanic(vec_info.Vector.child == i32);
276}
test/stage1/behavior/undefined.zig created+69
...@@ -0,0 +1,69 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(static_array[0] == 1);
15 assertOrPanic(static_array[4] == 2);
16 assertOrPanic(static_array[7] == 3);
17 assertOrPanic(static_array[9] == 4);
18
19 comptime {
20 assertOrPanic(static_array[0] == 1);
21 assertOrPanic(static_array[4] == 2);
22 assertOrPanic(static_array[7] == 3);
23 assertOrPanic(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 assertOrPanic(foo.x == 2);
44 }
45 {
46 var foo: Foo = undefined;
47 setFooX(&foo);
48 assertOrPanic(foo.x == 2);
49 }
50}
51
52test "assign undefined to struct with method" {
53 comptime {
54 var foo: Foo = undefined;
55 foo.setFooXMethod();
56 assertOrPanic(foo.x == 3);
57 }
58 {
59 var foo: Foo = undefined;
60 foo.setFooXMethod();
61 assertOrPanic(foo.x == 3);
62 }
63}
64
65test "type name of undefined" {
66 const x = undefined;
67 assertOrPanic(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 assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic = @import("std").debug.assertOrPanic;
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| assertOrPanic(arr[4] == 3),
31 else => unreachable,
32 }
33 switch ((err catch unreachable).val1) {
34 Value.Int => |x| assertOrPanic(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 assertOrPanic(foo.int == 1);
47 foo = Foo{ .float = 12.34 };
48 assertOrPanic(foo.float == 12.34);
49}
50
51test "comptime union field access" {
52 comptime {
53 var foo = Foo{ .int = 0 };
54 assertOrPanic(foo.int == 0);
55
56 foo = Foo{ .float = 42.42 };
57 assertOrPanic(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 assertOrPanic(foo.float == 12.34);
66
67 setInt(&foo, 42);
68 assertOrPanic(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 assertOrPanic(foo.int == 1);
87 foo.float = 12.34;
88 assertOrPanic(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 assertOrPanic(bar(Payload{ .A = 1234 }) == -10);
109}
110
111fn bar(value: Payload) i32 {
112 assertOrPanic(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 assertOrPanic(x == MultipleChoice.C);
129 assertOrPanic(@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 assertOrPanic(@TagType(@TagType(MultipleChoice2)) == u32);
146 testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
147 comptime testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
148}
149
150fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
151 assertOrPanic(@enumToInt(@TagType(MultipleChoice2)(x)) == 60);
152 assertOrPanic(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 assertOrPanic(@sizeOf(ExternPtrOrInt) == 8);
171}
172
173const PackedPtrOrInt = packed union {
174 ptr: *u8,
175 int: u64,
176};
177test "extern union size" {
178 comptime assertOrPanic(@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 assertOrPanic(@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 assertOrPanic(TheUnion.A == TheTag.A);
200 assertOrPanic(TheUnion.B == TheTag.B);
201 assertOrPanic(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 assertOrPanic(TheTag(x) == TheTag.B);
211}
212
213test "cast tag type of union to union" {
214 var x: Value2 = Letter2.B;
215 assertOrPanic(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 assertOrPanic(x == Letter2.B);
231 giveMeLetterB(x);
232}
233fn giveMeLetterB(x: Letter2) void {
234 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(Bar.A == u8);
286}
287
288test "tagged union initialization with runtime void" {
289 assertOrPanic(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 assertOrPanic(@TagType(Tag) == comptime_int);
328 var t = Tag(e);
329 assertOrPanic(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 assertOrPanic(@TagType(Tag) == comptime_int);
348 var t = Tag(e);
349 assertOrPanic(t == Expr.Literal);
350 assertOrPanic(@enumToInt(t) == 33);
351 comptime assertOrPanic(@enumToInt(t) == 33);
352}
test/stage1/behavior/var_args.zig created+84
...@@ -0,0 +1,84 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(add(i32(1), i32(2), i32(3), i32(4)) == 10);
16 assertOrPanic(add(i32(1234)) == 1234);
17 assertOrPanic(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 assertOrPanic(addSomeStuff(i32(1), i32(2), i32(3), i32(4)) == 10);
30 assertOrPanic(addSomeStuff(i32(1234)) == 1234);
31 assertOrPanic(addSomeStuff() == 0);
32}
33
34fn addSomeStuff(args: ...) i32 {
35 return add(args);
36}
37
38test "runtime parameter before var args" {
39 assertOrPanic(extraFn(10) == 0);
40 assertOrPanic(extraFn(10, false) == 1);
41 assertOrPanic(extraFn(10, false, true) == 2);
42
43 // TODO issue #313
44 //comptime {
45 // assertOrPanic(extraFn(10) == 0);
46 // assertOrPanic(extraFn(10, false) == 1);
47 // assertOrPanic(extraFn(10, false, true) == 2);
48 //}
49}
50
51fn extraFn(extra: u32, args: ...) usize {
52 if (args.len >= 1) {
53 assertOrPanic(args[0] == false);
54 }
55 if (args.len >= 2) {
56 assertOrPanic(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 assertOrPanic(foos[0]());
75 assertOrPanic(!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+20
...@@ -0,0 +1,20 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4test "implicit array to vector and vector to array" {
5 const S = struct {
6 fn doTheTest() void {
7 var v: @Vector(4, i32) = [4]i32{10, 20, 30, 40};
8 const x: @Vector(4, i32) = [4]i32{1, 2, 3, 4};
9 v +%= x;
10 const result: [4]i32 = v;
11 assertOrPanic(result[0] == 11);
12 assertOrPanic(result[1] == 22);
13 assertOrPanic(result[2] == 33);
14 assertOrPanic(result[3] == 44);
15 }
16 };
17 S.doTheTest();
18 comptime S.doTheTest();
19}
20
test/stage1/behavior/void.zig created+35
...@@ -0,0 +1,35 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
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 assertOrPanic(foo.a == {});
17 }
18}
19
20test "iterate over a void slice" {
21 var j: usize = 0;
22 for (times(10)) |_, i| {
23 assertOrPanic(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 assertOrPanic(x != null);
35}
test/stage1/behavior/while.zig created+228
...@@ -0,0 +1,228 @@
1const assertOrPanic = @import("std").debug.assertOrPanic;
2
3test "while loop" {
4 var i: i32 = 0;
5 while (i < 4) {
6 i += 1;
7 }
8 assertOrPanic(i == 4);
9 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(sum == 10);
82 assertOrPanic(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 assertOrPanic(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 assertOrPanic(got_else == 0);
101 } else {
102 got_else += 1;
103 }
104 assertOrPanic(sum == 45);
105 assertOrPanic(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 assertOrPanic(err == error.OutOfNumbers);
116 got_else += 1;
117 }
118 assertOrPanic(sum == 45);
119 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic(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 assertOrPanic = std.debug.assertOrPanic;
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 assertOrPanic(f == a);
13}
14
15test "implicit unsigned integer to signed integer" {
16 var a: u8 = 250;
17 var b: i16 = a;
18 assertOrPanic(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 assertOrPanic(d == a);
27}
28
test/tests.zig+70-48
...@@ -48,13 +48,14 @@ const test_targets = []TestTarget{...@@ -48,13 +48,14 @@ const test_targets = []TestTarget{
48const max_stdout_size = 1 * 1024 * 1024; // 1 MB48const max_stdout_size = 1 * 1024 * 1024; // 1 MB
4949
50pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {50pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
51 const cases = b.allocator.create(CompareOutputContext{51 const cases = b.allocator.create(CompareOutputContext) catch unreachable;
52 cases.* = CompareOutputContext{
52 .b = b,53 .b = b,
53 .step = b.step("test-compare-output", "Run the compare output tests"),54 .step = b.step("test-compare-output", "Run the compare output tests"),
54 .test_index = 0,55 .test_index = 0,
55 .test_filter = test_filter,56 .test_filter = test_filter,
56 .modes = modes,57 .modes = modes,
57 }) catch unreachable;58 };
5859
59 compare_output.addCases(cases);60 compare_output.addCases(cases);
6061
...@@ -62,13 +63,14 @@ pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes:...@@ -62,13 +63,14 @@ pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes:
62}63}
6364
64pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {65pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
65 const cases = b.allocator.create(CompareOutputContext{66 const cases = b.allocator.create(CompareOutputContext) catch unreachable;
67 cases.* = CompareOutputContext{
66 .b = b,68 .b = b,
67 .step = b.step("test-runtime-safety", "Run the runtime safety tests"),69 .step = b.step("test-runtime-safety", "Run the runtime safety tests"),
68 .test_index = 0,70 .test_index = 0,
69 .test_filter = test_filter,71 .test_filter = test_filter,
70 .modes = modes,72 .modes = modes,
71 }) catch unreachable;73 };
7274
73 runtime_safety.addCases(cases);75 runtime_safety.addCases(cases);
7476
...@@ -76,13 +78,14 @@ pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes:...@@ -76,13 +78,14 @@ pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes:
76}78}
7779
78pub fn addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {80pub fn addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
79 const cases = b.allocator.create(CompileErrorContext{81 const cases = b.allocator.create(CompileErrorContext) catch unreachable;
82 cases.* = CompileErrorContext{
80 .b = b,83 .b = b,
81 .step = b.step("test-compile-errors", "Run the compile error tests"),84 .step = b.step("test-compile-errors", "Run the compile error tests"),
82 .test_index = 0,85 .test_index = 0,
83 .test_filter = test_filter,86 .test_filter = test_filter,
84 .modes = modes,87 .modes = modes,
85 }) catch unreachable;88 };
8689
87 compile_errors.addCases(cases);90 compile_errors.addCases(cases);
8891
...@@ -90,13 +93,14 @@ pub fn addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes:...@@ -90,13 +93,14 @@ pub fn addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes:
90}93}
9194
92pub fn addBuildExampleTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {95pub fn addBuildExampleTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
93 const cases = b.allocator.create(BuildExamplesContext{96 const cases = b.allocator.create(BuildExamplesContext) catch unreachable;
97 cases.* = BuildExamplesContext{
94 .b = b,98 .b = b,
95 .step = b.step("test-build-examples", "Build the examples"),99 .step = b.step("test-build-examples", "Build the examples"),
96 .test_index = 0,100 .test_index = 0,
97 .test_filter = test_filter,101 .test_filter = test_filter,
98 .modes = modes,102 .modes = modes,
99 }) catch unreachable;103 };
100104
101 build_examples.addCases(cases);105 build_examples.addCases(cases);
102106
...@@ -119,13 +123,14 @@ pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const M...@@ -119,13 +123,14 @@ pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const M
119}123}
120124
121pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {125pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
122 const cases = b.allocator.create(CompareOutputContext{126 const cases = b.allocator.create(CompareOutputContext) catch unreachable;
127 cases.* = CompareOutputContext{
123 .b = b,128 .b = b,
124 .step = b.step("test-asm-link", "Run the assemble and link tests"),129 .step = b.step("test-asm-link", "Run the assemble and link tests"),
125 .test_index = 0,130 .test_index = 0,
126 .test_filter = test_filter,131 .test_filter = test_filter,
127 .modes = modes,132 .modes = modes,
128 }) catch unreachable;133 };
129134
130 assemble_and_link.addCases(cases);135 assemble_and_link.addCases(cases);
131136
...@@ -133,12 +138,13 @@ pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, mode...@@ -133,12 +138,13 @@ pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, mode
133}138}
134139
135pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step {140pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step {
136 const cases = b.allocator.create(TranslateCContext{141 const cases = b.allocator.create(TranslateCContext) catch unreachable;
142 cases.* = TranslateCContext{
137 .b = b,143 .b = b,
138 .step = b.step("test-translate-c", "Run the C transation tests"),144 .step = b.step("test-translate-c", "Run the C transation tests"),
139 .test_index = 0,145 .test_index = 0,
140 .test_filter = test_filter,146 .test_filter = test_filter,
141 }) catch unreachable;147 };
142148
143 translate_c.addCases(cases);149 translate_c.addCases(cases);
144150
...@@ -146,12 +152,13 @@ pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.St...@@ -146,12 +152,13 @@ pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.St
146}152}
147153
148pub fn addGenHTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step {154pub fn addGenHTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step {
149 const cases = b.allocator.create(GenHContext{155 const cases = b.allocator.create(GenHContext) catch unreachable;
156 cases.* = GenHContext{
150 .b = b,157 .b = b,
151 .step = b.step("test-gen-h", "Run the C header file generation tests"),158 .step = b.step("test-gen-h", "Run the C header file generation tests"),
152 .test_index = 0,159 .test_index = 0,
153 .test_filter = test_filter,160 .test_filter = test_filter,
154 }) catch unreachable;161 };
155162
156 gen_h.addCases(cases);163 gen_h.addCases(cases);
157164
...@@ -163,25 +170,32 @@ pub fn addPkgTests(b: *build.Builder, test_filter: ?[]const u8, root_src: []cons...@@ -163,25 +170,32 @@ pub fn addPkgTests(b: *build.Builder, test_filter: ?[]const u8, root_src: []cons
163 for (test_targets) |test_target| {170 for (test_targets) |test_target| {
164 const is_native = (test_target.os == builtin.os and test_target.arch == builtin.arch);171 const is_native = (test_target.os == builtin.os and test_target.arch == builtin.arch);
165 for (modes) |mode| {172 for (modes) |mode| {
166 for ([]bool{173 for ([]bool{ false, true }) |link_libc| {
167 false,174 for ([]bool{ false, true }) |single_threaded| {
168 true,175 if (link_libc and !is_native) {
169 }) |link_libc| {176 // don't assume we have a cross-compiling libc set up
170 if (link_libc and !is_native) {177 continue;
171 // don't assume we have a cross-compiling libc set up178 }
172 continue;179 const these_tests = b.addTest(root_src);
173 }180 these_tests.setNamePrefix(b.fmt(
174 const these_tests = b.addTest(root_src);181 "{}-{}-{}-{}-{}-{} ",
175 these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os), @tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare"));182 name,
176 these_tests.setFilter(test_filter);183 @tagName(test_target.os),
177 these_tests.setBuildMode(mode);184 @tagName(test_target.arch),
178 if (!is_native) {185 @tagName(mode),
179 these_tests.setTarget(test_target.arch, test_target.os, test_target.environ);186 if (link_libc) "c" else "bare",
180 }187 if (single_threaded) "single" else "multi",
181 if (link_libc) {188 ));
182 these_tests.linkSystemLibrary("c");189 these_tests.setFilter(test_filter);
190 these_tests.setBuildMode(mode);
191 if (!is_native) {
192 these_tests.setTarget(test_target.arch, test_target.os, test_target.environ);
193 }
194 if (link_libc) {
195 these_tests.linkSystemLibrary("c");
196 }
197 step.dependOn(&these_tests.step);
183 }198 }
184 step.dependOn(&these_tests.step);
185 }199 }
186 }200 }
187 }201 }
...@@ -237,7 +251,8 @@ pub const CompareOutputContext = struct {...@@ -237,7 +251,8 @@ pub const CompareOutputContext = struct {
237251
238 pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8, expected_output: []const u8, cli_args: []const []const u8) *RunCompareOutputStep {252 pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8, expected_output: []const u8, cli_args: []const []const u8) *RunCompareOutputStep {
239 const allocator = context.b.allocator;253 const allocator = context.b.allocator;
240 const ptr = allocator.create(RunCompareOutputStep{254 const ptr = allocator.create(RunCompareOutputStep) catch unreachable;
255 ptr.* = RunCompareOutputStep{
241 .context = context,256 .context = context,
242 .exe_path = exe_path,257 .exe_path = exe_path,
243 .name = name,258 .name = name,
...@@ -245,7 +260,7 @@ pub const CompareOutputContext = struct {...@@ -245,7 +260,7 @@ pub const CompareOutputContext = struct {
245 .test_index = context.test_index,260 .test_index = context.test_index,
246 .step = build.Step.init("RunCompareOutput", allocator, make),261 .step = build.Step.init("RunCompareOutput", allocator, make),
247 .cli_args = cli_args,262 .cli_args = cli_args,
248 }) catch unreachable;263 };
249 context.test_index += 1;264 context.test_index += 1;
250 return ptr;265 return ptr;
251 }266 }
...@@ -324,13 +339,14 @@ pub const CompareOutputContext = struct {...@@ -324,13 +339,14 @@ pub const CompareOutputContext = struct {
324339
325 pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8) *RuntimeSafetyRunStep {340 pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8) *RuntimeSafetyRunStep {
326 const allocator = context.b.allocator;341 const allocator = context.b.allocator;
327 const ptr = allocator.create(RuntimeSafetyRunStep{342 const ptr = allocator.create(RuntimeSafetyRunStep) catch unreachable;
343 ptr.* = RuntimeSafetyRunStep{
328 .context = context,344 .context = context,
329 .exe_path = exe_path,345 .exe_path = exe_path,
330 .name = name,346 .name = name,
331 .test_index = context.test_index,347 .test_index = context.test_index,
332 .step = build.Step.init("RuntimeSafetyRun", allocator, make),348 .step = build.Step.init("RuntimeSafetyRun", allocator, make),
333 }) catch unreachable;349 };
334350
335 context.test_index += 1;351 context.test_index += 1;
336 return ptr;352 return ptr;
...@@ -535,14 +551,15 @@ pub const CompileErrorContext = struct {...@@ -535,14 +551,15 @@ pub const CompileErrorContext = struct {
535551
536 pub fn create(context: *CompileErrorContext, name: []const u8, case: *const TestCase, build_mode: Mode) *CompileCmpOutputStep {552 pub fn create(context: *CompileErrorContext, name: []const u8, case: *const TestCase, build_mode: Mode) *CompileCmpOutputStep {
537 const allocator = context.b.allocator;553 const allocator = context.b.allocator;
538 const ptr = allocator.create(CompileCmpOutputStep{554 const ptr = allocator.create(CompileCmpOutputStep) catch unreachable;
555 ptr.* = CompileCmpOutputStep{
539 .step = build.Step.init("CompileCmpOutput", allocator, make),556 .step = build.Step.init("CompileCmpOutput", allocator, make),
540 .context = context,557 .context = context,
541 .name = name,558 .name = name,
542 .test_index = context.test_index,559 .test_index = context.test_index,
543 .case = case,560 .case = case,
544 .build_mode = build_mode,561 .build_mode = build_mode,
545 }) catch unreachable;562 };
546563
547 context.test_index += 1;564 context.test_index += 1;
548 return ptr;565 return ptr;
...@@ -654,13 +671,14 @@ pub const CompileErrorContext = struct {...@@ -654,13 +671,14 @@ pub const CompileErrorContext = struct {
654 }671 }
655672
656 pub fn create(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) *TestCase {673 pub fn create(self: *CompileErrorContext, name: []const u8, source: []const u8, expected_lines: ...) *TestCase {
657 const tc = self.b.allocator.create(TestCase{674 const tc = self.b.allocator.create(TestCase) catch unreachable;
675 tc.* = TestCase{
658 .name = name,676 .name = name,
659 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),677 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
660 .expected_errors = ArrayList([]const u8).init(self.b.allocator),678 .expected_errors = ArrayList([]const u8).init(self.b.allocator),
661 .link_libc = false,679 .link_libc = false,
662 .is_exe = false,680 .is_exe = false,
663 }) catch unreachable;681 };
664682
665 tc.addSourceFile(".tmp_source.zig", source);683 tc.addSourceFile(".tmp_source.zig", source);
666 comptime var arg_i = 0;684 comptime var arg_i = 0;
...@@ -814,13 +832,14 @@ pub const TranslateCContext = struct {...@@ -814,13 +832,14 @@ pub const TranslateCContext = struct {
814832
815 pub fn create(context: *TranslateCContext, name: []const u8, case: *const TestCase) *TranslateCCmpOutputStep {833 pub fn create(context: *TranslateCContext, name: []const u8, case: *const TestCase) *TranslateCCmpOutputStep {
816 const allocator = context.b.allocator;834 const allocator = context.b.allocator;
817 const ptr = allocator.create(TranslateCCmpOutputStep{835 const ptr = allocator.create(TranslateCCmpOutputStep) catch unreachable;
836 ptr.* = TranslateCCmpOutputStep{
818 .step = build.Step.init("ParseCCmpOutput", allocator, make),837 .step = build.Step.init("ParseCCmpOutput", allocator, make),
819 .context = context,838 .context = context,
820 .name = name,839 .name = name,
821 .test_index = context.test_index,840 .test_index = context.test_index,
822 .case = case,841 .case = case,
823 }) catch unreachable;842 };
824843
825 context.test_index += 1;844 context.test_index += 1;
826 return ptr;845 return ptr;
...@@ -921,12 +940,13 @@ pub const TranslateCContext = struct {...@@ -921,12 +940,13 @@ pub const TranslateCContext = struct {
921 }940 }
922941
923 pub fn create(self: *TranslateCContext, allow_warnings: bool, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) *TestCase {942 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{943 const tc = self.b.allocator.create(TestCase) catch unreachable;
944 tc.* = TestCase{
925 .name = name,945 .name = name,
926 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),946 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
927 .expected_lines = ArrayList([]const u8).init(self.b.allocator),947 .expected_lines = ArrayList([]const u8).init(self.b.allocator),
928 .allow_warnings = allow_warnings,948 .allow_warnings = allow_warnings,
929 }) catch unreachable;949 };
930950
931 tc.addSourceFile(filename, source);951 tc.addSourceFile(filename, source);
932 comptime var arg_i = 0;952 comptime var arg_i = 0;
...@@ -1008,14 +1028,15 @@ pub const GenHContext = struct {...@@ -1008,14 +1028,15 @@ pub const GenHContext = struct {
10081028
1009 pub fn create(context: *GenHContext, h_path: []const u8, name: []const u8, case: *const TestCase) *GenHCmpOutputStep {1029 pub fn create(context: *GenHContext, h_path: []const u8, name: []const u8, case: *const TestCase) *GenHCmpOutputStep {
1010 const allocator = context.b.allocator;1030 const allocator = context.b.allocator;
1011 const ptr = allocator.create(GenHCmpOutputStep{1031 const ptr = allocator.create(GenHCmpOutputStep) catch unreachable;
1032 ptr.* = GenHCmpOutputStep{
1012 .step = build.Step.init("ParseCCmpOutput", allocator, make),1033 .step = build.Step.init("ParseCCmpOutput", allocator, make),
1013 .context = context,1034 .context = context,
1014 .h_path = h_path,1035 .h_path = h_path,
1015 .name = name,1036 .name = name,
1016 .test_index = context.test_index,1037 .test_index = context.test_index,
1017 .case = case,1038 .case = case,
1018 }) catch unreachable;1039 };
10191040
1020 context.test_index += 1;1041 context.test_index += 1;
1021 return ptr;1042 return ptr;
...@@ -1055,11 +1076,12 @@ pub const GenHContext = struct {...@@ -1055,11 +1076,12 @@ pub const GenHContext = struct {
1055 }1076 }
10561077
1057 pub fn create(self: *GenHContext, filename: []const u8, name: []const u8, source: []const u8, expected_lines: ...) *TestCase {1078 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{1079 const tc = self.b.allocator.create(TestCase) catch unreachable;
1080 tc.* = TestCase{
1059 .name = name,1081 .name = name,
1060 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),1082 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
1061 .expected_lines = ArrayList([]const u8).init(self.b.allocator),1083 .expected_lines = ArrayList([]const u8).init(self.b.allocator),
1062 }) catch unreachable;1084 };
10631085
1064 tc.addSourceFile(filename, source);1086 tc.addSourceFile(filename, source);
1065 comptime var arg_i = 0;1087 comptime var arg_i = 0;