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:
1212 ninja install
1313 - test: |
1414 cd zig/build
15 bin/zig test ../test/behavior.zig
15 bin/zig test ../test/stage1/behavior.zig
1616 bin/zig test ../std/special/compiler_rt/index.zig
1717
18 bin/zig test ../test/behavior.zig --library c
18 bin/zig test ../test/stage1/behavior.zig --library c
1919 bin/zig test ../std/special/compiler_rt/index.zig --library c
2020
21 bin/zig test ../test/behavior.zig --release-fast
21 bin/zig test ../test/stage1/behavior.zig --release-fast
2222 bin/zig test ../std/special/compiler_rt/index.zig --release-fast
2323
24 bin/zig test ../test/behavior.zig --release-fast --library c
24 bin/zig test ../test/stage1/behavior.zig --release-fast --library c
2525 bin/zig test ../std/special/compiler_rt/index.zig --release-fast --library c
2626
27 bin/zig test ../test/behavior.zig --release-small --library c
27 bin/zig test ../test/stage1/behavior.zig --release-small --library c
2828 bin/zig test ../std/special/compiler_rt/index.zig --release-small --library c
2929
30 bin/zig test ../test/behavior.zig --release-small
30 bin/zig test ../test/stage1/behavior.zig --release-small
3131 bin/zig test ../std/special/compiler_rt/index.zig --release-small
3232
33 bin/zig test ../test/behavior.zig --release-safe
33 bin/zig test ../test/stage1/behavior.zig --release-safe
3434 bin/zig test ../std/special/compiler_rt/index.zig --release-safe
3535
36 bin/zig test ../test/behavior.zig --release-safe --library c
36 bin/zig test ../test/stage1/behavior.zig --release-safe --library c
3737 bin/zig test ../std/special/compiler_rt/index.zig --release-safe --library c
3838 # TODO enable all tests
3939 #bin/zig build --build-file ../build.zig test
CMakeLists.txt+16-15
......@@ -454,10 +454,10 @@ set(ZIG_STD_FILES
454454 "crypto/hmac.zig"
455455 "crypto/index.zig"
456456 "crypto/md5.zig"
457 "crypto/poly1305.zig"
457458 "crypto/sha1.zig"
458459 "crypto/sha2.zig"
459460 "crypto/sha3.zig"
460 "crypto/poly1305.zig"
461461 "crypto/x25519.zig"
462462 "cstr.zig"
463463 "debug/failing_allocator.zig"
......@@ -566,9 +566,9 @@ set(ZIG_STD_FILES
566566 "math/tan.zig"
567567 "math/tanh.zig"
568568 "math/trunc.zig"
569 "mem.zig"
569570 "meta/index.zig"
570571 "meta/trait.zig"
571 "mem.zig"
572572 "mutex.zig"
573573 "net.zig"
574574 "os/child_process.zig"
......@@ -576,16 +576,16 @@ set(ZIG_STD_FILES
576576 "os/darwin/errno.zig"
577577 "os/epoch.zig"
578578 "os/file.zig"
579 "os/freebsd/errno.zig"
580 "os/freebsd/index.zig"
579581 "os/get_app_data_dir.zig"
580582 "os/get_user_id.zig"
581583 "os/index.zig"
584 "os/linux/arm64.zig"
582585 "os/linux/errno.zig"
583586 "os/linux/index.zig"
584587 "os/linux/vdso.zig"
585588 "os/linux/x86_64.zig"
586 "os/linux/arm64.zig"
587 "os/freebsd/errno.zig"
588 "os/freebsd/index.zig"
589589 "os/path.zig"
590590 "os/time.zig"
591591 "os/uefi.zig"
......@@ -612,6 +612,16 @@ set(ZIG_STD_FILES
612612 "special/compiler_rt/comparetf2.zig"
613613 "special/compiler_rt/divti3.zig"
614614 "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"
615625 "special/compiler_rt/fixuint.zig"
616626 "special/compiler_rt/fixunsdfdi.zig"
617627 "special/compiler_rt/fixunsdfsi.zig"
......@@ -622,16 +632,6 @@ set(ZIG_STD_FILES
622632 "special/compiler_rt/fixunstfdi.zig"
623633 "special/compiler_rt/fixunstfsi.zig"
624634 "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"
635635 "special/compiler_rt/floattidf.zig"
636636 "special/compiler_rt/floattisf.zig"
637637 "special/compiler_rt/floattitf.zig"
......@@ -656,6 +656,7 @@ set(ZIG_STD_FILES
656656 "special/panic.zig"
657657 "special/test_runner.zig"
658658 "spinlock.zig"
659 "statically_initialized_mutex.zig"
659660 "unicode.zig"
660661 "zig/ast.zig"
661662 "zig/index.zig"
build.zig+10-11
......@@ -104,7 +104,7 @@ pub fn build(b: *Builder) !void {
104104 }
105105 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
109109 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 {
189189 const prefix_output = try b.exec([][]const u8{ llvm_config_exe, "--prefix" });
190190
191191 var result = LibraryDep{
192 .prefix = mem.split(prefix_output, " \r\n").next().?,
192 .prefix = mem.tokenize(prefix_output, " \r\n").next().?,
193193 .libs = ArrayList([]const u8).init(b.allocator),
194194 .system_libs = ArrayList([]const u8).init(b.allocator),
195195 .includes = ArrayList([]const u8).init(b.allocator),
196196 .libdirs = ArrayList([]const u8).init(b.allocator),
197197 };
198198 {
199 var it = mem.split(libs_output, " \r\n");
199 var it = mem.tokenize(libs_output, " \r\n");
200200 while (it.next()) |lib_arg| {
201201 if (mem.startsWith(u8, lib_arg, "-l")) {
202202 try result.system_libs.append(lib_arg[2..]);
......@@ -210,7 +210,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
210210 }
211211 }
212212 {
213 var it = mem.split(includes_output, " \r\n");
213 var it = mem.tokenize(includes_output, " \r\n");
214214 while (it.next()) |include_arg| {
215215 if (mem.startsWith(u8, include_arg, "-I")) {
216216 try result.includes.append(include_arg[2..]);
......@@ -220,7 +220,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
220220 }
221221 }
222222 {
223 var it = mem.split(libdir_output, " \r\n");
223 var it = mem.tokenize(libdir_output, " \r\n");
224224 while (it.next()) |libdir| {
225225 if (mem.startsWith(u8, libdir, "-L")) {
226226 try result.libdirs.append(libdir[2..]);
......@@ -233,7 +233,7 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
233233}
234234
235235pub fn installStdLib(b: *Builder, stdlib_files: []const u8) void {
236 var it = mem.split(stdlib_files, ";");
236 var it = mem.tokenize(stdlib_files, ";");
237237 while (it.next()) |stdlib_file| {
238238 const src_path = os.path.join(b.allocator, "std", stdlib_file) catch unreachable;
239239 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 {
242242}
243243
244244pub 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, ";");
246246 while (it.next()) |c_header_file| {
247247 const src_path = os.path.join(b.allocator, "c_headers", c_header_file) catch unreachable;
248248 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 {
277277 addCppLib(b, exe, ctx.cmake_binary_dir, "zig_cpp");
278278 if (ctx.lld_include_dir.len != 0) {
279279 exe.addIncludeDir(ctx.lld_include_dir);
280 var it = mem.split(ctx.lld_libraries, ";");
280 var it = mem.tokenize(ctx.lld_libraries, ";");
281281 while (it.next()) |lib| {
282282 exe.addObjectFile(lib);
283283 }
......@@ -299,8 +299,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
299299 } else if (exe.target.isFreeBSD()) {
300300 try addCxxKnownPath(b, ctx, exe, "libc++.a", null);
301301 exe.linkSystemLibrary("pthread");
302 }
303 else if (exe.target.isDarwin()) {
302 } else if (exe.target.isDarwin()) {
304303 if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) {
305304 // Compiler is GCC.
306305 try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null);
......@@ -335,7 +334,7 @@ fn addCxxKnownPath(
335334 ctx.cxx_compiler,
336335 b.fmt("-print-file-name={}", objname),
337336 });
338 const path_unpadded = mem.split(path_padded, "\r\n").next().?;
337 const path_unpadded = mem.tokenize(path_padded, "\r\n").next().?;
339338 if (mem.eql(u8, path_unpadded, objname)) {
340339 if (errtxt) |msg| {
341340 warn("{}", msg);
doc/langref.html.in+60-6
......@@ -1531,6 +1531,29 @@ test "array initialization with function calls" {
15311531 {#code_end#}
15321532 {#see_also|for|Slices#}
15331533 {#header_close#}
1534
1535 {#header_open|Vectors#}
1536 <p>
1537 A vector is a group of {#link|Integers#}, {#link|Floats#}, or {#link|Pointers#} which are operated on
1538 in parallel using a single instruction ({#link|SIMD#}). Vector types are created with the builtin
1539 function {#link|@Vector#}.
1540 </p>
1541 <p>
1542 TODO talk about C ABI interop
1543 </p>
1544 {#header_open|SIMD#}
1545 <p>
1546 TODO Zig's SIMD abilities are just beginning to be fleshed out. Here are some talking points to update the
1547 docs with:
1548 * What kind of operations can you do? All the operations on integers and floats? What about mixing scalar and vector?
1549 * How to convert to/from vectors/arrays
1550 * How to access individual elements from vectors, how to loop over the elements
1551 * "shuffle"
1552 * Advice on writing high perf software, how to abstract the best way
1553 </p>
1554 {#header_close#}
1555 {#header_close#}
1556
15341557 {#header_open|Pointers#}
15351558 <p>
15361559 Zig has two kinds of pointers:
......@@ -4327,7 +4350,7 @@ fn gimmeTheBiggerInteger(a: u64, b: u64) u64 {
43274350 <p>
43284351 For example, if we were to introduce another function to the above snippet:
43294352 </p>
4330 {#code_begin|test_err|unable to evaluate constant expression#}
4353 {#code_begin|test_err|values of type 'type' must be comptime known#}
43314354fn max(comptime T: type, a: T, b: T) T {
43324355 return if (a > b) a else b;
43334356}
......@@ -5905,13 +5928,13 @@ fn add(a: i32, b: i32) i32 { return a + b; }
59055928 This function is a low level intrinsic with no safety mechanisms. Most code
59065929 should not use this function, instead using something like this:
59075930 </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>
59095932 <p>
59105933 The optimizer is intelligent enough to turn the above snippet into a memcpy.
59115934 </p>
59125935 <p>There is also a standard library function for this:</p>
59135936 <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>
59155938 {#header_close#}
59165939
59175940 {#header_open|@memset#}
......@@ -5923,7 +5946,7 @@ mem.copy(u8, dest[0...byte_count], source[0...byte_count]);{#endsyntax#}</pre>
59235946 This function is a low level intrinsic with no safety mechanisms. Most
59245947 code should not use this function, instead using something like this:
59255948 </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>
59275950 <p>
59285951 The optimizer is intelligent enough to turn the above snippet into a memset.
59295952 </p>
......@@ -6592,9 +6615,10 @@ pub const TypeInfo = union(TypeId) {
65926615 {#header_close#}
65936616
65946617 {#header_open|@typeName#}
6595 <pre>{#syntax#}@typeName(T: type) []u8{#endsyntax#}</pre>
6618 <pre>{#syntax#}@typeName(T: type) [N]u8{#endsyntax#}</pre>
65966619 <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.
65986622 </p>
65996623
66006624 {#header_close#}
......@@ -6606,6 +6630,17 @@ pub const TypeInfo = union(TypeId) {
66066630 expression passed as an argument. The expression is evaluated.
66076631 </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>
66096644 {#header_close#}
66106645 {#header_close#}
66116646
......@@ -6679,6 +6714,25 @@ pub fn build(b: *Builder) void {
66796714 {#header_close#}
66806715 {#see_also|Compile Variables|Zig Build System|Undefined Behavior#}
66816716 {#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
66826736 {#header_open|Undefined Behavior#}
66836737 <p>
66846738 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 {
8383 const context_ref = c.LLVMContextCreate() orelse return error.OutOfMemory;
8484 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{
8788 .next = undefined,
8889 .data = context_ref,
89 });
90 };
9091 errdefer self.loop.allocator.destroy(node);
9192
9293 return LlvmHandle{ .node = node };
......@@ -596,7 +597,8 @@ pub const Compilation = struct {
596597 }
597598
598599 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{
600602 .base = Type{
601603 .name = "type",
602604 .base = Value{
......@@ -608,12 +610,13 @@ pub const Compilation = struct {
608610 .abi_alignment = Type.AbiAlignment.init(comp.loop),
609611 },
610612 .value = undefined,
611 });
613 };
612614 comp.meta_type.value = &comp.meta_type.base;
613615 comp.meta_type.base.base.typ = &comp.meta_type.base;
614616 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{
617620 .base = Type{
618621 .name = "void",
619622 .base = Value{
......@@ -624,10 +627,11 @@ pub const Compilation = struct {
624627 .id = builtin.TypeId.Void,
625628 .abi_alignment = Type.AbiAlignment.init(comp.loop),
626629 },
627 });
630 };
628631 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{
631635 .base = Type{
632636 .name = "noreturn",
633637 .base = Value{
......@@ -638,10 +642,11 @@ pub const Compilation = struct {
638642 .id = builtin.TypeId.NoReturn,
639643 .abi_alignment = Type.AbiAlignment.init(comp.loop),
640644 },
641 });
645 };
642646 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{
645650 .base = Type{
646651 .name = "comptime_int",
647652 .base = Value{
......@@ -652,10 +657,11 @@ pub const Compilation = struct {
652657 .id = builtin.TypeId.ComptimeInt,
653658 .abi_alignment = Type.AbiAlignment.init(comp.loop),
654659 },
655 });
660 };
656661 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{
659665 .base = Type{
660666 .name = "bool",
661667 .base = Value{
......@@ -666,45 +672,50 @@ pub const Compilation = struct {
666672 .id = builtin.TypeId.Bool,
667673 .abi_alignment = Type.AbiAlignment.init(comp.loop),
668674 },
669 });
675 };
670676 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{
673680 .base = Value{
674681 .id = Value.Id.Void,
675682 .typ = &Type.Void.get(comp).base,
676683 .ref_count = std.atomic.Int(usize).init(1),
677684 },
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{
681689 .base = Value{
682690 .id = Value.Id.Bool,
683691 .typ = &Type.Bool.get(comp).base,
684692 .ref_count = std.atomic.Int(usize).init(1),
685693 },
686694 .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{
690699 .base = Value{
691700 .id = Value.Id.Bool,
692701 .typ = &Type.Bool.get(comp).base,
693702 .ref_count = std.atomic.Int(usize).init(1),
694703 },
695704 .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{
699709 .base = Value{
700710 .id = Value.Id.NoReturn,
701711 .typ = &Type.NoReturn.get(comp).base,
702712 .ref_count = std.atomic.Int(usize).init(1),
703713 },
704 });
714 };
705715
706716 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{
708719 .base = Type{
709720 .name = cint.zig_name,
710721 .base = Value{
......@@ -720,11 +731,12 @@ pub const Compilation = struct {
720731 .bit_count = comp.target.cIntTypeSizeInBits(cint.id),
721732 },
722733 .garbage_node = undefined,
723 });
734 };
724735 comp.c_int_types[i] = c_int_type;
725736 assert((try comp.primitive_type_table.put(cint.zig_name, &c_int_type.base)) == null);
726737 }
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{
728740 .base = Type{
729741 .name = "u8",
730742 .base = Value{
......@@ -740,7 +752,7 @@ pub const Compilation = struct {
740752 .bit_count = 8,
741753 },
742754 .garbage_node = undefined,
743 });
755 };
744756 assert((try comp.primitive_type_table.put(comp.u8_type.base.name, &comp.u8_type.base)) == null);
745757 }
746758
......@@ -829,7 +841,7 @@ pub const Compilation = struct {
829841 };
830842 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);
833845 tree.* = try std.zig.parse(self.gpa(), source_code);
834846 errdefer {
835847 tree.deinit();
......@@ -925,7 +937,8 @@ pub const Compilation = struct {
925937 }
926938 } else {
927939 // 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{
929942 .base = Decl{
930943 .id = Decl.Id.Fn,
931944 .name = name,
......@@ -936,7 +949,7 @@ pub const Compilation = struct {
936949 },
937950 .value = Decl.Fn.Val{ .Unresolved = {} },
938951 .fn_proto = fn_proto,
939 });
952 };
940953 tree_scope.base.ref();
941954 errdefer self.gpa().destroy(fn_decl);
942955
......@@ -1140,12 +1153,13 @@ pub const Compilation = struct {
11401153 }
11411154 }
11421155
1143 const link_lib = try self.gpa().create(LinkLib{
1156 const link_lib = try self.gpa().create(LinkLib);
1157 link_lib.* = LinkLib{
11441158 .name = name,
11451159 .path = null,
11461160 .provided_explicitly = provided_explicitly,
11471161 .symbols = ArrayList([]u8).init(self.gpa()),
1148 });
1162 };
11491163 try self.link_libs_list.append(link_lib);
11501164 if (is_libc) {
11511165 self.libc_link_lib = link_lib;
src-self-hosted/errmsg.zig+12-8
......@@ -118,7 +118,8 @@ pub const Msg = struct {
118118 const realpath = try mem.dupe(comp.gpa(), u8, tree_scope.root().realpath);
119119 errdefer comp.gpa().free(realpath);
120120
121 const msg = try comp.gpa().create(Msg{
121 const msg = try comp.gpa().create(Msg);
122 msg.* = Msg{
122123 .text = text,
123124 .realpath = realpath,
124125 .data = Data{
......@@ -128,7 +129,7 @@ pub const Msg = struct {
128129 .span = span,
129130 },
130131 },
131 });
132 };
132133 tree_scope.base.ref();
133134 return msg;
134135 }
......@@ -139,13 +140,14 @@ pub const Msg = struct {
139140 const realpath_copy = try mem.dupe(comp.gpa(), u8, realpath);
140141 errdefer comp.gpa().free(realpath_copy);
141142
142 const msg = try comp.gpa().create(Msg{
143 const msg = try comp.gpa().create(Msg);
144 msg.* = Msg{
143145 .text = text,
144146 .realpath = realpath_copy,
145147 .data = Data{
146148 .Cli = Cli{ .allocator = comp.gpa() },
147149 },
148 });
150 };
149151 return msg;
150152 }
151153
......@@ -164,7 +166,8 @@ pub const Msg = struct {
164166 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
165167 try parse_error.render(&tree_scope.tree.tokens, out_stream);
166168
167 const msg = try comp.gpa().create(Msg{
169 const msg = try comp.gpa().create(Msg);
170 msg.* = Msg{
168171 .text = undefined,
169172 .realpath = realpath_copy,
170173 .data = Data{
......@@ -177,7 +180,7 @@ pub const Msg = struct {
177180 },
178181 },
179182 },
180 });
183 };
181184 tree_scope.base.ref();
182185 msg.text = text_buf.toOwnedSlice();
183186 return msg;
......@@ -203,7 +206,8 @@ pub const Msg = struct {
203206 var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
204207 try parse_error.render(&tree.tokens, out_stream);
205208
206 const msg = try allocator.create(Msg{
209 const msg = try allocator.create(Msg);
210 msg.* = Msg{
207211 .text = undefined,
208212 .realpath = realpath_copy,
209213 .data = Data{
......@@ -216,7 +220,7 @@ pub const Msg = struct {
216220 },
217221 },
218222 },
219 });
223 };
220224 msg.text = text_buf.toOwnedSlice();
221225 errdefer allocator.destroy(msg);
222226
src-self-hosted/ir.zig+9-6
......@@ -1021,12 +1021,13 @@ pub const Builder = struct {
10211021 pub const Error = Analyze.Error;
10221022
10231023 pub fn init(comp: *Compilation, tree_scope: *Scope.AstTree, begin_scope: ?*Scope) !Builder {
1024 const code = try comp.gpa().create(Code{
1024 const code = try comp.gpa().create(Code);
1025 code.* = Code{
10251026 .basic_block_list = undefined,
10261027 .arena = std.heap.ArenaAllocator.init(comp.gpa()),
10271028 .return_type = null,
10281029 .tree_scope = tree_scope,
1029 });
1030 };
10301031 code.basic_block_list = std.ArrayList(*BasicBlock).init(&code.arena.allocator);
10311032 errdefer code.destroy(comp.gpa());
10321033
......@@ -1052,7 +1053,8 @@ pub const Builder = struct {
10521053
10531054 /// No need to clean up resources thanks to the arena allocator.
10541055 pub fn createBasicBlock(self: *Builder, scope: *Scope, name_hint: [*]const u8) !*BasicBlock {
1055 const basic_block = try self.arena().create(BasicBlock{
1056 const basic_block = try self.arena().create(BasicBlock);
1057 basic_block.* = BasicBlock{
10561058 .ref_count = 0,
10571059 .name_hint = name_hint,
10581060 .debug_id = self.next_debug_id,
......@@ -1063,7 +1065,7 @@ pub const Builder = struct {
10631065 .ref_instruction = null,
10641066 .llvm_block = undefined,
10651067 .llvm_exit_block = undefined,
1066 });
1068 };
10671069 self.next_debug_id += 1;
10681070 return basic_block;
10691071 }
......@@ -1774,7 +1776,8 @@ pub const Builder = struct {
17741776 params: I.Params,
17751777 is_generated: bool,
17761778 ) !*Inst {
1777 const inst = try self.arena().create(I{
1779 const inst = try self.arena().create(I);
1780 inst.* = I{
17781781 .base = Inst{
17791782 .id = Inst.typeToId(I),
17801783 .is_generated = is_generated,
......@@ -1793,7 +1796,7 @@ pub const Builder = struct {
17931796 .owner_bb = self.current_basic_block,
17941797 },
17951798 .params = params,
1796 });
1799 };
17971800
17981801 // Look at the params and ref() other instructions
17991802 comptime var i = 0;
src-self-hosted/libc_installation.zig+4-4
......@@ -57,10 +57,10 @@ pub const LibCInstallation = struct {
5757 const contents = try std.io.readFileAlloc(allocator, libc_file);
5858 defer allocator.free(contents);
5959
60 var it = std.mem.split(contents, "\n");
60 var it = std.mem.tokenize(contents, "\n");
6161 while (it.next()) |line| {
6262 if (line.len == 0 or line[0] == '#') continue;
63 var line_it = std.mem.split(line, "=");
63 var line_it = std.mem.separate(line, "=");
6464 const name = line_it.next() orelse {
6565 try stderr.print("missing equal sign after field name\n");
6666 return error.ParseError;
......@@ -213,7 +213,7 @@ pub const LibCInstallation = struct {
213213 },
214214 }
215215
216 var it = std.mem.split(exec_result.stderr, "\n\r");
216 var it = std.mem.tokenize(exec_result.stderr, "\n\r");
217217 var search_paths = std.ArrayList([]const u8).init(loop.allocator);
218218 defer search_paths.deinit();
219219 while (it.next()) |line| {
......@@ -410,7 +410,7 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo
410410 return error.CCompilerCrashed;
411411 },
412412 }
413 var it = std.mem.split(exec_result.stdout, "\n\r");
413 var it = std.mem.tokenize(exec_result.stdout, "\n\r");
414414 const line = it.next() orelse return error.LibCRuntimeNotFound;
415415 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
351351 const root_name = if (provided_name) |n| n else blk: {
352352 if (root_source_file) |file| {
353353 const basename = os.path.basename(file);
354 var it = mem.split(basename, ".");
354 var it = mem.separate(basename, ".");
355355 break :blk it.next() orelse basename;
356356 } else {
357357 try stderr.write("--name [name] not provided and unable to infer\n");
......@@ -944,12 +944,13 @@ const CliPkg = struct {
944944 parent: ?*CliPkg,
945945
946946 pub fn init(allocator: *mem.Allocator, name: []const u8, path: []const u8, parent: ?*CliPkg) !*CliPkg {
947 var pkg = try allocator.create(CliPkg{
947 var pkg = try allocator.create(CliPkg);
948 pkg.* = CliPkg{
948949 .name = name,
949950 .path = path,
950951 .children = ArrayList(*CliPkg).init(allocator),
951952 .parent = parent,
952 });
953 };
953954 return pkg;
954955 }
955956
src-self-hosted/package.zig+4-2
......@@ -15,11 +15,13 @@ pub const Package = struct {
1515 /// makes internal copies of root_src_dir and root_src_path
1616 /// allocator should be an arena allocator because Package never frees anything
1717 pub fn create(allocator: *mem.Allocator, root_src_dir: []const u8, root_src_path: []const u8) !*Package {
18 return allocator.create(Package{
18 const ptr = try allocator.create(Package);
19 ptr.* = Package{
1920 .root_src_dir = try Buffer.init(allocator, root_src_dir),
2021 .root_src_path = try Buffer.init(allocator, root_src_path),
2122 .table = Table.init(allocator),
22 });
23 };
24 return ptr;
2325 }
2426
2527 pub fn add(self: *Package, name: []const u8, package: *Package) !void {
src-self-hosted/scope.zig+9-9
......@@ -120,7 +120,7 @@ pub const Scope = struct {
120120 /// Creates a Root scope with 1 reference
121121 /// Takes ownership of realpath
122122 pub fn create(comp: *Compilation, realpath: []u8) !*Root {
123 const self = try comp.gpa().createOne(Root);
123 const self = try comp.gpa().create(Root);
124124 self.* = Root{
125125 .base = Scope{
126126 .id = Id.Root,
......@@ -150,7 +150,7 @@ pub const Scope = struct {
150150 /// Creates a scope with 1 reference
151151 /// Takes ownership of tree, will deinit and destroy when done.
152152 pub fn create(comp: *Compilation, tree: *ast.Tree, root_scope: *Root) !*AstTree {
153 const self = try comp.gpa().createOne(AstTree);
153 const self = try comp.gpa().create(AstTree);
154154 self.* = AstTree{
155155 .base = undefined,
156156 .tree = tree,
......@@ -182,7 +182,7 @@ pub const Scope = struct {
182182
183183 /// Creates a Decls scope with 1 reference
184184 pub fn create(comp: *Compilation, parent: *Scope) !*Decls {
185 const self = try comp.gpa().createOne(Decls);
185 const self = try comp.gpa().create(Decls);
186186 self.* = Decls{
187187 .base = undefined,
188188 .table = event.RwLocked(Decl.Table).init(comp.loop, Decl.Table.init(comp.gpa())),
......@@ -235,7 +235,7 @@ pub const Scope = struct {
235235
236236 /// Creates a Block scope with 1 reference
237237 pub fn create(comp: *Compilation, parent: *Scope) !*Block {
238 const self = try comp.gpa().createOne(Block);
238 const self = try comp.gpa().create(Block);
239239 self.* = Block{
240240 .base = undefined,
241241 .incoming_values = undefined,
......@@ -262,7 +262,7 @@ pub const Scope = struct {
262262 /// Creates a FnDef scope with 1 reference
263263 /// Must set the fn_val later
264264 pub fn create(comp: *Compilation, parent: *Scope) !*FnDef {
265 const self = try comp.gpa().createOne(FnDef);
265 const self = try comp.gpa().create(FnDef);
266266 self.* = FnDef{
267267 .base = undefined,
268268 .fn_val = null,
......@@ -281,7 +281,7 @@ pub const Scope = struct {
281281
282282 /// Creates a CompTime scope with 1 reference
283283 pub fn create(comp: *Compilation, parent: *Scope) !*CompTime {
284 const self = try comp.gpa().createOne(CompTime);
284 const self = try comp.gpa().create(CompTime);
285285 self.* = CompTime{ .base = undefined };
286286 self.base.init(Id.CompTime, parent);
287287 return self;
......@@ -309,7 +309,7 @@ pub const Scope = struct {
309309 kind: Kind,
310310 defer_expr_scope: *DeferExpr,
311311 ) !*Defer {
312 const self = try comp.gpa().createOne(Defer);
312 const self = try comp.gpa().create(Defer);
313313 self.* = Defer{
314314 .base = undefined,
315315 .defer_expr_scope = defer_expr_scope,
......@@ -333,7 +333,7 @@ pub const Scope = struct {
333333
334334 /// Creates a DeferExpr scope with 1 reference
335335 pub fn create(comp: *Compilation, parent: *Scope, expr_node: *ast.Node) !*DeferExpr {
336 const self = try comp.gpa().createOne(DeferExpr);
336 const self = try comp.gpa().create(DeferExpr);
337337 self.* = DeferExpr{
338338 .base = undefined,
339339 .expr_node = expr_node,
......@@ -398,7 +398,7 @@ pub const Scope = struct {
398398 }
399399
400400 fn create(comp: *Compilation, parent: *Scope, name: []const u8, src_node: *ast.Node) !*Var {
401 const self = try comp.gpa().createOne(Var);
401 const self = try comp.gpa().create(Var);
402402 self.* = Var{
403403 .base = undefined,
404404 .name = name,
src-self-hosted/type.zig+26-7
......@@ -44,6 +44,7 @@ pub const Type = struct {
4444 Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),
4545 Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),
4646 Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(comp),
47 Id.Vector => @fieldParentPtr(Vector, "base", base).destroy(comp),
4748 }
4849 }
4950
......@@ -77,6 +78,7 @@ pub const Type = struct {
7778 Id.ArgTuple => unreachable,
7879 Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context),
7980 Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(allocator, llvm_context),
81 Id.Vector => return @fieldParentPtr(Vector, "base", base).getLlvmType(allocator, llvm_context),
8082 }
8183 }
8284
......@@ -103,6 +105,7 @@ pub const Type = struct {
103105 Id.Enum,
104106 Id.Fn,
105107 Id.Promise,
108 Id.Vector,
106109 => return false,
107110
108111 Id.Struct => @panic("TODO"),
......@@ -135,6 +138,7 @@ pub const Type = struct {
135138 Id.Float,
136139 Id.Fn,
137140 Id.Promise,
141 Id.Vector,
138142 => return true,
139143
140144 Id.Pointer => {
......@@ -409,7 +413,7 @@ pub const Type = struct {
409413 key.ref();
410414 errdefer key.deref(comp);
411415
412 const self = try comp.gpa().createOne(Fn);
416 const self = try comp.gpa().create(Fn);
413417 self.* = Fn{
414418 .base = undefined,
415419 .key = key,
......@@ -611,11 +615,12 @@ pub const Type = struct {
611615 }
612616 }
613617
614 const self = try comp.gpa().create(Int{
618 const self = try comp.gpa().create(Int);
619 self.* = Int{
615620 .base = undefined,
616621 .key = key,
617622 .garbage_node = undefined,
618 });
623 };
619624 errdefer comp.gpa().destroy(self);
620625
621626 const u_or_i = "ui"[@boolToInt(key.is_signed)];
......@@ -777,11 +782,12 @@ pub const Type = struct {
777782 }
778783 }
779784
780 const self = try comp.gpa().create(Pointer{
785 const self = try comp.gpa().create(Pointer);
786 self.* = Pointer{
781787 .base = undefined,
782788 .key = normal_key,
783789 .garbage_node = undefined,
784 });
790 };
785791 errdefer comp.gpa().destroy(self);
786792
787793 const size_str = switch (self.key.size) {
......@@ -875,11 +881,12 @@ pub const Type = struct {
875881 }
876882 }
877883
878 const self = try comp.gpa().create(Array{
884 const self = try comp.gpa().create(Array);
885 self.* = Array{
879886 .base = undefined,
880887 .key = key,
881888 .garbage_node = undefined,
882 });
889 };
883890 errdefer comp.gpa().destroy(self);
884891
885892 const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", key.len, key.elem_type.name);
......@@ -902,6 +909,18 @@ pub const Type = struct {
902909 }
903910 };
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
905924 pub const ComptimeFloat = struct {
906925 base: Type,
907926
src-self-hosted/value.zig+21-14
......@@ -135,14 +135,15 @@ pub const Value = struct {
135135 symbol_name: Buffer,
136136
137137 pub fn create(comp: *Compilation, fn_type: *Type.Fn, symbol_name: Buffer) !*FnProto {
138 const self = try comp.gpa().create(FnProto{
138 const self = try comp.gpa().create(FnProto);
139 self.* = FnProto{
139140 .base = Value{
140141 .id = Value.Id.FnProto,
141142 .typ = &fn_type.base,
142143 .ref_count = std.atomic.Int(usize).init(1),
143144 },
144145 .symbol_name = symbol_name,
145 });
146 };
146147 fn_type.base.base.ref();
147148 return self;
148149 }
......@@ -190,14 +191,16 @@ pub const Value = struct {
190191 /// Creates a Fn value with 1 ref
191192 /// Takes ownership of symbol_name
192193 pub fn create(comp: *Compilation, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: Buffer) !*Fn {
193 const link_set_node = try comp.gpa().create(Compilation.FnLinkSet.Node{
194 const link_set_node = try comp.gpa().create(Compilation.FnLinkSet.Node);
195 link_set_node.* = Compilation.FnLinkSet.Node{
194196 .data = null,
195197 .next = undefined,
196198 .prev = undefined,
197 });
199 };
198200 errdefer comp.gpa().destroy(link_set_node);
199201
200 const self = try comp.gpa().create(Fn{
202 const self = try comp.gpa().create(Fn);
203 self.* = Fn{
201204 .base = Value{
202205 .id = Value.Id.Fn,
203206 .typ = &fn_type.base,
......@@ -209,7 +212,7 @@ pub const Value = struct {
209212 .symbol_name = symbol_name,
210213 .containing_object = Buffer.initNull(comp.gpa()),
211214 .link_set_node = link_set_node,
212 });
215 };
213216 fn_type.base.base.ref();
214217 fndef_scope.fn_val = self;
215218 fndef_scope.base.ref();
......@@ -353,7 +356,8 @@ pub const Value = struct {
353356 var ptr_type_consumed = false;
354357 errdefer if (!ptr_type_consumed) ptr_type.base.base.deref(comp);
355358
356 const self = try comp.gpa().create(Value.Ptr{
359 const self = try comp.gpa().create(Value.Ptr);
360 self.* = Value.Ptr{
357361 .base = Value{
358362 .id = Value.Id.Ptr,
359363 .typ = &ptr_type.base,
......@@ -366,7 +370,7 @@ pub const Value = struct {
366370 },
367371 },
368372 .mut = Mut.CompTimeConst,
369 });
373 };
370374 ptr_type_consumed = true;
371375 errdefer comp.gpa().destroy(self);
372376
......@@ -430,14 +434,15 @@ pub const Value = struct {
430434 }) catch unreachable);
431435 errdefer array_type.base.base.deref(comp);
432436
433 const self = try comp.gpa().create(Value.Array{
437 const self = try comp.gpa().create(Value.Array);
438 self.* = Value.Array{
434439 .base = Value{
435440 .id = Value.Id.Array,
436441 .typ = &array_type.base,
437442 .ref_count = std.atomic.Int(usize).init(1),
438443 },
439444 .special = Special{ .OwnedBuffer = buffer },
440 });
445 };
441446 errdefer comp.gpa().destroy(self);
442447
443448 return self;
......@@ -509,14 +514,15 @@ pub const Value = struct {
509514 big_int: std.math.big.Int,
510515
511516 pub fn createFromString(comp: *Compilation, typ: *Type, base: u8, value: []const u8) !*Int {
512 const self = try comp.gpa().create(Value.Int{
517 const self = try comp.gpa().create(Value.Int);
518 self.* = Value.Int{
513519 .base = Value{
514520 .id = Value.Id.Int,
515521 .typ = typ,
516522 .ref_count = std.atomic.Int(usize).init(1),
517523 },
518524 .big_int = undefined,
519 });
525 };
520526 typ.base.ref();
521527 errdefer comp.gpa().destroy(self);
522528
......@@ -557,14 +563,15 @@ pub const Value = struct {
557563 old.base.typ.base.ref();
558564 errdefer old.base.typ.base.deref(comp);
559565
560 const new = try comp.gpa().create(Value.Int{
566 const new = try comp.gpa().create(Value.Int);
567 new.* = Value.Int{
561568 .base = Value{
562569 .id = Value.Id.Int,
563570 .typ = old.base.typ,
564571 .ref_count = std.atomic.Int(usize).init(1),
565572 },
566573 .big_int = undefined,
567 });
574 };
568575 errdefer comp.gpa().destroy(new);
569576
570577 new.big_int = try old.big_int.clone();
src/all_types.hpp+152-50
......@@ -56,9 +56,6 @@ struct IrExecutable {
5656 size_t next_debug_id;
5757 size_t *backward_branch_count;
5858 size_t backward_branch_quota;
59 bool invalid;
60 bool is_inline;
61 bool is_generic_instantiation;
6259 ZigFn *fn_entry;
6360 Buf *c_import_buf;
6461 AstNode *source_node;
......@@ -78,6 +75,10 @@ struct IrExecutable {
7875 IrBasicBlock *coro_suspend_block;
7976 IrBasicBlock *coro_final_cleanup_block;
8077 ZigVar *coro_allocator_var;
78
79 bool invalid;
80 bool is_inline;
81 bool is_generic_instantiation;
8182};
8283
8384enum OutType {
......@@ -90,6 +91,9 @@ enum OutType {
9091enum ConstParentId {
9192 ConstParentIdNone,
9293 ConstParentIdStruct,
94 ConstParentIdErrUnionCode,
95 ConstParentIdErrUnionPayload,
96 ConstParentIdOptionalPayload,
9397 ConstParentIdArray,
9498 ConstParentIdUnion,
9599 ConstParentIdScalar,
......@@ -107,6 +111,15 @@ struct ConstParent {
107111 ConstExprValue *struct_val;
108112 size_t field_index;
109113 } p_struct;
114 struct {
115 ConstExprValue *err_union_val;
116 } p_err_union_code;
117 struct {
118 ConstExprValue *err_union_val;
119 } p_err_union_payload;
120 struct {
121 ConstExprValue *optional_val;
122 } p_optional_payload;
110123 struct {
111124 ConstExprValue *union_val;
112125 } p_union;
......@@ -118,13 +131,11 @@ struct ConstParent {
118131
119132struct ConstStructValue {
120133 ConstExprValue *fields;
121 ConstParent parent;
122134};
123135
124136struct ConstUnionValue {
125137 BigInt tag;
126138 ConstExprValue *payload;
127 ConstParent parent;
128139};
129140
130141enum ConstArraySpecial {
......@@ -138,7 +149,6 @@ struct ConstArrayValue {
138149 union {
139150 struct {
140151 ConstExprValue *elements;
141 ConstParent parent;
142152 } s_none;
143153 Buf *s_buf;
144154 } data;
......@@ -153,19 +163,29 @@ enum ConstPtrSpecial {
153163 ConstPtrSpecialBaseArray,
154164 // The pointer points to a field in an underlying struct.
155165 ConstPtrSpecialBaseStruct,
166 // The pointer points to the error set field of an error union
167 ConstPtrSpecialBaseErrorUnionCode,
168 // The pointer points to the payload field of an error union
169 ConstPtrSpecialBaseErrorUnionPayload,
170 // The pointer points to the payload field of an optional
171 ConstPtrSpecialBaseOptionalPayload,
156172 // This means that we did a compile-time pointer reinterpret and we cannot
157173 // understand the value of pointee at compile time. However, we will still
158174 // emit a binary with a compile time known address.
159175 // In this case index is the numeric address value.
160 // We also use this for null pointer. We need the data layout for ConstCastOnly == true
161 // types to be the same, so all optionals of pointer types use x_ptr
162 // instead of x_optional
163176 ConstPtrSpecialHardCodedAddr,
164177 // This means that the pointer represents memory of assigning to _.
165178 // That is, storing discards the data, and loading is invalid.
166179 ConstPtrSpecialDiscard,
167180 // This is actually a function.
168181 ConstPtrSpecialFunction,
182 // This means the pointer is null. This is only allowed when the type is ?*T.
183 // We use this instead of ConstPtrSpecialHardCodedAddr because often we check
184 // for that value to avoid doing comptime work.
185 // We need the data layout for ConstCastOnly == true
186 // types to be the same, so all optionals of pointer types use x_ptr
187 // instead of x_optional.
188 ConstPtrSpecialNull,
169189};
170190
171191enum ConstPtrMut {
......@@ -199,6 +219,15 @@ struct ConstPtrValue {
199219 ConstExprValue *struct_val;
200220 size_t field_index;
201221 } base_struct;
222 struct {
223 ConstExprValue *err_union_val;
224 } base_err_union_code;
225 struct {
226 ConstExprValue *err_union_val;
227 } base_err_union_payload;
228 struct {
229 ConstExprValue *optional_val;
230 } base_optional_payload;
202231 struct {
203232 uint64_t addr;
204233 } hard_coded_addr;
......@@ -209,7 +238,7 @@ struct ConstPtrValue {
209238};
210239
211240struct ConstErrValue {
212 ErrorTableEntry *err;
241 ConstExprValue *error_set;
213242 ConstExprValue *payload;
214243};
215244
......@@ -265,6 +294,7 @@ struct ConstGlobalRefs {
265294struct ConstExprValue {
266295 ZigType *type;
267296 ConstValSpecial special;
297 ConstParent parent;
268298 ConstGlobalRefs *global_refs;
269299
270300 union {
......@@ -433,7 +463,7 @@ enum NodeType {
433463 NodeTypeArrayType,
434464 NodeTypeErrorType,
435465 NodeTypeIfErrorExpr,
436 NodeTypeTestExpr,
466 NodeTypeIfOptional,
437467 NodeTypeErrorSetDecl,
438468 NodeTypeCancel,
439469 NodeTypeResume,
......@@ -677,7 +707,7 @@ struct AstNodeUse {
677707 AstNode *expr;
678708
679709 TldResolution resolution;
680 IrInstruction *value;
710 ConstExprValue *value;
681711};
682712
683713struct AstNodeIfBoolExpr {
......@@ -1180,6 +1210,12 @@ struct ZigTypePromise {
11801210 ZigType *result_type;
11811211};
11821212
1213struct ZigTypeVector {
1214 // The type must be a pointer, integer, or float
1215 ZigType *elem_type;
1216 uint32_t len;
1217};
1218
11831219enum ZigTypeId {
11841220 ZigTypeIdInvalid,
11851221 ZigTypeIdMetaType,
......@@ -1206,6 +1242,7 @@ enum ZigTypeId {
12061242 ZigTypeIdArgTuple,
12071243 ZigTypeIdOpaque,
12081244 ZigTypeIdPromise,
1245 ZigTypeIdVector,
12091246};
12101247
12111248struct ZigType {
......@@ -1232,6 +1269,7 @@ struct ZigType {
12321269 ZigTypeFn fn;
12331270 ZigTypeBoundFn bound_fn;
12341271 ZigTypePromise promise;
1272 ZigTypeVector vector;
12351273 } data;
12361274
12371275 // use these fields to make sure we don't duplicate type table entries for the same type
......@@ -1385,6 +1423,7 @@ enum BuiltinFnId {
13851423 BuiltinFnIdEnumToInt,
13861424 BuiltinFnIdIntToEnum,
13871425 BuiltinFnIdIntType,
1426 BuiltinFnIdVectorType,
13881427 BuiltinFnIdSetCold,
13891428 BuiltinFnIdSetRuntimeSafety,
13901429 BuiltinFnIdSetFloatMode,
......@@ -1475,6 +1514,10 @@ struct TypeId {
14751514 ZigType *err_set_type;
14761515 ZigType *payload_type;
14771516 } error_union;
1517 struct {
1518 ZigType *elem_type;
1519 uint32_t len;
1520 } vector;
14781521 } data;
14791522};
14801523
......@@ -1610,7 +1653,7 @@ struct CodeGen {
16101653 HashMap<FnTypeId *, ZigType *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
16111654 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
16121655 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;
16141657 HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;
16151658 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names;
16161659 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
......@@ -1760,6 +1803,7 @@ struct CodeGen {
17601803 bool is_static;
17611804 bool strip_debug_symbols;
17621805 bool is_test_build;
1806 bool is_single_threaded;
17631807 bool is_native_target;
17641808 bool linker_rdynamic;
17651809 bool no_rosegment_workaround;
......@@ -1802,10 +1846,9 @@ enum VarLinkage {
18021846
18031847struct ZigVar {
18041848 Buf name;
1805 ConstExprValue *value;
1849 ConstExprValue *const_value;
1850 ZigType *var_type;
18061851 LLVMValueRef value_ref;
1807 bool src_is_const;
1808 bool gen_is_const;
18091852 IrInstruction *is_comptime;
18101853 // which node is the declaration of the variable
18111854 AstNode *decl_node;
......@@ -1815,17 +1858,21 @@ struct ZigVar {
18151858 Scope *parent_scope;
18161859 Scope *child_scope;
18171860 LLVMValueRef param_value_ref;
1818 bool shadowable;
18191861 size_t mem_slot_index;
18201862 IrExecutable *owner_exec;
18211863 size_t ref_count;
1822 VarLinkage linkage;
1823 uint32_t align_bytes;
18241864
18251865 // In an inline loop, multiple variables may be created,
18261866 // In this case, a reference to a variable should follow
18271867 // this pointer to the redefined variable.
18281868 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;
18291876};
18301877
18311878struct ErrorTableEntry {
......@@ -1891,10 +1938,11 @@ struct ScopeBlock {
18911938 ZigList<IrInstruction *> *incoming_values;
18921939 ZigList<IrBasicBlock *> *incoming_blocks;
18931940
1894 bool safety_off;
18951941 AstNode *safety_set_node;
1896 bool fast_math_on;
18971942 AstNode *fast_math_set_node;
1943
1944 bool safety_off;
1945 bool fast_math_on;
18981946};
18991947
19001948// This scope is created from every defer expression.
......@@ -2030,8 +2078,19 @@ struct IrBasicBlock {
20302078 IrInstruction *must_be_comptime_source_instr;
20312079};
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.
20332090enum IrInstructionId {
20342091 IrInstructionIdInvalid,
2092 IrInstructionIdDeclVarSrc,
2093 IrInstructionIdDeclVarGen,
20352094 IrInstructionIdBr,
20362095 IrInstructionIdCondBr,
20372096 IrInstructionIdSwitchBr,
......@@ -2040,7 +2099,6 @@ enum IrInstructionId {
20402099 IrInstructionIdPhi,
20412100 IrInstructionIdUnOp,
20422101 IrInstructionIdBinOp,
2043 IrInstructionIdDeclVar,
20442102 IrInstructionIdLoadPtr,
20452103 IrInstructionIdStorePtr,
20462104 IrInstructionIdFieldPtr,
......@@ -2069,7 +2127,7 @@ enum IrInstructionId {
20692127 IrInstructionIdAsm,
20702128 IrInstructionIdSizeOf,
20712129 IrInstructionIdTestNonNull,
2072 IrInstructionIdUnwrapOptional,
2130 IrInstructionIdOptionalUnwrapPtr,
20732131 IrInstructionIdOptionalWrap,
20742132 IrInstructionIdUnionTag,
20752133 IrInstructionIdClz,
......@@ -2085,7 +2143,8 @@ enum IrInstructionId {
20852143 IrInstructionIdCompileLog,
20862144 IrInstructionIdErrName,
20872145 IrInstructionIdEmbedFile,
2088 IrInstructionIdCmpxchg,
2146 IrInstructionIdCmpxchgSrc,
2147 IrInstructionIdCmpxchgGen,
20892148 IrInstructionIdFence,
20902149 IrInstructionIdTruncate,
20912150 IrInstructionIdIntCast,
......@@ -2094,6 +2153,7 @@ enum IrInstructionId {
20942153 IrInstructionIdFloatToInt,
20952154 IrInstructionIdBoolToInt,
20962155 IrInstructionIdIntType,
2156 IrInstructionIdVectorType,
20972157 IrInstructionIdBoolNot,
20982158 IrInstructionIdMemset,
20992159 IrInstructionIdMemcpy,
......@@ -2114,7 +2174,8 @@ enum IrInstructionId {
21142174 IrInstructionIdErrWrapPayload,
21152175 IrInstructionIdFnProto,
21162176 IrInstructionIdTestComptime,
2117 IrInstructionIdPtrCast,
2177 IrInstructionIdPtrCastSrc,
2178 IrInstructionIdPtrCastGen,
21182179 IrInstructionIdBitCast,
21192180 IrInstructionIdWidenOrShorten,
21202181 IrInstructionIdIntToPtr,
......@@ -2173,6 +2234,8 @@ enum IrInstructionId {
21732234 IrInstructionIdToBytes,
21742235 IrInstructionIdFromBytes,
21752236 IrInstructionIdCheckRuntimeScope,
2237 IrInstructionIdVectorToArray,
2238 IrInstructionIdArrayToVector,
21762239};
21772240
21782241struct IrInstruction {
......@@ -2194,6 +2257,22 @@ struct IrInstruction {
21942257 bool is_gen;
21952258};
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
21972276struct IrInstructionCondBr {
21982277 IrInstruction base;
21992278
......@@ -2302,20 +2381,11 @@ struct IrInstructionBinOp {
23022381 IrInstruction base;
23032382
23042383 IrInstruction *op1;
2305 IrBinOp op_id;
23062384 IrInstruction *op2;
2385 IrBinOp op_id;
23072386 bool safety_check_on;
23082387};
23092388
2310struct IrInstructionDeclVar {
2311 IrInstruction base;
2312
2313 ZigVar *var;
2314 IrInstruction *var_type;
2315 IrInstruction *align_value;
2316 IrInstruction *init_value;
2317};
2318
23192389struct IrInstructionLoadPtr {
23202390 IrInstruction base;
23212391
......@@ -2335,7 +2405,6 @@ struct IrInstructionFieldPtr {
23352405 IrInstruction *container_ptr;
23362406 Buf *field_name_buffer;
23372407 IrInstruction *field_name_expr;
2338 bool is_const;
23392408};
23402409
23412410struct IrInstructionStructFieldPtr {
......@@ -2378,13 +2447,13 @@ struct IrInstructionCall {
23782447 ZigFn *fn_entry;
23792448 size_t arg_count;
23802449 IrInstruction **args;
2381 bool is_comptime;
23822450 LLVMValueRef tmp_ptr;
2383 FnInline fn_inline;
2384 bool is_async;
23852451
23862452 IrInstruction *async_allocator;
23872453 IrInstruction *new_stack;
2454 FnInline fn_inline;
2455 bool is_async;
2456 bool is_comptime;
23882457};
23892458
23902459struct IrInstructionConst {
......@@ -2527,9 +2596,9 @@ struct IrInstructionSliceType {
25272596 IrInstruction base;
25282597
25292598 IrInstruction *align_value;
2599 IrInstruction *child_type;
25302600 bool is_const;
25312601 bool is_volatile;
2532 IrInstruction *child_type;
25332602};
25342603
25352604struct IrInstructionAsm {
......@@ -2557,10 +2626,12 @@ struct IrInstructionTestNonNull {
25572626 IrInstruction *value;
25582627};
25592628
2560struct IrInstructionUnwrapOptional {
2629// Takes a pointer to an optional value, returns a pointer
2630// to the payload.
2631struct IrInstructionOptionalUnwrapPtr {
25612632 IrInstruction base;
25622633
2563 IrInstruction *value;
2634 IrInstruction *base_ptr;
25642635 bool safety_check_on;
25652636};
25662637
......@@ -2651,7 +2722,7 @@ struct IrInstructionEmbedFile {
26512722 IrInstruction *name;
26522723};
26532724
2654struct IrInstructionCmpxchg {
2725struct IrInstructionCmpxchgSrc {
26552726 IrInstruction base;
26562727
26572728 IrInstruction *type_value;
......@@ -2661,14 +2732,19 @@ struct IrInstructionCmpxchg {
26612732 IrInstruction *success_order_value;
26622733 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
26692735 bool is_weak;
2736};
26702737
2738struct IrInstructionCmpxchgGen {
2739 IrInstruction base;
2740
2741 IrInstruction *ptr;
2742 IrInstruction *cmp_value;
2743 IrInstruction *new_value;
26712744 LLVMValueRef tmp_ptr;
2745 AtomicOrder success_order;
2746 AtomicOrder failure_order;
2747 bool is_weak;
26722748};
26732749
26742750struct IrInstructionFence {
......@@ -2748,6 +2824,13 @@ struct IrInstructionIntType {
27482824 IrInstruction *bit_count;
27492825};
27502826
2827struct IrInstructionVectorType {
2828 IrInstruction base;
2829
2830 IrInstruction *len;
2831 IrInstruction *elem_type;
2832};
2833
27512834struct IrInstructionBoolNot {
27522835 IrInstruction base;
27532836
......@@ -2851,7 +2934,7 @@ struct IrInstructionTestErr {
28512934struct IrInstructionUnwrapErrCode {
28522935 IrInstruction base;
28532936
2854 IrInstruction *value;
2937 IrInstruction *err_union;
28552938};
28562939
28572940struct IrInstructionUnwrapErrPayload {
......@@ -2899,13 +2982,19 @@ struct IrInstructionTestComptime {
28992982 IrInstruction *value;
29002983};
29012984
2902struct IrInstructionPtrCast {
2985struct IrInstructionPtrCastSrc {
29032986 IrInstruction base;
29042987
29052988 IrInstruction *dest_type;
29062989 IrInstruction *ptr;
29072990};
29082991
2992struct IrInstructionPtrCastGen {
2993 IrInstruction base;
2994
2995 IrInstruction *ptr;
2996};
2997
29092998struct IrInstructionBitCast {
29102999 IrInstruction base;
29113000
......@@ -3276,6 +3365,19 @@ struct IrInstructionBitReverse {
32763365 IrInstruction *op;
32773366};
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
32793381static const size_t slice_ptr_index = 0;
32803382static const size_t slice_len_index = 1;
32813383
src/analyze.cpp+361-151
......@@ -250,6 +250,7 @@ AstNode *type_decl_node(ZigType *type_entry) {
250250 case ZigTypeIdBoundFn:
251251 case ZigTypeIdArgTuple:
252252 case ZigTypeIdPromise:
253 case ZigTypeIdVector:
253254 return nullptr;
254255 }
255256 zig_unreachable();
......@@ -311,6 +312,7 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
311312 case ZigTypeIdBoundFn:
312313 case ZigTypeIdArgTuple:
313314 case ZigTypeIdPromise:
315 case ZigTypeIdVector:
314316 return true;
315317 }
316318 zig_unreachable();
......@@ -570,7 +572,7 @@ ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
570572 if (child_type->zero_bits) {
571573 entry->type_ref = LLVMInt1Type();
572574 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) {
574576 assert(child_type->di_type);
575577 // this is an optimization but also is necessary for calling C
576578 // functions where all pointers are maybe pointers
......@@ -1055,11 +1057,7 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
10551057 }
10561058 if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
10571059 X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);
1058 if (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));
1060 return abi_class == X64CABIClass_MEMORY;
10631061 } else if (target_is_arm(&g->zig_target)) {
10641062 return type_size(g, fn_type_id->return_type) > 16;
10651063 }
......@@ -1278,7 +1276,9 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind
12781276 return entry;
12791277}
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{
12821282 size_t backward_branch_count = 0;
12831283 return ir_eval_const_value(g, scope, node, type_entry,
12841284 &backward_branch_count, default_backward_branch_quota,
......@@ -1286,12 +1286,12 @@ static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *nod
12861286}
12871287
12881288ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
1289 IrInstruction *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
1290 if (result->value.type->id == ZigTypeIdInvalid)
1289 ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
1290 if (type_is_invalid(result->type))
12911291 return g->builtin_types.entry_invalid;
12921292
1293 assert(result->value.special != ConstValSpecialRuntime);
1294 return result->value.data.x_type;
1293 assert(result->special != ConstValSpecialRuntime);
1294 return result->data.x_type;
12951295}
12961296
12971297ZigType *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
13421342}
13431343
13441344static 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);
1346 if (type_is_invalid(align_result->value.type))
1345 ConstExprValue *align_result = analyze_const_value(g, scope, node, get_align_amt_type(g), nullptr);
1346 if (type_is_invalid(align_result->type))
13471347 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);
13501350 if (align_bytes == 0) {
13511351 add_node_error(g, node, buf_sprintf("alignment must be >= 1"));
13521352 return false;
......@@ -1364,12 +1364,12 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
13641364 ZigType *ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
13651365 PtrLenUnknown, 0, 0, 0);
13661366 ZigType *str_type = get_slice_type(g, ptr_type);
1367 IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr);
1368 if (type_is_invalid(instr->value.type))
1367 ConstExprValue *result_val = analyze_const_value(g, scope, node, str_type, nullptr);
1368 if (type_is_invalid(result_val->type))
13691369 return false;
13701370
1371 ConstExprValue *ptr_field = &instr->value.data.x_struct.fields[slice_ptr_index];
1372 ConstExprValue *len_field = &instr->value.data.x_struct.fields[slice_len_index];
1371 ConstExprValue *ptr_field = &result_val->data.x_struct.fields[slice_ptr_index];
1372 ConstExprValue *len_field = &result_val->data.x_struct.fields[slice_len_index];
13731373
13741374 assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray);
13751375 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) {
14221422 case ZigTypeIdPointer:
14231423 case ZigTypeIdArray:
14241424 case ZigTypeIdFn:
1425 case ZigTypeIdVector:
14251426 return true;
14261427 case ZigTypeIdStruct:
14271428 return type_entry->data.structure.layout == ContainerLayoutPacked;
......@@ -1470,6 +1471,8 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
14701471 default:
14711472 return false;
14721473 }
1474 case ZigTypeIdVector:
1475 return type_allowed_in_extern(g, type_entry->data.vector.elem_type);
14731476 case ZigTypeIdFloat:
14741477 return true;
14751478 case ZigTypeIdArray:
......@@ -1623,6 +1626,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
16231626 case ZigTypeIdUnion:
16241627 case ZigTypeIdFn:
16251628 case ZigTypeIdPromise:
1629 case ZigTypeIdVector:
16261630 switch (type_requires_comptime(g, type_entry)) {
16271631 case ReqCompTimeNo:
16281632 break;
......@@ -1718,6 +1722,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
17181722 case ZigTypeIdUnion:
17191723 case ZigTypeIdFn:
17201724 case ZigTypeIdPromise:
1725 case ZigTypeIdVector:
17211726 switch (type_requires_comptime(g, fn_type_id.return_type)) {
17221727 case ReqCompTimeInvalid:
17231728 return g->builtin_types.entry_invalid;
......@@ -2504,20 +2509,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) {
25042509 // In this first pass we resolve explicit tag values.
25052510 // In a second pass we will fill in the unspecified ones.
25062511 if (tag_value != nullptr) {
2507 IrInstruction *result_inst = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
2508 if (result_inst->value.type->id == ZigTypeIdInvalid) {
2512 ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
2513 if (type_is_invalid(result->type)) {
25092514 enum_type->data.enumeration.is_invalid = true;
25102515 continue;
25112516 }
2512 assert(result_inst->value.special != ConstValSpecialRuntime);
2513 assert(result_inst->value.type->id == ZigTypeIdInt ||
2514 result_inst->value.type->id == ZigTypeIdComptimeInt);
2515 auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);
2517 assert(result->special != ConstValSpecialRuntime);
2518 assert(result->type->id == ZigTypeIdInt ||
2519 result->type->id == ZigTypeIdComptimeInt);
2520 auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
25162521 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);
25182523 } else {
25192524 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
25222527 ErrorMsg *msg = add_node_error(g, tag_value,
25232528 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) {
29442949 // In a second pass we will fill in the unspecified ones.
29452950 if (tag_value != nullptr) {
29462951 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);
2948 if (result_inst->value.type->id == ZigTypeIdInvalid) {
2952 ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr);
2953 if (type_is_invalid(result->type)) {
29492954 union_type->data.unionation.is_invalid = true;
29502955 continue;
29512956 }
2952 assert(result_inst->value.special != ConstValSpecialRuntime);
2953 assert(result_inst->value.type->id == ZigTypeIdInt);
2954 auto entry = occupied_tag_values.put_unique(result_inst->value.data.x_bigint, tag_value);
2957 assert(result->special != ConstValSpecialRuntime);
2958 assert(result->type->id == ZigTypeIdInt);
2959 auto entry = occupied_tag_values.put_unique(result->data.x_bigint, tag_value);
29552960 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);
29572962 } else {
29582963 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
29612966 ErrorMsg *msg = add_node_error(g, tag_value,
29622967 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) {
34193424 resolve_top_level_decl(g, tld, false, tld->source_node);
34203425 assert(tld->id == TldIdVar);
34213426 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;
34233429 tld_var->var->align_bytes = get_abi_alignment(g, value->type);
34243430}
34253431
......@@ -3513,7 +3519,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
35133519 case NodeTypeArrayType:
35143520 case NodeTypeErrorType:
35153521 case NodeTypeIfErrorExpr:
3516 case NodeTypeTestExpr:
3522 case NodeTypeIfOptional:
35173523 case NodeTypeErrorSetDecl:
35183524 case NodeTypeCancel:
35193525 case NodeTypeResume:
......@@ -3574,6 +3580,7 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
35743580 case ZigTypeIdFn:
35753581 case ZigTypeIdBoundFn:
35763582 case ZigTypeIdPromise:
3583 case ZigTypeIdVector:
35773584 return type_entry;
35783585 }
35793586 zig_unreachable();
......@@ -3582,13 +3589,15 @@ ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry
35823589// Set name to nullptr to make the variable anonymous (not visible to programmer).
35833590// TODO merge with definition of add_local_var in ir.cpp
35843591ZigVar *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)
35863593{
35873594 Error err;
3588 assert(value);
3595 assert(const_value != nullptr);
3596 assert(var_type != nullptr);
35893597
35903598 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;
35923601 variable_entry->parent_scope = parent_scope;
35933602 variable_entry->shadowable = false;
35943603 variable_entry->mem_slot_index = SIZE_MAX;
......@@ -3597,23 +3606,23 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
35973606 assert(name);
35983607 buf_init_from_buf(&variable_entry->name, name);
35993608
3600 if ((err = type_resolve(g, value->type, ResolveStatusAlignmentKnown))) {
3601 variable_entry->value->type = g->builtin_types.entry_invalid;
3609 if ((err = type_resolve(g, var_type, ResolveStatusAlignmentKnown))) {
3610 variable_entry->var_type = g->builtin_types.entry_invalid;
36023611 } else {
3603 variable_entry->align_bytes = get_abi_alignment(g, value->type);
3612 variable_entry->align_bytes = get_abi_alignment(g, var_type);
36043613
36053614 ZigVar *existing_var = find_variable(g, parent_scope, name, nullptr);
36063615 if (existing_var && !existing_var->shadowable) {
36073616 ErrorMsg *msg = add_node_error(g, source_node,
36083617 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
36093618 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;
36113620 } else {
36123621 ZigType *type;
36133622 if (get_primitive_type(g, name, &type) != ErrorPrimitiveTypeNotFound) {
36143623 add_node_error(g, source_node,
36153624 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;
36173626 } else {
36183627 Scope *search_scope = nullptr;
36193628 if (src_tld == nullptr) {
......@@ -3627,7 +3636,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf
36273636 ErrorMsg *msg = add_node_error(g, source_node,
36283637 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
36293638 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;
36313640 }
36323641 }
36333642 }
......@@ -3677,7 +3686,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
36773686 linkage = VarLinkageInternal;
36783687 }
36793688
3680 IrInstruction *init_value = nullptr;
3689 ConstExprValue *init_value = nullptr;
36813690
36823691 // TODO more validation for types that can't be used for export/extern variables
36833692 ZigType *implicit_type = nullptr;
......@@ -3686,7 +3695,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
36863695 } else if (var_decl->expr) {
36873696 init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol);
36883697 assert(init_value);
3689 implicit_type = init_value->value.type;
3698 implicit_type = init_value->type;
36903699
36913700 if (implicit_type->id == ZigTypeIdUnreachable) {
36923701 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) {
37043713 add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant"));
37053714 implicit_type = g->builtin_types.entry_invalid;
37063715 }
3707 assert(implicit_type->id == ZigTypeIdInvalid || init_value->value.special != ConstValSpecialRuntime);
3716 assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime);
37083717 } else if (linkage != VarLinkageExternal) {
37093718 add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
37103719 implicit_type = g->builtin_types.entry_invalid;
......@@ -3713,19 +3722,19 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
37133722 ZigType *type = explicit_type ? explicit_type : implicit_type;
37143723 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
37183727 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);
37203729 tld_var->var->linkage = linkage;
37213730
37223731 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;
37243733 }
37253734
37263735 if (var_decl->align_expr != nullptr) {
37273736 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;
37293738 }
37303739 }
37313740
......@@ -3938,6 +3947,7 @@ static bool is_container(ZigType *type_entry) {
39383947 case ZigTypeIdArgTuple:
39393948 case ZigTypeIdOpaque:
39403949 case ZigTypeIdPromise:
3950 case ZigTypeIdVector:
39413951 return false;
39423952 }
39433953 zig_unreachable();
......@@ -3997,6 +4007,7 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) {
39974007 case ZigTypeIdArgTuple:
39984008 case ZigTypeIdOpaque:
39994009 case ZigTypeIdPromise:
4010 case ZigTypeIdVector:
40004011 zig_unreachable();
40014012 }
40024013}
......@@ -4090,7 +4101,7 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) {
40904101 }
40914102
40924103 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);
40944105 var->src_arg_index = i;
40954106 fn_table_entry->child_scope = var->child_scope;
40964107 var->shadowable = var->shadowable || is_var_args;
......@@ -4228,18 +4239,17 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *
42284239 preview_use_decl(g, src_use_node);
42294240 }
42304241
4231 IrInstruction *use_target_value = src_use_node->data.use.value;
4232 if (use_target_value->value.type->id == ZigTypeIdInvalid) {
4242 ConstExprValue *use_target_value = src_use_node->data.use.value;
4243 if (type_is_invalid(use_target_value->type)) {
42334244 dst_use_node->owner->any_imports_failed = true;
42344245 return;
42354246 }
42364247
42374248 dst_use_node->data.use.resolution = TldResolutionOk;
42384249
4239 ConstExprValue *const_val = &use_target_value->value;
4240 assert(const_val->special != ConstValSpecialRuntime);
4250 assert(use_target_value->special != ConstValSpecialRuntime);
42414251
4242 ImportTableEntry *target_import = const_val->data.x_import;
4252 ImportTableEntry *target_import = use_target_value->data.x_import;
42434253 assert(target_import);
42444254
42454255 if (target_import->any_imports_failed) {
......@@ -4302,10 +4312,10 @@ void preview_use_decl(CodeGen *g, AstNode *node) {
43024312 }
43034313
43044314 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,
43064316 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))
43094319 node->owner->any_imports_failed = true;
43104320
43114321 node->data.use.value = result;
......@@ -4447,6 +4457,42 @@ ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
44474457 return new_entry;
44484458}
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
44504496ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) {
44514497 return &g->builtin_types.entry_c_int[c_int_type];
44524498}
......@@ -4478,6 +4524,7 @@ bool handle_is_ptr(ZigType *type_entry) {
44784524 case ZigTypeIdFn:
44794525 case ZigTypeIdEnum:
44804526 case ZigTypeIdPromise:
4527 case ZigTypeIdVector:
44814528 return false;
44824529 case ZigTypeIdArray:
44834530 case ZigTypeIdStruct:
......@@ -4486,7 +4533,8 @@ bool handle_is_ptr(ZigType *type_entry) {
44864533 return type_has_bits(type_entry->data.error_union.payload_type);
44874534 case ZigTypeIdOptional:
44884535 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;
44904538 case ZigTypeIdUnion:
44914539 assert(type_entry->data.unionation.zero_bits_known);
44924540 if (type_entry->data.unionation.gen_field_count == 0)
......@@ -4732,6 +4780,11 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {
47324780 return true;
47334781}
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
47354788static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
47364789 uint32_t hash_val = 0;
47374790 switch (const_val->data.x_ptr.mut) {
......@@ -4763,6 +4816,18 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
47634816 hash_val += hash_ptr(const_val->data.x_ptr.data.base_struct.struct_val);
47644817 hash_val += hash_size(const_val->data.x_ptr.data.base_struct.field_index);
47654818 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;
47664831 case ConstPtrSpecialHardCodedAddr:
47674832 hash_val += (uint32_t)4048518294;
47684833 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) {
47744839 hash_val += (uint32_t)2590901619;
47754840 hash_val += hash_ptr(const_val->data.x_ptr.data.fn.fn_entry);
47764841 return hash_val;
4842 case ConstPtrSpecialNull:
4843 hash_val += (uint32_t)1486246455;
4844 return hash_val;
47774845 }
47784846 zig_unreachable();
47794847}
......@@ -4872,7 +4940,9 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
48724940 return 2709806591;
48734941 case ZigTypeIdOptional:
48744942 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;
48764946 } else {
48774947 if (const_val->data.x_optional) {
48784948 return hash_const_val(const_val->data.x_optional) * 1992916303;
......@@ -4884,10 +4954,12 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
48844954 // TODO better hashing algorithm
48854955 return 3415065496;
48864956 case ZigTypeIdErrorSet:
4887 assert(const_val->data.x_err_set != nullptr);
4888 return const_val->data.x_err_set->value ^ 2630160122;
4957 return hash_const_val_error_set(const_val);
48894958 case ZigTypeIdNamespace:
48904959 return hash_ptr(const_val->data.x_import);
4960 case ZigTypeIdVector:
4961 // TODO better hashing algorithm
4962 return 3647867726;
48914963 case ZigTypeIdBoundFn:
48924964 case ZigTypeIdInvalid:
48934965 case ZigTypeIdUnreachable:
......@@ -4940,6 +5012,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
49405012 case ZigTypeIdBool:
49415013 case ZigTypeIdUnreachable:
49425014 case ZigTypeIdInt:
5015 case ZigTypeIdVector:
49435016 case ZigTypeIdFloat:
49445017 case ZigTypeIdComptimeFloat:
49455018 case ZigTypeIdComptimeInt:
......@@ -4987,7 +5060,7 @@ static bool can_mutate_comptime_var_state(ConstExprValue *value) {
49875060 return can_mutate_comptime_var_state(value->data.x_optional);
49885061
49895062 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)
49915064 return false;
49925065 assert(value->data.x_err_union.payload != nullptr);
49935066 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) {
50235096 case ZigTypeIdErrorSet:
50245097 case ZigTypeIdEnum:
50255098 case ZigTypeIdPointer:
5099 case ZigTypeIdVector:
50265100 return true;
50275101
50285102 case ZigTypeIdArray:
......@@ -5048,9 +5122,9 @@ bool fn_eval_cacheable(Scope *scope, ZigType *return_type) {
50485122 while (scope) {
50495123 if (scope->id == ScopeIdVarDecl) {
50505124 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))
50525126 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))
50545128 return false;
50555129 } else if (scope->id == ScopeIdFnDef) {
50565130 return true;
......@@ -5068,7 +5142,7 @@ uint32_t fn_eval_hash(Scope* scope) {
50685142 while (scope) {
50695143 if (scope->id == ScopeIdVarDecl) {
50705144 ScopeVarDecl *var_scope = (ScopeVarDecl *)scope;
5071 result += hash_const_val(var_scope->var->value);
5145 result += hash_const_val(var_scope->var->const_value);
50725146 } else if (scope->id == ScopeIdFnDef) {
50735147 ScopeFnDef *fn_scope = (ScopeFnDef *)scope;
50745148 result += hash_ptr(fn_scope->fn_entry);
......@@ -5092,10 +5166,16 @@ bool fn_eval_eql(Scope *a, Scope *b) {
50925166 if (a->id == ScopeIdVarDecl) {
50935167 ScopeVarDecl *a_var_scope = (ScopeVarDecl *)a;
50945168 ScopeVarDecl *b_var_scope = (ScopeVarDecl *)b;
5095 if (a_var_scope->var->value->type != b_var_scope->var->value->type)
5096 return false;
5097 if (!const_values_equal(a->codegen, a_var_scope->var->value, b_var_scope->var->value))
5169 if (a_var_scope->var->var_type != b_var_scope->var->var_type)
50985170 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 }
50995179 } else if (a->id == ScopeIdFnDef) {
51005180 ScopeFnDef *a_fn_scope = (ScopeFnDef *)a;
51015181 ScopeFnDef *b_fn_scope = (ScopeFnDef *)b;
......@@ -5113,6 +5193,7 @@ bool fn_eval_eql(Scope *a, Scope *b) {
51135193 return false;
51145194}
51155195
5196// Whether the type has bits at runtime.
51165197bool type_has_bits(ZigType *type_entry) {
51175198 assert(type_entry);
51185199 assert(!type_is_invalid(type_entry));
......@@ -5120,6 +5201,66 @@ bool type_has_bits(ZigType *type_entry) {
51205201 return !type_entry->zero_bits;
51215202}
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
51235264ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
51245265 Error err;
51255266 if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
......@@ -5159,6 +5300,7 @@ ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry) {
51595300 case ZigTypeIdErrorSet:
51605301 case ZigTypeIdBool:
51615302 case ZigTypeIdInt:
5303 case ZigTypeIdVector:
51625304 case ZigTypeIdFloat:
51635305 case ZigTypeIdVoid:
51645306 case ZigTypeIdUnreachable:
......@@ -5574,6 +5716,33 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
55745716 if (a->data.x_ptr.data.base_struct.field_index != b->data.x_ptr.data.base_struct.field_index)
55755717 return false;
55765718 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;
55775746 case ConstPtrSpecialHardCodedAddr:
55785747 if (a->data.x_ptr.data.hard_coded_addr.addr != b->data.x_ptr.data.hard_coded_addr.addr)
55795748 return false;
......@@ -5582,10 +5751,34 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
55825751 return true;
55835752 case ConstPtrSpecialFunction:
55845753 return a->data.x_ptr.data.fn.fn_entry == b->data.x_ptr.data.fn.fn_entry;
5754 case ConstPtrSpecialNull:
5755 return true;
55855756 }
55865757 zig_unreachable();
55875758}
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
55895782bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
55905783 assert(a->type->id == b->type->id);
55915784 assert(a->special == ConstValSpecialStatic);
......@@ -5640,28 +5833,12 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
56405833 case ZigTypeIdPointer:
56415834 case ZigTypeIdFn:
56425835 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);
56435839 case ZigTypeIdArray: {
56445840 assert(a->type->data.array.len == b->type->data.array.len);
5645 assert(a->data.x_array.special != ConstArraySpecialUndef);
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;
5841 return const_values_equal_array(g, a, b, a->type->data.array.len);
56655842 }
56665843 case ZigTypeIdStruct:
56675844 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
57505927 }
57515928}
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) {
57545931 assert(type_entry->id == ZigTypeIdPointer);
57555932
57565933 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
57635940 zig_unreachable();
57645941 case ConstPtrSpecialRef:
57655942 case ConstPtrSpecialBaseStruct:
5943 case ConstPtrSpecialBaseErrorUnionCode:
5944 case ConstPtrSpecialBaseErrorUnionPayload:
5945 case ConstPtrSpecialBaseOptionalPayload:
57665946 buf_appendf(buf, "*");
57675947 // TODO we need a source node for const_ptr_pointee because it can generate compile errors
57685948 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
57905970 buf_appendf(buf, "@ptrCast(%s, %s)", buf_ptr(&const_val->type->name), buf_ptr(&fn_entry->symbol_name));
57915971 return;
57925972 }
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 }
57936018 }
57946019 zig_unreachable();
57956020}
......@@ -5874,39 +6099,10 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
58746099 }
58756100 case ZigTypeIdPointer:
58766101 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);
58776104 case ZigTypeIdArray:
5878 switch (const_val->data.x_array.special) {
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();
6105 return render_const_val_array(g, buf, const_val, type_entry->data.array.len);
59106106 case ZigTypeIdNull:
59116107 {
59126108 buf_appendf(buf, "null");
......@@ -5921,6 +6117,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
59216117 {
59226118 if (get_codegen_ptr_type(const_val->type) != nullptr)
59236119 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);
59246122 if (const_val->data.x_optional) {
59256123 render_const_value(g, buf, const_val->data.x_optional);
59266124 } else {
......@@ -5958,11 +6156,12 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
59586156 case ZigTypeIdErrorUnion:
59596157 {
59606158 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) {
59626161 render_const_value(g, buf, const_val->data.x_err_union.payload);
59636162 } else {
59646163 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));
59666165 }
59676166 buf_appendf(buf, ")");
59686167 return;
......@@ -5977,10 +6176,7 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
59776176 return;
59786177 }
59796178 case ZigTypeIdErrorSet:
5980 {
5981 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->name), buf_ptr(&const_val->data.x_err_set->name));
5982 return;
5983 }
6179 return render_const_val_err_set(g, buf, const_val, type_entry);
59846180 case ZigTypeIdArgTuple:
59856181 {
59866182 buf_appendf(buf, "(args value)");
......@@ -6065,6 +6261,8 @@ uint32_t type_id_hash(TypeId x) {
60656261 case ZigTypeIdInt:
60666262 return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) +
60676263 (((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);
60686266 }
60696267 zig_unreachable();
60706268}
......@@ -6113,6 +6311,9 @@ bool type_id_eql(TypeId a, TypeId b) {
61136311 case ZigTypeIdInt:
61146312 return a.data.integer.is_signed == b.data.integer.is_signed &&
61156313 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;
61166317 }
61176318 zig_unreachable();
61186319}
......@@ -6171,24 +6372,34 @@ bool zig_llvm_fn_key_eql(ZigLLVMFnKey a, ZigLLVMFnKey b) {
61716372
61726373// Canonicalize the array value as ConstArraySpecialNone
61736374void 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 }
61756390 switch (const_val->data.x_array.special) {
61766391 case ConstArraySpecialNone:
61776392 return;
61786393 case ConstArraySpecialUndef: {
61796394 const_val->data.x_array.special = ConstArraySpecialNone;
6180 size_t elem_count = const_val->type->data.array.len;
61816395 const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count);
61826396 for (size_t i = 0; i < elem_count; i += 1) {
61836397 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;
61856399 init_const_undefined(g, element_val);
6186 ConstParent *parent = get_const_val_parent(g, element_val);
6187 if (parent != nullptr) {
6188 parent->id = ConstParentIdArray;
6189 parent->data.p_array.array_val = const_val;
6190 parent->data.p_array.elem_index = i;
6191 }
6400 element_val->parent.id = ConstParentIdArray;
6401 element_val->parent.data.p_array.array_val = const_val;
6402 element_val->parent.data.p_array.elem_index = i;
61926403 }
61936404 return;
61946405 }
......@@ -6199,7 +6410,6 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
61996410 g->string_literals_table.maybe_remove(buf);
62006411
62016412 const_val->data.x_array.special = ConstArraySpecialNone;
6202 size_t elem_count = const_val->type->data.array.len;
62036413 assert(elem_count == buf_len(buf));
62046414 const_val->data.x_array.data.s_none.elements = create_const_vals(elem_count);
62056415 for (size_t i = 0; i < elem_count; i += 1) {
......@@ -6207,6 +6417,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
62076417 this_char->special = ConstValSpecialStatic;
62086418 this_char->type = g->builtin_types.entry_u8;
62096419 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;
62106423 }
62116424 return;
62126425 }
......@@ -6214,18 +6427,9 @@ void expand_undef_array(CodeGen *g, ConstExprValue *const_val) {
62146427 zig_unreachable();
62156428}
62166429
6430// Deprecated. Reference the parent field directly.
62176431ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) {
6218 assert(value->type);
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;
6432 return &value->parent;
62296433}
62306434
62316435static const ZigTypeId all_type_ids[] = {
......@@ -6253,6 +6457,7 @@ static const ZigTypeId all_type_ids[] = {
62536457 ZigTypeIdArgTuple,
62546458 ZigTypeIdOpaque,
62556459 ZigTypeIdPromise,
6460 ZigTypeIdVector,
62566461};
62576462
62586463ZigTypeId type_id_at_index(size_t index) {
......@@ -6318,6 +6523,8 @@ size_t type_id_index(ZigType *entry) {
63186523 return 22;
63196524 case ZigTypeIdPromise:
63206525 return 23;
6526 case ZigTypeIdVector:
6527 return 24;
63216528 }
63226529 zig_unreachable();
63236530}
......@@ -6374,6 +6581,8 @@ const char *type_id_name(ZigTypeId id) {
63746581 return "Opaque";
63756582 case ZigTypeIdPromise:
63766583 return "Promise";
6584 case ZigTypeIdVector:
6585 return "Vector";
63776586 }
63786587 zig_unreachable();
63796588}
......@@ -6453,7 +6662,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) {
64536662 resolve_top_level_decl(codegen, tld, false, nullptr);
64546663 assert(tld->id == TldIdVar);
64556664 TldVar *tld_var = (TldVar *)tld;
6456 ConstExprValue *var_value = tld_var->var->value;
6665 ConstExprValue *var_value = tld_var->var->const_value;
64576666 assert(var_value != nullptr);
64586667 return var_value;
64596668}
......@@ -6529,6 +6738,7 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {
65296738 case ZigTypeIdBool:
65306739 return X64CABIClass_INTEGER;
65316740 case ZigTypeIdFloat:
6741 case ZigTypeIdVector:
65326742 return X64CABIClass_SSE;
65336743 case ZigTypeIdStruct: {
65346744 // "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
2020uint64_t type_size(CodeGen *g, ZigType *type_entry);
2121uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);
2222ZigType *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);
2324ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
2425ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type);
2526ZigType *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);
7374bool is_ref(ZigType *type_entry);
7475bool is_array_ref(ZigType *type_entry);
7576bool is_container_ref(ZigType *type_entry);
77bool is_valid_vector_elem_type(ZigType *elem_type);
7678void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
7779void scan_import(CodeGen *g, ImportTableEntry *import);
7880void preview_use_decl(CodeGen *g, AstNode *node);
......@@ -81,7 +83,7 @@ ZigFn *scope_fn_entry(Scope *scope);
8183ImportTableEntry *get_scope_import(Scope *scope);
8284void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope);
8385ZigVar *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);
8587ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);
8688ZigFn *create_fn(CodeGen *g, AstNode *proto_node);
8789ZigFn *create_fn_raw(CodeGen *g, FnInline inline_value);
......@@ -222,6 +224,13 @@ enum ReqCompTime {
222224};
223225ReqCompTime 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
225234Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
226235 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) {
233233 return "ErrorType";
234234 case NodeTypeIfErrorExpr:
235235 return "IfErrorExpr";
236 case NodeTypeTestExpr:
237 return "TestExpr";
236 case NodeTypeIfOptional:
237 return "IfOptional";
238238 case NodeTypeErrorSetDecl:
239239 return "ErrorSetDecl";
240240 case NodeTypeCancel:
......@@ -387,7 +387,7 @@ static bool statement_terminates_without_semicolon(AstNode *node) {
387387 if (node->data.if_err_expr.else_node)
388388 return statement_terminates_without_semicolon(node->data.if_err_expr.else_node);
389389 return node->data.if_err_expr.then_node->type == NodeTypeBlock;
390 case NodeTypeTestExpr:
390 case NodeTypeIfOptional:
391391 if (node->data.test_expr.else_node)
392392 return statement_terminates_without_semicolon(node->data.test_expr.else_node);
393393 return node->data.test_expr.then_node->type == NodeTypeBlock;
......@@ -974,7 +974,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
974974 }
975975 break;
976976 }
977 case NodeTypeTestExpr:
977 case NodeTypeIfOptional:
978978 {
979979 fprintf(ar->f, "if (");
980980 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
222222 assert(chf->path != nullptr);
223223
224224 OsFile this_file;
225 if ((err = os_file_open_r(chf->path, &this_file)))
225 if ((err = os_file_open_r(chf->path, &this_file, &chf->mtime)))
226226 return err;
227227
228 if ((err = os_file_mtime(this_file, &chf->mtime))) {
229 os_file_close(this_file);
230 return err;
231 }
232
233228 if ((err = hash_file(chf->bin_digest, this_file, contents))) {
234229 os_file_close(this_file);
235230 return err;
......@@ -351,17 +346,12 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
351346
352347 // if the mtime matches we can trust the digest
353348 OsFile this_file;
354 if ((err = os_file_open_r(chf->path, &this_file))) {
349 OsTimeStamp actual_mtime;
350 if ((err = os_file_open_r(chf->path, &this_file, &actual_mtime))) {
355351 fprintf(stderr, "Unable to open %s\n: %s", buf_ptr(chf->path), err_str(err));
356352 os_file_close(ch->manifest_file);
357353 return ErrorCacheUnavailable;
358354 }
359 OsTimeStamp actual_mtime;
360 if ((err = os_file_mtime(this_file, &actual_mtime))) {
361 os_file_close(this_file);
362 os_file_close(ch->manifest_file);
363 return err;
364 }
365355 if (chf->mtime.sec == actual_mtime.sec && chf->mtime.nsec == actual_mtime.nsec) {
366356 os_file_close(this_file);
367357 } else {
src/codegen.cpp+396-104
......@@ -118,6 +118,7 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
118118 g->string_literals_table.init(16);
119119 g->type_info_cache.init(32);
120120 g->is_test_build = false;
121 g->is_single_threaded = false;
121122 buf_resize(&g->global_asm, 0);
122123
123124 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 *
313314static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const char *name);
314315static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name);
315316static 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
317320static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) {
318321 unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name));
......@@ -461,6 +464,21 @@ static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkag
461464 }
462465}
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
464482static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
465483 if (fn_table_entry->llvm_value)
466484 return fn_table_entry->llvm_value;
......@@ -598,9 +616,9 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
598616 } else if (type_is_codegen_pointer(return_type)) {
599617 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
600618 } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {
601 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
602619 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)) {
604622 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias");
605623 }
606624 init_gen_i = 1;
......@@ -1903,9 +1921,8 @@ static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) {
19031921}
19041922
19051923static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) {
1906 assert(alignment > 0);
19071924 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);
19091926 return result;
19101927}
19111928
......@@ -1963,7 +1980,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
19631980 break;
19641981 }
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 ||
19671984 ty->id == ZigTypeIdInt // TODO investigate if we need to change this
19681985 ) {
19691986 switch (fn_walk->id) {
......@@ -2200,10 +2217,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
22002217 assert(variable);
22012218 assert(variable->value_ref);
22022219
2203 if (!handle_is_ptr(variable->value->type)) {
2220 if (!handle_is_ptr(variable->var_type)) {
22042221 clear_debug_source_node(g);
2205 gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index), variable->value_ref,
2206 variable->align_bytes, false);
2222 gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index),
2223 variable->value_ref, variable->align_bytes, false);
22072224 }
22082225
22092226 if (variable->decl_node) {
......@@ -2643,6 +2660,27 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
26432660 } else {
26442661 return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, "");
26452662 }
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 }
26462684 } else {
26472685 zig_unreachable();
26482686 }
......@@ -2961,7 +2999,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
29612999}
29623000
29633001static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
2964 IrInstructionPtrCast *instruction)
3002 IrInstructionPtrCastGen *instruction)
29653003{
29663004 ZigType *wanted_type = instruction->base.value.type;
29673005 if (!type_has_bits(wanted_type)) {
......@@ -3149,11 +3187,11 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI
31493187}
31503188
31513189static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
3152 IrInstructionDeclVar *decl_var_instruction)
3190 IrInstructionDeclVarGen *decl_var_instruction)
31533191{
31543192 ZigVar *var = decl_var_instruction->var;
31553193
3156 if (!type_has_bits(var->value->type))
3194 if (!type_has_bits(var->var_type))
31573195 return nullptr;
31583196
31593197 if (var->ref_count == 0 && g->build_mode != BuildModeDebug)
......@@ -3161,34 +3199,16 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
31613199
31623200 IrInstruction *init_value = decl_var_instruction->init_value;
31633201
3164 bool have_init_expr = false;
3165
3166 ConstExprValue *const_val = &init_value->value;
3167 if (const_val->special == ConstValSpecialRuntime || const_val->special == ConstValSpecialStatic)
3168 have_init_expr = true;
3202 bool have_init_expr = !value_is_all_undef(&init_value->value);
31693203
31703204 if (have_init_expr) {
3171 assert(var->value->type == init_value->value.type);
3172 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,
3205 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->var_type, false, false,
31733206 PtrLenSingle, var->align_bytes, 0, 0);
31743207 LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);
31753208 gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);
3176 } else {
3177 bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);
3178 if (want_safe) {
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 }
3209 } else if (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;
3211 gen_undef_init(g, align_bytes, var->var_type, var->value_ref);
31923212 }
31933213
31943214 gen_var_debug_decl(g, var);
......@@ -3225,21 +3245,81 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
32253245 return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, "");
32263246}
32273247
3228static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {
3229 LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
3230 LLVMValueRef value = ir_llvm_value(g, instruction->value);
3248static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) {
3249 switch (const_val->data.x_array.special) {
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);
3233 ZigType *ptr_type = instruction->ptr->value.type;
3264static bool value_is_all_undef(ConstExprValue *const_val) {
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 }
32373317 return nullptr;
32383318}
32393319
32403320static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) {
32413321 ZigVar *var = instruction->var;
3242 if (type_has_bits(var->value->type)) {
3322 if (type_has_bits(var->var_type)) {
32433323 assert(var->value_ref);
32443324 return var->value_ref;
32453325 } else {
......@@ -3553,7 +3633,8 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab
35533633 LLVMPositionBuilderAtEnd(g->builder, ok_block);
35543634 }
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, "");
35573638 LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, "");
35583639 return bitcasted_union_field_ptr;
35593640}
......@@ -3715,8 +3796,8 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR
37153796 if (child_type->zero_bits) {
37163797 return maybe_handle;
37173798 } else {
3718 bool maybe_is_ptr = type_is_codegen_pointer(child_type);
3719 if (maybe_is_ptr) {
3799 bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet;
3800 if (is_scalar) {
37203801 return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), "");
37213802 } else {
37223803 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
37313812 return gen_non_null_bit(g, instruction->value->value.type, ir_llvm_value(g, instruction->value));
37323813}
37333814
3734static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
3735 IrInstructionUnwrapOptional *instruction)
3815static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *executable,
3816 IrInstructionOptionalUnwrapPtr *instruction)
37363817{
3737 ZigType *ptr_type = instruction->value->value.type;
3818 ZigType *ptr_type = instruction->base_ptr->value.type;
37383819 assert(ptr_type->id == ZigTypeIdPointer);
37393820 ZigType *maybe_type = ptr_type->data.pointer.child_type;
37403821 assert(maybe_type->id == ZigTypeIdOptional);
37413822 ZigType *child_type = maybe_type->data.maybe.child_type;
3742 LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value);
3743 LLVMValueRef maybe_handle = get_handle_value(g, maybe_ptr, maybe_type, ptr_type);
3823 LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->base_ptr);
37443824 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);
37453826 LLVMValueRef non_null_bit = gen_non_null_bit(g, maybe_type, maybe_handle);
37463827 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalOk");
37473828 LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapOptionalFail");
......@@ -3755,8 +3836,8 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
37553836 if (child_type->zero_bits) {
37563837 return nullptr;
37573838 } else {
3758 bool maybe_is_ptr = type_is_codegen_pointer(child_type);
3759 if (maybe_is_ptr) {
3839 bool is_scalar = type_is_codegen_pointer(child_type) || child_type->id == ZigTypeIdErrorSet;
3840 if (is_scalar) {
37603841 return maybe_ptr;
37613842 } else {
37623843 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)
41744255 zig_unreachable();
41754256}
41764257
4177static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchg *instruction) {
4258static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrInstructionCmpxchgGen *instruction) {
41784259 LLVMValueRef ptr_val = ir_llvm_value(g, instruction->ptr);
41794260 LLVMValueRef cmp_val = ir_llvm_value(g, instruction->cmp_value);
41804261 LLVMValueRef new_val = ir_llvm_value(g, instruction->new_value);
......@@ -4189,18 +4270,18 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn
41894270 assert(maybe_type->id == ZigTypeIdOptional);
41904271 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)) {
41934274 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
41944275 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
41954276 return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(child_type->type_ref), payload_val, "");
41964277 }
41974278
41984279 assert(instruction->tmp_ptr != nullptr);
4199 assert(type_has_bits(instruction->type));
4280 assert(type_has_bits(child_type));
42004281
42014282 LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, "");
42024283 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
42054286 LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, "");
42064287 LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, "");
......@@ -4351,6 +4432,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst
43514432 assert(array_type->data.structure.is_slice);
43524433 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
43534434 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind);
4435 assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(tmp_struct_ptr))) == LLVMStructTypeKind);
43544436
43554437 size_t ptr_index = array_type->data.structure.fields[slice_ptr_index].gen_index;
43564438 assert(ptr_index != SIZE_MAX);
......@@ -4540,12 +4622,14 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI
45404622 return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, "");
45414623}
45424624
4543static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable, IrInstructionUnwrapErrCode *instruction) {
4544 ZigType *ptr_type = instruction->value->value.type;
4625static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executable,
4626 IrInstructionUnwrapErrCode *instruction)
4627{
4628 ZigType *ptr_type = instruction->err_union->value.type;
45454629 assert(ptr_type->id == ZigTypeIdPointer);
45464630 ZigType *err_union_type = ptr_type->data.pointer.child_type;
45474631 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);
45494633 LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type);
45504634
45514635 if (type_has_bits(payload_type)) {
......@@ -4556,7 +4640,13 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, IrExecutable *executab
45564640 }
45574641}
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;
45604650 ZigType *ptr_type = instruction->value->value.type;
45614651 assert(ptr_type->id == ZigTypeIdPointer);
45624652 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
45684658 return err_union_handle;
45694659 }
45704660
4571 if (ir_want_runtime_safety(g, &instruction->base) && instruction->safety_check_on && g->errors_by_index.length > 1) {
4661 if (want_safety) {
45724662 LLVMValueRef err_val;
45734663 if (type_has_bits(payload_type)) {
45744664 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
46074697 }
46084698
46094699 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) {
46114701 return payload_val;
46124702 }
46134703
......@@ -5109,6 +5199,32 @@ static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutable *executable,
51095199 return LLVMBuildCall(g->builder, fn_val, &op, 1, "");
51105200}
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
51125228static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
51135229 AstNode *source_node = instruction->source_node;
51145230 Scope *scope = instruction->scope;
......@@ -5148,6 +5264,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
51485264 case IrInstructionIdCUndef:
51495265 case IrInstructionIdEmbedFile:
51505266 case IrInstructionIdIntType:
5267 case IrInstructionIdVectorType:
51515268 case IrInstructionIdMemberCount:
51525269 case IrInstructionIdMemberType:
51535270 case IrInstructionIdMemberName:
......@@ -5184,12 +5301,15 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
51845301 case IrInstructionIdToBytes:
51855302 case IrInstructionIdEnumToInt:
51865303 case IrInstructionIdCheckRuntimeScope:
5304 case IrInstructionIdDeclVarSrc:
5305 case IrInstructionIdPtrCastSrc:
5306 case IrInstructionIdCmpxchgSrc:
51875307 zig_unreachable();
51885308
5309 case IrInstructionIdDeclVarGen:
5310 return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction);
51895311 case IrInstructionIdReturn:
51905312 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
5191 case IrInstructionIdDeclVar:
5192 return ir_render_decl_var(g, executable, (IrInstructionDeclVar *)instruction);
51935313 case IrInstructionIdBinOp:
51945314 return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);
51955315 case IrInstructionIdCast:
......@@ -5220,8 +5340,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
52205340 return ir_render_asm(g, executable, (IrInstructionAsm *)instruction);
52215341 case IrInstructionIdTestNonNull:
52225342 return ir_render_test_non_null(g, executable, (IrInstructionTestNonNull *)instruction);
5223 case IrInstructionIdUnwrapOptional:
5224 return ir_render_unwrap_maybe(g, executable, (IrInstructionUnwrapOptional *)instruction);
5343 case IrInstructionIdOptionalUnwrapPtr:
5344 return ir_render_optional_unwrap_ptr(g, executable, (IrInstructionOptionalUnwrapPtr *)instruction);
52255345 case IrInstructionIdClz:
52265346 return ir_render_clz(g, executable, (IrInstructionClz *)instruction);
52275347 case IrInstructionIdCtz:
......@@ -5236,8 +5356,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
52365356 return ir_render_ref(g, executable, (IrInstructionRef *)instruction);
52375357 case IrInstructionIdErrName:
52385358 return ir_render_err_name(g, executable, (IrInstructionErrName *)instruction);
5239 case IrInstructionIdCmpxchg:
5240 return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchg *)instruction);
5359 case IrInstructionIdCmpxchgGen:
5360 return ir_render_cmpxchg(g, executable, (IrInstructionCmpxchgGen *)instruction);
52415361 case IrInstructionIdFence:
52425362 return ir_render_fence(g, executable, (IrInstructionFence *)instruction);
52435363 case IrInstructionIdTruncate:
......@@ -5278,8 +5398,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
52785398 return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
52795399 case IrInstructionIdUnionInit:
52805400 return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
5281 case IrInstructionIdPtrCast:
5282 return ir_render_ptr_cast(g, executable, (IrInstructionPtrCast *)instruction);
5401 case IrInstructionIdPtrCastGen:
5402 return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction);
52835403 case IrInstructionIdBitCast:
52845404 return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction);
52855405 case IrInstructionIdWidenOrShorten:
......@@ -5350,6 +5470,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
53505470 return ir_render_bswap(g, executable, (IrInstructionBswap *)instruction);
53515471 case IrInstructionIdBitReverse:
53525472 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);
53535477 }
53545478 zig_unreachable();
53555479}
......@@ -5377,6 +5501,9 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
53775501static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index);
53785502static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index);
53795503static 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
53815508static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent *parent) {
53825509 switch (parent->id) {
......@@ -5387,6 +5514,12 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
53875514 case ConstParentIdStruct:
53885515 return gen_const_ptr_struct_recursive(g, parent->data.p_struct.struct_val,
53895516 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);
53905523 case ConstParentIdArray:
53915524 return gen_const_ptr_array_recursive(g, parent->data.p_array.array_val,
53925525 parent->data.p_array.elem_index);
......@@ -5402,7 +5535,7 @@ static LLVMValueRef gen_parent_ptr(CodeGen *g, ConstExprValue *val, ConstParent
54025535
54035536static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *array_const_val, size_t index) {
54045537 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;
54065539 LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);
54075540
54085541 LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr)));
......@@ -5427,7 +5560,7 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
54275560}
54285561
54295562static 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;
54315564 LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent);
54325565
54335566 ZigType *u32 = g->builtin_types.entry_u32;
......@@ -5438,8 +5571,44 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s
54385571 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
54395572}
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
54415610static 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;
54435612 LLVMValueRef base_ptr = gen_parent_ptr(g, union_const_val, parent);
54445613
54455614 ZigType *u32 = g->builtin_types.entry_u32;
......@@ -5509,6 +5678,8 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
55095678 }
55105679 case ZigTypeIdArray:
55115680 zig_panic("TODO bit pack an array");
5681 case ZigTypeIdVector:
5682 zig_panic("TODO bit pack a vector");
55125683 case ZigTypeIdUnion:
55135684 zig_panic("TODO bit pack a union");
55145685 case ZigTypeIdStruct:
......@@ -5609,6 +5780,63 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
56095780 render_const_val_global(g, const_val, "");
56105781 return ptr_val;
56115782 }
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 }
56125840 case ConstPtrSpecialHardCodedAddr:
56135841 {
56145842 render_const_val_global(g, const_val, name);
......@@ -5621,10 +5849,17 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
56215849 }
56225850 case ConstPtrSpecialFunction:
56235851 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);
56245854 }
56255855 zig_unreachable();
56265856}
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
56285863static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) {
56295864 Error err;
56305865
......@@ -5644,9 +5879,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
56445879 case ZigTypeIdInt:
56455880 return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint);
56465881 case ZigTypeIdErrorSet:
5647 assert(const_val->data.x_err_set != nullptr);
5648 return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref,
5649 const_val->data.x_err_set->value, false);
5882 return gen_const_val_err_set(g, const_val, name);
56505883 case ZigTypeIdFloat:
56515884 switch (type_entry->data.floating.bit_count) {
56525885 case 16:
......@@ -5680,6 +5913,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
56805913 return LLVMConstInt(LLVMInt1Type(), const_val->data.x_optional ? 1 : 0, false);
56815914 } else if (type_is_codegen_pointer(child_type)) {
56825915 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);
56835918 } else {
56845919 LLVMValueRef child_val;
56855920 LLVMValueRef maybe_val;
......@@ -5816,7 +6051,33 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
58166051 return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf), true);
58176052 }
58186053 }
6054 zig_unreachable();
58196055 }
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 }
58206081 case ZigTypeIdUnion:
58216082 {
58226083 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
59146175 ZigType *err_set_type = type_entry->data.error_union.err_set_type;
59156176 if (!type_has_bits(payload_type)) {
59166177 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;
59186180 return LLVMConstInt(g->err_tag_type->type_ref, value, false);
59196181 } else if (!type_has_bits(err_set_type)) {
59206182 assert(type_has_bits(payload_type));
......@@ -5923,8 +6185,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
59236185 LLVMValueRef err_tag_value;
59246186 LLVMValueRef err_payload_value;
59256187 bool make_unnamed_struct;
5926 if (const_val->data.x_err_union.err) {
5927 err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, const_val->data.x_err_union.err->value, false);
6188 ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set;
6189 if (err_set != nullptr) {
6190 err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, err_set->value, false);
59286191 err_payload_value = LLVMConstNull(payload_type->type_ref);
59296192 make_unnamed_struct = false;
59306193 } else {
......@@ -6130,10 +6393,13 @@ static void do_code_gen(CodeGen *g) {
61306393 TldVar *tld_var = g->global_vars.at(i);
61316394 ZigVar *var = tld_var->var;
61326395
6133 if (var->value->type->id == ZigTypeIdComptimeFloat) {
6396 if (var->var_type->id == ZigTypeIdComptimeFloat) {
61346397 // Generate debug info for it but that's it.
6135 ConstExprValue *const_val = var->value;
6398 ConstExprValue *const_val = var->const_value;
61366399 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 }
61376403 ZigType *var_type = g->builtin_types.entry_f128;
61386404 ConstExprValue coerced_value;
61396405 coerced_value.special = ConstValSpecialStatic;
......@@ -6144,10 +6410,13 @@ static void do_code_gen(CodeGen *g) {
61446410 continue;
61456411 }
61466412
6147 if (var->value->type->id == ZigTypeIdComptimeInt) {
6413 if (var->var_type->id == ZigTypeIdComptimeInt) {
61486414 // Generate debug info for it but that's it.
6149 ConstExprValue *const_val = var->value;
6415 ConstExprValue *const_val = var->const_value;
61506416 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 }
61516420 size_t bits_needed = bigint_bits_needed(&const_val->data.x_bigint);
61526421 if (bits_needed < 8) {
61536422 bits_needed = 8;
......@@ -6158,7 +6427,7 @@ static void do_code_gen(CodeGen *g) {
61586427 continue;
61596428 }
61606429
6161 if (!type_has_bits(var->value->type))
6430 if (!type_has_bits(var->var_type))
61626431 continue;
61636432
61646433 assert(var->decl_node);
......@@ -6167,9 +6436,9 @@ static void do_code_gen(CodeGen *g) {
61676436 if (var->linkage == VarLinkageExternal) {
61686437 LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name));
61696438 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));
61716440 } 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));
61736442 // TODO debug info for the extern variable
61746443
61756444 LLVMSetLinkage(global_value, LLVMExternalLinkage);
......@@ -6180,9 +6449,9 @@ static void do_code_gen(CodeGen *g) {
61806449 } else {
61816450 bool exported = (var->linkage == VarLinkageExport);
61826451 const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));
6183 render_const_val(g, var->value, mangled_name);
6184 render_const_val_global(g, var->value, mangled_name);
6185 global_value = var->value->global_refs->llvm_global;
6452 render_const_val(g, var->const_value, mangled_name);
6453 render_const_val_global(g, var->const_value, mangled_name);
6454 global_value = var->const_value->global_refs->llvm_global;
61866455
61876456 if (exported) {
61886457 LLVMSetLinkage(global_value, LLVMExternalLinkage);
......@@ -6194,8 +6463,10 @@ static void do_code_gen(CodeGen *g) {
61946463 LLVMSetAlignment(global_value, var->align_bytes);
61956464
61966465 // TODO debug info for function pointers
6197 if (var->gen_is_const && var->value->type->id != ZigTypeIdFn) {
6198 gen_global_var(g, var, var->value->global_refs->llvm_value, var->value->type);
6466 // Here we use const_value->type because that's the type of the llvm global,
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);
61996470 }
62006471
62016472 LLVMSetGlobalConstant(global_value, var->gen_is_const);
......@@ -6249,6 +6520,7 @@ static void do_code_gen(CodeGen *g) {
62496520 IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i);
62506521 LLVMValueRef *slot;
62516522 ZigType *slot_type = instruction->value.type;
6523 uint32_t alignment_bytes = 0;
62526524 if (instruction->id == IrInstructionIdCast) {
62536525 IrInstructionCast *cast_instruction = (IrInstructionCast *)instruction;
62546526 slot = &cast_instruction->tmp_ptr;
......@@ -6281,13 +6553,17 @@ static void do_code_gen(CodeGen *g) {
62816553 } else if (instruction->id == IrInstructionIdErrWrapCode) {
62826554 IrInstructionErrWrapCode *err_wrap_code_instruction = (IrInstructionErrWrapCode *)instruction;
62836555 slot = &err_wrap_code_instruction->tmp_ptr;
6284 } else if (instruction->id == IrInstructionIdCmpxchg) {
6285 IrInstructionCmpxchg *cmpxchg_instruction = (IrInstructionCmpxchg *)instruction;
6556 } else if (instruction->id == IrInstructionIdCmpxchgGen) {
6557 IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;
62866558 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;
62876563 } else {
62886564 zig_unreachable();
62896565 }
6290 *slot = build_alloca(g, slot_type, "", get_abi_alignment(g, slot_type));
6566 *slot = build_alloca(g, slot_type, "", alignment_bytes);
62916567 }
62926568
62936569 ImportTableEntry *import = get_scope_import(&fn_table_entry->fndef_scope->base);
......@@ -6304,12 +6580,12 @@ static void do_code_gen(CodeGen *g) {
63046580 for (size_t var_i = 0; var_i < fn_table_entry->variable_list.length; var_i += 1) {
63056581 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)) {
63086584 continue;
63096585 }
63106586 if (ir_get_var_is_comptime(var))
63116587 continue;
6312 switch (type_requires_comptime(g, var->value->type)) {
6588 switch (type_requires_comptime(g, var->var_type)) {
63136589 case ReqCompTimeInvalid:
63146590 zig_unreachable();
63156591 case ReqCompTimeYes:
......@@ -6319,11 +6595,11 @@ static void do_code_gen(CodeGen *g) {
63196595 }
63206596
63216597 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
63246600 var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
63256601 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
63286604 } else if (is_c_abi) {
63296605 fn_walk_var.data.vars.var = var;
......@@ -6333,16 +6609,16 @@ static void do_code_gen(CodeGen *g) {
63336609 ZigType *gen_type;
63346610 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)) {
63376613 if (gen_info->is_byval) {
6338 gen_type = var->value->type;
6614 gen_type = var->var_type;
63396615 } else {
63406616 gen_type = gen_info->type;
63416617 }
63426618 var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index);
63436619 } else {
6344 gen_type = var->value->type;
6345 var->value_ref = build_alloca(g, var->value->type, buf_ptr(&var->name), var->align_bytes);
6620 gen_type = var->var_type;
6621 var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes);
63466622 }
63476623 if (var->decl_node) {
63486624 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) {
67427018 create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
67437019 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
67447020 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
7021 create_builtin_fn(g, BuiltinFnIdVectorType, "Vector", 2);
67457022 create_builtin_fn(g, BuiltinFnIdSetCold, "setCold", 1);
67467023 create_builtin_fn(g, BuiltinFnIdSetRuntimeSafety, "setRuntimeSafety", 1);
67477024 create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 1);
......@@ -6967,6 +7244,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
69677244 " ArgTuple: void,\n"
69687245 " Opaque: void,\n"
69697246 " Promise: Promise,\n"
7247 " Vector: Vector,\n"
69707248 "\n\n"
69717249 " pub const Int = struct {\n"
69727250 " is_signed: bool,\n"
......@@ -7085,6 +7363,11 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
70857363 " child: ?type,\n"
70867364 " };\n"
70877365 "\n"
7366 " pub const Vector = struct {\n"
7367 " len: u32,\n"
7368 " child: type,\n"
7369 " };\n"
7370 "\n"
70887371 " pub const Definition = struct {\n"
70897372 " name: []const u8,\n"
70907373 " is_pub: bool,\n"
......@@ -7153,6 +7436,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
71537436 buf_appendf(contents, "pub const endian = %s;\n", endian_str);
71547437 }
71557438 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));
71567440 buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);
71577441 buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);
71587442 buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ);
......@@ -7187,6 +7471,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
71877471 cache_buf(&cache_hash, compiler_id);
71887472 cache_int(&cache_hash, g->build_mode);
71897473 cache_bool(&cache_hash, g->is_test_build);
7474 cache_bool(&cache_hash, g->is_single_threaded);
71907475 cache_int(&cache_hash, g->zig_target.arch.arch);
71917476 cache_int(&cache_hash, g->zig_target.arch.sub_arch);
71927477 cache_int(&cache_hash, g->zig_target.vendor);
......@@ -7458,9 +7743,9 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
74587743 ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i];
74597744 this_val->special = ConstValSpecialStatic;
74607745 this_val->type = struct_type;
7461 this_val->data.x_struct.parent.id = ConstParentIdArray;
7462 this_val->data.x_struct.parent.data.p_array.array_val = test_fn_array;
7463 this_val->data.x_struct.parent.data.p_array.elem_index = i;
7746 this_val->parent.id = ConstParentIdArray;
7747 this_val->parent.data.p_array.array_val = test_fn_array;
7748 this_val->parent.data.p_array.elem_index = i;
74647749 this_val->data.x_struct.fields = create_const_vals(2);
74657750
74667751 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
76567941 case ZigTypeIdArray:
76577942 prepend_c_type_to_decl_list(g, gen_h, type_entry->data.array.child_type);
76587943 return;
7944 case ZigTypeIdVector:
7945 prepend_c_type_to_decl_list(g, gen_h, type_entry->data.vector.elem_type);
7946 return;
76597947 case ZigTypeIdOptional:
76607948 prepend_c_type_to_decl_list(g, gen_h, type_entry->data.maybe.child_type);
76617949 return;
......@@ -7787,6 +8075,8 @@ static void get_c_type(CodeGen *g, GenH *gen_h, ZigType *type_entry, Buf *out_bu
77878075 buf_appendf(out_buf, "%s", buf_ptr(child_buf));
77888076 return;
77898077 }
8078 case ZigTypeIdVector:
8079 zig_panic("TODO implement get_c_type for vector types");
77908080 case ZigTypeIdErrorUnion:
77918081 case ZigTypeIdErrorSet:
77928082 case ZigTypeIdFn:
......@@ -7952,6 +8242,7 @@ static void gen_h_file(CodeGen *g) {
79528242 case ZigTypeIdOptional:
79538243 case ZigTypeIdFn:
79548244 case ZigTypeIdPromise:
8245 case ZigTypeIdVector:
79558246 zig_unreachable();
79568247 case ZigTypeIdEnum:
79578248 if (type_entry->data.enumeration.layout == ContainerLayoutExtern) {
......@@ -8099,6 +8390,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
80998390 cache_bool(ch, g->is_static);
81008391 cache_bool(ch, g->strip_debug_symbols);
81018392 cache_bool(ch, g->is_test_build);
8393 cache_bool(ch, g->is_single_threaded);
81028394 cache_bool(ch, g->is_native_target);
81038395 cache_bool(ch, g->linker_rdynamic);
81048396 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_
167167 ZigType *dest_type, IrInstruction *dest_type_src);
168168static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
169169static 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
171173static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
172174 assert(get_src_ptr_type(const_val->type) != nullptr);
......@@ -178,15 +180,28 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
178180 case ConstPtrSpecialRef:
179181 result = const_val->data.x_ptr.data.ref.pointee;
180182 break;
181 case ConstPtrSpecialBaseArray:
182 expand_undef_array(g, 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[
184 const_val->data.x_ptr.data.base_array.elem_index];
183 case ConstPtrSpecialBaseArray: {
184 ConstExprValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
185 expand_undef_array(g, array_val);
186 result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];
185187 break;
188 }
186189 case ConstPtrSpecialBaseStruct:
187190 result = &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[
188191 const_val->data.x_ptr.data.base_struct.field_index];
189192 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;
190205 case ConstPtrSpecialHardCodedAddr:
191206 zig_unreachable();
192207 case ConstPtrSpecialDiscard:
......@@ -198,6 +213,11 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
198213 return result;
199214}
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
201221static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
202222 if (a == b)
203223 return true;
......@@ -208,15 +228,10 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
208228 if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr)
209229 return true;
210230
211 return false;
212}
231 if (is_opt_err_set(a) && is_opt_err_set(b))
232 return true;
213233
214ConstExprValue *const_ptr_pointee(CodeGen *g, ConstExprValue *const_val) {
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;
234 return false;
220235}
221236
222237static bool ir_should_inline(IrExecutable *exec, Scope *scope) {
......@@ -305,6 +320,14 @@ static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) {
305320 return new_bb;
306321}
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
308331static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) {
309332 return IrInstructionIdCondBr;
310333}
......@@ -337,10 +360,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) {
337360 return IrInstructionIdBinOp;
338361}
339362
340static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVar *) {
341 return IrInstructionIdDeclVar;
342}
343
344363static constexpr IrInstructionId ir_instruction_id(IrInstructionExport *) {
345364 return IrInstructionIdExport;
346365}
......@@ -449,8 +468,8 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestNonNull *) {
449468 return IrInstructionIdTestNonNull;
450469}
451470
452static constexpr IrInstructionId ir_instruction_id(IrInstructionUnwrapOptional *) {
453 return IrInstructionIdUnwrapOptional;
471static constexpr IrInstructionId ir_instruction_id(IrInstructionOptionalUnwrapPtr *) {
472 return IrInstructionIdOptionalUnwrapPtr;
454473}
455474
456475static constexpr IrInstructionId ir_instruction_id(IrInstructionClz *) {
......@@ -517,8 +536,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionEmbedFile *) {
517536 return IrInstructionIdEmbedFile;
518537}
519538
520static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchg *) {
521 return IrInstructionIdCmpxchg;
539static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgSrc *) {
540 return IrInstructionIdCmpxchgSrc;
541}
542
543static constexpr IrInstructionId ir_instruction_id(IrInstructionCmpxchgGen *) {
544 return IrInstructionIdCmpxchgGen;
522545}
523546
524547static constexpr IrInstructionId ir_instruction_id(IrInstructionFence *) {
......@@ -565,6 +588,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionIntType *) {
565588 return IrInstructionIdIntType;
566589}
567590
591static constexpr IrInstructionId ir_instruction_id(IrInstructionVectorType *) {
592 return IrInstructionIdVectorType;
593}
594
568595static constexpr IrInstructionId ir_instruction_id(IrInstructionBoolNot *) {
569596 return IrInstructionIdBoolNot;
570597}
......@@ -649,8 +676,12 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionTestComptime *)
649676 return IrInstructionIdTestComptime;
650677}
651678
652static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCast *) {
653 return IrInstructionIdPtrCast;
679static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastSrc *) {
680 return IrInstructionIdPtrCastSrc;
681}
682
683static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrCastGen *) {
684 return IrInstructionIdPtrCastGen;
654685}
655686
656687static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {
......@@ -869,6 +900,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCheckRuntimeScop
869900 return IrInstructionIdCheckRuntimeScope;
870901}
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
872911template<typename T>
873912static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
874913 T *special_instruction = allocate<T>(1);
......@@ -915,7 +954,7 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, Scope *scope, AstNode *so
915954 ir_ref_instruction(condition, irb->current_basic_block);
916955 ir_ref_bb(then_block);
917956 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
920959 return &cond_br_instruction->base;
921960}
......@@ -931,16 +970,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou
931970 return &return_instruction->base;
932971}
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
944973static IrInstruction *ir_build_const_void(IrBuilder *irb, Scope *scope, AstNode *source_node) {
945974 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
946975 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
11881217 call_instruction->async_allocator = async_allocator;
11891218 call_instruction->new_stack = new_stack;
11901219
1191 if (fn_ref)
1192 ir_ref_instruction(fn_ref, irb->current_basic_block);
1220 if (fn_ref != nullptr) ir_ref_instruction(fn_ref, irb->current_basic_block);
11931221 for (size_t i = 0; i < arg_count; i += 1)
11941222 ir_ref_instruction(args[i], irb->current_basic_block);
1195 if (async_allocator)
1196 ir_ref_instruction(async_allocator, irb->current_basic_block);
1197 if (new_stack != nullptr)
1198 ir_ref_instruction(new_stack, irb->current_basic_block);
1223 if (async_allocator != nullptr) ir_ref_instruction(async_allocator, irb->current_basic_block);
1224 if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block);
11991225
12001226 return &call_instruction->base;
12011227}
......@@ -1280,7 +1306,7 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope,
12801306 container_init_list_instruction->item_count = item_count;
12811307 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);
12841310 for (size_t i = 0; i < item_count; i += 1) {
12851311 ir_ref_instruction(items[i], irb->current_basic_block);
12861312 }
......@@ -1355,10 +1381,10 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, Scope *scope, AstNode *
13551381 return &instruction->base;
13561382}
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,
13591385 ZigVar *var, IrInstruction *var_type, IrInstruction *align_value, IrInstruction *init_value)
13601386{
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);
13621388 decl_var_instruction->base.value.special = ConstValSpecialStatic;
13631389 decl_var_instruction->base.value.type = irb->codegen->builtin_types.entry_void;
13641390 decl_var_instruction->var = var;
......@@ -1366,13 +1392,28 @@ static IrInstruction *ir_build_var_decl(IrBuilder *irb, Scope *scope, AstNode *s
13661392 decl_var_instruction->align_value = align_value;
13671393 decl_var_instruction->init_value = init_value;
13681394
1369 if (var_type) ir_ref_instruction(var_type, irb->current_basic_block);
1370 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);
1395 if (var_type != nullptr) ir_ref_instruction(var_type, irb->current_basic_block);
1396 if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block);
13711397 ir_ref_instruction(init_value, irb->current_basic_block);
13721398
13731399 return &decl_var_instruction->base;
13741400}
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
13761417static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node,
13771418 IrInstruction *name, IrInstruction *target, IrInstruction *linkage)
13781419{
......@@ -1542,14 +1583,14 @@ static IrInstruction *ir_build_test_nonnull(IrBuilder *irb, Scope *scope, AstNod
15421583 return &instruction->base;
15431584}
15441585
1545static IrInstruction *ir_build_unwrap_maybe(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value,
1546 bool safety_check_on)
1586static IrInstruction *ir_build_optional_unwrap_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
1587 IrInstruction *base_ptr, bool safety_check_on)
15471588{
1548 IrInstructionUnwrapOptional *instruction = ir_build_instruction<IrInstructionUnwrapOptional>(irb, scope, source_node);
1549 instruction->value = value;
1589 IrInstructionOptionalUnwrapPtr *instruction = ir_build_instruction<IrInstructionOptionalUnwrapPtr>(irb, scope, source_node);
1590 instruction->base_ptr = base_ptr;
15501591 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
15541595 return &instruction->base;
15551596}
......@@ -1765,13 +1806,12 @@ static IrInstruction *ir_build_embed_file(IrBuilder *irb, Scope *scope, AstNode
17651806 return &instruction->base;
17661807}
17671808
1768static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *type_value,
1769 IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
1809static IrInstruction *ir_build_cmpxchg_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
1810 IrInstruction *type_value, IrInstruction *ptr, IrInstruction *cmp_value, IrInstruction *new_value,
17701811 IrInstruction *success_order_value, IrInstruction *failure_order_value,
1771 bool is_weak,
1772 ZigType *type, AtomicOrder success_order, AtomicOrder failure_order)
1812 bool is_weak)
17731813{
1774 IrInstructionCmpxchg *instruction = ir_build_instruction<IrInstructionCmpxchg>(irb, scope, source_node);
1814 IrInstructionCmpxchgSrc *instruction = ir_build_instruction<IrInstructionCmpxchgSrc>(irb, scope, source_node);
17751815 instruction->type_value = type_value;
17761816 instruction->ptr = ptr;
17771817 instruction->cmp_value = cmp_value;
......@@ -1779,16 +1819,33 @@ static IrInstruction *ir_build_cmpxchg(IrBuilder *irb, Scope *scope, AstNode *so
17791819 instruction->success_order_value = success_order_value;
17801820 instruction->failure_order_value = failure_order_value;
17811821 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);
17871824 ir_ref_instruction(ptr, irb->current_basic_block);
17881825 ir_ref_instruction(cmp_value, irb->current_basic_block);
17891826 ir_ref_instruction(new_value, irb->current_basic_block);
1790 if (type_value != nullptr) 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);
1827 ir_ref_instruction(success_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
17931850 return &instruction->base;
17941851}
......@@ -1909,6 +1966,19 @@ static IrInstruction *ir_build_int_type(IrBuilder *irb, Scope *scope, AstNode *s
19091966 return &instruction->base;
19101967}
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
19121982static IrInstruction *ir_build_bool_not(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {
19131983 IrInstructionBoolNot *instruction = ir_build_instruction<IrInstructionBoolNot>(irb, scope, source_node);
19141984 instruction->value = value;
......@@ -2060,12 +2130,12 @@ static IrInstruction *ir_build_test_err(IrBuilder *irb, Scope *scope, AstNode *s
20602130}
20612131
20622132static IrInstruction *ir_build_unwrap_err_code(IrBuilder *irb, Scope *scope, AstNode *source_node,
2063 IrInstruction *value)
2133 IrInstruction *err_union)
20642134{
20652135 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
20702140 return &instruction->base;
20712141}
......@@ -2115,20 +2185,33 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo
21152185 return &instruction->base;
21162186}
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,
21192189 IrInstruction *dest_type, IrInstruction *ptr)
21202190{
2121 IrInstructionPtrCast *instruction = ir_build_instruction<IrInstructionPtrCast>(
2191 IrInstructionPtrCastSrc *instruction = ir_build_instruction<IrInstructionPtrCastSrc>(
21222192 irb, scope, source_node);
21232193 instruction->dest_type = dest_type;
21242194 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);
21272197 ir_ref_instruction(ptr, irb->current_basic_block);
21282198
21292199 return &instruction->base;
21302200}
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
21322215static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *source_node,
21332216 IrInstruction *dest_type, IrInstruction *value)
21342217{
......@@ -2747,6 +2830,34 @@ static IrInstruction *ir_build_check_runtime_scope(IrBuilder *irb, Scope *scope,
27472830 return &instruction->base;
27482831}
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
27502861static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
27512862 results[ReturnKindUnconditional] = 0;
27522863 results[ReturnKindError] = 0;
......@@ -2807,10 +2918,13 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o
28072918 Scope *defer_expr_scope = defer_node->data.defer.expr_scope;
28082919 IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);
28092920 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 {
28112924 is_noreturn = true;
28122925 } 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));
28142928 }
28152929 }
28162930 }
......@@ -3065,7 +3179,7 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
30653179 variable_entry->mem_slot_index = SIZE_MAX;
30663180 variable_entry->is_comptime = is_comptime;
30673181 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
30703184 if (is_comptime != nullptr) {
30713185 is_comptime->ref_count += 1;
......@@ -3080,20 +3194,20 @@ static ZigVar *create_local_var(CodeGen *codegen, AstNode *node, Scope *parent_s
30803194 ErrorMsg *msg = add_node_error(codegen, node,
30813195 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
30823196 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;
30843198 } else {
30853199 ZigType *type;
30863200 if (get_primitive_type(codegen, name, &type) != ErrorPrimitiveTypeNotFound) {
30873201 add_node_error(codegen, node,
30883202 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;
30903204 } else {
30913205 Tld *tld = find_decl(codegen, parent_scope, name);
30923206 if (tld != nullptr) {
30933207 ErrorMsg *msg = add_node_error(codegen, node,
30943208 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
30953209 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;
30973211 }
30983212 }
30993213 }
......@@ -3156,7 +3270,8 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
31563270 scope_block->incoming_blocks = &incoming_blocks;
31573271 scope_block->incoming_values = &incoming_values;
31583272 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));
31603275 }
31613276
31623277 bool is_continuation_unreachable = false;
......@@ -3174,9 +3289,9 @@ static IrInstruction *ir_gen_block(IrBuilder *irb, Scope *parent_scope, AstNode
31743289 // defer starts a new scope
31753290 child_scope = statement_node->data.defer.child_scope;
31763291 assert(child_scope);
3177 } else if (statement_value->id == IrInstructionIdDeclVar) {
3292 } else if (statement_value->id == IrInstructionIdDeclVarSrc) {
31783293 // variable declarations start a new scope
3179 IrInstructionDeclVar *decl_var_instruction = (IrInstructionDeclVar *)statement_value;
3294 IrInstructionDeclVarSrc *decl_var_instruction = (IrInstructionDeclVarSrc *)statement_value;
31803295 child_scope = decl_var_instruction->var->child_scope;
31813296 } else if (statement_value != irb->codegen->invalid_instruction && !is_continuation_unreachable) {
31823297 // this statement's value must be void
......@@ -3331,7 +3446,7 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod
33313446 return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
33323447}
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) {
33353450 assert(node->type == NodeTypeBinOpExpr);
33363451
33373452 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
33653480 ir_mark_gen(ir_build_br(irb, parent_scope, node, end_block, is_comptime));
33663481
33673482 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);
33693484 IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr);
33703485 IrBasicBlock *after_ok_block = irb->current_basic_block;
33713486 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)
34833598 case BinOpTypeMergeErrorSets:
34843599 return ir_gen_bin_op_id(irb, scope, node, IrBinOpMergeErrorSets);
34853600 case BinOpTypeUnwrapOptional:
3486 return ir_gen_maybe_ok_or(irb, scope, node);
3601 return ir_gen_orelse(irb, scope, node);
34873602 case BinOpTypeErrorUnion:
34883603 return ir_gen_error_union(irb, scope, node);
34893604 }
......@@ -3542,6 +3657,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
35423657 buf_ptr(variable_name)));
35433658 return irb->codegen->invalid_instruction;
35443659 }
3660 assert(err == ErrorPrimitiveTypeNotFound);
35453661 } else {
35463662 IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_type);
35473663 if (lval == LValPtr) {
......@@ -3904,9 +4020,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
39044020 if (arg5_value == irb->codegen->invalid_instruction)
39054021 return arg5_value;
39064022
3907 IrInstruction *cmpxchg = ir_build_cmpxchg(irb, scope, node, arg0_value, arg1_value,
3908 arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak),
3909 nullptr, AtomicOrderUnordered, AtomicOrderUnordered);
4023 IrInstruction *cmpxchg = ir_build_cmpxchg_src(irb, scope, node, arg0_value, arg1_value,
4024 arg2_value, arg3_value, arg4_value, arg5_value, (builtin_fn->id == BuiltinFnIdCmpxchgWeak));
39104025 return ir_lval_wrap(irb, scope, cmpxchg, lval);
39114026 }
39124027 case BuiltinFnIdFence:
......@@ -4169,6 +4284,21 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
41694284 IrInstruction *int_type = ir_build_int_type(irb, scope, node, arg0_value, arg1_value);
41704285 return ir_lval_wrap(irb, scope, int_type, lval);
41714286 }
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 }
41724302 case BuiltinFnIdMemcpy:
41734303 {
41744304 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
43464476 if (arg1_value == irb->codegen->invalid_instruction)
43474477 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);
43504480 return ir_lval_wrap(irb, scope, ptr_cast, lval);
43514481 }
43524482 case BuiltinFnIdBitCast:
......@@ -4784,7 +4914,8 @@ static IrInstruction *ir_gen_fn_call(IrBuilder *irb, Scope *scope, AstNode *node
47844914 }
47854915 }
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);
47884919 return ir_lval_wrap(irb, scope, fn_call, lval);
47894920}
47904921
......@@ -4793,7 +4924,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
47934924
47944925 IrInstruction *condition = ir_gen_node(irb, node->data.if_bool_expr.condition, scope);
47954926 if (condition == irb->codegen->invalid_instruction)
4796 return condition;
4927 return irb->codegen->invalid_instruction;
47974928
47984929 IrInstruction *is_comptime;
47994930 if (ir_should_inline(irb->exec, scope)) {
......@@ -4816,7 +4947,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, Scope *scope, AstNode
48164947 Scope *subexpr_scope = create_runtime_scope(irb->codegen, node, scope, is_comptime);
48174948 IrInstruction *then_expr_result = ir_gen_node(irb, then_node, subexpr_scope);
48184949 if (then_expr_result == irb->codegen->invalid_instruction)
4819 return then_expr_result;
4950 return irb->codegen->invalid_instruction;
48204951 IrBasicBlock *after_then_block = irb->current_basic_block;
48214952 if (!instr_is_unreachable(then_expr_result))
48224953 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
48264957 if (else_node) {
48274958 else_expr_result = ir_gen_node(irb, else_node, subexpr_scope);
48284959 if (else_expr_result == irb->codegen->invalid_instruction)
4829 return else_expr_result;
4960 return irb->codegen->invalid_instruction;
48304961 } else {
48314962 else_expr_result = ir_build_const_void(irb, scope, node);
48324963 }
......@@ -4927,7 +5058,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
49275058 ptr_len, align_value, bit_offset_start, host_int_bytes);
49285059}
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,
49315062 LVal lval)
49325063{
49335064 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
50535184 ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime);
50545185 ZigVar *var = ir_create_var(irb, node, scope, variable_declaration->symbol,
50555186 is_const, is_const, is_shadowable, is_comptime);
5056 // we detect IrInstructionIdDeclVar in gen_block to make sure the next node
5187 // we detect IrInstructionIdDeclVarSrc in gen_block to make sure the next node
50575188 // is inside var->child_scope
50585189
50595190 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;
50615192 add_node_error(irb->codegen, node, buf_sprintf("variables must be initialized"));
50625193 return irb->codegen->invalid_instruction;
50635194 }
......@@ -5084,7 +5215,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
50845215 if (init_value == irb->codegen->invalid_instruction)
50855216 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);
50885219}
50895220
50905221static 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
51405271 err_val_ptr, false);
51415272 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
51425273 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);
51445275 }
51455276
51465277 ZigList<IrInstruction *> incoming_values = {0};
......@@ -5180,7 +5311,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
51805311 true, false, false, is_comptime);
51815312 Scope *err_scope = err_var->child_scope;
51825313 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
51855316 IrInstruction *else_result = ir_gen_node(irb, else_node, err_scope);
51865317 if (else_result == irb->codegen->invalid_instruction)
......@@ -5220,10 +5351,10 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, Scope *scope, AstNode *n
52205351 }
52215352
52225353 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);
52245355 IrInstruction *var_value = node->data.while_expr.var_is_ptr ?
52255356 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
52285359 ZigList<IrInstruction *> incoming_values = {0};
52295360 ZigList<IrBasicBlock *> incoming_blocks = {0};
......@@ -5380,7 +5511,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
53805511 Scope *child_scope = elem_var->child_scope;
53815512
53825513 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);
53845515 IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var);
53855516
53865517 AstNode *index_var_source_node;
......@@ -5398,7 +5529,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo
53985529 IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize);
53995530 IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0);
54005531 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);
54025533 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
56225753 return ir_build_asm(irb, scope, node, input_list, output_types, output_vars, return_count, is_volatile);
56235754}
56245755
5625static IrInstruction *ir_gen_test_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
5626 assert(node->type == NodeTypeTestExpr);
5756static IrInstruction *ir_gen_if_optional_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
5757 assert(node->type == NodeTypeIfOptional);
56275758
56285759 Buf *var_symbol = node->data.test_expr.var_symbol;
56295760 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
56615792 ZigVar *var = ir_create_var(irb, node, subexpr_scope,
56625793 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);
56655796 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);
56675798 var_scope = var->child_scope;
56685799 } else {
56695800 var_scope = subexpr_scope;
......@@ -5738,7 +5869,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
57385869
57395870 IrInstruction *var_ptr_value = ir_build_unwrap_err_payload(irb, subexpr_scope, node, err_val_ptr, false);
57405871 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);
57425873 var_scope = var->child_scope;
57435874 } else {
57445875 var_scope = subexpr_scope;
......@@ -5763,7 +5894,7 @@ static IrInstruction *ir_gen_if_err_expr(IrBuilder *irb, Scope *scope, AstNode *
57635894 err_symbol, is_const, is_const, is_shadowable, is_comptime);
57645895
57655896 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);
57675898 err_var_scope = var->child_scope;
57685899 } else {
57695900 err_var_scope = subexpr_scope;
......@@ -5818,7 +5949,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit
58185949 var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr);
58195950 }
58205951 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);
58225953 } else {
58235954 child_scope = scope;
58245955 }
......@@ -6228,7 +6359,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node)
62286359 return ir_build_slice(irb, scope, node, ptr_value, start_value, end_value, true);
62296360}
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) {
62326363 assert(node->type == NodeTypeUnwrapErrorExpr);
62336364
62346365 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
62426373 add_node_error(irb->codegen, var_node, buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));
62436374 return irb->codegen->invalid_instruction;
62446375 }
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);
62466377 }
62476378
62486379
......@@ -6276,7 +6407,7 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
62766407 is_const, is_const, is_shadowable, is_comptime);
62776408 err_scope = var->child_scope;
62786409 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);
62806411 } else {
62816412 err_scope = parent_scope;
62826413 }
......@@ -6312,7 +6443,8 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o
63126443 ScopeVarDecl *var_scope = (ScopeVarDecl *)inner_scope;
63136444 if (need_comma)
63146445 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);
63166448 return true;
63176449}
63186450
......@@ -6562,7 +6694,7 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
65626694 IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010
65636695
65646696 // 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);
65666698 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
65676699 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
65686700 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
66406772 get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));
66416773
66426774 // 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);
66446776 IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
66456777 Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
66466778 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
67566888 IrInstruction *target_promise_type = ir_build_typeof(irb, scope, node, target_inst);
67576889 IrInstruction *promise_result_type = ir_build_promise_result_type(irb, scope, node, target_promise_type);
67586890 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);
67606892 IrInstruction *my_result_var_ptr = ir_build_var_ptr(irb, scope, node, result_var);
67616893 ir_build_store_ptr(irb, scope, node, result_ptr_field_ptr, my_result_var_ptr);
67626894 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
70507182 if (maybe_ptr == irb->codegen->invalid_instruction)
70517183 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);
70547186 if (lval == LValPtr)
70557187 return unwrapped_ptr;
70567188
......@@ -7074,8 +7206,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
70747206 return ir_lval_wrap(irb, scope, ir_gen_null_literal(irb, scope, node), lval);
70757207 case NodeTypeIfErrorExpr:
70767208 return ir_lval_wrap(irb, scope, ir_gen_if_err_expr(irb, scope, node), lval);
7077 case NodeTypeTestExpr:
7078 return ir_lval_wrap(irb, scope, ir_gen_test_expr(irb, scope, node), lval);
7209 case NodeTypeIfOptional:
7210 return ir_lval_wrap(irb, scope, ir_gen_if_optional_expr(irb, scope, node), lval);
70797211 case NodeTypeSwitchExpr:
70807212 return ir_lval_wrap(irb, scope, ir_gen_switch_expr(irb, scope, node), lval);
70817213 case NodeTypeCompTime:
......@@ -7093,7 +7225,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
70937225 case NodeTypeSliceExpr:
70947226 return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval);
70957227 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);
70977229 case NodeTypeContainerDecl:
70987230 return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval);
70997231 case NodeTypeFnProto:
......@@ -7152,6 +7284,7 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
71527284 ir_ref_bb(irb->current_basic_block);
71537285
71547286 ZigFn *fn_entry = exec_fn_entry(irb->exec);
7287
71557288 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
71567289 IrInstruction *coro_id;
71577290 IrInstruction *u8_ptr_type;
......@@ -7172,27 +7305,27 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
71727305 ZigType *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);
71737306 IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);
71747307 // 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);
71767309 coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var);
71777310
71787311 ZigVar *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
71797312 IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);
71807313 IrInstruction *await_handle_type_val = ir_build_const_type(irb, coro_scope, node,
71817314 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);
71837316 irb->exec->await_handle_var_ptr = ir_build_var_ptr(irb, coro_scope, node, await_handle_var);
71847317
71857318 u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
71867319 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);
71887321 coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);
71897322 coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
71907323 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);
71927325 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, coro_scope, node,
71937326 ImplicitAllocatorIdArg);
71947327 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);
71967329 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
71977330 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, coro_scope, node, implicit_allocator_ptr, alloc_field_name);
71987331 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
72087341 ir_build_return(irb, coro_scope, node, undef);
72097342
72107343 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);
72127345 irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);
72137346
72147347 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
72867419 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
72877420 false, false, PtrLenUnknown, 0, 0, 0));
72887421 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);
7290 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type_unknown_len,
7422 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, result_ptr);
7423 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
72917424 irb->exec->coro_result_field_ptr);
72927425 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,
72937426 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
73037436 // Before we destroy the coroutine frame, we need to load the target promise into
73047437 // a register or local variable which does not get spilled into the frame,
73057438 // 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,
73077440 irb->exec->await_handle_var_ptr, false);
73087441 IrInstruction *await_handle_in_block = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);
73097442 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
73387471 IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
73397472 get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
73407473 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);
73427475 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
73437476 IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
73447477 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
74357568 return val;
74367569}
74377570
7438static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) {
7571static ConstExprValue *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec) {
74397572 IrBasicBlock *bb = exec->basic_block_list.at(0);
74407573 for (size_t i = 0; i < bb->instruction_list.length; i += 1) {
74417574 IrInstruction *instruction = bb->instruction_list.at(i);
......@@ -7445,16 +7578,16 @@ static IrInstruction *ir_exec_const_result(CodeGen *codegen, IrExecutable *exec)
74457578 if (value->value.special == ConstValSpecialRuntime) {
74467579 exec_add_error_node(codegen, exec, value->source_node,
74477580 buf_sprintf("unable to evaluate constant expression"));
7448 return codegen->invalid_instruction;
7581 return &codegen->invalid_instruction->value;
74497582 }
7450 return value;
7583 return &value->value;
74517584 } else if (ir_has_side_effects(instruction)) {
74527585 exec_add_error_node(codegen, exec, instruction->source_node,
74537586 buf_sprintf("unable to evaluate constant expression"));
7454 return codegen->invalid_instruction;
7587 return &codegen->invalid_instruction->value;
74557588 }
74567589 }
7457 return codegen->invalid_instruction;
7590 return &codegen->invalid_instruction->value;
74587591}
74597592
74607593static 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
81748307
81758308 bool const_val_is_int = (const_val->type->id == ZigTypeIdInt || const_val->type->id == ZigTypeIdComptimeInt);
81768309 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
81788312 if (other_type->id == ZigTypeIdFloat) {
81798313 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
87688902 size_t errors_count = 0;
87698903 ZigType *err_set_type = nullptr;
87708904 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 }
87718908 if (type_is_global_error_set(prev_inst->value.type)) {
87728909 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
87738910 } else {
87748911 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 }
87788912 update_errors_helper(ira->codegen, &errors, &errors_count);
87798913
87808914 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
89339067 if (prev_type->id == ZigTypeIdArray) {
89349068 convert_to_const_slice = true;
89359069 }
9070 if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
9071 return ira->codegen->builtin_types.entry_invalid;
9072 }
89369073 if (type_is_global_error_set(cur_type)) {
89379074 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
89389075 continue;
......@@ -8940,9 +9077,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
89409077 if (err_set_type != nullptr && type_is_global_error_set(err_set_type)) {
89419078 continue;
89429079 }
8943 if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
8944 return ira->codegen->builtin_types.entry_invalid;
8945 }
89469080
89479081 update_errors_helper(ira->codegen, &errors, &errors_count);
89489082
......@@ -9432,14 +9566,23 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
94329566 }
94339567 return true;
94349568}
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
94359579static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
94369580 ZigType *wanted_type, CastOp cast_op, bool need_alloca)
94379581{
94389582 if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) &&
94399583 cast_op != CastOpResizeSlice)
94409584 {
9441 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
9442 source_instr->source_node, wanted_type);
9585 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
94439586 if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type,
94449587 &result->value, wanted_type))
94459588 {
......@@ -9476,9 +9619,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
94769619 if (pointee == nullptr)
94779620 return ira->codegen->invalid_instruction;
94789621 if (pointee->special != ConstValSpecialRuntime) {
9479 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
9480 source_instr->source_node, wanted_type);
9481 result->value.type = wanted_type;
9622 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
94829623 result->value.data.x_ptr.special = ConstPtrSpecialBaseArray;
94839624 result->value.data.x_ptr.mut = value->value.data.x_ptr.mut;
94849625 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
95179658 assert(is_slice(wanted_type));
95189659 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,
9521 source_instr->source_node, wanted_type);
9661 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
95229662 init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const);
95239663 result->value.data.x_struct.fields[slice_ptr_index].data.x_ptr.mut =
95249664 value->value.data.x_ptr.mut;
......@@ -9653,15 +9793,6 @@ static IrInstruction *ir_finish_anal(IrAnalyze *ira, IrInstruction *instruction)
96539793 return instruction;
96549794}
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
96659796static IrInstruction *ir_const_type(IrAnalyze *ira, IrInstruction *source_instruction, ZigType *ty) {
96669797 IrInstruction *result = ir_const(ira, source_instruction, ira->codegen->builtin_types.entry_type);
96679798 result->value.data.x_type = ty;
......@@ -9719,13 +9850,13 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
97199850 zig_unreachable();
97209851}
97219852
9722IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
9853ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
97239854 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
97249855 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
97259856 IrExecutable *parent_exec)
97269857{
97279858 if (expected_type != nullptr && type_is_invalid(expected_type))
9728 return codegen->invalid_instruction;
9859 return &codegen->invalid_instruction->value;
97299860
97309861 IrExecutable *ir_executable = allocate<IrExecutable>(1);
97319862 ir_executable->source_node = source_node;
......@@ -9738,13 +9869,13 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node
97389869 ir_gen(codegen, node, scope, ir_executable);
97399870
97409871 if (ir_executable->invalid)
9741 return codegen->invalid_instruction;
9872 return &codegen->invalid_instruction->value;
97429873
97439874 if (codegen->verbose_ir) {
97449875 fprintf(stderr, "\nSource: ");
97459876 ast_render(codegen, stderr, node, 4);
97469877 fprintf(stderr, "\n{ // (IR)\n");
9747 ir_print(codegen, stderr, ir_executable, 4);
9878 ir_print(codegen, stderr, ir_executable, 2);
97489879 fprintf(stderr, "}\n");
97499880 }
97509881 IrExecutable *analyzed_executable = allocate<IrExecutable>(1);
......@@ -9760,11 +9891,11 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node
97609891 analyzed_executable->begin_scope = scope;
97619892 ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, node);
97629893 if (type_is_invalid(result_type))
9763 return codegen->invalid_instruction;
9894 return &codegen->invalid_instruction->value;
97649895
97659896 if (codegen->verbose_ir) {
97669897 fprintf(stderr, "{ // (analyzed)\n");
9767 ir_print(codegen, stderr, analyzed_executable, 4);
9898 ir_print(codegen, stderr, analyzed_executable, 2);
97689899 fprintf(stderr, "}\n");
97699900 }
97709901
......@@ -9789,6 +9920,34 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) {
97899920 return const_val->data.x_type;
97909921}
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
97929951static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
97939952 if (fn_value == ira->codegen->invalid_instruction)
97949953 return nullptr;
......@@ -9810,7 +9969,9 @@ static ZigFn *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) {
98109969 return const_val->data.x_ptr.data.fn.fn_entry;
98119970}
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{
98149975 assert(wanted_type->id == ZigTypeIdOptional);
98159976
98169977 if (instr_is_comptime(value)) {
......@@ -9826,7 +9987,7 @@ static IrInstruction *ir_analyze_maybe_wrap(IrAnalyze *ira, IrInstruction *sourc
98269987 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
98279988 source_instr->scope, source_instr->source_node);
98289989 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)) {
98309991 copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst);
98319992 } else {
98329993 const_instruction->base.value.data.x_optional = val;
......@@ -9857,11 +10018,16 @@ static IrInstruction *ir_analyze_err_wrap_payload(IrAnalyze *ira, IrInstruction
985710018 if (!val)
985810019 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
986010026 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
986110027 source_instr->scope, source_instr->source_node);
986210028 const_instruction->base.value.type = wanted_type;
986310029 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;
986510031 const_instruction->base.value.data.x_err_union.payload = val;
986610032 return &const_instruction->base;
986710033 }
......@@ -9926,11 +10092,16 @@ static IrInstruction *ir_analyze_err_wrap_code(IrAnalyze *ira, IrInstruction *so
992610092 if (!val)
992710093 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
992910100 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
993010101 source_instr->scope, source_instr->source_node);
993110102 const_instruction->base.value.type = wanted_type;
993210103 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;
993410105 const_instruction->base.value.data.x_err_union.payload = nullptr;
993510106 return &const_instruction->base;
993610107 }
......@@ -9952,8 +10123,9 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so
995210123 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb, source_instr->scope, source_instr->source_node);
995310124 const_instruction->base.value.special = ConstValSpecialStatic;
995410125 if (get_codegen_ptr_type(wanted_type) != nullptr) {
9955 const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
9956 const_instruction->base.value.data.x_ptr.data.hard_coded_addr.addr = 0;
10126 const_instruction->base.value.data.x_ptr.special = ConstPtrSpecialNull;
10127 } else if (is_opt_err_set(wanted_type)) {
10128 const_instruction->base.value.data.x_err_set = nullptr;
995710129 } else {
995810130 const_instruction->base.value.data.x_optional = nullptr;
995910131 }
......@@ -9986,7 +10158,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
998610158 source_instruction->source_node, value, is_const, is_volatile);
998710159 new_instruction->value.type = ptr_type;
998810160 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)) {
999010162 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
999110163 assert(fn_entry);
999210164 fn_entry->alloca_list.append(new_instruction);
......@@ -10012,20 +10184,17 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
1001210184 ZigType *array_type = array->value.type;
1001310185 assert(array_type->id == ZigTypeIdArray);
1001410186
10015 if (instr_is_comptime(array)) {
10016 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10017 source_instr->source_node, wanted_type);
10187 if (instr_is_comptime(array) || array_type->data.array.len == 0) {
10188 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1001810189 init_const_slice(ira->codegen, &result->value, &array->value, 0, array_type->data.array.len, true);
1001910190 result->value.type = wanted_type;
1002010191 return result;
1002110192 }
1002210193
10023 IrInstruction *start = ir_create_const(&ira->new_irb, source_instr->scope,
10024 source_instr->source_node, ira->codegen->builtin_types.entry_usize);
10194 IrInstruction *start = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize);
1002510195 init_const_usize(ira->codegen, &start->value, 0);
1002610196
10027 IrInstruction *end = ir_create_const(&ira->new_irb, source_instr->scope,
10028 source_instr->source_node, ira->codegen->builtin_types.entry_usize);
10197 IrInstruction *end = ir_const(ira, source_instr, ira->codegen->builtin_types.entry_usize);
1002910198 init_const_usize(ira->codegen, &end->value, array_type->data.array.len);
1003010199
1003110200 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
1006410233 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
1006510234 if (!val)
1006610235 return ira->codegen->invalid_instruction;
10067 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10068 source_instr->source_node, wanted_type);
10236 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1006910237 init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag);
1007010238 return result;
1007110239 }
......@@ -10075,8 +10243,7 @@ static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *sour
1007510243 actual_type->data.enumeration.src_field_count == 1)
1007610244 {
1007710245 assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int);
10078 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10079 source_instr->source_node, wanted_type);
10246 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1008010247 init_const_bigint(&result->value, wanted_type,
1008110248 &actual_type->data.enumeration.fields[0].value);
1008210249 return result;
......@@ -10099,8 +10266,7 @@ static IrInstruction *ir_analyze_union_to_tag(IrAnalyze *ira, IrInstruction *sou
1009910266 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
1010010267 if (!val)
1010110268 return ira->codegen->invalid_instruction;
10102 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10103 source_instr->source_node, wanted_type);
10269 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1010410270 result->value.special = ConstValSpecialStatic;
1010510271 result->value.type = wanted_type;
1010610272 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
1011110277 if (wanted_type->data.enumeration.layout == ContainerLayoutAuto &&
1011210278 wanted_type->data.enumeration.src_field_count == 1)
1011310279 {
10114 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10115 source_instr->source_node, wanted_type);
10280 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1011610281 result->value.special = ConstValSpecialStatic;
1011710282 result->value.type = wanted_type;
1011810283 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
1012910294static IrInstruction *ir_analyze_undefined_to_anything(IrAnalyze *ira, IrInstruction *source_instr,
1013010295 IrInstruction *target, ZigType *wanted_type)
1013110296{
10132 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10133 source_instr->source_node, wanted_type);
10297 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1013410298 init_const_undefined(ira->codegen, &result->value);
1013510299 return result;
1013610300}
......@@ -10162,8 +10326,7 @@ static IrInstruction *ir_analyze_enum_to_union(IrAnalyze *ira, IrInstruction *so
1016210326 buf_sprintf("field '%s' declared here", buf_ptr(union_field->name)));
1016310327 return ira->codegen->invalid_instruction;
1016410328 }
10165 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10166 source_instr->source_node, wanted_type);
10329 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1016710330 result->value.special = ConstValSpecialStatic;
1016810331 result->value.type = wanted_type;
1016910332 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
1021810381 return ira->codegen->invalid_instruction;
1021910382 }
1022010383 }
10221 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10222 source_instr->source_node, wanted_type);
10384 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1022310385 result->value.type = wanted_type;
1022410386 if (wanted_type->id == ZigTypeIdInt) {
1022510387 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
1027310435 return ira->codegen->invalid_instruction;
1027410436 }
1027510437
10276 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10277 source_instr->source_node, wanted_type);
10438 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1027810439 bigint_init_bigint(&result->value.data.x_enum_tag, &val->data.x_bigint);
1027910440 return result;
1028010441 }
......@@ -10292,8 +10453,7 @@ static IrInstruction *ir_analyze_number_to_literal(IrAnalyze *ira, IrInstruction
1029210453 if (!val)
1029310454 return ira->codegen->invalid_instruction;
1029410455
10295 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10296 source_instr->source_node, wanted_type);
10456 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1029710457 if (wanted_type->id == ZigTypeIdComptimeFloat) {
1029810458 float_init_float(&result->value, val);
1029910459 } else if (wanted_type->id == ZigTypeIdComptimeInt) {
......@@ -10316,8 +10476,7 @@ static IrInstruction *ir_analyze_int_to_err(IrAnalyze *ira, IrInstruction *sourc
1031610476 if (!val)
1031710477 return ira->codegen->invalid_instruction;
1031810478
10319 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10320 source_instr->source_node, wanted_type);
10479 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1032110480
1032210481 if (!resolve_inferred_error_set(ira->codegen, wanted_type, source_instr->source_node)) {
1032310482 return ira->codegen->invalid_instruction;
......@@ -10381,12 +10540,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
1038110540 if (!val)
1038210541 return ira->codegen->invalid_instruction;
1038310542
10384 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10385 source_instr->source_node, wanted_type);
10543 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1038610544
1038710545 ErrorTableEntry *err;
1038810546 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;
1039010548 } else if (err_type->id == ZigTypeIdErrorSet) {
1039110549 err = val->data.x_err_set;
1039210550 } else {
......@@ -10421,15 +10579,11 @@ static IrInstruction *ir_analyze_err_to_int(IrAnalyze *ira, IrInstruction *sourc
1042110579 return ira->codegen->invalid_instruction;
1042210580 }
1042310581 if (err_set_type->data.error_set.err_count == 0) {
10424 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10425 source_instr->source_node, wanted_type);
10426 result->value.type = wanted_type;
10582 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1042710583 bigint_init_unsigned(&result->value.data.x_bigint, 0);
1042810584 return result;
1042910585 } else if (err_set_type->data.error_set.err_count == 1) {
10430 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
10431 source_instr->source_node, wanted_type);
10432 result->value.type = wanted_type;
10586 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1043310587 ErrorTableEntry *err = err_set_type->data.error_set.errors[0];
1043410588 bigint_init_unsigned(&result->value.data.x_bigint, err->value);
1043510589 return result;
......@@ -10476,8 +10630,8 @@ static IrInstruction *ir_analyze_ptr_to_array(IrAnalyze *ira, IrInstruction *sou
1047610630 array_val->type = array_type;
1047710631 array_val->data.x_array.special = ConstArraySpecialNone;
1047810632 array_val->data.x_array.data.s_none.elements = pointee;
10479 array_val->data.x_array.data.s_none.parent.id = ConstParentIdScalar;
10480 array_val->data.x_array.data.s_none.parent.data.p_scalar.scalar_val = pointee;
10633 array_val->parent.id = ConstParentIdScalar;
10634 array_val->parent.data.p_scalar.scalar_val = pointee;
1048110635
1048210636 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
1048310637 source_instr->scope, source_instr->source_node);
......@@ -10598,6 +10752,32 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
1059810752 }
1059910753}
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
1060110781static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
1060210782 ZigType *wanted_type, IrInstruction *value)
1060310783{
......@@ -10625,12 +10805,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1062510805 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,
1062610806 false).id == ConstCastResultIdOk)
1062710807 {
10628 return ir_analyze_maybe_wrap(ira, source_instr, value, wanted_type);
10808 return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type);
1062910809 } else if (actual_type->id == ZigTypeIdComptimeInt ||
1063010810 actual_type->id == ZigTypeIdComptimeFloat)
1063110811 {
1063210812 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);
1063410814 } else {
1063510815 return ira->codegen->invalid_instruction;
1063610816 }
......@@ -10654,7 +10834,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1065410834 wanted_child_type);
1065510835 if (type_is_invalid(cast1->value.type))
1065610836 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);
1065810838 }
1065910839 }
1066010840 }
......@@ -10707,6 +10887,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1070710887 (wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt ||
1070810888 wanted_type->id == ZigTypeIdFloat || wanted_type->id == ZigTypeIdComptimeFloat))
1070910889 {
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 }
1071010895 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type, true)) {
1071110896 if (wanted_type->id == ZigTypeIdComptimeInt || wanted_type->id == ZigTypeIdInt) {
1071210897 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
......@@ -10760,6 +10945,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1076010945
1076110946
1076210947 // cast from [N]T to []const T
10948 // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
1076310949 if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) {
1076410950 ZigType *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
1076510951 assert(ptr_type->id == ZigTypeIdPointer);
......@@ -10772,6 +10958,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1077210958 }
1077310959
1077410960 // cast from [N]T to ?[]const T
10961 // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
1077510962 if (wanted_type->id == ZigTypeIdOptional &&
1077610963 is_slice(wanted_type->data.maybe.child_type) &&
1077710964 actual_type->id == ZigTypeIdArray)
......@@ -10866,7 +11053,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1086611053 }
1086711054 }
1086811055
10869 // cast from error set to error union type
11056 // cast from E to E!T
1087011057 if (wanted_type->id == ZigTypeIdErrorUnion &&
1087111058 actual_type->id == ZigTypeIdErrorSet)
1087211059 {
......@@ -10979,6 +11166,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1097911166 }
1098011167 }
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
1098311187 // cast from undefined to anything
1098411188 if (actual_type->id == ZigTypeIdUndefined) {
......@@ -11018,8 +11222,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
1101811222 ZigType *child_type = type_entry->data.pointer.child_type;
1101911223 // dereferencing a *u0 is comptime known to be 0
1102011224 if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) {
11021 IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,
11022 source_instruction->source_node, child_type);
11225 IrInstruction *result = ir_const(ira, source_instruction, child_type);
1102311226 init_const_unsigned_negative(&result->value, child_type, 0, false);
1102411227 return result;
1102511228 }
......@@ -11033,8 +11236,7 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
1103311236 {
1103411237 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
1103511238 if (pointee->special != ConstValSpecialRuntime) {
11036 IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope,
11037 source_instruction->source_node, child_type);
11239 IrInstruction *result = ir_const(ira, source_instruction, child_type);
1103811240
1103911241 if ((err = ir_read_const_ptr(ira, ira->codegen, source_instruction->source_node, &result->value,
1104011242 &ptr->value)))
......@@ -11046,7 +11248,11 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
1104611248 }
1104711249 }
1104811250 }
11049 // TODO if the instruction is a const ref instruction we can skip it
11251 // 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 }
1105011256 IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,
1105111257 source_instruction->source_node, ptr);
1105211258 load_ptr_instruction->value.type = child_type;
......@@ -11293,8 +11499,7 @@ static IrInstruction *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructio
1129311499
1129411500static IrInstruction *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *instruction) {
1129511501 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
11296 // TODO determine if we need to use copy_const_val here
11297 result->value = instruction->base.value;
11502 copy_const_val(&result->value, &instruction->base.value, true);
1129811503 return result;
1129911504}
1130011505
......@@ -11369,6 +11574,8 @@ static bool optional_value_is_null(ConstExprValue *val) {
1136911574 if (get_codegen_ptr_type(val->type) != nullptr) {
1137011575 return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
1137111576 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;
1137211579 } else {
1137311580 return val->data.x_optional == nullptr;
1137411581 }
......@@ -11523,6 +11730,7 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1152311730 case ZigTypeIdComptimeInt:
1152411731 case ZigTypeIdInt:
1152511732 case ZigTypeIdFloat:
11733 case ZigTypeIdVector:
1152611734 operator_allowed = true;
1152711735 break;
1152811736
......@@ -11568,19 +11776,18 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1156811776 if (casted_op2 == ira->codegen->invalid_instruction)
1156911777 return ira->codegen->invalid_instruction;
1157011778
11571 bool requires_comptime;
11572 switch (type_requires_comptime(ira->codegen, resolved_type)) {
11573 case ReqCompTimeYes:
11574 requires_comptime = true;
11779 bool one_possible_value;
11780 switch (type_has_one_possible_value(ira->codegen, resolved_type)) {
11781 case OnePossibleValueInvalid:
11782 return ira->codegen->invalid_instruction;
11783 case OnePossibleValueYes:
11784 one_possible_value = true;
1157511785 break;
11576 case ReqCompTimeNo:
11577 requires_comptime = false;
11786 case OnePossibleValueNo:
11787 one_possible_value = false;
1157811788 break;
11579 case ReqCompTimeInvalid:
11580 return ira->codegen->invalid_instruction;
1158111789 }
1158211790
11583 bool one_possible_value = !requires_comptime && !type_has_bits(resolved_type);
1158411791 if (one_possible_value || (instr_is_comptime(casted_op1) && instr_is_comptime(casted_op2))) {
1158511792 ConstExprValue *op1_val = one_possible_value ? &casted_op1->value : ir_resolve_const(ira, casted_op1, UndefBad);
1158611793 if (op1_val == nullptr)
......@@ -11654,8 +11861,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
1165411861 return result;
1165511862}
1165611863
11657static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
11658 IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val)
11864static ErrorMsg *ir_eval_math_op_scalar(IrAnalyze *ira, IrInstruction *source_instr, ZigType *type_entry,
11865 ConstExprValue *op1_val, IrBinOp op_id, ConstExprValue *op2_val, ConstExprValue *out_val)
1165911866{
1166011867 bool is_int;
1166111868 bool is_float;
......@@ -11677,10 +11884,10 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
1167711884 if ((op_id == IrBinOpDivUnspecified || op_id == IrBinOpRemRem || op_id == IrBinOpRemMod ||
1167811885 op_id == IrBinOpDivTrunc || op_id == IrBinOpDivFloor) && op2_zcmp == CmpEQ)
1167911886 {
11680 return ErrorDivByZero;
11887 return ir_add_error(ira, source_instr, buf_sprintf("division by zero"));
1168111888 }
1168211889 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"));
1168411891 }
1168511892
1168611893 switch (op_id) {
......@@ -11726,7 +11933,7 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
1172611933 BigInt orig_bigint;
1172711934 bigint_shl(&orig_bigint, &out_val->data.x_bigint, &op2_val->data.x_bigint);
1172811935 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"));
1173011937 }
1173111938 break;
1173211939 }
......@@ -11794,14 +12001,14 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
1179412001 BigInt remainder;
1179512002 bigint_rem(&remainder, &op1_val->data.x_bigint, &op2_val->data.x_bigint);
1179612003 if (bigint_cmp_zero(&remainder) != CmpEQ) {
11797 return ErrorExactDivRemainder;
12004 return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder"));
1179812005 }
1179912006 } else {
1180012007 float_div_trunc(out_val, op1_val, op2_val);
1180112008 ConstExprValue remainder;
1180212009 float_rem(&remainder, op1_val, op2_val);
1180312010 if (float_cmp_zero(&remainder) != CmpEQ) {
11804 return ErrorExactDivRemainder;
12011 return ir_add_error(ira, source_instr, buf_sprintf("exact division had a remainder"));
1180512012 }
1180612013 }
1180712014 break;
......@@ -11825,13 +12032,51 @@ static int ir_eval_math_op(ZigType *type_entry, ConstExprValue *op1_val,
1182512032 if (!bigint_fits_in_bits(&out_val->data.x_bigint, type_entry->data.integral.bit_count,
1182612033 type_entry->data.integral.is_signed))
1182712034 {
11828 return ErrorOverflow;
12035 return ir_add_error(ira, source_instr, buf_sprintf("operation caused overflow"));
1182912036 }
1183012037 }
1183112038
1183212039 out_val->type = type_entry;
1183312040 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);
1183512080}
1183612081
1183712082static 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
1190312148 if (op2_val == nullptr)
1190412149 return ira->codegen->invalid_instruction;
1190512150
11906 IrInstruction *result_instruction = ir_const(ira, &bin_op_instruction->base, op1->value.type);
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;
12151 return ir_analyze_math_op(ira, &bin_op_instruction->base, op1->value.type, op1_val, op_id, op2_val);
1192412152 } else if (op1->value.type->id == ZigTypeIdComptimeInt) {
1192512153 ir_add_error(ira, &bin_op_instruction->base,
1192612154 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
1193912167 return result;
1194012168}
1194112169
11942static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {
11943 IrInstruction *op1 = instruction->op1->child;
11944 if (type_is_invalid(op1->value.type))
11945 return ira->codegen->invalid_instruction;
11946
11947 IrInstruction *op2 = instruction->op2->child;
11948 if (type_is_invalid(op2->value.type))
11949 return ira->codegen->invalid_instruction;
11950
11951 IrBinOp op_id = instruction->op_id;
11952
11953 // look for pointer math
11954 if (op1->value.type->id == ZigTypeIdPointer && op1->value.type->data.pointer.ptr_len == PtrLenUnknown &&
11955 (op_id == IrBinOpAdd || op_id == IrBinOpSub))
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 }
12170static bool ok_float_op(IrBinOp op) {
12171 switch (op) {
12172 case IrBinOpInvalid:
12173 zig_unreachable();
12174 case IrBinOpAdd:
12175 case IrBinOpSub:
12176 case IrBinOpMult:
12177 case IrBinOpDivUnspecified:
12178 case IrBinOpDivTrunc:
12179 case IrBinOpDivFloor:
12180 case IrBinOpDivExact:
12181 case IrBinOpRemRem:
12182 case IrBinOpRemMod:
12183 return true;
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};
1196812238 ZigType *resolved_type = ir_resolve_peer_types(ira, instruction->base.source_node, nullptr, instructions, 2);
1196912239 if (type_is_invalid(resolved_type))
1197012240 return ira->codegen->invalid_instruction;
......@@ -12076,21 +12346,20 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
1207612346 op_id = IrBinOpRemRem;
1207712347 }
1207812348
12349 bool ok = false;
1207912350 if (is_int) {
12080 // int
12081 } else if (is_float &&
12082 (op_id == IrBinOpAdd ||
12083 op_id == IrBinOpSub ||
12084 op_id == IrBinOpMult ||
12085 op_id == IrBinOpDivUnspecified ||
12086 op_id == IrBinOpDivTrunc ||
12087 op_id == IrBinOpDivFloor ||
12088 op_id == IrBinOpDivExact ||
12089 op_id == IrBinOpRemRem ||
12090 op_id == IrBinOpRemMod))
12091 {
12092 // float
12093 } else {
12351 ok = true;
12352 } else if (is_float && ok_float_op(op_id)) {
12353 ok = true;
12354 } else if (resolved_type->id == ZigTypeIdVector) {
12355 ZigType *elem_type = resolved_type->data.vector.elem_type;
12356 if (elem_type->id == ZigTypeIdInt || elem_type->id == ZigTypeIdComptimeInt) {
12357 ok = true;
12358 } else if ((elem_type->id == ZigTypeIdFloat || elem_type->id == ZigTypeIdComptimeFloat) && ok_float_op(op_id)) {
12359 ok = true;
12360 }
12361 }
12362 if (!ok) {
1209412363 AstNode *source_node = instruction->base.source_node;
1209512364 ir_add_error_node(ira, source_node,
1209612365 buf_sprintf("invalid operands to binary expression: '%s' and '%s'",
......@@ -12125,30 +12394,7 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
1212512394 if (op2_val == nullptr)
1212612395 return ira->codegen->invalid_instruction;
1212712396
12128 IrInstruction *result_instruction = ir_const(ira, &instruction->base, resolved_type);
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;
12397 return ir_analyze_math_op(ira, &instruction->base, resolved_type, op1_val, op_id, op2_val);
1215212398 }
1215312399
1215412400 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
1220212448 op1_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
1220312449 op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
1220412450 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);
1220612452 } else {
1220712453 ir_add_error(ira, op1,
1220812454 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
1221212458 ConstExprValue *op2_array_val;
1221312459 size_t op2_array_index;
1221412460 size_t op2_array_end;
12461 bool op2_type_valid;
1221512462 if (op2_type->id == ZigTypeIdArray) {
12216 if (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 }
12463 op2_type_valid = op2_type->data.array.child_type == child_type;
1222212464 op2_array_val = op2_val;
1222312465 op2_array_index = 0;
1222412466 op2_array_end = op2_array_val->type->data.array.len;
......@@ -12227,35 +12469,30 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
1222712469 op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray &&
1222812470 op2_val->data.x_ptr.data.base_array.is_cstr)
1222912471 {
12230 if (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 }
12472 op2_type_valid = child_type == ira->codegen->builtin_types.entry_u8;
1223612473 op2_array_val = op2_val->data.x_ptr.data.base_array.array_val;
1223712474 op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index;
1223812475 op2_array_end = op2_array_val->type->data.array.len - 1;
1223912476 } else if (is_slice(op2_type)) {
1224012477 ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index].type_entry;
12241 if (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 }
12478 op2_type_valid = ptr_type->data.pointer.child_type == child_type;
1224712479 ConstExprValue *ptr_val = &op2_val->data.x_struct.fields[slice_ptr_index];
1224812480 assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
1224912481 op2_array_val = ptr_val->data.x_ptr.data.base_array.array_val;
1225012482 op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
12251 op2_array_end = op2_array_val->type->data.array.len;
1225212483 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);
1225412485 } else {
1225512486 ir_add_error(ira, op2,
1225612487 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));
1225712488 return ira->codegen->invalid_instruction;
1225812489 }
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
1226012497 // The type of result is populated in the following if blocks
1226112498 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
......@@ -12388,26 +12625,14 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
1238812625}
1238912626
1239012627static 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);
1239212629 if (type_is_invalid(op1_type))
1239312630 return ira->codegen->invalid_instruction;
1239412631
12395 if (op1_type->id != ZigTypeIdErrorSet) {
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);
12632 ZigType *op2_type = ir_resolve_error_set_type(ira, &instruction->base, instruction->op2->child);
1240212633 if (type_is_invalid(op2_type))
1240312634 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
1241112636 if (type_is_global_error_set(op1_type) ||
1241212637 type_is_global_error_set(op2_type))
1241312638 {
......@@ -12481,13 +12706,15 @@ static IrInstruction *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructio
1248112706 zig_unreachable();
1248212707}
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{
1248512712 Error err;
1248612713 ZigVar *var = decl_var_instruction->var;
1248712714
1248812715 IrInstruction *init_value = decl_var_instruction->init_value->child;
1248912716 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;
1249112718 return ira->codegen->invalid_instruction;
1249212719 }
1249312720
......@@ -12498,7 +12725,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1249812725 ZigType *proposed_type = ir_resolve_type(ira, var_type);
1249912726 explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type);
1250012727 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;
1250212729 return ira->codegen->invalid_instruction;
1250312730 }
1250412731 }
......@@ -12523,7 +12750,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1252312750 case ReqCompTimeInvalid:
1252412751 result_type = ira->codegen->builtin_types.entry_invalid;
1252512752 break;
12526 case ReqCompTimeYes: {
12753 case ReqCompTimeYes:
1252712754 var_class_requires_const = true;
1252812755 if (!var->gen_is_const && !is_comptime_var) {
1252912756 ir_add_error_node(ira, source_node,
......@@ -12532,7 +12759,6 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1253212759 result_type = ira->codegen->builtin_types.entry_invalid;
1253312760 }
1253412761 break;
12535 }
1253612762 case ReqCompTimeNo:
1253712763 if (casted_init_value->value.special == ConstValSpecialStatic &&
1253812764 casted_init_value->value.type->id == ZigTypeIdFn &&
......@@ -12551,7 +12777,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1255112777 break;
1255212778 }
1255312779
12554 if (var->value->type != nullptr && !is_comptime_var) {
12780 if (var->var_type != nullptr && !is_comptime_var) {
1255512781 // This is at least the second time we've seen this variable declaration during analysis.
1255612782 // This means that this is actually a different variable due to, e.g. an inline while loop.
1255712783 // 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
1257312799 // This must be done after possibly creating a new variable above
1257412800 var->ref_count = 0;
1257512801
12576 var->value->type = result_type;
12577 assert(var->value->type);
12802 var->var_type = result_type;
12803 assert(var->var_type);
1257812804
1257912805 if (type_is_invalid(result_type)) {
1258012806 return ir_const_void(ira, &decl_var_instruction->base);
......@@ -12582,13 +12808,13 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1258212808
1258312809 if (decl_var_instruction->align_value == nullptr) {
1258412810 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;
1258612812 return ir_const_void(ira, &decl_var_instruction->base);
1258712813 }
1258812814 var->align_bytes = get_abi_alignment(ira->codegen, result_type);
1258912815 } else {
1259012816 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;
1259212818 }
1259312819 }
1259412820
......@@ -12605,7 +12831,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1260512831 } else if (is_comptime_var) {
1260612832 ir_add_error(ira, &decl_var_instruction->base,
1260712833 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;
1260912835 return ira->codegen->invalid_instruction;
1261012836 }
1261112837
......@@ -12613,11 +12839,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct
1261312839 if (fn_entry)
1261412840 fn_entry->variable_list.append(var);
1261512841
12616 IrInstruction *result = ir_build_var_decl(&ira->new_irb,
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;
12842 return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value);
1262112843}
1262212844
1262312845static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {
......@@ -12739,6 +12961,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
1273912961 case ZigTypeIdPointer:
1274012962 case ZigTypeIdArray:
1274112963 case ZigTypeIdBool:
12964 case ZigTypeIdVector:
1274212965 break;
1274312966 case ZigTypeIdMetaType:
1274412967 case ZigTypeIdVoid:
......@@ -12773,6 +12996,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
1277312996 case ZigTypeIdOptional:
1277412997 case ZigTypeIdErrorUnion:
1277512998 case ZigTypeIdErrorSet:
12999 case ZigTypeIdVector:
1277613000 zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name));
1277713001 case ZigTypeIdNamespace:
1277813002 case ZigTypeIdBoundFn:
......@@ -12947,7 +13171,7 @@ static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node
1294713171
1294813172 Buf *param_name = param_decl_node->data.param_decl.name;
1294913173 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);
1295113175 *exec_scope = var->child_scope;
1295213176 *next_proto_i += 1;
1295313177
......@@ -13005,7 +13229,7 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod
1300513229 if (!param_name) return false;
1300613230 if (!is_var_args) {
1300713231 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);
1300913233 *child_scope = var->child_scope;
1301013234 var->shadowable = !comptime_arg;
1301113235
......@@ -13059,9 +13283,7 @@ static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) {
1305913283 return fn_entry->variable_list.at(next_var_i);
1306013284}
1306113285
13062static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
13063 ZigVar *var)
13064{
13286static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, ZigVar *var) {
1306513287 while (var->next_var != nullptr) {
1306613288 var = var->next_var;
1306713289 }
......@@ -13070,14 +13292,14 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
1307013292 assert(ira->codegen->errors.length != 0);
1307113293 return ira->codegen->invalid_instruction;
1307213294 }
13073 if (var->value->type == nullptr || type_is_invalid(var->value->type))
13295 if (var->var_type == nullptr || type_is_invalid(var->var_type))
1307413296 return ira->codegen->invalid_instruction;
1307513297
1307613298 bool comptime_var_mem = ir_get_var_is_comptime(var);
1307713299
1307813300 ConstExprValue *mem_slot = nullptr;
13079 if (var->value->special == ConstValSpecialStatic) {
13080 mem_slot = var->value;
13301 if (var->const_value->special == ConstValSpecialStatic) {
13302 mem_slot = var->const_value;
1308113303 } else {
1308213304 if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) {
1308313305 // find the relevant exec_context
......@@ -13106,7 +13328,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
1310613328 assert(!comptime_var_mem);
1310713329 ptr_mut = ConstPtrMutRuntimeVar;
1310813330 }
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,
1311013332 ptr_mut, is_const, is_volatile, var->align_bytes);
1311113333 }
1311213334 }
......@@ -13117,7 +13339,7 @@ no_mem_slot:
1311713339
1311813340 IrInstruction *var_ptr_instruction = ir_build_var_ptr(&ira->new_irb,
1311913341 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,
1312113343 var->src_is_const, is_volatile, PtrLenSingle, var->align_bytes, 0, 0);
1312213344
1312313345 bool in_fn_scope = (scope_fn_entry(var->parent_scope) != nullptr);
......@@ -13126,6 +13348,96 @@ no_mem_slot:
1312613348 return var_ptr_instruction;
1312713349}
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
1312913441static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction,
1313013442 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
1313113443 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
1327013582 }
1327113583
1327213584 bool cacheable = fn_eval_cacheable(exec_scope, return_type);
13273 IrInstruction *result = nullptr;
13585 ConstExprValue *result = nullptr;
1327413586 if (cacheable) {
1327513587 auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope);
1327613588 if (entry)
......@@ -13286,18 +13598,19 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1328613598
1328713599 if (inferred_err_set_type != nullptr) {
1328813600 inferred_err_set_type->data.error_set.infer_fn = nullptr;
13289 if (result->value.type->id == ZigTypeIdErrorUnion) {
13290 if (result->value.data.x_err_union.err != nullptr) {
13601 if (result->type->id == ZigTypeIdErrorUnion) {
13602 ErrorTableEntry *err = result->data.x_err_union.error_set->data.x_err_set;
13603 if (err != nullptr) {
1329113604 inferred_err_set_type->data.error_set.err_count = 1;
1329213605 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;
1329413607 }
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;
1329613609 inferred_err_set_type->data.error_set.err_count = fn_inferred_err_set_type->data.error_set.err_count;
1329713610 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) {
13299 inferred_err_set_type->data.error_set.err_count = result->value.type->data.error_set.err_count;
13300 inferred_err_set_type->data.error_set.errors = result->value.type->data.error_set.errors;
13611 } else if (result->type->id == ZigTypeIdErrorSet) {
13612 inferred_err_set_type->data.error_set.err_count = result->type->data.error_set.err_count;
13613 inferred_err_set_type->data.error_set.errors = result->type->data.error_set.errors;
1330113614 }
1330213615 }
1330313616
......@@ -13305,13 +13618,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1330513618 ira->codegen->memoized_fn_eval_table.put(exec_scope, result);
1330613619 }
1330713620
13308 if (type_is_invalid(result->value.type))
13621 if (type_is_invalid(result->type))
1330913622 return ira->codegen->invalid_instruction;
1331013623 }
1331113624
13312 IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->value.type);
13313 // TODO should we use copy_const_val?
13314 new_instruction->value = result->value;
13625 IrInstruction *new_instruction = ir_const(ira, &call_instruction->base, result->type);
13626 copy_const_val(&new_instruction->value, result, true);
1331513627 new_instruction->value.type = return_type;
1331613628 return ir_finish_anal(ira, new_instruction);
1331713629 }
......@@ -13470,18 +13782,21 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1347013782 ConstExprValue *var_args_val = create_const_arg_tuple(ira->codegen,
1347113783 first_var_arg, inst_fn_type_id.param_count);
1347213784 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);
1347413786 impl_fn->child_scope = var->child_scope;
1347513787 }
1347613788
1347713789 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,
1347913791 fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),
1348013792 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota,
1348113793 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
1348313798 uint32_t align_bytes = 0;
13484 ir_resolve_align(ira, align_result, &align_bytes);
13799 ir_resolve_align(ira, &const_instruction->base, &align_bytes);
1348513800 impl_fn->align_bytes = align_bytes;
1348613801 inst_fn_type_id.alignment = align_bytes;
1348713802 }
......@@ -13559,12 +13874,12 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1355913874 ira->codegen->fn_defs.append(impl_fn);
1356013875 }
1356113876
13562 ZigType *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type;
13563 if (fn_type_can_fail(&impl_fn->type_entry->data.fn.fn_type_id)) {
13877 FnTypeId *impl_fn_type_id = &impl_fn->type_entry->data.fn.fn_type_id;
13878 if (fn_type_can_fail(impl_fn_type_id)) {
1356413879 parent_fn_entry->calls_or_awaits_errorable_fn = true;
1356513880 }
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;
1356813883 if (call_instruction->is_async) {
1356913884 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,
1357013885 fn_ref, casted_args, impl_param_count, async_allocator_inst);
......@@ -13577,9 +13892,9 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1357713892 call_instruction->base.scope, call_instruction->base.source_node,
1357813893 impl_fn, nullptr, impl_param_count, casted_args, false, fn_inline,
1357913894 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
1358413899 return ir_finish_anal(ira, new_call_instruction);
1358513900 }
......@@ -13774,6 +14089,13 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
1377414089 switch (ptr_val->data.x_ptr.special) {
1377514090 case ConstPtrSpecialInvalid:
1377614091 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;
1377714099 case ConstPtrSpecialRef: {
1377814100 opt_ir_add_error_node(ira, codegen, source_node,
1377914101 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
1380614128 return ErrorNone;
1380714129 }
1380814130 case ConstPtrSpecialBaseStruct:
14131 case ConstPtrSpecialBaseErrorUnionCode:
14132 case ConstPtrSpecialBaseErrorUnionPayload:
14133 case ConstPtrSpecialBaseOptionalPayload:
1380914134 case ConstPtrSpecialDiscard:
1381014135 case ConstPtrSpecialHardCodedAddr:
1381114136 case ConstPtrSpecialFunction:
......@@ -13830,6 +14155,7 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_
1383014155 case ZigTypeIdVoid:
1383114156 case ZigTypeIdBool:
1383214157 case ZigTypeIdInt:
14158 case ZigTypeIdVector:
1383314159 case ZigTypeIdFloat:
1383414160 case ZigTypeIdPointer:
1383514161 case ZigTypeIdArray:
......@@ -14001,9 +14327,14 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi
1400114327 if (!ir_resolve_comptime(ira, cond_br_instruction->is_comptime->child, &is_comptime))
1400214328 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)) {
1400514336 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))
1400714338 return ir_unreach_error(ira);
1400814339
1400914340 IrBasicBlock *old_dest_block = cond_is_true ?
......@@ -14022,11 +14353,6 @@ static IrInstruction *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructi
1402214353 return ir_finish_anal(ira, result);
1402314354 }
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
1403014356 assert(cond_br_instruction->then_block != cond_br_instruction->else_block);
1403114357 IrBasicBlock *new_then_block = ir_get_new_bb_runtime(ira, cond_br_instruction->then_block, &cond_br_instruction->base);
1403214358 if (new_then_block == nullptr)
......@@ -14065,8 +14391,7 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
1406514391
1406614392 if (value->value.special != ConstValSpecialRuntime) {
1406714393 IrInstruction *result = ir_const(ira, &phi_instruction->base, nullptr);
14068 // TODO use copy_const_val?
14069 result->value = value->value;
14394 copy_const_val(&result->value, &value->value, true);
1407014395 return result;
1407114396 } else {
1407214397 return value;
......@@ -14115,14 +14440,24 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
1411514440 if (type_is_invalid(resolved_type))
1411614441 return ira->codegen->invalid_instruction;
1411714442
14118 if (resolved_type->id == ZigTypeIdComptimeFloat ||
14119 resolved_type->id == ZigTypeIdComptimeInt ||
14120 resolved_type->id == ZigTypeIdNull ||
14121 resolved_type->id == ZigTypeIdUndefined)
14122 {
14443 switch (type_has_one_possible_value(ira->codegen, resolved_type)) {
14444 case OnePossibleValueInvalid:
14445 return ira->codegen->invalid_instruction;
14446 case OnePossibleValueYes:
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:
1412314456 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)));
1412514458 return ira->codegen->invalid_instruction;
14459 case ReqCompTimeNo:
14460 break;
1412614461 }
1412714462
1412814463 bool all_stack_ptrs = (resolved_type->id == ZigTypeIdPointer);
......@@ -14412,10 +14747,18 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1441214747 }
1441314748 case ConstPtrSpecialBaseStruct:
1441414749 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");
1441514756 case ConstPtrSpecialHardCodedAddr:
1441614757 zig_unreachable();
1441714758 case ConstPtrSpecialFunction:
1441814759 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");
1441914762 }
1442014763 if (new_index >= mem_size) {
1442114764 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
1446514808 }
1446614809 case ConstPtrSpecialBaseStruct:
1446714810 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");
1446814817 case ConstPtrSpecialHardCodedAddr:
1446914818 zig_unreachable();
1447014819 case ConstPtrSpecialFunction:
1447114820 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");
1447214823 }
1447314824 return result;
1447414825 } else if (array_type->id == ZigTypeIdArray) {
......@@ -15155,74 +15506,23 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
1515515506 }
1515615507}
1515715508
15158static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) {
15159 IrInstruction *ptr = load_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;
15509static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *instruction) {
15510 IrInstruction *ptr = instruction->ptr->child;
1516715511 if (type_is_invalid(ptr->value.type))
1516815512 return ira->codegen->invalid_instruction;
1516915513
15170 IrInstruction *value = store_ptr_instruction->value->child;
15514 IrInstruction *value = instruction->value->child;
1517115515 if (type_is_invalid(value->value.type))
1517215516 return ira->codegen->invalid_instruction;
1517315517
15174 if (ptr->value.type->id != ZigTypeIdPointer) {
15175 ir_add_error(ira, ptr,
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 }
15518 return ir_analyze_store_ptr(ira, &instruction->base, ptr, value);
15519}
1518815520
15189 ZigType *child_type = ptr->value.type->data.pointer.child_type;
15190 IrInstruction *casted_value = ir_implicit_cast(ira, value, child_type);
15191 if (casted_value == ira->codegen->invalid_instruction)
15521static IrInstruction *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *instruction) {
15522 IrInstruction *ptr = instruction->ptr->child;
15523 if (type_is_invalid(ptr->value.type))
1519215524 return ira->codegen->invalid_instruction;
15193
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;
15525 return ir_get_deref(ira, &instruction->base, ptr);
1522615526}
1522715527
1522815528static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) {
......@@ -15230,37 +15530,7 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio
1523015530 ZigType *type_entry = expr_value->value.type;
1523115531 if (type_is_invalid(type_entry))
1523215532 return ira->codegen->invalid_instruction;
15233 switch (type_entry->id) {
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();
15533 return ir_const_type(ira, &typeof_instruction->base, type_entry);
1526415534}
1526515535
1526615536static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
......@@ -15499,6 +15769,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
1549915769 case ZigTypeIdNamespace:
1550015770 case ZigTypeIdBoundFn:
1550115771 case ZigTypeIdPromise:
15772 case ZigTypeIdVector:
1550215773 {
1550315774 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
1550415775 return ira->codegen->invalid_instruction;
......@@ -15619,6 +15890,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
1561915890 case ZigTypeIdNamespace:
1562015891 case ZigTypeIdBoundFn:
1562115892 case ZigTypeIdPromise:
15893 case ZigTypeIdVector:
1562215894 {
1562315895 if ((err = ensure_complete_type(ira->codegen, child_type)))
1562415896 return ira->codegen->invalid_instruction;
......@@ -15685,6 +15957,7 @@ static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
1568515957 case ZigTypeIdUnion:
1568615958 case ZigTypeIdFn:
1568715959 case ZigTypeIdPromise:
15960 case ZigTypeIdVector:
1568815961 {
1568915962 uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
1569015963 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,
1569315966 zig_unreachable();
1569415967}
1569515968
15696static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) {
15697 IrInstruction *value = instruction->value->child;
15698 if (type_is_invalid(value->value.type))
15699 return ira->codegen->invalid_instruction;
15700
15969static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value) {
1570115970 ZigType *type_entry = value->value.type;
1570215971
1570315972 if (type_entry->id == ZigTypeIdOptional) {
......@@ -15706,60 +15975,66 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns
1570615975 if (!maybe_val)
1570715976 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));
1571015979 }
1571115980
1571215981 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);
1571415983 result->value.type = ira->codegen->builtin_types.entry_bool;
1571515984 return result;
1571615985 } else if (type_entry->id == ZigTypeIdNull) {
15717 return ir_const_bool(ira, &instruction->base, false);
15986 return ir_const_bool(ira, source_inst, false);
1571815987 } else {
15719 return ir_const_bool(ira, &instruction->base, true);
15988 return ir_const_bool(ira, source_inst, true);
1572015989 }
1572115990}
1572215991
15723static IrInstruction *ir_analyze_instruction_unwrap_maybe(IrAnalyze *ira,
15724 IrInstructionUnwrapOptional *unwrap_maybe_instruction)
15725{
15726 IrInstruction *value = unwrap_maybe_instruction->value->child;
15992static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrInstructionTestNonNull *instruction) {
15993 IrInstruction *value = instruction->value->child;
1572715994 if (type_is_invalid(value->value.type))
1572815995 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;
1573116004 assert(ptr_type->id == ZigTypeIdPointer);
1573216005
1573316006 ZigType *type_entry = ptr_type->data.pointer.child_type;
15734 if (type_is_invalid(type_entry)) {
16007 if (type_is_invalid(type_entry))
1573516008 return ira->codegen->invalid_instruction;
15736 } else if (type_entry->id != ZigTypeIdOptional) {
15737 ir_add_error_node(ira, unwrap_maybe_instruction->value->source_node,
16009
16010 if (type_entry->id != ZigTypeIdOptional) {
16011 ir_add_error_node(ira, base_ptr->source_node,
1573816012 buf_sprintf("expected optional type, found '%s'", buf_ptr(&type_entry->name)));
1573916013 return ira->codegen->invalid_instruction;
1574016014 }
16015
1574116016 ZigType *child_type = type_entry->data.maybe.child_type;
1574216017 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
1574316018 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0);
1574416019
15745 if (instr_is_comptime(value)) {
15746 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
16020 if (instr_is_comptime(base_ptr)) {
16021 ConstExprValue *val = ir_resolve_const(ira, base_ptr, UndefBad);
1574716022 if (!val)
1574816023 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);
1575016025 if (maybe_val == nullptr)
1575116026 return ira->codegen->invalid_instruction;
1575216027
1575316028 if (val->data.x_ptr.mut != ConstPtrMutRuntimeVar) {
1575416029 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"));
1575616031 return ira->codegen->invalid_instruction;
1575716032 }
15758 IrInstruction *result = ir_const(ira, &unwrap_maybe_instruction->base, result_type);
16033 IrInstruction *result = ir_const(ira, source_instr, result_type);
1575916034 ConstExprValue *out_val = &result->value;
1576016035 out_val->data.x_ptr.special = ConstPtrSpecialRef;
1576116036 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)) {
1576316038 out_val->data.x_ptr.data.ref.pointee = maybe_val;
1576416039 } else {
1576516040 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,
1576816043 }
1576916044 }
1577016045
15771 IrInstruction *result = ir_build_unwrap_maybe(&ira->new_irb,
15772 unwrap_maybe_instruction->base.scope, unwrap_maybe_instruction->base.source_node,
15773 value, unwrap_maybe_instruction->safety_check_on);
16046 IrInstruction *result = ir_build_optional_unwrap_ptr(&ira->new_irb, source_instr->scope,
16047 source_instr->source_node, base_ptr, safety_check_on);
1577416048 result->value.type = result_type;
1577516049 return result;
1577616050}
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
1577816062static IrInstruction *ir_analyze_instruction_ctz(IrAnalyze *ira, IrInstructionCtz *ctz_instruction) {
1577916063 IrInstruction *value = ctz_instruction->value->child;
1578016064 if (type_is_invalid(value->value.type)) {
......@@ -16075,9 +16359,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1607516359 return result;
1607616360 }
1607716361
16078 IrInstruction *result = ir_build_load_ptr(&ira->new_irb,
16079 switch_target_instruction->base.scope, switch_target_instruction->base.source_node,
16080 target_value_ptr);
16362 IrInstruction *result = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
1608116363 result->value.type = target_type;
1608216364 return result;
1608316365 }
......@@ -16107,8 +16389,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1610716389 return result;
1610816390 }
1610916391
16110 IrInstruction *union_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,
16111 switch_target_instruction->base.source_node, target_value_ptr);
16392 IrInstruction *union_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
1611216393 union_value->value.type = target_type;
1611316394
1611416395 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,
1613216413 return result;
1613316414 }
1613416415
16135 IrInstruction *enum_value = ir_build_load_ptr(&ira->new_irb, switch_target_instruction->base.scope,
16136 switch_target_instruction->base.source_node, target_value_ptr);
16416 IrInstruction *enum_value = ir_get_deref(ira, &switch_target_instruction->base, target_value_ptr);
1613716417 enum_value->value.type = target_type;
1613816418 return enum_value;
1613916419 }
......@@ -16147,6 +16427,7 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
1614716427 case ZigTypeIdBoundFn:
1614816428 case ZigTypeIdArgTuple:
1614916429 case ZigTypeIdOpaque:
16430 case ZigTypeIdVector:
1615016431 ir_add_error(ira, &switch_target_instruction->base,
1615116432 buf_sprintf("invalid switch target type '%s'", buf_ptr(&target_type->name)));
1615216433 return ira->codegen->invalid_instruction;
......@@ -16290,7 +16571,7 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
1629016571 Error err;
1629116572 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)))
1629416575 return ira->codegen->invalid_instruction;
1629516576
1629616577 if (instr_field_count != 1) {
......@@ -16322,7 +16603,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
1632216603 if ((err = type_resolve(ira->codegen, casted_field_value->value.type, ResolveStatusZeroBitsKnown)))
1632316604 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;
1632616608 if (is_comptime || casted_field_value->value.special != ConstValSpecialRuntime ||
1632716609 !type_has_bits(casted_field_value->value.type))
1632816610 {
......@@ -16334,12 +16616,8 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
1633416616 ConstExprValue *out_val = &result->value;
1633516617 out_val->data.x_union.payload = field_val;
1633616618 out_val->data.x_union.tag = type_field->enum_field->value;
16337
16338 ConstParent *parent = get_const_val_parent(ira->codegen, field_val);
16339 if (parent != nullptr) {
16340 parent->id = ConstParentIdUnion;
16341 parent->data.p_union.union_val = out_val;
16342 }
16619 out_val->parent.id = ConstParentIdUnion;
16620 out_val->parent.data.p_union.union_val = out_val;
1634316621
1634416622 return result;
1634516623 }
......@@ -16366,7 +16644,7 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1636616644 return ira->codegen->invalid_instruction;
1636716645 }
1636816646
16369 if ((err = ensure_complete_type(ira->codegen, container_type)))
16647 if ((err = type_resolve(ira->codegen, container_type, ResolveStatusSizeKnown)))
1637016648 return ira->codegen->invalid_instruction;
1637116649
1637216650 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
1637716655
1637816656 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
1638216661 ConstExprValue const_val = {};
1638316662 const_val.special = ConstValSpecialStatic;
......@@ -16445,9 +16724,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1644516724 if (const_val.special == ConstValSpecialStatic) {
1644616725 IrInstruction *result = ir_const(ira, instruction, nullptr);
1644716726 ConstExprValue *out_val = &result->value;
16448 // TODO copy_const_val?
16449 *out_val = const_val;
16450 result->value.type = container_type;
16727 copy_const_val(out_val, &const_val, true);
16728 out_val->type = container_type;
1645116729
1645216730 for (size_t i = 0; i < instr_field_count; i += 1) {
1645316731 ConstExprValue *field_val = &out_val->data.x_struct.fields[i];
......@@ -16479,127 +16757,119 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1647916757static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
1648016758 IrInstructionContainerInitList *instruction)
1648116759{
16482 IrInstruction *container_type_value = instruction->container_type->child;
16483 if (type_is_invalid(container_type_value->value.type))
16760 ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
16761 if (type_is_invalid(container_type))
1648416762 return ira->codegen->invalid_instruction;
1648516763
1648616764 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) {
16493 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
16494 0, nullptr);
16495 } 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 wrong
16497 ZigType *child_type;
16498 if (container_type->id == ZigTypeIdArray) {
16499 child_type = container_type->data.array.child_type;
16500 if (container_type->data.array.len != elem_count) {
16501 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
16766 if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {
16767 return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
16768 0, nullptr);
16769 } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) {
16770 // array is same as slice init but we make a compile error if the length is wrong
16771 ZigType *child_type;
16772 if (container_type->id == ZigTypeIdArray) {
16773 child_type = container_type->data.array.child_type;
16774 if (container_type->data.array.len != elem_count) {
16775 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
1650216776
16503 ir_add_error(ira, &instruction->base,
16504 buf_sprintf("expected %s literal, found %s literal",
16505 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
16506 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;
16777 ir_add_error(ira, &instruction->base,
16778 buf_sprintf("expected %s literal, found %s literal",
16779 buf_ptr(&container_type->name), buf_ptr(&literal_type->name)));
16780 return ira->codegen->invalid_instruction;
1651216781 }
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 = {};
16517 const_val.special = ConstValSpecialStatic;
16518 const_val.type = fixed_size_array_type;
16519 const_val.data.x_array.data.s_none.elements = create_const_vals(elem_count);
16790 ConstExprValue const_val = {};
16791 const_val.special = ConstValSpecialStatic;
16792 const_val.type = fixed_size_array_type;
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) {
16528 IrInstruction *arg_value = instruction->items[i]->child;
16529 if (type_is_invalid(arg_value->value.type))
16530 return ira->codegen->invalid_instruction;
16801 for (size_t i = 0; i < elem_count; i += 1) {
16802 IrInstruction *arg_value = instruction->items[i]->child;
16803 if (type_is_invalid(arg_value->value.type))
16804 return ira->codegen->invalid_instruction;
1653116805
16532 IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);
16533 if (casted_arg == ira->codegen->invalid_instruction)
16534 return ira->codegen->invalid_instruction;
16806 IrInstruction *casted_arg = ir_implicit_cast(ira, arg_value, child_type);
16807 if (casted_arg == 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) {
16539 if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {
16540 ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);
16541 if (!elem_val)
16542 return ira->codegen->invalid_instruction;
16812 if (const_val.special == ConstValSpecialStatic) {
16813 if (is_comptime || casted_arg->value.special != ConstValSpecialRuntime) {
16814 ConstExprValue *elem_val = ir_resolve_const(ira, casted_arg, UndefBad);
16815 if (!elem_val)
16816 return ira->codegen->invalid_instruction;
1654316817
16544 copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);
16545 } else {
16546 first_non_const_instruction = casted_arg;
16547 const_val.special = ConstValSpecialRuntime;
16548 }
16818 copy_const_val(&const_val.data.x_array.data.s_none.elements[i], elem_val, true);
16819 } else {
16820 first_non_const_instruction = casted_arg;
16821 const_val.special = ConstValSpecialRuntime;
1654916822 }
1655016823 }
16824 }
1655116825
16552 if (const_val.special == ConstValSpecialStatic) {
16553 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
16554 ConstExprValue *out_val = &result->value;
16555 // TODO copy_const_val?
16556 *out_val = const_val;
16557 result->value.type = fixed_size_array_type;
16558 for (size_t i = 0; i < elem_count; i += 1) {
16559 ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];
16560 ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);
16561 if (parent != nullptr) {
16562 parent->id = ConstParentIdArray;
16563 parent->data.p_array.array_val = out_val;
16564 parent->data.p_array.elem_index = i;
16565 }
16826 if (const_val.special == ConstValSpecialStatic) {
16827 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
16828 ConstExprValue *out_val = &result->value;
16829 copy_const_val(out_val, &const_val, true);
16830 result->value.type = fixed_size_array_type;
16831 for (size_t i = 0; i < elem_count; i += 1) {
16832 ConstExprValue *elem_val = &out_val->data.x_array.data.s_none.elements[i];
16833 ConstParent *parent = get_const_val_parent(ira->codegen, elem_val);
16834 if (parent != nullptr) {
16835 parent->id = ConstParentIdArray;
16836 parent->data.p_array.array_val = out_val;
16837 parent->data.p_array.elem_index = i;
1656616838 }
16567 return result;
1656816839 }
16840 return result;
16841 }
1656916842
16570 if (is_comptime) {
16571 ir_add_error_node(ira, first_non_const_instruction->source_node,
16572 buf_sprintf("unable to evaluate constant expression"));
16573 return ira->codegen->invalid_instruction;
16574 }
16843 if (is_comptime) {
16844 ir_add_error_node(ira, first_non_const_instruction->source_node,
16845 buf_sprintf("unable to evaluate constant expression"));
16846 return ira->codegen->invalid_instruction;
16847 }
1657516848
16576 IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,
16577 instruction->base.scope, instruction->base.source_node,
16578 container_type_value, elem_count, new_items);
16579 new_instruction->value.type = fixed_size_array_type;
16580 ir_add_alloca(ira, new_instruction, fixed_size_array_type);
16581 return new_instruction;
16582 } else if (container_type->id == ZigTypeIdVoid) {
16583 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 {
16849 IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,
16850 instruction->base.scope, instruction->base.source_node,
16851 nullptr, elem_count, new_items);
16852 new_instruction->value.type = fixed_size_array_type;
16853 ir_add_alloca(ira, new_instruction, fixed_size_array_type);
16854 return new_instruction;
16855 } else if (container_type->id == ZigTypeIdVoid) {
16856 if (elem_count != 0) {
1659016857 ir_add_error_node(ira, instruction->base.source_node,
16591 buf_sprintf("type '%s' does not support array initialization",
16592 buf_ptr(&container_type->name)));
16858 buf_sprintf("void expression expects no arguments"));
1659316859 return ira->codegen->invalid_instruction;
1659416860 }
16861 return ir_const_void(ira, &instruction->base);
1659516862 } else {
16596 ir_add_error(ira, container_type_value,
16597 buf_sprintf("expected type, found '%s' value", buf_ptr(&container_type_value->value.type->name)));
16863 ir_add_error_node(ira, instruction->base.source_node,
16864 buf_sprintf("type '%s' does not support array initialization",
16865 buf_ptr(&container_type->name)));
1659816866 return ira->codegen->invalid_instruction;
1659916867 }
1660016868}
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{
1660316873 IrInstruction *container_type_value = instruction->container_type->child;
1660416874 ZigType *container_type = ir_resolve_type(ira, container_type_value);
1660516875 if (type_is_invalid(container_type))
......@@ -16659,7 +16929,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct
1665916929 if (type_is_invalid(value->value.type))
1666016930 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);
1666316933 if (type_is_invalid(casted_value->value.type))
1666416934 return ira->codegen->invalid_instruction;
1666516935
......@@ -16920,10 +17190,11 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig
1692017190
1692117191 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)))
1692417194 return ira->codegen->builtin_types.entry_invalid;
16925 assert(var->value->type->id == ZigTypeIdMetaType);
16926 return var->value->data.x_type;
17195
17196 assert(var->const_value->type->id == ZigTypeIdMetaType);
17197 return var->const_value->data.x_type;
1692717198}
1692817199
1692917200static 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
1697817249 definition_array->special = ConstValSpecialStatic;
1697917250 definition_array->type = get_array_type(ira->codegen, type_info_definition_type, definition_count);
1698017251 definition_array->data.x_array.special = ConstArraySpecialNone;
16981 definition_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1698217252 definition_array->data.x_array.data.s_none.elements = create_const_vals(definition_count);
1698317253 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
1700917279 inner_fields[1].data.x_bool = curr_entry->value->visib_mod == VisibModPub;
1701017280 inner_fields[2].special = ConstValSpecialStatic;
1701117281 inner_fields[2].type = type_info_definition_data_type;
17012 inner_fields[2].data.x_union.parent.id = ConstParentIdStruct;
17013 inner_fields[2].data.x_union.parent.data.p_struct.struct_val = definition_val;
17014 inner_fields[2].data.x_union.parent.data.p_struct.field_index = 1;
17282 inner_fields[2].parent.id = ConstParentIdStruct;
17283 inner_fields[2].parent.data.p_struct.struct_val = definition_val;
17284 inner_fields[2].parent.data.p_struct.field_index = 1;
1701517285
1701617286 switch (curr_entry->value->id) {
1701717287 case TldIdVar:
1701817288 {
1701917289 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)))
1702117291 return ErrorSemanticAnalyzeFail;
1702217292
17023 if (var->value->type->id == ZigTypeIdMetaType)
17024 {
17293 if (var->const_value->type->id == ZigTypeIdMetaType) {
1702517294 // We have a variable of type 'type', so it's actually a type definition.
1702617295 // 0: Data.Type: type
1702717296 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 0);
17028 inner_fields[2].data.x_union.payload = var->value;
17029 }
17030 else
17031 {
17297 inner_fields[2].data.x_union.payload = var->const_value;
17298 } else {
1703217299 // We have a variable of another type, so we store the type of the variable.
1703317300 // 1: Data.Var: type
1703417301 bigint_init_unsigned(&inner_fields[2].data.x_union.tag, 1);
1703517302
1703617303 ConstExprValue *payload = create_const_vals(1);
1703717304 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
1704017307 inner_fields[2].data.x_union.payload = payload;
1704117308 }
......@@ -17055,8 +17322,8 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
1705517322 ConstExprValue *fn_def_val = create_const_vals(1);
1705617323 fn_def_val->special = ConstValSpecialStatic;
1705717324 fn_def_val->type = type_info_fn_def_type;
17058 fn_def_val->data.x_struct.parent.id = ConstParentIdUnion;
17059 fn_def_val->data.x_struct.parent.data.p_union.union_val = &inner_fields[2];
17325 fn_def_val->parent.id = ConstParentIdUnion;
17326 fn_def_val->parent.data.p_union.union_val = &inner_fields[2];
1706017327
1706117328 ConstExprValue *fn_def_fields = create_const_vals(9);
1706217329 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
1712017387 fn_arg_name_array->type = get_array_type(ira->codegen,
1712117388 get_slice_type(ira->codegen, u8_ptr), fn_arg_count);
1712217389 fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;
17123 fn_arg_name_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1712417390 fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
1712517391
1712617392 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++)
17129 {
17394 for (size_t fn_arg_index = 0; fn_arg_index < fn_arg_count; fn_arg_index++) {
1713017395 ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index);
1713117396 ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index];
1713217397 ConstExprValue *arg_name = create_const_str_lit(ira->codegen, &arg_var->name);
1713317398 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;
17135 fn_arg_name_val->data.x_struct.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;
17399 fn_arg_name_val->parent.id = ConstParentIdArray;
17400 fn_arg_name_val->parent.data.p_array.array_val = fn_arg_name_array;
17401 fn_arg_name_val->parent.data.p_array.elem_index = fn_arg_index;
1713717402 }
1713817403
1713917404 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
1735417619
1735517620 break;
1735617621 }
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 }
1735717643 case ZigTypeIdOptional:
1735817644 {
1735917645 result = create_const_vals(1);
......@@ -17426,7 +17712,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1742617712 enum_field_array->special = ConstValSpecialStatic;
1742717713 enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count);
1742817714 enum_field_array->data.x_array.special = ConstArraySpecialNone;
17429 enum_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1743017715 enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count);
1743117716
1743217717 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
1743617721 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum_field_index];
1743717722 ConstExprValue *enum_field_val = &enum_field_array->data.x_array.data.s_none.elements[enum_field_index];
1743817723 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;
17440 enum_field_val->data.x_struct.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;
17724 enum_field_val->parent.id = ConstParentIdArray;
17725 enum_field_val->parent.data.p_array.array_val = enum_field_array;
17726 enum_field_val->parent.data.p_array.elem_index = enum_field_index;
1744217727 }
1744317728 // defs: []TypeInfo.Definition
1744417729 ensure_field_index(result->type, "defs", 3);
......@@ -17465,7 +17750,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1746517750 error_array->special = ConstValSpecialStatic;
1746617751 error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count);
1746717752 error_array->data.x_array.special = ConstArraySpecialNone;
17468 error_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1746917753 error_array->data.x_array.data.s_none.elements = create_const_vals(error_count);
1747017754
1747117755 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
1748917773 bigint_init_unsigned(&inner_fields[1].data.x_bigint, error->value);
1749017774
1749117775 error_val->data.x_struct.fields = inner_fields;
17492 error_val->data.x_struct.parent.id = ConstParentIdArray;
17493 error_val->data.x_struct.parent.data.p_array.array_val = error_array;
17494 error_val->data.x_struct.parent.data.p_array.elem_index = error_index;
17776 error_val->parent.id = ConstParentIdArray;
17777 error_val->parent.data.p_array.array_val = error_array;
17778 error_val->parent.data.p_array.elem_index = error_index;
1749517779 }
1749617780
1749717781 break;
......@@ -17560,7 +17844,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1756017844 union_field_array->special = ConstValSpecialStatic;
1756117845 union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count);
1756217846 union_field_array->data.x_array.special = ConstArraySpecialNone;
17563 union_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1756417847 union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count);
1756517848
1756617849 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
1759317876 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(union_field->name), true);
1759417877
1759517878 union_field_val->data.x_struct.fields = inner_fields;
17596 union_field_val->data.x_struct.parent.id = ConstParentIdArray;
17597 union_field_val->data.x_struct.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;
17879 union_field_val->parent.id = ConstParentIdArray;
17880 union_field_val->parent.data.p_array.array_val = union_field_array;
17881 union_field_val->parent.data.p_array.elem_index = union_field_index;
1759917882 }
1760017883 // defs: []TypeInfo.Definition
1760117884 ensure_field_index(result->type, "defs", 3);
......@@ -17635,7 +17918,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1763517918 struct_field_array->special = ConstValSpecialStatic;
1763617919 struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count);
1763717920 struct_field_array->data.x_array.special = ConstArraySpecialNone;
17638 struct_field_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1763917921 struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count);
1764017922
1764117923 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
1766917951 init_const_slice(ira->codegen, &inner_fields[0], name, 0, buf_len(struct_field->name), true);
1767017952
1767117953 struct_field_val->data.x_struct.fields = inner_fields;
17672 struct_field_val->data.x_struct.parent.id = ConstParentIdArray;
17673 struct_field_val->data.x_struct.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;
17954 struct_field_val->parent.id = ConstParentIdArray;
17955 struct_field_val->parent.data.p_array.array_val = struct_field_array;
17956 struct_field_val->parent.data.p_array.elem_index = struct_field_index;
1767517957 }
1767617958 // defs: []TypeInfo.Definition
1767717959 ensure_field_index(result->type, "defs", 2);
......@@ -17741,7 +18023,6 @@ static Error ir_make_type_info_value(IrAnalyze *ira, ZigType *type_entry, ConstE
1774118023 fn_arg_array->special = ConstValSpecialStatic;
1774218024 fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count);
1774318025 fn_arg_array->data.x_array.special = ConstArraySpecialNone;
17744 fn_arg_array->data.x_array.data.s_none.parent.id = ConstParentIdNone;
1774518026 fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
1774618027
1774718028 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
1777818059 }
1777918060
1778018061 fn_arg_val->data.x_struct.fields = inner_fields;
17781 fn_arg_val->data.x_struct.parent.id = ConstParentIdArray;
17782 fn_arg_val->data.x_struct.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;
18062 fn_arg_val->parent.id = ConstParentIdArray;
18063 fn_arg_val->parent.data.p_array.array_val = fn_arg_array;
18064 fn_arg_val->parent.data.p_array.elem_index = fn_arg_index;
1778418065 }
1778518066
1778618067 break;
......@@ -17824,8 +18105,8 @@ static IrInstruction *ir_analyze_instruction_type_info(IrAnalyze *ira,
1782418105
1782518106 if (payload != nullptr) {
1782618107 assert(payload->type->id == ZigTypeIdStruct);
17827 payload->data.x_struct.parent.id = ConstParentIdUnion;
17828 payload->data.x_struct.parent.data.p_union.union_val = out_val;
18108 payload->parent.id = ConstParentIdUnion;
18109 payload->parent.data.p_union.union_val = out_val;
1782918110 }
1783018111
1783118112 return result;
......@@ -17897,10 +18178,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
1789718178
1789818179 // Execute the C import block like an inline function
1789918180 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,
1790118182 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,
1790218183 &cimport_scope->buf, block_node, nullptr, nullptr);
17903 if (type_is_invalid(cimport_result->value.type))
18184 if (type_is_invalid(cimport_result->type))
1790418185 return ira->codegen->invalid_instruction;
1790518186
1790618187 find_libc_include_path(ira->codegen);
......@@ -18050,7 +18331,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru
1805018331 return result;
1805118332}
1805218333
18053static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchg *instruction) {
18334static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructionCmpxchgSrc *instruction) {
1805418335 ZigType *operand_type = ir_resolve_atomic_operand_type(ira, instruction->type_value->child);
1805518336 if (type_is_invalid(operand_type))
1805618337 return ira->codegen->invalid_instruction;
......@@ -18122,9 +18403,9 @@ static IrInstruction *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstructi
1812218403 zig_panic("TODO compile-time execution of cmpxchg");
1812318404 }
1812418405
18125 IrInstruction *result = ir_build_cmpxchg(&ira->new_irb, instruction->base.scope, instruction->base.source_node,
18126 nullptr, casted_ptr, casted_cmp_value, casted_new_value, nullptr, nullptr, instruction->is_weak,
18127 operand_type, success_order, failure_order);
18406 IrInstruction *result = ir_build_cmpxchg_gen(ira, &instruction->base,
18407 casted_ptr, casted_cmp_value, casted_new_value,
18408 success_order, failure_order, instruction->is_weak);
1812818409 result->value.type = get_optional_type(ira->codegen, operand_type);
1812918410 ir_add_alloca(ira, result, result->value.type);
1813018411 return result;
......@@ -18296,18 +18577,6 @@ static IrInstruction *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInst
1829618577 return ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type);
1829718578}
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
1831118580static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {
1831218581 Error err;
1831318582
......@@ -18426,6 +18695,20 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct
1842618695 return ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);
1842718696}
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
1842918712static IrInstruction *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) {
1843018713 ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
1843118714 if (type_is_invalid(dest_type))
......@@ -18532,6 +18815,27 @@ static IrInstruction *ir_analyze_instruction_int_type(IrAnalyze *ira, IrInstruct
1853218815 return ir_const_type(ira, &instruction->base, get_int_type(ira->codegen, is_signed, (uint32_t)bit_count));
1853318816}
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
1853518839static IrInstruction *ir_analyze_instruction_bool_not(IrAnalyze *ira, IrInstructionBoolNot *instruction) {
1853618840 IrInstruction *value = instruction->value->child;
1853718841 if (type_is_invalid(value->value.type))
......@@ -18630,10 +18934,18 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio
1863018934 }
1863118935 case ConstPtrSpecialBaseStruct:
1863218936 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");
1863318943 case ConstPtrSpecialHardCodedAddr:
1863418944 zig_unreachable();
1863518945 case ConstPtrSpecialFunction:
1863618946 zig_panic("TODO memset on ptr cast from function");
18947 case ConstPtrSpecialNull:
18948 zig_panic("TODO memset on null ptr");
1863718949 }
1863818950
1863918951 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
1874519057 }
1874619058 case ConstPtrSpecialBaseStruct:
1874719059 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");
1874819066 case ConstPtrSpecialHardCodedAddr:
1874919067 zig_unreachable();
1875019068 case ConstPtrSpecialFunction:
1875119069 zig_panic("TODO memcpy on ptr cast from function");
19070 case ConstPtrSpecialNull:
19071 zig_panic("TODO memcpy on null ptr");
1875219072 }
1875319073
1875419074 if (dest_start + count > dest_end) {
......@@ -18781,10 +19101,18 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
1878119101 }
1878219102 case ConstPtrSpecialBaseStruct:
1878319103 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");
1878419110 case ConstPtrSpecialHardCodedAddr:
1878519111 zig_unreachable();
1878619112 case ConstPtrSpecialFunction:
1878719113 zig_panic("TODO memcpy on ptr cast from function");
19114 case ConstPtrSpecialNull:
19115 zig_panic("TODO memcpy on null ptr");
1878819116 }
1878919117
1879019118 if (src_start + count > src_end) {
......@@ -18812,9 +19140,9 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1881219140 if (type_is_invalid(ptr_ptr->value.type))
1881319141 return ira->codegen->invalid_instruction;
1881419142
18815 ZigType *ptr_type = ptr_ptr->value.type;
18816 assert(ptr_type->id == ZigTypeIdPointer);
18817 ZigType *array_type = ptr_type->data.pointer.child_type;
19143 ZigType *ptr_ptr_type = ptr_ptr->value.type;
19144 assert(ptr_ptr_type->id == ZigTypeIdPointer);
19145 ZigType *array_type = ptr_ptr_type->data.pointer.child_type;
1881819146
1881919147 IrInstruction *start = instruction->start->child;
1882019148 if (type_is_invalid(start->value.type))
......@@ -18843,10 +19171,10 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1884319171 bool is_comptime_const = ptr_ptr->value.special == ConstValSpecialStatic &&
1884419172 ptr_ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst;
1884519173 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,
18847 ptr_type->data.pointer.is_volatile,
19174 ptr_ptr_type->data.pointer.is_const || is_comptime_const,
19175 ptr_ptr_type->data.pointer.is_volatile,
1884819176 PtrLenUnknown,
18849 ptr_type->data.pointer.explicit_alignment, 0, 0);
19177 ptr_ptr_type->data.pointer.explicit_alignment, 0, 0);
1885019178 return_type = get_slice_type(ira->codegen, slice_ptr_type);
1885119179 } else if (array_type->id == ZigTypeIdPointer) {
1885219180 if (array_type->data.pointer.ptr_len == PtrLenSingle) {
......@@ -18944,6 +19272,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1894419272 break;
1894519273 case ConstPtrSpecialBaseStruct:
1894619274 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");
1894719281 case ConstPtrSpecialHardCodedAddr:
1894819282 array_val = nullptr;
1894919283 abs_offset = 0;
......@@ -18951,6 +19285,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1895119285 break;
1895219286 case ConstPtrSpecialFunction:
1895319287 zig_panic("TODO slice of ptr cast from function");
19288 case ConstPtrSpecialNull:
19289 zig_panic("TODO slice of null ptr");
1895419290 }
1895519291 } else if (is_slice(array_type)) {
1895619292 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
1898119317 break;
1898219318 case ConstPtrSpecialBaseStruct:
1898319319 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");
1898419326 case ConstPtrSpecialHardCodedAddr:
1898519327 array_val = nullptr;
1898619328 abs_offset = 0;
......@@ -18988,6 +19330,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1898819330 break;
1898919331 case ConstPtrSpecialFunction:
1899019332 zig_panic("TODO slice of slice cast from function");
19333 case ConstPtrSpecialNull:
19334 zig_panic("TODO slice of null");
1899119335 }
1899219336 } else {
1899319337 zig_unreachable();
......@@ -19053,6 +19397,12 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1905319397 zig_unreachable();
1905419398 case ConstPtrSpecialBaseStruct:
1905519399 zig_panic("TODO");
19400 case ConstPtrSpecialBaseErrorUnionCode:
19401 zig_panic("TODO");
19402 case ConstPtrSpecialBaseErrorUnionPayload:
19403 zig_panic("TODO");
19404 case ConstPtrSpecialBaseOptionalPayload:
19405 zig_panic("TODO");
1905619406 case ConstPtrSpecialHardCodedAddr:
1905719407 init_const_ptr_hard_coded_addr(ira->codegen, ptr_val,
1905819408 parent_ptr->type->data.pointer.child_type,
......@@ -19061,6 +19411,8 @@ static IrInstruction *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstruction
1906119411 break;
1906219412 case ConstPtrSpecialFunction:
1906319413 zig_panic("TODO");
19414 case ConstPtrSpecialNull:
19415 zig_panic("TODO");
1906419416 }
1906519417
1906619418 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
1928719639 case ZigTypeIdEnum:
1928819640 case ZigTypeIdUnion:
1928919641 case ZigTypeIdFn:
19642 case ZigTypeIdVector:
1929019643 {
1929119644 uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry);
1929219645 return ir_const_unsigned(ira, &instruction->base, align_in_bytes);
......@@ -19416,7 +19769,8 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
1941619769 return ira->codegen->invalid_instruction;
1941719770
1941819771 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));
1942019774 }
1942119775 }
1942219776
......@@ -19442,48 +19796,47 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct
1944219796 }
1944319797}
1944419798
19445static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira,
19446 IrInstructionUnwrapErrCode *instruction)
19447{
19448 IrInstruction *value = instruction->value->child;
19449 if (type_is_invalid(value->value.type))
19799static IrInstruction *ir_analyze_instruction_unwrap_err_code(IrAnalyze *ira, IrInstructionUnwrapErrCode *instruction) {
19800 IrInstruction *base_ptr = instruction->err_union->child;
19801 if (type_is_invalid(base_ptr->value.type))
1945019802 return ira->codegen->invalid_instruction;
19451 ZigType *ptr_type = value->value.type;
19803 ZigType *ptr_type = base_ptr->value.type;
1945219804
1945319805 // This will be a pointer type because unwrap err payload IR instruction operates on a pointer to a thing.
1945419806 assert(ptr_type->id == ZigTypeIdPointer);
1945519807
1945619808 ZigType *type_entry = ptr_type->data.pointer.child_type;
19457 if (type_is_invalid(type_entry)) {
19809 if (type_is_invalid(type_entry))
1945819810 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,
19472 type_entry->data.error_union.err_set_type);
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,
19812 if (type_entry->id != ZigTypeIdErrorUnion) {
19813 ir_add_error(ira, base_ptr,
1948419814 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
1948519815 return ira->codegen->invalid_instruction;
1948619816 }
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;
1948719840}
1948819841
1948919842static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
......@@ -19499,48 +19852,48 @@ static IrInstruction *ir_analyze_instruction_unwrap_err_payload(IrAnalyze *ira,
1949919852 assert(ptr_type->id == ZigTypeIdPointer);
1950019853
1950119854 ZigType *type_entry = ptr_type->data.pointer.child_type;
19502 if (type_is_invalid(type_entry)) {
19855 if (type_is_invalid(type_entry))
1950319856 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);
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 {
19858 if (type_entry->id != ZigTypeIdErrorUnion) {
1953919859 ir_add_error(ira, value,
1954019860 buf_sprintf("expected error union type, found '%s'", buf_ptr(&type_entry->name)));
1954119861 return ira->codegen->invalid_instruction;
1954219862 }
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;
1954419897}
1954519898
1954619899static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstructionFnProto *instruction) {
......@@ -19957,7 +20310,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
1995720310 return ira->codegen->invalid_instruction;
1995820311 }
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);
1996120314 copy_const_val(&result->value, val, false);
1996220315 result->value.type = result_type;
1996320316 return result;
......@@ -20005,8 +20358,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
2000520358 if (!val)
2000620359 return ira->codegen->invalid_instruction;
2000720360
20008 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope, source_instr->source_node,
20009 dest_type);
20361 IrInstruction *result = ir_const(ira, source_instr, dest_type);
2001020362 copy_const_val(&result->value, val, false);
2001120363 result->value.type = dest_type;
2001220364 return result;
......@@ -20029,9 +20381,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
2002920381 return ira->codegen->invalid_instruction;
2003020382 }
2003120383
20032 IrInstruction *casted_ptr = ir_build_ptr_cast(&ira->new_irb, source_instr->scope,
20033 source_instr->source_node, nullptr, ptr);
20034 casted_ptr->value.type = dest_type;
20384 IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr);
2003520385
2003620386 if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
2003720387 ErrorMsg *msg = ir_add_error(ira, source_instr,
......@@ -20057,7 +20407,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
2005720407 return result;
2005820408}
2005920409
20060static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCast *instruction) {
20410static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCastSrc *instruction) {
2006120411 IrInstruction *dest_type_value = instruction->dest_type->child;
2006220412 ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
2006320413 if (type_is_invalid(dest_type))
......@@ -20071,6 +20421,17 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct
2007120421 return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value);
2007220422}
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
2007420435static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) {
2007520436 if (val->special == ConstValSpecialUndef)
2007620437 val->special = ConstValSpecialStatic;
......@@ -20116,17 +20477,9 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
2011620477 zig_unreachable();
2011720478 }
2011820479 case ZigTypeIdArray:
20119 {
20120 size_t buf_i = 0;
20121 // TODO optimize the buf case
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;
20480 return buf_write_value_bytes_array(codegen, buf, val, val->type->data.array.len);
20481 case ZigTypeIdVector:
20482 return buf_write_value_bytes_array(codegen, buf, val, val->type->data.vector.len);
2013020483 case ZigTypeIdStruct:
2013120484 zig_panic("TODO buf_write_value_bytes struct type");
2013220485 case ZigTypeIdOptional:
......@@ -20143,6 +20496,31 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
2014320496 zig_unreachable();
2014420497}
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
2014620524static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ConstExprValue *val) {
2014720525 Error err;
2014820526 assert(val->special == ConstValSpecialStatic);
......@@ -20181,29 +20559,27 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
2018120559 val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn);
2018220560 return ErrorNone;
2018320561 }
20184 case ZigTypeIdArray: {
20185 uint64_t elem_size = type_size(codegen, val->type->data.array.child_type);
20186 size_t len = val->type->data.array.len;
20187
20188 switch (val->data.x_array.special) {
20189 case ConstArraySpecialNone:
20190 val->data.x_array.data.s_none.elements = create_const_vals(len);
20191 for (size_t i = 0; i < len; i++) {
20192 ConstExprValue *elem = &val->data.x_array.data.s_none.elements[i];
20193 elem->special = ConstValSpecialStatic;
20194 elem->type = val->type->data.array.child_type;
20195 if ((err = buf_read_value_bytes(ira, codegen, source_node, buf + (elem_size * i), elem)))
20196 return err;
20197 }
20198 break;
20199 case ConstArraySpecialUndef:
20200 zig_panic("TODO buf_read_value_bytes ConstArraySpecialUndef array type");
20201 case ConstArraySpecialBuf:
20202 zig_panic("TODO buf_read_value_bytes ConstArraySpecialBuf array type");
20562 case ZigTypeIdArray:
20563 return buf_read_value_bytes_array(ira, codegen, source_node, buf, val, val->type->data.array.child_type,
20564 val->type->data.array.len);
20565 case ZigTypeIdVector:
20566 return buf_read_value_bytes_array(ira, codegen, source_node, buf, val, val->type->data.vector.elem_type,
20567 val->type->data.vector.len);
20568 case ZigTypeIdEnum:
20569 switch (val->type->data.enumeration.layout) {
20570 case ContainerLayoutAuto:
20571 zig_panic("TODO buf_read_value_bytes enum auto");
20572 case ContainerLayoutPacked:
20573 zig_panic("TODO buf_read_value_bytes enum packed");
20574 case ContainerLayoutExtern: {
20575 ZigType *tag_int_type = val->type->data.enumeration.tag_int_type;
20576 assert(tag_int_type->id == ZigTypeIdInt);
20577 bigint_read_twos_complement(&val->data.x_enum_tag, buf, tag_int_type->data.integral.bit_count,
20578 codegen->is_big_endian, tag_int_type->data.integral.is_signed);
20579 return ErrorNone;
20580 }
2020320581 }
20204
20205 return ErrorNone;
20206 }
20582 zig_unreachable();
2020720583 case ZigTypeIdStruct:
2020820584 switch (val->type->data.structure.layout) {
2020920585 case ContainerLayoutAuto: {
......@@ -20242,8 +20618,6 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
2024220618 zig_panic("TODO buf_read_value_bytes error union");
2024320619 case ZigTypeIdErrorSet:
2024420620 zig_panic("TODO buf_read_value_bytes pure error type");
20245 case ZigTypeIdEnum:
20246 zig_panic("TODO buf_read_value_bytes enum type");
2024720621 case ZigTypeIdFn:
2024820622 zig_panic("TODO buf_read_value_bytes fn type");
2024920623 case ZigTypeIdUnion:
......@@ -20264,10 +20638,10 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
2026420638 if (type_is_invalid(src_type))
2026520639 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)))
2026820642 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)))
2027120645 return ira->codegen->invalid_instruction;
2027220646
2027320647 if (get_codegen_ptr_type(src_type) != nullptr) {
......@@ -20330,6 +20704,16 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
2033020704 return ira->codegen->invalid_instruction;
2033120705 }
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
2033320717 if (instr_is_comptime(value)) {
2033420718 ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
2033520719 if (!val)
......@@ -20410,8 +20794,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
2041020794 case TldIdContainer:
2041120795 case TldIdCompTime:
2041220796 zig_unreachable();
20413 case TldIdVar:
20414 {
20797 case TldIdVar: {
2041520798 TldVar *tld_var = (TldVar *)tld;
2041620799 ZigVar *var = tld_var->var;
2041720800
......@@ -20429,8 +20812,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
2042920812 return ir_get_deref(ira, &instruction->base, var_ptr);
2043020813 }
2043120814 }
20432 case TldIdFn:
20433 {
20815 case TldIdFn: {
2043420816 TldFn *tld_fn = (TldFn *)tld;
2043520817 ZigFn *fn_entry = tld_fn->fn_entry;
2043620818 assert(fn_entry->type_entry);
......@@ -20476,8 +20858,7 @@ static IrInstruction *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstru
2047620858 if (!val)
2047720859 return ira->codegen->invalid_instruction;
2047820860 if (val->type->id == ZigTypeIdPointer && val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
20479 IrInstruction *result = ir_create_const(&ira->new_irb, instruction->base.scope,
20480 instruction->base.source_node, usize);
20861 IrInstruction *result = ir_const(ira, &instruction->base, usize);
2048120862 bigint_init_unsigned(&result->value.data.x_bigint, val->data.x_ptr.data.hard_coded_addr.addr);
2048220863 result->value.type = usize;
2048320864 return result;
......@@ -21315,6 +21696,11 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2131521696 case IrInstructionIdErrWrapCode:
2131621697 case IrInstructionIdErrWrapPayload:
2131721698 case IrInstructionIdCast:
21699 case IrInstructionIdDeclVarGen:
21700 case IrInstructionIdPtrCastGen:
21701 case IrInstructionIdCmpxchgGen:
21702 case IrInstructionIdArrayToVector:
21703 case IrInstructionIdVectorToArray:
2131821704 zig_unreachable();
2131921705
2132021706 case IrInstructionIdReturn:
......@@ -21325,8 +21711,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2132521711 return ir_analyze_instruction_un_op(ira, (IrInstructionUnOp *)instruction);
2132621712 case IrInstructionIdBinOp:
2132721713 return ir_analyze_instruction_bin_op(ira, (IrInstructionBinOp *)instruction);
21328 case IrInstructionIdDeclVar:
21329 return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVar *)instruction);
21714 case IrInstructionIdDeclVarSrc:
21715 return ir_analyze_instruction_decl_var(ira, (IrInstructionDeclVarSrc *)instruction);
2133021716 case IrInstructionIdLoadPtr:
2133121717 return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction);
2133221718 case IrInstructionIdStorePtr:
......@@ -21371,8 +21757,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2137121757 return ir_analyze_instruction_size_of(ira, (IrInstructionSizeOf *)instruction);
2137221758 case IrInstructionIdTestNonNull:
2137321759 return ir_analyze_instruction_test_non_null(ira, (IrInstructionTestNonNull *)instruction);
21374 case IrInstructionIdUnwrapOptional:
21375 return ir_analyze_instruction_unwrap_maybe(ira, (IrInstructionUnwrapOptional *)instruction);
21760 case IrInstructionIdOptionalUnwrapPtr:
21761 return ir_analyze_instruction_optional_unwrap_ptr(ira, (IrInstructionOptionalUnwrapPtr *)instruction);
2137621762 case IrInstructionIdClz:
2137721763 return ir_analyze_instruction_clz(ira, (IrInstructionClz *)instruction);
2137821764 case IrInstructionIdCtz:
......@@ -21413,8 +21799,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2141321799 return ir_analyze_instruction_c_undef(ira, (IrInstructionCUndef *)instruction);
2141421800 case IrInstructionIdEmbedFile:
2141521801 return ir_analyze_instruction_embed_file(ira, (IrInstructionEmbedFile *)instruction);
21416 case IrInstructionIdCmpxchg:
21417 return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchg *)instruction);
21802 case IrInstructionIdCmpxchgSrc:
21803 return ir_analyze_instruction_cmpxchg(ira, (IrInstructionCmpxchgSrc *)instruction);
2141821804 case IrInstructionIdFence:
2141921805 return ir_analyze_instruction_fence(ira, (IrInstructionFence *)instruction);
2142021806 case IrInstructionIdTruncate:
......@@ -21437,6 +21823,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2143721823 return ir_analyze_instruction_bool_to_int(ira, (IrInstructionBoolToInt *)instruction);
2143821824 case IrInstructionIdIntType:
2143921825 return ir_analyze_instruction_int_type(ira, (IrInstructionIntType *)instruction);
21826 case IrInstructionIdVectorType:
21827 return ir_analyze_instruction_vector_type(ira, (IrInstructionVectorType *)instruction);
2144021828 case IrInstructionIdBoolNot:
2144121829 return ir_analyze_instruction_bool_not(ira, (IrInstructionBoolNot *)instruction);
2144221830 case IrInstructionIdMemset:
......@@ -21481,8 +21869,8 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
2148121869 return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction);
2148221870 case IrInstructionIdPanic:
2148321871 return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);
21484 case IrInstructionIdPtrCast:
21485 return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCast *)instruction);
21872 case IrInstructionIdPtrCastSrc:
21873 return ir_analyze_instruction_ptr_cast(ira, (IrInstructionPtrCastSrc *)instruction);
2148621874 case IrInstructionIdBitCast:
2148721875 return ir_analyze_instruction_bit_cast(ira, (IrInstructionBitCast *)instruction);
2148821876 case IrInstructionIdIntToPtr:
......@@ -21666,7 +22054,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2166622054 case IrInstructionIdBr:
2166722055 case IrInstructionIdCondBr:
2166822056 case IrInstructionIdSwitchBr:
21669 case IrInstructionIdDeclVar:
22057 case IrInstructionIdDeclVarSrc:
22058 case IrInstructionIdDeclVarGen:
2167022059 case IrInstructionIdStorePtr:
2167122060 case IrInstructionIdCall:
2167222061 case IrInstructionIdReturn:
......@@ -21681,7 +22070,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2168122070 case IrInstructionIdCInclude:
2168222071 case IrInstructionIdCDefine:
2168322072 case IrInstructionIdCUndef:
21684 case IrInstructionIdCmpxchg:
2168522073 case IrInstructionIdFence:
2168622074 case IrInstructionIdMemset:
2168722075 case IrInstructionIdMemcpy:
......@@ -21709,6 +22097,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2170922097 case IrInstructionIdMergeErrRetTraces:
2171022098 case IrInstructionIdMarkErrRetTracePtr:
2171122099 case IrInstructionIdAtomicRmw:
22100 case IrInstructionIdCmpxchgGen:
22101 case IrInstructionIdCmpxchgSrc:
2171222102 return true;
2171322103
2171422104 case IrInstructionIdPhi:
......@@ -21734,7 +22124,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2173422124 case IrInstructionIdSliceType:
2173522125 case IrInstructionIdSizeOf:
2173622126 case IrInstructionIdTestNonNull:
21737 case IrInstructionIdUnwrapOptional:
22127 case IrInstructionIdOptionalUnwrapPtr:
2173822128 case IrInstructionIdClz:
2173922129 case IrInstructionIdCtz:
2174022130 case IrInstructionIdPopCount:
......@@ -21745,6 +22135,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2174522135 case IrInstructionIdEmbedFile:
2174622136 case IrInstructionIdTruncate:
2174722137 case IrInstructionIdIntType:
22138 case IrInstructionIdVectorType:
2174822139 case IrInstructionIdBoolNot:
2174922140 case IrInstructionIdSlice:
2175022141 case IrInstructionIdMemberCount:
......@@ -21761,7 +22152,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2176122152 case IrInstructionIdErrWrapPayload:
2176222153 case IrInstructionIdFnProto:
2176322154 case IrInstructionIdTestComptime:
21764 case IrInstructionIdPtrCast:
22155 case IrInstructionIdPtrCastSrc:
22156 case IrInstructionIdPtrCastGen:
2176522157 case IrInstructionIdBitCast:
2176622158 case IrInstructionIdWidenOrShorten:
2176722159 case IrInstructionIdPtrToInt:
......@@ -21804,6 +22196,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2180422196 case IrInstructionIdFromBytes:
2180522197 case IrInstructionIdToBytes:
2180622198 case IrInstructionIdEnumToInt:
22199 case IrInstructionIdVectorToArray:
22200 case IrInstructionIdArrayToVector:
2180722201 return false;
2180822202
2180922203 case IrInstructionIdAsm:
src/ir.hpp+1-1
......@@ -13,7 +13,7 @@
1313bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable);
1414bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
1515
16IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
16ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
1717 ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
1818 ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
1919 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
172172 }
173173}
174174
175static void ir_print_decl_var(IrPrint *irp, IrInstructionDeclVar *decl_var_instruction) {
175static void ir_print_decl_var_src(IrPrint *irp, IrInstructionDeclVarSrc *decl_var_instruction) {
176176 const char *var_or_const = decl_var_instruction->var->gen_is_const ? "const" : "var";
177177 const char *name = buf_ptr(&decl_var_instruction->var->name);
178178 if (decl_var_instruction->var_type) {
......@@ -332,8 +332,8 @@ static void ir_print_var_ptr(IrPrint *irp, IrInstructionVarPtr *instruction) {
332332}
333333
334334static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
335 fprintf(irp->f, "*");
336335 ir_print_other_instruction(irp, instruction->ptr);
336 fprintf(irp->f, ".*");
337337}
338338
339339static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {
......@@ -479,15 +479,15 @@ static void ir_print_size_of(IrPrint *irp, IrInstructionSizeOf *instruction) {
479479 fprintf(irp->f, ")");
480480}
481481
482static void ir_print_test_null(IrPrint *irp, IrInstructionTestNonNull *instruction) {
483 fprintf(irp->f, "*");
482static void ir_print_test_non_null(IrPrint *irp, IrInstructionTestNonNull *instruction) {
484483 ir_print_other_instruction(irp, instruction->value);
485484 fprintf(irp->f, " != null");
486485}
487486
488static void ir_print_unwrap_maybe(IrPrint *irp, IrInstructionUnwrapOptional *instruction) {
489 fprintf(irp->f, "&??*");
490 ir_print_other_instruction(irp, instruction->value);
487static void ir_print_optional_unwrap_ptr(IrPrint *irp, IrInstructionOptionalUnwrapPtr *instruction) {
488 fprintf(irp->f, "&");
489 ir_print_other_instruction(irp, instruction->base_ptr);
490 fprintf(irp->f, ".*.?");
491491 if (!instruction->safety_check_on) {
492492 fprintf(irp->f, " // no safety");
493493 }
......@@ -613,7 +613,7 @@ static void ir_print_embed_file(IrPrint *irp, IrInstructionEmbedFile *instructio
613613 fprintf(irp->f, ")");
614614}
615615
616static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {
616static void ir_print_cmpxchg_src(IrPrint *irp, IrInstructionCmpxchgSrc *instruction) {
617617 fprintf(irp->f, "@cmpxchg(");
618618 ir_print_other_instruction(irp, instruction->ptr);
619619 fprintf(irp->f, ", ");
......@@ -627,6 +627,16 @@ static void ir_print_cmpxchg(IrPrint *irp, IrInstructionCmpxchg *instruction) {
627627 fprintf(irp->f, ")");
628628}
629629
630static void ir_print_cmpxchg_gen(IrPrint *irp, IrInstructionCmpxchgGen *instruction) {
631 fprintf(irp->f, "@cmpxchg(");
632 ir_print_other_instruction(irp, instruction->ptr);
633 fprintf(irp->f, ", ");
634 ir_print_other_instruction(irp, instruction->cmp_value);
635 fprintf(irp->f, ", ");
636 ir_print_other_instruction(irp, instruction->new_value);
637 fprintf(irp->f, ", TODO print atomic orders)");
638}
639
630640static void ir_print_fence(IrPrint *irp, IrInstructionFence *instruction) {
631641 fprintf(irp->f, "@fence(");
632642 ir_print_other_instruction(irp, instruction->order_value);
......@@ -709,6 +719,14 @@ static void ir_print_int_type(IrPrint *irp, IrInstructionIntType *instruction) {
709719 fprintf(irp->f, ")");
710720}
711721
722static void ir_print_vector_type(IrPrint *irp, IrInstructionVectorType *instruction) {
723 fprintf(irp->f, "@Vector(");
724 ir_print_other_instruction(irp, instruction->len);
725 fprintf(irp->f, ", ");
726 ir_print_other_instruction(irp, instruction->elem_type);
727 fprintf(irp->f, ")");
728}
729
712730static void ir_print_bool_not(IrPrint *irp, IrInstructionBoolNot *instruction) {
713731 fprintf(irp->f, "! ");
714732 ir_print_other_instruction(irp, instruction->value);
......@@ -820,13 +838,13 @@ static void ir_print_test_err(IrPrint *irp, IrInstructionTestErr *instruction) {
820838}
821839
822840static void ir_print_unwrap_err_code(IrPrint *irp, IrInstructionUnwrapErrCode *instruction) {
823 fprintf(irp->f, "@unwrapErrorCode(");
824 ir_print_other_instruction(irp, instruction->value);
841 fprintf(irp->f, "UnwrapErrorCode(");
842 ir_print_other_instruction(irp, instruction->err_union);
825843 fprintf(irp->f, ")");
826844}
827845
828846static void ir_print_unwrap_err_payload(IrPrint *irp, IrInstructionUnwrapErrPayload *instruction) {
829 fprintf(irp->f, "@unwrapErrorPayload(");
847 fprintf(irp->f, "ErrorUnionFieldPayload(");
830848 ir_print_other_instruction(irp, instruction->value);
831849 fprintf(irp->f, ")");
832850 if (!instruction->safety_check_on) {
......@@ -879,7 +897,7 @@ static void ir_print_test_comptime(IrPrint *irp, IrInstructionTestComptime *inst
879897 fprintf(irp->f, ")");
880898}
881899
882static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {
900static void ir_print_ptr_cast_src(IrPrint *irp, IrInstructionPtrCastSrc *instruction) {
883901 fprintf(irp->f, "@ptrCast(");
884902 if (instruction->dest_type) {
885903 ir_print_other_instruction(irp, instruction->dest_type);
......@@ -889,6 +907,12 @@ static void ir_print_ptr_cast(IrPrint *irp, IrInstructionPtrCast *instruction) {
889907 fprintf(irp->f, ")");
890908}
891909
910static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruction) {
911 fprintf(irp->f, "@ptrCast(");
912 ir_print_other_instruction(irp, instruction->ptr);
913 fprintf(irp->f, ")");
914}
915
892916static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
893917 fprintf(irp->f, "@bitCast(");
894918 if (instruction->dest_type) {
......@@ -900,7 +924,7 @@ static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
900924}
901925
902926static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) {
903 fprintf(irp->f, "@widenOrShorten(");
927 fprintf(irp->f, "WidenOrShorten(");
904928 ir_print_other_instruction(irp, instruction->target);
905929 fprintf(irp->f, ")");
906930}
......@@ -948,6 +972,18 @@ static void ir_print_check_runtime_scope(IrPrint *irp, IrInstructionCheckRuntime
948972 fprintf(irp->f, ")");
949973}
950974
975static void ir_print_array_to_vector(IrPrint *irp, IrInstructionArrayToVector *instruction) {
976 fprintf(irp->f, "ArrayToVector(");
977 ir_print_other_instruction(irp, instruction->array);
978 fprintf(irp->f, ")");
979}
980
981static void ir_print_vector_to_array(IrPrint *irp, IrInstructionVectorToArray *instruction) {
982 fprintf(irp->f, "VectorToArray(");
983 ir_print_other_instruction(irp, instruction->vector);
984 fprintf(irp->f, ")");
985}
986
951987static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {
952988 fprintf(irp->f, "inttoerr ");
953989 ir_print_other_instruction(irp, instruction->target);
......@@ -1323,6 +1359,20 @@ static void ir_print_sqrt(IrPrint *irp, IrInstructionSqrt *instruction) {
13231359 fprintf(irp->f, ")");
13241360}
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
13261376static void ir_print_bswap(IrPrint *irp, IrInstructionBswap *instruction) {
13271377 fprintf(irp->f, "@bswap(");
13281378 if (instruction->type != nullptr) {
......@@ -1361,8 +1411,8 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
13611411 case IrInstructionIdBinOp:
13621412 ir_print_bin_op(irp, (IrInstructionBinOp *)instruction);
13631413 break;
1364 case IrInstructionIdDeclVar:
1365 ir_print_decl_var(irp, (IrInstructionDeclVar *)instruction);
1414 case IrInstructionIdDeclVarSrc:
1415 ir_print_decl_var_src(irp, (IrInstructionDeclVarSrc *)instruction);
13661416 break;
13671417 case IrInstructionIdCast:
13681418 ir_print_cast(irp, (IrInstructionCast *)instruction);
......@@ -1452,10 +1502,10 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
14521502 ir_print_size_of(irp, (IrInstructionSizeOf *)instruction);
14531503 break;
14541504 case IrInstructionIdTestNonNull:
1455 ir_print_test_null(irp, (IrInstructionTestNonNull *)instruction);
1505 ir_print_test_non_null(irp, (IrInstructionTestNonNull *)instruction);
14561506 break;
1457 case IrInstructionIdUnwrapOptional:
1458 ir_print_unwrap_maybe(irp, (IrInstructionUnwrapOptional *)instruction);
1507 case IrInstructionIdOptionalUnwrapPtr:
1508 ir_print_optional_unwrap_ptr(irp, (IrInstructionOptionalUnwrapPtr *)instruction);
14591509 break;
14601510 case IrInstructionIdCtz:
14611511 ir_print_ctz(irp, (IrInstructionCtz *)instruction);
......@@ -1508,8 +1558,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
15081558 case IrInstructionIdEmbedFile:
15091559 ir_print_embed_file(irp, (IrInstructionEmbedFile *)instruction);
15101560 break;
1511 case IrInstructionIdCmpxchg:
1512 ir_print_cmpxchg(irp, (IrInstructionCmpxchg *)instruction);
1561 case IrInstructionIdCmpxchgSrc:
1562 ir_print_cmpxchg_src(irp, (IrInstructionCmpxchgSrc *)instruction);
1563 break;
1564 case IrInstructionIdCmpxchgGen:
1565 ir_print_cmpxchg_gen(irp, (IrInstructionCmpxchgGen *)instruction);
15131566 break;
15141567 case IrInstructionIdFence:
15151568 ir_print_fence(irp, (IrInstructionFence *)instruction);
......@@ -1544,6 +1597,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
15441597 case IrInstructionIdIntType:
15451598 ir_print_int_type(irp, (IrInstructionIntType *)instruction);
15461599 break;
1600 case IrInstructionIdVectorType:
1601 ir_print_vector_type(irp, (IrInstructionVectorType *)instruction);
1602 break;
15471603 case IrInstructionIdBoolNot:
15481604 ir_print_bool_not(irp, (IrInstructionBoolNot *)instruction);
15491605 break;
......@@ -1607,8 +1663,11 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
16071663 case IrInstructionIdTestComptime:
16081664 ir_print_test_comptime(irp, (IrInstructionTestComptime *)instruction);
16091665 break;
1610 case IrInstructionIdPtrCast:
1611 ir_print_ptr_cast(irp, (IrInstructionPtrCast *)instruction);
1666 case IrInstructionIdPtrCastSrc:
1667 ir_print_ptr_cast_src(irp, (IrInstructionPtrCastSrc *)instruction);
1668 break;
1669 case IrInstructionIdPtrCastGen:
1670 ir_print_ptr_cast_gen(irp, (IrInstructionPtrCastGen *)instruction);
16121671 break;
16131672 case IrInstructionIdBitCast:
16141673 ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);
......@@ -1775,6 +1834,15 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
17751834 case IrInstructionIdCheckRuntimeScope:
17761835 ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction);
17771836 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;
17781846 }
17791847 fprintf(irp->f, "\n");
17801848}
src/main.cpp+6
......@@ -59,6 +59,7 @@ static int print_full_usage(const char *arg0) {
5959 " --release-fast build with optimizations on and safety off\n"
6060 " --release-safe build with optimizations on and safety on\n"
6161 " --release-small build with size optimizations on and safety off\n"
62 " --single-threaded source may assume it is only used single-threaded\n"
6263 " --static output will be statically linked\n"
6364 " --strip exclude debug symbols\n"
6465 " --target-arch [name] specify target architecture\n"
......@@ -393,6 +394,7 @@ int main(int argc, char **argv) {
393394 bool no_rosegment_workaround = false;
394395 bool system_linker_hack = false;
395396 TargetSubsystem subsystem = TargetSubsystemAuto;
397 bool is_single_threaded = false;
396398
397399 if (argc >= 2 && strcmp(argv[1], "build") == 0) {
398400 Buf zig_exe_path_buf = BUF_INIT;
......@@ -550,6 +552,8 @@ int main(int argc, char **argv) {
550552 disable_pic = true;
551553 } else if (strcmp(arg, "--system-linker-hack") == 0) {
552554 system_linker_hack = true;
555 } else if (strcmp(arg, "--single-threaded") == 0) {
556 is_single_threaded = true;
553557 } else if (strcmp(arg, "--test-cmd-bin") == 0) {
554558 test_exec_args.append(nullptr);
555559 } else if (arg[1] == 'L' && arg[2] != 0) {
......@@ -816,6 +820,7 @@ int main(int argc, char **argv) {
816820 switch (cmd) {
817821 case CmdBuiltin: {
818822 CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, get_zig_lib_dir());
823 g->is_single_threaded = is_single_threaded;
819824 Buf *builtin_source = codegen_generate_builtin_source(g);
820825 if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {
821826 fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));
......@@ -889,6 +894,7 @@ int main(int argc, char **argv) {
889894 codegen_set_out_name(g, buf_out_name);
890895 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
891896 codegen_set_is_test(g, cmd == CmdTest);
897 g->is_single_threaded = is_single_threaded;
892898 codegen_set_linker_script(g, linker_script);
893899 if (each_lib_rpath)
894900 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) {
18081808#endif
18091809}
18101810
1811Error os_file_open_r(Buf *full_path, OsFile *out_file) {
1811Error os_file_open_r(Buf *full_path, OsFile *out_file, OsTimeStamp *mtime) {
18121812#if defined(ZIG_OS_WINDOWS)
18131813 // TODO use CreateFileW
18141814 HANDLE result = CreateFileA(buf_ptr(full_path), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
......@@ -1834,8 +1834,18 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) {
18341834 return ErrorUnexpected;
18351835 }
18361836 }
1837
18381837 *out_file = result;
1838
1839 if (mtime != nullptr) {
1840 FILETIME last_write_time;
1841 if (!GetFileTime(result, nullptr, nullptr, &last_write_time)) {
1842 CloseHandle(result);
1843 return ErrorUnexpected;
1844 }
1845 mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime;
1846 mtime->nsec = 0;
1847 }
1848
18391849 return ErrorNone;
18401850#else
18411851 for (;;) {
......@@ -1858,7 +1868,26 @@ Error os_file_open_r(Buf *full_path, OsFile *out_file) {
18581868 return ErrorFileSystem;
18591869 }
18601870 }
1871 struct stat statbuf;
1872 if (fstat(fd, &statbuf) == -1) {
1873 close(fd);
1874 return ErrorFileSystem;
1875 }
1876 if (S_ISDIR(statbuf.st_mode)) {
1877 close(fd);
1878 return ErrorIsDir;
1879 }
18611880 *out_file = fd;
1881
1882 if (mtime != nullptr) {
1883#if defined(ZIG_OS_DARWIN)
1884 mtime->sec = statbuf.st_mtimespec.tv_sec;
1885 mtime->nsec = statbuf.st_mtimespec.tv_nsec;
1886#else
1887 mtime->sec = statbuf.st_mtim.tv_sec;
1888 mtime->nsec = statbuf.st_mtim.tv_nsec;
1889#endif
1890 }
18621891 return ErrorNone;
18631892 }
18641893#endif
......@@ -1948,35 +1977,6 @@ Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {
19481977#endif
19491978}
19501979
1951Error os_file_mtime(OsFile file, OsTimeStamp *mtime) {
1952#if defined(ZIG_OS_WINDOWS)
1953 FILETIME last_write_time;
1954 if (!GetFileTime(file, nullptr, nullptr, &last_write_time))
1955 return ErrorUnexpected;
1956 mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime;
1957 mtime->nsec = 0;
1958 return ErrorNone;
1959#elif defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD)
1960 struct stat statbuf;
1961 if (fstat(file, &statbuf) == -1)
1962 return ErrorFileSystem;
1963
1964 mtime->sec = statbuf.st_mtim.tv_sec;
1965 mtime->nsec = statbuf.st_mtim.tv_nsec;
1966 return ErrorNone;
1967#elif defined(ZIG_OS_DARWIN)
1968 struct stat statbuf;
1969 if (fstat(file, &statbuf) == -1)
1970 return ErrorFileSystem;
1971
1972 mtime->sec = statbuf.st_mtimespec.tv_sec;
1973 mtime->nsec = statbuf.st_mtimespec.tv_nsec;
1974 return ErrorNone;
1975#else
1976#error unimplemented
1977#endif
1978}
1979
19801980Error os_file_read(OsFile file, void *ptr, size_t *len) {
19811981#if defined(ZIG_OS_WINDOWS)
19821982 DWORD amt_read;
src/os.hpp+1-2
......@@ -101,9 +101,8 @@ bool os_path_is_absolute(Buf *path);
101101Error ATTRIBUTE_MUST_USE os_make_path(Buf *path);
102102Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path);
103103
104Error ATTRIBUTE_MUST_USE os_file_open_r(Buf *full_path, OsFile *out_file);
104Error ATTRIBUTE_MUST_USE os_file_open_r(Buf *full_path, OsFile *out_file, OsTimeStamp *mtime);
105105Error ATTRIBUTE_MUST_USE os_file_open_lock_rw(Buf *full_path, OsFile *out_file);
106Error ATTRIBUTE_MUST_USE os_file_mtime(OsFile file, OsTimeStamp *mtime);
107106Error ATTRIBUTE_MUST_USE os_file_read(OsFile file, void *ptr, size_t *len);
108107Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents);
109108Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents);
src/parser.cpp+4-4
......@@ -381,7 +381,7 @@ static AstNode *ast_parse_if_expr_helper(ParseContext *pc, AstNode *(*body_parse
381381 else_body = ast_expect(pc, body_parser);
382382 }
383383
384 assert(res->type == NodeTypeTestExpr);
384 assert(res->type == NodeTypeIfOptional);
385385 if (err_payload != nullptr) {
386386 AstNodeTestExpr old = res->data.test_expr;
387387 res->type = NodeTypeIfErrorExpr;
......@@ -990,7 +990,7 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) {
990990 if (requires_semi && else_body == nullptr)
991991 expect_token(pc, TokenIdSemicolon);
992992
993 assert(res->type == NodeTypeTestExpr);
993 assert(res->type == NodeTypeIfOptional);
994994 if (err_payload != nullptr) {
995995 AstNodeTestExpr old = res->data.test_expr;
996996 res->type = NodeTypeIfErrorExpr;
......@@ -2204,7 +2204,7 @@ static AstNode *ast_parse_if_prefix(ParseContext *pc) {
22042204 Optional<PtrPayload> opt_payload = ast_parse_ptr_payload(pc);
22052205
22062206 PtrPayload payload;
2207 AstNode *res = ast_create_node(pc, NodeTypeTestExpr, first);
2207 AstNode *res = ast_create_node(pc, NodeTypeIfOptional, first);
22082208 res->data.test_expr.target_node = condition;
22092209 if (opt_payload.unwrap(&payload)) {
22102210 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
29992999 visit_field(&node->data.if_err_expr.then_node, visit, context);
30003000 visit_field(&node->data.if_err_expr.else_node, visit, context);
30013001 break;
3002 case NodeTypeTestExpr:
3002 case NodeTypeIfOptional:
30033003 visit_field(&node->data.test_expr.target_node, visit, context);
30043004 visit_field(&node->data.test_expr.then_node, visit, context);
30053005 visit_field(&node->data.test_expr.else_node, visit, context);
src/tokenizer.cpp+5-7
......@@ -248,13 +248,8 @@ ATTRIBUTE_PRINTF(2, 3)
248248static void tokenize_error(Tokenize *t, const char *format, ...) {
249249 t->state = TokenizeStateError;
250250
251 if (t->cur_tok) {
252 t->out->err_line = t->cur_tok->start_line;
253 t->out->err_column = t->cur_tok->start_column;
254 } else {
255 t->out->err_line = t->line;
256 t->out->err_column = t->column;
257 }
251 t->out->err_line = t->line;
252 t->out->err_column = t->column;
258253
259254 va_list ap;
260255 va_start(ap, format);
......@@ -886,6 +881,9 @@ void tokenize(Buf *buf, Tokenization *out) {
886881 break;
887882 case TokenizeStateSawAmpersand:
888883 switch (c) {
884 case '&':
885 tokenize_error(&t, "`&&` is invalid. Note that `and` is boolean AND.");
886 break;
889887 case '=':
890888 set_token_id(&t, t.cur_tok, TokenIdBitAndEq);
891889 end_token(&t);
src/zig_llvm.cpp+13
......@@ -263,6 +263,19 @@ ZigLLVMDIType *ZigLLVMCreateDebugBasicType(ZigLLVMDIBuilder *dibuilder, const ch
263263 return reinterpret_cast<ZigLLVMDIType*>(di_type);
264264}
265265
266struct ZigLLVMDIType *ZigLLVMDIBuilderCreateVectorType(struct ZigLLVMDIBuilder *dibuilder,
267 uint64_t 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
266279ZigLLVMDIType *ZigLLVMCreateDebugArrayType(ZigLLVMDIBuilder *dibuilder, uint64_t size_in_bits,
267280 uint64_t align_in_bits, ZigLLVMDIType *elem_type, int elem_count)
268281{
src/zig_llvm.h+2
......@@ -191,6 +191,8 @@ ZIG_EXTERN_C struct ZigLLVMDISubprogram *ZigLLVMCreateFunction(struct ZigLLVMDIB
191191 unsigned lineno, struct ZigLLVMDIType *fn_di_type, bool is_local_to_unit, bool is_definition,
192192 unsigned scope_line, unsigned flags, bool is_optimized, struct ZigLLVMDISubprogram *decl_subprogram);
193193
194ZIG_EXTERN_C struct ZigLLVMDIType *ZigLLVMDIBuilderCreateVectorType(struct ZigLLVMDIBuilder *dibuilder,
195 uint64_t Size, uint32_t AlignInBits, struct ZigLLVMDIType *Ty);
194196
195197ZIG_EXTERN_C void ZigLLVMFnSetSubprogram(LLVMValueRef fn, struct ZigLLVMDISubprogram *subprogram);
196198
std/atomic/queue.zig+32-15
......@@ -170,20 +170,36 @@ test "std.atomic.Queue" {
170170 .get_count = 0,
171171 };
172172
173 var putters: [put_thread_count]*std.os.Thread = undefined;
174 for (putters) |*t| {
175 t.* = try std.os.spawnThread(&context, startPuts);
176 }
177 var getters: [put_thread_count]*std.os.Thread = undefined;
178 for (getters) |*t| {
179 t.* = try std.os.spawnThread(&context, startGets);
180 }
173 if (builtin.single_threaded) {
174 {
175 var i: usize = 0;
176 while (i < put_thread_count) : (i += 1) {
177 std.debug.assertOrPanic(startPuts(&context) == 0);
178 }
179 }
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|
183 t.wait();
184 _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
185 for (getters) |t|
186 t.wait();
197 for (putters) |t|
198 t.wait();
199 _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
200 for (getters) |t|
201 t.wait();
202 }
187203
188204 if (context.put_sum != context.get_sum) {
189205 std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum);
......@@ -205,11 +221,12 @@ fn startPuts(ctx: *Context) u8 {
205221 while (put_count != 0) : (put_count -= 1) {
206222 std.os.time.sleep(1); // let the os scheduler be our fuzz
207223 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{
209226 .prev = undefined,
210227 .next = undefined,
211228 .data = x,
212 }) catch unreachable;
229 };
213230 ctx.queue.put(node);
214231 _ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst);
215232 }
std/atomic/stack.zig+59-28
......@@ -4,10 +4,13 @@ const AtomicOrder = builtin.AtomicOrder;
44
55/// Many reader, many writer, non-allocating, thread-safe
66/// Uses a spinlock to protect push() and pop()
7/// When building in single threaded mode, this is a simple linked list.
78pub fn Stack(comptime T: type) type {
89 return struct {
910 root: ?*Node,
10 lock: u8,
11 lock: @typeOf(lock_init),
12
13 const lock_init = if (builtin.single_threaded) {} else u8(0);
1114
1215 pub const Self = @This();
1316
......@@ -19,7 +22,7 @@ pub fn Stack(comptime T: type) type {
1922 pub fn init() Self {
2023 return Self{
2124 .root = null,
22 .lock = 0,
25 .lock = lock_init,
2326 };
2427 }
2528
......@@ -31,20 +34,31 @@ pub fn Stack(comptime T: type) type {
3134 }
3235
3336 pub fn push(self: *Self, node: *Node) void {
34 while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
35 defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
36
37 node.next = self.root;
38 self.root = node;
37 if (builtin.single_threaded) {
38 node.next = self.root;
39 self.root = node;
40 } else {
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 }
3947 }
4048
4149 pub fn pop(self: *Self) ?*Node {
42 while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
43 defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
44
45 const root = self.root orelse return null;
46 self.root = root.next;
47 return root;
50 if (builtin.single_threaded) {
51 const root = self.root orelse return null;
52 self.root = root.next;
53 return root;
54 } else {
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 }
4862 }
4963
5064 pub fn isEmpty(self: *Self) bool {
......@@ -90,20 +104,36 @@ test "std.atomic.stack" {
90104 .get_count = 0,
91105 };
92106
93 var putters: [put_thread_count]*std.os.Thread = undefined;
94 for (putters) |*t| {
95 t.* = try std.os.spawnThread(&context, startPuts);
96 }
97 var getters: [put_thread_count]*std.os.Thread = undefined;
98 for (getters) |*t| {
99 t.* = try std.os.spawnThread(&context, startGets);
100 }
107 if (builtin.single_threaded) {
108 {
109 var i: usize = 0;
110 while (i < put_thread_count) : (i += 1) {
111 std.debug.assertOrPanic(startPuts(&context) == 0);
112 }
113 }
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|
103 t.wait();
104 _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
105 for (getters) |t|
106 t.wait();
131 for (putters) |t|
132 t.wait();
133 _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
134 for (getters) |t|
135 t.wait();
136 }
107137
108138 if (context.put_sum != context.get_sum) {
109139 std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum);
......@@ -125,10 +155,11 @@ fn startPuts(ctx: *Context) u8 {
125155 while (put_count != 0) : (put_count -= 1) {
126156 std.os.time.sleep(1); // let the os scheduler be our fuzz
127157 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{
129160 .next = undefined,
130161 .data = x,
131 }) catch unreachable;
162 };
132163 ctx.stack.push(node);
133164 _ = @atomicRmw(isize, &ctx.put_sum, builtin.AtomicRmwOp.Add, x, AtomicOrder.SeqCst);
134165 }
std/build.zig+39-23
......@@ -89,7 +89,7 @@ pub const Builder = struct {
8989 };
9090
9191 pub fn init(allocator: *Allocator, zig_exe: []const u8, build_root: []const u8, cache_root: []const u8) Builder {
92 const env_map = allocator.createOne(BufMap) catch unreachable;
92 const env_map = allocator.create(BufMap) catch unreachable;
9393 env_map.* = os.getEnvMap(allocator) catch unreachable;
9494 var self = Builder{
9595 .zig_exe = zig_exe,
......@@ -170,7 +170,8 @@ pub const Builder = struct {
170170 }
171171
172172 pub fn addTest(self: *Builder, root_src: []const u8) *TestStep {
173 const test_step = self.allocator.create(TestStep.init(self, root_src)) catch unreachable;
173 const test_step = self.allocator.create(TestStep) catch unreachable;
174 test_step.* = TestStep.init(self, root_src);
174175 return test_step;
175176 }
176177
......@@ -202,18 +203,21 @@ pub const Builder = struct {
202203 }
203204
204205 pub fn addWriteFile(self: *Builder, file_path: []const u8, data: []const u8) *WriteFileStep {
205 const write_file_step = self.allocator.create(WriteFileStep.init(self, file_path, data)) catch unreachable;
206 const write_file_step = self.allocator.create(WriteFileStep) catch unreachable;
207 write_file_step.* = WriteFileStep.init(self, file_path, data);
206208 return write_file_step;
207209 }
208210
209211 pub fn addLog(self: *Builder, comptime format: []const u8, args: ...) *LogStep {
210212 const data = self.fmt(format, args);
211 const log_step = self.allocator.create(LogStep.init(self, data)) catch unreachable;
213 const log_step = self.allocator.create(LogStep) catch unreachable;
214 log_step.* = LogStep.init(self, data);
212215 return log_step;
213216 }
214217
215218 pub fn addRemoveDirTree(self: *Builder, dir_path: []const u8) *RemoveDirStep {
216 const remove_dir_step = self.allocator.create(RemoveDirStep.init(self, dir_path)) catch unreachable;
219 const remove_dir_step = self.allocator.create(RemoveDirStep) catch unreachable;
220 remove_dir_step.* = RemoveDirStep.init(self, dir_path);
217221 return remove_dir_step;
218222 }
219223
......@@ -320,7 +324,7 @@ pub const Builder = struct {
320324
321325 fn processNixOSEnvVars(self: *Builder) void {
322326 if (os.getEnvVarOwned(self.allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {
323 var it = mem.split(nix_cflags_compile, " ");
327 var it = mem.tokenize(nix_cflags_compile, " ");
324328 while (true) {
325329 const word = it.next() orelse break;
326330 if (mem.eql(u8, word, "-isystem")) {
......@@ -338,7 +342,7 @@ pub const Builder = struct {
338342 assert(err == error.EnvironmentVariableNotFound);
339343 }
340344 if (os.getEnvVarOwned(self.allocator, "NIX_LDFLAGS")) |nix_ldflags| {
341 var it = mem.split(nix_ldflags, " ");
345 var it = mem.tokenize(nix_ldflags, " ");
342346 while (true) {
343347 const word = it.next() orelse break;
344348 if (mem.eql(u8, word, "-rpath")) {
......@@ -414,10 +418,11 @@ pub const Builder = struct {
414418 }
415419
416420 pub fn step(self: *Builder, name: []const u8, description: []const u8) *Step {
417 const step_info = self.allocator.create(TopLevelStep{
421 const step_info = self.allocator.create(TopLevelStep) catch unreachable;
422 step_info.* = TopLevelStep{
418423 .step = Step.initNoOp(name, self.allocator),
419424 .description = description,
420 }) catch unreachable;
425 };
421426 self.top_level_steps.append(step_info) catch unreachable;
422427 return &step_info.step;
423428 }
......@@ -616,7 +621,8 @@ pub const Builder = struct {
616621 const full_dest_path = os.path.resolve(self.allocator, self.prefix, dest_rel_path) catch unreachable;
617622 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);
620626 return install_step;
621627 }
622628
......@@ -683,7 +689,7 @@ pub const Builder = struct {
683689 if (os.path.isAbsolute(name)) {
684690 return name;
685691 }
686 var it = mem.split(PATH, []u8{os.path.delimiter});
692 var it = mem.tokenize(PATH, []u8{os.path.delimiter});
687693 while (it.next()) |path| {
688694 const full_path = try os.path.join(self.allocator, path, self.fmt("{}{}", name, exe_extension));
689695 if (os.path.real(self.allocator, full_path)) |real_path| {
......@@ -865,43 +871,51 @@ pub const LibExeObjStep = struct {
865871 };
866872
867873 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);
869876 return self;
870877 }
871878
872879 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);
874882 return self;
875883 }
876884
877885 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));
879888 return self;
880889 }
881890
882891 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);
884894 return self;
885895 }
886896
887897 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));
889900 return self;
890901 }
891902
892903 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);
894906 self.object_src = src;
895907 return self;
896908 }
897909
898910 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));
900913 return self;
901914 }
902915
903916 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);
905919 return self;
906920 }
907921
......@@ -1914,13 +1928,14 @@ pub const CommandStep = struct {
19141928
19151929 /// ::argv is copied.
19161930 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{
19181933 .builder = builder,
19191934 .step = Step.init(argv[0], builder.allocator, make),
19201935 .argv = builder.allocator.alloc([]u8, argv.len) catch unreachable,
19211936 .cwd = cwd,
19221937 .env_map = env_map,
1923 }) catch unreachable;
1938 };
19241939
19251940 mem.copy([]const u8, self.argv, argv);
19261941 self.step.name = self.argv[0];
......@@ -1949,12 +1964,13 @@ const InstallArtifactStep = struct {
19491964 LibExeObjStep.Kind.Exe => builder.exe_dir,
19501965 LibExeObjStep.Kind.Lib => builder.lib_dir,
19511966 };
1952 const self = builder.allocator.create(Self{
1967 const self = builder.allocator.create(Self) catch unreachable;
1968 self.* = Self{
19531969 .builder = builder,
19541970 .step = Step.init(builder.fmt("install {}", artifact.step.name), builder.allocator, make),
19551971 .artifact = artifact,
19561972 .dest_file = os.path.join(builder.allocator, dest_dir, artifact.out_filename) catch unreachable,
1957 }) catch unreachable;
1973 };
19581974 self.step.dependOn(&artifact.step);
19591975 builder.pushInstalledFile(self.dest_file);
19601976 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 {
7373};
7474
7575pub const timeval = extern struct {
76 tv_sec: isize,
77 tv_usec: isize,
76 tv_sec: c_long,
77 tv_usec: i32,
7878};
7979
8080pub const timezone = extern struct {
......@@ -176,6 +176,24 @@ pub const kevent64_s = extern struct {
176176 ext: [2]u64,
177177};
178178
179pub const mach_port_t = c_uint;
180pub const clock_serv_t = mach_port_t;
181pub const clock_res_t = c_int;
182pub const mach_port_name_t = natural_t;
183pub const natural_t = c_uint;
184pub const mach_timespec_t = extern struct {
185 tv_sec: c_uint,
186 tv_nsec: clock_res_t,
187};
188pub const kern_return_t = c_int;
189pub const host_t = mach_port_t;
190pub const CALENDAR_CLOCK = 1;
191
192pub extern fn mach_host_self() mach_port_t;
193pub extern fn clock_get_time(clock_serv: clock_serv_t, cur_time: *mach_timespec_t) kern_return_t;
194pub extern fn host_get_clock_service(host: host_t, clock_id: clock_id_t, clock_serv: ?[*]clock_serv_t) kern_return_t;
195pub extern fn mach_port_deallocate(task: ipc_space_t, name: mach_port_name_t) kern_return_t;
196
179197// sys/types.h on macos uses #pragma pack() so these checks are
180198// to make sure the struct is laid out the same. These values were
181199// produced from C code using the offsetof macro.
std/c/index.zig+1-1
......@@ -44,7 +44,7 @@ pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) c_int;
4444pub extern "c" fn readlink(noalias path: [*]const u8, noalias buf: [*]u8, bufsize: usize) isize;
4545pub extern "c" fn realpath(noalias file_name: [*]const u8, noalias resolved_name: [*]u8) ?[*]u8;
4646pub extern "c" fn sigprocmask(how: c_int, noalias set: *const sigset_t, noalias oset: ?*sigset_t) c_int;
47pub extern "c" fn gettimeofday(tv: ?*timeval, tz: ?*timezone) c_int;
47pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int;
4848pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int;
4949pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int;
5050pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int;
std/debug/index.zig+4-3
......@@ -751,7 +751,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
751751 const self_file = try os.openSelfExe();
752752 defer self_file.close();
753753
754 const coff_obj = try allocator.createOne(coff.Coff);
754 const coff_obj = try allocator.create(coff.Coff);
755755 coff_obj.* = coff.Coff{
756756 .in_file = self_file,
757757 .allocator = allocator,
......@@ -1036,7 +1036,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
10361036 }
10371037 }
10381038 }
1039 const sentinel = try allocator.createOne(macho.nlist_64);
1039 const sentinel = try allocator.create(macho.nlist_64);
10401040 sentinel.* = macho.nlist_64{
10411041 .n_strx = 0,
10421042 .n_type = 36,
......@@ -1949,7 +1949,8 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void {
19491949
19501950 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
19541955 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 {
5454 const buffer_nodes = try loop.allocator.alloc(T, capacity);
5555 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{
5859 .loop = loop,
5960 .buffer_len = 0,
6061 .buffer_nodes = buffer_nodes,
......@@ -66,7 +67,7 @@ pub fn Channel(comptime T: type) type {
6667 .or_null_queue = std.atomic.Queue(*std.atomic.Queue(GetNode).Node).init(),
6768 .get_count = 0,
6869 .put_count = 0,
69 });
70 };
7071 errdefer loop.allocator.destroy(self);
7172
7273 return self;
......@@ -319,6 +320,9 @@ pub fn Channel(comptime T: type) type {
319320}
320321
321322test "std.event.Channel" {
323 // https://github.com/ziglang/zig/issues/1908
324 if (builtin.single_threaded) return error.SkipZigTest;
325
322326 var da = std.heap.DirectAllocator.init();
323327 defer da.deinit();
324328
std/event/fs.zig+27-30
......@@ -495,7 +495,7 @@ pub const CloseOperation = struct {
495495 };
496496
497497 pub fn start(loop: *Loop) (error{OutOfMemory}!*CloseOperation) {
498 const self = try loop.allocator.createOne(CloseOperation);
498 const self = try loop.allocator.create(CloseOperation);
499499 self.* = CloseOperation{
500500 .loop = loop,
501501 .os_data = switch (builtin.os) {
......@@ -787,7 +787,7 @@ pub fn Watch(comptime V: type) type {
787787 },
788788
789789 builtin.Os.windows => {
790 const self = try loop.allocator.createOne(Self);
790 const self = try loop.allocator.create(Self);
791791 errdefer loop.allocator.destroy(self);
792792 self.* = Self{
793793 .channel = channel,
......@@ -802,7 +802,7 @@ pub fn Watch(comptime V: type) type {
802802 },
803803
804804 builtin.Os.macosx, builtin.Os.freebsd => {
805 const self = try loop.allocator.createOne(Self);
805 const self = try loop.allocator.create(Self);
806806 errdefer loop.allocator.destroy(self);
807807
808808 self.* = Self{
......@@ -1068,7 +1068,7 @@ pub fn Watch(comptime V: type) type {
10681068 }
10691069 } else {
10701070 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);
10721072 errdefer self.channel.loop.allocator.destroy(dir);
10731073
10741074 dir.* = OsData.Dir{
......@@ -1307,32 +1307,29 @@ pub fn Watch(comptime V: type) type {
13071307
13081308const test_tmp_dir = "std_event_fs_test";
13091309
1310test "write a file, watch it, write it again" {
1311 if (builtin.os == builtin.Os.windows) {
1312 // TODO this test is disabled on windows until the coroutine rewrite is finished.
1313 // https://github.com/ziglang/zig/issues/1363
1314 return error.SkipZigTest;
1315 }
1316 var da = std.heap.DirectAllocator.init();
1317 defer da.deinit();
1318
1319 const allocator = &da.allocator;
1320
1321 // TODO move this into event loop too
1322 try os.makePath(allocator, test_tmp_dir);
1323 defer os.deleteTree(allocator, test_tmp_dir) catch {};
1324
1325 var loop: Loop = undefined;
1326 try loop.initMultiThreaded(allocator);
1327 defer loop.deinit();
1328
1329 var result: anyerror!void = error.ResultNeverWritten;
1330 const handle = try async<allocator> testFsWatchCantFail(&loop, &result);
1331 defer cancel handle;
1332
1333 loop.run();
1334 return result;
1335}
1310// TODO this test is disabled until the coroutine rewrite is finished.
1311//test "write a file, watch it, write it again" {
1312// return error.SkipZigTest;
1313// var da = std.heap.DirectAllocator.init();
1314// defer da.deinit();
1315//
1316// const allocator = &da.allocator;
1317//
1318// // TODO move this into event loop too
1319// try os.makePath(allocator, test_tmp_dir);
1320// defer os.deleteTree(allocator, test_tmp_dir) catch {};
1321//
1322// var loop: Loop = undefined;
1323// try loop.initMultiThreaded(allocator);
1324// defer loop.deinit();
1325//
1326// var result: anyerror!void = error.ResultNeverWritten;
1327// const handle = try async<allocator> testFsWatchCantFail(&loop, &result);
1328// defer cancel handle;
1329//
1330// loop.run();
1331// return result;
1332//}
13361333
13371334async fn testFsWatchCantFail(loop: *Loop, result: *(anyerror!void)) void {
13381335 result.* = await (async testFsWatch(loop) catch unreachable);
std/event/future.zig+3
......@@ -84,6 +84,9 @@ pub fn Future(comptime T: type) type {
8484}
8585
8686test "std.event.Future" {
87 // https://github.com/ziglang/zig/issues/1908
88 if (builtin.single_threaded) return error.SkipZigTest;
89
8790 var da = std.heap.DirectAllocator.init();
8891 defer da.deinit();
8992
std/event/group.zig+6-2
......@@ -42,10 +42,11 @@ pub fn Group(comptime ReturnType: type) type {
4242
4343 /// Add a promise to the group. Thread-safe.
4444 pub fn add(self: *Self, handle: promise->ReturnType) (error{OutOfMemory}!void) {
45 const node = try self.lock.loop.allocator.create(Stack.Node{
45 const node = try self.lock.loop.allocator.create(Stack.Node);
46 node.* = Stack.Node{
4647 .next = undefined,
4748 .data = handle,
48 });
49 };
4950 self.alloc_stack.push(node);
5051 }
5152
......@@ -121,6 +122,9 @@ pub fn Group(comptime ReturnType: type) type {
121122}
122123
123124test "std.event.Group" {
125 // https://github.com/ziglang/zig/issues/1908
126 if (builtin.single_threaded) return error.SkipZigTest;
127
124128 var da = std.heap.DirectAllocator.init();
125129 defer da.deinit();
126130
std/event/lock.zig+3
......@@ -122,6 +122,9 @@ pub const Lock = struct {
122122};
123123
124124test "std.event.Lock" {
125 // https://github.com/ziglang/zig/issues/1908
126 if (builtin.single_threaded) return error.SkipZigTest;
127
125128 var da = std.heap.DirectAllocator.init();
126129 defer da.deinit();
127130
std/event/loop.zig+22
......@@ -97,6 +97,7 @@ pub const Loop = struct {
9797 /// TODO copy elision / named return values so that the threads referencing *Loop
9898 /// have the correct pointer value.
9999 pub fn initMultiThreaded(self: *Loop, allocator: *mem.Allocator) !void {
100 if (builtin.single_threaded) @compileError("initMultiThreaded unavailable when building in single-threaded mode");
100101 const core_count = try os.cpuCount(allocator);
101102 return self.initInternal(allocator, core_count);
102103 }
......@@ -201,6 +202,11 @@ pub const Loop = struct {
201202 self.os_data.fs_thread.wait();
202203 }
203204
205 if (builtin.single_threaded) {
206 assert(extra_thread_count == 0);
207 return;
208 }
209
204210 var extra_thread_index: usize = 0;
205211 errdefer {
206212 // writing 8 bytes to an eventfd cannot fail
......@@ -301,6 +307,11 @@ pub const Loop = struct {
301307 self.os_data.fs_thread.wait();
302308 }
303309
310 if (builtin.single_threaded) {
311 assert(extra_thread_count == 0);
312 return;
313 }
314
304315 var extra_thread_index: usize = 0;
305316 errdefer {
306317 _ = os.bsdKEvent(self.os_data.kqfd, final_kev_arr, empty_kevs, null) catch unreachable;
......@@ -338,6 +349,11 @@ pub const Loop = struct {
338349 self.available_eventfd_resume_nodes.push(eventfd_node);
339350 }
340351
352 if (builtin.single_threaded) {
353 assert(extra_thread_count == 0);
354 return;
355 }
356
341357 var extra_thread_index: usize = 0;
342358 errdefer {
343359 var i: usize = 0;
......@@ -845,6 +861,9 @@ pub const Loop = struct {
845861};
846862
847863test "std.event.Loop - basic" {
864 // https://github.com/ziglang/zig/issues/1908
865 if (builtin.single_threaded) return error.SkipZigTest;
866
848867 var da = std.heap.DirectAllocator.init();
849868 defer da.deinit();
850869
......@@ -858,6 +877,9 @@ test "std.event.Loop - basic" {
858877}
859878
860879test "std.event.Loop - call" {
880 // https://github.com/ziglang/zig/issues/1908
881 if (builtin.single_threaded) return error.SkipZigTest;
882
861883 var da = std.heap.DirectAllocator.init();
862884 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 {
269269}
270270
271271test "listen on a port, send bytes, receive bytes" {
272 // https://github.com/ziglang/zig/issues/1908
273 if (builtin.single_threaded) return error.SkipZigTest;
274
272275 if (builtin.os != builtin.Os.linux) {
273276 // TODO build abstractions for other operating systems
274277 return error.SkipZigTest;
std/event/rwlock.zig+3
......@@ -211,6 +211,9 @@ pub const RwLock = struct {
211211};
212212
213213test "std.event.RwLock" {
214 // https://github.com/ziglang/zig/issues/1908
215 if (builtin.single_threaded) return error.SkipZigTest;
216
214217 var da = std.heap.DirectAllocator.init();
215218 defer da.deinit();
216219
std/fmt/index.zig-2
......@@ -982,13 +982,11 @@ test "fmt.format" {
982982 context = BufPrintContext{ .remaining = buf1[0..] };
983983 try formatType('a', "c", &context, error{BufferTooSmall}, bufPrintWrite);
984984 res = buf1[0 .. buf1.len - context.remaining.len];
985 debug.warn("{}\n", res);
986985 assert(mem.eql(u8, res, "a"));
987986
988987 context = BufPrintContext{ .remaining = buf1[0..] };
989988 try formatType(0b1100, "b", &context, error{BufferTooSmall}, bufPrintWrite);
990989 res = buf1[0 .. buf1.len - context.remaining.len];
991 debug.warn("{}\n", res);
992990 assert(mem.eql(u8, res, "1100"));
993991 }
994992 {
std/hash_map.zig+2
......@@ -508,6 +508,7 @@ pub fn autoHash(key: var, comptime rng: *std.rand.Random, comptime HashInt: type
508508
509509 builtin.TypeId.Optional => @compileError("TODO auto hash for optionals"),
510510 builtin.TypeId.Array => @compileError("TODO auto hash for arrays"),
511 builtin.TypeId.Vector => @compileError("TODO auto hash for vectors"),
511512 builtin.TypeId.Struct => @compileError("TODO auto hash for structs"),
512513 builtin.TypeId.Union => @compileError("TODO auto hash for unions"),
513514 builtin.TypeId.ErrorUnion => @compileError("TODO auto hash for unions"),
......@@ -555,5 +556,6 @@ pub fn autoEql(a: var, b: @typeOf(a)) bool {
555556 builtin.TypeId.Struct => @compileError("TODO auto eql for structs"),
556557 builtin.TypeId.Union => @compileError("TODO auto eql for unions"),
557558 builtin.TypeId.ErrorUnion => @compileError("TODO auto eql for unions"),
559 builtin.TypeId.Vector => @compileError("TODO auto eql for vectors"),
558560 }
559561}
std/heap.zig+2-1
......@@ -518,7 +518,8 @@ fn testAllocator(allocator: *mem.Allocator) !void {
518518 var slice = try allocator.alloc(*i32, 100);
519519 assert(slice.len == 100);
520520 for (slice) |*item, i| {
521 item.* = try allocator.create(@intCast(i32, i));
521 item.* = try allocator.create(i32);
522 item.*.* = @intCast(i32, i);
522523 }
523524
524525 slice = try allocator.realloc(*i32, slice, 20000);
std/index.zig+2
......@@ -9,6 +9,7 @@ pub const DynLib = @import("dynamic_library.zig").DynLib;
99pub const HashMap = @import("hash_map.zig").HashMap;
1010pub const LinkedList = @import("linked_list.zig").LinkedList;
1111pub const Mutex = @import("mutex.zig").Mutex;
12pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex;
1213pub const SegmentedList = @import("segmented_list.zig").SegmentedList;
1314pub const SpinLock = @import("spinlock.zig").SpinLock;
1415
......@@ -55,6 +56,7 @@ test "std" {
5556 _ = @import("hash_map.zig");
5657 _ = @import("linked_list.zig");
5758 _ = @import("mutex.zig");
59 _ = @import("statically_initialized_mutex.zig");
5860 _ = @import("segmented_list.zig");
5961 _ = @import("spinlock.zig");
6062
std/io.zig+654-13
......@@ -8,6 +8,8 @@ const debug = std.debug;
88const assert = debug.assert;
99const os = std.os;
1010const mem = std.mem;
11const meta = std.meta;
12const trait = meta.trait;
1113const Buffer = std.Buffer;
1214const fmt = std.fmt;
1315const File = std.os.File;
......@@ -463,6 +465,153 @@ pub const SliceInStream = struct {
463465 }
464466};
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
466615/// This is a simple OutStream that writes to a slice, and returns an error
467616/// when it runs out of space.
468617pub const SliceOutStream = struct {
......@@ -515,7 +664,7 @@ test "io.SliceOutStream" {
515664 const stream = &slice_stream.stream;
516665
517666 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()));
519668}
520669
521670var null_out_stream_state = NullOutStream.init();
......@@ -577,7 +726,7 @@ test "io.CountingOutStream" {
577726
578727 const bytes = "yay" ** 10000;
579728 stream.write(bytes) catch unreachable;
580 debug.assert(counting_stream.bytes_written == bytes.len);
729 debug.assertOrPanic(counting_stream.bytes_written == bytes.len);
581730}
582731
583732pub fn BufferedOutStream(comptime Error: type) type {
......@@ -656,6 +805,137 @@ pub const BufferOutStream = struct {
656805 }
657806};
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
659939pub const BufferedAtomicFile = struct {
660940 atomic_file: os.AtomicFile,
661941 file_stream: os.File.OutStream,
......@@ -664,12 +944,13 @@ pub const BufferedAtomicFile = struct {
664944
665945 pub fn create(allocator: *mem.Allocator, dest_path: []const u8) !*BufferedAtomicFile {
666946 // 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{
668949 .atomic_file = undefined,
669950 .file_stream = undefined,
670951 .buffered_stream = undefined,
671952 .allocator = allocator,
672 });
953 };
673954 errdefer allocator.destroy(self);
674955
675956 self.atomic_file = try os.AtomicFile.init(dest_path, os.File.default_mode);
......@@ -696,11 +977,6 @@ pub const BufferedAtomicFile = struct {
696977 }
697978};
698979
699test "import io tests" {
700 comptime {
701 _ = @import("io_test.zig");
702 }
703}
704980
705981pub fn readLine(buf: *std.Buffer) ![]u8 {
706982 var stdin = try getStdIn();
......@@ -738,10 +1014,10 @@ test "io.readLineFrom" {
7381014 );
7391015 const stream = &mem_stream.stream;
7401016
741 debug.assert(mem.eql(u8, "Line 1", try readLineFrom(stream, &buf)));
742 debug.assert(mem.eql(u8, "Line 22", try readLineFrom(stream, &buf)));
1017 debug.assertOrPanic(mem.eql(u8, "Line 1", try readLineFrom(stream, &buf)));
1018 debug.assertOrPanic(mem.eql(u8, "Line 22", try readLineFrom(stream, &buf)));
7431019 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"));
7451021}
7461022
7471023pub fn readLineSlice(slice: []u8) ![]u8 {
......@@ -769,6 +1045,371 @@ test "io.readLineSliceFrom" {
7691045 );
7701046 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..])));
7731049 debug.assertError(readLineSliceFrom(stream, buf[0..]), error.OutOfMemory);
7741050}
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 @@
11const std = @import("index.zig");
22const io = std.io;
3const meta = std.meta;
4const trait = std.trait;
35const DefaultPrng = std.rand.DefaultPrng;
46const assert = std.debug.assert;
57const assertError = std.debug.assertError;
......@@ -132,3 +134,438 @@ test "SliceOutStream" {
132134 assertError(ss.stream.write("Hello world!"), error.OutOfSpace);
133135 assert(mem.eql(u8, ss.getWritten(), "Hello worl"));
134136}
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 {
190190 /// Returns:
191191 /// A pointer to the new node.
192192 pub fn allocateNode(list: *Self, allocator: *Allocator) !*Node {
193 return allocator.create(Node(undefined));
193 return allocator.create(Node);
194194 }
195195
196196 /// Deallocate a node.
std/mem.zig+132-25
......@@ -36,20 +36,9 @@ pub const Allocator = struct {
3636 /// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn`
3737 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
5039 /// Call `destroy` with the result.
5140 /// 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 {
5342 if (@sizeOf(T) == 0) return &(T{});
5443 const slice = try self.alloc(T, 1);
5544 return &slice[0];
......@@ -700,23 +689,114 @@ pub fn eql_slice_u8(a: []const u8, b: []const u8) bool {
700689}
701690
702691/// Returns an iterator that iterates over the slices of `buffer` that are not
703/// any of the bytes in `split_bytes`.
704/// split(" abc def ghi ", " ")
692/// any of the bytes in `delimiter_bytes`.
693/// tokenize(" abc def ghi ", " ")
705694/// 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);
707763 return SplitIterator{
708764 .index = 0,
709765 .buffer = buffer,
710 .split_bytes = split_bytes,
766 .delimiter = delimiter,
711767 };
712768}
713769
714test "mem.split" {
715 var it = split(" abc def ghi ", " ");
770test "mem.separate" {
771 var it = separate("abc|def||ghi", "|");
716772 assert(eql(u8, it.next().?, "abc"));
717773 assert(eql(u8, it.next().?, "def"));
774 assert(eql(u8, it.next().?, ""));
718775 assert(eql(u8, it.next().?, "ghi"));
719776 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);
720800}
721801
722802pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool {
......@@ -737,12 +817,13 @@ test "mem.endsWith" {
737817 assert(!endsWith(u8, "Bob", "Bo"));
738818}
739819
740pub const SplitIterator = struct {
820pub const TokenIterator = struct {
741821 buffer: []const u8,
742 split_bytes: []const u8,
822 delimiter_bytes: []const u8,
743823 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 {
746827 // move to beginning of token
747828 while (self.index < self.buffer.len and self.isSplitByte(self.buffer[self.index])) : (self.index += 1) {}
748829 const start = self.index;
......@@ -758,16 +839,16 @@ pub const SplitIterator = struct {
758839 }
759840
760841 /// 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 {
762843 // move to beginning of token
763844 var index: usize = self.index;
764845 while (index < self.buffer.len and self.isSplitByte(self.buffer[index])) : (index += 1) {}
765846 return self.buffer[index..];
766847 }
767848
768 fn isSplitByte(self: *const SplitIterator, byte: u8) bool {
769 for (self.split_bytes) |split_byte| {
770 if (byte == split_byte) {
849 fn isSplitByte(self: TokenIterator, byte: u8) bool {
850 for (self.delimiter_bytes) |delimiter_byte| {
851 if (byte == delimiter_byte) {
771852 return true;
772853 }
773854 }
......@@ -775,6 +856,32 @@ pub const SplitIterator = struct {
775856 }
776857};
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
778885/// Naively combines a series of strings with a separator.
779886/// Allocates memory for the result, which must be freed by the caller.
780887pub fn join(allocator: *Allocator, sep: u8, strings: ...) ![]u8 {
std/meta/index.zig+35-3
......@@ -95,7 +95,7 @@ test "std.meta.stringToEnum" {
9595 debug.assert(null == stringToEnum(E1, "C"));
9696}
9797
98pub fn bitCount(comptime T: type) u32 {
98pub fn bitCount(comptime T: type) comptime_int {
9999 return switch (@typeInfo(T)) {
100100 TypeId.Int => |info| info.bits,
101101 TypeId.Float => |info| info.bits,
......@@ -108,7 +108,7 @@ test "std.meta.bitCount" {
108108 debug.assert(bitCount(f32) == 32);
109109}
110110
111pub fn alignment(comptime T: type) u29 {
111pub fn alignment(comptime T: type) comptime_int {
112112 //@alignOf works on non-pointer types
113113 const P = if (comptime trait.is(TypeId.Pointer)(T)) T else *T;
114114 return @typeInfo(P).Pointer.alignment;
......@@ -386,6 +386,33 @@ test "std.meta.activeTag" {
386386 debug.assert(activeTag(u) == UE.Float);
387387}
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
389416///Compares two of any type for equality. Containers are compared on a field-by-field basis,
390417/// where possible. Pointers are not followed.
391418pub fn eql(a: var, b: @typeOf(a)) bool {
......@@ -439,6 +466,11 @@ pub fn eql(a: var, b: @typeOf(a)) bool {
439466 builtin.TypeInfo.Pointer.Size.Slice => return a.ptr == b.ptr and a.len == b.len,
440467 }
441468 },
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 },
442474 else => return a == b,
443475 }
444476}
......@@ -452,7 +484,7 @@ test "std.meta.eql" {
452484
453485 const U = union(enum) {
454486 s: S,
455 f: f32,
487 f: ?f32,
456488 };
457489
458490 const s_1 = S{
std/meta/trait.zig+31
......@@ -231,6 +231,37 @@ test "std.meta.trait.isPacked" {
231231 debug.assert(!isPacked(u8));
232232}
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
234265///
235266pub fn isSingleItemPtr(comptime T: type) bool {
236267 if (comptime is(builtin.TypeId.Pointer)(T)) {
std/mutex.zig+104-47
......@@ -5,74 +5,124 @@ const AtomicRmwOp = builtin.AtomicRmwOp;
55const assert = std.debug.assert;
66const SpinLock = std.SpinLock;
77const linux = std.os.linux;
8const windows = std.os.windows;
89
910/// Lock may be held only once. If the same thread
1011/// tries to acquire the same mutex twice, it deadlocks.
12/// This type must be initialized at runtime, and then deinitialized when no
13/// longer needed, to free resources.
14/// If you need static initialization, use std.StaticallyInitializedMutex.
1115/// The Linux implementation is based on mutex3 from
1216/// https://www.akkadia.org/drepper/futex.pdf
13pub const Mutex = struct {
14 /// 0: unlocked
15 /// 1: locked, no waiters
16 /// 2: locked, one or more waiters
17 linux_lock: @typeOf(linux_lock_init),
17/// When an application is built in single threaded release mode, all the functions are
18/// no-ops. In single threaded debug mode, there is deadlock detection.
19pub const Mutex = if (builtin.single_threaded)
20 struct {
21 lock: @typeOf(lock_init),
1822
19 /// TODO better implementation than spin lock
20 spin_lock: @typeOf(spin_lock_init),
23 const lock_init = if (std.debug.runtime_safety) false else {};
2124
22 const linux_lock_init = if (builtin.os == builtin.Os.linux) i32(0) else {};
23 const spin_lock_init = if (builtin.os != builtin.Os.linux) SpinLock.init() else {};
25 pub const Held = struct {
26 mutex: *Mutex,
2427
25 pub const Held = struct {
26 mutex: *Mutex,
28 pub fn release(self: Held) void {
29 if (std.debug.runtime_safety) {
30 self.mutex.lock = false;
31 }
32 }
33 };
34 pub fn init() Mutex {
35 return Mutex{ .lock = lock_init };
36 }
37 pub fn deinit(self: *Mutex) void {}
2738
28 pub fn release(self: Held) void {
29 if (builtin.os == builtin.Os.linux) {
30 const c = @atomicRmw(i32, &self.mutex.linux_lock, AtomicRmwOp.Sub, 1, AtomicOrder.Release);
39 pub fn acquire(self: *Mutex) Held {
40 if (std.debug.runtime_safety and self.lock) {
41 @panic("deadlock detected");
42 }
43 return Held{ .mutex = self };
44 }
45 }
46else switch (builtin.os) {
47 builtin.Os.linux => struct {
48 /// 0: unlocked
49 /// 1: locked, no waiters
50 /// 2: locked, one or more waiters
51 lock: i32,
52
53 pub const Held = struct {
54 mutex: *Mutex,
55
56 pub fn release(self: Held) void {
57 const c = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Sub, 1, AtomicOrder.Release);
3158 if (c != 1) {
32 _ = @atomicRmw(i32, &self.mutex.linux_lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release);
33 const rc = linux.futex_wake(&self.mutex.linux_lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1);
59 _ = @atomicRmw(i32, &self.mutex.lock, AtomicRmwOp.Xchg, 0, AtomicOrder.Release);
60 const rc = linux.futex_wake(&self.mutex.lock, linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG, 1);
3461 switch (linux.getErrno(rc)) {
3562 0 => {},
3663 linux.EINVAL => unreachable,
3764 else => unreachable,
3865 }
3966 }
40 } else {
41 SpinLock.Held.release(SpinLock.Held{ .spinlock = &self.mutex.spin_lock });
4267 }
68 };
69
70 pub fn init() Mutex {
71 return Mutex{ .lock = 0 };
4372 }
44 };
4573
46 pub fn init() Mutex {
47 return Mutex{
48 .linux_lock = linux_lock_init,
49 .spin_lock = spin_lock_init,
50 };
51 }
74 pub fn deinit(self: *Mutex) void {}
5275
53 pub fn acquire(self: *Mutex) Held {
54 if (builtin.os == builtin.Os.linux) {
55 var c = @cmpxchgWeak(i32, &self.linux_lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse
76 pub fn acquire(self: *Mutex) Held {
77 var c = @cmpxchgWeak(i32, &self.lock, 0, 1, AtomicOrder.Acquire, AtomicOrder.Monotonic) orelse
5678 return Held{ .mutex = self };
5779 if (c != 2)
58 c = @atomicRmw(i32, &self.linux_lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
80 c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
5981 while (c != 0) {
60 const rc = linux.futex_wait(&self.linux_lock, linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG, 2, null);
82 const rc = linux.futex_wait(&self.lock, linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG, 2, null);
6183 switch (linux.getErrno(rc)) {
6284 0, linux.EINTR, linux.EAGAIN => {},
6385 linux.EINVAL => unreachable,
6486 else => unreachable,
6587 }
66 c = @atomicRmw(i32, &self.linux_lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
88 c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
6789 }
68 } else {
69 _ = self.spin_lock.acquire();
90 return Held{ .mutex = self };
7091 }
71 return Held{ .mutex = self };
72 }
92 },
93 // TODO once https://github.com/ziglang/zig/issues/287 (copy elision) is solved, we can make a
94 // better implementation of this. The problem is we need the init() function to have access to
95 // the address of the CRITICAL_SECTION, and then have it not move.
96 builtin.Os.windows => std.StaticallyInitializedMutex,
97 else => struct {
98 /// TODO better implementation than spin lock.
99 /// When changing this, one must also change the corresponding
100 /// std.StaticallyInitializedMutex code, since it aliases this type,
101 /// under the assumption that it works both statically and at runtime.
102 lock: SpinLock,
103
104 pub const Held = struct {
105 mutex: *Mutex,
106
107 pub fn release(self: Held) void {
108 SpinLock.Held.release(SpinLock.Held{ .spinlock = &self.mutex.lock });
109 }
110 };
111
112 pub fn init() Mutex {
113 return Mutex{ .lock = SpinLock.init() };
114 }
115
116 pub fn deinit(self: *Mutex) void {}
117
118 pub fn acquire(self: *Mutex) Held {
119 _ = self.lock.acquire();
120 return Held{ .mutex = self };
121 }
122 },
73123};
74124
75const Context = struct {
125const TestContext = struct {
76126 mutex: *Mutex,
77127 data: i128,
78128
......@@ -90,25 +140,32 @@ test "std.Mutex" {
90140 var a = &fixed_buffer_allocator.allocator;
91141
92142 var mutex = Mutex.init();
93 var context = Context{
143 defer mutex.deinit();
144
145 var context = TestContext{
94146 .mutex = &mutex,
95147 .data = 0,
96148 };
97149
98 const thread_count = 10;
99 var threads: [thread_count]*std.os.Thread = undefined;
100 for (threads) |*t| {
101 t.* = try std.os.spawnThread(&context, worker);
102 }
103 for (threads) |t|
104 t.wait();
150 if (builtin.single_threaded) {
151 worker(&context);
152 std.debug.assertOrPanic(context.data == TestContext.incr_count);
153 } else {
154 const thread_count = 10;
155 var threads: [thread_count]*std.os.Thread = undefined;
156 for (threads) |*t| {
157 t.* = try std.os.spawnThread(&context, worker);
158 }
159 for (threads) |t|
160 t.wait();
105161
106 std.debug.assertOrPanic(context.data == thread_count * Context.incr_count);
162 std.debug.assertOrPanic(context.data == thread_count * TestContext.incr_count);
163 }
107164}
108165
109fn worker(ctx: *Context) void {
166fn worker(ctx: *TestContext) void {
110167 var i: usize = 0;
111 while (i != Context.incr_count) : (i += 1) {
168 while (i != TestContext.incr_count) : (i += 1) {
112169 const held = ctx.mutex.acquire();
113170 defer held.release();
114171
std/os/child_process.zig+4-3
......@@ -88,7 +88,8 @@ pub const ChildProcess = struct {
8888 /// First argument in argv is the executable.
8989 /// On success must call deinit.
9090 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{
9293 .allocator = allocator,
9394 .argv = argv,
9495 .pid = undefined,
......@@ -109,7 +110,7 @@ pub const ChildProcess = struct {
109110 .stdin_behavior = StdIo.Inherit,
110111 .stdout_behavior = StdIo.Inherit,
111112 .stderr_behavior = StdIo.Inherit,
112 });
113 };
113114 errdefer allocator.destroy(child);
114115 return child;
115116 }
......@@ -594,7 +595,7 @@ pub const ChildProcess = struct {
594595 const PATH = try os.getEnvVarOwned(self.allocator, "PATH");
595596 defer self.allocator.free(PATH);
596597
597 var it = mem.split(PATH, ";");
598 var it = mem.tokenize(PATH, ";");
598599 while (it.next()) |search_path| {
599600 const joined_path = try os.path.join(self.allocator, search_path, app_name);
600601 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:
608608 // +1 for the null terminating byte
609609 const path_buf = try allocator.alloc(u8, PATH.len + exe_path.len + 2);
610610 defer allocator.free(path_buf);
611 var it = mem.split(PATH, ":");
611 var it = mem.tokenize(PATH, ":");
612612 var seen_eacces = false;
613613 var err: usize = undefined;
614614 while (it.next()) |search_path| {
......@@ -3013,6 +3013,7 @@ pub const SpawnThreadError = error{
30133013/// where T is u8, noreturn, void, or !void
30143014/// caller must call wait on the returned thread
30153015pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread {
3016 if (builtin.single_threaded) @compileError("cannot spawn thread when building in single-threaded mode");
30163017 // TODO compile-time call graph analysis to determine stack upper bound
30173018 // https://github.com/ziglang/zig/issues/157
30183019 const default_stack_size = 8 * 1024 * 1024;
......@@ -3046,7 +3047,8 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
30463047 const bytes_ptr = windows.HeapAlloc(heap_handle, 0, byte_count) orelse return SpawnThreadError.OutOfMemory;
30473048 errdefer assert(windows.HeapFree(heap_handle, 0, bytes_ptr) != 0);
30483049 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{
30503052 .thread = Thread{
30513053 .data = Thread.Data{
30523054 .heap_handle = heap_handle,
......@@ -3055,7 +3057,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
30553057 },
30563058 },
30573059 .inner = context,
3058 }) catch unreachable;
3060 };
30593061
30603062 const parameter = if (@sizeOf(Context) == 0) null else @ptrCast(*c_void, &outer_context.inner);
30613063 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 {
184184 return relative_path;
185185 }
186186
187 var it = mem.split(path, []u8{this_sep});
187 var it = mem.tokenize(path, []u8{this_sep});
188188 _ = (it.next() orelse return relative_path);
189189 _ = (it.next() orelse return relative_path);
190190 return WindowsPath{
......@@ -202,7 +202,7 @@ pub fn windowsParsePath(path: []const u8) WindowsPath {
202202 return relative_path;
203203 }
204204
205 var it = mem.split(path, []u8{this_sep});
205 var it = mem.tokenize(path, []u8{this_sep});
206206 _ = (it.next() orelse return relative_path);
207207 _ = (it.next() orelse return relative_path);
208208 return WindowsPath{
......@@ -264,8 +264,8 @@ fn networkShareServersEql(ns1: []const u8, ns2: []const u8) bool {
264264 const sep1 = ns1[0];
265265 const sep2 = ns2[0];
266266
267 var it1 = mem.split(ns1, []u8{sep1});
268 var it2 = mem.split(ns2, []u8{sep2});
267 var it1 = mem.tokenize(ns1, []u8{sep1});
268 var it2 = mem.tokenize(ns2, []u8{sep2});
269269
270270 // TODO ASCII is wrong, we actually need full unicode support to compare paths.
271271 return asciiEqlIgnoreCase(it1.next().?, it2.next().?);
......@@ -285,8 +285,8 @@ fn compareDiskDesignators(kind: WindowsPath.Kind, p1: []const u8, p2: []const u8
285285 const sep1 = p1[0];
286286 const sep2 = p2[0];
287287
288 var it1 = mem.split(p1, []u8{sep1});
289 var it2 = mem.split(p2, []u8{sep2});
288 var it1 = mem.tokenize(p1, []u8{sep1});
289 var it2 = mem.tokenize(p2, []u8{sep2});
290290
291291 // TODO ASCII is wrong, we actually need full unicode support to compare paths.
292292 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 {
337337/// If all paths are relative it uses the current working directory as a starting point.
338338/// Each drive has its own current working directory.
339339/// 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.
340342pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
341343 if (paths.len == 0) {
342344 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 {
416418 },
417419 WindowsPath.Kind.NetworkShare => {
418420 result = try allocator.alloc(u8, max_size);
419 var it = mem.split(paths[first_index], "/\\");
421 var it = mem.tokenize(paths[first_index], "/\\");
420422 const server_name = it.next().?;
421423 const other_name = it.next().?;
422424
......@@ -483,7 +485,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
483485 if (!correct_disk_designator) {
484486 continue;
485487 }
486 var it = mem.split(p[parsed.disk_designator.len..], "/\\");
488 var it = mem.tokenize(p[parsed.disk_designator.len..], "/\\");
487489 while (it.next()) |component| {
488490 if (mem.eql(u8, component, ".")) {
489491 continue;
......@@ -516,6 +518,8 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
516518/// It resolves "." and "..".
517519/// The result does not have a trailing path separator.
518520/// 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.
519523pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
520524 if (paths.len == 0) {
521525 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 {
550554 errdefer allocator.free(result);
551555
552556 for (paths[first_index..]) |p, i| {
553 var it = mem.split(p, "/");
557 var it = mem.tokenize(p, "/");
554558 while (it.next()) |component| {
555559 if (mem.eql(u8, component, ".")) {
556560 continue;
......@@ -937,8 +941,8 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8)
937941 return resolved_to;
938942 }
939943
940 var from_it = mem.split(resolved_from, "/\\");
941 var to_it = mem.split(resolved_to, "/\\");
944 var from_it = mem.tokenize(resolved_from, "/\\");
945 var to_it = mem.tokenize(resolved_to, "/\\");
942946 while (true) {
943947 const from_component = from_it.next() orelse return mem.dupe(allocator, u8, to_it.rest());
944948 const to_rest = to_it.rest();
......@@ -967,7 +971,7 @@ pub fn relativeWindows(allocator: *Allocator, from: []const u8, to: []const u8)
967971 // shave off the trailing slash
968972 result_index -= 1;
969973
970 var rest_it = mem.split(to_rest, "/\\");
974 var rest_it = mem.tokenize(to_rest, "/\\");
971975 while (rest_it.next()) |to_component| {
972976 result[result_index] = '\\';
973977 result_index += 1;
......@@ -988,8 +992,8 @@ pub fn relativePosix(allocator: *Allocator, from: []const u8, to: []const u8) ![
988992 const resolved_to = try resolvePosix(allocator, [][]const u8{to});
989993 defer allocator.free(resolved_to);
990994
991 var from_it = mem.split(resolved_from, "/");
992 var to_it = mem.split(resolved_to, "/");
995 var from_it = mem.tokenize(resolved_from, "/");
996 var to_it = mem.tokenize(resolved_to, "/");
993997 while (true) {
994998 const from_component = from_it.next() orelse return mem.dupe(allocator, u8, to_it.rest());
995999 const to_rest = to_it.rest();
std/os/test.zig+4
......@@ -40,6 +40,8 @@ fn testThreadIdFn(thread_id: *os.Thread.Id) void {
4040}
4141
4242test "std.os.Thread.getCurrentId" {
43 if (builtin.single_threaded) return error.SkipZigTest;
44
4345 var thread_current_id: os.Thread.Id = undefined;
4446 const thread = try os.spawnThread(&thread_current_id, testThreadIdFn);
4547 const thread_id = thread.handle();
......@@ -53,6 +55,8 @@ test "std.os.Thread.getCurrentId" {
5355}
5456
5557test "spawn threads" {
58 if (builtin.single_threaded) return error.SkipZigTest;
59
5660 var shared_ctx: i32 = 1;
5761
5862 const thread1 = try std.os.spawnThread({}, start1);
std/os/time.zig+3-5
......@@ -79,14 +79,12 @@ fn milliTimestampWindows() u64 {
7979}
8080
8181fn milliTimestampDarwin() u64 {
82 //Sources suggest MacOS 10.12 has support for
83 // posix clock_gettime.
8482 var tv: darwin.timeval = undefined;
8583 var err = darwin.gettimeofday(&tv, null);
8684 debug.assert(err == 0);
87 const sec_ms = @intCast(u64, tv.tv_sec) * ms_per_s;
88 const usec_ms = @divFloor(@intCast(u64, tv.tv_usec), us_per_s / ms_per_s);
89 return u64(sec_ms) + u64(usec_ms);
85 const sec_ms = tv.tv_sec * ms_per_s;
86 const usec_ms = @divFloor(tv.tv_usec, us_per_s / ms_per_s);
87 return @intCast(u64, sec_ms + usec_ms);
9088}
9189
9290fn milliTimestampPosix() u64 {
std/os/windows/index.zig+1
......@@ -49,6 +49,7 @@ pub const UNICODE = false;
4949pub const WCHAR = u16;
5050pub const WORD = u16;
5151pub const LARGE_INTEGER = i64;
52pub const LONG = c_long;
5253
5354pub const TRUE = 1;
5455pub const FALSE = 0;
std/os/windows/kernel32.zig+47
......@@ -220,3 +220,50 @@ pub const FOREGROUND_BLUE = 1;
220220pub const FOREGROUND_GREEN = 2;
221221pub const FOREGROUND_RED = 4;
222222pub 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 {
1717 defer stack.deinit();
1818
1919 const arena = &tree_arena.allocator;
20 const root_node = try arena.create(ast.Node.Root{
20 const root_node = try arena.create(ast.Node.Root);
21 root_node.* = ast.Node.Root{
2122 .base = ast.Node{ .id = ast.Node.Id.Root },
2223 .decls = ast.Node.Root.DeclList.init(arena),
2324 .doc_comments = null,
2425 .shebang = null,
2526 // initialized when we get the eof token
2627 .eof_token = undefined,
27 });
28 };
2829
2930 var tree = ast.Tree{
3031 .source = source,
......@@ -75,20 +76,22 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
7576 Token.Id.Keyword_test => {
7677 stack.append(State.TopLevel) catch unreachable;
7778
78 const block = try arena.create(ast.Node.Block{
79 const block = try arena.create(ast.Node.Block);
80 block.* = ast.Node.Block{
7981 .base = ast.Node{ .id = ast.Node.Id.Block },
8082 .label = null,
8183 .lbrace = undefined,
8284 .statements = ast.Node.Block.StatementList.init(arena),
8385 .rbrace = undefined,
84 });
85 const test_node = try arena.create(ast.Node.TestDecl{
86 };
87 const test_node = try arena.create(ast.Node.TestDecl);
88 test_node.* = ast.Node.TestDecl{
8689 .base = ast.Node{ .id = ast.Node.Id.TestDecl },
8790 .doc_comments = comments,
8891 .test_token = token_index,
8992 .name = undefined,
9093 .body_node = &block.base,
91 });
94 };
9295 try root_node.decls.push(&test_node.base);
9396 try stack.append(State{ .Block = block });
9497 try stack.append(State{
......@@ -119,19 +122,21 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
119122 continue;
120123 },
121124 Token.Id.Keyword_comptime => {
122 const block = try arena.create(ast.Node.Block{
125 const block = try arena.create(ast.Node.Block);
126 block.* = ast.Node.Block{
123127 .base = ast.Node{ .id = ast.Node.Id.Block },
124128 .label = null,
125129 .lbrace = undefined,
126130 .statements = ast.Node.Block.StatementList.init(arena),
127131 .rbrace = undefined,
128 });
129 const node = try arena.create(ast.Node.Comptime{
132 };
133 const node = try arena.create(ast.Node.Comptime);
134 node.* = ast.Node.Comptime{
130135 .base = ast.Node{ .id = ast.Node.Id.Comptime },
131136 .comptime_token = token_index,
132137 .expr = &block.base,
133138 .doc_comments = comments,
134 });
139 };
135140 try root_node.decls.push(&node.base);
136141
137142 stack.append(State.TopLevel) catch unreachable;
......@@ -235,14 +240,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
235240 return tree;
236241 }
237242
238 const node = try arena.create(ast.Node.Use{
243 const node = try arena.create(ast.Node.Use);
244 node.* = ast.Node.Use{
239245 .base = ast.Node{ .id = ast.Node.Id.Use },
240246 .use_token = token_index,
241247 .visib_token = ctx.visib_token,
242248 .expr = undefined,
243249 .semicolon_token = undefined,
244250 .doc_comments = ctx.comments,
245 });
251 };
246252 try ctx.decls.push(&node.base);
247253
248254 stack.append(State{
......@@ -276,7 +282,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
276282 continue;
277283 },
278284 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{
280287 .base = ast.Node{ .id = ast.Node.Id.FnProto },
281288 .doc_comments = ctx.comments,
282289 .visib_token = ctx.visib_token,
......@@ -292,7 +299,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
292299 .lib_name = ctx.lib_name,
293300 .align_expr = null,
294301 .section_expr = null,
295 });
302 };
296303 try ctx.decls.push(&fn_proto.base);
297304 stack.append(State{ .FnDef = fn_proto }) catch unreachable;
298305 try stack.append(State{ .FnProto = fn_proto });
......@@ -309,12 +316,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
309316 continue;
310317 },
311318 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{
313321 .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },
314322 .async_token = token_index,
315323 .allocator_type = null,
316324 .rangle_bracket = null,
317 });
325 };
318326 fn_proto.async_attr = async_node;
319327
320328 try stack.append(State{
......@@ -341,13 +349,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
341349 },
342350 State.TopLevelExternOrField => |ctx| {
343351 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{
345354 .base = ast.Node{ .id = ast.Node.Id.StructField },
346355 .doc_comments = ctx.comments,
347356 .visib_token = ctx.visib_token,
348357 .name_token = identifier,
349358 .type_expr = undefined,
350 });
359 };
351360 const node_ptr = try ctx.container_decl.fields_and_decls.addOne();
352361 node_ptr.* = &node.base;
353362
......@@ -391,7 +400,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
391400 const token = nextToken(&tok_it, &tree);
392401 const token_index = token.index;
393402 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{
395405 .base = ast.Node{ .id = ast.Node.Id.ContainerDecl },
396406 .layout_token = ctx.layout_token,
397407 .kind_token = switch (token_ptr.id) {
......@@ -405,7 +415,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
405415 .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(arena),
406416 .lbrace_token = undefined,
407417 .rbrace_token = undefined,
408 });
418 };
409419 ctx.opt_ctx.store(&node.base);
410420
411421 stack.append(State{ .ContainerDecl = node }) catch unreachable;
......@@ -464,13 +474,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
464474 Token.Id.Identifier => {
465475 switch (tree.tokens.at(container_decl.kind_token).id) {
466476 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{
468479 .base = ast.Node{ .id = ast.Node.Id.StructField },
469480 .doc_comments = comments,
470481 .visib_token = null,
471482 .name_token = token_index,
472483 .type_expr = undefined,
473 });
484 };
474485 const node_ptr = try container_decl.fields_and_decls.addOne();
475486 node_ptr.* = &node.base;
476487
......@@ -485,13 +496,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
485496 continue;
486497 },
487498 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{
489501 .base = ast.Node{ .id = ast.Node.Id.UnionTag },
490502 .name_token = token_index,
491503 .type_expr = null,
492504 .value_expr = null,
493505 .doc_comments = comments,
494 });
506 };
495507 try container_decl.fields_and_decls.push(&node.base);
496508
497509 try stack.append(State{
......@@ -506,12 +518,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
506518 continue;
507519 },
508520 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{
510523 .base = ast.Node{ .id = ast.Node.Id.EnumTag },
511524 .name_token = token_index,
512525 .value = null,
513526 .doc_comments = comments,
514 });
527 };
515528 try container_decl.fields_and_decls.push(&node.base);
516529
517530 try stack.append(State{
......@@ -593,7 +606,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
593606 },
594607
595608 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{
597611 .base = ast.Node{ .id = ast.Node.Id.VarDecl },
598612 .doc_comments = ctx.comments,
599613 .visib_token = ctx.visib_token,
......@@ -609,7 +623,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
609623 .name_token = undefined,
610624 .eq_token = undefined,
611625 .semicolon_token = undefined,
612 });
626 };
613627 try ctx.list.push(&var_decl.base);
614628
615629 try stack.append(State{ .VarDeclAlign = var_decl });
......@@ -708,13 +722,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
708722 const token_ptr = token.ptr;
709723 switch (token_ptr.id) {
710724 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{
712727 .base = ast.Node{ .id = ast.Node.Id.Block },
713728 .label = null,
714729 .lbrace = token_index,
715730 .statements = ast.Node.Block.StatementList.init(arena),
716731 .rbrace = undefined,
717 });
732 };
718733 fn_proto.body_node = &block.base;
719734 stack.append(State{ .Block = block }) catch unreachable;
720735 continue;
......@@ -770,10 +785,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
770785 // TODO: this is a special case. Remove this when #760 is fixed
771786 if (token_ptr.id == Token.Id.Keyword_anyerror) {
772787 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{
774790 .base = ast.Node{ .id = ast.Node.Id.ErrorType },
775791 .token = token_index,
776 });
792 };
777793 fn_proto.return_type = ast.Node.FnProto.ReturnType{ .Explicit = &error_type_node.base };
778794 continue;
779795 }
......@@ -791,14 +807,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
791807 if (eatToken(&tok_it, &tree, Token.Id.RParen)) |_| {
792808 continue;
793809 }
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{
795812 .base = ast.Node{ .id = ast.Node.Id.ParamDecl },
796813 .comptime_token = null,
797814 .noalias_token = null,
798815 .name_token = null,
799816 .type_node = undefined,
800817 .var_args_token = null,
801 });
818 };
802819 try fn_proto.params.push(&param_decl.base);
803820
804821 stack.append(State{
......@@ -877,13 +894,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
877894 const token_ptr = token.ptr;
878895 switch (token_ptr.id) {
879896 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{
881899 .base = ast.Node{ .id = ast.Node.Id.Block },
882900 .label = ctx.label,
883901 .lbrace = token_index,
884902 .statements = ast.Node.Block.StatementList.init(arena),
885903 .rbrace = undefined,
886 });
904 };
887905 ctx.opt_ctx.store(&block.base);
888906 stack.append(State{ .Block = block }) catch unreachable;
889907 continue;
......@@ -970,7 +988,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
970988 }
971989 },
972990 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{
974993 .base = ast.Node{ .id = ast.Node.Id.While },
975994 .label = ctx.label,
976995 .inline_token = ctx.inline_token,
......@@ -980,7 +999,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
980999 .continue_expr = null,
9811000 .body = undefined,
9821001 .@"else" = null,
983 });
1002 };
9841003 ctx.opt_ctx.store(&node.base);
9851004 stack.append(State{ .Else = &node.@"else" }) catch unreachable;
9861005 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } });
......@@ -999,7 +1018,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
9991018 continue;
10001019 },
10011020 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{
10031023 .base = ast.Node{ .id = ast.Node.Id.For },
10041024 .label = ctx.label,
10051025 .inline_token = ctx.inline_token,
......@@ -1008,7 +1028,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
10081028 .payload = null,
10091029 .body = undefined,
10101030 .@"else" = null,
1011 });
1031 };
10121032 ctx.opt_ctx.store(&node.base);
10131033 stack.append(State{ .Else = &node.@"else" }) catch unreachable;
10141034 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.body } });
......@@ -1020,12 +1040,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
10201040 },
10211041 State.Else => |dest| {
10221042 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{
10241045 .base = ast.Node{ .id = ast.Node.Id.Else },
10251046 .else_token = else_token,
10261047 .payload = null,
10271048 .body = undefined,
1028 });
1049 };
10291050 dest.* = node;
10301051
10311052 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 {
10831104 continue;
10841105 },
10851106 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{
10871109 .base = ast.Node{ .id = ast.Node.Id.Defer },
10881110 .defer_token = token_index,
10891111 .expr = undefined,
1090 });
1112 };
10911113 const node_ptr = try block.statements.addOne();
10921114 node_ptr.* = &node.base;
10931115
......@@ -1096,13 +1118,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
10961118 continue;
10971119 },
10981120 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{
11001123 .base = ast.Node{ .id = ast.Node.Id.Block },
11011124 .label = null,
11021125 .lbrace = token_index,
11031126 .statements = ast.Node.Block.StatementList.init(arena),
11041127 .rbrace = undefined,
1105 });
1128 };
11061129 try block.statements.push(&inner_block.base);
11071130
11081131 stack.append(State{ .Block = inner_block }) catch unreachable;
......@@ -1164,14 +1187,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
11641187 continue;
11651188 }
11661189
1167 const node = try arena.create(ast.Node.AsmOutput{
1190 const node = try arena.create(ast.Node.AsmOutput);
1191 node.* = ast.Node.AsmOutput{
11681192 .base = ast.Node{ .id = ast.Node.Id.AsmOutput },
11691193 .lbracket = lbracket_index,
11701194 .symbolic_name = undefined,
11711195 .constraint = undefined,
11721196 .kind = undefined,
11731197 .rparen = undefined,
1174 });
1198 };
11751199 try items.push(node);
11761200
11771201 stack.append(State{ .AsmOutputItems = items }) catch unreachable;
......@@ -1218,14 +1242,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
12181242 continue;
12191243 }
12201244
1221 const node = try arena.create(ast.Node.AsmInput{
1245 const node = try arena.create(ast.Node.AsmInput);
1246 node.* = ast.Node.AsmInput{
12221247 .base = ast.Node{ .id = ast.Node.Id.AsmInput },
12231248 .lbracket = lbracket_index,
12241249 .symbolic_name = undefined,
12251250 .constraint = undefined,
12261251 .expr = undefined,
12271252 .rparen = undefined,
1228 });
1253 };
12291254 try items.push(node);
12301255
12311256 stack.append(State{ .AsmInputItems = items }) catch unreachable;
......@@ -1283,12 +1308,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
12831308 continue;
12841309 }
12851310
1286 const node = try arena.create(ast.Node.FieldInitializer{
1311 const node = try arena.create(ast.Node.FieldInitializer);
1312 node.* = ast.Node.FieldInitializer{
12871313 .base = ast.Node{ .id = ast.Node.Id.FieldInitializer },
12881314 .period_token = undefined,
12891315 .name_token = undefined,
12901316 .expr = undefined,
1291 });
1317 };
12921318 try list_state.list.push(&node.base);
12931319
12941320 stack.append(State{ .FieldInitListCommaOrEnd = list_state }) catch unreachable;
......@@ -1390,13 +1416,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
13901416 }
13911417
13921418 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{
13941421 .base = ast.Node{ .id = ast.Node.Id.SwitchCase },
13951422 .items = ast.Node.SwitchCase.ItemList.init(arena),
13961423 .payload = null,
13971424 .expr = undefined,
13981425 .arrow_token = undefined,
1399 });
1426 };
14001427 try list_state.list.push(&node.base);
14011428 try stack.append(State{ .SwitchCaseCommaOrEnd = list_state });
14021429 try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .Required = &node.expr } });
......@@ -1427,10 +1454,11 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
14271454 const token_index = token.index;
14281455 const token_ptr = token.ptr;
14291456 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{
14311459 .base = ast.Node{ .id = ast.Node.Id.SwitchElse },
14321460 .token = token_index,
1433 });
1461 };
14341462 try switch_case.items.push(&else_node.base);
14351463
14361464 try stack.append(State{
......@@ -1537,7 +1565,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
15371565
15381566 State.ExternType => |ctx| {
15391567 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{
15411570 .base = ast.Node{ .id = ast.Node.Id.FnProto },
15421571 .doc_comments = ctx.comments,
15431572 .visib_token = null,
......@@ -1553,7 +1582,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
15531582 .lib_name = null,
15541583 .align_expr = null,
15551584 .section_expr = null,
1556 });
1585 };
15571586 ctx.opt_ctx.store(&fn_proto.base);
15581587 stack.append(State{ .FnProto = fn_proto }) catch unreachable;
15591588 continue;
......@@ -1711,12 +1740,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
17111740 continue;
17121741 }
17131742
1714 const node = try arena.create(ast.Node.Payload{
1743 const node = try arena.create(ast.Node.Payload);
1744 node.* = ast.Node.Payload{
17151745 .base = ast.Node{ .id = ast.Node.Id.Payload },
17161746 .lpipe = token_index,
17171747 .error_symbol = undefined,
17181748 .rpipe = undefined,
1719 });
1749 };
17201750 opt_ctx.store(&node.base);
17211751
17221752 stack.append(State{
......@@ -1747,13 +1777,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
17471777 continue;
17481778 }
17491779
1750 const node = try arena.create(ast.Node.PointerPayload{
1780 const node = try arena.create(ast.Node.PointerPayload);
1781 node.* = ast.Node.PointerPayload{
17511782 .base = ast.Node{ .id = ast.Node.Id.PointerPayload },
17521783 .lpipe = token_index,
17531784 .ptr_token = null,
17541785 .value_symbol = undefined,
17551786 .rpipe = undefined,
1756 });
1787 };
17571788 opt_ctx.store(&node.base);
17581789
17591790 try stack.append(State{
......@@ -1790,14 +1821,15 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
17901821 continue;
17911822 }
17921823
1793 const node = try arena.create(ast.Node.PointerIndexPayload{
1824 const node = try arena.create(ast.Node.PointerIndexPayload);
1825 node.* = ast.Node.PointerIndexPayload{
17941826 .base = ast.Node{ .id = ast.Node.Id.PointerIndexPayload },
17951827 .lpipe = token_index,
17961828 .ptr_token = null,
17971829 .value_symbol = undefined,
17981830 .index_symbol = null,
17991831 .rpipe = undefined,
1800 });
1832 };
18011833 opt_ctx.store(&node.base);
18021834
18031835 stack.append(State{
......@@ -1824,12 +1856,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
18241856 const token_ptr = token.ptr;
18251857 switch (token_ptr.id) {
18261858 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{
18281861 .base = ast.Node{ .id = ast.Node.Id.ControlFlowExpression },
18291862 .ltoken = token_index,
18301863 .kind = undefined,
18311864 .rhs = null,
1832 });
1865 };
18331866 opt_ctx.store(&node.base);
18341867
18351868 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 {
18531886 continue;
18541887 },
18551888 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{
18571891 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
18581892 .op_token = token_index,
18591893 .op = switch (token_ptr.id) {
......@@ -1863,7 +1897,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
18631897 else => unreachable,
18641898 },
18651899 .rhs = undefined,
1866 });
1900 };
18671901 opt_ctx.store(&node.base);
18681902
18691903 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 {
18871921 const lhs = opt_ctx.get() orelse continue;
18881922
18891923 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{
18911926 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
18921927 .lhs = lhs,
18931928 .op_token = ellipsis3,
18941929 .op = ast.Node.InfixOp.Op.Range,
18951930 .rhs = undefined,
1896 });
1931 };
18971932 opt_ctx.store(&node.base);
18981933 stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
18991934 continue;
......@@ -1912,13 +1947,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
19121947 const token_index = token.index;
19131948 const token_ptr = token.ptr;
19141949 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{
19161952 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
19171953 .lhs = lhs,
19181954 .op_token = token_index,
19191955 .op = ass_id,
19201956 .rhs = undefined,
1921 });
1957 };
19221958 opt_ctx.store(&node.base);
19231959 stack.append(State{ .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
19241960 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.rhs } });
......@@ -1942,13 +1978,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
19421978 const token_index = token.index;
19431979 const token_ptr = token.ptr;
19441980 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{
19461983 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
19471984 .lhs = lhs,
19481985 .op_token = token_index,
19491986 .op = unwrap_id,
19501987 .rhs = undefined,
1951 });
1988 };
19521989 opt_ctx.store(&node.base);
19531990
19541991 stack.append(State{ .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
......@@ -1974,13 +2011,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
19742011 const lhs = opt_ctx.get() orelse continue;
19752012
19762013 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{
19782016 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
19792017 .lhs = lhs,
19802018 .op_token = or_token,
19812019 .op = ast.Node.InfixOp.Op.BoolOr,
19822020 .rhs = undefined,
1983 });
2021 };
19842022 opt_ctx.store(&node.base);
19852023 stack.append(State{ .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
19862024 try stack.append(State{ .BoolAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
......@@ -1998,13 +2036,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
19982036 const lhs = opt_ctx.get() orelse continue;
19992037
20002038 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{
20022041 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
20032042 .lhs = lhs,
20042043 .op_token = and_token,
20052044 .op = ast.Node.InfixOp.Op.BoolAnd,
20062045 .rhs = undefined,
2007 });
2046 };
20082047 opt_ctx.store(&node.base);
20092048 stack.append(State{ .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
20102049 try stack.append(State{ .ComparisonExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
......@@ -2025,13 +2064,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
20252064 const token_index = token.index;
20262065 const token_ptr = token.ptr;
20272066 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{
20292069 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
20302070 .lhs = lhs,
20312071 .op_token = token_index,
20322072 .op = comp_id,
20332073 .rhs = undefined,
2034 });
2074 };
20352075 opt_ctx.store(&node.base);
20362076 stack.append(State{ .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
20372077 try stack.append(State{ .BinaryOrExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
......@@ -2052,13 +2092,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
20522092 const lhs = opt_ctx.get() orelse continue;
20532093
20542094 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{
20562097 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
20572098 .lhs = lhs,
20582099 .op_token = pipe,
20592100 .op = ast.Node.InfixOp.Op.BitOr,
20602101 .rhs = undefined,
2061 });
2102 };
20622103 opt_ctx.store(&node.base);
20632104 stack.append(State{ .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
20642105 try stack.append(State{ .BinaryXorExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
......@@ -2076,13 +2117,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
20762117 const lhs = opt_ctx.get() orelse continue;
20772118
20782119 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{
20802122 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
20812123 .lhs = lhs,
20822124 .op_token = caret,
20832125 .op = ast.Node.InfixOp.Op.BitXor,
20842126 .rhs = undefined,
2085 });
2127 };
20862128 opt_ctx.store(&node.base);
20872129 stack.append(State{ .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
20882130 try stack.append(State{ .BinaryAndExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
......@@ -2100,13 +2142,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
21002142 const lhs = opt_ctx.get() orelse continue;
21012143
21022144 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{
21042147 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
21052148 .lhs = lhs,
21062149 .op_token = ampersand,
21072150 .op = ast.Node.InfixOp.Op.BitAnd,
21082151 .rhs = undefined,
2109 });
2152 };
21102153 opt_ctx.store(&node.base);
21112154 stack.append(State{ .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
21122155 try stack.append(State{ .BitShiftExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
......@@ -2127,13 +2170,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
21272170 const token_index = token.index;
21282171 const token_ptr = token.ptr;
21292172 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{
21312175 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
21322176 .lhs = lhs,
21332177 .op_token = token_index,
21342178 .op = bitshift_id,
21352179 .rhs = undefined,
2136 });
2180 };
21372181 opt_ctx.store(&node.base);
21382182 stack.append(State{ .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
21392183 try stack.append(State{ .AdditionExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
......@@ -2157,13 +2201,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
21572201 const token_index = token.index;
21582202 const token_ptr = token.ptr;
21592203 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{
21612206 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
21622207 .lhs = lhs,
21632208 .op_token = token_index,
21642209 .op = add_id,
21652210 .rhs = undefined,
2166 });
2211 };
21672212 opt_ctx.store(&node.base);
21682213 stack.append(State{ .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
21692214 try stack.append(State{ .MultiplyExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
......@@ -2187,13 +2232,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
21872232 const token_index = token.index;
21882233 const token_ptr = token.ptr;
21892234 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{
21912237 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
21922238 .lhs = lhs,
21932239 .op_token = token_index,
21942240 .op = mult_id,
21952241 .rhs = undefined,
2196 });
2242 };
21972243 opt_ctx.store(&node.base);
21982244 stack.append(State{ .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
21992245 try stack.append(State{ .CurlySuffixExpressionBegin = OptionalCtx{ .Required = &node.rhs } });
......@@ -2215,12 +2261,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
22152261 const lhs = opt_ctx.get() orelse continue;
22162262
22172263 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{
22192266 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
22202267 .lhs = lhs,
22212268 .op = ast.Node.SuffixOp.Op{ .StructInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) },
22222269 .rtoken = undefined,
2223 });
2270 };
22242271 opt_ctx.store(&node.base);
22252272
22262273 stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
......@@ -2234,12 +2281,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
22342281 continue;
22352282 }
22362283
2237 const node = try arena.create(ast.Node.SuffixOp{
2284 const node = try arena.create(ast.Node.SuffixOp);
2285 node.* = ast.Node.SuffixOp{
22382286 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
22392287 .lhs = lhs,
22402288 .op = ast.Node.SuffixOp.Op{ .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena) },
22412289 .rtoken = undefined,
2242 });
2290 };
22432291 opt_ctx.store(&node.base);
22442292 stack.append(State{ .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
22452293 try stack.append(State{ .IfToken = Token.Id.LBrace });
......@@ -2263,13 +2311,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
22632311 const lhs = opt_ctx.get() orelse continue;
22642312
22652313 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{
22672316 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
22682317 .lhs = lhs,
22692318 .op_token = bang,
22702319 .op = ast.Node.InfixOp.Op.ErrorUnion,
22712320 .rhs = undefined,
2272 });
2321 };
22732322 opt_ctx.store(&node.base);
22742323 stack.append(State{ .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable;
22752324 try stack.append(State{ .PrefixOpExpression = OptionalCtx{ .Required = &node.rhs } });
......@@ -2282,22 +2331,24 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
22822331 const token_index = token.index;
22832332 const token_ptr = token.ptr;
22842333 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{
22862336 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
22872337 .op_token = token_index,
22882338 .op = prefix_id,
22892339 .rhs = undefined,
2290 });
2340 };
22912341 opt_ctx.store(&node.base);
22922342
22932343 // Treat '**' token as two pointer types
22942344 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{
22962347 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
22972348 .op_token = token_index,
22982349 .op = prefix_id,
22992350 .rhs = undefined,
2300 });
2351 };
23012352 node.rhs = &child.base;
23022353 node = child;
23032354 }
......@@ -2316,12 +2367,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
23162367
23172368 State.SuffixOpExpressionBegin => |opt_ctx| {
23182369 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{
23202372 .base = ast.Node{ .id = ast.Node.Id.AsyncAttribute },
23212373 .async_token = async_token,
23222374 .allocator_type = null,
23232375 .rangle_bracket = null,
2324 });
2376 };
23252377 stack.append(State{
23262378 .AsyncEnd = AsyncEndCtx{
23272379 .ctx = opt_ctx,
......@@ -2347,7 +2399,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
23472399 const token_ptr = token.ptr;
23482400 switch (token_ptr.id) {
23492401 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{
23512404 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
23522405 .lhs = lhs,
23532406 .op = ast.Node.SuffixOp.Op{
......@@ -2357,7 +2410,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
23572410 },
23582411 },
23592412 .rtoken = undefined,
2360 });
2413 };
23612414 opt_ctx.store(&node.base);
23622415
23632416 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
......@@ -2371,12 +2424,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
23712424 continue;
23722425 },
23732426 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{
23752429 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
23762430 .lhs = lhs,
23772431 .op = ast.Node.SuffixOp.Op{ .ArrayAccess = undefined },
23782432 .rtoken = undefined,
2379 });
2433 };
23802434 opt_ctx.store(&node.base);
23812435
23822436 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
......@@ -2386,34 +2440,37 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
23862440 },
23872441 Token.Id.Period => {
23882442 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{
23902445 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
23912446 .lhs = lhs,
23922447 .op = ast.Node.SuffixOp.Op.Deref,
23932448 .rtoken = asterisk_token,
2394 });
2449 };
23952450 opt_ctx.store(&node.base);
23962451 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
23972452 continue;
23982453 }
23992454 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{
24012457 .base = ast.Node{ .id = ast.Node.Id.SuffixOp },
24022458 .lhs = lhs,
24032459 .op = ast.Node.SuffixOp.Op.UnwrapOptional,
24042460 .rtoken = question_token,
2405 });
2461 };
24062462 opt_ctx.store(&node.base);
24072463 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
24082464 continue;
24092465 }
2410 const node = try arena.create(ast.Node.InfixOp{
2466 const node = try arena.create(ast.Node.InfixOp);
2467 node.* = ast.Node.InfixOp{
24112468 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
24122469 .lhs = lhs,
24132470 .op_token = token_index,
24142471 .op = ast.Node.InfixOp.Op.Period,
24152472 .rhs = undefined,
2416 });
2473 };
24172474 opt_ctx.store(&node.base);
24182475
24192476 stack.append(State{ .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
......@@ -2467,11 +2524,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
24672524 continue;
24682525 },
24692526 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{
24712529 .base = ast.Node{ .id = ast.Node.Id.PromiseType },
24722530 .promise_token = token.index,
24732531 .result = null,
2474 });
2532 };
24752533 opt_ctx.store(&node.base);
24762534 const next_token = nextToken(&tok_it, &tree);
24772535 const next_token_index = next_token.index;
......@@ -2493,12 +2551,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
24932551 continue;
24942552 },
24952553 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{
24972556 .base = ast.Node{ .id = ast.Node.Id.GroupedExpression },
24982557 .lparen = token.index,
24992558 .expr = undefined,
25002559 .rparen = undefined,
2501 });
2560 };
25022561 opt_ctx.store(&node.base);
25032562
25042563 stack.append(State{
......@@ -2511,12 +2570,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
25112570 continue;
25122571 },
25132572 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{
25152575 .base = ast.Node{ .id = ast.Node.Id.BuiltinCall },
25162576 .builtin_token = token.index,
25172577 .params = ast.Node.BuiltinCall.ParamList.init(arena),
25182578 .rparen_token = undefined,
2519 });
2579 };
25202580 opt_ctx.store(&node.base);
25212581
25222582 stack.append(State{
......@@ -2530,12 +2590,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
25302590 continue;
25312591 },
25322592 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{
25342595 .base = ast.Node{ .id = ast.Node.Id.PrefixOp },
25352596 .op_token = token.index,
25362597 .op = undefined,
25372598 .rhs = undefined,
2538 });
2599 };
25392600 opt_ctx.store(&node.base);
25402601
25412602 stack.append(State{ .SliceOrArrayType = node }) catch unreachable;
......@@ -2593,7 +2654,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
25932654 continue;
25942655 },
25952656 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{
25972659 .base = ast.Node{ .id = ast.Node.Id.FnProto },
25982660 .doc_comments = null,
25992661 .visib_token = null,
......@@ -2609,13 +2671,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
26092671 .lib_name = null,
26102672 .align_expr = null,
26112673 .section_expr = null,
2612 });
2674 };
26132675 opt_ctx.store(&fn_proto.base);
26142676 stack.append(State{ .FnProto = fn_proto }) catch unreachable;
26152677 continue;
26162678 },
26172679 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{
26192682 .base = ast.Node{ .id = ast.Node.Id.FnProto },
26202683 .doc_comments = null,
26212684 .visib_token = null,
......@@ -2631,7 +2694,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
26312694 .lib_name = null,
26322695 .align_expr = null,
26332696 .section_expr = null,
2634 });
2697 };
26352698 opt_ctx.store(&fn_proto.base);
26362699 stack.append(State{ .FnProto = fn_proto }) catch unreachable;
26372700 try stack.append(State{
......@@ -2643,7 +2706,8 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
26432706 continue;
26442707 },
26452708 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{
26472711 .base = ast.Node{ .id = ast.Node.Id.Asm },
26482712 .asm_token = token.index,
26492713 .volatile_token = null,
......@@ -2652,7 +2716,7 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
26522716 .inputs = ast.Node.Asm.InputList.init(arena),
26532717 .clobbers = ast.Node.Asm.ClobberList.init(arena),
26542718 .rparen = undefined,
2655 });
2719 };
26562720 opt_ctx.store(&node.base);
26572721
26582722 stack.append(State{
......@@ -2701,13 +2765,14 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
27012765
27022766 State.ErrorTypeOrSetDecl => |ctx| {
27032767 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{
27052770 .base = ast.Node{ .id = ast.Node.Id.InfixOp },
27062771 .lhs = &(try createLiteral(arena, ast.Node.ErrorType, ctx.error_token)).base,
27072772 .op_token = undefined,
27082773 .op = ast.Node.InfixOp.Op.Period,
27092774 .rhs = undefined,
2710 });
2775 };
27112776 ctx.opt_ctx.store(&node.base);
27122777 stack.append(State{ .Identifier = OptionalCtx{ .Required = &node.rhs } }) catch unreachable;
27132778 try stack.append(State{
......@@ -2719,12 +2784,13 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
27192784 continue;
27202785 }
27212786
2722 const node = try arena.create(ast.Node.ErrorSetDecl{
2787 const node = try arena.create(ast.Node.ErrorSetDecl);
2788 node.* = ast.Node.ErrorSetDecl{
27232789 .base = ast.Node{ .id = ast.Node.Id.ErrorSetDecl },
27242790 .error_token = ctx.error_token,
27252791 .decls = ast.Node.ErrorSetDecl.DeclList.init(arena),
27262792 .rbrace_token = undefined,
2727 });
2793 };
27282794 ctx.opt_ctx.store(&node.base);
27292795
27302796 stack.append(State{
......@@ -2785,11 +2851,12 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
27852851 return tree;
27862852 }
27872853
2788 const node = try arena.create(ast.Node.ErrorTag{
2854 const node = try arena.create(ast.Node.ErrorTag);
2855 node.* = ast.Node.ErrorTag{
27892856 .base = ast.Node{ .id = ast.Node.Id.ErrorTag },
27902857 .doc_comments = comments,
27912858 .name_token = ident_token_index,
2792 });
2859 };
27932860 node_ptr.* = &node.base;
27942861 continue;
27952862 },
......@@ -3129,10 +3196,11 @@ fn pushDocComment(arena: *mem.Allocator, line_comment: TokenIndex, result: *?*as
31293196 if (result.*) |comment_node| {
31303197 break :blk comment_node;
31313198 } 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{
31333201 .base = ast.Node{ .id = ast.Node.Id.DocComment },
31343202 .lines = ast.Node.DocComment.LineList.init(arena),
3135 });
3203 };
31363204 result.* = comment_node;
31373205 break :blk comment_node;
31383206 }
......@@ -3158,10 +3226,11 @@ fn parseStringLiteral(arena: *mem.Allocator, tok_it: *ast.Tree.TokenList.Iterato
31583226 return &(try createLiteral(arena, ast.Node.StringLiteral, token_index)).base;
31593227 },
31603228 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{
31623231 .base = ast.Node{ .id = ast.Node.Id.MultilineStringLiteral },
31633232 .lines = ast.Node.MultilineStringLiteral.LineList.init(arena),
3164 });
3233 };
31653234 try node.lines.push(token_index);
31663235 while (true) {
31673236 const multiline_str = nextToken(tok_it, tree);
......@@ -3186,25 +3255,27 @@ fn parseStringLiteral(arena: *mem.Allocator, tok_it: *ast.Tree.TokenList.Iterato
31863255fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: OptionalCtx, token_ptr: Token, token_index: TokenIndex) !bool {
31873256 switch (token_ptr.id) {
31883257 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{
31903260 .base = ast.Node{ .id = ast.Node.Id.Suspend },
31913261 .suspend_token = token_index,
31923262 .body = null,
3193 });
3263 };
31943264 ctx.store(&node.base);
31953265
31963266 stack.append(State{ .SuspendBody = node }) catch unreachable;
31973267 return true;
31983268 },
31993269 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{
32013272 .base = ast.Node{ .id = ast.Node.Id.If },
32023273 .if_token = token_index,
32033274 .condition = undefined,
32043275 .payload = null,
32053276 .body = undefined,
32063277 .@"else" = null,
3207 });
3278 };
32083279 ctx.store(&node.base);
32093280
32103281 stack.append(State{ .Else = &node.@"else" }) catch unreachable;
......@@ -3238,13 +3309,14 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: Opti
32383309 return true;
32393310 },
32403311 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{
32423314 .base = ast.Node{ .id = ast.Node.Id.Switch },
32433315 .switch_token = token_index,
32443316 .expr = undefined,
32453317 .cases = ast.Node.Switch.CaseList.init(arena),
32463318 .rbrace = undefined,
3247 });
3319 };
32483320 ctx.store(&node.base);
32493321
32503322 stack.append(State{
......@@ -3260,25 +3332,27 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: Opti
32603332 return true;
32613333 },
32623334 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{
32643337 .base = ast.Node{ .id = ast.Node.Id.Comptime },
32653338 .comptime_token = token_index,
32663339 .expr = undefined,
32673340 .doc_comments = null,
3268 });
3341 };
32693342 ctx.store(&node.base);
32703343
32713344 try stack.append(State{ .Expression = OptionalCtx{ .Required = &node.expr } });
32723345 return true;
32733346 },
32743347 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{
32763350 .base = ast.Node{ .id = ast.Node.Id.Block },
32773351 .label = null,
32783352 .lbrace = token_index,
32793353 .statements = ast.Node.Block.StatementList.init(arena),
32803354 .rbrace = undefined,
3281 });
3355 };
32823356 ctx.store(&block.base);
32833357 stack.append(State{ .Block = block }) catch unreachable;
32843358 return true;
......@@ -3412,10 +3486,12 @@ fn tokenIdToPrefixOp(id: Token.Id) ?ast.Node.PrefixOp.Op {
34123486}
34133487
34143488fn 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{
34163491 .base = ast.Node{ .id = ast.Node.typeToId(T) },
34173492 .token = token_index,
3418 });
3493 };
3494 return result;
34193495}
34203496
34213497fn 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 @@
11const tests = @import("tests.zig");
22
33pub 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
438 cases.add(
539 "compile log a pointer to an opaque value",
640 \\export fn entry() void {
......@@ -267,8 +301,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
267301 \\ const Errors = error{} || u16;
268302 \\}
269303 ,
270 ".tmp_source.zig:2:20: error: expected error set type, found 'u8'",
271 ".tmp_source.zig:5:31: error: expected error set type, found 'u16'",
304 ".tmp_source.zig:2:20: error: expected error set type, found type 'u8'",
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",
272308 );
273309
274310 cases.add(
......@@ -2618,7 +2654,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
26182654 \\
26192655 \\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
26202656 ,
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",
26222658 );
26232659
26242660 cases.add(
......@@ -3193,7 +3229,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
31933229 \\ return 2;
31943230 \\}
31953231 ,
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",
31973233 );
31983234
31993235 cases.add(
......@@ -3539,7 +3575,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
35393575 \\
35403576 \\export fn entry() usize { return @sizeOf(@typeOf(a)); }
35413577 ,
3542 ".tmp_source.zig:2:11: error: expected type, found 'i32'",
3578 ".tmp_source.zig:2:11: error: expected type 'type', found 'i32'",
35433579 );
35443580
35453581 cases.add(
......@@ -5331,4 +5367,32 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
53315367 ,
53325368 ".tmp_source.zig:2:35: error: expected sized integer or sized float, found comptime_float",
53335369 );
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 );
53345398}
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{
4848const max_stdout_size = 1 * 1024 * 1024; // 1 MB
4949
5050pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
51 const cases = b.allocator.create(CompareOutputContext{
51 const cases = b.allocator.create(CompareOutputContext) catch unreachable;
52 cases.* = CompareOutputContext{
5253 .b = b,
5354 .step = b.step("test-compare-output", "Run the compare output tests"),
5455 .test_index = 0,
5556 .test_filter = test_filter,
5657 .modes = modes,
57 }) catch unreachable;
58 };
5859
5960 compare_output.addCases(cases);
6061
......@@ -62,13 +63,14 @@ pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes:
6263}
6364
6465pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
65 const cases = b.allocator.create(CompareOutputContext{
66 const cases = b.allocator.create(CompareOutputContext) catch unreachable;
67 cases.* = CompareOutputContext{
6668 .b = b,
6769 .step = b.step("test-runtime-safety", "Run the runtime safety tests"),
6870 .test_index = 0,
6971 .test_filter = test_filter,
7072 .modes = modes,
71 }) catch unreachable;
73 };
7274
7375 runtime_safety.addCases(cases);
7476
......@@ -76,13 +78,14 @@ pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes:
7678}
7779
7880pub fn addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
79 const cases = b.allocator.create(CompileErrorContext{
81 const cases = b.allocator.create(CompileErrorContext) catch unreachable;
82 cases.* = CompileErrorContext{
8083 .b = b,
8184 .step = b.step("test-compile-errors", "Run the compile error tests"),
8285 .test_index = 0,
8386 .test_filter = test_filter,
8487 .modes = modes,
85 }) catch unreachable;
88 };
8689
8790 compile_errors.addCases(cases);
8891
......@@ -90,13 +93,14 @@ pub fn addCompileErrorTests(b: *build.Builder, test_filter: ?[]const u8, modes:
9093}
9194
9295pub fn addBuildExampleTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
93 const cases = b.allocator.create(BuildExamplesContext{
96 const cases = b.allocator.create(BuildExamplesContext) catch unreachable;
97 cases.* = BuildExamplesContext{
9498 .b = b,
9599 .step = b.step("test-build-examples", "Build the examples"),
96100 .test_index = 0,
97101 .test_filter = test_filter,
98102 .modes = modes,
99 }) catch unreachable;
103 };
100104
101105 build_examples.addCases(cases);
102106
......@@ -119,13 +123,14 @@ pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const M
119123}
120124
121125pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
122 const cases = b.allocator.create(CompareOutputContext{
126 const cases = b.allocator.create(CompareOutputContext) catch unreachable;
127 cases.* = CompareOutputContext{
123128 .b = b,
124129 .step = b.step("test-asm-link", "Run the assemble and link tests"),
125130 .test_index = 0,
126131 .test_filter = test_filter,
127132 .modes = modes,
128 }) catch unreachable;
133 };
129134
130135 assemble_and_link.addCases(cases);
131136
......@@ -133,12 +138,13 @@ pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, mode
133138}
134139
135140pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step {
136 const cases = b.allocator.create(TranslateCContext{
141 const cases = b.allocator.create(TranslateCContext) catch unreachable;
142 cases.* = TranslateCContext{
137143 .b = b,
138144 .step = b.step("test-translate-c", "Run the C transation tests"),
139145 .test_index = 0,
140146 .test_filter = test_filter,
141 }) catch unreachable;
147 };
142148
143149 translate_c.addCases(cases);
144150
......@@ -146,12 +152,13 @@ pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.St
146152}
147153
148154pub fn addGenHTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step {
149 const cases = b.allocator.create(GenHContext{
155 const cases = b.allocator.create(GenHContext) catch unreachable;
156 cases.* = GenHContext{
150157 .b = b,
151158 .step = b.step("test-gen-h", "Run the C header file generation tests"),
152159 .test_index = 0,
153160 .test_filter = test_filter,
154 }) catch unreachable;
161 };
155162
156163 gen_h.addCases(cases);
157164
......@@ -163,25 +170,32 @@ pub fn addPkgTests(b: *build.Builder, test_filter: ?[]const u8, root_src: []cons
163170 for (test_targets) |test_target| {
164171 const is_native = (test_target.os == builtin.os and test_target.arch == builtin.arch);
165172 for (modes) |mode| {
166 for ([]bool{
167 false,
168 true,
169 }) |link_libc| {
170 if (link_libc and !is_native) {
171 // don't assume we have a cross-compiling libc set up
172 continue;
173 }
174 const these_tests = b.addTest(root_src);
175 these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os), @tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare"));
176 these_tests.setFilter(test_filter);
177 these_tests.setBuildMode(mode);
178 if (!is_native) {
179 these_tests.setTarget(test_target.arch, test_target.os, test_target.environ);
180 }
181 if (link_libc) {
182 these_tests.linkSystemLibrary("c");
173 for ([]bool{ false, true }) |link_libc| {
174 for ([]bool{ false, true }) |single_threaded| {
175 if (link_libc and !is_native) {
176 // don't assume we have a cross-compiling libc set up
177 continue;
178 }
179 const these_tests = b.addTest(root_src);
180 these_tests.setNamePrefix(b.fmt(
181 "{}-{}-{}-{}-{}-{} ",
182 name,
183 @tagName(test_target.os),
184 @tagName(test_target.arch),
185 @tagName(mode),
186 if (link_libc) "c" else "bare",
187 if (single_threaded) "single" else "multi",
188 ));
189 these_tests.setFilter(test_filter);
190 these_tests.setBuildMode(mode);
191 if (!is_native) {
192 these_tests.setTarget(test_target.arch, test_target.os, test_target.environ);
193 }
194 if (link_libc) {
195 these_tests.linkSystemLibrary("c");
196 }
197 step.dependOn(&these_tests.step);
183198 }
184 step.dependOn(&these_tests.step);
185199 }
186200 }
187201 }
......@@ -237,7 +251,8 @@ pub const CompareOutputContext = struct {
237251
238252 pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8, expected_output: []const u8, cli_args: []const []const u8) *RunCompareOutputStep {
239253 const allocator = context.b.allocator;
240 const ptr = allocator.create(RunCompareOutputStep{
254 const ptr = allocator.create(RunCompareOutputStep) catch unreachable;
255 ptr.* = RunCompareOutputStep{
241256 .context = context,
242257 .exe_path = exe_path,
243258 .name = name,
......@@ -245,7 +260,7 @@ pub const CompareOutputContext = struct {
245260 .test_index = context.test_index,
246261 .step = build.Step.init("RunCompareOutput", allocator, make),
247262 .cli_args = cli_args,
248 }) catch unreachable;
263 };
249264 context.test_index += 1;
250265 return ptr;
251266 }
......@@ -324,13 +339,14 @@ pub const CompareOutputContext = struct {
324339
325340 pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8) *RuntimeSafetyRunStep {
326341 const allocator = context.b.allocator;
327 const ptr = allocator.create(RuntimeSafetyRunStep{
342 const ptr = allocator.create(RuntimeSafetyRunStep) catch unreachable;
343 ptr.* = RuntimeSafetyRunStep{
328344 .context = context,
329345 .exe_path = exe_path,
330346 .name = name,
331347 .test_index = context.test_index,
332348 .step = build.Step.init("RuntimeSafetyRun", allocator, make),
333 }) catch unreachable;
349 };
334350
335351 context.test_index += 1;
336352 return ptr;
......@@ -535,14 +551,15 @@ pub const CompileErrorContext = struct {
535551
536552 pub fn create(context: *CompileErrorContext, name: []const u8, case: *const TestCase, build_mode: Mode) *CompileCmpOutputStep {
537553 const allocator = context.b.allocator;
538 const ptr = allocator.create(CompileCmpOutputStep{
554 const ptr = allocator.create(CompileCmpOutputStep) catch unreachable;
555 ptr.* = CompileCmpOutputStep{
539556 .step = build.Step.init("CompileCmpOutput", allocator, make),
540557 .context = context,
541558 .name = name,
542559 .test_index = context.test_index,
543560 .case = case,
544561 .build_mode = build_mode,
545 }) catch unreachable;
562 };
546563
547564 context.test_index += 1;
548565 return ptr;
......@@ -654,13 +671,14 @@ pub const CompileErrorContext = struct {
654671 }
655672
656673 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{
658676 .name = name,
659677 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
660678 .expected_errors = ArrayList([]const u8).init(self.b.allocator),
661679 .link_libc = false,
662680 .is_exe = false,
663 }) catch unreachable;
681 };
664682
665683 tc.addSourceFile(".tmp_source.zig", source);
666684 comptime var arg_i = 0;
......@@ -814,13 +832,14 @@ pub const TranslateCContext = struct {
814832
815833 pub fn create(context: *TranslateCContext, name: []const u8, case: *const TestCase) *TranslateCCmpOutputStep {
816834 const allocator = context.b.allocator;
817 const ptr = allocator.create(TranslateCCmpOutputStep{
835 const ptr = allocator.create(TranslateCCmpOutputStep) catch unreachable;
836 ptr.* = TranslateCCmpOutputStep{
818837 .step = build.Step.init("ParseCCmpOutput", allocator, make),
819838 .context = context,
820839 .name = name,
821840 .test_index = context.test_index,
822841 .case = case,
823 }) catch unreachable;
842 };
824843
825844 context.test_index += 1;
826845 return ptr;
......@@ -921,12 +940,13 @@ pub const TranslateCContext = struct {
921940 }
922941
923942 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{
925945 .name = name,
926946 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
927947 .expected_lines = ArrayList([]const u8).init(self.b.allocator),
928948 .allow_warnings = allow_warnings,
929 }) catch unreachable;
949 };
930950
931951 tc.addSourceFile(filename, source);
932952 comptime var arg_i = 0;
......@@ -1008,14 +1028,15 @@ pub const GenHContext = struct {
10081028
10091029 pub fn create(context: *GenHContext, h_path: []const u8, name: []const u8, case: *const TestCase) *GenHCmpOutputStep {
10101030 const allocator = context.b.allocator;
1011 const ptr = allocator.create(GenHCmpOutputStep{
1031 const ptr = allocator.create(GenHCmpOutputStep) catch unreachable;
1032 ptr.* = GenHCmpOutputStep{
10121033 .step = build.Step.init("ParseCCmpOutput", allocator, make),
10131034 .context = context,
10141035 .h_path = h_path,
10151036 .name = name,
10161037 .test_index = context.test_index,
10171038 .case = case,
1018 }) catch unreachable;
1039 };
10191040
10201041 context.test_index += 1;
10211042 return ptr;
......@@ -1055,11 +1076,12 @@ pub const GenHContext = struct {
10551076 }
10561077
10571078 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{
10591081 .name = name,
10601082 .sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
10611083 .expected_lines = ArrayList([]const u8).init(self.b.allocator),
1062 }) catch unreachable;
1084 };
10631085
10641086 tc.addSourceFile(filename, source);
10651087 comptime var arg_i = 0;